Skip to content

Commit 972754e

Browse files
committed
Cleaning up public API and tests
1 parent b9ca619 commit 972754e

File tree

2 files changed

+135
-28
lines changed

2 files changed

+135
-28
lines changed

FirebaseAdmin/FirebaseAdmin.Tests/Auth/FirebaseUserManagerTest.cs

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,111 @@ public async Task GetUserById()
9595
ProjectId = MockProjectId,
9696
ClientFactory = factory,
9797
});
98+
99+
var userRecord = await userManager.GetUserById("user1");
100+
Assert.Equal("user1", userRecord.Uid);
101+
Assert.Null(userRecord.DisplayName);
102+
Assert.Null(userRecord.Email);
103+
Assert.Null(userRecord.PhoneNumber);
104+
Assert.Null(userRecord.PhotoUrl);
105+
Assert.Equal("firebase", userRecord.ProviderId);
106+
Assert.Empty(userRecord.CustomClaims);
107+
Assert.Empty(userRecord.ProviderData);
108+
Assert.False(userRecord.Disabled);
109+
Assert.False(userRecord.EmailVerified);
110+
Assert.Equal(UserRecord.UnixEpoch, userRecord.TokensValidAfterTimestamp);
111+
Assert.Equal(0, userRecord.UserMetaData.CreationTimestamp);
112+
Assert.Equal(0, userRecord.UserMetaData.LastSignInTimestamp);
113+
}
114+
115+
[Fact]
116+
public async Task GetUserByIdWithProperties()
117+
{
118+
var handler = new MockMessageHandler()
119+
{
120+
Response = new GetAccountInfoResponse()
121+
{
122+
Kind = "identitytoolkit#GetAccountInfoResponse",
123+
Users = new List<GetAccountInfoResponse.User>()
124+
{
125+
new GetAccountInfoResponse.User()
126+
{
127+
UserId = "user1",
128+
DisplayName = "Test User",
129+
Email = "[email protected]",
130+
PhoneNumber = "+11234567890",
131+
PhotoUrl = "https://domain.com/user.png",
132+
Disabled = true,
133+
EmailVerified = true,
134+
ValidSince = 3600,
135+
CreatedAt = 100,
136+
LastLoginAt = 150,
137+
CustomClaims = @"{""admin"": true, ""level"": 10}",
138+
Providers = new List<GetAccountInfoResponse.Provider>()
139+
{
140+
new GetAccountInfoResponse.Provider()
141+
{
142+
ProviderID = "google.com",
143+
UserId = "googleuid",
144+
},
145+
new GetAccountInfoResponse.Provider()
146+
{
147+
ProviderID = "other.com",
148+
UserId = "otheruid",
149+
DisplayName = "Other Name",
150+
},
151+
},
152+
},
153+
},
154+
},
155+
};
156+
157+
var factory = new MockHttpClientFactory(handler);
158+
var userManager = new FirebaseUserManager(
159+
new FirebaseUserManagerArgs
160+
{
161+
Credential = MockCredential,
162+
ProjectId = MockProjectId,
163+
ClientFactory = factory,
164+
});
165+
98166
var userRecord = await userManager.GetUserById("user1");
99167
Assert.Equal("user1", userRecord.Uid);
168+
Assert.Equal("Test User", userRecord.DisplayName);
169+
Assert.Equal("[email protected]", userRecord.Email);
170+
Assert.Equal("+11234567890", userRecord.PhoneNumber);
171+
Assert.Equal("https://domain.com/user.png", userRecord.PhotoUrl);
172+
Assert.Equal("firebase", userRecord.ProviderId);
173+
174+
var claims = new Dictionary<string, object>()
175+
{
176+
{ "admin", true },
177+
{ "level", 10L },
178+
};
179+
Assert.Equal(claims, userRecord.CustomClaims);
180+
181+
Assert.Equal(2, userRecord.ProviderData.Length);
182+
var provider = userRecord.ProviderData[0];
183+
Assert.Equal("google.com", provider.ProviderId);
184+
Assert.Equal("googleuid", provider.Uid);
185+
Assert.Null(provider.DisplayName);
186+
Assert.Null(provider.Email);
187+
Assert.Null(provider.PhoneNumber);
188+
Assert.Null(provider.PhotoUrl);
189+
190+
provider = userRecord.ProviderData[1];
191+
Assert.Equal("other.com", provider.ProviderId);
192+
Assert.Equal("otheruid", provider.Uid);
193+
Assert.Equal("Other Name", provider.DisplayName);
194+
Assert.Null(provider.Email);
195+
Assert.Null(provider.PhoneNumber);
196+
Assert.Null(provider.PhotoUrl);
197+
198+
Assert.True(userRecord.Disabled);
199+
Assert.True(userRecord.EmailVerified);
200+
Assert.Equal(UserRecord.UnixEpoch.AddSeconds(3600), userRecord.TokensValidAfterTimestamp);
201+
Assert.Equal(100, userRecord.UserMetaData.CreationTimestamp);
202+
Assert.Equal(150, userRecord.UserMetaData.LastSignInTimestamp);
100203
}
101204

