using Microsoft.EntityFrameworkCore; using System.Collections.Generic; using System.Linq; using Oqtane.Models; using System.Text; using System; using System.Text.Json; using System.Text.Json.Serialization; namespace Oqtane.Repository { public class PermissionRepository : IPermissionRepository { private TenantDBContext db; private readonly IRoleRepository Roles; public PermissionRepository(TenantDBContext context, IRoleRepository Roles) { db = context; this.Roles = Roles; } public IEnumerable GetPermissions(int SiteId, string EntityName) { try { return db.Permission.Where(item => item.SiteId == SiteId) .Where(item => item.EntityName == EntityName) .Include(item => item.Role); // eager load roles } catch { throw; } } public IEnumerable GetPermissions(string EntityName, int EntityId) { try { return db.Permission.Where(item => item.EntityName == EntityName) .Where(item => item.EntityId == EntityId) .Include(item => item.Role); // eager load roles } catch { throw; } } public IEnumerable GetPermissions(string EntityName, int EntityId, string PermissionName) { try { return db.Permission.Where(item => item.EntityName == EntityName) .Where(item => item.EntityId == EntityId) .Where(item => item.PermissionName == PermissionName) .Include(item => item.Role); // eager load roles } catch { throw; } } public Permission AddPermission(Permission Permission) { try { db.Permission.Add(Permission); db.SaveChanges(); return Permission; } catch { throw; } } public Permission UpdatePermission(Permission Permission) { try { db.Entry(Permission).State = EntityState.Modified; db.SaveChanges(); return Permission; } catch { throw; } } public void UpdatePermissions(int SiteId, string EntityName, int EntityId, string Permissions) { // get current permissions and delete List permissions = db.Permission.Where(item => item.EntityName == EntityName) .Where(item => item.EntityId == EntityId).ToList(); foreach(Permission permission in permissions) { db.Permission.Remove(permission); } // add permissions permissions = DecodePermissions(Permissions, SiteId, EntityName, EntityId); foreach (Permission permission in permissions) { db.Permission.Add(permission); } db.SaveChanges(); } public Permission GetPermission(int PermissionId) { try { return db.Permission.Find(PermissionId); } catch { throw; } } public void DeletePermission(int PermissionId) { try { Permission Permission = db.Permission.Find(PermissionId); db.Permission.Remove(Permission); db.SaveChanges(); } catch { throw; } } // permissions are stored in the format "{permissionname:!rolename1;![userid1];rolename2;rolename3;[userid2];[userid3]}" where "!" designates Deny permissions public string EncodePermissions(int EntityId, List Permissions) { List permissionstrings = new List(); string permissionname = ""; string permissions = ""; StringBuilder permissionsbuilder = new StringBuilder(); string securityid = ""; foreach (Permission permission in Permissions.Where(item => item.EntityId == EntityId).OrderBy(item => item.PermissionName)) { // permission collections are grouped by permissionname if (permissionname != permission.PermissionName) { permissions = permissionsbuilder.ToString(); if (permissions != "") { permissionstrings.Add(new PermissionString { PermissionName = permissionname, Permissions = permissions.Substring(0, permissions.Length - 1) }); } permissionname = permission.PermissionName; permissionsbuilder = new StringBuilder(); } // deny permissions are prefixed with a "!" string prefix = !permission.IsAuthorized ? "!" : ""; // encode permission if (permission.UserId == null) { securityid = prefix + permission.Role.Name + ";"; } else { securityid = prefix + "[" + permission.UserId.ToString() + "];"; } // insert deny permissions at the beginning and append grant permissions at the end if (prefix == "!") { permissionsbuilder.Insert(0, securityid); } else { permissionsbuilder.Append(securityid); } } permissions = permissionsbuilder.ToString(); if (permissions != "") { permissionstrings.Add(new PermissionString { PermissionName = permissionname, Permissions = permissions.Substring(0, permissions.Length - 1) }); } return JsonSerializer.Serialize(permissionstrings); } public List DecodePermissions(string PermissionStrings, int SiteId, string EntityName, int EntityId) { List permissions = new List(); List roles = Roles.GetRoles(SiteId).ToList(); string securityid = ""; foreach (PermissionString permissionstring in JsonSerializer.Deserialize>(PermissionStrings)) { foreach (string id in permissionstring.Permissions.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries)) { securityid = id; Permission permission = new Permission(); permission.SiteId = SiteId; permission.EntityName = EntityName; permission.EntityId = EntityId; permission.PermissionName = permissionstring.PermissionName; permission.RoleId = null; permission.UserId = null; permission.IsAuthorized = true; if (securityid.StartsWith("!")) { // deny permission securityid.Replace("!", ""); permission.IsAuthorized = false; } if (securityid.StartsWith("[") && securityid.EndsWith("]")) { // user id securityid = securityid.Replace("[", "").Replace("]", ""); permission.UserId = int.Parse(securityid); } else { // role name Role role = roles.Where(item => item.Name == securityid).SingleOrDefault(); if (role != null) { permission.RoleId = role.RoleId; } } if (permission.UserId != null || permission.RoleId != null) { permissions.Add(permission); } } } return permissions; } } }