Skip to content

Commit

Permalink
Fix credential provider enum and add some user overrides
Browse files Browse the repository at this point in the history
  • Loading branch information
nirinchev committed Aug 8, 2022
1 parent 8d34305 commit 711af7e
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 22 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
* None

### Fixed
* None
* 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))
* Added override to `User.ToString()` that outputs the user id and provider. (PR [#2988](https://github.com/realm/realm-dotnet/pull/2988))
* Added == and != operator overloads to `User` that matches the behavior of `User.Equals`. (PR [#2988](https://github.com/realm/realm-dotnet/pull/2988))

### Compatibility
* Realm Studio: 12.0.0 or later.
Expand Down
24 changes: 15 additions & 9 deletions Realm/Realm/Sync/Credentials.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,43 +40,43 @@ public enum AuthProvider
/// <summary>
/// OAuth2-based mechanism for logging in with an existing Facebook account.
/// </summary>
Facebook = 1,
Facebook = 2,

/// <summary>
/// Mechanism for logging in with an existing Google account using an auth code or Id token.
/// </summary>
Google = 2,
Google = 3,

/// <summary>
/// OAuth2-based mechanism for logging in with an Apple ID.
/// </summary>
Apple = 3,
Apple = 4,

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

/// <summary>
/// Mechanism for authenticating with an email and a password.
/// </summary>
EmailPassword = 5,
EmailPassword = 6,

/// <summary>
/// Allow users to log in with arbitrary credentials according to custom authentication logic that you define
/// on the server.
/// </summary>
Function = 6,
Function = 7,

/// <summary>
/// Mechanism for logging in with API keys generated by the client SDK.
/// </summary>
ApiKey = 7,
ApiKey = 8,

/// <summary>
/// Mechanism for logging in with API keys generated in the server UI.
/// </summary>
ServerApiKey = 8,
ServerApiKey = 9,

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

/// <summary>
/// Creates credentials representing a login using a Facebook access token.
Expand Down
20 changes: 10 additions & 10 deletions Realm/Realm/Sync/User.cs
Original file line number Diff line number Diff line change
Expand Up @@ -274,25 +274,25 @@ public async Task<User> LinkCredentialsAsync(Credentials credentials)
}

/// <inheritdoc />
public override bool Equals(object obj)
{
return Equals(obj as User);
}
public override bool Equals(object obj) => Equals(obj as User);

/// <summary>
/// Determines whether this instance and another <see cref="User"/> instance are equal by comparing their identities.
/// </summary>
/// <param name="other">The <see cref="User"/> instance to compare with.</param>
/// <returns>true if the two instances are equal; false otherwise.</returns>
public bool Equals(User other)
{
return Id.Equals(other?.Id);
}
public bool Equals(User other) => Id.Equals(other?.Id);

/// <inheritdoc />
public override int GetHashCode()
public override int GetHashCode() => Id.GetHashCode();

public static bool operator ==(User user1, User user2) => user1?.Id == user2?.Id;

public static bool operator !=(User user1, User user2) => !(user1 == user2);

public override string ToString()
{
return Id.GetHashCode();
return $"User {Id}, State: {State}, Provider: {Provider}";
}

/// <summary>
Expand Down
74 changes: 74 additions & 0 deletions Tests/Realm.Tests/Sync/UserManagementTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -951,6 +951,80 @@ public void UserCustomData_Generic()
});
}

[Test]
public void UserAnonymous([Values(true, false)] bool firstReuse, [Values(true, false)] bool secondReuse)
{
SyncTestHelpers.RunBaasTestAsync(async () =>
{
var user = await DefaultApp.LogInAsync(Credentials.Anonymous(reuseExisting: firstReuse));
Assert.That(user, Is.Not.Null);
Assert.That(user.Id, Is.Not.Null);
var anotherUser = await DefaultApp.LogInAsync(Credentials.Anonymous(reuseExisting: secondReuse));
Assert.That(anotherUser, Is.Not.Null);
Assert.That(anotherUser.Id, Is.Not.Null);
// We only expect both users to be the same if they both reused their credentials
Assert.That(user.Id == anotherUser.Id, Is.EqualTo(secondReuse), $"Expected Ids to {(secondReuse ? string.Empty : "not ")}match");
Assert.That(user == anotherUser, Is.EqualTo(secondReuse), $"Expected Users to {(secondReuse ? string.Empty : "not ")}match");
});
}

[Test]
public void UserAnonymous_CombiningReuseAndNotReuse()
{
SyncTestHelpers.RunBaasTestAsync(async () =>
{
var anonA = await DefaultApp.LogInAsync(Credentials.Anonymous(reuseExisting: false));
var reusedA1 = await DefaultApp.LogInAsync(Credentials.Anonymous());
var reusedA2 = await DefaultApp.LogInAsync(Credentials.Anonymous());
var anonB = await DefaultApp.LogInAsync(Credentials.Anonymous(reuseExisting: false));
var reusedB = await DefaultApp.LogInAsync(Credentials.Anonymous());
Assert.That(anonA, Is.EqualTo(reusedA1));
Assert.That(anonA, Is.EqualTo(reusedA2));
Assert.That(anonB, Is.Not.EqualTo(anonA));
Assert.That(anonB, Is.EqualTo(reusedB));
await anonB.LogOutAsync();
Assert.That(anonB.State, Is.EqualTo(UserState.Removed));
Assert.That(reusedB.State, Is.EqualTo(UserState.Removed));
var reusedA3 = await DefaultApp.LogInAsync(Credentials.Anonymous());
Assert.That(reusedA3, Is.EqualTo(anonA));
});
}

[Test]
public void UserEqualsOverrides()
{
SyncTestHelpers.RunBaasTestAsync(async () =>
{
var user = await DefaultApp.LogInAsync(Credentials.Anonymous(reuseExisting: false));
var currentUser = DefaultApp.CurrentUser;
Assert.That(user.Id, Is.EqualTo(currentUser.Id));
Assert.That(user.Equals(currentUser));
Assert.That(user == currentUser);
var anotherUser = await DefaultApp.LogInAsync(Credentials.Anonymous(reuseExisting: false));
Assert.That(user.Id, Is.Not.EqualTo(anotherUser.Id));
Assert.That(user.Equals(anotherUser), Is.False);
Assert.That(user != anotherUser);
});
}

[Test]
public void UserToStringOverride()
{
var user = GetFakeUser();
Assert.That(user.ToString(), Does.Contain(user.Id));
Assert.That(user.ToString(), Does.Contain(user.Provider.ToString()));
}

private class CustomDataDocument
{
[Preserve]
Expand Down
6 changes: 4 additions & 2 deletions wrappers/src/app_cs.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,10 @@ namespace binding {
AppCredentials to_app_credentials() {
switch (provider)
{
case AuthProvider::ANONYMOUS:
return AppCredentials::anonymous();
case AuthProvider::ANONYMOUS: {
Utf16StringAccessor reuse_existing(additional_info, additional_info_len);
return AppCredentials::anonymous(reuse_existing == "true");
}

case AuthProvider::FACEBOOK:
return AppCredentials::facebook(Utf16StringAccessor(token, token_len));
Expand Down

0 comments on commit 711af7e

Please sign in to comment.