102205
[Fact]

FirebaseAdmin/FirebaseAdmin/Auth/UserRecord.cs

Lines changed: 32 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,10 @@ namespace FirebaseAdmin.Auth
2727
/// </summary>
2828
public sealed class UserRecord : IUserInfo
2929
{
30-
private const string PROVIDERID = "firebase";
30+
internal static readonly DateTime UnixEpoch = new DateTime(
31+
1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
32+
33+
private const string DefaultProviderId = "firebase";
3134

3235
private string uid;
3336
private string email;
@@ -36,8 +39,8 @@ public sealed class UserRecord : IUserInfo
3639
private string displayName;
3740
private string photoUrl;
3841
private bool disabled;
39-
private List<ProviderUserInfo> providers;
40-
private long tokensValidAfterTimestamp;
42+
private IUserInfo[] providers;
43+
private long validSinceTimestampInSeconds;
4144
private UserMetadata userMetaData;
4245
private IReadOnlyDictionary<string, object> customClaims;
4346

@@ -80,20 +83,19 @@ internal UserRecord(GetAccountInfoResponse.User user)
8083

8184
if (user.Providers == null || user.Providers.Count == 0)
8285
{
83-
this.providers = new List<ProviderUserInfo>();
86+
this.providers = new IUserInfo[0];
8487
}
8588
else
8689
{
8790
var count = user.Providers.Count;
88-
this.providers = new List<ProviderUserInfo>(count);
89-
91+
this.providers = new IUserInfo[count];
9092
for (int i = 0; i < count; i++)
9193
{
92-
this.providers.Add(new ProviderUserInfo(user.Providers[i]));
94+
this.providers[i] = new ProviderUserInfo(user.Providers[i]);
9395
}
9496
}
9597

96-
this.tokensValidAfterTimestamp = user.ValidSince * 1000;
98+
this.validSinceTimestampInSeconds = user.ValidSince;
9799
this.userMetaData = new UserMetadata(user.CreatedAt, user.LastLoginAt);
98100
this.customClaims = UserRecord.ParseCustomClaims(user.CustomClaims);
99101
}
@@ -112,49 +114,43 @@ private set
112114
}
113115

114116
/// <summary>
115-
/// Gets the user's display name, if available.
117+
/// Gets the user's display name, if available. Otherwise null.
116118
/// </summary>
117-
/// <returns>a display name string or null.</returns>
118119
public string DisplayName
119120
{
120121
get => this.displayName;
121122
}
122123

123124
/// <summary>
124-
/// Gets the user's email address, if available.
125+
/// Gets the user's email address, if available. Otherwise null.
125126
/// </summary>
126-
/// <returns>an email address string or null.</returns>
127127
public string Email
128128
{
129129
get => this.email;
130130
}
131131

