diff --git a/Storage/Storage/Internal/AVCorePlugins.cs b/Storage/Storage/Internal/AVCorePlugins.cs index 0199c28..4b94af5 100644 --- a/Storage/Storage/Internal/AVCorePlugins.cs +++ b/Storage/Storage/Internal/AVCorePlugins.cs @@ -23,7 +23,6 @@ namespace LeanCloud.Storage.Internal { private AVFileController fileController; private AVObjectController objectController; private AVQueryController queryController; - private AVSessionController sessionController; private AVUserController userController; private ObjectSubclassingController subclassingController; @@ -43,7 +42,6 @@ namespace LeanCloud.Storage.Internal { CloudCodeController = null; FileController = null; ObjectController = null; - SessionController = null; UserController = null; SubclassingController = null; @@ -98,20 +96,8 @@ namespace LeanCloud.Storage.Internal { if (fileController != null) { return fileController; } - lock (mutex) { - switch (AVClient.CurrentConfiguration.RegionValue) { - case 0: - fileController = new QiniuFileController(); - break; - case 2: - fileController = new QCloudCosFileController(); - break; - case 1: - fileController = new AWSS3FileController(); - break; - } - return fileController; - } + fileController = new AVFileController(); + return fileController; } set { lock (mutex) { @@ -150,20 +136,6 @@ namespace LeanCloud.Storage.Internal { } } - public AVSessionController SessionController { - get { - lock (mutex) { - sessionController = sessionController ?? new AVSessionController(); - return sessionController; - } - } - set { - lock (mutex) { - sessionController = value; - } - } - } - public AVUserController UserController { get { lock (mutex) { diff --git a/Storage/Storage/Internal/File/Controller/AVFileController.cs b/Storage/Storage/Internal/File/Controller/AVFileController.cs index f58a30e..c76f7d7 100644 --- a/Storage/Storage/Internal/File/Controller/AVFileController.cs +++ b/Storage/Storage/Internal/File/Controller/AVFileController.cs @@ -8,12 +8,40 @@ using System.Collections.Generic; using System.Linq; namespace LeanCloud.Storage.Internal { - public abstract class AVFileController { - public abstract Task SaveAsync(FileState state, + public interface IFileUploader { + Task Upload(FileState state, Stream dataStream, IDictionary fileToken, IProgress progress, + CancellationToken cancellationToken); + } + + public class AVFileController { + const string QCloud = "qcloud"; + const string AWS = "s3"; + + public Task SaveAsync(FileState state, Stream dataStream, String sessionToken, IProgress progress, - CancellationToken cancellationToken = default(CancellationToken)); + CancellationToken cancellationToken = default(CancellationToken)) { + if (state.Url != null) { + // !isDirty + return Task.FromResult(state); + } + + return GetFileToken(state, cancellationToken).OnSuccess(t => { + // 根据 provider 区分 cdn + var ret = t.Result; + var fileToken = ret.Item2; + var provider = fileToken["provider"] as string; + switch (provider) { + case QCloud: + return new QCloudUploader().Upload(state, dataStream, fileToken, progress, cancellationToken); + case AWS: + return new AWSUploader().Upload(state, dataStream, fileToken, progress, cancellationToken); + default: + return new QiniuUploader().Upload(state, dataStream, fileToken, progress, cancellationToken); + } + }).Unwrap(); + } public Task DeleteAsync(FileState state, string sessionToken, CancellationToken cancellationToken) { var command = new AVCommand { @@ -24,7 +52,6 @@ namespace LeanCloud.Storage.Internal { } internal Task>> GetFileToken(FileState fileState, CancellationToken cancellationToken) { - Task>> rtn; string currentSessionToken = AVUser.CurrentSessionToken; string str = fileState.Name; IDictionary parameters = new Dictionary(); diff --git a/Storage/Storage/Internal/File/Controller/AWSS3FileController.cs b/Storage/Storage/Internal/File/Controller/AWSUploader.cs similarity index 56% rename from Storage/Storage/Internal/File/Controller/AWSS3FileController.cs rename to Storage/Storage/Internal/File/Controller/AWSUploader.cs index 2dfa8bb..f6b6be6 100644 --- a/Storage/Storage/Internal/File/Controller/AWSS3FileController.cs +++ b/Storage/Storage/Internal/File/Controller/AWSUploader.cs @@ -6,21 +6,14 @@ using System.Collections.Generic; using System.Net.Http; namespace LeanCloud.Storage.Internal { - internal class AWSS3FileController : AVFileController { - public override Task SaveAsync(FileState state, Stream dataStream, string sessionToken, IProgress progress, CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { - if (state.Url != null) { - return Task.FromResult(state); - } - - return GetFileToken(state, cancellationToken).OnSuccess(t => { - var fileToken = t.Result.Item2; - var uploadUrl = fileToken["upload_url"].ToString(); - state.ObjectId = fileToken["objectId"].ToString(); - string url = fileToken["url"] as string; - state.Url = new Uri(url, UriKind.Absolute); - return PutFile(state, uploadUrl, dataStream); - - }).Unwrap().OnSuccess(s => { + internal class AWSUploader : IFileUploader { + public Task Upload(FileState state, Stream dataStream, IDictionary fileToken, IProgress progress, + CancellationToken cancellationToken) { + var uploadUrl = fileToken["upload_url"].ToString(); + state.ObjectId = fileToken["objectId"].ToString(); + string url = fileToken["url"] as string; + state.Url = new Uri(url, UriKind.Absolute); + return PutFile(state, uploadUrl, dataStream).OnSuccess(s => { return s.Result; }); } diff --git a/Storage/Storage/Internal/File/Controller/QCloudCosFileController.cs b/Storage/Storage/Internal/File/Controller/QCloudUploader.cs similarity index 84% rename from Storage/Storage/Internal/File/Controller/QCloudCosFileController.cs rename to Storage/Storage/Internal/File/Controller/QCloudUploader.cs index be6f47f..6f47b42 100644 --- a/Storage/Storage/Internal/File/Controller/QCloudCosFileController.cs +++ b/Storage/Storage/Internal/File/Controller/QCloudUploader.cs @@ -6,10 +6,9 @@ using System.Net.Http; using System.Text; using System.Threading; using System.Threading.Tasks; -using Newtonsoft.Json; namespace LeanCloud.Storage.Internal { - internal class QCloudCosFileController : AVFileController { + internal class QCloudUploader : IFileUploader { private object mutex = new object(); FileState fileState; @@ -20,33 +19,22 @@ namespace LeanCloud.Storage.Internal { bool done; private long sliceSize = (long)CommonSize.KB512; - public override Task SaveAsync(FileState state, - Stream dataStream, - string sessionToken, - IProgress progress, - CancellationToken cancellationToken) { - if (state.Url != null) { - return Task.FromResult(state); - } + public Task Upload(FileState state, Stream dataStream, IDictionary fileToken, IProgress progress, CancellationToken cancellationToken) { fileState = state; data = dataStream; - return GetFileToken(fileState, cancellationToken).OnSuccess(_ => { - var fileToken = _.Result.Item2; - uploadUrl = fileToken["upload_url"].ToString(); - token = fileToken["token"].ToString(); - fileState.ObjectId = fileToken["objectId"].ToString(); - bucket = fileToken["bucket"].ToString(); - - return FileSlice(cancellationToken).OnSuccess(t => { - if (done) return Task.FromResult(state); - var response = t.Result.Item2; - var resumeData = response["data"] as IDictionary; - if (resumeData.ContainsKey("access_url")) return Task.FromResult(state); - var sliceSession = resumeData["session"].ToString(); - var sliceOffset = long.Parse(resumeData["offset"].ToString()); - return UploadSlice(sliceSession, sliceOffset, dataStream, progress, cancellationToken); - }).Unwrap(); + uploadUrl = fileToken["upload_url"].ToString(); + token = fileToken["token"].ToString(); + fileState.ObjectId = fileToken["objectId"].ToString(); + bucket = fileToken["bucket"].ToString(); + return FileSlice(cancellationToken).OnSuccess(t => { + if (done) return Task.FromResult(state); + var response = t.Result.Item2; + var resumeData = response["data"] as IDictionary; + if (resumeData.ContainsKey("access_url")) return Task.FromResult(state); + var sliceSession = resumeData["session"].ToString(); + var sliceOffset = long.Parse(resumeData["offset"].ToString()); + return UploadSlice(sliceSession, sliceOffset, dataStream, progress, cancellationToken); }).Unwrap(); } diff --git a/Storage/Storage/Internal/File/Controller/QiniuFileController.cs b/Storage/Storage/Internal/File/Controller/QiniuUploader.cs similarity index 81% rename from Storage/Storage/Internal/File/Controller/QiniuFileController.cs rename to Storage/Storage/Internal/File/Controller/QiniuUploader.cs index 935f1ae..5a83f79 100644 --- a/Storage/Storage/Internal/File/Controller/QiniuFileController.cs +++ b/Storage/Storage/Internal/File/Controller/QiniuUploader.cs @@ -9,104 +9,75 @@ using System.Threading.Tasks; using System.Net.Http; using Newtonsoft.Json; -namespace LeanCloud.Storage.Internal -{ - internal enum CommonSize : long - { +namespace LeanCloud.Storage.Internal { + internal enum CommonSize : long { MB4 = 1024 * 1024 * 4, MB1 = 1024 * 1024, KB512 = 1024 * 1024 / 2, KB256 = 1024 * 1024 / 4 } - internal class QiniuFileController : AVFileController - { + internal class QiniuUploader : IFileUploader { private static int BLOCKSIZE = 1024 * 1024 * 4; private const int blockMashk = (1 << blockBits) - 1; private const int blockBits = 22; - private int CalcBlockCount(long fsize) - { + private int CalcBlockCount(long fsize) { return (int)((fsize + blockMashk) >> blockBits); } internal static string UP_HOST = "https://up.qbox.me"; private object mutex = new object(); - public override Task SaveAsync(FileState state, - Stream dataStream, - String sessionToken, - IProgress progress, - CancellationToken cancellationToken) - { - if (state.Url != null) - { - return Task.FromResult(state); - } + public Task Upload(FileState state, Stream dataStream, IDictionary fileToken, IProgress progress, CancellationToken cancellationToken) { state.frozenData = dataStream; state.CloudName = GetUniqueName(state); - return GetQiniuToken(state, CancellationToken.None).ContinueWith(t => - { - MergeFromJSON(state, t.Result.Item2); - return UploadNextChunk(state, dataStream, string.Empty, 0, progress); - }).Unwrap().OnSuccess(s => - { + MergeFromJSON(state, fileToken); + return UploadNextChunk(state, dataStream, string.Empty, 0, progress).OnSuccess(_ => { return state; }); } - Task UploadNextChunk(FileState state, Stream dataStream, string context, long offset, IProgress progress) - { + + Task UploadNextChunk(FileState state, Stream dataStream, string context, long offset, IProgress progress) { var totalSize = dataStream.Length; var remainingSize = totalSize - state.completed; - if (progress != null) - { - lock (mutex) - { - progress.Report(new AVUploadProgressEventArgs() - { + if (progress != null) { + lock (mutex) { + progress.Report(new AVUploadProgressEventArgs() { Progress = AVFileController.CalcProgress(state.completed, totalSize) }); } } - if (state.completed == totalSize) - { + if (state.completed == totalSize) { return QiniuMakeFile(state, state.frozenData, state.token, state.CloudName, totalSize, state.block_ctxes.ToArray(), CancellationToken.None); - } - else if (state.completed % BLOCKSIZE == 0) - { + } else if (state.completed % BLOCKSIZE == 0) { var firstChunkBinary = GetChunkBinary(state.completed, dataStream); var blockSize = remainingSize > BLOCKSIZE ? BLOCKSIZE : remainingSize; - return MakeBlock(state, firstChunkBinary, blockSize).ContinueWith(t => - { + return MakeBlock(state, firstChunkBinary, blockSize).ContinueWith(t => { var dict = JsonConvert.DeserializeObject>(t.Result.Item2, new LeanCloudJsonConverter()); var ctx = dict["ctx"].ToString(); offset = long.Parse(dict["offset"].ToString()); var host = dict["host"].ToString(); state.completed += firstChunkBinary.Length; - if (state.completed % BLOCKSIZE == 0 || state.completed == totalSize) - { + if (state.completed % BLOCKSIZE == 0 || state.completed == totalSize) { state.block_ctxes.Add(ctx); } return UploadNextChunk(state, dataStream, ctx, offset, progress); }).Unwrap(); - } - else - { + } else { var chunkBinary = GetChunkBinary(state.completed, dataStream); - return PutChunk(state, chunkBinary, context, offset).ContinueWith(t => - { + return PutChunk(state, chunkBinary, context, offset).ContinueWith(t => { var dict = JsonConvert.DeserializeObject>(t.Result.Item2, new LeanCloudJsonConverter()); var ctx = dict["ctx"].ToString(); offset = long.Parse(dict["offset"].ToString()); var host = dict["host"].ToString(); state.completed += chunkBinary.Length; - if (state.completed % BLOCKSIZE == 0 || state.completed == totalSize) - { + if (state.completed % BLOCKSIZE == 0 || state.completed == totalSize) { state.block_ctxes.Add(ctx); } //if (AVClient.fileUploaderDebugLog) @@ -119,11 +90,9 @@ namespace LeanCloud.Storage.Internal } } - byte[] GetChunkBinary(long completed, Stream dataStream) - { + byte[] GetChunkBinary(long completed, Stream dataStream) { long chunkSize = (long)CommonSize.MB1; - if (completed + chunkSize > dataStream.Length) - { + if (completed + chunkSize > dataStream.Length) { chunkSize = dataStream.Length - completed; } byte[] chunkBinary = new byte[chunkSize]; @@ -132,16 +101,13 @@ namespace LeanCloud.Storage.Internal return chunkBinary; } - internal string GetUniqueName(FileState state) - { + internal string GetUniqueName(FileState state) { string key = Guid.NewGuid().ToString();//file Key in Qiniu. string extension = Path.GetExtension(state.Name); key += extension; return key; } - internal Task>> GetQiniuToken(FileState state, CancellationToken cancellationToken) - { - Task>> rtn; + internal Task>> GetQiniuToken(FileState state, CancellationToken cancellationToken) { string currentSessionToken = AVUser.CurrentSessionToken; string str = state.Name; @@ -162,8 +128,7 @@ namespace LeanCloud.Storage.Internal }; return AVPlugins.Instance.CommandRunner.RunCommandAsync>(command); } - IList> GetQiniuRequestHeaders(FileState state) - { + IList> GetQiniuRequestHeaders(FileState state) { IList> makeBlockHeaders = new List>(); string authHead = "UpToken " + state.token; @@ -212,19 +177,16 @@ namespace LeanCloud.Storage.Internal return await JsonUtils.DeserializeObjectAsync>(content); } - internal async Task> QiniuMakeFile(FileState state, Stream dataStream, string upToken, string key, long fsize, string[] ctxes, CancellationToken cancellationToken) - { + internal async Task> QiniuMakeFile(FileState state, Stream dataStream, string upToken, string key, long fsize, string[] ctxes, CancellationToken cancellationToken) { StringBuilder urlBuilder = new StringBuilder(); urlBuilder.AppendFormat("{0}/mkfile/{1}", UP_HOST, fsize); - if (key != null) - { + if (key != null) { urlBuilder.AppendFormat("/key/{0}", ToBase64URLSafe(key)); } var metaData = GetMetaData(state, dataStream); StringBuilder sb = new StringBuilder(); - foreach (string _key in metaData.Keys) - { + foreach (string _key in metaData.Keys) { sb.AppendFormat("/{0}/{1}", _key, ToBase64URLSafe(metaData[_key].ToString())); } urlBuilder.Append(sb.ToString()); @@ -238,12 +200,10 @@ namespace LeanCloud.Storage.Internal int proCount = ctxes.Length; Stream body = new MemoryStream(); - for (int i = 0; i < proCount; i++) - { + for (int i = 0; i < proCount; i++) { byte[] bctx = StringToAscii(ctxes[i]); body.Write(bctx, 0, bctx.Length); - if (i != proCount - 1) - { + if (i != proCount - 1) { body.WriteByte((byte)','); } } @@ -263,10 +223,8 @@ namespace LeanCloud.Storage.Internal return await JsonUtils.DeserializeObjectAsync>(content); } - internal void MergeFromJSON(FileState state, IDictionary jsonData) - { - lock (this.mutex) - { + internal void MergeFromJSON(FileState state, IDictionary jsonData) { + lock (this.mutex) { string url = jsonData["url"] as string; state.Url = new Uri(url, UriKind.Absolute); state.bucketId = FetchBucketId(url); @@ -276,17 +234,14 @@ namespace LeanCloud.Storage.Internal } } - string FetchBucketId(string url) - { + string FetchBucketId(string url) { var elements = url.Split('/'); return elements[elements.Length - 1]; } - public static byte[] StringToAscii(string s) - { + public static byte[] StringToAscii(string s) { byte[] retval = new byte[s.Length]; - for (int ix = 0; ix < s.Length; ++ix) - { + for (int ix = 0; ix < s.Length; ++ix) { char ch = s[ix]; if (ch <= 0x7f) retval[ix] = (byte)ch; @@ -295,20 +250,17 @@ namespace LeanCloud.Storage.Internal } return retval; } - public static string ToBase64URLSafe(string str) - { + public static string ToBase64URLSafe(string str) { return Encode(str); } - public static string Encode(byte[] bs) - { + public static string Encode(byte[] bs) { if (bs == null || bs.Length == 0) return ""; string encodedStr = Convert.ToBase64String(bs); encodedStr = encodedStr.Replace('+', '-').Replace('/', '_'); return encodedStr; } - public static string Encode(string text) - { + public static string Encode(string text) { if (String.IsNullOrEmpty(text)) return ""; byte[] bs = Encoding.UTF8.GetBytes(text); @@ -317,28 +269,23 @@ namespace LeanCloud.Storage.Internal return encodedStr; } - internal static string GetMD5Code(Stream data) - { + internal static string GetMD5Code(Stream data) { MD5 md5 = new MD5CryptoServiceProvider(); byte[] retVal = md5.ComputeHash(data); StringBuilder sb = new StringBuilder(); - for (int i = 0; i < retVal.Length; i++) - { + for (int i = 0; i < retVal.Length; i++) { sb.Append(retVal[i].ToString("x2")); } return sb.ToString(); } - internal IDictionary GetMetaData(FileState state, Stream data) - { + internal IDictionary GetMetaData(FileState state, Stream data) { IDictionary rtn = new Dictionary(); - if (state.MetaData != null) - { - foreach (var meta in state.MetaData) - { + if (state.MetaData != null) { + foreach (var meta in state.MetaData) { rtn.Add(meta.Key, meta.Value); } } @@ -351,14 +298,10 @@ namespace LeanCloud.Storage.Internal return rtn; } - internal void MergeDic(IDictionary dic, string key, object value) - { - if (dic.ContainsKey(key)) - { + internal void MergeDic(IDictionary dic, string key, object value) { + if (dic.ContainsKey(key)) { dic[key] = value; - } - else - { + } else { dic.Add(key, value); } } diff --git a/Storage/Storage/Internal/Object/Subclassing/ObjectSubclassingController.cs b/Storage/Storage/Internal/Object/Subclassing/ObjectSubclassingController.cs index 4c9fdd5..b31f88a 100644 --- a/Storage/Storage/Internal/Object/Subclassing/ObjectSubclassingController.cs +++ b/Storage/Storage/Internal/Object/Subclassing/ObjectSubclassingController.cs @@ -97,9 +97,7 @@ namespace LeanCloud.Storage.Internal { registerActions.TryGetValue(className, out toPerform); mutex.ExitReadLock(); - if (toPerform != null) { - toPerform(); - } + toPerform?.Invoke(); } public void UnregisterSubclass(Type type) { diff --git a/Storage/Storage/Internal/Session/Controller/AVSessionController.cs b/Storage/Storage/Internal/Session/Controller/AVSessionController.cs deleted file mode 100644 index 60957f0..0000000 --- a/Storage/Storage/Internal/Session/Controller/AVSessionController.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using System.Net.Http; - -namespace LeanCloud.Storage.Internal { - public class AVSessionController { - public Task GetSessionAsync(string sessionToken, CancellationToken cancellationToken) { - var command = new AVCommand { - Path = "sessions/me", - Method = HttpMethod.Get - }; - return AVPlugins.Instance.CommandRunner.RunCommandAsync>(command, cancellationToken: cancellationToken).OnSuccess(t => { - return AVObjectCoder.Instance.Decode(t.Result.Item2, AVDecoder.Instance); - }); - } - - public Task RevokeAsync(string sessionToken, CancellationToken cancellationToken) { - var command = new AVCommand { - Path = "logout", - Method = HttpMethod.Post - }; - return AVPlugins.Instance.CommandRunner.RunCommandAsync>(command, cancellationToken: cancellationToken); - } - - public Task UpgradeToRevocableSessionAsync(string sessionToken, CancellationToken cancellationToken) { - var command = new AVCommand { - Path = "upgradeToRevocableSession", - Method = HttpMethod.Post, - }; - return AVPlugins.Instance.CommandRunner.RunCommandAsync>(command, cancellationToken: cancellationToken).OnSuccess(t => { - return AVObjectCoder.Instance.Decode(t.Result.Item2, AVDecoder.Instance); - }); - } - - public bool IsRevocableSessionToken(string sessionToken) { - return sessionToken.Contains("r:"); - } - } -} diff --git a/Storage/Storage/Internal/Utilities/AVSessionExtensions.cs b/Storage/Storage/Internal/Utilities/AVSessionExtensions.cs deleted file mode 100644 index 40a3c3d..0000000 --- a/Storage/Storage/Internal/Utilities/AVSessionExtensions.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; - -namespace LeanCloud.Storage.Internal { - /// - /// So here's the deal. We have a lot of internal APIs for AVObject, AVUser, etc. - /// - /// These cannot be 'internal' anymore if we are fully modularizing things out, because - /// they are no longer a part of the same library, especially as we create things like - /// Installation inside push library. - /// - /// So this class contains a bunch of extension methods that can live inside another - /// namespace, which 'wrap' the intenral APIs that already exist. - /// - public static class AVSessionExtensions { - public static Task UpgradeToRevocableSessionAsync(string sessionToken, CancellationToken cancellationToken) { - return AVSession.UpgradeToRevocableSessionAsync(sessionToken, cancellationToken); - } - - public static Task RevokeAsync(string sessionToken, CancellationToken cancellationToken) { - return AVSession.RevokeAsync(sessionToken, cancellationToken); - } - } -} diff --git a/Storage/Storage/Public/AVClient.cs b/Storage/Storage/Public/AVClient.cs index 9dbed61..a2e07a5 100644 --- a/Storage/Storage/Public/AVClient.cs +++ b/Storage/Storage/Public/AVClient.cs @@ -251,7 +251,6 @@ namespace LeanCloud { AVObject.RegisterSubclass(); AVObject.RegisterSubclass(); - AVObject.RegisterSubclass(); } internal static void Config(Configuration configuration) { diff --git a/Storage/Storage/Public/AVCloud.cs b/Storage/Storage/Public/AVCloud.cs index f5f7fc8..9dddf7d 100644 --- a/Storage/Storage/Public/AVCloud.cs +++ b/Storage/Storage/Public/AVCloud.cs @@ -350,129 +350,4 @@ namespace LeanCloud { } } - - - /// - /// AVRPCC loud function base. - /// - public class AVRPCCloudFunctionBase { - /// - /// AVRPCD eserialize. - /// - public delegate R AVRPCDeserialize(IDictionary result); - /// - /// AVRPCS erialize. - /// - public delegate IDictionary AVRPCSerialize

(P parameters); - - public AVRPCCloudFunctionBase() - : this(true) { - - } - - public AVRPCCloudFunctionBase(bool noneParameters) { - if (noneParameters) { - this.Encode = n => { - return null; - }; - } - } - - - - private AVRPCDeserialize _decode; - public AVRPCDeserialize Decode { - get { - return _decode; - } - set { - _decode = value; - } - } - - - private AVRPCSerialize

_encode; - public AVRPCSerialize

Encode { - get { - if (_encode == null) { - _encode = n => { - if (n != null) { - return JsonConvert.DeserializeObject>(n.ToString(), new LeanCloudJsonConverter()); - } - return null; - }; - } - return _encode; - } - set { - _encode = value; - } - - } - public string FunctionName { get; set; } - - public Task ExecuteAsync(P parameters) { - var encodedParameters = Encode(parameters); - var command = new EngineCommand { - Path = $"call/{Uri.EscapeUriString(FunctionName)}", - Method = HttpMethod.Post, - Content = encodedParameters - }; - return AVPlugins.Instance.CommandRunner.RunCommandAsync>(command).OnSuccess(s => { - var responseBody = s.Result.Item2; - if (!responseBody.ContainsKey("result")) { - return default(R); - } - - return Decode(responseBody); - }); - } - } - - - public class AVObjectRPCCloudFunction : AVObjectRPCCloudFunction { - - } - public class AVObjectListRPCCloudFunction : AVObjectListRPCCloudFunction { - - } - - public class AVObjectListRPCCloudFunction : AVRPCCloudFunctionBase> where R : AVObject { - public AVObjectListRPCCloudFunction() - : base(true) { - this.Decode = this.AVObjectListDeserializer(); - } - - public AVRPCDeserialize> AVObjectListDeserializer() { - AVRPCDeserialize> del = data => { - var items = data["result"] as IList; - - return items.Select(item => { - var state = AVObjectCoder.Instance.Decode(item as IDictionary, AVDecoder.Instance); - return AVObject.FromState(state, state.ClassName); - }).ToList() as IList; - - }; - return del; - } - } - - public class AVObjectRPCCloudFunction : AVRPCCloudFunctionBase where R : AVObject { - public AVObjectRPCCloudFunction() - : base(true) { - this.Decode = this.AVObjectDeserializer(); - } - - - public AVRPCDeserialize AVObjectDeserializer() { - AVRPCDeserialize del = data => { - var item = data["result"] as object; - var state = AVObjectCoder.Instance.Decode(item as IDictionary, AVDecoder.Instance); - - return AVObject.FromState(state, state.ClassName); - }; - return del; - - } - } } diff --git a/Storage/Storage/Public/AVSession.cs b/Storage/Storage/Public/AVSession.cs deleted file mode 100644 index 9da3ea5..0000000 --- a/Storage/Storage/Public/AVSession.cs +++ /dev/null @@ -1,106 +0,0 @@ -using LeanCloud.Storage.Internal; -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; - -namespace LeanCloud -{ - /// - /// Represents a session of a user for a LeanCloud application. - /// - [AVClassName("_Session")] - public class AVSession : AVObject - { - private static readonly HashSet readOnlyKeys = new HashSet { - "sessionToken", "createdWith", "restricted", "user", "expiresAt", "installationId" - }; - - protected override bool IsKeyMutable(string key) - { - return !readOnlyKeys.Contains(key); - } - - /// - /// Gets the session token for a user, if they are logged in. - /// - [AVFieldName("sessionToken")] - public string SessionToken - { - get { return GetProperty(null, "SessionToken"); } - } - - /// - /// Constructs a for AVSession. - /// - public static AVQuery Query - { - get - { - return new AVQuery(); - } - } - - internal static AVSessionController SessionController - { - get - { - return AVPlugins.Instance.SessionController; - } - } - - /// - /// Gets the current object related to the current user. - /// - public static Task GetCurrentSessionAsync() - { - return GetCurrentSessionAsync(CancellationToken.None); - } - - /// - /// Gets the current object related to the current user. - /// - /// The cancellation token - public static Task GetCurrentSessionAsync(CancellationToken cancellationToken) - { - AVUser user = AVUser.CurrentUser; - if (user == null) { - return Task.FromResult((AVSession)null); - } - - string sessionToken = user.SessionToken; - if (sessionToken == null) { - return Task.FromResult((AVSession)null); - } - - return SessionController.GetSessionAsync(sessionToken, cancellationToken).OnSuccess(t => - { - AVSession session = AVObject.FromState(t.Result, "_Session"); - return session; - }); - } - - internal static Task RevokeAsync(string sessionToken, CancellationToken cancellationToken) - { - if (sessionToken == null || !SessionController.IsRevocableSessionToken(sessionToken)) - { - return Task.FromResult(0); - } - return SessionController.RevokeAsync(sessionToken, cancellationToken); - } - - internal static Task UpgradeToRevocableSessionAsync(string sessionToken, CancellationToken cancellationToken) - { - if (sessionToken == null || SessionController.IsRevocableSessionToken(sessionToken)) - { - return Task.FromResult(sessionToken); - } - - return SessionController.UpgradeToRevocableSessionAsync(sessionToken, cancellationToken).OnSuccess(t => - { - AVSession session = AVObject.FromState(t.Result, "_Session"); - return session.SessionToken; - }); - } - } -} diff --git a/Storage/Storage/Public/AVUser.cs b/Storage/Storage/Public/AVUser.cs index 129e188..c16b94f 100644 --- a/Storage/Storage/Public/AVUser.cs +++ b/Storage/Storage/Public/AVUser.cs @@ -343,47 +343,12 @@ namespace LeanCloud { /// Typically, you should use , unless you are managing your own threading. /// public static void LogOut() { + CurrentUser = null; + // 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 void 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 void LogOutAsync(CancellationToken cancellationToken) { - CurrentUser = null; - } - - //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(); @@ -391,8 +356,8 @@ namespace LeanCloud { } public static AVUser CurrentUser { - // TODO 线程问题 - get; internal set; + get; + internal set; } /// @@ -404,27 +369,6 @@ namespace LeanCloud { } } - #region Legacy / Revocable Session Tokens - - private static readonly object isRevocableSessionEnabledMutex = new object(); - private static bool isRevocableSessionEnabled; - - internal static void DisableRevocableSession() { - lock (isRevocableSessionEnabledMutex) { - isRevocableSessionEnabled = false; - } - } - - internal static bool IsRevocableSessionEnabled { - get { - lock (isRevocableSessionEnabledMutex) { - return isRevocableSessionEnabled; - } - } - } - - #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. @@ -803,7 +747,7 @@ namespace LeanCloud { /// 注册时使用的手机号 /// public static Task RequestPasswordResetBySmsCode(string mobilePhoneNumber) { - return AVUser.RequestPasswordResetBySmsCode(mobilePhoneNumber, null, CancellationToken.None); + return RequestPasswordResetBySmsCode(mobilePhoneNumber, null, CancellationToken.None); } /// @@ -823,7 +767,7 @@ namespace LeanCloud { /// Validate token. /// public static Task RequestPasswordResetBySmsCode(string mobilePhoneNumber, string validateToken) { - return AVUser.RequestPasswordResetBySmsCode(mobilePhoneNumber, validateToken, CancellationToken.None); + return RequestPasswordResetBySmsCode(mobilePhoneNumber, validateToken, CancellationToken.None); } /// @@ -834,9 +778,7 @@ namespace LeanCloud { /// cancellationToken /// public static Task RequestPasswordResetBySmsCode(string mobilePhoneNumber, string validateToken, CancellationToken cancellationToken) { - string currentSessionToken = AVUser.CurrentSessionToken; - Dictionary strs = new Dictionary() - { + Dictionary strs = new Dictionary { { "mobilePhoneNumber", mobilePhoneNumber }, }; if (String.IsNullOrEmpty(validateToken)) { @@ -868,9 +810,7 @@ namespace LeanCloud { /// cancellationToken /// public static Task ResetPasswordBySmsCodeAsync(string newPassword, string smsCode, CancellationToken cancellationToken) { - string currentSessionToken = AVUser.CurrentSessionToken; - Dictionary strs = new Dictionary() - { + Dictionary strs = new Dictionary { { "password", newPassword } }; var command = new AVCommand { @@ -918,7 +858,6 @@ namespace LeanCloud { /// CancellationToken /// public static Task RequestMobilePhoneVerifyAsync(string mobilePhoneNumber, string validateToken, CancellationToken cancellationToken) { - string currentSessionToken = AVUser.CurrentSessionToken; Dictionary strs = new Dictionary { { "mobilePhoneNumber", mobilePhoneNumber } };