Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 18 additions & 3 deletions examples/audience/Assets/SampleApp/Scripts/AudienceSample.cs
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ private void OnIdentify() => RunAndLog("identify()", () =>
{
var f = CaptureIdentifyForm();
var traits = ParseTraits(f.RawTraits);
ImmutableAudience.Identify(f.Id, f.Type, traits);
ImmutableAudience.Identify(f.Id, ParseIdentityType(f.Type), traits);
// SDK drops via Log.Warn when id is empty or consent < Full. Mirror
// only when accepted — otherwise the panel would show stale state.
var accepted = !string.IsNullOrEmpty(f.Id)
Expand All @@ -212,7 +212,7 @@ private void OnIdentifyTraits() => RunAndLog("identify(traits)", () =>
if (string.IsNullOrEmpty(userId)) throw new InvalidOperationException("no active identity — call Identify first");
var traits = ParseTraits(CaptureTraitsUpdate());
if (traits == null || traits.Count == 0) throw new InvalidOperationException("traits required");
ImmutableAudience.Identify(userId, _mirrorIdentityType ?? IdentityType.Custom.ToLowercaseString(), traits);
ImmutableAudience.Identify(userId, ParseIdentityType(_mirrorIdentityType), traits);
_mirrorTraits = traits;
OnSdkStateChanged();
return Json.Serialize(traits, 2);
Expand All @@ -221,7 +221,7 @@ private void OnIdentifyTraits() => RunAndLog("identify(traits)", () =>
private void OnAlias() => RunAndLog("alias()", () =>
{
var f = CaptureAliasForm();
ImmutableAudience.Alias(f.FromId, f.FromType, f.ToId, f.ToType);
ImmutableAudience.Alias(f.FromId, ParseIdentityType(f.FromType), f.ToId, ParseIdentityType(f.ToType));
// SDK drops via Log.Warn when fromId/toId is empty or consent < Full.
// The IsAliasReady gate keeps empty endpoints unreachable from the
// UI; this post-call check is defense-in-depth.
Expand Down Expand Up @@ -371,5 +371,20 @@ private void ResetIdentityMirror()

private static Dictionary<string, object>? ParseTraits(string? raw) =>
string.IsNullOrWhiteSpace(raw) ? null : JsonReader.DeserializeObject(raw!);

// Parses a wire-format identity string (e.g. "steam") back into the
// IdentityType enum the SDK now requires. Falls back to Custom for
// unknown or empty values.
private static IdentityType ParseIdentityType(string? value) => (value ?? "").ToLowerInvariant() switch
{
"passport" => IdentityType.Passport,
"steam" => IdentityType.Steam,
"epic" => IdentityType.Epic,
"google" => IdentityType.Google,
"apple" => IdentityType.Apple,
"discord" => IdentityType.Discord,
"email" => IdentityType.Email,
_ => IdentityType.Custom,
};
}
}
40 changes: 6 additions & 34 deletions src/Packages/Audience/Runtime/ImmutableAudience.cs
Original file line number Diff line number Diff line change
Expand Up @@ -308,20 +308,7 @@ public static void Track(string eventName, Dictionary<string, object>? propertie
/// <param name="userId">The player's identifier within the chosen provider.</param>
/// <param name="identityType">The identity provider that issued <paramref name="userId"/>.</param>
/// <param name="traits">Optional player attributes (email, name, etc.).</param>
public static void Identify(string userId, IdentityType identityType, Dictionary<string, object>? traits = null) =>
Identify(userId, identityType.ToLowercaseString(), traits);

/// <summary>
/// Attaches a known user ID to subsequent events. String overload
/// for providers outside the <see cref="IdentityType"/> enum.
/// </summary>
/// <param name="userId">The player's identifier within the chosen provider.</param>
/// <param name="identityType">
/// The identity provider name. Required. Data-deletion requests
/// match events by this namespace.
/// </param>
/// <param name="traits">Optional player attributes (email, name, etc.).</param>
public static void Identify(string userId, string identityType, Dictionary<string, object>? traits = null)
public static void Identify(string userId, IdentityType identityType, Dictionary<string, object>? traits = null)
{
if (!_initialized) return;

Expand Down Expand Up @@ -352,8 +339,8 @@ public static void Identify(string userId, string identityType, Dictionary<strin
}

var anonymousId = Identity.GetOrCreate(config.PersistentDataPath!, level);
var msg = MessageBuilder.Identify(anonymousId, userId, identityType, config.PackageVersion,
SnapshotCallerDict(traits));
var msg = MessageBuilder.Identify(anonymousId, userId, identityType.ToLowercaseString(),
config.PackageVersion, SnapshotCallerDict(traits));
EnqueueIdentity(msg);
}

Expand All @@ -364,23 +351,7 @@ public static void Identify(string userId, string identityType, Dictionary<strin
/// <param name="fromType">Identity provider for <paramref name="fromId"/>.</param>
/// <param name="toId">The new identifier.</param>
/// <param name="toType">Identity provider for <paramref name="toId"/>.</param>
public static void Alias(string fromId, IdentityType fromType, string toId, IdentityType toType) =>
Alias(fromId, fromType.ToLowercaseString(), toId, toType.ToLowercaseString());

/// <summary>
/// Links two user IDs for the same player. String overload for
/// providers outside the <see cref="IdentityType"/> enum.
/// </summary>
/// <param name="fromId">The previously-known identifier.</param>
/// <param name="fromType">
/// Identity provider for <paramref name="fromId"/>. Required.
/// Data-deletion requests match events by this namespace.
/// </param>
/// <param name="toId">The new identifier.</param>
/// <param name="toType">
/// Identity provider for <paramref name="toId"/>. Required.
/// </param>
public static void Alias(string fromId, string fromType, string toId, string toType)
public static void Alias(string fromId, IdentityType fromType, string toId, IdentityType toType)
{
if (!_initialized) return;

Expand All @@ -399,7 +370,8 @@ public static void Alias(string fromId, string fromType, string toId, string toT
var config = _config;
if (config == null) return;

var msg = MessageBuilder.Alias(fromId, fromType, toId, toType, config.PackageVersion);
var msg = MessageBuilder.Alias(fromId, fromType.ToLowercaseString(), toId, toType.ToLowercaseString(),
config.PackageVersion);
EnqueueIdentity(msg);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -618,7 +618,7 @@ public void Identify_FullConsent_WritesIdentifyEvent()
{
ImmutableAudience.Init(MakeConfig(ConsentLevel.Full));

ImmutableAudience.Identify("76561198012345", "steam");
ImmutableAudience.Identify("76561198012345", IdentityType.Steam);
ImmutableAudience.Shutdown();

var queueDir = AudiencePaths.QueueDir(_testDir);
Expand All @@ -633,7 +633,7 @@ public void Identify_AnonymousConsent_IsIgnored()
{
ImmutableAudience.Init(MakeConfig(ConsentLevel.Anonymous));

ImmutableAudience.Identify("user1", "steam");
ImmutableAudience.Identify("user1", IdentityType.Steam);
ImmutableAudience.Shutdown();

var queueDir = AudiencePaths.QueueDir(_testDir);
Expand All @@ -648,7 +648,7 @@ public void Alias_FullConsent_WritesAliasEvent()
{
ImmutableAudience.Init(MakeConfig(ConsentLevel.Full));

ImmutableAudience.Alias("steam123", "steam", "user_456", "passport");
ImmutableAudience.Alias("steam123", IdentityType.Steam, "user_456", IdentityType.Passport);
ImmutableAudience.Shutdown();

var queueDir = AudiencePaths.QueueDir(_testDir);
Expand Down Expand Up @@ -971,7 +971,7 @@ public void SetConsent_DowngradeToAnonymous_StressTest_NoUserIdLeak()
for (int iter = 0; iter < iterations; iter++)
{
ImmutableAudience.Init(MakeConfig(ConsentLevel.Full));
ImmutableAudience.Identify(testUserId, "steam");
ImmutableAudience.Identify(testUserId, IdentityType.Steam);

// Clear Init events so only race events can leak.
ImmutableAudience.FlushQueueToDiskForTesting();
Expand Down
Loading