Skip to content

Commit 2dfb622

Browse files
committed
Fixing lint errors in user mgt code
2 parents ad58b40 + 88bcb1b commit 2dfb622

File tree

7 files changed

+520
-0
lines changed

7 files changed

+520
-0
lines changed

FirebaseAdmin/FirebaseAdmin.IntegrationTests/FirebaseAuthTest.cs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,34 @@ public async Task CreateCustomTokenWithoutServiceAccount()
9494
}
9595
}
9696

97+
[Fact]
98+
public async Task SetCustomUserClaims()
99+
{
100+
var customClaims = new Dictionary<string, object>()
101+
{
102+
{ "admin", true },
103+
};
104+
105+
await FirebaseAuth.DefaultInstance.SetCustomUserClaimsAsync("testuser", customClaims);
106+
}
107+
108+
[Fact]
109+
public async Task SetCustomUserClaimsWithEmptyClaims()
110+
{
111+
var customClaims = new Dictionary<string, object>();
112+
113+
await FirebaseAuth.DefaultInstance.SetCustomUserClaimsAsync("testuser", customClaims);
114+
}
115+
116+
[Fact]
117+
public async Task SetCustomUserClaimsWithWrongUid()
118+
{
119+
var customClaims = new Dictionary<string, object>();
120+
121+
await Assert.ThrowsAsync<FirebaseException>(
122+
async () => await FirebaseAuth.DefaultInstance.SetCustomUserClaimsAsync("mock-uid", customClaims));
123+
}
124+
97125
private static async Task<string> SignInWithCustomTokenAsync(string customToken)
98126
{
99127
var rb = new Google.Apis.Requests.RequestBuilder()

FirebaseAdmin/FirebaseAdmin.Tests/Auth/FirebaseAuthTest.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,18 @@ await Assert.ThrowsAnyAsync<OperationCanceledException>(
141141
idToken, canceller.Token));
142142
}
143143

144+
[Fact]
145+
public async Task SetCustomUserClaimsNoProjectId()
146+
{
147+
FirebaseApp.Create(new AppOptions() { Credential = MockCredential });
148+
var customClaims = new Dictionary<string, object>()
149+
{
150+
{ "admin", true },
151+
};
152+
await Assert.ThrowsAsync<ArgumentException>(
153+
async () => await FirebaseAuth.DefaultInstance.SetCustomUserClaimsAsync("user1", customClaims));
154+
}
155+
144156
public void Dispose()
145157
{
146158
FirebaseApp.DeleteAll();
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
// Copyright 2019, Google Inc. All rights reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
using System;
16+
using System.Collections.Generic;
17+
using System.Net;
18+
using System.Threading.Tasks;
19+
using FirebaseAdmin.Tests;
20+
using Google.Apis.Auth.OAuth2;
21+
using Xunit;
22+
23+
namespace FirebaseAdmin.Auth.Tests
24+
{
25+
public class FirebaseUserManagerTest
26+
{
27+
private const string MockProjectId = "project1";
28+
29+
private static readonly GoogleCredential MockCredential =
30+
GoogleCredential.FromAccessToken("test-token");
31+
32+
[Fact]
33+
public void InvalidUidForUserRecord()
34+
{
35+
Assert.Throws<ArgumentException>(() => new UserRecord(null));
36+
Assert.Throws<ArgumentException>(() => new UserRecord(string.Empty));
37+
Assert.Throws<ArgumentException>(() => new UserRecord(new string('a', 129)));
38+
}
39+
40+
[Fact]
41+
public void ReservedClaims()
42+
{
43+
foreach (var key in FirebaseTokenFactory.ReservedClaims)
44+
{
45+
var customClaims = new Dictionary<string, object>()
46+
{
47+
{ key, "value" },
48+
};
49+
Assert.Throws<ArgumentException>(() => new UserRecord("user1") { CustomClaims = customClaims });
50+
}
51+
}
52+
53+
[Fact]
54+
public void EmptyClaims()
55+
{
56+
var emptyClaims = new Dictionary<string, object>()
57+
{
58+
{ string.Empty, "value" },
59+
};
60+
Assert.Throws<ArgumentException>(() => new UserRecord("user1") { CustomClaims = emptyClaims });
61+
}
62+
63+
[Fact]
64+
public void TooLargeClaimsPayload()
65+
{
66+
var customClaims = new Dictionary<string, object>()
67+
{
68+
{ "testClaim", new string('a', 1001) },
69+
};
70+
71+
Assert.Throws<ArgumentException>(() => new UserRecord("user1") { CustomClaims = customClaims });
72+
}
73+
74+
[Fact]
75+
public async Task UpdateUser()
76+
{
77+
var handler = new MockMessageHandler()
78+
{
79+
Response = new UserRecord("user1"),
80+
};
81+
var factory = new MockHttpClientFactory(handler);
82+
var userManager = new FirebaseUserManager(
83+
new FirebaseUserManagerArgs
84+
{
85+
Credential = MockCredential,
86+
ProjectId = MockProjectId,
87+
ClientFactory = factory,
88+
});
89+
var customClaims = new Dictionary<string, object>()
90+
{
91+
{ "admin", true },
92+
};
93+
94+
await userManager.UpdateUserAsync(new UserRecord("user1") { CustomClaims = customClaims });
95+
}
96+
97+
[Fact]
98+
public async Task UpdateUserIncorrectResponseObject()
99+
{
100+
var handler = new MockMessageHandler()
101+
{
102+
Response = new object(),
103+
};
104+
var factory = new MockHttpClientFactory(handler);
105+
var userManager = new FirebaseUserManager(
106+
new FirebaseUserManagerArgs
107+
{
108+
Credential = MockCredential,
109+
ProjectId = MockProjectId,
110+
ClientFactory = factory,
111+
});
112+
var customClaims = new Dictionary<string, object>()
113+
{
114+
{ "admin", true },
115+
};
116+
117+
await Assert.ThrowsAsync<FirebaseException>(
118+
async () => await userManager.UpdateUserAsync(new UserRecord("user1") { CustomClaims = customClaims }));
119+
}
120+
121+
[Fact]
122+
public async Task UpdateUserIncorrectResponseUid()
123+
{
124+
var handler = new MockMessageHandler()
125+
{
126+
Response = new UserRecord("testuser"),
127+
};
128+
var factory = new MockHttpClientFactory(handler);
129+
var userManager = new FirebaseUserManager(
130+
new FirebaseUserManagerArgs
131+
{
132+
Credential = MockCredential,
133+
ProjectId = MockProjectId,
134+
ClientFactory = factory,
135+
});
136+
var customClaims = new Dictionary<string, object>()
137+
{
138+
{ "admin", true },
139+
};
140+
141+
await Assert.ThrowsAsync<FirebaseException>(
142+
async () => await userManager.UpdateUserAsync(new UserRecord("user1") { CustomClaims = customClaims }));
143+
}
144+
145+
[Fact]
146+
public async Task UpdateUserHttpError()
147+
{
148+
var handler = new MockMessageHandler()
149+
{
150+
StatusCode = HttpStatusCode.InternalServerError,
151+
};
152+
var factory = new MockHttpClientFactory(handler);
153+
var userManager = new FirebaseUserManager(
154+
new FirebaseUserManagerArgs
155+
{
156+
Credential = MockCredential,
157+
ProjectId = MockProjectId,
158+
ClientFactory = factory,
159+
});
160+
var customClaims = new Dictionary<string, object>()
161+
{
162+
{ "admin", true },
163+
};
164+
165+
await Assert.ThrowsAsync<FirebaseException>(
166+
async () => await userManager.UpdateUserAsync(new UserRecord("user1") { CustomClaims = customClaims }));
167+
}
168+
}
169+
}

FirebaseAdmin/FirebaseAdmin/Auth/FirebaseAuth.cs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ public sealed class FirebaseAuth : IFirebaseService
2828
private readonly FirebaseApp app;
2929
private readonly Lazy<FirebaseTokenFactory> tokenFactory;
3030
private readonly Lazy<FirebaseTokenVerifier> idTokenVerifier;
31+
private readonly Lazy<FirebaseUserManager> userManager;
3132
private readonly object authLock = new object();
3233
private bool deleted;
3334

@@ -38,6 +39,8 @@ private FirebaseAuth(FirebaseApp app)
3839
() => FirebaseTokenFactory.Create(this.app), true);
3940
this.idTokenVerifier = new Lazy<FirebaseTokenVerifier>(
4041
() => FirebaseTokenVerifier.CreateIDTokenVerifier(this.app), true);
42+
this.userManager = new Lazy<FirebaseUserManager>(() =>
43+
FirebaseUserManager.Create(this.app));
4144
}
4245

