Skip to content

Commit

Permalink
Implement getUserByProviderUid.
Browse files Browse the repository at this point in the history
  • Loading branch information
nrsim committed Feb 3, 2020
1 parent d672e23 commit 0f69aca
Show file tree
Hide file tree
Showing 4 changed files with 216 additions and 5 deletions.
19 changes: 18 additions & 1 deletion FirebaseAdmin/FirebaseAdmin.IntegrationTests/FirebaseAuthTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 225,15 @@ public async Task UserLifecycle()
user = await FirebaseAuth.DefaultInstance.GetUserByEmailAsync(randomUser.Email);
Assert.Equal(uid, user.Uid);

// Disable user and remove properties
// Get user by phone provider uid
user = await FirebaseAuth.DefaultInstance.GetUserByProviderUidAsync("phone", randomUser.PhoneNumber);
Assert.Equal(uid, user.Uid);

// Get user by email provider uid
user = await FirebaseAuth.DefaultInstance.GetUserByProviderUidAsync("email", randomUser.Email);
Assert.Equal(uid, user.Uid);

// Disable user and remove properties
var disableArgs = new UserRecordArgs()
{
Uid = uid,
Expand Down Expand Up @@ -276,6 284,15 @@ public async Task GetUserNonExistingEmail()
Assert.Equal(AuthErrorCode.UserNotFound, exception.AuthErrorCode);
}

[Fact]
public async Task GetUserNonExistingProviderUid()
{
var exception = await Assert.ThrowsAsync<FirebaseAuthException>(
async () => await FirebaseAuth.DefaultInstance.GetUserByProviderUidAsync("google.com", "non_existing_user"));

Assert.Equal(AuthErrorCode.UserNotFound, exception.AuthErrorCode);
}

[Fact]
public async Task UpdateUserNonExistingUid()
{
Expand Down
103 changes: 103 additions & 0 deletions FirebaseAdmin/FirebaseAdmin.Tests/Auth/FirebaseUserManagerTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 326,109 @@ public async Task GetUserByPhoneNumberEmpty()
await Assert.ThrowsAsync<ArgumentException>(() => auth.GetUserByPhoneNumberAsync(string.Empty));
}

[Fact]
public async Task GetUserByProviderUid()
{
var handler = new MockMessageHandler()
{
Response = GetUserResponse,
};
var auth = this.CreateFirebaseAuth(handler);

var userRecord = await auth.GetUserByProviderUidAsync("google.com", "google_uid");

Assert.Equal("user1", userRecord.Uid);
Assert.Null(userRecord.DisplayName);
Assert.Null(userRecord.Email);
Assert.Null(userRecord.PhoneNumber);
Assert.Null(userRecord.PhotoUrl);
Assert.Equal("firebase", userRecord.ProviderId);
Assert.False(userRecord.Disabled);
Assert.False(userRecord.EmailVerified);
Assert.Equal(UserRecord.UnixEpoch, userRecord.TokensValidAfterTimestamp);
Assert.Empty(userRecord.CustomClaims);
Assert.Empty(userRecord.ProviderData);
Assert.Null(userRecord.UserMetaData.CreationTimestamp);
Assert.Null(userRecord.UserMetaData.LastSignInTimestamp);

var request = NewtonsoftJsonSerializer.Instance.Deserialize<Dictionary<string, object>>(handler.LastRequestBody);
Assert.Equal(new JArray("{providerId: google.com, rawId: google_uid}"), request["federatedUserId"]);
this.AssertClientVersion(handler.LastRequestHeaders);
}

[Fact]
public async Task GetUserByProviderUidWithPhoneProvider()
{
var handler = new MockMessageHandler()
{
Response = GetUserResponse,
};
var auth = this.CreateFirebaseAuth(handler);

var userRecord = await auth.GetUserByProviderUidAsync("phone", " 1234567890");

Assert.Equal("user1", userRecord.Uid);

var request = NewtonsoftJsonSerializer.Instance.Deserialize<Dictionary<string, object>>(handler.LastRequestBody);
Assert.Equal(new JArray(" 1234567890"), request["phoneNumber"]);
Assert.False(request.ContainsKey("federatedUserId"));
this.AssertClientVersion(handler.LastRequestHeaders);
}

[Fact]
public async Task GetUserByProviderUidWithEmailProvider()
{
var handler = new MockMessageHandler()
{
Response = GetUserResponse,
};
var auth = this.CreateFirebaseAuth(handler);

var userRecord = await auth.GetUserByProviderUidAsync("email", "[email protected]");

Assert.Equal("user1", userRecord.Uid);

var request = NewtonsoftJsonSerializer.Instance.Deserialize<Dictionary<string, object>>(handler.LastRequestBody);
Assert.Equal(new JArray("[email protected]"), request["email"]);
Assert.False(request.ContainsKey("federatedUserId"));
this.AssertClientVersion(handler.LastRequestHeaders);
}

[Fact]
public async Task GetUserByProviderUidUserNotFound()
{
var handler = new MockMessageHandler()
{
Response = @"{""users"": []}",
};
var auth = this.CreateFirebaseAuth(handler);

var exception = await Assert.ThrowsAsync<FirebaseAuthException>(
async () => await auth.GetUserByProviderUidAsync("google.com", "google_uid"));

Assert.Equal(ErrorCode.NotFound, exception.ErrorCode);
Assert.Equal(AuthErrorCode.UserNotFound, exception.AuthErrorCode);
Assert.Equal("Failed to get user with federated user ID: {providerId: google.com, rawId: google_uid}", exception.Message);
Assert.NotNull(exception.HttpResponse);
Assert.Null(exception.InnerException);
}

[Fact]
public async Task GetUserByProviderUidNull()
{
var auth = this.CreateFirebaseAuth(new MockMessageHandler());
await Assert.ThrowsAsync<ArgumentException>(() => auth.GetUserByProviderUidAsync("google.com", null));
await Assert.ThrowsAsync<ArgumentException>(() => auth.GetUserByProviderUidAsync(null, "google_uid"));
}

[Fact]
public async Task GetUserByProviderUidEmpty()
{
var auth = this.CreateFirebaseAuth(new MockMessageHandler());
await Assert.ThrowsAsync<ArgumentException>(() => auth.GetUserByProviderUidAsync("google.com", string.Empty));
await Assert.ThrowsAsync<ArgumentException>(() => auth.GetUserByProviderUidAsync(string.Empty, "google_uid"));
}

[Fact]
public async Task ListUsers()
{
Expand Down
43 changes: 43 additions & 0 deletions FirebaseAdmin/FirebaseAdmin/Auth/FirebaseAuth.cs
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 413,49 @@ public async Task<UserRecord> GetUserByPhoneNumberAsync(string phoneNumber)
.ConfigureAwait(false);
}

/// <summary>
/// Gets a <see cref="UserRecord"/> object containing information about the user identified by
/// <paramref name="providerId"/> and <paramref name="providerUid"/>.
/// </summary>
/// <param name="providerId">Identifier for the given provider, for example,
/// "google.com" for the Google provider.</param>
/// <param name="providerUid">The user identifier with the given provider.</param>
/// <returns>A task that completes with a <see cref="UserRecord"/> representing
/// a user with the specified provider user identifier.</returns>
/// <exception cref="ArgumentException">If the provider identifier is null or empty,
/// or if the provider user identifier is empty.</exception>
/// <exception cref="FirebaseAuthException">If a user cannot be found with the specified
/// provider user identifier.</exception>
public async Task<UserRecord> GetUserByProviderUidAsync(string providerId, string providerUid)
{
return await this.GetUserByProviderUidAsync(providerId, providerUid, default(CancellationToken))
.ConfigureAwait(false);
}

