Skip to content

Commit d5b334a

Browse files
authored
Fix credential provider enum (#2988)
1 parent 8d34305 commit d5b334a

File tree

5 files changed

+106
-22
lines changed

5 files changed

+106
-22
lines changed

CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
* None
55

66
### Fixed
7-
* None
7+
* Fixed an issue introduced in 10.15.0 that would prevent non-anonoymous user authentication against Atlas App Services. (Issue [#2987](https://github.com/realm/realm-dotnet/issues/2987))
8+
* Added override to `User.ToString()` that outputs the user id and provider. (PR [#2988](https://github.com/realm/realm-dotnet/pull/2988))
9+
* Added == and != operator overloads to `User` that matches the behavior of `User.Equals`. (PR [#2988](https://github.com/realm/realm-dotnet/pull/2988))
810

911
### Compatibility
1012
* Realm Studio: 12.0.0 or later.

Realm/Realm/Sync/Credentials.cs

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -40,43 +40,43 @@ public enum AuthProvider
4040
/// <summary>
4141
/// OAuth2-based mechanism for logging in with an existing Facebook account.
4242
/// </summary>
43-
Facebook = 1,
43+
Facebook = 2,
4444

4545
/// <summary>
4646
/// Mechanism for logging in with an existing Google account using an auth code or Id token.
4747
/// </summary>
48-
Google = 2,
48+
Google = 3,
4949

5050
/// <summary>
5151
/// OAuth2-based mechanism for logging in with an Apple ID.
5252
/// </summary>
53-
Apple = 3,
53+
Apple = 4,
5454

5555
/// <summary>
5656
/// Allow users to log in with JWT-based credentials generated by a service external to Realm.
5757
/// </summary>
58-
JWT = 4,
58+
JWT = 5,
5959

6060
/// <summary>
6161
/// Mechanism for authenticating with an email and a password.
6262
/// </summary>
63-
EmailPassword = 5,
63+
EmailPassword = 6,
6464

6565
/// <summary>
6666
/// Allow users to log in with arbitrary credentials according to custom authentication logic that you define
6767
/// on the server.
6868
/// </summary>
69-
Function = 6,
69+
Function = 7,
7070

7171
/// <summary>
7272
/// Mechanism for logging in with API keys generated by the client SDK.
7373
/// </summary>
74-
ApiKey = 7,
74+
ApiKey = 8,
7575

7676
/// <summary>
7777
/// Mechanism for logging in with API keys generated in the server UI.
7878
/// </summary>
79-
ServerApiKey = 8,
79+
ServerApiKey = 9,
8080

8181
/// <summary>
8282
/// A provider that is not among the well known provider types. This is most likely the result of the server
@@ -88,9 +88,15 @@ public enum AuthProvider
8888
/// <summary>
8989
/// Creates credentials representing an anonymous user.
9090
/// </summary>
91+
/// <param name="reuseExisting">
92+
/// A value indicating whether anonymous users should be reused. Passing <c>true</c> means that multiple calls to
93+
/// <c>app.LoginAsync(Credentials.Anonymous())</c> will return the same anonymous user as long as that user hasn't
94+
/// logged out. If <paramref name="reuseExisting"/> is <c>false</c>, every time you call <see cref="App.LogInAsync(Credentials)"/>,
95+
/// a new user will be created on the server.
96+
/// </param>
9197
/// <returns>A Credentials that can be used to authenticate an anonymous user.</returns>
9298
/// <seealso href="https://docs.mongodb.com/realm/authentication/anonymous/">Anonymous Authentication Docs</seealso>
93-
public static Credentials Anonymous() => new Credentials(AuthProvider.Anonymous);
99+
public static Credentials Anonymous(bool reuseExisting = true) => new(AuthProvider.Anonymous, additionalInfo: reuseExisting.ToString().ToLower());
94100

95101
/// <summary>
96102
/// Creates credentials representing a login using a Facebook access token.

Realm/Realm/Sync/User.cs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -274,25 +274,25 @@ public async Task<User> LinkCredentialsAsync(Credentials credentials)
274274
}
275275

276276
/// <inheritdoc />
277-
public override bool Equals(object obj)
278-
{
279-
return Equals(obj as User);
280-
}
277+
public override bool Equals(object obj) => Equals(obj as User);
281278

282279
/// <summary>
283280
/// Determines whether this instance and another <see cref="User"/> instance are equal by comparing their identities.
284281
/// </summary>
285282
/// <param name="other">The <see cref="User"/> instance to compare with.</param>
286283
/// <returns>true if the two instances are equal; false otherwise.</returns>
287-
public bool Equals(User other)
288-
{
289-
return Id.Equals(other?.Id);
290-
}
284+
public bool Equals(User other) => Id.Equals(other?.Id);
291285

292286
/// <inheritdoc />
293-
public override int GetHashCode()
287+
public override int GetHashCode() => Id.GetHashCode();
288+
289+
public static bool operator ==(User user1, User user2) => user1?.Id == user2?.Id;
290+
291+
public static bool operator !=(User user1, User user2) => !(user1 == user2);
292+
293+
public override string ToString()
294294
{
295-
return Id.GetHashCode();
295+
return $"User {Id}, State: {State}, Provider: {Provider}";
296296
}
297297

298298
/// <summary>

Tests/Realm.Tests/Sync/UserManagementTests.cs

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -951,6 +951,80 @@ public void UserCustomData_Generic()
951951
});
952952
}
953953

954+
[Test]
955+
public void UserAnonymous([Values(true, false)] bool firstReuse, [Values(true, false)] bool secondReuse)
956+
{
957+
SyncTestHelpers.RunBaasTestAsync(async () =>
958+
{
959+
var user = await DefaultApp.LogInAsync(Credentials.Anonymous(reuseExisting: firstReuse));
960+
Assert.That(user, Is.Not.Null);
961+
Assert.That(user.Id, Is.Not.Null);
962+
963+
var anotherUser = await DefaultApp.LogInAsync(Credentials.Anonymous(reuseExisting: secondReuse));
964+
Assert.That(anotherUser, Is.Not.Null);
965+
Assert.That(anotherUser.Id, Is.Not.Null);
966+
967+
// We only expect both users to be the same if they both reused their credentials
968+
Assert.That(user.Id == anotherUser.Id, Is.EqualTo(secondReuse), $"Expected Ids to {(secondReuse ? string.Empty : "not ")}match");
969+
Assert.That(user == anotherUser, Is.EqualTo(secondReuse), $"Expected Users to {(secondReuse ? string.Empty : "not ")}match");
970+
});
971+
}
972+
973+
[Test]
974+
public void UserAnonymous_CombiningReuseAndNotReuse()
975+
{
976+
SyncTestHelpers.RunBaasTestAsync(async () =>
977+
{
978+
var anonA = await DefaultApp.LogInAsync(Credentials.Anonymous(reuseExisting: false));
979+
var reusedA1 = await DefaultApp.LogInAsync(Credentials.Anonymous());
980+
var reusedA2 = await DefaultApp.LogInAsync(Credentials.Anonymous());
981+
var anonB = await DefaultApp.LogInAsync(Credentials.Anonymous(reuseExisting: false));
982+
var reusedB = await DefaultApp.LogInAsync(Credentials.Anonymous());
983+
984+
Assert.That(anonA, Is.EqualTo(reusedA1));
985+
Assert.That(anonA, Is.EqualTo(reusedA2));
986+
987+
Assert.That(anonB, Is.Not.EqualTo(anonA));
988+
Assert.That(anonB, Is.EqualTo(reusedB));
989+
990+
await anonB.LogOutAsync();
991+
992+
Assert.That(anonB.State, Is.EqualTo(UserState.Removed));
993+
Assert.That(reusedB.State, Is.EqualTo(UserState.Removed));
994+
995+
var reusedA3 = await DefaultApp.LogInAsync(Credentials.Anonymous());
996+
997+
Assert.That(reusedA3, Is.EqualTo(anonA));
998+
});
999+
}
1000+
1001+
[Test]
1002+
public void UserEqualsOverrides()
1003+
{
1004+
SyncTestHelpers.RunBaasTestAsync(async () =>
1005+
{
1006+
var user = await DefaultApp.LogInAsync(Credentials.Anonymous(reuseExisting: false));
1007+
var currentUser = DefaultApp.CurrentUser;
1008+
1009+
Assert.That(user.Id, Is.EqualTo(currentUser.Id));
1010+
Assert.That(user.Equals(currentUser));
1011+
Assert.That(user == currentUser);
1012+
1013+
var anotherUser = await DefaultApp.LogInAsync(Credentials.Anonymous(reuseExisting: false));
1014+
Assert.That(user.Id, Is.Not.EqualTo(anotherUser.Id));
1015+
Assert.That(user.Equals(anotherUser), Is.False);
1016+
Assert.That(user != anotherUser);
1017+
});
1018+
}
1019+
1020+
[Test]
1021+
public void UserToStringOverride()
1022+
{
1023+
var user = GetFakeUser();
1024+
Assert.That(user.ToString(), Does.Contain(user.Id));
1025+
Assert.That(user.ToString(), Does.Contain(user.Provider.ToString()));
1026+
}
1027+
9541028
private class CustomDataDocument
9551029
{
9561030
[Preserve]

wrappers/src/app_cs.hpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,10 @@ namespace binding {
6969
AppCredentials to_app_credentials() {
7070
switch (provider)
7171
{
72-
case AuthProvider::ANONYMOUS:
73-
return AppCredentials::anonymous();
72+
case AuthProvider::ANONYMOUS: {
73+
Utf16StringAccessor reuse_existing(additional_info, additional_info_len);
74+
return AppCredentials::anonymous(reuse_existing == "true");
75+
}
7476

7577
case AuthProvider::FACEBOOK:
7678
return AppCredentials::facebook(Utf16StringAccessor(token, token_len));

0 commit comments

Comments
 (0)