csharp-sdk-upm/Storage/Source/Public/AVACL.cs

285 lines
11 KiB
C#
Raw Normal View History

2019-07-19 15:01:34 +08:00
using System;
using System.Collections.Generic;
using System.Linq;
using LeanCloud.Storage.Internal;
namespace LeanCloud {
/// <summary>
/// A AVACL is used to control which users and roles can access or modify a particular object. Each
/// <see cref="AVObject"/> can have its own AVACL. You can grant read and write permissions
/// separately to specific users, to groups of users that belong to roles, or you can grant permissions
/// to "the public" so that, for example, any user could read a particular object but only a particular
/// set of users could write to that object.
/// </summary>
public class AVACL : IJsonConvertible {
private enum AccessKind {
Read,
Write
}
private const string publicName = "*";
private readonly ICollection<string> readers = new HashSet<string>();
private readonly ICollection<string> writers = new HashSet<string>();
internal AVACL(IDictionary<string, object> jsonObject) {
readers = new HashSet<string>(from pair in jsonObject
where ((IDictionary<string, object>)pair.Value).ContainsKey("read")
select pair.Key);
writers = new HashSet<string>(from pair in jsonObject
where ((IDictionary<string, object>)pair.Value).ContainsKey("write")
select pair.Key);
}
/// <summary>
/// Creates an ACL with no permissions granted.
/// </summary>
public AVACL() {
}
/// <summary>
/// Creates an ACL where only the provided user has access.
/// </summary>
/// <param name="owner">The only user that can read or write objects governed by this ACL.</param>
public AVACL(AVUser owner) {
SetReadAccess(owner, true);
SetWriteAccess(owner, true);
}
IDictionary<string, object> IJsonConvertible.ToJSON() {
var result = new Dictionary<string, object>();
foreach (var user in readers.Union(writers)) {
var userPermissions = new Dictionary<string, object>();
if (readers.Contains(user)) {
userPermissions["read"] = true;
}
if (writers.Contains(user)) {
userPermissions["write"] = true;
}
result[user] = userPermissions;
}
return result;
}
private void SetAccess(AccessKind kind, string userId, bool allowed) {
if (userId == null) {
throw new ArgumentException("Cannot set access for an unsaved user or role.");
}
ICollection<string> target = null;
switch (kind) {
case AccessKind.Read:
target = readers;
break;
case AccessKind.Write:
target = writers;
break;
default:
throw new NotImplementedException("Unknown AccessKind");
}
if (allowed) {
target.Add(userId);
} else {
target.Remove(userId);
}
}
private bool GetAccess(AccessKind kind, string userId) {
if (userId == null) {
throw new ArgumentException("Cannot get access for an unsaved user or role.");
}
switch (kind) {
case AccessKind.Read:
return readers.Contains(userId);
case AccessKind.Write:
return writers.Contains(userId);
default:
throw new NotImplementedException("Unknown AccessKind");
}
}
/// <summary>
/// Gets or sets whether the public is allowed to read this object.
/// </summary>
public bool PublicReadAccess {
get {
return GetAccess(AccessKind.Read, publicName);
}
set {
SetAccess(AccessKind.Read, publicName, value);
}
}
/// <summary>
/// Gets or sets whether the public is allowed to write this object.
/// </summary>
public bool PublicWriteAccess {
get {
return GetAccess(AccessKind.Write, publicName);
}
set {
SetAccess(AccessKind.Write, publicName, value);
}
}
/// <summary>
/// Sets whether the given user id is allowed to read this object.
/// </summary>
/// <param name="userId">The objectId of the user.</param>
/// <param name="allowed">Whether the user has permission.</param>
public void SetReadAccess(string userId, bool allowed) {
SetAccess(AccessKind.Read, userId, allowed);
}
/// <summary>
/// Sets whether the given user is allowed to read this object.
/// </summary>
/// <param name="user">The user.</param>
/// <param name="allowed">Whether the user has permission.</param>
public void SetReadAccess(AVUser user, bool allowed) {
SetReadAccess(user.ObjectId, allowed);
}
/// <summary>
/// Sets whether the given user id is allowed to write this object.
/// </summary>
/// <param name="userId">The objectId of the user.</param>
/// <param name="allowed">Whether the user has permission.</param>
public void SetWriteAccess(string userId, bool allowed) {
SetAccess(AccessKind.Write, userId, allowed);
}
/// <summary>
/// Sets whether the given user is allowed to write this object.
/// </summary>
/// <param name="user">The user.</param>
/// <param name="allowed">Whether the user has permission.</param>
public void SetWriteAccess(AVUser user, bool allowed) {
SetWriteAccess(user.ObjectId, allowed);
}
/// <summary>
/// Gets whether the given user id is *explicitly* allowed to read this object.
/// Even if this returns false, the user may still be able to read it if
/// PublicReadAccess is true or a role that the user belongs to has read access.
/// </summary>
/// <param name="userId">The user objectId to check.</param>
/// <returns>Whether the user has access.</returns>
public bool GetReadAccess(string userId) {
return GetAccess(AccessKind.Read, userId);
}
/// <summary>
/// Gets whether the given user is *explicitly* allowed to read this object.
/// Even if this returns false, the user may still be able to read it if
/// PublicReadAccess is true or a role that the user belongs to has read access.
/// </summary>
/// <param name="user">The user to check.</param>
/// <returns>Whether the user has access.</returns>
public bool GetReadAccess(AVUser user) {
return GetReadAccess(user.ObjectId);
}
/// <summary>
/// Gets whether the given user id is *explicitly* allowed to write this object.
/// Even if this returns false, the user may still be able to write it if
/// PublicReadAccess is true or a role that the user belongs to has write access.
/// </summary>
/// <param name="userId">The user objectId to check.</param>
/// <returns>Whether the user has access.</returns>
public bool GetWriteAccess(string userId) {
return GetAccess(AccessKind.Write, userId);
}
/// <summary>
/// Gets whether the given user is *explicitly* allowed to write this object.
/// Even if this returns false, the user may still be able to write it if
/// PublicReadAccess is true or a role that the user belongs to has write access.
/// </summary>
/// <param name="user">The user to check.</param>
/// <returns>Whether the user has access.</returns>
public bool GetWriteAccess(AVUser user) {
return GetWriteAccess(user.ObjectId);
}
/// <summary>
/// Sets whether users belonging to the role with the given <paramref name="roleName"/>
/// are allowed to read this object.
/// </summary>
/// <param name="roleName">The name of the role.</param>
/// <param name="allowed">Whether the role has access.</param>
public void SetRoleReadAccess(string roleName, bool allowed) {
SetAccess(AccessKind.Read, "role:" + roleName, allowed);
}
/// <summary>
/// Sets whether users belonging to the given role are allowed to read this object.
/// </summary>
/// <param name="role">The role.</param>
/// <param name="allowed">Whether the role has access.</param>
public void SetRoleReadAccess(AVRole role, bool allowed) {
SetRoleReadAccess(role.Name, allowed);
}
/// <summary>
/// Gets whether users belonging to the role with the given <paramref name="roleName"/>
/// are allowed to read this object. Even if this returns false, the role may still be
/// able to read it if a parent role has read access.
/// </summary>
/// <param name="roleName">The name of the role.</param>
/// <returns>Whether the role has access.</returns>
public bool GetRoleReadAccess(string roleName) {
return GetAccess(AccessKind.Read, "role:" + roleName);
}
/// <summary>
/// Gets whether users belonging to the role are allowed to read this object.
/// Even if this returns false, the role may still be able to read it if a
/// parent role has read access.
/// </summary>
/// <param name="role">The name of the role.</param>
/// <returns>Whether the role has access.</returns>
public bool GetRoleReadAccess(AVRole role) {
return GetRoleReadAccess(role.Name);
}
/// <summary>
/// Sets whether users belonging to the role with the given <paramref name="roleName"/>
/// are allowed to write this object.
/// </summary>
/// <param name="roleName">The name of the role.</param>
/// <param name="allowed">Whether the role has access.</param>
public void SetRoleWriteAccess(string roleName, bool allowed) {
SetAccess(AccessKind.Write, "role:" + roleName, allowed);
}
/// <summary>
/// Sets whether users belonging to the given role are allowed to write this object.
/// </summary>
/// <param name="role">The role.</param>
/// <param name="allowed">Whether the role has access.</param>
public void SetRoleWriteAccess(AVRole role, bool allowed) {
SetRoleWriteAccess(role.Name, allowed);
}
/// <summary>
/// Gets whether users belonging to the role with the given <paramref name="roleName"/>
/// are allowed to write this object. Even if this returns false, the role may still be
/// able to write it if a parent role has write access.
/// </summary>
/// <param name="roleName">The name of the role.</param>
/// <returns>Whether the role has access.</returns>
public bool GetRoleWriteAccess(string roleName) {
return GetAccess(AccessKind.Write, "role:" + roleName);
}
/// <summary>
/// Gets whether users belonging to the role are allowed to write this object.
/// Even if this returns false, the role may still be able to write it if a
/// parent role has write access.
/// </summary>
/// <param name="role">The name of the role.</param>
/// <returns>Whether the role has access.</returns>
public bool GetRoleWriteAccess(AVRole role) {
return GetRoleWriteAccess(role.Name);
}
}
}