Removed unnecessary files + added proper documentation to admin page generators
This commit is contained in:
@@ -2,6 +2,11 @@ namespace HopFrame.Web.Admin.Generators;
|
|||||||
|
|
||||||
public interface IAdminContextGenerator {
|
public interface IAdminContextGenerator {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the generator object for the specified Admin Page. This needs to be within the same Admin Context.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TModel">The Model of the Admin Page</typeparam>
|
||||||
|
/// <returns></returns>
|
||||||
IAdminPageGenerator<TModel> Page<TModel>();
|
IAdminPageGenerator<TModel> Page<TModel>();
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -5,24 +5,105 @@ namespace HopFrame.Web.Admin.Generators;
|
|||||||
|
|
||||||
public interface IAdminPageGenerator<TModel> {
|
public interface IAdminPageGenerator<TModel> {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the title of the Admin Page
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="title">the specified title</param>
|
||||||
|
/// <returns></returns>
|
||||||
IAdminPageGenerator<TModel> Title(string title);
|
IAdminPageGenerator<TModel> Title(string title);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the description of the Admin Page
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="description">the specified description</param>
|
||||||
|
/// <returns></returns>
|
||||||
IAdminPageGenerator<TModel> Description(string description);
|
IAdminPageGenerator<TModel> Description(string description);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the url for the Admin Page
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="url">the specified url (administration/{url})</param>
|
||||||
|
/// <returns></returns>
|
||||||
IAdminPageGenerator<TModel> Url(string url);
|
IAdminPageGenerator<TModel> Url(string url);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the permission needed to view the Admin Page
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="permission">the specified permission</param>
|
||||||
|
/// <returns></returns>
|
||||||
IAdminPageGenerator<TModel> ViewPermission(string permission);
|
IAdminPageGenerator<TModel> ViewPermission(string permission);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the permission needed to create a new Entry
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="permission">the specified permission</param>
|
||||||
|
/// <returns></returns>
|
||||||
IAdminPageGenerator<TModel> CreatePermission(string permission);
|
IAdminPageGenerator<TModel> CreatePermission(string permission);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the permission needed to update an Entry
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="permission">the specified permission</param>
|
||||||
|
/// <returns></returns>
|
||||||
IAdminPageGenerator<TModel> UpdatePermission(string permission);
|
IAdminPageGenerator<TModel> UpdatePermission(string permission);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the permission needed to delete an Entry
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="permission">the specified permission</param>
|
||||||
|
/// <returns></returns>
|
||||||
IAdminPageGenerator<TModel> DeletePermission(string permission);
|
IAdminPageGenerator<TModel> DeletePermission(string permission);
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enables or disables the create button
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="show">the specified state</param>
|
||||||
|
/// <returns></returns>
|
||||||
IAdminPageGenerator<TModel> ShowCreateButton(bool show);
|
IAdminPageGenerator<TModel> ShowCreateButton(bool show);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enables or disables the delete button
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="show">the specified state</param>
|
||||||
|
/// <returns></returns>
|
||||||
IAdminPageGenerator<TModel> ShowDeleteButton(bool show);
|
IAdminPageGenerator<TModel> ShowDeleteButton(bool show);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enables or disables the update button
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="show">the specified state</param>
|
||||||
|
/// <returns></returns>
|
||||||
IAdminPageGenerator<TModel> ShowUpdateButton(bool show);
|
IAdminPageGenerator<TModel> ShowUpdateButton(bool show);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Specifies the default sort property and direction
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="propertyExpression">Which property should be sorted</param>
|
||||||
|
/// <param name="direction">In which direction should be sorted</param>
|
||||||
|
/// <returns></returns>
|
||||||
IAdminPageGenerator<TModel> DefaultSort<TProperty>(Expression<Func<TModel, TProperty>> propertyExpression, ListSortDirection direction);
|
IAdminPageGenerator<TModel> DefaultSort<TProperty>(Expression<Func<TModel, TProperty>> propertyExpression, ListSortDirection direction);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Specifies the repository for the page
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TRepository">The specified repository</typeparam>
|
||||||
|
/// <returns></returns>
|
||||||
IAdminPageGenerator<TModel> ConfigureRepository<TRepository>() where TRepository : ModelRepository<TModel>;
|
IAdminPageGenerator<TModel> ConfigureRepository<TRepository>() where TRepository : ModelRepository<TModel>;
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the generator of the specified property
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="propertyExpression">The property</param>
|
||||||
|
/// <returns></returns>
|
||||||
IAdminPropertyGenerator<TProperty, TModel> Property<TProperty>(Expression<Func<TModel, TProperty>> propertyExpression);
|
IAdminPropertyGenerator<TProperty, TModel> Property<TProperty>(Expression<Func<TModel, TProperty>> propertyExpression);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Specifies the default property that should be displayed as a property in other listings
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="propertyExpression">The property</param>
|
||||||
|
/// <returns></returns>
|
||||||
IAdminPageGenerator<TModel> ListingProperty<TProperty>(Expression<Func<TModel, TProperty>> propertyExpression);
|
IAdminPageGenerator<TModel> ListingProperty<TProperty>(Expression<Func<TModel, TProperty>> propertyExpression);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,25 +4,120 @@ namespace HopFrame.Web.Admin.Generators;
|
|||||||
|
|
||||||
public interface IAdminPropertyGenerator<TProperty, TModel> {
|
public interface IAdminPropertyGenerator<TProperty, TModel> {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Should the property be sortable or not
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
IAdminPropertyGenerator<TProperty, TModel> Sortable(bool sortable);
|
IAdminPropertyGenerator<TProperty, TModel> Sortable(bool sortable);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Should the admin be able to edit the property after creation or not
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
IAdminPropertyGenerator<TProperty, TModel> Editable(bool editable);
|
IAdminPropertyGenerator<TProperty, TModel> Editable(bool editable);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Should the value of the property be displayed while editing or not (useful for passwords and tokens)
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
IAdminPropertyGenerator<TProperty, TModel> DisplayValueWhileEditing(bool display);
|
IAdminPropertyGenerator<TProperty, TModel> DisplayValueWhileEditing(bool display);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Should the property be a column on the page list or not
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
IAdminPropertyGenerator<TProperty, TModel> DisplayInListing(bool display = true);
|
IAdminPropertyGenerator<TProperty, TModel> DisplayInListing(bool display = true);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Should the property be ignored completely
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
IAdminPropertyGenerator<TProperty, TModel> Ignore(bool ignore = true);
|
IAdminPropertyGenerator<TProperty, TModel> Ignore(bool ignore = true);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Is the value of the property database generated and is not meant to be changed
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
IAdminPropertyGenerator<TProperty, TModel> Generated(bool generated = true);
|
IAdminPropertyGenerator<TProperty, TModel> Generated(bool generated = true);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Should the property value be bold in the listing or not
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
IAdminPropertyGenerator<TProperty, TModel> Bold(bool bold = true);
|
IAdminPropertyGenerator<TProperty, TModel> Bold(bool bold = true);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Is the value of the property unique under all other entries in the dataset
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="unique"></param>
|
||||||
|
/// <returns></returns>
|
||||||
IAdminPropertyGenerator<TProperty, TModel> Unique(bool unique = true);
|
IAdminPropertyGenerator<TProperty, TModel> Unique(bool unique = true);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Specifies the display name in the listing and editing/creation
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
IAdminPropertyGenerator<TProperty, TModel> DisplayName(string displayName);
|
IAdminPropertyGenerator<TProperty, TModel> DisplayName(string displayName);
|
||||||
IAdminPropertyGenerator<TProperty, TModel> Description(string description);
|
|
||||||
|
/// <summary>
|
||||||
|
/// Has the value of the property a never changing prefix that doesn't need to be specified or displayed
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
IAdminPropertyGenerator<TProperty, TModel> Prefix(string prefix);
|
IAdminPropertyGenerator<TProperty, TModel> Prefix(string prefix);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The specified function gets called before creation/edit to verify that the entered value matches the property requirements
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
IAdminPropertyGenerator<TProperty, TModel> Validator(Func<TProperty, string> validator);
|
IAdminPropertyGenerator<TProperty, TModel> Validator(Func<TProperty, string> validator);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the input type in creation/edit to a selector for the property type. The property type needs to have its own admin page in order for the selector to work!
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
IAdminPropertyGenerator<TProperty, TModel> IsSelector(bool selector = true);
|
IAdminPropertyGenerator<TProperty, TModel> IsSelector(bool selector = true);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the input type in creation/edit to a selector for the specified type. The specified type needs to have its own admin page in order for the selector to work!
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="selector"></param>
|
||||||
|
/// <typeparam name="TSelectorType"></typeparam>
|
||||||
|
/// <returns></returns>
|
||||||
IAdminPropertyGenerator<TProperty, TModel> IsSelector<TSelectorType>(bool selector = true);
|
IAdminPropertyGenerator<TProperty, TModel> IsSelector<TSelectorType>(bool selector = true);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The specified function gets called, whenever the entry is changed/created in order to convert the raw string input to the proper property type
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
IAdminPropertyGenerator<TProperty, TModel> Parser(Func<TModel, string, TProperty> parser);
|
IAdminPropertyGenerator<TProperty, TModel> Parser(Func<TModel, string, TProperty> parser);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The specified function gets called, whenever the entry is changed/created in order to convert the raw string input to the proper property type
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TInput">Needs to be specified if the field is not a plain string field (like a selector with a different type)</typeparam>
|
||||||
|
/// <returns></returns>
|
||||||
IAdminPropertyGenerator<TProperty, TModel> Parser<TInput>(Func<TModel, TInput, TProperty> parser);
|
IAdminPropertyGenerator<TProperty, TModel> Parser<TInput>(Func<TModel, TInput, TProperty> parser);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The specified function gets called, whenever the entry is changed/created in order to convert the raw string input to the proper property type
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TInput">Needs to be specified if the field is not a plain string field (like a selector with a different type)</typeparam>
|
||||||
|
/// <typeparam name="TInnerProperty">Needs to be specified if the property type is a List</typeparam>
|
||||||
|
/// <returns></returns>
|
||||||
IAdminPropertyGenerator<TProperty, TModel> Parser<TInput, TInnerProperty>(Func<TModel, TInput, TInnerProperty> parser);
|
IAdminPropertyGenerator<TProperty, TModel> Parser<TInput, TInnerProperty>(Func<TModel, TInput, TInnerProperty> parser);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Specifies the default property that should be displayed as a value
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="propertyExpression"></param>
|
||||||
|
/// <returns></returns>
|
||||||
IAdminPropertyGenerator<TProperty, TModel> DisplayProperty(Expression<Func<TProperty, object>> propertyExpression);
|
IAdminPropertyGenerator<TProperty, TModel> DisplayProperty(Expression<Func<TProperty, object>> propertyExpression);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Specifies the default property that should be displayed as a value
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TInnerProperty">Needs to be specified if the property type is a List</typeparam>
|
||||||
|
/// <returns></returns>
|
||||||
IAdminPropertyGenerator<TProperty, TModel> DisplayProperty<TInnerProperty>(Expression<Func<TInnerProperty, object>> propertyExpression);
|
IAdminPropertyGenerator<TProperty, TModel> DisplayProperty<TInnerProperty>(Expression<Func<TInnerProperty, object>> propertyExpression);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,10 @@ namespace HopFrame.Web.Admin.Generators;
|
|||||||
|
|
||||||
public interface IGenerator<out TGeneratedType> {
|
public interface IGenerator<out TGeneratedType> {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Compiles the generator with all specified options
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The compiled data structure</returns>
|
||||||
TGeneratedType Compile();
|
TGeneratedType Compile();
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -61,11 +61,6 @@ internal sealed class AdminPropertyGenerator<TProperty, TModel>(string name, Typ
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IAdminPropertyGenerator<TProperty, TModel> Description(string description) {
|
|
||||||
_property.Description = description;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IAdminPropertyGenerator<TProperty, TModel> Prefix(string prefix) {
|
public IAdminPropertyGenerator<TProperty, TModel> Prefix(string prefix) {
|
||||||
_property.Prefix = prefix;
|
_property.Prefix = prefix;
|
||||||
return this;
|
return this;
|
||||||
@@ -153,11 +148,6 @@ internal sealed class AdminPropertyGenerator<TProperty, TModel>(string name, Typ
|
|||||||
DisplayName(attribute?.Name);
|
DisplayName(attribute?.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attributes.Any(a => a is AdminDescriptionAttribute)) {
|
|
||||||
var attribute = attributes.Single(a => a is AdminDescriptionAttribute) as AdminDescriptionAttribute;
|
|
||||||
Description(attribute?.Description);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (attributes.Any(a => a is AdminBoldAttribute)) {
|
if (attributes.Any(a => a is AdminBoldAttribute)) {
|
||||||
var attribute = attributes.Single(a => a is AdminBoldAttribute) as AdminBoldAttribute;
|
var attribute = attributes.Single(a => a is AdminBoldAttribute) as AdminBoldAttribute;
|
||||||
Bold(attribute?.Bold == true);
|
Bold(attribute?.Bold == true);
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ public class AdminPage {
|
|||||||
public IList<AdminPageProperty> Properties { get; set; }
|
public IList<AdminPageProperty> Properties { get; set; }
|
||||||
public string ListingProperty { get; set; }
|
public string ListingProperty { get; set; }
|
||||||
|
|
||||||
[JsonIgnore]
|
|
||||||
public Type RepositoryProvider { get; set; }
|
public Type RepositoryProvider { get; set; }
|
||||||
|
|
||||||
public Type ModelType { get; set; }
|
public Type ModelType { get; set; }
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ namespace HopFrame.Web.Admin.Models;
|
|||||||
public sealed class AdminPageProperty {
|
public sealed class AdminPageProperty {
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
public string DisplayName { get; set; }
|
public string DisplayName { get; set; }
|
||||||
public string Description { get; set; }
|
|
||||||
public string Prefix { get; set; }
|
public string Prefix { get; set; }
|
||||||
public string DisplayPropertyName { get; set; }
|
public string DisplayPropertyName { get; set; }
|
||||||
|
|
||||||
@@ -21,7 +20,6 @@ public sealed class AdminPageProperty {
|
|||||||
public bool Selector { get; set; }
|
public bool Selector { get; set; }
|
||||||
public Type SelectorType { get; set; }
|
public Type SelectorType { get; set; }
|
||||||
|
|
||||||
[JsonIgnore]
|
|
||||||
public Type Type { get; set; }
|
public Type Type { get; set; }
|
||||||
|
|
||||||
public Func<object, string> Validator { get; set; }
|
public Func<object, string> Validator { get; set; }
|
||||||
|
|||||||
@@ -1,292 +0,0 @@
|
|||||||
@rendermode InteractiveServer
|
|
||||||
|
|
||||||
@using BlazorStrap
|
|
||||||
@using BlazorStrap.Shared.Components.Modal
|
|
||||||
@using static Microsoft.AspNetCore.Components.Web.RenderMode
|
|
||||||
@using BlazorStrap.V5
|
|
||||||
@using CurrieTechnologies.Razor.SweetAlert2
|
|
||||||
@using HopFrame.Database.Models
|
|
||||||
@using HopFrame.Database.Repositories
|
|
||||||
@using HopFrame.Security.Claims
|
|
||||||
@using HopFrame.Web.Model
|
|
||||||
|
|
||||||
<BSModal DataId="add-group-modal" HideOnValidSubmit="true" IsStaticBackdrop="true" @ref="_modal">
|
|
||||||
<BSForm Model="_group" OnValidSubmit="AddGroup">
|
|
||||||
@if (_isEdit) {
|
|
||||||
<BSModalHeader>Edit group</BSModalHeader>
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
<BSModalHeader>Add group</BSModalHeader>
|
|
||||||
}
|
|
||||||
<BSModalContent>
|
|
||||||
<div class="mb-3">
|
|
||||||
<BSLabel>Name</BSLabel>
|
|
||||||
@if (!_isEdit) {
|
|
||||||
<BSInputGroup>
|
|
||||||
<span class="@BS.Input_Group_Text">group.</span>
|
|
||||||
<BSInput InputType="InputType.Text" @bind-Value="_group.GroupName" required/>
|
|
||||||
</BSInputGroup>
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
<input type="text" class="form-control" disabled value="@_group.Name"/>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@if (_isEdit) {
|
|
||||||
<div class="mb-3">
|
|
||||||
<BSLabel>Created at</BSLabel>
|
|
||||||
<input type="text" class="form-control" disabled value="@_group.CreatedAt"/>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
<div class="mb-3">
|
|
||||||
<BSLabel>Description</BSLabel>
|
|
||||||
<BSInput InputType="InputType.TextArea" @bind-Value="_group.Description"/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="mb-3">
|
|
||||||
<BSInputSwitch @bind-Value="_group.IsDefaultGroup" CheckedValue="true" UnCheckedValue="false">
|
|
||||||
Default group
|
|
||||||
</BSInputSwitch>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="mb-3">
|
|
||||||
<BSLabel>Inherits from</BSLabel>
|
|
||||||
<BSListGroup>
|
|
||||||
<BSListGroupItem>
|
|
||||||
<BSListGroup IsFlush="true">
|
|
||||||
@foreach (var group in _group.Permissions.Where(g => g.PermissionName.StartsWith("group."))) {
|
|
||||||
<BSListGroupItem>
|
|
||||||
<BSButton Color="BSColor.Danger" Size="Size.ExtraSmall" MarginEnd="Margins.Small" OnClick="() => RemovePermission(group)">
|
|
||||||
<HopIconDisplay Type="HopIconDisplay.HopIcon.Cross"/>
|
|
||||||
</BSButton>
|
|
||||||
|
|
||||||
<span>@group.PermissionName.Replace("group.", "")</span>
|
|
||||||
</BSListGroupItem>
|
|
||||||
}
|
|
||||||
</BSListGroup>
|
|
||||||
</BSListGroupItem>
|
|
||||||
<BSListGroupItem>
|
|
||||||
<div style="display: flex; gap: 20px">
|
|
||||||
<BSInput InputType="InputType.Select" @bind-Value="_groupToAdd">
|
|
||||||
<option selected>Select group</option>
|
|
||||||
|
|
||||||
@foreach (var group in _allGroups) {
|
|
||||||
@if (_group.Permissions.All(g => g.PermissionName != group.Name) && group.Name != _group.Name) {
|
|
||||||
<option value="@group.Name">@group.Name.Replace("group.", "")</option>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</BSInput>
|
|
||||||
<BSButton Color="BSColor.Secondary" OnClick="AddInheritanceGroup">Add</BSButton>
|
|
||||||
</div>
|
|
||||||
</BSListGroupItem>
|
|
||||||
</BSListGroup>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="mb-3">
|
|
||||||
<BSLabel>Permissions</BSLabel>
|
|
||||||
<BSListGroup>
|
|
||||||
<BSListGroupItem>
|
|
||||||
<BSListGroup IsFlush="true">
|
|
||||||
@foreach (var perm in _group.Permissions.Where(perm => !perm.PermissionName.StartsWith("group."))) {
|
|
||||||
<BSListGroupItem>
|
|
||||||
<BSButton Color="BSColor.Danger" Size="Size.ExtraSmall" MarginEnd="Margins.Small" OnClick="() => RemovePermission(perm)">
|
|
||||||
<HopIconDisplay Type="HopIconDisplay.HopIcon.Cross"/>
|
|
||||||
</BSButton>
|
|
||||||
|
|
||||||
<span>@perm.PermissionName</span>
|
|
||||||
</BSListGroupItem>
|
|
||||||
}
|
|
||||||
</BSListGroup>
|
|
||||||
</BSListGroupItem>
|
|
||||||
<BSListGroupItem>
|
|
||||||
<div style="display: flex; gap: 20px">
|
|
||||||
<BSInput InputType="InputType.Text" @bind-Value="_permissionToAdd"/>
|
|
||||||
<BSButton Color="BSColor.Secondary" OnClick="AddPermission">Add</BSButton>
|
|
||||||
</div>
|
|
||||||
</BSListGroupItem>
|
|
||||||
</BSListGroup>
|
|
||||||
</div>
|
|
||||||
</BSModalContent>
|
|
||||||
<BSModalFooter>
|
|
||||||
<BSButton Target="add-group-modal">Cancel</BSButton>
|
|
||||||
<BSButton IsSubmit="true" Color="BSColor.Primary">Save</BSButton>
|
|
||||||
</BSModalFooter>
|
|
||||||
</BSForm>
|
|
||||||
</BSModal>
|
|
||||||
|
|
||||||
@inject IGroupRepository Groups
|
|
||||||
@inject IPermissionRepository Permissions
|
|
||||||
@inject SweetAlertService Alerts
|
|
||||||
@inject ITokenContext Context
|
|
||||||
|
|
||||||
@code {
|
|
||||||
[Parameter] public Func<Task> ReloadPage { get; set; }
|
|
||||||
|
|
||||||
private PermissionGroupAdd _group;
|
|
||||||
|
|
||||||
private BSModalBase _modal;
|
|
||||||
private string _permissionToAdd;
|
|
||||||
private string _groupToAdd;
|
|
||||||
|
|
||||||
private IList<PermissionGroup> _allGroups;
|
|
||||||
|
|
||||||
private bool _isEdit;
|
|
||||||
|
|
||||||
public async Task ShowAsync(PermissionGroup group = null) {
|
|
||||||
_allGroups = await Groups.GetPermissionGroups();
|
|
||||||
|
|
||||||
if (group is not null) {
|
|
||||||
_group = new PermissionGroupAdd {
|
|
||||||
CreatedAt = group.CreatedAt,
|
|
||||||
Description = group.Description,
|
|
||||||
Name = group.Name,
|
|
||||||
IsDefaultGroup = group.IsDefaultGroup,
|
|
||||||
Permissions = group.Permissions
|
|
||||||
};
|
|
||||||
_isEdit = true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
_group = new PermissionGroupAdd {
|
|
||||||
Permissions = new List<Permission>(),
|
|
||||||
IsDefaultGroup = false
|
|
||||||
};
|
|
||||||
_isEdit = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
await _modal.ShowAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task AddPermission() {
|
|
||||||
if (string.IsNullOrWhiteSpace(_permissionToAdd)) {
|
|
||||||
await Alerts.FireAsync(new SweetAlertOptions {
|
|
||||||
Title = "Enter a permission name!",
|
|
||||||
Icon = SweetAlertIcon.Error,
|
|
||||||
ShowConfirmButton = true
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_isEdit) {
|
|
||||||
if (!await Permissions.HasPermission(Context.User, Security.AdminPermissions.EditGroup)) {
|
|
||||||
await NoEditPermissions();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await Permissions.AddPermission(_group, _permissionToAdd);
|
|
||||||
}
|
|
||||||
|
|
||||||
_group.Permissions.Add(new Permission {
|
|
||||||
PermissionName = _permissionToAdd,
|
|
||||||
GrantedAt = DateTime.Now
|
|
||||||
});
|
|
||||||
|
|
||||||
_permissionToAdd = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task RemovePermission(Permission permission) {
|
|
||||||
if (_isEdit) {
|
|
||||||
await Permissions.RemovePermission(_group, permission.PermissionName);
|
|
||||||
}
|
|
||||||
|
|
||||||
_group.Permissions.Remove(permission);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task AddInheritanceGroup() {
|
|
||||||
if (string.IsNullOrWhiteSpace(_groupToAdd)) {
|
|
||||||
await Alerts.FireAsync(new SweetAlertOptions {
|
|
||||||
Title = "Select a group!",
|
|
||||||
Icon = SweetAlertIcon.Error,
|
|
||||||
ShowConfirmButton = true
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_isEdit) {
|
|
||||||
if (!await Permissions.HasPermission(Context.User, Security.AdminPermissions.EditGroup)) {
|
|
||||||
await NoEditPermissions();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await Permissions.AddPermission(_group, _groupToAdd);
|
|
||||||
}
|
|
||||||
|
|
||||||
_group.Permissions.Add(new Permission {
|
|
||||||
PermissionName = _groupToAdd
|
|
||||||
});
|
|
||||||
|
|
||||||
_groupToAdd = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task AddGroup() {
|
|
||||||
if (_isEdit) {
|
|
||||||
if (!await Permissions.HasPermission(Context.User, Security.AdminPermissions.EditGroup)) {
|
|
||||||
await NoEditPermissions();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await Groups.EditPermissionGroup(_group);
|
|
||||||
|
|
||||||
if (ReloadPage is not null)
|
|
||||||
await ReloadPage.Invoke();
|
|
||||||
|
|
||||||
await Alerts.FireAsync(new SweetAlertOptions {
|
|
||||||
Title = "Group edited!",
|
|
||||||
Icon = SweetAlertIcon.Success,
|
|
||||||
Timer = 1500,
|
|
||||||
ShowConfirmButton = false
|
|
||||||
});
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!await Permissions.HasPermission(Context.User, Security.AdminPermissions.AddGroup)) {
|
|
||||||
await NoAddPermissions();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_allGroups.Any(group => group.Name == _group.Name)) {
|
|
||||||
await Alerts.FireAsync(new SweetAlertOptions {
|
|
||||||
Title = "Something went wrong!",
|
|
||||||
Text = "This group already exists!",
|
|
||||||
Icon = SweetAlertIcon.Error,
|
|
||||||
ShowConfirmButton = false,
|
|
||||||
Timer = 1500
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await Groups.CreatePermissionGroup(new PermissionGroup {
|
|
||||||
Description = _group.Description,
|
|
||||||
IsDefaultGroup = _group.IsDefaultGroup,
|
|
||||||
Permissions = _group.Permissions,
|
|
||||||
Name = "group." + _group.GroupName
|
|
||||||
});
|
|
||||||
|
|
||||||
if (ReloadPage is not null)
|
|
||||||
await ReloadPage.Invoke();
|
|
||||||
|
|
||||||
await Alerts.FireAsync(new SweetAlertOptions {
|
|
||||||
Title = "Group added!",
|
|
||||||
Icon = SweetAlertIcon.Success,
|
|
||||||
Timer = 1500,
|
|
||||||
ShowConfirmButton = false
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task NoEditPermissions() {
|
|
||||||
await Alerts.FireAsync(new SweetAlertOptions {
|
|
||||||
Title = "Unauthorized!",
|
|
||||||
Text = "You don't have the required permissions to edit a group!",
|
|
||||||
Icon = SweetAlertIcon.Error
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task NoAddPermissions() {
|
|
||||||
await Alerts.FireAsync(new SweetAlertOptions {
|
|
||||||
Title = "Unauthorized!",
|
|
||||||
Text = "You don't have the required permissions to add a group!",
|
|
||||||
Icon = SweetAlertIcon.Error
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,136 +0,0 @@
|
|||||||
@rendermode InteractiveServer
|
|
||||||
|
|
||||||
@using BlazorStrap
|
|
||||||
@using static Microsoft.AspNetCore.Components.Web.RenderMode
|
|
||||||
@using BlazorStrap.Shared.Components.Modal
|
|
||||||
@using BlazorStrap.V5
|
|
||||||
@using CurrieTechnologies.Razor.SweetAlert2
|
|
||||||
@using HopFrame.Database.Models
|
|
||||||
@using HopFrame.Database.Repositories
|
|
||||||
@using HopFrame.Security.Claims
|
|
||||||
@using HopFrame.Web.Model
|
|
||||||
|
|
||||||
<BSModal DataId="add-user-modal" HideOnValidSubmit="true" IsStaticBackdrop="true" OnShow="() => _user = new()" @ref="_modal">
|
|
||||||
<BSForm Model="_user" OnValidSubmit="AddUser">
|
|
||||||
<BSModalHeader>Add user</BSModalHeader>
|
|
||||||
<BSModalContent>
|
|
||||||
<div class="mb-3">
|
|
||||||
<BSLabel>E-Mail</BSLabel>
|
|
||||||
<BSInput InputType="InputType.Email" @bind-Value="_user.Email" required/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="mb-3">
|
|
||||||
<BSLabel>Username</BSLabel>
|
|
||||||
<BSInput InputType="InputType.Text" @bind-Value="_user.Username" required/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="mb-3">
|
|
||||||
<BSLabel>Password</BSLabel>
|
|
||||||
<BSInput InputType="InputType.Password" @bind-Value="_user.Password" required/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="mb-3">
|
|
||||||
<BSLabel>Primary group</BSLabel>
|
|
||||||
<BSInput InputType="InputType.Select" @bind-Value="_user.Group">
|
|
||||||
<option value="">Select group</option>
|
|
||||||
|
|
||||||
@foreach (var group in _allGroups) {
|
|
||||||
<option value="@group.Name">@group.Name.Replace("group.", "")</option>
|
|
||||||
}
|
|
||||||
</BSInput>
|
|
||||||
</div>
|
|
||||||
</BSModalContent>
|
|
||||||
<BSModalFooter>
|
|
||||||
<BSButton Target="add-user-modal">Cancel</BSButton>
|
|
||||||
<BSButton IsSubmit="true" Color="BSColor.Primary">Save</BSButton>
|
|
||||||
</BSModalFooter>
|
|
||||||
</BSForm>
|
|
||||||
</BSModal>
|
|
||||||
|
|
||||||
@inject IUserRepository Users
|
|
||||||
@inject IPermissionRepository Permissions
|
|
||||||
@inject IGroupRepository Groups
|
|
||||||
@inject SweetAlertService Alerts
|
|
||||||
@inject ITokenContext Auth
|
|
||||||
|
|
||||||
@code {
|
|
||||||
[Parameter] public Func<Task> ReloadPage { get; set; }
|
|
||||||
|
|
||||||
private IList<PermissionGroup> _allGroups = new List<PermissionGroup>();
|
|
||||||
private IList<User> _allUsers = new List<User>();
|
|
||||||
private UserAdd _user;
|
|
||||||
|
|
||||||
private BSModalBase _modal;
|
|
||||||
|
|
||||||
public async Task ShowAsync() {
|
|
||||||
_allGroups = await Groups.GetPermissionGroups();
|
|
||||||
_allUsers = await Users.GetUsers();
|
|
||||||
|
|
||||||
await _modal.ShowAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task AddUser() {
|
|
||||||
if (!(await Permissions.HasPermission(Auth.User, Security.AdminPermissions.AddUser))) {
|
|
||||||
await NoAddPermissions();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
string errorMessage = null;
|
|
||||||
|
|
||||||
if (_allUsers.Any(user => user.Username == _user.Username)) {
|
|
||||||
errorMessage = "Username is already taken!";
|
|
||||||
}
|
|
||||||
else if (_allUsers.Any(user => user.Email == _user.Email)) {
|
|
||||||
errorMessage = "E-Mail is already taken!";
|
|
||||||
}
|
|
||||||
else if (!_user.PasswordIsValid) {
|
|
||||||
errorMessage = "The password needs to be at least 8 characters long!";
|
|
||||||
}
|
|
||||||
else if (!_user.EmailIsValid) {
|
|
||||||
errorMessage = "Invalid E-Mail address!";
|
|
||||||
}
|
|
||||||
else if (string.IsNullOrWhiteSpace(_user.Username)) {
|
|
||||||
errorMessage = "You need to set a username!";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(errorMessage)) {
|
|
||||||
await Alerts.FireAsync(new SweetAlertOptions {
|
|
||||||
Title = "Something went wrong!",
|
|
||||||
Text = errorMessage,
|
|
||||||
Icon = SweetAlertIcon.Error,
|
|
||||||
ShowConfirmButton = false,
|
|
||||||
Timer = 1500
|
|
||||||
});
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var user = await Users.AddUser(new User {
|
|
||||||
Username = _user.Username,
|
|
||||||
Email = _user.Email,
|
|
||||||
Password = _user.Password
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(_user.Group)) {
|
|
||||||
await Permissions.AddPermission(user, _user.Group);
|
|
||||||
}
|
|
||||||
|
|
||||||
await ReloadPage.Invoke();
|
|
||||||
|
|
||||||
await Alerts.FireAsync(new SweetAlertOptions {
|
|
||||||
Title = "New user added!",
|
|
||||||
Icon = SweetAlertIcon.Success,
|
|
||||||
ShowConfirmButton = false,
|
|
||||||
Timer = 1500
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task NoAddPermissions() {
|
|
||||||
await Alerts.FireAsync(new SweetAlertOptions {
|
|
||||||
Title = "Unauthorized!",
|
|
||||||
Text = "You don't have the required permissions to add a user!",
|
|
||||||
Icon = SweetAlertIcon.Error
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,306 +0,0 @@
|
|||||||
@rendermode InteractiveServer
|
|
||||||
|
|
||||||
@using BlazorStrap
|
|
||||||
@using BlazorStrap.Shared.Components.Modal
|
|
||||||
@using static Microsoft.AspNetCore.Components.Web.RenderMode
|
|
||||||
@using BlazorStrap.V5
|
|
||||||
@using CurrieTechnologies.Razor.SweetAlert2
|
|
||||||
@using HopFrame.Database.Models
|
|
||||||
@using HopFrame.Database.Repositories
|
|
||||||
@using HopFrame.Security.Claims
|
|
||||||
@using HopFrame.Web.Model
|
|
||||||
|
|
||||||
<BSModal DataId="edit-user-modal" HideOnValidSubmit="true" IsStaticBackdrop="true" @ref="_modal">
|
|
||||||
<BSForm Model="_user" OnValidSubmit="EditUser">
|
|
||||||
<BSModalHeader>Edit @_user.Username</BSModalHeader>
|
|
||||||
<BSModalContent>
|
|
||||||
<div class="mb-3">
|
|
||||||
<BSLabel>User id</BSLabel>
|
|
||||||
<input type="text" class="form-control" disabled value="@_user.Id"/>
|
|
||||||
</div>
|
|
||||||
<div class="mb-3">
|
|
||||||
<BSLabel>Created at</BSLabel>
|
|
||||||
<input type="text" class="form-control" disabled value="@_user.CreatedAt"/>
|
|
||||||
</div>
|
|
||||||
<div class="mb-3">
|
|
||||||
<BSLabel>E-Mail</BSLabel>
|
|
||||||
<BSInput InputType="InputType.Email" @bind-Value="_user.Email" required/>
|
|
||||||
</div>
|
|
||||||
<div class="mb-3">
|
|
||||||
<BSLabel>Username</BSLabel>
|
|
||||||
<BSInput InputType="InputType.Text" @bind-Value="_user.Username" required/>
|
|
||||||
</div>
|
|
||||||
<div class="mb-3">
|
|
||||||
<BSLabel>Password</BSLabel>
|
|
||||||
<BSInput InputType="InputType.Password" @bind-Value="_newPassword"/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="mb-3">
|
|
||||||
<BSLabel>Groups</BSLabel>
|
|
||||||
<BSListGroup>
|
|
||||||
<BSListGroupItem>
|
|
||||||
<BSListGroup IsFlush="true">
|
|
||||||
@foreach (var group in _userGroups) {
|
|
||||||
<BSListGroupItem>
|
|
||||||
<BSButton Color="BSColor.Danger" Size="Size.ExtraSmall" MarginEnd="Margins.Small" OnClick="() => RemoveGroup(group)">
|
|
||||||
<HopIconDisplay Type="HopIconDisplay.HopIcon.Cross"/>
|
|
||||||
</BSButton>
|
|
||||||
|
|
||||||
<span>@group.Name.Replace("group.", "")</span>
|
|
||||||
</BSListGroupItem>
|
|
||||||
}
|
|
||||||
</BSListGroup>
|
|
||||||
</BSListGroupItem>
|
|
||||||
<BSListGroupItem>
|
|
||||||
<div style="display: flex; gap: 20px">
|
|
||||||
<BSInput InputType="InputType.Select" @bind-Value="_selectedGroup">
|
|
||||||
<option selected>Select group</option>
|
|
||||||
|
|
||||||
@foreach (var group in _allGroups) {
|
|
||||||
@if (_userGroups?.All(g => g.Name != group.Name) == true) {
|
|
||||||
<option value="@group.Name">@group.Name.Replace("group.", "")</option>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</BSInput>
|
|
||||||
<BSButton Color="BSColor.Secondary" OnClick="AddGroup">Add</BSButton>
|
|
||||||
</div>
|
|
||||||
</BSListGroupItem>
|
|
||||||
</BSListGroup>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="mb-3">
|
|
||||||
<BSLabel>Permissions</BSLabel>
|
|
||||||
<BSListGroup>
|
|
||||||
<BSListGroupItem>
|
|
||||||
<BSListGroup IsFlush="true">
|
|
||||||
@foreach (var perm in _user.Permissions.Where(perm => !perm.PermissionName.StartsWith("group."))) {
|
|
||||||
<BSListGroupItem>
|
|
||||||
<BSButton Color="BSColor.Danger" Size="Size.ExtraSmall" MarginEnd="Margins.Small" OnClick="() => RemovePermission(perm)">
|
|
||||||
<HopIconDisplay Type="HopIconDisplay.HopIcon.Cross"/>
|
|
||||||
</BSButton>
|
|
||||||
|
|
||||||
<span>@perm.PermissionName</span>
|
|
||||||
</BSListGroupItem>
|
|
||||||
}
|
|
||||||
</BSListGroup>
|
|
||||||
</BSListGroupItem>
|
|
||||||
<BSListGroupItem>
|
|
||||||
<div style="display: flex; gap: 20px">
|
|
||||||
<BSInput InputType="InputType.Text" @bind-Value="_permissionToAdd"/>
|
|
||||||
<BSButton Color="BSColor.Secondary" OnClick="AddPermission">Add</BSButton>
|
|
||||||
</div>
|
|
||||||
</BSListGroupItem>
|
|
||||||
</BSListGroup>
|
|
||||||
</div>
|
|
||||||
</BSModalContent>
|
|
||||||
<BSModalFooter>
|
|
||||||
<BSButton Target="edit-user-modal">Cancel</BSButton>
|
|
||||||
<BSButton IsSubmit="true" Color="BSColor.Primary">Save</BSButton>
|
|
||||||
</BSModalFooter>
|
|
||||||
</BSForm>
|
|
||||||
</BSModal>
|
|
||||||
|
|
||||||
@inject IUserRepository Users
|
|
||||||
@inject IPermissionRepository Permissions
|
|
||||||
@inject IGroupRepository Groups
|
|
||||||
@inject SweetAlertService Alerts
|
|
||||||
@inject ITokenContext Auth
|
|
||||||
|
|
||||||
@code {
|
|
||||||
[Parameter] public Func<Task> ReloadPage { get; set; }
|
|
||||||
|
|
||||||
private BSModalBase _modal;
|
|
||||||
private User _user;
|
|
||||||
private string _newPassword;
|
|
||||||
|
|
||||||
private IList<PermissionGroup> _userGroups;
|
|
||||||
private IList<PermissionGroup> _allGroups;
|
|
||||||
private string _selectedGroup;
|
|
||||||
private string _permissionToAdd;
|
|
||||||
|
|
||||||
public async Task ShowAsync(User user) {
|
|
||||||
if (!await Permissions.HasPermission(Auth.User, Security.AdminPermissions.EditUser)) {
|
|
||||||
await NoEditPermissions();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_user = user;
|
|
||||||
_userGroups = await Groups.GetUserGroups(user);
|
|
||||||
_allGroups = await Groups.GetPermissionGroups();
|
|
||||||
await _modal.ShowAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task AddGroup() {
|
|
||||||
if (!await Permissions.HasPermission(Auth.User, Security.AdminPermissions.EditUser)) {
|
|
||||||
await NoEditPermissions();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(_selectedGroup)) {
|
|
||||||
await Alerts.FireAsync(new SweetAlertOptions {
|
|
||||||
Title = "Select a group!",
|
|
||||||
Icon = SweetAlertIcon.Error,
|
|
||||||
ShowConfirmButton = true
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var group = _allGroups.SingleOrDefault(group => group.Name == _selectedGroup);
|
|
||||||
|
|
||||||
await Permissions.AddPermission(_user, group?.Name);
|
|
||||||
_userGroups.Add(group);
|
|
||||||
|
|
||||||
await Alerts.FireAsync(new SweetAlertOptions {
|
|
||||||
Title = "Group added!",
|
|
||||||
Icon = SweetAlertIcon.Success,
|
|
||||||
Timer = 1500,
|
|
||||||
ShowConfirmButton = false
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task RemoveGroup(PermissionGroup group) {
|
|
||||||
if (!await Permissions.HasPermission(Auth.User, Security.AdminPermissions.EditUser)) {
|
|
||||||
await NoEditPermissions();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var result = await Alerts.FireAsync(new SweetAlertOptions {
|
|
||||||
Title = "Are you sure?",
|
|
||||||
Icon = SweetAlertIcon.Warning,
|
|
||||||
ConfirmButtonText = "Yes",
|
|
||||||
ShowCancelButton = true,
|
|
||||||
ShowConfirmButton = true
|
|
||||||
});
|
|
||||||
|
|
||||||
if (result.IsConfirmed) {
|
|
||||||
await Permissions.RemovePermission(_user, group.Name);
|
|
||||||
_userGroups.Remove(group);
|
|
||||||
StateHasChanged();
|
|
||||||
|
|
||||||
await Alerts.FireAsync(new SweetAlertOptions {
|
|
||||||
Title = "Group removed!",
|
|
||||||
Icon = SweetAlertIcon.Success,
|
|
||||||
Timer = 1500,
|
|
||||||
ShowConfirmButton = false
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task AddPermission() {
|
|
||||||
if (!await Permissions.HasPermission(Auth.User, Security.AdminPermissions.EditUser)) {
|
|
||||||
await NoEditPermissions();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(_permissionToAdd)) {
|
|
||||||
await Alerts.FireAsync(new SweetAlertOptions {
|
|
||||||
Title = "Enter a permission name!",
|
|
||||||
Icon = SweetAlertIcon.Error,
|
|
||||||
ShowConfirmButton = true
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_user.Permissions.Add(await Permissions.AddPermission(_user, _permissionToAdd));
|
|
||||||
_permissionToAdd = "";
|
|
||||||
|
|
||||||
await Alerts.FireAsync(new SweetAlertOptions {
|
|
||||||
Title = "Permission added!",
|
|
||||||
Icon = SweetAlertIcon.Success,
|
|
||||||
Timer = 1500,
|
|
||||||
ShowConfirmButton = false
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task RemovePermission(Permission perm) {
|
|
||||||
if (!await Permissions.HasPermission(Auth.User, Security.AdminPermissions.EditUser)) {
|
|
||||||
await NoEditPermissions();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var result = await Alerts.FireAsync(new SweetAlertOptions {
|
|
||||||
Title = "Are you sure?",
|
|
||||||
Icon = SweetAlertIcon.Warning,
|
|
||||||
ConfirmButtonText = "Yes",
|
|
||||||
ShowCancelButton = true,
|
|
||||||
ShowConfirmButton = true
|
|
||||||
});
|
|
||||||
|
|
||||||
if (result.IsConfirmed) {
|
|
||||||
await Permissions.RemovePermission(perm.User, perm.PermissionName);
|
|
||||||
_user.Permissions.Remove(perm);
|
|
||||||
StateHasChanged();
|
|
||||||
|
|
||||||
await Alerts.FireAsync(new SweetAlertOptions {
|
|
||||||
Title = "Permission removed!",
|
|
||||||
Icon = SweetAlertIcon.Success,
|
|
||||||
Timer = 1500,
|
|
||||||
ShowConfirmButton = false
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void EditUser() {
|
|
||||||
if (!await Permissions.HasPermission(Auth.User, Security.AdminPermissions.EditUser)) {
|
|
||||||
await NoEditPermissions();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
string errorMessage = null;
|
|
||||||
var validator = new RegisterData {
|
|
||||||
Password = _newPassword,
|
|
||||||
Email = _user.Email
|
|
||||||
};
|
|
||||||
|
|
||||||
var allUsers = await Users.GetUsers();
|
|
||||||
|
|
||||||
if (allUsers.Any(user => user.Username == _user.Username && user.Id != _user.Id)) {
|
|
||||||
errorMessage = "Username is already taken!";
|
|
||||||
}
|
|
||||||
else if (allUsers.Any(user => user.Email == _user.Email && user.Id != _user.Id)) {
|
|
||||||
errorMessage = "E-Mail is already taken!";
|
|
||||||
}
|
|
||||||
else if (!string.IsNullOrWhiteSpace(_newPassword) && !validator.PasswordIsValid) {
|
|
||||||
errorMessage = "The password needs to be at least 8 characters long!";
|
|
||||||
}
|
|
||||||
else if (!validator.EmailIsValid) {
|
|
||||||
errorMessage = "Invalid E-Mail address!";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(errorMessage)) {
|
|
||||||
await Alerts.FireAsync(new SweetAlertOptions {
|
|
||||||
Title = "Something went wrong!",
|
|
||||||
Text = errorMessage,
|
|
||||||
Icon = SweetAlertIcon.Error,
|
|
||||||
ShowConfirmButton = false,
|
|
||||||
Timer = 1500
|
|
||||||
});
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await Users.UpdateUser(_user);
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(_newPassword)) {
|
|
||||||
await Users.ChangePassword(_user, _newPassword);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ReloadPage is not null)
|
|
||||||
await ReloadPage.Invoke();
|
|
||||||
|
|
||||||
await Alerts.FireAsync(new SweetAlertOptions {
|
|
||||||
Title = "User edited!",
|
|
||||||
Icon = SweetAlertIcon.Success,
|
|
||||||
Timer = 1500,
|
|
||||||
ShowConfirmButton = false
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task NoEditPermissions() {
|
|
||||||
await Alerts.FireAsync(new SweetAlertOptions {
|
|
||||||
Title = "Unauthorized!",
|
|
||||||
Text = "You don't have the required permissions to edit a user!",
|
|
||||||
Icon = SweetAlertIcon.Error
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
namespace HopFrame.Web.Model;
|
|
||||||
|
|
||||||
public sealed class NavigationItem {
|
|
||||||
public string Name { get; set; }
|
|
||||||
public string Url { get; set; }
|
|
||||||
public string Permission { get; set; }
|
|
||||||
public string Description { get; set; }
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
using HopFrame.Database.Models;
|
|
||||||
|
|
||||||
namespace HopFrame.Web.Model;
|
|
||||||
|
|
||||||
internal sealed class PermissionGroupAdd : PermissionGroup {
|
|
||||||
public string GroupName { get; set; }
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
using HopFrame.Security.Models;
|
|
||||||
|
|
||||||
namespace HopFrame.Web.Model;
|
|
||||||
|
|
||||||
internal class RegisterData : UserRegister {
|
|
||||||
public string RepeatedPassword { get; set; }
|
|
||||||
|
|
||||||
public bool PasswordsMatch => Password == RepeatedPassword;
|
|
||||||
public bool PasswordIsValid => Password?.Length >= 8;
|
|
||||||
public bool EmailIsValid => Email?.Contains('@') == true && Email?.Contains('.') == true && Email?.EndsWith('.') == false;
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
namespace HopFrame.Web.Model;
|
|
||||||
|
|
||||||
internal sealed class UserAdd : RegisterData {
|
|
||||||
public string Group { get; set; }
|
|
||||||
}
|
|
||||||
@@ -1,192 +0,0 @@
|
|||||||
@page "/administration/group"
|
|
||||||
@rendermode InteractiveServer
|
|
||||||
@layout AdminLayout
|
|
||||||
|
|
||||||
@using System.Globalization
|
|
||||||
@using static Microsoft.AspNetCore.Components.Web.RenderMode
|
|
||||||
@using BlazorStrap
|
|
||||||
@using Microsoft.AspNetCore.Components.Web
|
|
||||||
@using HopFrame.Web.Components
|
|
||||||
@using HopFrame.Web.Components.Administration
|
|
||||||
@using BlazorStrap.V5
|
|
||||||
@using CurrieTechnologies.Razor.SweetAlert2
|
|
||||||
@using HopFrame.Database.Models
|
|
||||||
@using HopFrame.Database.Repositories
|
|
||||||
@using HopFrame.Security.Claims
|
|
||||||
@using HopFrame.Web.Pages.Administration.Layout
|
|
||||||
|
|
||||||
<PageTitle>Groups</PageTitle>
|
|
||||||
<AuthorizedView Permission="@Security.AdminPermissions.ViewGroups" RedirectIfUnauthorized="administration/login?redirect=/administration/groups"/>
|
|
||||||
|
|
||||||
<GroupAddModal ReloadPage="Reload" @ref="_groupAddModal"/>
|
|
||||||
|
|
||||||
<div class="title">
|
|
||||||
<h3>
|
|
||||||
Groups administration
|
|
||||||
<span class="reload" @onclick="Reload">
|
|
||||||
<HopIconDisplay Type="HopIconDisplay.HopIcon.Reload"/>
|
|
||||||
</span>
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<form class="d-flex" role="search" id="search" @onsubmit="Search">
|
|
||||||
<input class="form-control me-2 input-dark" type="search" placeholder="Search" aria-label="Search" @bind="_searchText">
|
|
||||||
<BSButton Color="BSColor.Success" IsOutlined="true" type="submit">Search</BSButton>
|
|
||||||
</form>
|
|
||||||
<AuthorizedView Permission="@Security.AdminPermissions.AddGroup">
|
|
||||||
<BSButton IsSubmit="false" Color="BSColor.Success" Target="add-user" OnClick="() => _groupAddModal.ShowAsync()">Add Group</BSButton>
|
|
||||||
</AuthorizedView>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<BSTable IsStriped="true" IsHoverable="true" IsDark="true" Color="BSColor.Dark">
|
|
||||||
<BSTHead>
|
|
||||||
<BSTR>
|
|
||||||
<BSTD>
|
|
||||||
<span class="sorter" @onclick="() => OrderBy(OrderType.Name)">Name</span>
|
|
||||||
@if (_currentOrder == OrderType.Name) {
|
|
||||||
<HopIconDisplay Type="_currentOrderDirection == OrderDirection.Desc ? HopIconDisplay.HopIcon.ArrowDown : HopIconDisplay.HopIcon.ArrowUp"/>
|
|
||||||
}
|
|
||||||
</BSTD>
|
|
||||||
<BSTD>Description</BSTD>
|
|
||||||
<BSTD>Default</BSTD>
|
|
||||||
<BSTD>
|
|
||||||
<span class="sorter" @onclick="() => OrderBy(OrderType.Created)">Created</span>
|
|
||||||
@if (_currentOrder == OrderType.Created) {
|
|
||||||
<HopIconDisplay Type="_currentOrderDirection == OrderDirection.Desc ? HopIconDisplay.HopIcon.ArrowDown : HopIconDisplay.HopIcon.ArrowUp"/>
|
|
||||||
}
|
|
||||||
</BSTD>
|
|
||||||
|
|
||||||
@if (_hasEditPrivileges || _hasDeletePrivileges) {
|
|
||||||
<BSTD>Actions</BSTD>
|
|
||||||
}
|
|
||||||
</BSTR>
|
|
||||||
</BSTHead>
|
|
||||||
|
|
||||||
<BSTBody>
|
|
||||||
@foreach (var group in _groups) {
|
|
||||||
<BSTR>
|
|
||||||
<BSTD Class="bold">@group.Name.Replace("group.", "")</BSTD>
|
|
||||||
<BSTD>@group.Description</BSTD>
|
|
||||||
<BSTD>
|
|
||||||
@if (group.IsDefaultGroup) {
|
|
||||||
<span>Yes</span>
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
<span>No</span>
|
|
||||||
}
|
|
||||||
</BSTD>
|
|
||||||
<BSTD>@group.CreatedAt</BSTD>
|
|
||||||
|
|
||||||
@if (_hasEditPrivileges || _hasDeletePrivileges) {
|
|
||||||
<BSTD>
|
|
||||||
<BSButtonGroup>
|
|
||||||
@if (_hasEditPrivileges) {
|
|
||||||
<BSButton Color="BSColor.Warning" OnClick="() => _groupAddModal.ShowAsync(group)">Edit</BSButton>
|
|
||||||
}
|
|
||||||
|
|
||||||
@if (_hasDeletePrivileges) {
|
|
||||||
<BSButton Color="BSColor.Danger" OnClick="() => Delete(group)">Delete</BSButton>
|
|
||||||
}
|
|
||||||
</BSButtonGroup>
|
|
||||||
</BSTD>
|
|
||||||
}
|
|
||||||
</BSTR>
|
|
||||||
}
|
|
||||||
</BSTBody>
|
|
||||||
</BSTable>
|
|
||||||
|
|
||||||
@inject IGroupRepository Groups
|
|
||||||
@inject IPermissionRepository Permissions
|
|
||||||
@inject ITokenContext Auth
|
|
||||||
@inject SweetAlertService Alerts
|
|
||||||
|
|
||||||
@code {
|
|
||||||
private IList<PermissionGroup> _groups = new List<PermissionGroup>();
|
|
||||||
|
|
||||||
private bool _hasEditPrivileges = false;
|
|
||||||
private bool _hasDeletePrivileges = false;
|
|
||||||
private string _searchText;
|
|
||||||
private OrderType _currentOrder = OrderType.None;
|
|
||||||
private OrderDirection _currentOrderDirection = OrderDirection.Asc;
|
|
||||||
|
|
||||||
private GroupAddModal _groupAddModal;
|
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync() {
|
|
||||||
_groups = await Groups.GetPermissionGroups();
|
|
||||||
|
|
||||||
_hasEditPrivileges = await Permissions.HasPermission(Auth.User, Security.AdminPermissions.EditGroup);
|
|
||||||
_hasDeletePrivileges = await Permissions.HasPermission(Auth.User, Security.AdminPermissions.DeleteGroup);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task Reload() {
|
|
||||||
_groups = new List<PermissionGroup>();
|
|
||||||
|
|
||||||
_groups = await Groups.GetPermissionGroups();
|
|
||||||
|
|
||||||
OrderBy(_currentOrder, false);
|
|
||||||
StateHasChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task Search() {
|
|
||||||
var groups = await Groups.GetPermissionGroups();
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(_searchText)) {
|
|
||||||
groups = groups
|
|
||||||
.Where(group => group.Name.Contains(_searchText) ||
|
|
||||||
group.Description?.Contains(_searchText) == true ||
|
|
||||||
group.CreatedAt.ToString(CultureInfo.InvariantCulture).Contains(_searchText) ||
|
|
||||||
group.Permissions.Any(perm => perm.PermissionName.Contains(_searchText)))
|
|
||||||
.ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
_groups = groups;
|
|
||||||
OrderBy(_currentOrder, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OrderBy(OrderType type, bool changeDir = true) {
|
|
||||||
if (_currentOrder == type && changeDir) _currentOrderDirection = (OrderDirection)(((byte)_currentOrderDirection + 1) % 2);
|
|
||||||
if (_currentOrder != type) _currentOrderDirection = OrderDirection.Asc;
|
|
||||||
|
|
||||||
if (type == OrderType.Name) {
|
|
||||||
_groups = _currentOrderDirection == OrderDirection.Asc ? _groups.OrderBy(group => group.Name).ToList() : _groups.OrderByDescending(group => group.Name).ToList();
|
|
||||||
}
|
|
||||||
else if (type == OrderType.Created) {
|
|
||||||
_groups = _currentOrderDirection == OrderDirection.Asc ? _groups.OrderBy(group => group.CreatedAt).ToList() : _groups.OrderByDescending(group => group.CreatedAt).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
_currentOrder = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task Delete(PermissionGroup group) {
|
|
||||||
var result = await Alerts.FireAsync(new SweetAlertOptions {
|
|
||||||
Title = "Are you sure?",
|
|
||||||
Text = "You won't be able to revert this!",
|
|
||||||
Icon = SweetAlertIcon.Warning,
|
|
||||||
ConfirmButtonText = "Yes",
|
|
||||||
ShowCancelButton = true,
|
|
||||||
ShowConfirmButton = true
|
|
||||||
});
|
|
||||||
|
|
||||||
if (result.IsConfirmed) {
|
|
||||||
await Groups.DeletePermissionGroup(group);
|
|
||||||
await Reload();
|
|
||||||
|
|
||||||
await Alerts.FireAsync(new SweetAlertOptions {
|
|
||||||
Title = "Deleted!",
|
|
||||||
Icon = SweetAlertIcon.Success,
|
|
||||||
Timer = 1500,
|
|
||||||
ShowConfirmButton = false
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private enum OrderType {
|
|
||||||
None,
|
|
||||||
Name,
|
|
||||||
Created
|
|
||||||
}
|
|
||||||
|
|
||||||
private enum OrderDirection : byte {
|
|
||||||
Asc = 0,
|
|
||||||
Desc = 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
.title {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
gap: 10px;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#search {
|
|
||||||
margin-left: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
th, h3 {
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
h3 {
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.reload, .sorter {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bold {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
@@ -1,222 +0,0 @@
|
|||||||
@page "/administration/user"
|
|
||||||
@rendermode InteractiveServer
|
|
||||||
@layout AdminLayout
|
|
||||||
|
|
||||||
@using System.Globalization
|
|
||||||
@using BlazorStrap
|
|
||||||
@using CurrieTechnologies.Razor.SweetAlert2
|
|
||||||
@using HopFrame.Database.Models
|
|
||||||
@using HopFrame.Security.Claims
|
|
||||||
@using HopFrame.Web.Pages.Administration.Layout
|
|
||||||
@using static Microsoft.AspNetCore.Components.Web.RenderMode
|
|
||||||
@using Microsoft.AspNetCore.Components.Web
|
|
||||||
@using HopFrame.Web.Components
|
|
||||||
@using BlazorStrap.V5
|
|
||||||
@using HopFrame.Database.Repositories
|
|
||||||
@using HopFrame.Web.Components.Administration
|
|
||||||
|
|
||||||
<PageTitle>Users</PageTitle>
|
|
||||||
<AuthorizedView Permission="@Security.AdminPermissions.ViewUsers" RedirectIfUnauthorized="administration/login?redirect=/administration/users"/>
|
|
||||||
|
|
||||||
<UserAddModal @ref="_userAddModal" ReloadPage="Reload"/>
|
|
||||||
<UserEditModal @ref="_userEditModal" ReloadPage="Reload"/>
|
|
||||||
|
|
||||||
<div class="title">
|
|
||||||
<h3>
|
|
||||||
Users administration
|
|
||||||
<span class="reload" @onclick="Reload">
|
|
||||||
<HopIconDisplay Type="HopIconDisplay.HopIcon.Reload"/>
|
|
||||||
</span>
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<form class="d-flex" role="search" @onsubmit="Search" id="search">
|
|
||||||
<input class="form-control me-2 input-dark" type="search" placeholder="Search" aria-label="Search" @bind="_searchText">
|
|
||||||
<BSButton Color="BSColor.Success" IsOutlined="true" type="submit">Search</BSButton>
|
|
||||||
</form>
|
|
||||||
<AuthorizedView Permission="@Security.AdminPermissions.AddUser">
|
|
||||||
<BSButton IsSubmit="false" Color="BSColor.Success" Target="add-user" OnClick="() => _userAddModal.ShowAsync()">Add User</BSButton>
|
|
||||||
</AuthorizedView>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<BSTable IsStriped="true" IsHoverable="true" IsDark="true" Color="BSColor.Dark">
|
|
||||||
<BSTHead>
|
|
||||||
<BSTR>
|
|
||||||
<BSTD>#</BSTD>
|
|
||||||
<BSTD>
|
|
||||||
<span class="sorter" @onclick="() => OrderBy(OrderType.Email)">E-Mail</span>
|
|
||||||
@if (_currentOrder == OrderType.Email) {
|
|
||||||
<HopIconDisplay Type="_currentOrderDirection == OrderDirection.Desc ? HopIconDisplay.HopIcon.ArrowDown : HopIconDisplay.HopIcon.ArrowUp"/>
|
|
||||||
}
|
|
||||||
</BSTD>
|
|
||||||
<BSTD>
|
|
||||||
<span class="sorter" @onclick="() => OrderBy(OrderType.Username)">Username</span>
|
|
||||||
@if (_currentOrder == OrderType.Username) {
|
|
||||||
<HopIconDisplay Type="_currentOrderDirection == OrderDirection.Desc ? HopIconDisplay.HopIcon.ArrowDown : HopIconDisplay.HopIcon.ArrowUp"/>
|
|
||||||
}
|
|
||||||
</BSTD>
|
|
||||||
<BSTD>
|
|
||||||
<span class="sorter" @onclick="() => OrderBy(OrderType.Registered)">Registered</span>
|
|
||||||
@if (_currentOrder == OrderType.Registered) {
|
|
||||||
<HopIconDisplay Type="_currentOrderDirection == OrderDirection.Desc ? HopIconDisplay.HopIcon.ArrowDown : HopIconDisplay.HopIcon.ArrowUp"/>
|
|
||||||
}
|
|
||||||
</BSTD>
|
|
||||||
<BSTD>Primary Group</BSTD>
|
|
||||||
|
|
||||||
@if (_hasEditPrivileges || _hasDeletePrivileges) {
|
|
||||||
<BSTD>Actions</BSTD>
|
|
||||||
}
|
|
||||||
</BSTR>
|
|
||||||
</BSTHead>
|
|
||||||
|
|
||||||
<BSTBody>
|
|
||||||
@foreach (var user in _users) {
|
|
||||||
<BSTR>
|
|
||||||
<BSTD class="bold">@user.Id</BSTD>
|
|
||||||
<BSTD>@user.Email</BSTD>
|
|
||||||
<BSTD>@user.Username</BSTD>
|
|
||||||
<BSTD>@user.CreatedAt</BSTD>
|
|
||||||
<BSTD>@GetFriendlyGroupName(user)</BSTD>
|
|
||||||
|
|
||||||
@if (_hasEditPrivileges || _hasDeletePrivileges) {
|
|
||||||
<BSTD>
|
|
||||||
<BSButtonGroup>
|
|
||||||
@if (_hasEditPrivileges) {
|
|
||||||
<BSButton Color="BSColor.Warning" OnClick="() => _userEditModal.ShowAsync(user)">Edit</BSButton>
|
|
||||||
}
|
|
||||||
|
|
||||||
@if (_hasDeletePrivileges) {
|
|
||||||
<BSButton Color="BSColor.Danger" OnClick="() => Delete(user)">Delete</BSButton>
|
|
||||||
}
|
|
||||||
</BSButtonGroup>
|
|
||||||
</BSTD>
|
|
||||||
}
|
|
||||||
</BSTR>
|
|
||||||
}
|
|
||||||
</BSTBody>
|
|
||||||
</BSTable>
|
|
||||||
|
|
||||||
@inject IUserRepository UserService
|
|
||||||
@inject IPermissionRepository PermissionsService
|
|
||||||
@inject IGroupRepository Groups
|
|
||||||
@inject SweetAlertService Alerts
|
|
||||||
@inject ITokenContext Auth
|
|
||||||
|
|
||||||
@code {
|
|
||||||
private IList<User> _users = new List<User>();
|
|
||||||
private IDictionary<Guid, PermissionGroup> _userGroups = new Dictionary<Guid, PermissionGroup>();
|
|
||||||
|
|
||||||
private OrderType _currentOrder = OrderType.None;
|
|
||||||
private OrderDirection _currentOrderDirection = OrderDirection.Asc;
|
|
||||||
|
|
||||||
private string _searchText;
|
|
||||||
|
|
||||||
private bool _hasEditPrivileges = false;
|
|
||||||
private bool _hasDeletePrivileges = false;
|
|
||||||
|
|
||||||
private UserAddModal _userAddModal;
|
|
||||||
private UserEditModal _userEditModal;
|
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync() {
|
|
||||||
_users = await UserService.GetUsers();
|
|
||||||
|
|
||||||
foreach (var user in _users) {
|
|
||||||
var groups = await Groups.GetUserGroups(user);
|
|
||||||
_userGroups.Add(user.Id, groups.LastOrDefault());
|
|
||||||
}
|
|
||||||
|
|
||||||
_hasEditPrivileges = await PermissionsService.HasPermission(Auth.User, Security.AdminPermissions.EditUser);
|
|
||||||
_hasDeletePrivileges = await PermissionsService.HasPermission(Auth.User, Security.AdminPermissions.DeleteUser);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task Reload() {
|
|
||||||
_users = new List<User>();
|
|
||||||
_userGroups = new Dictionary<Guid, PermissionGroup>();
|
|
||||||
|
|
||||||
_users = await UserService.GetUsers();
|
|
||||||
|
|
||||||
foreach (var user in _users) {
|
|
||||||
var groups = await Groups.GetUserGroups(user);
|
|
||||||
_userGroups.Add(user.Id, groups.LastOrDefault());
|
|
||||||
}
|
|
||||||
|
|
||||||
OrderBy(_currentOrder, false);
|
|
||||||
StateHasChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task Search() {
|
|
||||||
var users = await UserService.GetUsers();
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(_searchText)) {
|
|
||||||
users = users
|
|
||||||
.Where(user =>
|
|
||||||
user.Email.Contains(_searchText) ||
|
|
||||||
user.Username.Contains(_searchText) ||
|
|
||||||
user.Id.ToString().Contains(_searchText) ||
|
|
||||||
user.CreatedAt.ToString(CultureInfo.InvariantCulture).Contains(_searchText) ||
|
|
||||||
_userGroups[user.Id]?.Name.Contains(_searchText) == true)
|
|
||||||
.ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
_users = users;
|
|
||||||
OrderBy(_currentOrder, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private string GetFriendlyGroupName(User user) {
|
|
||||||
var group = _userGroups[user.Id];
|
|
||||||
if (group is null) return null;
|
|
||||||
|
|
||||||
return group.Name.Replace("group.", "");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OrderBy(OrderType type, bool changeDir = true) {
|
|
||||||
if (_currentOrder == type && changeDir) _currentOrderDirection = (OrderDirection)(((byte)_currentOrderDirection + 1) % 2);
|
|
||||||
if (_currentOrder != type) _currentOrderDirection = OrderDirection.Asc;
|
|
||||||
|
|
||||||
if (type == OrderType.Email) {
|
|
||||||
_users = _currentOrderDirection == OrderDirection.Asc ? _users.OrderBy(user => user.Email).ToList() : _users.OrderByDescending(user => user.Email).ToList();
|
|
||||||
}
|
|
||||||
else if (type == OrderType.Username) {
|
|
||||||
_users = _currentOrderDirection == OrderDirection.Asc ? _users.OrderBy(user => user.Username).ToList() : _users.OrderByDescending(user => user.Username).ToList();
|
|
||||||
}
|
|
||||||
else if (type == OrderType.Registered) {
|
|
||||||
_users = _currentOrderDirection == OrderDirection.Asc ? _users.OrderBy(user => user.CreatedAt).ToList() : _users.OrderByDescending(user => user.CreatedAt).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
_currentOrder = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task Delete(User user) {
|
|
||||||
var result = await Alerts.FireAsync(new SweetAlertOptions {
|
|
||||||
Title = "Are you sure?",
|
|
||||||
Text = "You won't be able to revert this!",
|
|
||||||
Icon = SweetAlertIcon.Warning,
|
|
||||||
ConfirmButtonText = "Yes",
|
|
||||||
ShowCancelButton = true,
|
|
||||||
ShowConfirmButton = true
|
|
||||||
});
|
|
||||||
|
|
||||||
if (result.IsConfirmed) {
|
|
||||||
await UserService.DeleteUser(user);
|
|
||||||
await Reload();
|
|
||||||
|
|
||||||
await Alerts.FireAsync(new SweetAlertOptions {
|
|
||||||
Title = "Deleted!",
|
|
||||||
Icon = SweetAlertIcon.Success,
|
|
||||||
Timer = 1500,
|
|
||||||
ShowConfirmButton = false
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private enum OrderType {
|
|
||||||
None,
|
|
||||||
Email,
|
|
||||||
Username,
|
|
||||||
Registered
|
|
||||||
}
|
|
||||||
|
|
||||||
private enum OrderDirection : byte {
|
|
||||||
Asc = 0,
|
|
||||||
Desc = 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
.title {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
gap: 10px;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#search {
|
|
||||||
margin-left: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
th, h3 {
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
h3 {
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.reload, .sorter {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bold {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user