From 0af4e8c9e788a3bbf4d6879a7f42660cb47ddedb Mon Sep 17 00:00:00 2001 From: crupest Date: Thu, 12 Nov 2020 18:31:41 +0800 Subject: feat: Add user permission service. TODO: Add unit tests. --- BackEnd/Timeline/Services/UserPermissionService.cs | 213 +++++++++++++++++++++ 1 file changed, 213 insertions(+) create mode 100644 BackEnd/Timeline/Services/UserPermissionService.cs (limited to 'BackEnd/Timeline/Services/UserPermissionService.cs') diff --git a/BackEnd/Timeline/Services/UserPermissionService.cs b/BackEnd/Timeline/Services/UserPermissionService.cs new file mode 100644 index 00000000..466ee252 --- /dev/null +++ b/BackEnd/Timeline/Services/UserPermissionService.cs @@ -0,0 +1,213 @@ +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Timeline.Entities; +using Timeline.Services.Exceptions; + +namespace Timeline.Services +{ + public enum UserPermission + { + /// + /// This permission allows to manage user (creating, deleting or modifying). + /// + UserManagement, + /// + /// This permission allows to view and modify all timelines. + /// + AllTimelineManagement, + /// + /// This permission allow to add or remove highlight timelines. + /// + HighlightTimelineManangement + } + + /// + /// Represents a user's permissions. + /// + public class UserPermissions : IEnumerable + { + public static UserPermissions AllPermissions { get; } = new UserPermissions(Enum.GetValues()); + + /// + /// Create an instance containing given permissions. + /// + /// Permission list. + public UserPermissions(params UserPermission[] permissions) : this(permissions as IEnumerable) + { + + } + + /// + /// Create an instance containing given permissions. + /// + /// Permission list. + /// Thrown when is null. + public UserPermissions(IEnumerable permissions) + { + if (permissions == null) throw new ArgumentNullException(nameof(permissions)); + _permissions = new HashSet(permissions); + } + + private readonly HashSet _permissions = new(); + + /// + /// Check if a permission is contained in the list. + /// + /// The permission to check. + /// True if contains. Otherwise false. + public bool Contains(UserPermission permission) + { + return _permissions.Contains(permission); + } + + /// + /// To a serializable string list. + /// + /// A string list. + public List ToStringList() + { + return _permissions.Select(p => p.ToString().ToUpperInvariant()).ToList(); + } + + /// + /// Convert a string list to user permissions. + /// + /// The string list. + /// An instance. + /// Thrown when is null. + /// Thrown when there is unknown permission name. + public static UserPermissions FromStringList(IEnumerable list) + { + List permissions = new(); + + foreach (var value in list) + { + if (Enum.TryParse(value, false, out var result)) + { + permissions.Add(result); + } + else + { + throw new ArgumentException("Unknown permission name.", nameof(list)); + } + } + + return new UserPermissions(permissions); + } + + public IEnumerator GetEnumerator() + { + return _permissions.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return ((IEnumerable)_permissions).GetEnumerator(); + } + } + + public interface IUserPermissionService + { + /// + /// Get permissions of a user. + /// + /// The id of the user. + /// Whether check the user's existence. + /// The permission list. + /// Thrown when is true and user does not exist. + Task GetPermissionsOfUserAsync(long userId, bool checkUserExistence = true); + + /// + /// Add a permission to user. + /// + /// The id of the user. + /// The new permission. + /// Whether check the user's existence. + /// Thrown when is true and user does not exist. + Task AddPermissionToUserAsync(long userId, UserPermission permission, bool checkUserExistence = true); + + /// + /// Remove a permission from user. + /// + /// The id of the user. + /// The permission. + /// Whether check the user's existence. + /// Thrown when is true and user does not exist. + Task RemovePermissionFromUserAsync(long userId, UserPermission permission, bool checkUserExistence = true); + } + + public class UserPermissionService : IUserPermissionService + { + private readonly DatabaseContext _database; + + public UserPermissionService(DatabaseContext database) + { + _database = database; + } + + private async Task CheckUserExistence(long userId, bool checkUserExistence) + { + if (checkUserExistence) + { + var existence = await _database.Users.AnyAsync(u => u.Id == userId); + if (!existence) + { + throw new UserNotExistException(userId); + } + } + } + + public async Task GetPermissionsOfUserAsync(long userId, bool checkUserExistence = true) + { + if (userId == 1) // The init administrator account. + { + return UserPermissions.AllPermissions; + } + + await CheckUserExistence(userId, checkUserExistence); + + var permissionNameList = await _database.UserPermission.Where(e => e.UserId == userId).Select(e => e.Permission).ToListAsync(); + + return UserPermissions.FromStringList(permissionNameList); + } + + public async Task AddPermissionToUserAsync(long userId, UserPermission permission, bool checkUserExistence) + { + if (userId == 1) // The init administrator account. + return; + + await CheckUserExistence(userId, checkUserExistence); + + var alreadyHas = await _database.UserPermission + .AnyAsync(e => e.UserId == userId && e.Permission.Equals(permission.ToString(), StringComparison.InvariantCultureIgnoreCase)); + + if (alreadyHas) return; + + _database.UserPermission.Add(new UserPermissionEntity { UserId = userId, Permission = permission.ToString() }); + + await _database.SaveChangesAsync(); + } + + public async Task RemovePermissionFromUserAsync(long userId, UserPermission permission, bool checkUserExistence) + { + if (userId == 1) // The init administrator account. + return; + + await CheckUserExistence(userId, checkUserExistence); + + var entity = await _database.UserPermission + .Where(e => e.UserId == userId && e.Permission.Equals(permission.ToString(), StringComparison.InvariantCultureIgnoreCase)) + .SingleOrDefaultAsync(); + + if (entity == null) return; + + _database.UserPermission.Remove(entity); + + await _database.SaveChangesAsync(); + } + } +} -- cgit v1.2.3