feature: flag permissions
feature: flag permissions
This commit is contained in:
@@ -78,14 +78,16 @@ namespace Disco.Web.Areas.API.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateClaims(AuthorizationRole AuthorizationRole, string[] ClaimKeys)
|
||||
private void UpdateClaims(AuthorizationRole AuthorizationRole, string[] claimKeys)
|
||||
{
|
||||
var proposedClaims = Claims.BuildClaims(ClaimKeys);
|
||||
claimKeys = claimKeys ?? Array.Empty<string>();
|
||||
|
||||
var proposedClaims = Claims.BuildClaims(claimKeys);
|
||||
|
||||
var currentToken = RoleToken.FromAuthorizationRole(AuthorizationRole);
|
||||
var currentClaimKeys = Claims.GetClaimKeys(currentToken.Claims);
|
||||
var removedClaims = currentClaimKeys.Except(ClaimKeys).ToArray();
|
||||
var addedClaims = ClaimKeys.Except(currentClaimKeys).ToArray();
|
||||
var removedClaims = currentClaimKeys.Except(claimKeys).ToArray();
|
||||
var addedClaims = claimKeys.Except(currentClaimKeys).ToArray();
|
||||
|
||||
AuthorizationRole.SetClaims(proposedClaims);
|
||||
UserService.UpdateAuthorizationRole(Database, AuthorizationRole);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Services;
|
||||
using Disco.Services.Authorization;
|
||||
using Disco.Services.Web;
|
||||
using System;
|
||||
using System.Data.Entity;
|
||||
@@ -12,7 +11,7 @@ namespace Disco.Web.Areas.API.Controllers
|
||||
public partial class DeviceFlagAssignmentController : AuthorizedDatabaseController
|
||||
{
|
||||
const string pComments = "comments";
|
||||
|
||||
[HttpPost, ValidateAntiForgeryToken]
|
||||
public virtual ActionResult Update(int id, string key, string value = null, bool? redirect = null)
|
||||
{
|
||||
try
|
||||
@@ -21,7 +20,9 @@ namespace Disco.Web.Areas.API.Controllers
|
||||
throw new ArgumentOutOfRangeException(nameof(id));
|
||||
if (string.IsNullOrEmpty(key))
|
||||
throw new ArgumentNullException(nameof(key));
|
||||
var assignment = Database.DeviceFlagAssignments.FirstOrDefault(a => a.Id == id);
|
||||
var assignment = Database.DeviceFlagAssignments
|
||||
.Include(a => a.DeviceFlag)
|
||||
.FirstOrDefault(a => a.Id == id);
|
||||
if (assignment != null)
|
||||
{
|
||||
switch (key.ToLower())
|
||||
@@ -52,7 +53,7 @@ namespace Disco.Web.Areas.API.Controllers
|
||||
}
|
||||
|
||||
#region Update Shortcut Methods
|
||||
[DiscoAuthorizeAny(Claims.Device.Actions.EditFlags)]
|
||||
[HttpPost, ValidateAntiForgeryToken]
|
||||
public virtual ActionResult UpdateComments(int id, string Comments = null, bool? redirect = null)
|
||||
{
|
||||
return Update(id, pComments, Comments, redirect);
|
||||
@@ -60,20 +61,19 @@ namespace Disco.Web.Areas.API.Controllers
|
||||
#endregion
|
||||
|
||||
#region Update Properties
|
||||
private void UpdateComments(DeviceFlagAssignment assignment, string Comments)
|
||||
private void UpdateComments(DeviceFlagAssignment assignment, string comments)
|
||||
{
|
||||
if (!assignment.CanEditComments())
|
||||
if (!assignment.CanEdit())
|
||||
throw new InvalidOperationException("Editing comments for device flags is denied");
|
||||
|
||||
assignment.OnEditComments(Comments);
|
||||
assignment.OnEdit(comments);
|
||||
Database.SaveChanges();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Actions
|
||||
|
||||
[DiscoAuthorizeAny(Claims.Device.Actions.AddFlags)]
|
||||
public virtual ActionResult AddDevice(int id, string DeviceSerialNumber, string Comments)
|
||||
[HttpPost, ValidateAntiForgeryToken]
|
||||
public virtual ActionResult AddDevice(int id, string deviceSerialNumber, string comments)
|
||||
{
|
||||
Database.Configuration.LazyLoadingEnabled = true;
|
||||
|
||||
@@ -81,37 +81,35 @@ namespace Disco.Web.Areas.API.Controllers
|
||||
if (flag == null)
|
||||
throw new ArgumentException("Invalid Device Flag Id", nameof(id));
|
||||
|
||||
var device = Database.Devices.Include(u => u.DeviceFlagAssignments).FirstOrDefault(d => d.SerialNumber == DeviceSerialNumber);
|
||||
var device = Database.Devices.Include(u => u.DeviceFlagAssignments).FirstOrDefault(d => d.SerialNumber == deviceSerialNumber);
|
||||
if (device == null)
|
||||
throw new ArgumentException("Invalid Device Serial Number", nameof(DeviceSerialNumber));
|
||||
throw new ArgumentException("Invalid Device Serial Number", nameof(deviceSerialNumber));
|
||||
|
||||
if (!device.CanAddDeviceFlag(flag))
|
||||
throw new InvalidOperationException("Adding device flag is denied");
|
||||
return Unauthorized("Adding device flag is denied");
|
||||
|
||||
var addingUser = Database.Users.Find(CurrentUser.UserId);
|
||||
|
||||
var assignment = device.OnAddDeviceFlag(Database, flag, addingUser, Comments);
|
||||
var assignment = device.OnAddDeviceFlag(Database, flag, comments);
|
||||
|
||||
Database.SaveChanges();
|
||||
|
||||
return Redirect($"{Url.Action(MVC.Device.Show(device.SerialNumber))}#DeviceDetailTab-Flags");
|
||||
}
|
||||
|
||||
[DiscoAuthorizeAny(Claims.Device.Actions.RemoveFlags)]
|
||||
[HttpPost, ValidateAntiForgeryToken]
|
||||
public virtual ActionResult RemoveDevice(int id)
|
||||
{
|
||||
Database.Configuration.LazyLoadingEnabled = true;
|
||||
|
||||
var assignment = Database.DeviceFlagAssignments.FirstOrDefault(a => a.Id == id);
|
||||
var assignment = Database.DeviceFlagAssignments
|
||||
.Include(a => a.DeviceFlag)
|
||||
.FirstOrDefault(a => a.Id == id);
|
||||
if (assignment == null)
|
||||
throw new ArgumentException("Invalid Device Flag Assignment Id", nameof(id));
|
||||
|
||||
if (!assignment.CanRemove())
|
||||
throw new InvalidOperationException("Removing device flag assignment is denied");
|
||||
return Unauthorized("Removing device flag assignment is denied");
|
||||
|
||||
var removingUser = Database.Users.Find(CurrentUser.UserId);
|
||||
|
||||
assignment.OnRemove(Database, removingUser);
|
||||
assignment.OnRemove(Database);
|
||||
Database.SaveChanges();
|
||||
|
||||
return Redirect($"{Url.Action(MVC.Device.Show(assignment.DeviceSerialNumber))}#DeviceDetailTab-Flags");
|
||||
@@ -120,4 +118,4 @@ namespace Disco.Web.Areas.API.Controllers
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,9 @@ using Disco.Services.Devices.DeviceFlags;
|
||||
using Disco.Services.Exporting;
|
||||
using Disco.Services.Interop.ActiveDirectory;
|
||||
using Disco.Services.Tasks;
|
||||
using Disco.Services.Users.UserFlags;
|
||||
using Disco.Services.Web;
|
||||
using Disco.Web.Areas.API.Models.Shared;
|
||||
using Disco.Web.Areas.Config.Models.DeviceFlag;
|
||||
using Disco.Web.Extensions;
|
||||
using System;
|
||||
@@ -467,6 +469,24 @@ namespace Disco.Web.Areas.API.Controllers
|
||||
return RedirectToAction(MVC.Config.Export.Create(savedExport.Id));
|
||||
}
|
||||
|
||||
[DiscoAuthorize(Claims.Config.DeviceFlag.Configure)]
|
||||
[HttpPost, ValidateAntiForgeryToken]
|
||||
public virtual ActionResult Permission(int id, FlagPermissionModel model = null)
|
||||
{
|
||||
var deviceFlag = Database.DeviceFlags.Find(id);
|
||||
|
||||
if (deviceFlag == null)
|
||||
return NotFound();
|
||||
|
||||
if (model == null || !model.IsOverride)
|
||||
deviceFlag.Permissions = null;
|
||||
else
|
||||
deviceFlag.Permissions = model.ToFlagPermission(deviceFlag);
|
||||
|
||||
DeviceFlagService.Update(Database, deviceFlag);
|
||||
|
||||
return RedirectToAction(MVC.Config.DeviceFlag.Index(deviceFlag.Id));
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,9 @@ using Disco.Services.Authorization;
|
||||
using Disco.Services.Interop.ActiveDirectory;
|
||||
using Disco.Services.Interop.DiscoServices;
|
||||
using Disco.Services.Messaging;
|
||||
using Disco.Services.Users;
|
||||
using Disco.Services.Web;
|
||||
using Disco.Web.Areas.API.Models.Shared;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
@@ -320,38 +322,64 @@ namespace Disco.Web.Areas.API.Controllers
|
||||
};
|
||||
}
|
||||
|
||||
[DiscoAuthorizeAny(Claims.DiscoAdminAccount, Claims.Config.JobQueue.Configure)]
|
||||
public virtual ActionResult SearchSubjects(string term)
|
||||
[DiscoAuthorizeAny(Claims.DiscoAdminAccount, Claims.Config.JobQueue.Configure, Claims.Config.UserFlag.Configure, Claims.Config.DeviceFlag.Configure)]
|
||||
public virtual ActionResult SearchSubjects(string term, bool includeAuthorizationRoles = false)
|
||||
{
|
||||
var groupResults = ActiveDirectory.SearchADGroups(term).Cast<IADObject>();
|
||||
var userResults = ActiveDirectory.SearchADUserAccounts(term, true).Cast<IADObject>();
|
||||
var groupResults = ActiveDirectory.SearchADGroups(term).Select(r => SubjectDescriptorModel.FromActiveDirectoryObject(r));
|
||||
var userResults = ActiveDirectory.SearchADUserAccounts(term, true).Select(r => SubjectDescriptorModel.FromActiveDirectoryObject(r));
|
||||
|
||||
var results = groupResults.Concat(userResults).OrderBy(r => r.SamAccountName)
|
||||
.Select(r => Models.Shared.SubjectDescriptorModel.FromActiveDirectoryObject(r)).ToList();
|
||||
IEnumerable<SubjectDescriptorModel> roleResults;
|
||||
if (includeAuthorizationRoles)
|
||||
{
|
||||
roleResults = Database.AuthorizationRoles.AsNoTracking().Where(r => r.Name.Contains(term))
|
||||
.ToList()
|
||||
.Select(r => SubjectDescriptorModel.FromAuthorizationRole(r));
|
||||
}
|
||||
else
|
||||
roleResults = Enumerable.Empty<SubjectDescriptorModel>();
|
||||
|
||||
var results = groupResults.Concat(userResults).Concat(roleResults)
|
||||
.OrderBy(r => r.Id).ToList();
|
||||
|
||||
return Json(results, JsonRequestBehavior.AllowGet);
|
||||
}
|
||||
|
||||
[DiscoAuthorizeAny(Claims.Config.UserFlag.Configure)]
|
||||
[DiscoAuthorizeAny(Claims.DiscoAdminAccount, Claims.Config.DeviceProfile.Configure, Claims.Config.DocumentTemplate.Configure, Claims.Config.Plugin.Configure, Claims.Config.UserFlag.Configure, Claims.Config.DeviceFlag.Configure)]
|
||||
public virtual ActionResult SearchGroupSubjects(string term)
|
||||
{
|
||||
var groupResults = ActiveDirectory.SearchADGroups(term).Cast<IADObject>();
|
||||
|
||||
var results = groupResults.OrderBy(r => r.SamAccountName)
|
||||
.Select(r => Models.Shared.SubjectDescriptorModel.FromActiveDirectoryObject(r)).ToList();
|
||||
.Select(r => SubjectDescriptorModel.FromActiveDirectoryObject(r)).ToList();
|
||||
|
||||
return Json(results, JsonRequestBehavior.AllowGet);
|
||||
}
|
||||
|
||||
[DiscoAuthorizeAny(Claims.DiscoAdminAccount, Claims.Config.JobQueue.Configure)]
|
||||
public virtual ActionResult Subject(string Id)
|
||||
[DiscoAuthorizeAny(Claims.DiscoAdminAccount, Claims.Config.JobQueue.Configure, Claims.Config.UserFlag.Configure, Claims.Config.DeviceFlag.Configure)]
|
||||
public virtual ActionResult Subject(string Id, bool includeAuthorizationRoles = false)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(Id))
|
||||
return Json(null, JsonRequestBehavior.AllowGet);
|
||||
|
||||
if (Id.StartsWith("[", StringComparison.Ordinal))
|
||||
{
|
||||
if (includeAuthorizationRoles && int.TryParse(Id.Trim('[', ']'), out var roleId))
|
||||
{
|
||||
var roleName = UserService.GetAuthorizationRoleName(roleId);
|
||||
if (roleName != null)
|
||||
{
|
||||
return Json(SubjectDescriptorModel.FromAuthorizationRole(roleId, roleName), JsonRequestBehavior.AllowGet);
|
||||
}
|
||||
}
|
||||
return Json(null, JsonRequestBehavior.AllowGet);
|
||||
}
|
||||
|
||||
var subject = ActiveDirectory.RetrieveADObject(Id, Quick: true);
|
||||
|
||||
if (subject == null)
|
||||
return Json(null, JsonRequestBehavior.AllowGet);
|
||||
else
|
||||
return Json(Models.Shared.SubjectDescriptorModel.FromActiveDirectoryObject(subject), JsonRequestBehavior.AllowGet);
|
||||
return Json(SubjectDescriptorModel.FromActiveDirectoryObject(subject), JsonRequestBehavior.AllowGet);
|
||||
}
|
||||
|
||||
[DiscoAuthorizeAny(Claims.Config.UserFlag.Configure, Claims.Config.DeviceFlag.Configure, Claims.Config.DeviceProfile.Configure, Claims.Config.DocumentTemplate.Configure)]
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace Disco.Web.Areas.API.Controllers
|
||||
public partial class UserFlagAssignmentController : AuthorizedDatabaseController
|
||||
{
|
||||
const string pComments = "comments";
|
||||
|
||||
[HttpPost, ValidateAntiForgeryToken]
|
||||
public virtual ActionResult Update(int id, string key, string value = null, bool? redirect = null)
|
||||
{
|
||||
try
|
||||
@@ -21,7 +21,9 @@ namespace Disco.Web.Areas.API.Controllers
|
||||
throw new ArgumentOutOfRangeException(nameof(id));
|
||||
if (string.IsNullOrEmpty(key))
|
||||
throw new ArgumentNullException(nameof(key));
|
||||
var userFlagAssignment = Database.UserFlagAssignments.FirstOrDefault(a => a.Id == id);
|
||||
var userFlagAssignment = Database.UserFlagAssignments
|
||||
.Include(a => a.UserFlag)
|
||||
.FirstOrDefault(a => a.Id == id);
|
||||
if (userFlagAssignment != null)
|
||||
{
|
||||
switch (key.ToLower())
|
||||
@@ -52,7 +54,7 @@ namespace Disco.Web.Areas.API.Controllers
|
||||
}
|
||||
|
||||
#region Update Shortcut Methods
|
||||
[DiscoAuthorizeAny(Claims.User.Actions.EditFlags)]
|
||||
[HttpPost, ValidateAntiForgeryToken]
|
||||
public virtual ActionResult UpdateComments(int id, string Comments = null, bool? redirect = null)
|
||||
{
|
||||
return Update(id, pComments, Comments, redirect);
|
||||
@@ -60,19 +62,19 @@ namespace Disco.Web.Areas.API.Controllers
|
||||
#endregion
|
||||
|
||||
#region Update Properties
|
||||
private void UpdateComments(UserFlagAssignment userFlagAssignment, string Comments)
|
||||
private void UpdateComments(UserFlagAssignment userFlagAssignment, string comments)
|
||||
{
|
||||
if (!userFlagAssignment.CanEditComments())
|
||||
if (!userFlagAssignment.CanEdit())
|
||||
throw new InvalidOperationException("Editing comments for user flags is denied");
|
||||
|
||||
userFlagAssignment.OnEditComments(Comments);
|
||||
userFlagAssignment.OnEdit(comments);
|
||||
Database.SaveChanges();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Actions
|
||||
|
||||
[DiscoAuthorizeAny(Claims.User.Actions.AddFlags)]
|
||||
[HttpPost, ValidateAntiForgeryToken]
|
||||
public virtual ActionResult AddUser(int id, string UserId, string Comments)
|
||||
{
|
||||
Database.Configuration.LazyLoadingEnabled = true;
|
||||
@@ -86,32 +88,30 @@ namespace Disco.Web.Areas.API.Controllers
|
||||
throw new ArgumentException("Invalid User Id", nameof(UserId));
|
||||
|
||||
if (!user.CanAddUserFlag(userFlag))
|
||||
throw new InvalidOperationException("Adding user flag is denied");
|
||||
return Unauthorized("Adding user flag is denied");
|
||||
|
||||
var addingUser = Database.Users.Find(CurrentUser.UserId);
|
||||
|
||||
var userFlagAssignment = user.OnAddUserFlag(Database, userFlag, addingUser, Comments);
|
||||
var userFlagAssignment = user.OnAddUserFlag(Database, userFlag, Comments);
|
||||
|
||||
Database.SaveChanges();
|
||||
|
||||
return Redirect($"{Url.Action(MVC.User.Show(user.UserId))}#UserDetailTab-Flags");
|
||||
}
|
||||
|
||||
[DiscoAuthorizeAny(Claims.User.Actions.RemoveFlags)]
|
||||
[HttpPost, ValidateAntiForgeryToken]
|
||||
public virtual ActionResult RemoveUser(int id)
|
||||
{
|
||||
Database.Configuration.LazyLoadingEnabled = true;
|
||||
|
||||
var userFlagAssignment = Database.UserFlagAssignments.FirstOrDefault(a => a.Id == id);
|
||||
var userFlagAssignment = Database.UserFlagAssignments
|
||||
.Include(a => a.UserFlag)
|
||||
.FirstOrDefault(a => a.Id == id);
|
||||
if (userFlagAssignment == null)
|
||||
throw new ArgumentException("Invalid User Flag Assignment Id", nameof(id));
|
||||
|
||||
if (!userFlagAssignment.CanRemove())
|
||||
throw new InvalidOperationException("Removing user flag assignment is denied");
|
||||
return Unauthorized("Removing user flag assignment is denied");
|
||||
|
||||
var removingUser = Database.Users.Find(CurrentUser.UserId);
|
||||
|
||||
userFlagAssignment.OnRemove(Database, removingUser);
|
||||
userFlagAssignment.OnRemove(Database);
|
||||
Database.SaveChanges();
|
||||
|
||||
return Redirect($"{Url.Action(MVC.User.Show(userFlagAssignment.UserId))}#UserDetailTab-Flags");
|
||||
@@ -120,4 +120,4 @@ namespace Disco.Web.Areas.API.Controllers
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ using Disco.Services.Interop.ActiveDirectory;
|
||||
using Disco.Services.Tasks;
|
||||
using Disco.Services.Users.UserFlags;
|
||||
using Disco.Services.Web;
|
||||
using Disco.Web.Areas.API.Models.Shared;
|
||||
using Disco.Web.Areas.Config.Models.UserFlag;
|
||||
using Disco.Web.Extensions;
|
||||
using System;
|
||||
@@ -467,6 +468,24 @@ namespace Disco.Web.Areas.API.Controllers
|
||||
return RedirectToAction(MVC.Config.Export.Create(savedExport.Id));
|
||||
}
|
||||
|
||||
[DiscoAuthorize(Claims.Config.UserFlag.Configure)]
|
||||
[HttpPost, ValidateAntiForgeryToken]
|
||||
public virtual ActionResult Permission(int id, FlagPermissionModel model = null)
|
||||
{
|
||||
var userFlag = Database.UserFlags.Find(id);
|
||||
|
||||
if (userFlag == null)
|
||||
return NotFound();
|
||||
|
||||
if (model == null || !model.IsOverride)
|
||||
userFlag.Permissions = null;
|
||||
else
|
||||
userFlag.Permissions = model.ToFlagPermission(userFlag);
|
||||
|
||||
UserFlagService.Update(Database, userFlag);
|
||||
|
||||
return RedirectToAction(MVC.Config.UserFlag.Index(userFlag.Id));
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user