using LeanCloud.Storage.Internal;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace LeanCloud
{
///
/// Represents a user for a LeanCloud application.
///
[AVClassName("_User")]
public class AVUser : AVObject
{
private static readonly IDictionary authProviders =
new Dictionary();
private static readonly HashSet readOnlyKeys = new HashSet {
"sessionToken", "isNew"
};
internal static IAVUserController UserController
{
get
{
return AVPlugins.Instance.UserController;
}
}
internal static IAVCurrentUserController CurrentUserController
{
get
{
return AVPlugins.Instance.CurrentUserController;
}
}
///
/// Whether the AVUser has been authenticated on this device. Only an authenticated
/// AVUser can be saved and deleted.
///
[Obsolete("This property is deprecated, please use IsAuthenticatedAsync instead.")]
public bool IsAuthenticated
{
get
{
lock (mutex)
{
return SessionToken != null &&
CurrentUser != null &&
CurrentUser.ObjectId == ObjectId;
}
}
}
///
/// Whether the AVUser has been authenticated on this device, and the AVUser's session token is expired.
/// Only an authenticated AVUser can be saved and deleted.
///
public Task IsAuthenticatedAsync()
{
lock (mutex)
{
if (SessionToken == null || CurrentUser == null || CurrentUser.ObjectId != ObjectId)
{
return Task.FromResult(false);
}
}
var command = new AVCommand(String.Format("users/me?session_token={0}", CurrentSessionToken),
method: "GET",
data: null);
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
{
return AVClient.IsSuccessStatusCode(t.Result.Item1);
});
}
///
/// Refresh this user's session token, and current session token will be invalid.
///
public Task RefreshSessionTokenAsync(CancellationToken cancellationToken)
{
return UserController.RefreshSessionTokenAsync(ObjectId, SessionToken, cancellationToken).OnSuccess(t =>
{
var serverState = t.Result;
HandleSave(serverState);
});
}
///
/// Removes a key from the object's data if it exists.
///
/// The key to remove.
/// Cannot remove the username key.
public override void Remove(string key)
{
if (key == "username")
{
throw new ArgumentException("Cannot remove the username key.");
}
base.Remove(key);
}
protected override bool IsKeyMutable(string key)
{
return !readOnlyKeys.Contains(key);
}
internal override void HandleSave(IObjectState serverState)
{
base.HandleSave(serverState);
SynchronizeAllAuthData();
CleanupAuthData();
MutateState(mutableClone =>
{
mutableClone.ServerData.Remove("password");
});
}
///
/// authenticated token.
///
public string SessionToken
{
get
{
if (State.ContainsKey("sessionToken"))
{
return State["sessionToken"] as string;
}
return null;
}
}
internal static string CurrentSessionToken
{
get
{
Task sessionTokenTask = GetCurrentSessionTokenAsync();
sessionTokenTask.Wait();
return sessionTokenTask.Result;
}
}
internal static Task GetCurrentSessionTokenAsync(CancellationToken cancellationToken = default(CancellationToken))
{
return CurrentUserController.GetCurrentSessionTokenAsync(cancellationToken);
}
internal Task SetSessionTokenAsync(string newSessionToken)
{
return SetSessionTokenAsync(newSessionToken, CancellationToken.None);
}
internal Task SetSessionTokenAsync(string newSessionToken, CancellationToken cancellationToken)
{
MutateState(mutableClone =>
{
mutableClone.ServerData["sessionToken"] = newSessionToken;
});
return SaveCurrentUserAsync(this);
}
///
/// Gets or sets the username.
///
[AVFieldName("username")]
public string Username
{
get { return GetProperty(null, "Username"); }
set { SetProperty(value, "Username"); }
}
///
/// Sets the password.
///
[AVFieldName("password")]
public string Password
{
private get { return GetProperty(null, "Password"); }
set { SetProperty(value, "Password"); }
}
///
/// Sets the email address.
///
[AVFieldName("email")]
public string Email
{
get { return GetProperty(null, "Email"); }
set { SetProperty(value, "Email"); }
}
///
/// 用户手机号。
///
[AVFieldName("mobilePhoneNumber")]
public string MobilePhoneNumber
{
get
{
return GetProperty(null, "MobilePhoneNumber");
}
set
{
SetProperty(value, "MobilePhoneNumber");
}
}
///
/// 用户手机号是否已经验证
///
/// true if mobile phone verified; otherwise, false.
[AVFieldName("mobilePhoneVerified")]
public bool MobilePhoneVerified
{
get
{
return GetProperty(false, "MobilePhoneVerified");
}
set
{
SetProperty(value, "MobilePhoneVerified");
}
}
///
/// 判断用户是否为匿名用户
///
public bool IsAnonymous
{
get
{
bool rtn = false;
if (this.AuthData != null)
{
rtn = this.AuthData.Keys.Contains("anonymous");
}
return rtn;
}
}
internal Task SignUpAsync(Task toAwait, CancellationToken cancellationToken)
{
return this.Create(toAwait, cancellationToken).OnSuccess(_ => SaveCurrentUserAsync(this)).Unwrap();
}
///
/// Signs up a new user. This will create a new AVUser on the server and will also persist the
/// session on disk so that you can access the user using . A username and
/// password must be set before calling SignUpAsync.
///
public Task SignUpAsync()
{
return SignUpAsync(CancellationToken.None);
}
///
/// Signs up a new user. This will create a new AVUser on the server and will also persist the
/// session on disk so that you can access the user using . A username and
/// password must be set before calling SignUpAsync.
///
/// The cancellation token.
public Task SignUpAsync(CancellationToken cancellationToken)
{
return taskQueue.Enqueue(toAwait => SignUpAsync(toAwait, cancellationToken),
cancellationToken);
}
#region 事件流系统相关 API
///
/// 关注某个用户
///
/// 被关注的用户
///
public Task FollowAsync(string userObjectId)
{
return this.FollowAsync(userObjectId, null);
}
///
/// 关注某个用户
///
/// 被关注的用户Id
/// 关注的时候附加属性
///
public Task FollowAsync(string userObjectId, IDictionary data)
{
if (data != null)
{
data = this.EncodeForSaving(data);
}
var command = new AVCommand(string.Format("users/{0}/friendship/{1}", this.ObjectId, userObjectId),
method: "POST",
sessionToken: CurrentSessionToken,
data: data);
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
{
return AVClient.IsSuccessStatusCode(t.Result.Item1);
});
}
///
/// 取关某一个用户
///
///
///
public Task UnfollowAsync(string userObjectId)
{
var command = new AVCommand(string.Format("users/{0}/friendship/{1}", this.ObjectId, userObjectId),
method: "DELETE",
sessionToken: CurrentSessionToken,
data: null);
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
{
return AVClient.IsSuccessStatusCode(t.Result.Item1);
});
}
///
/// 获取当前用户的关注者的查询
///
///
public AVQuery GetFollowerQuery()
{
AVQuery query = new AVQuery();
query.RelativeUri = string.Format("users/{0}/followers", this.ObjectId);
return query;
}
///
/// 获取当前用户所关注的用户的查询
///
///
public AVQuery GetFolloweeQuery()
{
AVQuery query = new AVQuery();
query.RelativeUri = string.Format("users/{0}/followees", this.ObjectId);
return query;
}
///
/// 同时查询关注了当前用户的关注者和当前用户所关注的用户
///
///
public AVQuery GetFollowersAndFolloweesQuery()
{
AVQuery query = new AVQuery();
query.RelativeUri = string.Format("users/{0}/followersAndFollowees", this.ObjectId);
return query;
}
///
/// 获取当前用户的关注者
///
///
public Task> GetFollowersAsync()
{
return this.GetFollowerQuery().FindAsync();
}
///
/// 获取当前用户所关注的用户
///
///
public Task> GetFolloweesAsync()
{
return this.GetFolloweeQuery().FindAsync();
}
//public Task SendStatusAsync()
//{
//}
#endregion
///
/// Logs in a user with a username and password. On success, this saves the session to disk so you
/// can retrieve the currently logged in user using .
///
/// The username to log in with.
/// The password to log in with.
/// The newly logged-in user.
public static Task LogInAsync(string username, string password)
{
return LogInAsync(username, password, CancellationToken.None);
}
///
/// Logs in a user with a username and password. On success, this saves the session to disk so you
/// can retrieve the currently logged in user using .
///
/// The username to log in with.
/// The password to log in with.
/// The cancellation token.
/// The newly logged-in user.
public static Task LogInAsync(string username,
string password,
CancellationToken cancellationToken)
{
return UserController.LogInAsync(username, null, password, cancellationToken).OnSuccess(t =>
{
AVUser user = AVObject.FromState(t.Result, "_User");
return SaveCurrentUserAsync(user).OnSuccess(_ => user);
}).Unwrap();
}
///
/// Logs in a user with a username and password. On success, this saves the session to disk so you
/// can retrieve the currently logged in user using .
///
/// The session token to authorize with
/// The user if authorization was successful
public static Task BecomeAsync(string sessionToken)
{
return BecomeAsync(sessionToken, CancellationToken.None);
}
///
/// Logs in a user with a username and password. On success, this saves the session to disk so you
/// can retrieve the currently logged in user using .
///
/// The session token to authorize with
/// The cancellation token.
/// The user if authorization was successful
public static Task BecomeAsync(string sessionToken, CancellationToken cancellationToken)
{
return UserController.GetUserAsync(sessionToken, cancellationToken).OnSuccess(t =>
{
AVUser user = AVObject.FromState(t.Result, "_User");
return SaveCurrentUserAsync(user).OnSuccess(_ => user);
}).Unwrap();
}
protected override Task SaveAsync(Task toAwait, CancellationToken cancellationToken)
{
lock (mutex)
{
if (ObjectId == null)
{
throw new InvalidOperationException("You must call SignUpAsync before calling SaveAsync.");
}
return base.SaveAsync(toAwait, cancellationToken).OnSuccess(_ =>
{
if (!CurrentUserController.IsCurrent(this))
{
return Task.FromResult(0);
}
return SaveCurrentUserAsync(this);
}).Unwrap();
}
}
internal override Task FetchAsyncInternal(Task toAwait, IDictionary queryString, CancellationToken cancellationToken)
{
return base.FetchAsyncInternal(toAwait, queryString, cancellationToken).OnSuccess(t =>
{
if (!CurrentUserController.IsCurrent(this))
{
return Task.FromResult(t.Result);
}
// If this is already the current user, refresh its state on disk.
return SaveCurrentUserAsync(this).OnSuccess(_ => t.Result);
}).Unwrap();
}
///
/// Logs out the currently logged in user session. This will remove the session from disk, log out of
/// linked services, and future calls to will return null.
///
///
/// Typically, you should use , unless you are managing your own threading.
///
public static void LogOut()
{
// TODO (hallucinogen): this will without a doubt fail in Unity. But what else can we do?
LogOutAsync().Wait();
}
///
/// Logs out the currently logged in user session. This will remove the session from disk, log out of
/// linked services, and future calls to will return null.
///
///
/// This is preferable to using , unless your code is already running from a
/// background thread.
///
public static Task LogOutAsync()
{
return LogOutAsync(CancellationToken.None);
}
///
/// Logs out the currently logged in user session. This will remove the session from disk, log out of
/// linked services, and future calls to will return null.
///
/// This is preferable to using , unless your code is already running from a
/// background thread.
///
public static Task LogOutAsync(CancellationToken cancellationToken)
{
return GetCurrentUserAsync().OnSuccess(t =>
{
LogOutWithProviders();
AVUser user = t.Result;
if (user == null)
{
return Task.FromResult(0);
}
return user.taskQueue.Enqueue(toAwait => user.LogOutAsync(toAwait, cancellationToken), cancellationToken);
}).Unwrap();
}
internal Task LogOutAsync(Task toAwait, CancellationToken cancellationToken)
{
string oldSessionToken = SessionToken;
if (oldSessionToken == null)
{
return Task.FromResult(0);
}
// Cleanup in-memory session.
MutateState(mutableClone =>
{
mutableClone.ServerData.Remove("sessionToken");
});
var revokeSessionTask = AVSession.RevokeAsync(oldSessionToken, cancellationToken);
return Task.WhenAll(revokeSessionTask, CurrentUserController.LogOutAsync(cancellationToken));
}
private static void LogOutWithProviders()
{
foreach (var provider in authProviders.Values)
{
provider.Deauthenticate();
}
}
///
/// Gets the currently logged in AVUser with a valid session, either from memory or disk
/// if necessary.
///
public static AVUser CurrentUser
{
get
{
var userTask = GetCurrentUserAsync();
// TODO (hallucinogen): this will without a doubt fail in Unity. How should we fix it?
userTask.Wait();
return userTask.Result;
}
}
public static Task GetCurrentAsync()
{
var userTask = GetCurrentUserAsync();
return userTask;
}
///
/// Gets the currently logged in AVUser with a valid session, either from memory or disk
/// if necessary, asynchronously.
///
public static Task GetCurrentUserAsync()
{
return GetCurrentUserAsync(CancellationToken.None);
}
///
/// Gets the currently logged in AVUser with a valid session, either from memory or disk
/// if necessary, asynchronously.
///
internal static Task GetCurrentUserAsync(CancellationToken cancellationToken)
{
return CurrentUserController.GetAsync(cancellationToken);
}
private static Task SaveCurrentUserAsync(AVUser user)
{
return SaveCurrentUserAsync(user, CancellationToken.None);
}
private static Task SaveCurrentUserAsync(AVUser user, CancellationToken cancellationToken)
{
return CurrentUserController.SetAsync(user, cancellationToken);
}
internal static void ClearInMemoryUser()
{
CurrentUserController.ClearFromMemory();
}
///
/// Constructs a for AVUsers.
///
public static AVQuery Query
{
get
{
return new AVQuery();
}
}
#region Legacy / Revocable Session Tokens
private static readonly object isRevocableSessionEnabledMutex = new object();
private static bool isRevocableSessionEnabled;
///
/// Tells server to use revocable session on LogIn and SignUp, even when App's Settings
/// has "Require Revocable Session" turned off. Issues network request in background to
/// migrate the sessionToken on disk to revocable session.
///
/// The Task that upgrades the session.
public static Task EnableRevocableSessionAsync()
{
return EnableRevocableSessionAsync(CancellationToken.None);
}
///
/// Tells server to use revocable session on LogIn and SignUp, even when App's Settings
/// has "Require Revocable Session" turned off. Issues network request in background to
/// migrate the sessionToken on disk to revocable session.
///
/// The Task that upgrades the session.
public static Task EnableRevocableSessionAsync(CancellationToken cancellationToken)
{
lock (isRevocableSessionEnabledMutex)
{
isRevocableSessionEnabled = true;
}
return GetCurrentUserAsync(cancellationToken).OnSuccess(t =>
{
var user = t.Result;
return user.UpgradeToRevocableSessionAsync(cancellationToken);
});
}
internal static void DisableRevocableSession()
{
lock (isRevocableSessionEnabledMutex)
{
isRevocableSessionEnabled = false;
}
}
internal static bool IsRevocableSessionEnabled
{
get
{
lock (isRevocableSessionEnabledMutex)
{
return isRevocableSessionEnabled;
}
}
}
internal Task UpgradeToRevocableSessionAsync()
{
return UpgradeToRevocableSessionAsync(CancellationToken.None);
}
public Task UpgradeToRevocableSessionAsync(CancellationToken cancellationToken)
{
return taskQueue.Enqueue(toAwait => UpgradeToRevocableSessionAsync(toAwait, cancellationToken),
cancellationToken);
}
internal Task UpgradeToRevocableSessionAsync(Task toAwait, CancellationToken cancellationToken)
{
string sessionToken = SessionToken;
return toAwait.OnSuccess(_ =>
{
return AVSession.UpgradeToRevocableSessionAsync(sessionToken, cancellationToken);
}).Unwrap().OnSuccess(t =>
{
return SetSessionTokenAsync(t.Result);
}).Unwrap();
}
#endregion
///
/// Requests a password reset email to be sent to the specified email address associated with the
/// user account. This email allows the user to securely reset their password on the LeanCloud site.
///
/// The email address associated with the user that forgot their password.
public static Task RequestPasswordResetAsync(string email)
{
return RequestPasswordResetAsync(email, CancellationToken.None);
}
///
/// Requests a password reset email to be sent to the specified email address associated with the
/// user account. This email allows the user to securely reset their password on the LeanCloud site.
///
/// The email address associated with the user that forgot their password.
/// The cancellation token.
public static Task RequestPasswordResetAsync(string email,
CancellationToken cancellationToken)
{
return UserController.RequestPasswordResetAsync(email, cancellationToken);
}
///
/// Updates current user's password. Need the user's old password,
///
/// The password.
/// Old password.
/// New password.
/// Cancellation token.
public Task UpdatePassword(string oldPassword, string newPassword, CancellationToken cancellationToken)
{
return UserController.UpdatePasswordAsync(ObjectId, SessionToken, oldPassword, newPassword, cancellationToken);
}
///
/// Gets the authData for this user.
///
internal IDictionary> AuthData
{
get
{
IDictionary> authData;
if (this.TryGetValue>>(
"authData", out authData))
{
return authData;
}
return null;
}
private set
{
this["authData"] = value;
}
}
private static IAVAuthenticationProvider GetProvider(string providerName)
{
IAVAuthenticationProvider provider;
if (authProviders.TryGetValue(providerName, out provider))
{
return provider;
}
return null;
}
///
/// Removes null values from authData (which exist temporarily for unlinking)
///
private void CleanupAuthData()
{
lock (mutex)
{
if (!CurrentUserController.IsCurrent(this))
{
return;
}
var authData = AuthData;
if (authData == null)
{
return;
}
foreach (var pair in new Dictionary>(authData))
{
if (pair.Value == null)
{
authData.Remove(pair.Key);
}
}
}
}
///
/// 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));
}
}
}
private void SynchronizeAuthData(IAVAuthenticationProvider provider)
{
bool restorationSuccess = false;
lock (mutex)
{
var authData = AuthData;
if (authData == null || provider == null)
{
return;
}
IDictionary data;
if (authData.TryGetValue(provider.AuthType, out data))
{
restorationSuccess = provider.RestoreAuthentication(data);
}
}
if (!restorationSuccess)
{
this.UnlinkFromAsync(provider.AuthType, CancellationToken.None);
}
}
public Task LinkWithAsync(string authType, IDictionary data, CancellationToken cancellationToken)
{
return taskQueue.Enqueue(toAwait =>
{
AuthData = new Dictionary>();
AuthData[authType] = data;
return SaveAsync(cancellationToken);
}, cancellationToken);
}
public Task LinkWithAsync(string authType, CancellationToken cancellationToken)
{
var provider = GetProvider(authType);
return provider.AuthenticateAsync(cancellationToken)
.OnSuccess(t => LinkWithAsync(authType, t.Result, cancellationToken))
.Unwrap();
}
///
/// Unlinks a user from a service.
///
public Task UnlinkFromAsync(string authType, CancellationToken cancellationToken)
{
return LinkWithAsync(authType, null, cancellationToken);
}
///
/// 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 Task LogInWithAsync(string authType,
IDictionary data,
bool failOnNotExist,
CancellationToken cancellationToken)
{
AVUser user = null;
return UserController.LogInAsync(authType, data, failOnNotExist, cancellationToken).OnSuccess(t =>
{
user = AVObject.FromState(t.Result, "_User");
lock (user.mutex)
{
if (user.AuthData == null)
{
user.AuthData = new Dictionary>();
}
user.AuthData[authType] = data;
user.SynchronizeAllAuthData();
}
return SaveCurrentUserAsync(user);
}).Unwrap().OnSuccess(t => user);
}
internal static Task LogInWithAsync(string authType,
CancellationToken cancellationToken)
{
var provider = GetProvider(authType);
return provider.AuthenticateAsync(cancellationToken)
.OnSuccess(authData => LogInWithAsync(authType, authData.Result, false, cancellationToken))
.Unwrap();
}
internal static void RegisterProvider(IAVAuthenticationProvider provider)
{
authProviders[provider.AuthType] = provider;
var curUser = AVUser.CurrentUser;
if (curUser != null)
{
curUser.SynchronizeAuthData(provider);
}
}
#region 手机号登录
internal static Task LogInWithParametersAsync(Dictionary strs, CancellationToken cancellationToken)
{
AVUser avUser = AVObject.CreateWithoutData(null);
return UserController.LogInWithParametersAsync("login", strs, cancellationToken).OnSuccess(t =>
{
var user = (AVUser)AVObject.CreateWithoutData(null);
user.HandleFetchResult(t.Result);
return SaveCurrentUserAsync(user).OnSuccess(_ => user);
}).Unwrap();
}
///
/// 以手机号和密码实现登陆。
///
/// 手机号
/// 密码
///
public static Task LogInByMobilePhoneNumberAsync(string mobilePhoneNumber, string password)
{
return AVUser.LogInByMobilePhoneNumberAsync(mobilePhoneNumber, password, CancellationToken.None);
}
///
/// 以手机号和验证码匹配登陆
///
/// 手机号
/// 短信验证码
///
public static Task LogInBySmsCodeAsync(string mobilePhoneNumber, string smsCode)
{
return AVUser.LogInBySmsCodeAsync(mobilePhoneNumber, smsCode, CancellationToken.None);
}
///
/// 用邮箱作和密码匹配登录
///
/// 邮箱
/// 密码
///
public static Task LogInByEmailAsync(string email, string password, CancellationToken cancellationToken = default(CancellationToken))
{
return UserController.LogInAsync(null, email, password, cancellationToken).OnSuccess(t => {
AVUser user = AVObject.FromState(t.Result, "_User");
return SaveCurrentUserAsync(user).OnSuccess(_ => user);
}).Unwrap();
}
///
/// 以手机号和密码匹配登陆
///
/// 手机号
/// 密码
///
///
public static Task LogInByMobilePhoneNumberAsync(string mobilePhoneNumber, string password, CancellationToken cancellationToken)
{
Dictionary strs = new Dictionary()
{
{ "mobilePhoneNumber", mobilePhoneNumber },
{ "password", password }
};
return AVUser.LogInWithParametersAsync(strs, cancellationToken);
}
///
/// 以手机号和验证码登陆
///
/// 手机号
/// 短信验证码
///
///
public static Task LogInBySmsCodeAsync(string mobilePhoneNumber, string smsCode, CancellationToken cancellationToken = default(CancellationToken))
{
Dictionary strs = new Dictionary()
{
{ "mobilePhoneNumber", mobilePhoneNumber },
{ "smsCode", smsCode }
};
return AVUser.LogInWithParametersAsync(strs, cancellationToken);
}
///
/// Requests the login SMS code asynchronous.
///
/// The mobile phone number.
///
public static Task RequestLogInSmsCodeAsync(string mobilePhoneNumber)
{
return AVUser.RequestLogInSmsCodeAsync(mobilePhoneNumber, CancellationToken.None);
}
///
/// Requests the login SMS code asynchronous.
///
/// The mobile phone number.
/// Validate token.
///
public static Task RequestLogInSmsCodeAsync(string mobilePhoneNumber, string validateToken)
{
return AVUser.RequestLogInSmsCodeAsync(mobilePhoneNumber, null, CancellationToken.None);
}
///
/// Requests the login SMS code asynchronous.
///
/// The mobile phone number.
/// The cancellation token.
///
public static Task RequestLogInSmsCodeAsync(string mobilePhoneNumber, CancellationToken cancellationToken)
{
return RequestLogInSmsCodeAsync(mobilePhoneNumber, null, cancellationToken);
}
///
/// Requests the login SMS code asynchronous.
///
/// The mobile phone number.
/// Validate token.
/// The cancellation token.
///
public static Task RequestLogInSmsCodeAsync(string mobilePhoneNumber, string validateToken, CancellationToken cancellationToken)
{
Dictionary strs = new Dictionary()
{
{ "mobilePhoneNumber", mobilePhoneNumber },
};
if (String.IsNullOrEmpty(validateToken))
{
strs.Add("validate_token", validateToken);
}
var command = new AVCommand("requestLoginSmsCode",
method: "POST",
sessionToken: CurrentSessionToken,
data: strs);
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
{
return AVClient.IsSuccessStatusCode(t.Result.Item1);
});
}
///
/// 手机号一键登录
///
/// 手机号
/// 短信验证码
///
public static Task SignUpOrLogInByMobilePhoneAsync(string mobilePhoneNumber, string smsCode, CancellationToken cancellationToken)
{
Dictionary strs = new Dictionary()
{
{ "mobilePhoneNumber", mobilePhoneNumber },
{ "smsCode", smsCode }
};
return UserController.LogInWithParametersAsync("usersByMobilePhone", strs, cancellationToken).OnSuccess(t =>
{
var user = (AVUser)AVObject.CreateWithoutData(null);
user.HandleFetchResult(t.Result);
return SaveCurrentUserAsync(user).OnSuccess(_ => user);
}).Unwrap();
}
///
/// 手机号一键登录
///
/// signup or login by mobile phone async.
/// 手机号
/// 短信验证码
public static Task SignUpOrLogInByMobilePhoneAsync(string mobilePhoneNumber, string smsCode)
{
return AVUser.SignUpOrLogInByMobilePhoneAsync(mobilePhoneNumber, smsCode, CancellationToken.None);
}
#region mobile sms shortcode sign up & log in.
///
/// Send sign up sms code async.
///
/// The sign up sms code async.
/// Mobile phone number.
public static Task SendSignUpSmsCodeAsync(string mobilePhoneNumber)
{
return AVCloud.RequestSMSCodeAsync(mobilePhoneNumber);
}
///
/// Sign up by mobile phone async.
///
/// The up by mobile phone async.
/// Mobile phone number.
/// Sms code.
public static Task SignUpByMobilePhoneAsync(string mobilePhoneNumber, string smsCode)
{
return AVUser.SignUpOrLogInByMobilePhoneAsync(mobilePhoneNumber, smsCode);
}
///
/// Send log in sms code async.
///
/// The log in sms code async.
/// Mobile phone number.
public static Task SendLogInSmsCodeAsync(string mobilePhoneNumber)
{
return AVUser.RequestLogInSmsCodeAsync(mobilePhoneNumber);
}
///
/// Log in by mobile phone async.
///
/// The in by mobile phone async.
/// Mobile phone number.
/// Sms code.
public static Task LogInByMobilePhoneAsync(string mobilePhoneNumber, string smsCode)
{
return AVUser.LogInBySmsCodeAsync(mobilePhoneNumber, smsCode);
}
#endregion
#endregion
#region 重置密码
///
/// 请求重置密码,需要传入注册时使用的手机号。
///
/// 注册时使用的手机号
///
public static Task RequestPasswordResetBySmsCode(string mobilePhoneNumber)
{
return AVUser.RequestPasswordResetBySmsCode(mobilePhoneNumber, null, CancellationToken.None);
}
///
/// 请求重置密码,需要传入注册时使用的手机号。
///
/// 注册时使用的手机号
/// cancellationToken
///
public static Task RequestPasswordResetBySmsCode(string mobilePhoneNumber, CancellationToken cancellationToken)
{
return RequestPasswordResetBySmsCode(mobilePhoneNumber, null, cancellationToken);
}
///
/// 请求重置密码,需要传入注册时使用的手机号。
///
/// 注册时使用的手机号
/// Validate token.
///
public static Task RequestPasswordResetBySmsCode(string mobilePhoneNumber, string validateToken)
{
return AVUser.RequestPasswordResetBySmsCode(mobilePhoneNumber, validateToken, CancellationToken.None);
}
///
/// 请求重置密码,需要传入注册时使用的手机号。
///
/// 注册时使用的手机号
/// Validate token.
/// cancellationToken
///
public static Task RequestPasswordResetBySmsCode(string mobilePhoneNumber, string validateToken, CancellationToken cancellationToken)
{
string currentSessionToken = AVUser.CurrentSessionToken;
Dictionary strs = new Dictionary()
{
{ "mobilePhoneNumber", mobilePhoneNumber },
};
if (String.IsNullOrEmpty(validateToken))
{
strs.Add("validate_token", validateToken);
}
var command = new AVCommand("requestPasswordResetBySmsCode",
method: "POST",
sessionToken: currentSessionToken,
data: strs);
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
{
return AVClient.IsSuccessStatusCode(t.Result.Item1);
});
}
///
/// 通过验证码重置密码。
///
/// 新密码
/// 6位数验证码
///
public static Task ResetPasswordBySmsCodeAsync(string newPassword, string smsCode)
{
return AVUser.ResetPasswordBySmsCodeAsync(newPassword, smsCode, CancellationToken.None);
}
///
/// 通过验证码重置密码。
///
/// 新密码
/// 6位数验证码
/// cancellationToken
///
public static Task ResetPasswordBySmsCodeAsync(string newPassword, string smsCode, CancellationToken cancellationToken)
{
string currentSessionToken = AVUser.CurrentSessionToken;
Dictionary strs = new Dictionary()
{
{ "password", newPassword }
};
var command = new AVCommand("resetPasswordBySmsCode/" + smsCode,
method: "PUT",
sessionToken: currentSessionToken,
data: strs);
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
{
return AVClient.IsSuccessStatusCode(t.Result.Item1);
});
}
///
/// 发送认证码到需要认证的手机上
///
/// 手机号
///
public static Task RequestMobilePhoneVerifyAsync(string mobilePhoneNumber)
{
return AVUser.RequestMobilePhoneVerifyAsync(mobilePhoneNumber, null, CancellationToken.None);
}
///
/// 发送认证码到需要认证的手机上
///
/// 手机号
/// Validate token.
///
public static Task RequestMobilePhoneVerifyAsync(string mobilePhoneNumber, string validateToken)
{
return AVUser.RequestMobilePhoneVerifyAsync(mobilePhoneNumber, validateToken, CancellationToken.None);
}
///
/// 发送认证码到需要认证的手机上
///
/// 手机号
/// CancellationToken
///
public static Task RequestMobilePhoneVerifyAsync(string mobilePhoneNumber, CancellationToken cancellationToken)
{
return RequestMobilePhoneVerifyAsync(mobilePhoneNumber, null, cancellationToken);
}
///
/// 发送认证码到需要认证的手机上
///
/// 手机号
/// Validate token.
/// CancellationToken
///
public static Task RequestMobilePhoneVerifyAsync(string mobilePhoneNumber, string validateToken, CancellationToken cancellationToken)
{
string currentSessionToken = AVUser.CurrentSessionToken;
Dictionary strs = new Dictionary()
{
{ "mobilePhoneNumber", mobilePhoneNumber }
};
if (String.IsNullOrEmpty(validateToken))
{
strs.Add("validate_token", validateToken);
}
var command = new AVCommand("requestMobilePhoneVerify",
method: "POST",
sessionToken: currentSessionToken,
data: strs);
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
{
return AVClient.IsSuccessStatusCode(t.Result.Item1);
});
}
///
/// 验证手机验证码是否为有效值
///
/// 手机收到的验证码
/// 手机号
///
public static Task VerifyMobilePhoneAsync(string code, string mobilePhoneNumber)
{
return AVUser.VerifyMobilePhoneAsync(code, mobilePhoneNumber, CancellationToken.None);
}
///
/// 验证手机验证码是否为有效值
///
/// 手机收到的验证码
/// 手机号,可选
///
///
public static Task VerifyMobilePhoneAsync(string code, string mobilePhoneNumber, CancellationToken cancellationToken)
{
var command = new AVCommand("verifyMobilePhone/" + code.Trim() + "?mobilePhoneNumber=" + mobilePhoneNumber.Trim(),
method: "POST",
sessionToken: null,
data: null);
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
{
return AVClient.IsSuccessStatusCode(t.Result.Item1);
});
}
///
/// 验证手机验证码是否为有效值
///
/// 手机收到的验证码
///
public static Task VerifyMobilePhoneAsync(string code)
{
var command = new AVCommand("verifyMobilePhone/" + code.Trim(),
method: "POST",
sessionToken: null,
data: null);
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
{
return AVClient.IsSuccessStatusCode(t.Result.Item1);
});
}
///
/// 验证手机验证码是否为有效值
///
/// 手机收到的验证码
/// cancellationToken
///
public static Task VerifyMobilePhoneAsync(string code, CancellationToken cancellationToken)
{
return AVUser.VerifyMobilePhoneAsync(code, CancellationToken.None);
}
#endregion
#region 邮箱验证
///
/// 申请发送验证邮箱的邮件,一周之内有效
/// 如果该邮箱已经验证通过,会直接返回 True,并不会真正发送邮件
/// 注意,不能频繁的调用此接口,一天之内只允许向同一个邮箱发送验证邮件 3 次,超过调用次数,会直接返回错误
///
/// 邮箱地址
///
public static Task RequestEmailVerifyAsync(string email)
{
Dictionary strs = new Dictionary()
{
{ "email", email }
};
var command = new AVCommand("requestEmailVerify",
method: "POST",
sessionToken: null,
data: strs);
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
{
return AVClient.IsSuccessStatusCode(t.Result.Item1);
});
}
#endregion
#region in no-local-storage enviroment
internal Task Create()
{
return this.Create(CancellationToken.None);
}
internal Task Create(CancellationToken cancellationToken)
{
return taskQueue.Enqueue(toAwait => Create(toAwait, cancellationToken),
cancellationToken);
}
internal Task Create(Task toAwait, CancellationToken cancellationToken)
{
if (AuthData == null)
{
// TODO (hallucinogen): make an Extension of Task to create Task with exception/canceled.
if (string.IsNullOrEmpty(Username))
{
TaskCompletionSource