Security fixes for Site Administrators to ensure proper access. Improvements to User and Role management components. Fix logic in CreateUser so that it does not prevent Administrators from creating users.

This commit is contained in:
Shaun Walker
2020-04-21 15:16:12 -04:00
parent 72995cd8fa
commit ab5257cea2
15 changed files with 910 additions and 592 deletions

View File

@ -5,75 +5,86 @@
@inject IProfileService ProfileService
@inject ISettingService SettingService
@if (profiles != null)
{
<table class="table table-borderless">
<tr>
<td>
<label class="control-label">Username: </label>
</td>
<td>
<input class="form-control" @bind="@username" />
</td>
</tr>
<tr>
<td>
<label class="control-label">Password: </label>
</td>
<td>
<input type="password" class="form-control" @bind="@password" />
</td>
</tr>
<tr>
<td>
<label class="control-label">Confirm Password: </label>
</td>
<td>
<input type="password" class="form-control" @bind="@confirm" />
</td>
</tr>
<tr>
<td>
<label class="control-label">Email: </label>
</td>
<td>
<input class="form-control" @bind="@email" />
</td>
</tr>
<tr>
<td>
<label class="control-label">Full Name: </label>
</td>
<td>
<input class="form-control" @bind="@displayname" />
</td>
</tr>
@foreach (Profile profile in profiles)
<TabStrip>
<TabPanel Name="Identity">
@if (profiles != null)
{
var p = profile;
if (p.Category != category)
{
<table class="table table-borderless">
<tr>
<th colspan="2" style="text-align: center;">
@p.Category
</th>
<td>
<label class="control-label">Username: </label>
</td>
<td>
<input class="form-control" @bind="@username" />
</td>
</tr>
category = p.Category;
}
<tr>
<td>
<label for="@p.Name" class="control-label">@p.Title: </label>
</td>
<td>
<input class="form-control" maxlength="@p.MaxLength" placeholder="@p.Description" @onchange="@(e => ProfileChanged(e, p.Name))" />
</td>
</tr>
<tr>
<td>
<label class="control-label">Password: </label>
</td>
<td>
<input type="password" class="form-control" @bind="@password" />
</td>
</tr>
<tr>
<td>
<label class="control-label">Confirm Password: </label>
</td>
<td>
<input type="password" class="form-control" @bind="@confirm" />
</td>
</tr>
<tr>
<td>
<label class="control-label">Email: </label>
</td>
<td>
<input class="form-control" @bind="@email" />
</td>
</tr>
<tr>
<td>
<label class="control-label">Full Name: </label>
</td>
<td>
<input class="form-control" @bind="@displayname" />
</td>
</tr>
</table>
}
</table>
<button type="button" class="btn btn-primary" @onclick="SaveUser">Save</button>
<NavLink class="btn btn-secondary" href="@NavigateUrl()">Cancel</NavLink>
}
</TabPanel>
<TabPanel Name="Profile">
@if (profiles != null)
{
<table class="table table-borderless">
@foreach (Profile profile in profiles)
{
var p = profile;
if (p.Category != category)
{
<tr>
<th colspan="2" style="text-align: center;">
@p.Category
</th>
</tr>
category = p.Category;
}
<tr>
<td>
<label for="@p.Name" class="control-label">@p.Title: </label>
</td>
<td>
<input class="form-control" maxlength="@p.MaxLength" placeholder="@p.Description" @onchange="@(e => ProfileChanged(e, p.Name))" />
</td>
</tr>
}
</table>
}
</TabPanel>
</TabStrip>
<button type="button" class="btn btn-primary" @onclick="SaveUser">Save</button>
<NavLink class="btn btn-secondary" href="@NavigateUrl()">Cancel</NavLink>
@code {
private string username = string.Empty;

View File

@ -5,105 +5,115 @@
@inject IProfileService ProfileService
@inject ISettingService SettingService
@if (profiles != null)
@if (PageState.User != null && photofileid != -1)
{
@if (photofileid != -1)
{
<img src="@(ContentUrl(photofileid))" alt="@displayname" style="max-width: 400px" class="rounded-circle mx-auto d-block">
}
else
{
<br />
}
<table class="table table-borderless">
<tr>
<td>
<label class="control-label">Username: </label>
</td>
<td>
<input class="form-control" @bind="@username" readonly />
</td>
</tr>
<tr>
<td>
<label class="control-label">Password: </label>
</td>
<td>
<input type="password" class="form-control" @bind="@password" />
</td>
</tr>
<tr>
<td>
<label class="control-label">Confirm Password: </label>
</td>
<td>
<input type="password" class="form-control" @bind="@confirm" />
</td>
</tr>
<tr>
<td>
<label class="control-label">Email: </label>
</td>
<td>
<input class="form-control" @bind="@email" />
</td>
</tr>
<tr>
<td>
<label class="control-label">Full Name: </label>
</td>
<td>
<input class="form-control" @bind="@displayname" />
</td>
</tr>
<tr>
<td>
<label class="control-label">Photo: </label>
</td>
<td>
<FileManager FileId="@photofileid.ToString()" @ref="filemanager" />
</td>
</tr>
@foreach (Profile profile in profiles)
{
var p = profile;
if (p.Category != category)
{
<tr>
<th colspan="2" style="text-align: center;">
@p.Category
</th>
</tr>
category = p.Category;
}
<tr>
<td>
<label for="@p.Name" class="control-label">@p.Title: </label>
</td>
<td>
<input class="form-control" maxlength="@p.MaxLength" value="@GetProfileValue(p.Name, p.DefaultValue)" placeholder="@p.Description" @onchange="@(e => ProfileChanged(e, p.Name))" />
</td>
</tr>
}
<tr>
<td>
<Label For="isDeleted" HelpText="Has the user been deleted">Is Deleted? </Label>
</td>
<td>
<select id="isDeleted" class="form-control" @bind="@isdeleted">
<option value="True">Yes</option>
<option value="False">No</option>
</select>
</td>
</tr>
</table>
<button type="button" class="btn btn-primary" @onclick="SaveUser">Save</button>
<NavLink class="btn btn-secondary" href="@NavigateUrl()">Cancel</NavLink>
<br />
<br />
<AuditInfo CreatedBy="@createdby" CreatedOn="@createdon" ModifiedBy="@modifiedby" ModifiedOn="@modifiedon" DeletedBy="@deletedby" DeletedOn="@deletedon"></AuditInfo>
<img src="@(ContentUrl(photofileid))" alt="@displayname" style="max-width: 400px" class="rounded-circle mx-auto d-block">
}
else
{
<br />
}
<TabStrip>
<TabPanel Name="Identity">
@if (profiles != null)
{
<table class="table table-borderless">
<tr>
<td>
<label class="control-label">Username: </label>
</td>
<td>
<input class="form-control" @bind="@username" readonly />
</td>
</tr>
<tr>
<td>
<label class="control-label">Password: </label>
</td>
<td>
<input type="password" class="form-control" @bind="@password" />
</td>
</tr>
<tr>
<td>
<label class="control-label">Confirm Password: </label>
</td>
<td>
<input type="password" class="form-control" @bind="@confirm" />
</td>
</tr>
<tr>
<td>
<label class="control-label">Email: </label>
</td>
<td>
<input class="form-control" @bind="@email" />
</td>
</tr>
<tr>
<td>
<label class="control-label">Full Name: </label>
</td>
<td>
<input class="form-control" @bind="@displayname" />
</td>
</tr>
<tr>
<td>
<label class="control-label">Photo: </label>
</td>
<td>
<FileManager FileId="@photofileid.ToString()" @ref="filemanager" />
</td>
</tr>
<tr>
<td>
<label class="control-label">Is Deleted? </label>
</td>
<td>
<select class="form-control" @bind="@isdeleted">
<option value="True">Yes</option>
<option value="False">No</option>
</select>
</td>
</tr>
</table>
}
</TabPanel>
<TabPanel Name="Profile">
@if (profiles != null)
{
<table class="table table-borderless">
@foreach (Profile profile in profiles)
{
var p = profile;
if (p.Category != category)
{
<tr>
<th colspan="2" style="text-align: center;">
@p.Category
</th>
</tr>
category = p.Category;
}
<tr>
<td>
<label for="@p.Name" class="control-label">@p.Title: </label>
</td>
<td>
<input class="form-control" maxlength="@p.MaxLength" value="@GetProfileValue(p.Name, p.DefaultValue)" placeholder="@p.Description" @onchange="@(e => ProfileChanged(e, p.Name))" />
</td>
</tr>
}
</table>
}
</TabPanel>
</TabStrip>
<button type="button" class="btn btn-primary" @onclick="SaveUser">Save</button>
<NavLink class="btn btn-secondary" href="@NavigateUrl()">Cancel</NavLink>
<br /><br />
<AuditInfo CreatedBy="@createdby" CreatedOn="@createdon" ModifiedBy="@modifiedby" ModifiedOn="@modifiedon" DeletedBy="@deletedby" DeletedOn="@deletedon"></AuditInfo>
@code {
private int userid;
@ -140,12 +150,12 @@
username = user.Username;
email = user.Email;
displayname = user.DisplayName;
if (user.PhotoFileId != null)
{
photofileid = user.PhotoFileId.Value;
}
settings = await SettingService.GetUserSettingsAsync(user.UserId);
createdby = user.CreatedBy;
createdon = user.CreatedOn;
@ -170,7 +180,7 @@
{
try
{
if (username != string.Empty && password != string.Empty && confirm != string.Empty && email != string.Empty)
if (username != string.Empty && email != string.Empty)
{
if (password == confirm)
{
@ -182,12 +192,12 @@
user.DisplayName = string.IsNullOrWhiteSpace(displayname) ? username : displayname;
user.PhotoFileId = null;
photofileid = filemanager.GetFileId();
if (photofileid != -1)
{
user.PhotoFileId = photofileid;
}
user.IsDeleted = (isdeleted == null ? true : Boolean.Parse(isdeleted));
user = await UserService.UpdateUserAsync(user);

View File

@ -1,6 +1,7 @@
@namespace Oqtane.Modules.Admin.Users
@inherits ModuleBase
@inject IRoleService RoleService
@inject IUserService UserService
@inject IUserRoleService UserRoleService
@if (userroles == null)
@ -12,7 +13,15 @@ else
<table class="table table-borderless">
<tr>
<td>
<Label For="role" HelpText="What is the role of this user">Role: </Label>
<Label For="user" HelpText="The user you are assigning roles to">User: </Label>
</td>
<td>
<input id="user" class="form-control" @bind="@name" disabled />
</td>
</tr>
<tr>
<td>
<Label For="role" HelpText="Select a role">Role: </Label>
</td>
<td>
<select id="role" class="form-control" @bind="@roleid">
@ -26,7 +35,7 @@ else
</tr>
<tr>
<td>
<Label For="effectiveDate" HelpText="The date that this role is implemented">Effective Date: </Label>
<Label For="effectiveDate" HelpText="The date that this role assignment is active">Effective Date: </Label>
</td>
<td>
<input id="effectiveDate" class="form-control" @bind="@effectivedate" />
@ -34,7 +43,7 @@ else
</tr>
<tr>
<td>
<Label For="expiryDate" HelpText="The date that this role expires">Expiry Date: </Label>
<Label For="expiryDate" HelpText="The date that this role assignment expires">Expiry Date: </Label>
</td>
<td>
<input id="expiryDate" class="form-control" @bind="@expirydate" />
@ -48,16 +57,16 @@ else
<p align="center">
<Pager Items="@userroles">
<Header>
<th>Role</th>
<th>Roles</th>
<th>&nbsp;</th>
</Header>
<Row>
<td>@context.Role.Name</td>
<td>
@if (!context.Role.IsSystem)
{
@if (context.Role.Name != Constants.RegisteredRole)
{
<button type="button" class="btn btn-danger" @onclick=@(async () => await DeleteUserRole(context.UserRoleId))>Delete</button>
}
}
</td>
</Row>
</Pager>
@ -66,6 +75,7 @@ else
@code {
private int userid;
private string name = string.Empty;
private List<Role> roles;
private int roleid = -1;
private string effectivedate = string.Empty;
@ -79,6 +89,8 @@ else
try
{
userid = Int32.Parse(PageState.QueryString["id"]);
User user = await UserService.GetUserAsync(userid, PageState.Site.SiteId);
name = user.DisplayName;
roles = await RoleService.GetRolesAsync(PageState.Site.SiteId);
await GetUserRoles();
}
@ -120,7 +132,7 @@ else
{
userrole.EffectiveDate = DateTime.Parse(effectivedate);
}
if (string.IsNullOrEmpty(expirydate))
{
userrole.ExpiryDate = null;
@ -136,7 +148,7 @@ else
userrole = new UserRole();
userrole.UserId = userid;
userrole.RoleId = roleid;
if (string.IsNullOrEmpty(effectivedate))
{
userrole.EffectiveDate = null;
@ -145,7 +157,7 @@ else
{
userrole.EffectiveDate = DateTime.Parse(effectivedate);
}
if (string.IsNullOrEmpty(expirydate))
{
userrole.ExpiryDate = null;
@ -154,10 +166,10 @@ else
{
userrole.ExpiryDate = DateTime.Parse(expirydate);
}
await UserRoleService.AddUserRoleAsync(userrole);
}
await GetUserRoles();
await logger.LogInformation("User Assigned To Role {UserRole}", userrole);
AddModuleMessage("User Assigned To Role", MessageType.Success);