* ACLTest.cs:
* LCDecoder.cs: * LCEncoder.cs: * LCObjectData.cs: * LCACL.cs: chore: 调整 ACL 逻辑;支持 ACL 反序列化
parent
66e07a2041
commit
4647128888
|
@ -78,12 +78,15 @@ namespace Storage.Test {
|
|||
|
||||
[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(account);
|
||||
TestContext.WriteLine($"public read access: {account.ACL.PublicReadAccess}");
|
||||
TestContext.WriteLine($"public write access: {account.ACL.PublicWriteAccess}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,10 +68,26 @@ namespace LeanCloud.Storage.Internal.Codec {
|
|||
}
|
||||
|
||||
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) {
|
||||
Console.WriteLine($"count: {dict.Count}");
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -83,18 +83,25 @@ namespace LeanCloud.Storage.Internal.Codec {
|
|||
}
|
||||
|
||||
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) {
|
||||
|
|
|
@ -44,7 +44,12 @@ namespace LeanCloud.Storage.Internal.Object {
|
|||
} else if (key == "updatedAt" && DateTime.TryParse(value.ToString(), out DateTime 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;
|
||||
|
|
|
@ -10,22 +10,32 @@ namespace LeanCloud.Storage {
|
|||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -33,28 +43,28 @@ namespace LeanCloud.Storage {
|
|||
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) {
|
||||
|
@ -90,7 +100,7 @@ namespace LeanCloud.Storage {
|
|||
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) {
|
||||
|
@ -98,7 +108,7 @@ namespace LeanCloud.Storage {
|
|||
throw new ArgumentNullException(nameof(role));
|
||||
}
|
||||
string roleKey = $"{RoleKeyPrefix}{role.ObjectId}";
|
||||
SetAccess(readers, roleKey, value);
|
||||
SetAccess(readAccess, roleKey, value);
|
||||
}
|
||||
|
||||
public bool GetRoleWriteAccess(LCRole role) {
|
||||
|
@ -106,7 +116,7 @@ namespace LeanCloud.Storage {
|
|||
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) {
|
||||
|
@ -114,34 +124,16 @@ namespace LeanCloud.Storage {
|
|||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue