diff --git a/Storage/Storage.Test/UserTest.cs b/Storage/Storage.Test/UserTest.cs
index f839c47..024b93b 100644
--- a/Storage/Storage.Test/UserTest.cs
+++ b/Storage/Storage.Test/UserTest.cs
@@ -35,7 +35,7 @@ namespace LeanCloudTests {
[Test]
public async Task LoginWithEmail() {
- AVUser user = await AVUser.LogInByEmailAsync("111111@qq.com", "111111");
+ AVUser user = await AVUser.LogInWithEmailAsync("111111@qq.com", "111111");
Assert.AreEqual(user, AVUser.CurrentUser);
TestContext.Out.WriteLine($"{AVUser.CurrentUser.SessionToken} login");
}
@@ -49,7 +49,7 @@ namespace LeanCloudTests {
[Test]
public async Task IsAuthenticated() {
- AVUser user = await AVUser.LogInByEmailAsync("111111@qq.com", "111111");
+ AVUser user = await AVUser.LogInWithEmailAsync("111111@qq.com", "111111");
Assert.IsTrue(user.IsCurrent);
Assert.AreEqual(user, AVUser.CurrentUser);
bool authenticated = await user.IsAuthenticatedAsync();
@@ -58,7 +58,7 @@ namespace LeanCloudTests {
[Test]
public async Task RefreshSessionToken() {
- AVUser user = await AVUser.LogInByEmailAsync("111111@qq.com", "111111");
+ AVUser user = await AVUser.LogInWithEmailAsync("111111@qq.com", "111111");
Assert.IsTrue(user.IsCurrent);
await user.RefreshSessionTokenAsync();
TestContext.Out.WriteLine(user.SessionToken);
diff --git a/Storage/Storage/Internal/Authentication/IAVAuthenticationProvider.cs b/Storage/Storage/Internal/Authentication/IAVAuthenticationProvider.cs
deleted file mode 100644
index 406e37c..0000000
--- a/Storage/Storage/Internal/Authentication/IAVAuthenticationProvider.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-using System.Collections.Generic;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace LeanCloud.Storage.Internal {
- public interface IAVAuthenticationProvider {
- ///
- /// Authenticates with the service.
- ///
- /// The cancellation token.
- Task> AuthenticateAsync(CancellationToken cancellationToken);
-
- ///
- /// Deauthenticates (logs out) the user associated with this provider. This
- /// call may block.
- ///
- void Deauthenticate();
-
- ///
- /// Restores authentication that has been serialized, such as session keys,
- /// etc.
- ///
- /// The auth data for the provider. This value may be null
- /// when unlinking an account.
- /// true iff the authData was successfully synchronized. A false return
- /// value indicates that the user should no longer be associated because of bad auth
- /// data.
- bool RestoreAuthentication(IDictionary authData);
-
- ///
- /// Provides a unique name for the type of authentication the provider does.
- /// For example, the FacebookAuthenticationProvider would return "facebook".
- ///
- string AuthType { get; }
- }
-}
diff --git a/Storage/Storage/Public/AVUser.cs b/Storage/Storage/Public/AVUser.cs
index 7a7f910..465397f 100644
--- a/Storage/Storage/Public/AVUser.cs
+++ b/Storage/Storage/Public/AVUser.cs
@@ -11,9 +11,6 @@ namespace LeanCloud {
///
[AVClassName("_User")]
public class AVUser : AVObject {
- private static readonly IDictionary authProviders =
- new Dictionary();
-
internal static AVUserController UserController {
get {
return AVPlugins.Instance.UserController;
@@ -21,52 +18,22 @@ namespace LeanCloud {
}
///
- /// 判断是否是当前用户
+ /// 获取当前用户
///
- public bool IsCurrent {
+ public static AVUser CurrentUser {
+ get;
+ internal set;
+ }
+
+ ///
+ /// 创建一个 AVUser 查询对象
+ ///
+ public static AVQuery Query {
get {
- return CurrentUser == this;
+ return new AVQuery();
}
}
- ///
- /// 判断当前用户的 Session Token 是否有效
- ///
- ///
- public async Task IsAuthenticatedAsync() {
- lock (mutex) {
- if (SessionToken == null || CurrentUser == null || CurrentUser.ObjectId != ObjectId) {
- return false;
- }
- }
- var command = new AVCommand {
- Path = $"users/me?session_token={SessionToken}",
- Method = HttpMethod.Get
- };
- await AVPlugins.Instance.CommandRunner.RunCommandAsync>(command);
- return true;
- }
-
- ///
- /// 刷新用户的 Session Token,刷新后 Session Token 将会改变
- ///
- ///
- public async Task RefreshSessionTokenAsync() {
- var serverState = await UserController.RefreshSessionTokenAsync(ObjectId);
- HandleSave(serverState);
- }
-
- ///
- /// 获取 Session Token
- ///
- public string SessionToken {
- get {
- if (State.ContainsKey("sessionToken")) {
- return State["sessionToken"] as string;
- }
- return null;
- }
- }
///
/// 用户名
@@ -134,6 +101,33 @@ namespace LeanCloud {
}
}
+ ///
+ /// 获取 Session Token
+ ///
+ public string SessionToken {
+ get {
+ if (State.ContainsKey("sessionToken")) {
+ return State["sessionToken"] as string;
+ }
+ return null;
+ }
+ }
+
+ ///
+ /// 用户数据
+ ///
+ internal IDictionary> AuthData {
+ get {
+ if (TryGetValue("authData", out IDictionary> authData)) {
+ return authData;
+ }
+ return null;
+ }
+ private set {
+ this["authData"] = value;
+ }
+ }
+
///
/// 判断用户是否为匿名用户
///
@@ -143,6 +137,44 @@ namespace LeanCloud {
}
}
+ ///
+ /// 判断是否是当前用户
+ ///
+ public bool IsCurrent {
+ get {
+ return CurrentUser == this;
+ }
+ }
+
+ ///
+ /// 判断当前用户的 Session Token 是否有效
+ ///
+ ///
+ public async Task IsAuthenticatedAsync() {
+ lock (mutex) {
+ if (SessionToken == null || CurrentUser == null || CurrentUser.ObjectId != ObjectId) {
+ return false;
+ }
+ }
+ var command = new AVCommand {
+ Path = $"users/me?session_token={SessionToken}",
+ Method = HttpMethod.Get
+ };
+ await AVPlugins.Instance.CommandRunner.RunCommandAsync>(command);
+ return true;
+ }
+
+ ///
+ /// 刷新用户的 Session Token,刷新后 Session Token 将会改变
+ ///
+ ///
+ public async Task RefreshSessionTokenAsync() {
+ var serverState = await UserController.RefreshSessionTokenAsync(ObjectId);
+ HandleSave(serverState);
+ }
+
+ #region 账号密码登陆
+
///
/// 注册新用户,注册成功后将保存为当前用户。必须设置用户名和密码。
///
@@ -170,99 +202,6 @@ namespace LeanCloud {
}
}
- #region 事件流系统相关 API
-
- ///
- /// 关注某个用户
- ///
- /// 被关注的用户
- ///
- public Task FollowAsync(string userObjectId) {
- return FollowAsync(userObjectId, null);
- }
-
- ///
- /// 关注某个用户
- ///
- /// 被关注的用户Id
- /// 关注的时候附加属性
- ///
- public Task FollowAsync(string userObjectId, IDictionary data) {
- if (data != null) {
- data = EncodeForSaving(data);
- }
- var command = new AVCommand {
- Path = $"users/{ObjectId}/friendship/{userObjectId}",
- Method = HttpMethod.Post,
- Content = data
- };
- return AVPlugins.Instance.CommandRunner.RunCommandAsync>(command);
- }
-
- ///
- /// 取关某一个用户
- ///
- ///
- ///
- public Task UnfollowAsync(string userObjectId) {
- var command = new AVCommand {
- Path = $"users/{ObjectId}/friendship/{userObjectId}",
- Method = HttpMethod.Delete
- };
- return AVPlugins.Instance.CommandRunner.RunCommandAsync>(command);
- }
-
- ///
- /// 获取当前用户的关注者的查询
- ///
- ///
- public AVQuery GetFollowerQuery() {
- AVQuery query = new AVQuery {
- Path = $"users/{ObjectId}/followers"
- };
- return query;
- }
-
- ///
- /// 获取当前用户所关注的用户的查询
- ///
- ///
- public AVQuery GetFolloweeQuery() {
- AVQuery query = new AVQuery {
- Path = $"users/{ObjectId}/followees"
- };
- return query;
- }
-
- ///
- /// 同时查询关注了当前用户的关注者和当前用户所关注的用户
- ///
- ///
- public AVQuery GetFollowersAndFolloweesQuery() {
- AVQuery query = new AVQuery {
- Path = $"users/{ObjectId}/followersAndFollowees"
- };
- return query;
- }
-
- ///
- /// 获取当前用户的关注者
- ///
- ///
- public Task> GetFollowersAsync() {
- return GetFollowerQuery().FindAsync(CancellationToken.None);
- }
-
- ///
- /// 获取当前用户所关注的用户
- ///
- ///
- public Task> GetFolloweesAsync() {
- return GetFolloweeQuery().FindAsync(CancellationToken.None);
- }
-
- #endregion
-
///
/// 使用用户名和密码登陆。登陆成功后,将用户设置为当前用户
///
@@ -277,45 +216,16 @@ namespace LeanCloud {
}
///
- /// 使用 Session Token 登录。
+ /// 用邮箱作和密码匹配登录
///
- /// Session Token
+ /// 邮箱
+ /// 密码
///
- public static async Task BecomeAsync(string sessionToken) {
- var ret = await UserController.GetUserAsync(sessionToken);
+ public static async Task LogInWithEmailAsync(string email, string password) {
+ var ret = await UserController.LogInAsync(null, email, password);
AVUser user = FromState(ret, "_User");
CurrentUser = user;
- return user;
- }
-
- ///
- /// 用户登出
- ///
- public static void LogOut() {
- CurrentUser = null;
- }
-
- private static void LogOutWithProviders() {
- foreach (var provider in authProviders.Values) {
- provider.Deauthenticate();
- }
- }
-
- ///
- /// 获取当前用户
- ///
- public static AVUser CurrentUser {
- get;
- internal set;
- }
-
- ///
- /// 创建一个 AVUser 查询对象
- ///
- public static AVQuery Query {
- get {
- return new AVQuery();
- }
+ return CurrentUser;
}
///
@@ -339,83 +249,99 @@ namespace LeanCloud {
}
///
- /// 用户数据
+ /// 申请发送验证邮箱的邮件,一周之内有效
+ /// 如果该邮箱已经验证通过,会直接返回 True,并不会真正发送邮件
+ /// 注意,不能频繁的调用此接口,一天之内只允许向同一个邮箱发送验证邮件 3 次,超过调用次数,会直接返回错误
///
- internal IDictionary> AuthData {
- get {
- if (TryGetValue("authData", out IDictionary> authData)) {
- return authData;
- }
- return null;
- }
- private set {
- this["authData"] = value;
- }
+ /// 邮箱地址
+ ///
+ public static Task RequestEmailVerifyAsync(string email) {
+ Dictionary strs = new Dictionary {
+ { "email", email }
+ };
+ var command = new AVCommand {
+ Path = "requestEmailVerify",
+ Method = HttpMethod.Post,
+ Content = strs
+ };
+ return AVPlugins.Instance.CommandRunner.RunCommandAsync>(command);
}
- private static IAVAuthenticationProvider GetProvider(string providerName) {
- if (authProviders.TryGetValue(providerName, out IAVAuthenticationProvider provider)) {
- return provider;
+ #endregion
+
+
+ #region 第三方登录
+
+ ///
+ /// 使用第三方数据注册;如果已经存在相同的 Auth Data,则执行登录
+ ///
+ /// Auth Data
+ /// 平台
+ ///
+ ///
+ public static Task LogInWithAuthDataAsync(IDictionary authData, string platform, AVUserAuthDataLogInOption options = null) {
+ if (options == null) {
+ options = new AVUserAuthDataLogInOption();
}
- return null;
+ return LogInWithAsync(platform, authData, options.FailOnNotExist);
}
///
- /// Removes null values from authData (which exist temporarily for unlinking)
+ /// 使用第三方数据注册;
///
- private void CleanupAuthData() {
- lock (mutex) {
- if (!IsCurrent) {
- return;
- }
- var authData = AuthData;
-
- if (authData == null) {
- return;
- }
-
- foreach (var pair in new Dictionary>(authData)) {
- if (pair.Value == null) {
- authData.Remove(pair.Key);
- }
- }
+ /// Auth data
+ /// 平台标识
+ ///
+ ///
+ ///
+ public static Task LogInWithAuthDataAndUnionIdAsync(IDictionary authData, string platform, string unionId,
+ AVUserAuthDataLogInOption options = null) {
+ if (options == null) {
+ options = new AVUserAuthDataLogInOption();
}
+ MergeAuthData(authData, unionId, options);
+ return LogInWithAsync(platform, authData, options.FailOnNotExist);
}
///
- /// Synchronizes authData for all providers.
+ /// 绑定第三方登录
///
- private void SynchronizeAllAuthData() {
- lock (mutex) {
- var authData = AuthData;
-
- if (authData == null) {
- return;
- }
-
- foreach (var pair in authData) {
- SynchronizeAuthData(GetProvider(pair.Key));
- }
- }
+ /// Auth data
+ /// 平台标识
+ ///
+ public Task AssociateAuthDataAsync(IDictionary authData, string platform) {
+ return LinkWithAsync(platform, authData);
}
- private void SynchronizeAuthData(IAVAuthenticationProvider provider) {
- bool restorationSuccess = false;
- lock (mutex) {
- var authData = AuthData;
- if (authData == null || provider == null) {
- return;
- }
- if (authData.TryGetValue(provider.AuthType, out IDictionary data)) {
- restorationSuccess = provider.RestoreAuthentication(data);
- }
- }
-
- if (!restorationSuccess) {
- UnlinkFromAsync(provider.AuthType, CancellationToken.None);
+ ///
+ /// 绑定第三方登录
+ ///
+ /// OAuth data
+ /// 平台标识
+ ///
+ ///
+ ///
+ public Task AssociateAuthDataAndUnionIdAsync(IDictionary authData, string platform, string unionId,
+ AVUserAuthDataLogInOption options = null) {
+ if (options == null) {
+ options = new AVUserAuthDataLogInOption();
}
+ MergeAuthData(authData, unionId, options);
+ return LinkWithAsync(platform, authData);
}
+ ///
+ /// 解绑第三方登录
+ ///
+ /// 平台标识
+ ///
+ public Task DisassociateWithAuthDataAsync(string platform) {
+ return LinkWithAsync(platform, null);
+ }
+
+ #endregion
+
+
public Task LinkWithAsync(string authType, IDictionary data) {
AuthData = new Dictionary> {
[authType] = data
@@ -423,85 +349,25 @@ namespace LeanCloud {
return SaveAsync();
}
- public Task LinkWithAsync(string authType, CancellationToken cancellationToken) {
- var provider = GetProvider(authType);
- return provider.AuthenticateAsync(cancellationToken)
- .OnSuccess(t => LinkWithAsync(authType, t.Result))
- .Unwrap();
- }
-
- ///
- /// Unlinks a user from a service.
- ///
- public Task UnlinkFromAsync(string authType, CancellationToken cancellationToken) {
- return LinkWithAsync(authType, null);
- }
-
- ///
- /// Checks whether a user is linked to a service.
- ///
- internal bool IsLinked(string authType) {
- lock (mutex) {
- return AuthData != null && AuthData.ContainsKey(authType) && AuthData[authType] != null;
- }
- }
-
internal static async Task LogInWithAsync(string authType, IDictionary data, bool failOnNotExist) {
var ret = await UserController.LogInAsync(authType, data, failOnNotExist);
AVUser user = FromState(ret, "_User");
- user.AuthData = new Dictionary>();
- user.AuthData[authType] = data;
- user.SynchronizeAllAuthData();
+ user.AuthData = new Dictionary> {
+ [authType] = data
+ };
CurrentUser = user;
return CurrentUser;
}
- internal static Task LogInWithAsync(string authType) {
- var provider = GetProvider(authType);
- return provider.AuthenticateAsync(CancellationToken.None)
- .OnSuccess(authData => LogInWithAsync(authType, authData.Result, false))
- .Unwrap();
- }
-
- internal static void RegisterProvider(IAVAuthenticationProvider provider) {
- authProviders[provider.AuthType] = provider;
- var curUser = CurrentUser;
- if (curUser != null) {
- curUser.SynchronizeAuthData(provider);
- }
- }
-
#region 手机号登录
- internal static async Task LogInWithParametersAsync(Dictionary strs) {
- IObjectState ret = await UserController.LogInWithParametersAsync("login", strs);
- AVUser user = CreateWithoutData(null);
- user.HandleFetchResult(ret);
- CurrentUser = user;
- return CurrentUser;
- }
-
- ///
- /// 用邮箱作和密码匹配登录
- ///
- /// 邮箱
- /// 密码
- ///
- public static async Task LogInByEmailAsync(string email, string password) {
- var ret = await UserController.LogInAsync(null, email, password);
- AVUser user = FromState(ret, "_User");
- CurrentUser = user;
- return CurrentUser;
- }
-
-
///
/// 用手机号和密码匹配登陆
///
/// 手机号
/// 密码
///
- public static Task LogInByMobilePhoneNumberAsync(string mobilePhoneNumber, string password) {
+ public static Task LogInWithMobilePhoneNumberAsync(string mobilePhoneNumber, string password) {
Dictionary strs = new Dictionary {
{ "mobilePhoneNumber", mobilePhoneNumber },
{ "password", password }
@@ -515,7 +381,7 @@ namespace LeanCloud {
/// 手机号
/// 短信验证码
///
- public static Task LogInByMobilePhoneNumberSmsCodeAsync(string mobilePhoneNumber, string smsCode) {
+ public static Task LogInWithMobilePhoneNumberSmsCodeAsync(string mobilePhoneNumber, string smsCode) {
Dictionary strs = new Dictionary {
{ "mobilePhoneNumber", mobilePhoneNumber },
{ "smsCode", smsCode }
@@ -641,60 +507,10 @@ namespace LeanCloud {
#endregion
- #region 邮箱验证
-
///
- /// 申请发送验证邮箱的邮件,一周之内有效
- /// 如果该邮箱已经验证通过,会直接返回 True,并不会真正发送邮件
- /// 注意,不能频繁的调用此接口,一天之内只允许向同一个邮箱发送验证邮件 3 次,超过调用次数,会直接返回错误
+ /// 匿名登录
///
- /// 邮箱地址
///
- public static Task RequestEmailVerifyAsync(string email) {
- Dictionary strs = new Dictionary {
- { "email", email }
- };
- var command = new AVCommand {
- Path = "requestEmailVerify",
- Method = HttpMethod.Post,
- Content = strs
- };
- return AVPlugins.Instance.CommandRunner.RunCommandAsync>(command);
- }
-
- #endregion
-
- #region AVUser Extension
-
- public IDictionary> GetAuthData() {
- return AuthData;
- }
-
- ///
- /// use 3rd auth data to sign up or log in.if user with the same auth data exits,it will transfer as log in.
- ///
- /// OAuth data, like {"accessToken":"xxxxxx"}
- /// auth platform,maybe "facebook"/"twiiter"/"weibo"/"weixin" .etc
- ///
- public static Task LogInWithAuthDataAsync(IDictionary data, string platform, AVUserAuthDataLogInOption options = null) {
- if (options == null) {
- options = new AVUserAuthDataLogInOption();
- }
- return LogInWithAsync(platform, data, options.FailOnNotExist);
- }
-
- public static Task LogInWithAuthDataAndUnionIdAsync(
- IDictionary authData,
- string platform,
- string unionId,
- AVUserAuthDataLogInOption options = null) {
- if (options == null) {
- options = new AVUserAuthDataLogInOption();
- }
- MergeAuthData(authData, unionId, options);
- return LogInWithAsync(platform, authData, options.FailOnNotExist);
- }
-
public static Task LogInAnonymouslyAsync() {
var data = new Dictionary {
{ "id", Guid.NewGuid().ToString() }
@@ -704,35 +520,124 @@ namespace LeanCloud {
}
///
- /// link a 3rd auth account to the user.
+ /// 使用 Session Token 登录。
///
- /// OAuth data, like {"accessToken":"xxxxxx"}
- /// auth platform,maybe "facebook"/"twiiter"/"weibo"/"weixin" .etc
+ /// Session Token
///
- public Task AssociateAuthDataAsync(IDictionary data, string platform) {
- return LinkWithAsync(platform, data);
- }
-
- public Task AssociateAuthDataAndUnionIdAsync(
- IDictionary authData,
- string platform,
- string unionId,
- AVUserAuthDataLogInOption options = null) {
- if (options == null) {
- options = new AVUserAuthDataLogInOption();
- }
- MergeAuthData(authData, unionId, options);
- return LinkWithAsync(platform, authData);
+ public static async Task BecomeAsync(string sessionToken) {
+ var ret = await UserController.GetUserAsync(sessionToken);
+ AVUser user = FromState(ret, "_User");
+ CurrentUser = user;
+ return user;
}
///
- /// unlink a 3rd auth account from the user.
+ /// 用户登出
///
- /// auth platform,maybe "facebook"/"twiiter"/"weibo"/"weixin" .etc
- ///
+ public static void LogOut() {
+ CurrentUser = null;
+ }
+
+ #region 事件流系统相关 API
+
+ ///
+ /// 关注某个用户
+ ///
+ /// 被关注的用户
///
- public Task DisassociateWithAuthDataAsync(string platform, CancellationToken cancellationToken = default(System.Threading.CancellationToken)) {
- return UnlinkFromAsync(platform, cancellationToken);
+ public Task FollowAsync(string userObjectId) {
+ return FollowAsync(userObjectId, null);
+ }
+
+ ///
+ /// 关注某个用户
+ ///
+ /// 被关注的用户Id
+ /// 关注的时候附加属性
+ ///
+ public Task FollowAsync(string userObjectId, IDictionary data) {
+ if (data != null) {
+ data = EncodeForSaving(data);
+ }
+ var command = new AVCommand {
+ Path = $"users/{ObjectId}/friendship/{userObjectId}",
+ Method = HttpMethod.Post,
+ Content = data
+ };
+ return AVPlugins.Instance.CommandRunner.RunCommandAsync>(command);
+ }
+
+ ///
+ /// 取关某一个用户
+ ///
+ ///
+ ///
+ public Task UnfollowAsync(string userObjectId) {
+ var command = new AVCommand {
+ Path = $"users/{ObjectId}/friendship/{userObjectId}",
+ Method = HttpMethod.Delete
+ };
+ return AVPlugins.Instance.CommandRunner.RunCommandAsync>(command);
+ }
+
+ ///
+ /// 获取当前用户的关注者的查询
+ ///
+ ///
+ public AVQuery GetFollowerQuery() {
+ AVQuery query = new AVQuery {
+ Path = $"users/{ObjectId}/followers"
+ };
+ return query;
+ }
+
+ ///
+ /// 获取当前用户所关注的用户的查询
+ ///
+ ///
+ public AVQuery GetFolloweeQuery() {
+ AVQuery query = new AVQuery {
+ Path = $"users/{ObjectId}/followees"
+ };
+ return query;
+ }
+
+ ///
+ /// 同时查询关注了当前用户的关注者和当前用户所关注的用户
+ ///
+ ///
+ public AVQuery GetFollowersAndFolloweesQuery() {
+ AVQuery query = new AVQuery {
+ Path = $"users/{ObjectId}/followersAndFollowees"
+ };
+ return query;
+ }
+
+ ///
+ /// 获取当前用户的关注者
+ ///
+ ///
+ public Task> GetFollowersAsync() {
+ return GetFollowerQuery().FindAsync(CancellationToken.None);
+ }
+
+ ///
+ /// 获取当前用户所关注的用户
+ ///
+ ///
+ public Task> GetFolloweesAsync() {
+ return GetFolloweeQuery().FindAsync(CancellationToken.None);
+ }
+
+ #endregion
+
+
+ internal static async Task LogInWithParametersAsync(Dictionary strs) {
+ IObjectState ret = await UserController.LogInWithParametersAsync("login", strs);
+ AVUser user = CreateWithoutData(null);
+ user.HandleFetchResult(ret);
+ CurrentUser = user;
+ return CurrentUser;
}
/// 合并为支持 AuthData 的格式
@@ -741,7 +646,5 @@ namespace LeanCloud {
authData["main_account"] = options.AsMainAccount;
authData["unionid"] = unionId;
}
-
- #endregion
}
}