Skip to content

Commit

Permalink
Merge pull request #72 from onerain88/chore
Browse files Browse the repository at this point in the history
Chore
  • Loading branch information
onerain88 authored May 28, 2020
2 parents 3e8e6b5 + 4f7d3f8 commit 2939203
Show file tree
Hide file tree
Showing 16 changed files with 150 additions and 70 deletions.
3 changes: 3 additions & 0 deletions Common/Common-Unity/Common-Unity.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@
<Compile Include="..\Common\Json\LCJsonConverter.cs">
<Link>Json\LCJsonConverter.cs</Link>
</Compile>
<Compile Include="..\Common\Exception\LCException.cs">
<Link>Exception\LCException.cs</Link>
</Compile>
</ItemGroup>
<ItemGroup>
<Reference Include="Newtonsoft.Json">
Expand Down
1 change: 1 addition & 0 deletions Common/Common/Common.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@
<Folder Include="Log\" />
<Folder Include="Http\" />
<Folder Include="Task\" />
<Folder Include="Exception\" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
using System;

namespace LeanCloud.Storage {
namespace LeanCloud {
/// <summary>
/// LeanCloud 异常
/// </summary>
public class LCException : Exception {
/// <summary>
/// 错误码
/// </summary>
public int Code {
get; set;
}

/// <summary>
/// 错误信息
/// </summary>
public new string Message {
get; set;
}
Expand All @@ -14,5 +23,9 @@ public LCException(int code, string message) {
Code = code;
Message = message;
}

public override string ToString() {
return $"{Code} - {Message}";
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ internal async Task<LCIMConversation> CreateConv(
attrs["name"] = name;
}
if (properties != null) {
attrs = properties.Union(attrs)
attrs = properties.Union(attrs.Where(kv => !properties.ContainsKey(kv.Key)))
.ToDictionary(k => k.Key, v => v.Value);
}
conv.Attr = new JsonObjectMessage {
Expand Down
3 changes: 0 additions & 3 deletions Storage/Storage-Unity/Storage-Unity.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,6 @@
<Compile Include="..\Storage\LCCloud.cs">
<Link>LCCloud.cs</Link>
</Compile>
<Compile Include="..\Storage\LCException.cs">
<Link>LCException.cs</Link>
</Compile>
<Compile Include="..\Storage\LCFile.cs">
<Link>LCFile.cs</Link>
</Compile>
Expand Down
15 changes: 15 additions & 0 deletions Storage/Storage.Test/ACLTest.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using NUnit.Framework;
using System.Threading.Tasks;
using System.Collections.ObjectModel;
using LeanCloud;
using LeanCloud.Storage;

Expand Down Expand Up @@ -74,5 +75,19 @@ public async Task Query() {
TestContext.WriteLine(account.ObjectId);
Assert.NotNull(account.ObjectId);
}

[Test]
public async Task Serialization() {
await LCUser.Login("hello", "world");
LCQuery<LCObject> query = new LCQuery<LCObject>("Account") {
IncludeACL = true
};
query.OrderByDescending("createdAt");
ReadOnlyCollection<LCObject> accounts = await query.Find();
foreach (LCObject account in accounts) {
TestContext.WriteLine($"public read access: {account.ACL.PublicReadAccess}");
TestContext.WriteLine($"public write access: {account.ACL.PublicWriteAccess}");
}
}
}
}
2 changes: 1 addition & 1 deletion Storage/Storage.Test/ExceptionTest.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using NUnit.Framework;
using LeanCloud.Storage;
using LeanCloud;

namespace Storage.Test {
public class ExceptionTest {
Expand Down
19 changes: 17 additions & 2 deletions Storage/Storage/Internal/Codec/LCDecoder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,25 @@ public static LCRelation<LCObject> DecodeRelation(IDictionary dict) {
}

public static LCGeoPoint DecodeGeoPoint(IDictionary data) {
double latitude = double.Parse(data["latitude"].ToString());
double longitude = double.Parse(data["longitude"].ToString());
double latitude = Convert.ToDouble(data["latitude"]);
double longitude = Convert.ToDouble(data["longitude"]);
LCGeoPoint geoPoint = new LCGeoPoint(latitude, longitude);
return geoPoint;
}

public static LCACL DecodeACL(Dictionary<string, object> dict) {
LCACL acl = new LCACL();
foreach (KeyValuePair<string, object> kv in dict) {
string key = kv.Key;
Dictionary<string, object> access = kv.Value as Dictionary<string, object>;
if (access.TryGetValue("read", out object ra)) {
acl.readAccess[key] = Convert.ToBoolean(ra);
}
if (access.TryGetValue("write", out object wa)) {
acl.writeAccess[key] = Convert.ToBoolean(wa);
}
}
return acl;
}
}
}
29 changes: 18 additions & 11 deletions Storage/Storage/Internal/Codec/LCEncoder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,18 +83,25 @@ public static object EncodeQueryCondition(ILCQueryCondition cond) {
}

public static object EncodeACL(LCACL acl) {
HashSet<string> readers = acl.readers;
HashSet<string> writers = acl.writers;
HashSet<string> union = new HashSet<string>(readers);
union.UnionWith(writers);
Dictionary<string, object> dict = new Dictionary<string, object>();
foreach (string k in union) {
dict[k] = new Dictionary<string, object> {
{ "read", readers.Contains(k) },
{ "write", writers.Contains(k) }
};
HashSet<string> keys = new HashSet<string>();
if (acl.readAccess.Count > 0) {
keys.UnionWith(acl.readAccess.Keys);
}
return dict;
if (acl.writeAccess.Count > 0) {
keys.UnionWith(acl.writeAccess.Keys);
}
Dictionary<string, object> result = new Dictionary<string, object>();
foreach (string key in keys) {
Dictionary<string, bool> access = new Dictionary<string, bool>();
if (acl.readAccess.TryGetValue(key, out bool ra)) {
access["read"] = ra;
}
if (acl.writeAccess.TryGetValue(key, out bool wa)) {
access["write"] = wa;
}
result[key] = access;
}
return result;
}

public static object EncodeRelation(LCRelation<LCObject> relation) {
Expand Down
15 changes: 10 additions & 5 deletions Storage/Storage/Internal/Object/LCObjectData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,16 @@ public static LCObjectData Decode(IDictionary dict) {
} else if (key == "objectId") {
objectData.ObjectId = value.ToString();
} else if (key == "createdAt" && DateTime.TryParse(value.ToString(), out DateTime createdAt)) {
objectData.CreatedAt = createdAt;
objectData.CreatedAt = createdAt.ToLocalTime();
} else if (key == "updatedAt" && DateTime.TryParse(value.ToString(), out DateTime updatedAt)) {
objectData.UpdatedAt = updatedAt;
objectData.UpdatedAt = updatedAt.ToLocalTime();
} else {
objectData.CustomPropertyDict[key] = LCDecoder.Decode(value);
if (key == "ACL" &&
value is Dictionary<string, object> dic) {
objectData.CustomPropertyDict[key] = LCDecoder.DecodeACL(dic);
} else {
objectData.CustomPropertyDict[key] = LCDecoder.Decode(value);
}
}
}
return objectData;
Expand All @@ -61,10 +66,10 @@ public static Dictionary<string, object> Encode(LCObjectData objectData) {
dict["objectId"] = objectData.ObjectId;
}
if (objectData.CreatedAt != null) {
dict["createdAt"] = objectData.CreatedAt;
dict["createdAt"] = objectData.CreatedAt.ToUniversalTime();
}
if (objectData.UpdatedAt != null) {
dict["updatedAt"] = objectData.UpdatedAt;
dict["updatedAt"] = objectData.UpdatedAt.ToUniversalTime();
}
if (objectData.CustomPropertyDict != null) {
foreach (KeyValuePair<string, object> kv in objectData.CustomPropertyDict) {
Expand Down
7 changes: 7 additions & 0 deletions Storage/Storage/Internal/Query/LCCompositionalCondition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ public int Limit {
get; set;
}

public bool IncludeACL {
get; set;
}

public LCCompositionalCondition(string composition = And) {
this.composition = composition;
Skip = 0;
Expand Down Expand Up @@ -217,6 +221,9 @@ public Dictionary<string, object> BuildParams() {
if (selectedKeys != null && selectedKeys.Count > 0) {
dict["keys"] = string.Join(",", selectedKeys);
}
if (IncludeACL) {
dict["returnACL"] = "true";
}
return dict;
}

Expand Down
66 changes: 29 additions & 37 deletions Storage/Storage/LCACL.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,51 +10,61 @@ public class LCACL {

const string RoleKeyPrefix = "role:";

internal HashSet<string> readers;
internal HashSet<string> writers;
internal Dictionary<string, bool> readAccess = new Dictionary<string, bool>();
internal Dictionary<string, bool> writeAccess = new Dictionary<string, bool>();

public static LCACL CreateWithOwner(LCUser owner) {
if (owner == null) {
throw new ArgumentNullException(nameof(owner));
}
LCACL acl = new LCACL();
acl.SetUserReadAccess(owner, true);
acl.SetUserWriteAccess(owner, true);
return acl;
}

public bool PublicReadAccess {
get {
return GetAccess(readers, PublicKey);
return GetAccess(readAccess, PublicKey);
} set {
SetAccess(readers, PublicKey, value);
SetAccess(readAccess, PublicKey, value);
}
}

public bool PublicWriteAccess {
get {
return GetAccess(writers, PublicKey);
return GetAccess(writeAccess, PublicKey);
} set {
SetAccess(writers, PublicKey, value);
SetAccess(writeAccess, PublicKey, value);
}
}

public bool GetUserIdReadAccess(string userId) {
if (string.IsNullOrEmpty(userId)) {
throw new ArgumentNullException(nameof(userId));
}
return GetAccess(readers, userId);
return GetAccess(readAccess, userId);
}

public void SetUserIdReadAccess(string userId, bool value) {
if (string.IsNullOrEmpty(userId)) {
throw new ArgumentNullException(nameof(userId));
}
SetAccess(readers, userId, value);
SetAccess(readAccess, userId, value);
}

public bool GetUserIdWriteAccess(string userId) {
if (string.IsNullOrEmpty(userId)) {
throw new ArgumentNullException(nameof(userId));
}
return GetAccess(writers, userId);
return GetAccess(writeAccess, userId);
}

public void SetUserIdWriteAccess(string userId, bool value) {
if (string.IsNullOrEmpty(userId)) {
throw new ArgumentNullException(nameof(userId));
}
SetAccess(writers, userId, value);
SetAccess(writeAccess, userId, value);
}

public bool GetUserReadAccess(LCUser user) {
Expand Down Expand Up @@ -90,58 +100,40 @@ public bool GetRoleReadAccess(LCRole role) {
throw new ArgumentNullException(nameof(role));
}
string roleKey = $"{RoleKeyPrefix}{role.ObjectId}";
return GetAccess(readers, roleKey);
return GetAccess(readAccess, roleKey);
}

public void SetRoleReadAccess(LCRole role, bool value) {
if (role == null) {
throw new ArgumentNullException(nameof(role));
}
string roleKey = $"{RoleKeyPrefix}{role.ObjectId}";
SetAccess(readers, roleKey, value);
SetAccess(readAccess, roleKey, value);
}

public bool GetRoleWriteAccess(LCRole role) {
if (role == null) {
throw new ArgumentNullException(nameof(role));
}
string roleKey = $"{RoleKeyPrefix}{role.ObjectId}";
return GetAccess(writers, roleKey);
return GetAccess(writeAccess, roleKey);
}

public void SetRoleWriteAccess(LCRole role, bool value) {
if (role == null) {
throw new ArgumentNullException(nameof(role));
}
string roleKey = $"{RoleKeyPrefix}{role.ObjectId}";
SetAccess(writers, roleKey, value);
SetAccess(writeAccess, roleKey, value);
}

public LCACL() {
readers = new HashSet<string>();
writers = new HashSet<string>();
bool GetAccess(Dictionary<string, bool> access, string key) {
return access.ContainsKey(key) ?
access[key] : false;
}

public static LCACL CreateWithOwner(LCUser owner) {
if (owner == null) {
throw new ArgumentNullException(nameof(owner));
}
LCACL acl = new LCACL();
acl.SetUserReadAccess(owner, true);
acl.SetUserWriteAccess(owner, true);
return acl;
}

bool GetAccess(HashSet<string> set, string key) {
return set.Contains(key);
}

void SetAccess(HashSet<string> set, string key, bool value) {
if (value) {
set.Add(key);
} else {
set.Remove(key);
}
void SetAccess(Dictionary<string, bool> access, string key, bool value) {
access[key] = value;
}
}
}
23 changes: 17 additions & 6 deletions Storage/Storage/LCCloud.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,31 @@ namespace LeanCloud.Storage {
/// </summary>
public static class LCCloud {
/// <summary>
/// 调用云函数,结果为 Dictionary 类型
/// 调用云函数
/// </summary>
/// <param name="name"></param>
/// <param name="parameters"></param>
/// <returns></returns>
public static async Task<Dictionary<string, object>> Run(string name, Dictionary<string, object> parameters = null) {
/// <returns>返回类型为 Dictionary<string, object></returns>
public static async Task<Dictionary<string, object>> Run(string name,
Dictionary<string, object> parameters = null) {
string path = $"functions/{name}";
Dictionary<string, object> response = await LCApplication.HttpClient.Post<Dictionary<string, object>>(path, data: parameters);
object encodeParams = LCEncoder.Encode(parameters);
Dictionary<string, object> response = await LCApplication.HttpClient.Post<Dictionary<string, object>>(path,
data: encodeParams);
return response;
}

public static async Task<object> RPC(string name, Dictionary<string, object> parameters = null) {
/// <summary>
/// 调用 RPC 云函数
/// </summary>
/// <param name="name"></param>
/// <param name="parameters"></param>
/// <returns>返回类型为 LCObject 容器类型</returns>
public static async Task<object> RPC(string name, object parameters = null) {
string path = $"call/{name}";
Dictionary<string, object> response = await LCApplication.HttpClient.Post<Dictionary<string, object>>(path, data: parameters);
object encodeParams = LCEncoder.Encode(parameters);
Dictionary<string, object> response = await LCApplication.HttpClient.Post<Dictionary<string, object>>(path,
data: encodeParams);
return LCDecoder.Decode(response["result"]);
}
}
Expand Down
Loading

0 comments on commit 2939203

Please sign in to comment.