add support for API permissions at the UI layer - including ability to delegate user, role, profile management
This commit is contained in:
		| @ -42,7 +42,7 @@ | ||||
|     private string _description = string.Empty; | ||||
|     private string _isautoassigned = "False"; | ||||
|  | ||||
|     public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin; | ||||
|     public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit; | ||||
|  | ||||
|     private async Task SaveRole() | ||||
|     { | ||||
|  | ||||
| @ -49,7 +49,7 @@ | ||||
|     private string _modifiedby; | ||||
|     private DateTime _modifiedon; | ||||
|  | ||||
|     public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin; | ||||
|     public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit; | ||||
|  | ||||
|     protected override async Task OnInitializedAsync() | ||||
|     { | ||||
|  | ||||
| @ -10,7 +10,7 @@ | ||||
| } | ||||
| else | ||||
| { | ||||
|     <ActionLink Action="Add" Text="Add Role" ResourceKey="AddRole" /> | ||||
| 	<ActionLink Action="Add" Text="Add Role" Security="SecurityAccessLevel.Edit" ResourceKey="AddRole" /> | ||||
|  | ||||
|     <Pager Items="@_roles"> | ||||
|         <Header> | ||||
| @ -20,9 +20,9 @@ else | ||||
|             <th>@SharedLocalizer["Name"]</th> | ||||
|         </Header> | ||||
|         <Row> | ||||
|             <td><ActionLink Action="Edit" Parameters="@($"id=" + context.RoleId.ToString())" Disabled="@(context.IsSystem)" ResourceKey="Edit" /></td> | ||||
|             <td><ActionDialog Header="Delete Role" Message="@string.Format(Localizer["Confirm.DeleteUser"], context.Name)" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteRole(context))" Disabled="@(context.IsSystem)" ResourceKey="DeleteRole" /></td> | ||||
|             <td><ActionLink Action="Users" Parameters="@($"id=" + context.RoleId.ToString())" ResourceKey="Users" /></td> | ||||
| 			<td><ActionLink Action="Edit" Parameters="@($"id=" + context.RoleId.ToString())" Security="SecurityAccessLevel.Edit" Disabled="@(context.IsSystem)" ResourceKey="Edit" /></td> | ||||
|             <td><ActionDialog Header="Delete Role" Message="@string.Format(Localizer["Confirm.DeleteUser"], context.Name)" Action="Delete" Security="SecurityAccessLevel.Edit" Class="btn btn-danger" OnClick="@(async () => await DeleteRole(context))" Disabled="@(context.IsSystem)" ResourceKey="DeleteRole" /></td> | ||||
| 			<td><ActionLink Action="Users" Parameters="@($"id=" + context.RoleId.ToString())" Security="SecurityAccessLevel.Edit" ResourceKey="Users" /></td> | ||||
|             <td>@context.Name</td> | ||||
|         </Row> | ||||
|     </Pager> | ||||
| @ -31,7 +31,7 @@ else | ||||
| @code { | ||||
|     private List<Role> _roles; | ||||
|  | ||||
|     public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin; | ||||
|     public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.View; | ||||
|  | ||||
|     protected override async Task OnParametersSetAsync() | ||||
|     { | ||||
|  | ||||
							
								
								
									
										19
									
								
								Oqtane.Client/Modules/Admin/Roles/ModuleInfo.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								Oqtane.Client/Modules/Admin/Roles/ModuleInfo.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | ||||
| using Oqtane.Documentation; | ||||
| using Oqtane.Models; | ||||
| using Oqtane.Shared; | ||||
|  | ||||
| namespace Oqtane.Modules.Admin.Roles | ||||
| { | ||||
|     [PrivateApi("Mark this as private, since it's not very useful in the public docs")] | ||||
|     public class ModuleInfo : IModule | ||||
|     { | ||||
|         public ModuleDefinition ModuleDefinition => new ModuleDefinition | ||||
|         { | ||||
|             Name = "Roles", | ||||
|             Description = "Manage Roles", | ||||
|             Categories = "Admin", | ||||
|             Version = Constants.Version, | ||||
|             PermissionNames = $"{PermissionNames.View},{PermissionNames.Edit},{EntityNames.Role}:{PermissionNames.Write}:{RoleNames.Admin},{EntityNames.UserRole}:{PermissionNames.Write}:{RoleNames.Admin}" | ||||
|         }; | ||||
|     } | ||||
| } | ||||
| @ -23,13 +23,7 @@ else | ||||
|             <div class="row mb-1 align-items-center"> | ||||
|                 <Label Class="col-sm-3" For="user" HelpText="Select a user" ResourceKey="User">User: </Label> | ||||
|                 <div class="col-sm-9"> | ||||
|                     <select id="user" class="form-select" @bind="@userid" required> | ||||
|                         <option value="-1"><@Localizer["User.Select"]></option> | ||||
|                         @foreach (UserRole userrole in users) | ||||
|                         { | ||||
|                             <option value="@(userrole.UserId)">@userrole.User.DisplayName</option> | ||||
|                         } | ||||
|                     </select> | ||||
| 					<AutoComplete OnSearch="GetUsers" Placeholder="@Localizer["User.Select"]" @ref="user" /> | ||||
|                 </div> | ||||
|             </div> | ||||
|             <div class="row mb-1 align-items-center"> | ||||
| @ -64,7 +58,7 @@ else | ||||
|                             <td>@context.EffectiveDate</td> | ||||
|                             <td>@context.ExpiryDate</td> | ||||
|                             <td> | ||||
|                                 <ActionDialog Header="Remove User" Message="@string.Format(Localizer["Confirm.User.DeleteRole"], context.User.DisplayName)" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteUserRole(context.UserRoleId))" Disabled="@(context.Role.IsAutoAssigned || PageState.User.Username == UserNames.Host)" ResourceKey="DeleteUserRole" /> | ||||
| 								<ActionDialog Header="Remove User" Message="@string.Format(Localizer["Confirm.User.DeleteRole"], context.User.DisplayName)" Action="Delete" Security="SecurityAccessLevel.Edit" Class="btn btn-danger" OnClick="@(async () => await DeleteUserRole(context.UserRoleId))" Disabled="@(context.Role.IsAutoAssigned || context.User.Username == UserNames.Host || context.User.UserId == PageState.User.UserId)" ResourceKey="DeleteUserRole" /> | ||||
|                             </td> | ||||
|                         </Row> | ||||
|                     </Pager> | ||||
| @ -75,81 +69,96 @@ else | ||||
| } | ||||
|  | ||||
| @code { | ||||
|     private ElementReference form; | ||||
|     private bool validated = false; | ||||
| 	private ElementReference form; | ||||
| 	private bool validated = false; | ||||
|  | ||||
|     private int roleid; | ||||
|     private string name = string.Empty; | ||||
|     private List<UserRole> users; | ||||
|     private int userid = -1; | ||||
|     private DateTime? effectivedate = null; | ||||
|     private DateTime? expirydate = null; | ||||
|     private List<UserRole> userroles; | ||||
| 	private int roleid; | ||||
| 	private string name = string.Empty; | ||||
| 	private AutoComplete user; | ||||
| 	private DateTime? effectivedate = null; | ||||
| 	private DateTime? expirydate = null; | ||||
| 	private List<UserRole> userroles; | ||||
|  | ||||
|     public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin; | ||||
| 	public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit; | ||||
|  | ||||
|     protected override async Task OnInitializedAsync() | ||||
|     { | ||||
|         try | ||||
|         { | ||||
|             roleid = Int32.Parse(PageState.QueryString["id"]); | ||||
|             Role role = await RoleService.GetRoleAsync(roleid); | ||||
|             name = role.Name; | ||||
|             users = await UserRoleService.GetUserRolesAsync(PageState.Site.SiteId, RoleNames.Registered); | ||||
|             await GetUserRoles(); | ||||
|         } | ||||
|         catch (Exception ex) | ||||
|         { | ||||
|             await logger.LogError(ex, "Error Loading Users {Error}", ex.Message); | ||||
|             AddModuleMessage(Localizer["Error.User.Load"], MessageType.Error); | ||||
|         } | ||||
|     } | ||||
| 	protected override async Task OnInitializedAsync() | ||||
| 	{ | ||||
| 		try | ||||
| 		{ | ||||
| 			roleid = Int32.Parse(PageState.QueryString["id"]); | ||||
| 			Role role = await RoleService.GetRoleAsync(roleid); | ||||
| 			name = role.Name; | ||||
| 			await GetUserRoles(); | ||||
| 		} | ||||
| 		catch (Exception ex) | ||||
| 		{ | ||||
| 			await logger.LogError(ex, "Error Loading Users {Error}", ex.Message); | ||||
| 			AddModuleMessage(Localizer["Error.User.Load"], MessageType.Error); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
|     private async Task GetUserRoles() | ||||
|     { | ||||
|         try | ||||
|         { | ||||
|             userroles = await UserRoleService.GetUserRolesAsync(PageState.Site.SiteId, name); | ||||
|         } | ||||
|         catch (Exception ex) | ||||
|         { | ||||
|             await logger.LogError(ex, "Error Loading User Roles {RoleId} {Error}", roleid, ex.Message); | ||||
|             AddModuleMessage(Localizer["Error.User.LoadRole"], MessageType.Error); | ||||
|         } | ||||
|     } | ||||
| 	private async Task<Dictionary<string, string>> GetUsers(string filter) | ||||
| 	{ | ||||
| 		try | ||||
| 		{ | ||||
| 			var users = await UserRoleService.GetUserRolesAsync(PageState.Site.SiteId, RoleNames.Registered); | ||||
| 			return users.Where(item => item.User.DisplayName.Contains(filter, StringComparison.OrdinalIgnoreCase)) | ||||
| 				.ToDictionary(item => item.UserId.ToString(), item => item.User.DisplayName); | ||||
| 		} | ||||
| 		catch (Exception ex) | ||||
| 		{ | ||||
| 			await logger.LogError(ex, "Error Loading Users {filter} {Error}", filter, ex.Message); | ||||
| 			AddModuleMessage(Localizer["Error.User.Load"], MessageType.Error); | ||||
| 		} | ||||
| 		return new Dictionary<string, string>(); | ||||
| 	} | ||||
|  | ||||
|     private async Task SaveUserRole() | ||||
|     { | ||||
|         validated = true; | ||||
|         var interop = new Interop(JSRuntime); | ||||
|         if (await interop.FormValid(form)) | ||||
|         { | ||||
|             try | ||||
|             { | ||||
|                 if (userid != -1) | ||||
|                 { | ||||
|                     var userrole = userroles.Where(item => item.UserId == userid && item.RoleId == roleid).FirstOrDefault(); | ||||
|                     if (userrole != null) | ||||
|                     { | ||||
|                         userrole.EffectiveDate = effectivedate; | ||||
|                         userrole.ExpiryDate = expirydate; | ||||
|                         await UserRoleService.UpdateUserRoleAsync(userrole); | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         userrole = new UserRole(); | ||||
|                         userrole.UserId = userid; | ||||
|                         userrole.RoleId = roleid; | ||||
|                         userrole.EffectiveDate = effectivedate; | ||||
|                         userrole.ExpiryDate = expirydate; | ||||
| 	private async Task GetUserRoles() | ||||
| 	{ | ||||
| 		try | ||||
| 		{ | ||||
| 			userroles = await UserRoleService.GetUserRolesAsync(PageState.Site.SiteId, name); | ||||
| 		} | ||||
| 		catch (Exception ex) | ||||
| 		{ | ||||
| 			await logger.LogError(ex, "Error Loading User Roles {RoleId} {Error}", roleid, ex.Message); | ||||
| 			AddModuleMessage(Localizer["Error.User.LoadRole"], MessageType.Error); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
|                         await UserRoleService.AddUserRoleAsync(userrole); | ||||
|                     } | ||||
| 	private async Task SaveUserRole() | ||||
| 	{ | ||||
| 		validated = true; | ||||
| 		var interop = new Interop(JSRuntime); | ||||
| 		if (await interop.FormValid(form)) | ||||
| 		{ | ||||
| 			try | ||||
| 			{ | ||||
| 				if (!string.IsNullOrEmpty(user.Key) && int.TryParse(user.Key, out int userid)) | ||||
| 				{ | ||||
| 					var userrole = userroles.Where(item => item.UserId == userid && item.RoleId == roleid).FirstOrDefault(); | ||||
| 					if (userrole != null) | ||||
| 					{ | ||||
| 						userrole.EffectiveDate = effectivedate; | ||||
| 						userrole.ExpiryDate = expirydate; | ||||
| 						await UserRoleService.UpdateUserRoleAsync(userrole); | ||||
| 					} | ||||
| 					else | ||||
| 					{ | ||||
| 						userrole = new UserRole(); | ||||
| 						userrole.UserId = userid; | ||||
| 						userrole.RoleId = roleid; | ||||
| 						userrole.EffectiveDate = effectivedate; | ||||
| 						userrole.ExpiryDate = expirydate; | ||||
|  | ||||
|                     await logger.LogInformation("User Assigned To Role {UserRole}", userrole); | ||||
|                     AddModuleMessage(Localizer["Success.User.AssignedRole"], MessageType.Success); | ||||
|                     await GetUserRoles(); | ||||
|                     StateHasChanged(); | ||||
| 						await UserRoleService.AddUserRoleAsync(userrole); | ||||
| 					} | ||||
|  | ||||
| 					await logger.LogInformation("User Assigned To Role {UserRole}", userrole); | ||||
| 					AddModuleMessage(Localizer["Success.User.AssignedRole"], MessageType.Success); | ||||
| 					await GetUserRoles(); | ||||
| 					user.Clear(); | ||||
| 					StateHasChanged(); | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 Shaun Walker
					Shaun Walker