public IActionResult EditPermissions(int?id) { if (id == null) { return(NotFound()); } var accessGroup = Context.AccessGroups.Where(x => x.Id == id).SingleOrDefault(); var roles = Context.Roles.AsNoTracking().OrderBy(x => x.Name).ToList(); var relatedRoles = Context.AccessGroupRoles.AsNoTracking().Where(x => x.AccessGroupId == id).Select(x => x.RoleId).ToList(); roles.Where(x => relatedRoles.Contains(x.Id)).ToList().ForEach(y => y.RelationshipPresent = true); var presentation = new AccessGroupPermissionsModel(); presentation.AccessGroup = accessGroup; presentation.Roles = roles; return(View(presentation)); }
public async Task <IActionResult> EditPermissions(int?id, AccessGroupPermissionsModel model) { // Make life 100x easier by setting default to notracking Context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking; var accessGroupQuery = Context.AccessGroups.Where(x => x.Id == id) .Include(i => i.UserAccessGroups) .ThenInclude(y => y.User); var accessGroup = accessGroupQuery.FirstOrDefault(); var accessGroupId = accessGroup.Id; var relatedUsers = accessGroupQuery.SelectMany(x => x.UserAccessGroups).Select(y => y.User).ToList(); model.AccessGroup = accessGroup; var allRoleIds = Context.Roles.Select(y => y.Id).ToList(); var currentRoleIds = Context.AccessGroupRoles.Where(x => x.AccessGroupId == id).Select(y => y.RoleId).ToList(); var futureRoleIds = model.Roles.Where(x => x.RelationshipPresent == true).Select(y => y.Id).ToList(); if (ModelState.IsValid) { // Rebuild Access Group Roles foreach (var roleId in allRoleIds) { if (futureRoleIds.Contains(roleId) && !currentRoleIds.Contains(roleId)) { var roleToAdd = Context.AccessGroupRoles.Add(new AccessGroupRole { RoleId = roleId, AccessGroupId = id.Value }); } else if (!futureRoleIds.Contains(roleId) && currentRoleIds.Contains(roleId)) { var roleToRemove = Context.AccessGroupRoles.AsTracking().Where(x => x.AccessGroupId == id && x.RoleId == roleId).SingleOrDefault(); Context.AccessGroupRoles.Remove(roleToRemove); } } Context.SaveChanges(); // Rebuild User Roles foreach (User user in relatedUsers) { var userIdParam = new NpgsqlParameter("userid", user.Id); //??? var accessGroupIdParam = new NpgsqlParameter("accessGroupId", accessGroupId); var currentUserRoles = Context.Roles.FromSqlRaw( "select r.* from roles r " + "join user_roles ur " + "on ur.roleid = r.id " + $"where ur.userid = @userid", userIdParam).ToList(); var roleIdsOutside = Context.Roles.FromSqlRaw( "select r.* " + "from user_accessgroups uag " + "join accessgroups ag " + "on ag.id = uag.accessgroupid " + "join accessgroup_roles agr " + "on agr.accessgroupid = ag.id " + "join roles r " + "on r.id = agr.roleid " + "where uag.userid = @userid " + "and ag.id != @accessGroupId ", new[] { userIdParam, accessGroupIdParam }).Select(x => x.Id).ToList(); var futureUserRoleIds = model.Roles.Where(x => x.RelationshipPresent).Select(x => x.Id).ToList(); var currentUserRoleIds = currentUserRoles.Select(x => x.Id).ToList(); var accessGroupRoles = currentRoleIds; foreach (var roleId in allRoleIds) { var theRole = Context.Roles.Where(x => x.Id == roleId).FirstOrDefault(); if (futureUserRoleIds.Contains(roleId) && !currentUserRoleIds.Contains(roleId)) { await _userManager.AddToRoleAsync(user, theRole.Name); } else if (!futureUserRoleIds.Contains(roleId) && currentUserRoleIds.Contains(roleId)) { // Remove the Role from the User only if that user // doesn't have access to that Role through another Access Group if (!roleIdsOutside.Contains(roleId)) { await _userManager.RemoveFromRoleAsync(user, theRole.Name); } } } Context.SaveChanges(); } Context.SaveChanges(); TempData["SuccessMessage"] = "Access Group Permissions Updated"; return(RedirectToAction(nameof(Index))); } return(View(model)); }