/// <summary>
/// Gets a <see cref="UserRecord"/> object containing information about the user identified by
/// <paramref name="providerId"/> and <paramref name="providerUid"/>.
/// </summary>
/// <param name="providerId">Identifier for the given provider, for example,
/// "google.com" for the Google provider.</param>
/// <param name="providerUid">The user identifier with the given provider.</param>
/// <param name="cancellationToken">A cancellation token to monitor the asynchronous
/// operation.</param>
/// <returns>A task that completes with a <see cref="UserRecord"/> representing
/// a user with the specified provider user identifier.</returns>
/// <exception cref="ArgumentException">If the provider identifier is null or empty,
/// or if the provider user identifier is empty.</exception>
/// <exception cref="FirebaseAuthException">If a user cannot be found with the specified
/// provider user identifier.</exception>
public async Task<UserRecord> GetUserByProviderUidAsync(
string providerId, string providerUid, CancellationToken cancellationToken)
{
var userManager = this.IfNotDeleted(() => this.userManager.Value);

return await userManager.GetUserByProviderUidAsync(providerId, providerUid, cancellationToken)
.ConfigureAwait(false);
}

/// <summary>
/// Updates an existing user account with the attributes contained in the specified <see cref="UserRecordArgs"/>.
/// The <see cref="UserRecordArgs.Uid"/> property must be specified.
Expand Down
56 changes: 52 additions & 4 deletions FirebaseAdmin/FirebaseAdmin/Auth/FirebaseUserManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 102,7 @@ internal static FirebaseUserManager Create(FirebaseApp app)
var query = new UserQuery()
{
Field = "localId",
Value = uid,
Value = new string[] { uid },
Label = "uid",
};
return await this.GetUserAsync(query, cancellationToken)
Expand All @@ -127,7 127,55 @@ internal static FirebaseUserManager Create(FirebaseApp app)
var query = new UserQuery()
{
Field = "email",
Value = email,
Value = new string[] { email },
};
return await this.GetUserAsync(query, cancellationToken)
.ConfigureAwait(false);
}

/// <summary>
/// Gets the user data corresponding to the given provider user identifer.
/// </summary>
/// <param name="providerId">Identifier for the given provider, for example,
/// "google.com" for the Google provider.</param>
/// <param name="providerUid">The user identifier with the given provider.</param>
/// <param name="cancellationToken">A cancellation token to monitor the asynchronous
/// operation.</param>
/// <returns>A record of user with the queried provider user identifier if one exists.</returns>
internal async Task<UserRecord> GetUserByProviderUidAsync(
string providerId, string providerUid, CancellationToken cancellationToken = default(CancellationToken))
{
if (string.IsNullOrEmpty(providerId))
{
throw new ArgumentException("providerId cannot be null or empty.");
}

if (string.IsNullOrEmpty(providerUid))
{
throw new ArgumentException("providerUid cannot be null or empty.");
}

if (providerId.Equals("phone"))
{
return await this.GetUserByPhoneNumberAsync(providerUid, cancellationToken);
}

if (providerId.Equals("email"))
{
return await this.GetUserByEmailAsync(providerUid, cancellationToken);
}

var federatedUserId = new Dictionary<string, object>()
{
{ "rawId", providerUid },
{ "providerId", providerId },
};

var query = new UserQuery()
{
Field = "federatedUserId",
Value = new Dictionary<string, object>[] { federatedUserId },
Label = "Provider user ID",
};
return await this.GetUserAsync(query, cancellationToken)
.ConfigureAwait(false);
Expand Down Expand Up @@ -309,7 357,7 @@ private class UserQuery
{
internal string Field { get; set; }

internal string Value { get; set; }
internal object Value { get; set; }

internal string Label { get; set; }

Expand All @@ -331,7 379,7 @@ internal string Description
{
return new Dictionary<string, object>()
{
{ this.Field, new string[] { this.Value } },
{ this.Field, this.Value },
};
}
}
Expand Down

0 comments on commit 0f69aca

Please sign in to comment.