4346
/// <summary>
@@ -277,6 +280,39 @@ public async Task<FirebaseToken> VerifyIdTokenAsync(
277280
.ConfigureAwait(false);
278281
}
279282

283+
/// <summary>
284+
/// Sets the specified custom claims on an existing user account. A null claims value
285+
/// removes any claims currently set on the user account. The claims should serialize into
286+
/// a valid JSON string. The serialized claims must not be larger than 1000 characters.
287+
/// </summary>
288+
/// <returns>A task that completes when the claims have been set.</returns>
289+
/// <exception cref="ArgumentException">If <paramref name="uid"/> is null, empty or longer
290+
/// than 128 characters. Or, if the serialized <paramref name="claims"/> is larger than 1000
291+
/// characters.</exception>
292+
/// <param name="uid">The user ID string for the custom claims will be set. Must not be null
293+
/// or longer than 128 characters.
294+
/// </param>
295+
/// <param name="claims">The claims to be stored on the user account, and made
296+
/// available to Firebase security rules. These must be serializable to JSON, and after
297+
/// serialization it should not be larger than 1000 characters.</param>
298+
public async Task SetCustomUserClaimsAsync(string uid, IReadOnlyDictionary<string, object> claims)
299+
{
300+
lock (this.authLock)
301+
{
302+
if (this.deleted)
303+
{
304+
throw new InvalidOperationException("Cannot invoke after deleting the app.");
305+
}
306+
}
307+
308+
var user = new UserRecord(uid)
309+
{
310+
CustomClaims = claims,
311+
};
312+
313+
await this.userManager.Value.UpdateUserAsync(user);
314+
}
315+
280316
/// <summary>
281317
/// Deletes this <see cref="FirebaseAuth"/> service instance.
282318
/// </summary>
@@ -289,6 +325,11 @@ void IFirebaseService.Delete()
289325
{
290326
this.tokenFactory.Value.Dispose();
291327
}
328+
329+
if (this.userManager.IsValueCreated)
330+
{
331+
this.userManager.Value.Dispose();
332+
}
292333
}
293334
}
294335
}

0 commit comments

Comments
 (0)