132132
/// <summary>
133-
/// Gets the user's phone number.
133+
/// Gets the user's phone number, if available. Otherwise null.
134134
/// </summary>
135-
/// <returns>a phone number string or null.</returns>
136135
public string PhoneNumber
137136
{
138137
get => this.phoneNumber;
139138
}
140139

141140
/// <summary>
142-
/// Gets the user's photo URL, if available.
141+
/// Gets the user's photo URL, if available. Otherwise null.
143142
/// </summary>
144-
/// <returns>a URL string or null.</returns>
145143
public string PhotoUrl
146144
{
147145
get => this.photoUrl;
148146
}
149147

150148
/// <summary>
151-
/// Gets the ID of the identity provider. This can be a short domain name (e.g. google.com) or
152-
/// the identifier of an OpenID identity provider.
149+
/// Gets the ID of the identity provider. This has the constant value <c>firebase</c>.
153150
/// </summary>
154-
/// <returns>an ID string that uniquely identifies the identity provider.</returns>
155151
public string ProviderId
156152
{
157-
get => UserRecord.PROVIDERID;
153+
get => UserRecord.DefaultProviderId;
158154
}
159155

160156
/// <summary>
@@ -168,28 +164,36 @@ public string ProviderId
168164
public bool Disabled => this.disabled;
169165

170166
/// <summary>
171-
/// Gets a list of provider data for this user.
167+
/// Gets a non-null array of provider data for this user. Possibly empty.
172168
/// </summary>
173-
public IEnumerable<IUserInfo> Providers => this.providers;
169+
public IUserInfo[] ProviderData => this.providers;
174170

175171
/// <summary>
176-
/// Gets a timestamp representing the date and time that this token will become active.
172+
/// Gets a timestamp that indicates the earliest point in time at which a valid ID token
173+
/// could have been issued to this user. Tokens issued prior to this timestamp are
174+
/// considered invalid.
177175
/// </summary>
178-
public long TokensValidAfterTimestamp => this.tokensValidAfterTimestamp;
176+
public DateTime TokensValidAfterTimestamp
177+
{
178+
get
179+
{
180+
return UnixEpoch.AddSeconds(this.validSinceTimestampInSeconds);
181+
}
182+
}
179183

180184
/// <summary>
181185
/// Gets additional user metadata.
182186
/// </summary>
183187
public UserMetadata UserMetaData => this.userMetaData;
184188

185189
/// <summary>
186-
/// Gets or sets the custom claims set on this user.
190+
/// Gets the custom claims set on this user.
187191
/// </summary>
188192
[JsonIgnore]
189193
public IReadOnlyDictionary<string, object> CustomClaims
190194
{
191195
get => this.customClaims;
192-
set
196+
internal set
193197
{
194198
CheckCustomClaims(value);
195199
this.customClaims = value;
@@ -204,7 +208,7 @@ public IReadOnlyDictionary<string, object> CustomClaims
204208
/// </summary>
205209
/// <param name="uid">The user ID. Must not be null or longer than
206210
/// 128 characters.</param>
207-
public static void CheckUid(string uid)
211+
private static void CheckUid(string uid)
208212
{
209213
if (string.IsNullOrEmpty(uid))
210214
{
@@ -222,7 +226,7 @@ public static void CheckUid(string uid)
222226
/// <param name="customClaims">The custom claims. Claim names must
223227
/// not be null or empty and must not be reserved and the serialized
224228
/// claims have to be less than 1000 bytes.</param>
225-
internal static void CheckCustomClaims(IReadOnlyDictionary<string, object> customClaims)
229+
private static void CheckCustomClaims(IReadOnlyDictionary<string, object> customClaims)
226230
{
227231
if (customClaims == null)
228232
{

0 commit comments

Comments
 (0)