* UserTest.cs: chore: 完善用户功能和测试
* LCUser.cs: * LCUserAuthDataLoginOption.cs: * LCHttpClient.cs:
parent
00941b3082
commit
6576cbd47f
|
@ -1,114 +1,186 @@
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Linq;
|
using LeanCloud.Storage;
|
||||||
using System;
|
|
||||||
using LeanCloud;
|
|
||||||
|
|
||||||
namespace LeanCloud.Test {
|
namespace LeanCloud.Test {
|
||||||
public class UserTest {
|
public class UserTest {
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void SetUp() {
|
public void SetUp() {
|
||||||
AVClient.Initialize(new AVClient.Configuration {
|
Logger.LogDelegate += Utils.Print;
|
||||||
ApplicationId = "BMYV4RKSTwo8WSqt8q9ezcWF-gzGzoHsz",
|
LeanCloud.Initialize("ikGGdRE2YcVOemAaRbgp1xGJ-gzGzoHsz", "NUKmuRbdAhg1vrb2wexYo1jo", "https://ikggdre2.lc-cn-n1-shared.com");
|
||||||
ApplicationKey = "pbf6Nk5seyjilexdpyrPwjSp",
|
}
|
||||||
ApiServer = "https://avoscloud.com"
|
|
||||||
});
|
[TearDown]
|
||||||
AVClient.HttpLog(TestContext.Out.WriteLine);
|
public void TearDown() {
|
||||||
|
Logger.LogDelegate -= Utils.Print;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public async Task Register() {
|
public async Task SignUp() {
|
||||||
AVUser user = new AVUser {
|
LCUser user = new LCUser();
|
||||||
Username = $"hello_{DateTimeOffset.UtcNow.ToUnixTimeSeconds()}",
|
long unixTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
|
||||||
Password = "world"
|
user.Username = $"{unixTime}";
|
||||||
};
|
user.Password = "world";
|
||||||
await user.SignUpAsync();
|
string email = $"{unixTime}@qq.com";
|
||||||
TestContext.Out.WriteLine($"{user.ObjectId} registered");
|
user.Email = email;
|
||||||
|
string mobile = $"{unixTime / 100}";
|
||||||
|
user.Mobile = mobile;
|
||||||
|
await user.SignUp();
|
||||||
|
|
||||||
|
TestContext.WriteLine(user.Username);
|
||||||
|
TestContext.WriteLine(user.Password);
|
||||||
|
|
||||||
|
Assert.NotNull(user.ObjectId);
|
||||||
|
TestContext.WriteLine(user.ObjectId);
|
||||||
|
Assert.NotNull(user.SessionToken);
|
||||||
|
TestContext.WriteLine(user.SessionToken);
|
||||||
|
Assert.AreEqual(user.Email, email);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public async Task LoginWithUsername() {
|
public async Task Login() {
|
||||||
AVUser user = await AVUser.LogInAsync("hello", "111111");
|
await LCUser.Login("hello", "world");
|
||||||
TestContext.Out.WriteLine($"{user.ObjectId}, {user.SessionToken} login");
|
LCUser current = await LCUser.GetCurrent();
|
||||||
|
Assert.NotNull(current.ObjectId);
|
||||||
|
Assert.IsFalse(current.EmailVerified);
|
||||||
|
Assert.IsFalse(current.MobileVerified);
|
||||||
|
Assert.AreEqual(current.Mobile, "15101006008");
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public async Task LoginWithEmail() {
|
public async Task LoginByEmail() {
|
||||||
AVUser user = await AVUser.LogInWithEmailAsync("111111@qq.com", "111111");
|
await LCUser.LoginByEmail("171253484@qq.com", "world");
|
||||||
Assert.AreEqual(user, AVUser.CurrentUser);
|
LCUser current = await LCUser.GetCurrent();
|
||||||
TestContext.Out.WriteLine($"{AVUser.CurrentUser.SessionToken} login");
|
Assert.NotNull(current.ObjectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public async Task Become() {
|
public async Task LoginBySessionToken() {
|
||||||
AVUser user = await AVUser.BecomeAsync("o8onm9bq8z127lz837mi6qhcg");
|
string sessionToken = "luo2fpl4qij2050e7enqfz173";
|
||||||
Assert.AreEqual(user, AVUser.CurrentUser);
|
await LCUser.BecomeWithSessionToken(sessionToken);
|
||||||
TestContext.Out.WriteLine($"{AVUser.CurrentUser.SessionToken} login");
|
LCUser current = await LCUser.GetCurrent();
|
||||||
|
Assert.NotNull(current.ObjectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public async Task IsAuthenticated() {
|
public async Task RelateObject() {
|
||||||
AVUser user = await AVUser.LogInWithEmailAsync("111111@qq.com", "111111");
|
LCUser user = await LCUser.LoginByMobilePhoneNumber("15101006007", "112358");
|
||||||
Assert.IsTrue(user.IsCurrent);
|
LCObject account = new LCObject("Account");
|
||||||
Assert.AreEqual(user, AVUser.CurrentUser);
|
account["user"] = user;
|
||||||
bool authenticated = await user.IsAuthenticatedAsync();
|
await account.Save();
|
||||||
Assert.IsTrue(authenticated);
|
Assert.AreEqual(user.ObjectId, "5e0d5c667d5774006a5c1177");
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public async Task RefreshSessionToken() {
|
public async Task LoginAnonymous() {
|
||||||
AVUser user = await AVUser.LogInWithEmailAsync("111111@qq.com", "111111");
|
LCUser user = await LCUser.LoginAnonymously();
|
||||||
Assert.IsTrue(user.IsCurrent);
|
Assert.NotNull(user.ObjectId);
|
||||||
await user.RefreshSessionTokenAsync();
|
|
||||||
TestContext.Out.WriteLine(user.SessionToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public async Task UpdatePassword() {
|
|
||||||
AVUser user = await AVUser.LogInAsync("111111", "111111");
|
|
||||||
await user.UpdatePasswordAsync("111111", "222222");
|
|
||||||
await user.UpdatePasswordAsync("222222", "111111");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public async Task LoginWithAuthData() {
|
public async Task LoginWithAuthData() {
|
||||||
AVUser user = await AVUser.LogInWithAuthDataAsync(new Dictionary<string, object> {
|
string uuid = Guid.NewGuid().ToString();
|
||||||
{ "openid", "0395BA18A5CD6255E5BA185E7BEBA242" },
|
Dictionary<string, object> authData = new Dictionary<string, object> {
|
||||||
{ "access_token", "12345678-SaMpLeTuo3m2avZxh5cjJmIrAfx4ZYyamdofM7IjU" },
|
{ "expires_in", 7200 },
|
||||||
{ "expires_in", 1382686496 }
|
{ "openid", uuid },
|
||||||
}, "qq");
|
{ "access_token", uuid }
|
||||||
Assert.NotNull(user.SessionToken);
|
};
|
||||||
TestContext.Out.WriteLine(user.SessionToken);
|
LCUser currentUser = await LCUser.LoginWithAuthData(authData, "weixin");
|
||||||
|
TestContext.WriteLine(currentUser.SessionToken);
|
||||||
|
Assert.NotNull(currentUser.SessionToken);
|
||||||
|
string userId = currentUser.ObjectId;
|
||||||
|
TestContext.WriteLine($"userId: {userId}");
|
||||||
|
TestContext.WriteLine(currentUser.AuthData);
|
||||||
|
|
||||||
|
await LCUser.Logout();
|
||||||
|
currentUser = await LCUser.GetCurrent();
|
||||||
|
Assert.IsNull(currentUser);
|
||||||
|
|
||||||
|
currentUser = await LCUser.LoginWithAuthData(authData, "weixin");
|
||||||
|
TestContext.WriteLine(currentUser.SessionToken);
|
||||||
|
Assert.NotNull(currentUser.SessionToken);
|
||||||
|
Assert.AreEqual(currentUser.ObjectId, userId);
|
||||||
|
TestContext.WriteLine(currentUser.AuthData);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public async Task AssociateAuthData() {
|
public async Task AssociateAuthData() {
|
||||||
AVUser user = await AVUser.LogInAsync("111111", "111111");
|
string uuid = Guid.NewGuid().ToString();
|
||||||
Assert.NotNull(user.SessionToken);
|
LCUser currentUser = await LCUser.Login("hello", "world");
|
||||||
await user.AssociateAuthDataAsync(new Dictionary<string, object> {
|
Dictionary<string, object> authData = new Dictionary<string, object> {
|
||||||
{ "openid", "0395BA18A5CD6255E5BA185E7BEBA243" },
|
{ "expires_in", 7200 },
|
||||||
{ "access_token", "12345678-SaMpLeTuo3m2avZxh5cjJmIrAfx4ZYyamdofM7IjU" },
|
{ "openid", uuid },
|
||||||
{ "expires_in", 1382686496 }
|
{ "access_token", uuid }
|
||||||
}, "qq");
|
};
|
||||||
|
await currentUser.AssociateAuthData(authData, "weixin");
|
||||||
|
TestContext.WriteLine(currentUser.AuthData);
|
||||||
|
TestContext.WriteLine(currentUser.AuthData["weixin"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public async Task Anonymously() {
|
public async Task DisassociateAuthData() {
|
||||||
AVUser user = await AVUser.LogInAnonymouslyAsync();
|
LCUser currentUser = await LCUser.Login("hello", "world");
|
||||||
Assert.NotNull(user.SessionToken);
|
await currentUser.DisassociateWithAuthData("weixin");
|
||||||
TestContext.Out.WriteLine(user.SessionToken);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public async Task GetRoles() {
|
public async Task IsAuthenticated() {
|
||||||
AVUser user = await AVUser.LogInAsync("111111", "111111");
|
LCUser currentUser = await LCUser.Login("hello", "world");
|
||||||
Assert.NotNull(user.SessionToken);
|
bool isAuthenticated = await currentUser.IsAuthenticated();
|
||||||
IEnumerable<AVRole> roles = await user.GetRolesAsync();
|
TestContext.WriteLine(isAuthenticated);
|
||||||
Assert.Greater(roles.Count(), 0);
|
Assert.IsTrue(isAuthenticated);
|
||||||
foreach (AVRole role in roles) {
|
|
||||||
TestContext.Out.WriteLine(role.Name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task UpdatePassword() {
|
||||||
|
LCUser currentUser = await LCUser.Login("hello", "world");
|
||||||
|
await currentUser.UpdatePassword("world", "newWorld");
|
||||||
|
await currentUser.UpdatePassword("newWorld", "world");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task LoginWithAuthDataWithUnionId() {
|
||||||
|
string uuid = Guid.NewGuid().ToString();
|
||||||
|
Dictionary<string, object> authData = new Dictionary<string, object> {
|
||||||
|
{ "expires_in", 7200 },
|
||||||
|
{ "openid", uuid },
|
||||||
|
{ "access_token", uuid }
|
||||||
|
};
|
||||||
|
string unionId = Guid.NewGuid().ToString();
|
||||||
|
|
||||||
|
LCUserAuthDataLoginOption option = new LCUserAuthDataLoginOption();
|
||||||
|
option.AsMainAccount = true;
|
||||||
|
LCUser currentUser = await LCUser.LoginWithAuthDataAndUnionId(authData, "weixin_app", unionId, option: option);
|
||||||
|
TestContext.WriteLine(currentUser.SessionToken);
|
||||||
|
Assert.NotNull(currentUser.SessionToken);
|
||||||
|
string userId = currentUser.ObjectId;
|
||||||
|
TestContext.WriteLine($"userId: {userId}");
|
||||||
|
TestContext.WriteLine(currentUser.AuthData);
|
||||||
|
|
||||||
|
await LCUser.Logout();
|
||||||
|
currentUser = await LCUser.GetCurrent();
|
||||||
|
Assert.IsNull(currentUser);
|
||||||
|
|
||||||
|
currentUser = await LCUser.LoginWithAuthDataAndUnionId(authData, "weixin_mini_app", unionId, option: option);
|
||||||
|
TestContext.WriteLine(currentUser.SessionToken);
|
||||||
|
Assert.NotNull(currentUser.SessionToken);
|
||||||
|
Assert.AreEqual(currentUser.ObjectId, userId);
|
||||||
|
TestContext.WriteLine(currentUser.AuthData);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task AssociateAuthDataWithUnionId() {
|
||||||
|
LCUser currentUser = await LCUser.Login("hello", "world");
|
||||||
|
string uuid = Guid.NewGuid().ToString();
|
||||||
|
Dictionary<string, object> authData = new Dictionary<string, object> {
|
||||||
|
{ "expires_in", 7200 },
|
||||||
|
{ "openid", uuid },
|
||||||
|
{ "access_token", uuid }
|
||||||
|
};
|
||||||
|
string unionId = Guid.NewGuid().ToString();
|
||||||
|
await currentUser.AssociateAuthDataAndUnionId(authData, "qq", unionId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ namespace LeanCloud.Storage.Internal.Http {
|
||||||
client.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue(product));
|
client.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue(product));
|
||||||
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
|
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
|
||||||
client.DefaultRequestHeaders.Add("X-LC-Id", appId);
|
client.DefaultRequestHeaders.Add("X-LC-Id", appId);
|
||||||
// TODO
|
// TODO 改为 signature
|
||||||
client.DefaultRequestHeaders.Add("X-LC-Key", appKey);
|
client.DefaultRequestHeaders.Add("X-LC-Key", appKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,6 +58,10 @@ namespace LeanCloud.Storage.Internal.Http {
|
||||||
request.Headers.Add(kv.Key, kv.Value.ToString());
|
request.Headers.Add(kv.Key, kv.Value.ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
LCUser currentUser = await LCUser.GetCurrent();
|
||||||
|
if (currentUser != null) {
|
||||||
|
request.Headers.Add("X-LC-Session", currentUser.SessionToken);
|
||||||
|
}
|
||||||
HttpUtils.PrintRequest(client, request);
|
HttpUtils.PrintRequest(client, request);
|
||||||
HttpResponseMessage response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
|
HttpResponseMessage response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
|
||||||
request.Dispose();
|
request.Dispose();
|
||||||
|
@ -144,6 +148,10 @@ namespace LeanCloud.Storage.Internal.Http {
|
||||||
Content = new StringContent(content)
|
Content = new StringContent(content)
|
||||||
};
|
};
|
||||||
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
|
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
|
||||||
|
LCUser currentUser = await LCUser.GetCurrent();
|
||||||
|
if (currentUser != null) {
|
||||||
|
request.Headers.Add("X-LC-Session", currentUser.SessionToken);
|
||||||
|
}
|
||||||
HttpUtils.PrintRequest(client, request, content);
|
HttpUtils.PrintRequest(client, request, content);
|
||||||
HttpResponseMessage response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
|
HttpResponseMessage response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
|
||||||
request.Dispose();
|
request.Dispose();
|
||||||
|
|
|
@ -1,11 +1,553 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using LeanCloud.Storage.Internal.Object;
|
||||||
|
|
||||||
namespace LeanCloud.Storage {
|
namespace LeanCloud.Storage {
|
||||||
public class LCUser : LCObject {
|
public class LCUser : LCObject {
|
||||||
public const string CLASS_NAME = "_User";
|
public const string CLASS_NAME = "_User";
|
||||||
|
|
||||||
|
public string Username {
|
||||||
|
get {
|
||||||
|
return this["username"] as string;
|
||||||
|
} set {
|
||||||
|
this["username"] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Password {
|
||||||
|
get {
|
||||||
|
return this["password"] as string;
|
||||||
|
} set {
|
||||||
|
this["password"] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Email {
|
||||||
|
get {
|
||||||
|
return this["email"] as string;
|
||||||
|
} set {
|
||||||
|
this["email"] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Mobile {
|
||||||
|
get {
|
||||||
|
return this["mobilePhoneNumber"] as string;
|
||||||
|
} set {
|
||||||
|
this["mobilePhoneNumber"] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string SessionToken {
|
||||||
|
get {
|
||||||
|
return this["sessionToken"] as string;
|
||||||
|
} set {
|
||||||
|
this["sessionToken"] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool EmailVerified {
|
||||||
|
get {
|
||||||
|
return (bool)this["emailVerified"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool MobileVerified {
|
||||||
|
get {
|
||||||
|
return (bool)this["mobilePhoneVerified"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Dictionary<string, object> AuthData {
|
||||||
|
get {
|
||||||
|
return this["authData"] as Dictionary<string, object>;
|
||||||
|
} set {
|
||||||
|
this["authData"] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static LCUser currentUser;
|
||||||
|
|
||||||
|
public static Task<LCUser> GetCurrent() {
|
||||||
|
// TODO 加载持久化数据
|
||||||
|
|
||||||
|
return Task.FromResult(currentUser);
|
||||||
|
}
|
||||||
|
|
||||||
public LCUser() : base(CLASS_NAME) {
|
public LCUser() : base(CLASS_NAME) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LCUser(LCObjectData objectData) : this() {
|
||||||
|
Merge(objectData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 注册
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<LCUser> SignUp() {
|
||||||
|
if (string.IsNullOrEmpty(Username)) {
|
||||||
|
throw new ArgumentNullException(nameof(Username));
|
||||||
|
}
|
||||||
|
if (string.IsNullOrEmpty(Password)) {
|
||||||
|
throw new ArgumentNullException(nameof(Password));
|
||||||
|
}
|
||||||
|
if (!string.IsNullOrEmpty(ObjectId)) {
|
||||||
|
throw new ArgumentException("Cannot sign up a user that already exists.");
|
||||||
|
}
|
||||||
|
await Save();
|
||||||
|
currentUser = this;
|
||||||
|
// TODO Persistence
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 请求登录注册码
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="mobile"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static async Task RequestLoginSMSCode(string mobile) {
|
||||||
|
if (string.IsNullOrEmpty(mobile)) {
|
||||||
|
throw new ArgumentNullException(nameof(mobile));
|
||||||
|
}
|
||||||
|
Dictionary<string, object> data = new Dictionary<string, object> {
|
||||||
|
{ "mobilePhoneNumber", mobile }
|
||||||
|
};
|
||||||
|
await LeanCloud.HttpClient.Post<Dictionary<string, object>>("requestLoginSmsCode", data: data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 使用手机号和验证码注册或登录
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="mobile"></param>
|
||||||
|
/// <param name="code"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static async Task<LCUser> SignUpOrLoginByMobilePhone(string mobile, string code) {
|
||||||
|
if (string.IsNullOrEmpty(mobile)) {
|
||||||
|
throw new ArgumentNullException(nameof(mobile));
|
||||||
|
}
|
||||||
|
if (string.IsNullOrEmpty(mobile)) {
|
||||||
|
throw new ArgumentNullException(nameof(code));
|
||||||
|
}
|
||||||
|
Dictionary<string, object> data = new Dictionary<string, object> {
|
||||||
|
{ "mobilePhoneNumber", mobile },
|
||||||
|
{ "smsCode", code }
|
||||||
|
};
|
||||||
|
Dictionary<string, object> response = await LeanCloud.HttpClient.Post<Dictionary<string, object>>("usersByMobilePhone", data: data);
|
||||||
|
LCObjectData objectData = LCObjectData.Decode(response);
|
||||||
|
currentUser = new LCUser(objectData);
|
||||||
|
return currentUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 以账号和密码登陆
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="username"></param>
|
||||||
|
/// <param name="password"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static Task<LCUser> Login(string username, string password) {
|
||||||
|
if (string.IsNullOrEmpty(username)) {
|
||||||
|
throw new ArgumentNullException(nameof(username));
|
||||||
|
}
|
||||||
|
if (string.IsNullOrEmpty(password)) {
|
||||||
|
throw new ArgumentNullException(nameof(password));
|
||||||
|
}
|
||||||
|
Dictionary<string, object> data = new Dictionary<string, object> {
|
||||||
|
{ "username", username },
|
||||||
|
{ "password", password }
|
||||||
|
};
|
||||||
|
return Login(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 以邮箱和密码登陆
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="email"></param>
|
||||||
|
/// <param name="password"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static Task<LCUser> LoginByEmail(string email, string password) {
|
||||||
|
if (string.IsNullOrEmpty(email)) {
|
||||||
|
throw new ArgumentNullException(nameof(email));
|
||||||
|
}
|
||||||
|
if (string.IsNullOrEmpty(password)) {
|
||||||
|
throw new ArgumentNullException(nameof(password));
|
||||||
|
}
|
||||||
|
Dictionary<string, object> data = new Dictionary<string, object> {
|
||||||
|
{ "email", email },
|
||||||
|
{ "password", password }
|
||||||
|
};
|
||||||
|
return Login(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 以手机号和密码登陆
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="mobile"></param>
|
||||||
|
/// <param name="password"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static Task<LCUser> LoginByMobilePhoneNumber(string mobile, string password) {
|
||||||
|
if (string.IsNullOrEmpty(mobile)) {
|
||||||
|
throw new ArgumentNullException(nameof(mobile));
|
||||||
|
}
|
||||||
|
if (string.IsNullOrEmpty(password)) {
|
||||||
|
throw new ArgumentNullException(nameof(password));
|
||||||
|
}
|
||||||
|
Dictionary<string, object> data = new Dictionary<string, object> {
|
||||||
|
{ "mobilePhoneNumber", mobile },
|
||||||
|
{ "password", password }
|
||||||
|
};
|
||||||
|
return Login(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 以手机号和验证码登录
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="mobile"></param>
|
||||||
|
/// <param name="code"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static Task<LCUser> LoginBySMSCode(string mobile, string code) {
|
||||||
|
if (string.IsNullOrEmpty(mobile)) {
|
||||||
|
throw new ArgumentNullException(nameof(mobile));
|
||||||
|
}
|
||||||
|
if (string.IsNullOrEmpty(code)) {
|
||||||
|
throw new ArgumentNullException(nameof(code));
|
||||||
|
}
|
||||||
|
Dictionary<string, object> data = new Dictionary<string, object> {
|
||||||
|
{ "mobilePhoneNumber", mobile },
|
||||||
|
{ "smsCode", code }
|
||||||
|
};
|
||||||
|
return Login(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 使用第三方数据登录
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="authData"></param>
|
||||||
|
/// <param name="platform"></param>
|
||||||
|
/// <param name="option"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static Task<LCUser> LoginWithAuthData(Dictionary<string, object> authData, string platform,
|
||||||
|
LCUserAuthDataLoginOption option = null) {
|
||||||
|
if (authData == null) {
|
||||||
|
throw new ArgumentNullException(nameof(authData));
|
||||||
|
}
|
||||||
|
if (string.IsNullOrEmpty(platform)) {
|
||||||
|
throw new ArgumentNullException(nameof(platform));
|
||||||
|
}
|
||||||
|
if (option == null) {
|
||||||
|
option = new LCUserAuthDataLoginOption();
|
||||||
|
}
|
||||||
|
return LoginWithAuthData(platform, authData, option.FailOnNotExist);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 使用第三方数据和 Union Id 登录
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="authData"></param>
|
||||||
|
/// <param name="platform"></param>
|
||||||
|
/// <param name="unionId"></param>
|
||||||
|
/// <param name="option"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static Task<LCUser> LoginWithAuthDataAndUnionId(Dictionary<string, object> authData, string platform, string unionId,
|
||||||
|
LCUserAuthDataLoginOption option = null) {
|
||||||
|
if (authData == null) {
|
||||||
|
throw new ArgumentNullException(nameof(authData));
|
||||||
|
}
|
||||||
|
if (string.IsNullOrEmpty(platform)) {
|
||||||
|
throw new ArgumentNullException(nameof(platform));
|
||||||
|
}
|
||||||
|
if (string.IsNullOrEmpty(unionId)) {
|
||||||
|
throw new ArgumentNullException(nameof(unionId));
|
||||||
|
}
|
||||||
|
if (option == null) {
|
||||||
|
option = new LCUserAuthDataLoginOption();
|
||||||
|
}
|
||||||
|
MergeAuthData(authData, unionId, option);
|
||||||
|
return LoginWithAuthData(platform, authData, option.FailOnNotExist);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 绑定第三方登录
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="authData"></param>
|
||||||
|
/// <param name="platform"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public Task AssociateAuthData(Dictionary<string, object> authData, string platform) {
|
||||||
|
if (authData == null) {
|
||||||
|
throw new ArgumentNullException(nameof(authData));
|
||||||
|
}
|
||||||
|
if (string.IsNullOrEmpty(platform)) {
|
||||||
|
throw new ArgumentNullException(nameof(platform));
|
||||||
|
}
|
||||||
|
return LinkWithAuthData(platform, authData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 使用 Union Id 绑定第三方登录
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="authData"></param>
|
||||||
|
/// <param name="platform"></param>
|
||||||
|
/// <param name="unionId"></param>
|
||||||
|
/// <param name="option"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public Task AssociateAuthDataAndUnionId(Dictionary<string, object> authData, string platform, string unionId,
|
||||||
|
LCUserAuthDataLoginOption option = null) {
|
||||||
|
if (authData == null) {
|
||||||
|
throw new ArgumentNullException(nameof(authData));
|
||||||
|
}
|
||||||
|
if (string.IsNullOrEmpty(platform)) {
|
||||||
|
throw new ArgumentNullException(nameof(platform));
|
||||||
|
}
|
||||||
|
if (string.IsNullOrEmpty(unionId)) {
|
||||||
|
throw new ArgumentNullException(nameof(unionId));
|
||||||
|
}
|
||||||
|
if (option == null) {
|
||||||
|
option = new LCUserAuthDataLoginOption();
|
||||||
|
}
|
||||||
|
MergeAuthData(authData, unionId, option);
|
||||||
|
return LinkWithAuthData(platform, authData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 解绑第三方登录
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="platform"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public Task DisassociateWithAuthData(string platform) {
|
||||||
|
if (string.IsNullOrEmpty(platform)) {
|
||||||
|
throw new ArgumentNullException(nameof(platform));
|
||||||
|
}
|
||||||
|
return LinkWithAuthData(platform, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 匿名登录
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static Task<LCUser> LoginAnonymously() {
|
||||||
|
Dictionary<string, object> data = new Dictionary<string, object> {
|
||||||
|
{ "id", Guid.NewGuid().ToString() }
|
||||||
|
};
|
||||||
|
return LoginWithAuthData(data, "anonymous");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 请求验证邮箱
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="email"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static async Task RequestEmailVerify(string email) {
|
||||||
|
if (string.IsNullOrEmpty(email)) {
|
||||||
|
throw new ArgumentNullException(nameof(email));
|
||||||
|
}
|
||||||
|
Dictionary<string, object> data = new Dictionary<string, object> {
|
||||||
|
{ "email", email }
|
||||||
|
};
|
||||||
|
await LeanCloud.HttpClient.Post<Dictionary<string, object>>("requestEmailVerify", data: data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 请求手机验证码
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="mobile"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static async Task RequestMobilePhoneVerify(string mobile) {
|
||||||
|
if (string.IsNullOrEmpty(mobile)) {
|
||||||
|
throw new ArgumentNullException(nameof(mobile));
|
||||||
|
}
|
||||||
|
Dictionary<string, object> data = new Dictionary<string, object> {
|
||||||
|
{ "mobilePhoneNumber", mobile }
|
||||||
|
};
|
||||||
|
await LeanCloud.HttpClient.Post<Dictionary<string, object>>("requestMobilePhoneVerify", data: data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 验证手机号
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="mobile"></param>
|
||||||
|
/// <param name="code"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static async Task VerifyMobilePhone(string mobile, string code) {
|
||||||
|
if (string.IsNullOrEmpty(mobile)) {
|
||||||
|
throw new ArgumentNullException(nameof(mobile));
|
||||||
|
}
|
||||||
|
if (string.IsNullOrEmpty(code)) {
|
||||||
|
throw new ArgumentNullException(nameof(code));
|
||||||
|
}
|
||||||
|
string path = $"verifyMobilePhone/{code}";
|
||||||
|
Dictionary<string, object> data = new Dictionary<string, object> {
|
||||||
|
{ "mobilePhoneNumber", mobile }
|
||||||
|
};
|
||||||
|
await LeanCloud.HttpClient.Post<Dictionary<string, object>>(path, data: data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设置当前用户
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sessionToken"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static async Task<LCUser> BecomeWithSessionToken(string sessionToken) {
|
||||||
|
if (string.IsNullOrEmpty(sessionToken)) {
|
||||||
|
throw new ArgumentNullException(nameof(sessionToken));
|
||||||
|
}
|
||||||
|
Dictionary<string, object> headers = new Dictionary<string, object> {
|
||||||
|
{ "X-LC-Session", sessionToken }
|
||||||
|
};
|
||||||
|
Dictionary<string, object> response = await LeanCloud.HttpClient.Get<Dictionary<string, object>>("users/me",
|
||||||
|
headers: headers);
|
||||||
|
LCObjectData objectData = LCObjectData.Decode(response);
|
||||||
|
currentUser = new LCUser(objectData);
|
||||||
|
return currentUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 请求使用邮箱重置密码
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="email"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static async Task RequestPasswordReset(string email) {
|
||||||
|
if (string.IsNullOrEmpty(email)) {
|
||||||
|
throw new ArgumentNullException(nameof(email));
|
||||||
|
}
|
||||||
|
Dictionary<string, object> data = new Dictionary<string, object> {
|
||||||
|
{ "email", email }
|
||||||
|
};
|
||||||
|
await LeanCloud.HttpClient.Post<Dictionary<string, object>>("requestPasswordReset",
|
||||||
|
data: data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 请求验证码重置密码
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="email"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static async Task RequestPasswordRestBySmsCode(string mobile) {
|
||||||
|
if (string.IsNullOrEmpty(mobile)) {
|
||||||
|
throw new ArgumentNullException(nameof(mobile));
|
||||||
|
}
|
||||||
|
Dictionary<string, object> data = new Dictionary<string, object> {
|
||||||
|
{ "mobilePhoneNumber", mobile }
|
||||||
|
};
|
||||||
|
await LeanCloud.HttpClient.Post<Dictionary<string, object>>("requestPasswordResetBySmsCode",
|
||||||
|
data: data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 使用验证码重置密码
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="mobile"></param>
|
||||||
|
/// <param name="code"></param>
|
||||||
|
/// <param name="newPassword"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static async Task ResetPasswordBySmsCode(string mobile, string code, string newPassword) {
|
||||||
|
if (string.IsNullOrEmpty(mobile)) {
|
||||||
|
throw new ArgumentNullException(nameof(mobile));
|
||||||
|
}
|
||||||
|
if (string.IsNullOrEmpty(code)) {
|
||||||
|
throw new ArgumentNullException(nameof(code));
|
||||||
|
}
|
||||||
|
if (string.IsNullOrEmpty(newPassword)) {
|
||||||
|
throw new ArgumentNullException(nameof(newPassword));
|
||||||
|
}
|
||||||
|
Dictionary<string, object> data = new Dictionary<string, object> {
|
||||||
|
{ "mobilePhoneNumber", mobile },
|
||||||
|
{ "password", newPassword }
|
||||||
|
};
|
||||||
|
await LeanCloud.HttpClient.Put<Dictionary<string, object>>($"resetPasswordBySmsCode/{code}",
|
||||||
|
data: data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 更新密码
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="oldPassword"></param>
|
||||||
|
/// <param name="newPassword"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task UpdatePassword(string oldPassword, string newPassword) {
|
||||||
|
if (string.IsNullOrEmpty(oldPassword)) {
|
||||||
|
throw new ArgumentNullException(nameof(oldPassword));
|
||||||
|
}
|
||||||
|
if (string.IsNullOrEmpty(newPassword)) {
|
||||||
|
throw new ArgumentNullException(nameof(newPassword));
|
||||||
|
}
|
||||||
|
Dictionary<string, object> data = new Dictionary<string, object> {
|
||||||
|
{ "old_password", oldPassword },
|
||||||
|
{ "new_password", newPassword }
|
||||||
|
};
|
||||||
|
Dictionary<string, object> response = await LeanCloud.HttpClient.Put<Dictionary<string, object>>(
|
||||||
|
$"users/{ObjectId}/updatePassword", data:data);
|
||||||
|
LCObjectData objectData = LCObjectData.Decode(response);
|
||||||
|
Merge(objectData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 注销登录
|
||||||
|
/// </summary>
|
||||||
|
public static Task Logout() {
|
||||||
|
currentUser = null;
|
||||||
|
// TODO 清理持久化数据
|
||||||
|
|
||||||
|
return Task.FromResult<object>(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否是有效登录
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<bool> IsAuthenticated() {
|
||||||
|
if (SessionToken == null || ObjectId == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
await LeanCloud.HttpClient.Get<Dictionary<string, object>>("users/me");
|
||||||
|
return true;
|
||||||
|
} catch (Exception) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 得到 LCUser 类型的查询对象
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static LCQuery<LCUser> GetQuery() {
|
||||||
|
return new LCQuery<LCUser>(CLASS_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
Task LinkWithAuthData(string authType, Dictionary<string, object> data) {
|
||||||
|
AuthData = new Dictionary<string, object> {
|
||||||
|
{ authType, data }
|
||||||
|
};
|
||||||
|
return Save();
|
||||||
|
}
|
||||||
|
|
||||||
|
static async Task<LCUser> Login(Dictionary<string, object> data) {
|
||||||
|
Dictionary<string, object> response = await LeanCloud.HttpClient.Post<Dictionary<string, object>>("login", data: data);
|
||||||
|
LCObjectData objectData = LCObjectData.Decode(response);
|
||||||
|
currentUser = new LCUser(objectData);
|
||||||
|
return currentUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
static async Task<LCUser> LoginWithAuthData(string authType, Dictionary<string, object> data, bool failOnNotExist) {
|
||||||
|
Dictionary<string, object> authData = new Dictionary<string, object> {
|
||||||
|
{ authType, data }
|
||||||
|
};
|
||||||
|
string path = failOnNotExist ? "users?failOnNotExist=true" : "users";
|
||||||
|
Dictionary<string, object> response = await LeanCloud.HttpClient.Post<Dictionary<string, object>>(path, data: new Dictionary<string, object> {
|
||||||
|
{ "authData", authData }
|
||||||
|
});
|
||||||
|
LCObjectData objectData = LCObjectData.Decode(response);
|
||||||
|
currentUser = new LCUser(objectData);
|
||||||
|
return currentUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MergeAuthData(Dictionary<string, object> authData, string unionId, LCUserAuthDataLoginOption option) {
|
||||||
|
authData["platform"] = option.UnionIdPlatform;
|
||||||
|
authData["main_account"] = option.AsMainAccount;
|
||||||
|
authData["unionid"] = unionId;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,33 @@
|
||||||
using System;
|
/// <summary>
|
||||||
|
/// 第三方登录选项
|
||||||
|
/// </summary>
|
||||||
namespace LeanCloud.Storage {
|
namespace LeanCloud.Storage {
|
||||||
public class LCUserAuthDataLoginOption {
|
public class LCUserAuthDataLoginOption {
|
||||||
|
/// <summary>
|
||||||
|
/// Union Id 平台
|
||||||
|
/// </summary>
|
||||||
|
public string UnionIdPlatform {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否作为主账号
|
||||||
|
/// </summary>
|
||||||
|
public bool AsMainAccount {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否在不存在的情况下返回失败
|
||||||
|
/// </summary>
|
||||||
|
public bool FailOnNotExist {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
public LCUserAuthDataLoginOption() {
|
public LCUserAuthDataLoginOption() {
|
||||||
|
UnionIdPlatform = "weixin";
|
||||||
|
AsMainAccount = false;
|
||||||
|
FailOnNotExist = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue