add support for API permissions at the UI layer - including ability to delegate user, role, profile management
This commit is contained in:
parent
1616f94b86
commit
e136972cd7
|
@ -49,7 +49,6 @@ namespace Microsoft.Extensions.DependencyInjection
|
||||||
services.AddScoped<IUrlMappingService, UrlMappingService>();
|
services.AddScoped<IUrlMappingService, UrlMappingService>();
|
||||||
services.AddScoped<IVisitorService, VisitorService>();
|
services.AddScoped<IVisitorService, VisitorService>();
|
||||||
services.AddScoped<ISyncService, SyncService>();
|
services.AddScoped<ISyncService, SyncService>();
|
||||||
services.AddScoped<IApiService, ApiService>();
|
|
||||||
|
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,75 +0,0 @@
|
||||||
@namespace Oqtane.Modules.Admin.Apis
|
|
||||||
@inherits ModuleBase
|
|
||||||
@inject IApiService ApiService
|
|
||||||
@inject NavigationManager NavigationManager
|
|
||||||
@inject IStringLocalizer<Edit> Localizer
|
|
||||||
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
|
||||||
|
|
||||||
<div class="container">
|
|
||||||
<div class="row mb-1 align-items-center">
|
|
||||||
<Label Class="col-sm-3" For="entityname" HelpText="The name of the entity" ResourceKey="EntityName">Entity: </Label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<input id="entityname" class="form-control" @bind="@_entityname" readonly />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<br />
|
|
||||||
<div class="row mb-1 align-items-center">
|
|
||||||
@if (_permissions != null)
|
|
||||||
{
|
|
||||||
<PermissionGrid EntityName="@_entityname" PermissionNames="@_permissionnames" Permissions="@_permissions" @ref="_permissionGrid" />
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<button type="button" class="btn btn-success" @onclick="SaveModuleDefinition">@SharedLocalizer["Save"]</button>
|
|
||||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
|
||||||
|
|
||||||
@code {
|
|
||||||
private string _entityname;
|
|
||||||
private string _permissionnames;
|
|
||||||
private string _permissions;
|
|
||||||
|
|
||||||
#pragma warning disable 649
|
|
||||||
private PermissionGrid _permissionGrid;
|
|
||||||
#pragma warning restore 649
|
|
||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
_entityname = PageState.QueryString["entity"];
|
|
||||||
var api = await ApiService.GetApiAsync(PageState.Site.SiteId, _entityname);
|
|
||||||
if (api != null)
|
|
||||||
{
|
|
||||||
var apis = await ApiService.GetApisAsync(PageState.Site.SiteId);
|
|
||||||
_permissionnames = apis.SingleOrDefault(item => item.EntityName == _entityname).Permissions;
|
|
||||||
_permissions = api.Permissions;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
await logger.LogError(ex, "Error Loading API {EntityName} {Error}", _entityname, ex.Message);
|
|
||||||
AddModuleMessage(Localizer["Error.Module.Load"], MessageType.Error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task SaveModuleDefinition()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var api = new Api();
|
|
||||||
api.SiteId = PageState.Site.SiteId;
|
|
||||||
api.EntityName = _entityname;
|
|
||||||
api.Permissions = _permissionGrid.GetPermissions();
|
|
||||||
await ApiService.UpdateApiAsync(api);
|
|
||||||
await logger.LogInformation("API Saved {Api}", api);
|
|
||||||
NavigationManager.NavigateTo(NavigateUrl());
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
await logger.LogError(ex, "Error Saving Api {EntityName} {Error}", _entityname, ex.Message);
|
|
||||||
AddModuleMessage(Localizer["Error.Module.Save"], MessageType.Error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,36 +0,0 @@
|
||||||
@namespace Oqtane.Modules.Admin.Apis
|
|
||||||
@inherits ModuleBase
|
|
||||||
@inject IApiService ApiService
|
|
||||||
@inject IStringLocalizer<Index> Localizer
|
|
||||||
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
|
||||||
|
|
||||||
@if (_apis == null)
|
|
||||||
{
|
|
||||||
<p><em>@SharedLocalizer["Loading"]</em></p>
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<Pager Items="@_apis">
|
|
||||||
<Header>
|
|
||||||
<th style="width: 1px;"> </th>
|
|
||||||
<th>@Localizer["Entity"]</th>
|
|
||||||
<th>@Localizer["Permissions"]</th>
|
|
||||||
</Header>
|
|
||||||
<Row>
|
|
||||||
<td><ActionLink Action="Edit" Parameters="@($"entity=" + context.EntityName)" ResourceKey="Edit" /></td>
|
|
||||||
<td>@context.EntityName</td>
|
|
||||||
<td>@context.Permissions</td>
|
|
||||||
</Row>
|
|
||||||
</Pager>
|
|
||||||
}
|
|
||||||
|
|
||||||
@code {
|
|
||||||
private List<Api> _apis;
|
|
||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
|
||||||
|
|
||||||
protected override async Task OnParametersSetAsync()
|
|
||||||
{
|
|
||||||
_apis = await ApiService.GetApisAsync(PageState.Site.SiteId);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -22,11 +22,14 @@
|
||||||
@code {
|
@code {
|
||||||
private List<Page> _pages;
|
private List<Page> _pages;
|
||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Anonymous;
|
||||||
|
|
||||||
protected override void OnInitialized()
|
protected override void OnInitialized()
|
||||||
{
|
{
|
||||||
var admin = PageState.Pages.FirstOrDefault(item => item.Path == "admin");
|
var admin = PageState.Pages.FirstOrDefault(item => item.Path == "admin");
|
||||||
|
if (admin != null)
|
||||||
|
{
|
||||||
_pages = PageState.Pages.Where(item => item.ParentId == admin?.PageId).ToList();
|
_pages = PageState.Pages.Where(item => item.ParentId == admin?.PageId).ToList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -131,7 +131,7 @@ else
|
||||||
moduleDefinition = await ModuleDefinitionService.CreateModuleDefinitionAsync(moduleDefinition);
|
moduleDefinition = await ModuleDefinitionService.CreateModuleDefinitionAsync(moduleDefinition);
|
||||||
|
|
||||||
var settings = await SettingService.GetModuleSettingsAsync(ModuleState.ModuleId);
|
var settings = await SettingService.GetModuleSettingsAsync(ModuleState.ModuleId);
|
||||||
SettingService.SetSetting(settings, "ModuleDefinitionName", moduleDefinition.ModuleDefinitionName);
|
settings = SettingService.SetSetting(settings, "ModuleDefinitionName", moduleDefinition.ModuleDefinitionName);
|
||||||
await SettingService.UpdateModuleSettingsAsync(settings, ModuleState.ModuleId);
|
await SettingService.UpdateModuleSettingsAsync(settings, ModuleState.ModuleId);
|
||||||
|
|
||||||
GetLocation();
|
GetLocation();
|
||||||
|
|
|
@ -157,6 +157,7 @@
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
}
|
}
|
||||||
</TabStrip>
|
</TabStrip>
|
||||||
|
<br />
|
||||||
<button type="button" class="btn btn-success" @onclick="SavePage">@SharedLocalizer["Save"]</button>
|
<button type="button" class="btn btn-success" @onclick="SavePage">@SharedLocalizer["Save"]</button>
|
||||||
<button type="button" class="btn btn-secondary" @onclick="Cancel">@SharedLocalizer["Cancel"]</button>
|
<button type="button" class="btn btn-secondary" @onclick="Cancel">@SharedLocalizer["Cancel"]</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -148,7 +148,8 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Section>
|
</Section>
|
||||||
<br /><br />
|
<br />
|
||||||
|
<br />
|
||||||
<AuditInfo CreatedBy="@_createdby" CreatedOn="@_createdon" ModifiedBy="@_modifiedby" ModifiedOn="@_modifiedon" DeletedBy="@_deletedby" DeletedOn="@_deletedon"></AuditInfo>
|
<AuditInfo CreatedBy="@_createdby" CreatedOn="@_createdon" ModifiedBy="@_modifiedby" ModifiedOn="@_modifiedon" DeletedBy="@_deletedby" DeletedOn="@_deletedon"></AuditInfo>
|
||||||
}
|
}
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
|
@ -189,6 +190,7 @@
|
||||||
<br />
|
<br />
|
||||||
}
|
}
|
||||||
</TabStrip>
|
</TabStrip>
|
||||||
|
<br />
|
||||||
<button type="button" class="btn btn-success" @onclick="SavePage">@SharedLocalizer["Save"]</button>
|
<button type="button" class="btn btn-success" @onclick="SavePage">@SharedLocalizer["Save"]</button>
|
||||||
<button type="button" class="btn btn-secondary" @onclick="Cancel">@SharedLocalizer["Cancel"]</button>
|
<button type="button" class="btn btn-secondary" @onclick="Cancel">@SharedLocalizer["Cancel"]</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
19
Oqtane.Client/Modules/Admin/Profiles/ModuleInfo.cs
Normal file
19
Oqtane.Client/Modules/Admin/Profiles/ModuleInfo.cs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
using Oqtane.Documentation;
|
||||||
|
using Oqtane.Models;
|
||||||
|
using Oqtane.Shared;
|
||||||
|
|
||||||
|
namespace Oqtane.Modules.Admin.Profiles
|
||||||
|
{
|
||||||
|
[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 = "Profiles",
|
||||||
|
Description = "Manage Profiles",
|
||||||
|
Categories = "Admin",
|
||||||
|
Version = Constants.Version,
|
||||||
|
PermissionNames = $"{PermissionNames.View},{PermissionNames.Edit},{EntityNames.Profile}:{PermissionNames.Write}:{RoleNames.Admin}"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -42,7 +42,7 @@
|
||||||
private string _description = string.Empty;
|
private string _description = string.Empty;
|
||||||
private string _isautoassigned = "False";
|
private string _isautoassigned = "False";
|
||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit;
|
||||||
|
|
||||||
private async Task SaveRole()
|
private async Task SaveRole()
|
||||||
{
|
{
|
||||||
|
|
|
@ -49,7 +49,7 @@
|
||||||
private string _modifiedby;
|
private string _modifiedby;
|
||||||
private DateTime _modifiedon;
|
private DateTime _modifiedon;
|
||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit;
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
<ActionLink Action="Add" Text="Add Role" ResourceKey="AddRole" />
|
<ActionLink Action="Add" Text="Add Role" Security="SecurityAccessLevel.Edit" ResourceKey="AddRole" />
|
||||||
|
|
||||||
<Pager Items="@_roles">
|
<Pager Items="@_roles">
|
||||||
<Header>
|
<Header>
|
||||||
|
@ -20,9 +20,9 @@ else
|
||||||
<th>@SharedLocalizer["Name"]</th>
|
<th>@SharedLocalizer["Name"]</th>
|
||||||
</Header>
|
</Header>
|
||||||
<Row>
|
<Row>
|
||||||
<td><ActionLink Action="Edit" Parameters="@($"id=" + context.RoleId.ToString())" Disabled="@(context.IsSystem)" ResourceKey="Edit" /></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.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteRole(context))" Disabled="@(context.IsSystem)" ResourceKey="DeleteRole" /></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())" ResourceKey="Users" /></td>
|
<td><ActionLink Action="Users" Parameters="@($"id=" + context.RoleId.ToString())" Security="SecurityAccessLevel.Edit" ResourceKey="Users" /></td>
|
||||||
<td>@context.Name</td>
|
<td>@context.Name</td>
|
||||||
</Row>
|
</Row>
|
||||||
</Pager>
|
</Pager>
|
||||||
|
@ -31,7 +31,7 @@ else
|
||||||
@code {
|
@code {
|
||||||
private List<Role> _roles;
|
private List<Role> _roles;
|
||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.View;
|
||||||
|
|
||||||
protected override async Task OnParametersSetAsync()
|
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">
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="user" HelpText="Select a user" ResourceKey="User">User: </Label>
|
<Label Class="col-sm-3" For="user" HelpText="Select a user" ResourceKey="User">User: </Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<select id="user" class="form-select" @bind="@userid" required>
|
<AutoComplete OnSearch="GetUsers" Placeholder="@Localizer["User.Select"]" @ref="user" />
|
||||||
<option value="-1"><@Localizer["User.Select"]></option>
|
|
||||||
@foreach (UserRole userrole in users)
|
|
||||||
{
|
|
||||||
<option value="@(userrole.UserId)">@userrole.User.DisplayName</option>
|
|
||||||
}
|
|
||||||
</select>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
|
@ -64,7 +58,7 @@ else
|
||||||
<td>@context.EffectiveDate</td>
|
<td>@context.EffectiveDate</td>
|
||||||
<td>@context.ExpiryDate</td>
|
<td>@context.ExpiryDate</td>
|
||||||
<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>
|
</td>
|
||||||
</Row>
|
</Row>
|
||||||
</Pager>
|
</Pager>
|
||||||
|
@ -80,13 +74,12 @@ else
|
||||||
|
|
||||||
private int roleid;
|
private int roleid;
|
||||||
private string name = string.Empty;
|
private string name = string.Empty;
|
||||||
private List<UserRole> users;
|
private AutoComplete user;
|
||||||
private int userid = -1;
|
|
||||||
private DateTime? effectivedate = null;
|
private DateTime? effectivedate = null;
|
||||||
private DateTime? expirydate = null;
|
private DateTime? expirydate = null;
|
||||||
private List<UserRole> userroles;
|
private List<UserRole> userroles;
|
||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit;
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
|
@ -95,7 +88,6 @@ else
|
||||||
roleid = Int32.Parse(PageState.QueryString["id"]);
|
roleid = Int32.Parse(PageState.QueryString["id"]);
|
||||||
Role role = await RoleService.GetRoleAsync(roleid);
|
Role role = await RoleService.GetRoleAsync(roleid);
|
||||||
name = role.Name;
|
name = role.Name;
|
||||||
users = await UserRoleService.GetUserRolesAsync(PageState.Site.SiteId, RoleNames.Registered);
|
|
||||||
await GetUserRoles();
|
await GetUserRoles();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
@ -105,6 +97,22 @@ else
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 GetUserRoles()
|
private async Task GetUserRoles()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -126,7 +134,7 @@ else
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (userid != -1)
|
if (!string.IsNullOrEmpty(user.Key) && int.TryParse(user.Key, out int userid))
|
||||||
{
|
{
|
||||||
var userrole = userroles.Where(item => item.UserId == userid && item.RoleId == roleid).FirstOrDefault();
|
var userrole = userroles.Where(item => item.UserId == userid && item.RoleId == roleid).FirstOrDefault();
|
||||||
if (userrole != null)
|
if (userrole != null)
|
||||||
|
@ -149,6 +157,7 @@ else
|
||||||
await logger.LogInformation("User Assigned To Role {UserRole}", userrole);
|
await logger.LogInformation("User Assigned To Role {UserRole}", userrole);
|
||||||
AddModuleMessage(Localizer["Success.User.AssignedRole"], MessageType.Success);
|
AddModuleMessage(Localizer["Success.User.AssignedRole"], MessageType.Success);
|
||||||
await GetUserRoles();
|
await GetUserRoles();
|
||||||
|
user.Clear();
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -602,12 +602,12 @@
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var settings = await SettingService.GetSiteSettingsAsync(PageState.Site.SiteId);
|
var settings = await SettingService.GetSiteSettingsAsync(PageState.Site.SiteId);
|
||||||
SettingService.SetSetting(settings, "SMTPHost", _smtphost, true);
|
settings = SettingService.SetSetting(settings, "SMTPHost", _smtphost, true);
|
||||||
SettingService.SetSetting(settings, "SMTPPort", _smtpport, true);
|
settings = SettingService.SetSetting(settings, "SMTPPort", _smtpport, true);
|
||||||
SettingService.SetSetting(settings, "SMTPSSL", _smtpssl, true);
|
settings = SettingService.SetSetting(settings, "SMTPSSL", _smtpssl, true);
|
||||||
SettingService.SetSetting(settings, "SMTPUsername", _smtpusername, true);
|
settings = SettingService.SetSetting(settings, "SMTPUsername", _smtpusername, true);
|
||||||
SettingService.SetSetting(settings, "SMTPPassword", _smtppassword, true);
|
settings = SettingService.SetSetting(settings, "SMTPPassword", _smtppassword, true);
|
||||||
SettingService.SetSetting(settings, "SMTPSender", _smtpsender, true);
|
settings = SettingService.SetSetting(settings, "SMTPSender", _smtpsender, true);
|
||||||
await SettingService.UpdateSiteSettingsAsync(settings, PageState.Site.SiteId);
|
await SettingService.UpdateSiteSettingsAsync(settings, PageState.Site.SiteId);
|
||||||
await logger.LogInformation("Site SMTP Settings Saved");
|
await logger.LogInformation("Site SMTP Settings Saved");
|
||||||
|
|
||||||
|
|
|
@ -305,7 +305,14 @@ else
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetProfileValue(string SettingName, string DefaultValue)
|
private string GetProfileValue(string SettingName, string DefaultValue)
|
||||||
=> SettingService.GetSetting(settings, SettingName, DefaultValue);
|
{
|
||||||
|
string value = SettingService.GetSetting(settings, SettingName, DefaultValue);
|
||||||
|
if (value.Contains("]"))
|
||||||
|
{
|
||||||
|
value = value.Substring(value.IndexOf("]") + 1);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
private async Task Save()
|
private async Task Save()
|
||||||
{
|
{
|
||||||
|
|
|
@ -104,7 +104,7 @@
|
||||||
private Dictionary<string, string> settings;
|
private Dictionary<string, string> settings;
|
||||||
private string category = string.Empty;
|
private string category = string.Empty;
|
||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit;
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
|
@ -122,7 +122,14 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetProfileValue(string SettingName, string DefaultValue)
|
private string GetProfileValue(string SettingName, string DefaultValue)
|
||||||
=> SettingService.GetSetting(settings, SettingName, DefaultValue);
|
{
|
||||||
|
string value = SettingService.GetSetting(settings, SettingName, DefaultValue);
|
||||||
|
if (value.Contains("]"))
|
||||||
|
{
|
||||||
|
value = value.Substring(value.IndexOf("]") + 1);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
private async Task SaveUser()
|
private async Task SaveUser()
|
||||||
{
|
{
|
||||||
|
|
|
@ -174,7 +174,7 @@ else
|
||||||
private string deletedby;
|
private string deletedby;
|
||||||
private DateTime? deletedon;
|
private DateTime? deletedon;
|
||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit;
|
||||||
|
|
||||||
protected override async Task OnParametersSetAsync()
|
protected override async Task OnParametersSetAsync()
|
||||||
{
|
{
|
||||||
|
@ -223,7 +223,14 @@ else
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetProfileValue(string SettingName, string DefaultValue)
|
private string GetProfileValue(string SettingName, string DefaultValue)
|
||||||
=> SettingService.GetSetting(settings, SettingName, DefaultValue);
|
{
|
||||||
|
string value = SettingService.GetSetting(settings, SettingName, DefaultValue);
|
||||||
|
if (value.Contains("]"))
|
||||||
|
{
|
||||||
|
value = value.Substring(value.IndexOf("]") + 1);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
private async Task SaveUser()
|
private async Task SaveUser()
|
||||||
{
|
{
|
||||||
|
|
|
@ -20,7 +20,7 @@ else
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<div class="col-sm-4">
|
<div class="col-sm-4">
|
||||||
<ActionLink Action="Add" Text="Add User" ResourceKey="AddUser" />
|
<ActionLink Action="Add" Text="Add User" Security="SecurityAccessLevel.Edit" ResourceKey="AddUser" />
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-4">
|
<div class="col-sm-4">
|
||||||
<input class="form-control" @bind="@_search" />
|
<input class="form-control" @bind="@_search" />
|
||||||
|
@ -41,21 +41,21 @@ else
|
||||||
</Header>
|
</Header>
|
||||||
<Row>
|
<Row>
|
||||||
<td>
|
<td>
|
||||||
<ActionLink Action="Edit" Parameters="@($"id=" + context.UserId.ToString())" ResourceKey="EditUser" />
|
<ActionLink Action="Edit" Parameters="@($"id=" + context.UserId.ToString())" Security="SecurityAccessLevel.Edit" ResourceKey="EditUser" />
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<ActionDialog Header="Delete User" Message="@string.Format(Localizer["Confirm.User.Delete"], context.User.DisplayName)" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteUser(context))" Disabled="@(context.UserId == PageState.User.UserId)" ResourceKey="DeleteUser" />
|
<ActionDialog Header="Delete User" Message="@string.Format(Localizer["Confirm.User.Delete"], context.User.DisplayName)" Action="Delete" Security="SecurityAccessLevel.Edit" Class="btn btn-danger" OnClick="@(async () => await DeleteUser(context))" Disabled="@(context.UserId == PageState.User.UserId)" ResourceKey="DeleteUser" />
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<ActionLink Action="Roles" Parameters="@($"id=" + context.UserId.ToString())" ResourceKey="Roles" />
|
<ActionLink Action="Roles" Parameters="@($"id=" + context.UserId.ToString())" Security="SecurityAccessLevel.Edit" ResourceKey="Roles" />
|
||||||
</td>
|
</td>
|
||||||
<td>@context.User.Username</td>
|
<td>@context.User.Username</td>
|
||||||
<td>@((MarkupString)string.Format("<a href=\"mailto:{0}\">{1}</a>", @context.User.Email, @context.User.DisplayName))</td>
|
<td>@((MarkupString)string.Format("<a href=\"mailto:{0}\">{1}</a>", @context.User.Email, @context.User.DisplayName))</td>
|
||||||
<td>@string.Format("{0:dd-MMM-yyyy HH:mm:ss}", context.User.LastLoginOn)</td>
|
<td>@((context.User.LastLoginOn != DateTime.MinValue) ? string.Format("{0:dd-MMM-yyyy HH:mm:ss}", context.User.LastLoginOn) : "")</td>
|
||||||
</Row>
|
</Row>
|
||||||
</Pager>
|
</Pager>
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
<TabPanel Name="Settings" Heading="Settings" ResourceKey="Settings">
|
<TabPanel Name="Settings" Heading="Settings" ResourceKey="Settings" Security="SecurityAccessLevel.Admin">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<Section Name="User" Heading="User Settings" ResourceKey="UserSettings">
|
<Section Name="User" Heading="User Settings" ResourceKey="UserSettings">
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
|
@ -406,7 +406,7 @@ else
|
||||||
private string _lifetime;
|
private string _lifetime;
|
||||||
private string _token;
|
private string _token;
|
||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.View;
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
|
@ -456,7 +456,8 @@ else
|
||||||
_togglesecret = SharedLocalizer["ShowPassword"];
|
_togglesecret = SharedLocalizer["ShowPassword"];
|
||||||
_issuer = SettingService.GetSetting(settings, "JwtOptions:Issuer", PageState.Uri.Scheme + "://" + PageState.Alias.Name);
|
_issuer = SettingService.GetSetting(settings, "JwtOptions:Issuer", PageState.Uri.Scheme + "://" + PageState.Alias.Name);
|
||||||
_audience = SettingService.GetSetting(settings, "JwtOptions:Audience", "");
|
_audience = SettingService.GetSetting(settings, "JwtOptions:Audience", "");
|
||||||
_lifetime = SettingService.GetSetting(settings, "JwtOptions:Lifetime", "20"); }
|
_lifetime = SettingService.GetSetting(settings, "JwtOptions:Lifetime", "20");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task LoadUsersAsync(bool load)
|
private async Task LoadUsersAsync(bool load)
|
||||||
|
@ -522,7 +523,7 @@ else
|
||||||
private async Task UpdateUserSettingsAsync()
|
private async Task UpdateUserSettingsAsync()
|
||||||
{
|
{
|
||||||
Dictionary<string, string> settings = await SettingService.GetUserSettingsAsync(PageState.User.UserId);
|
Dictionary<string, string> settings = await SettingService.GetUserSettingsAsync(PageState.User.UserId);
|
||||||
SettingService.SetSetting(settings, settingSearch, _search);
|
settings = SettingService.SetSetting(settings, settingSearch, _search);
|
||||||
await SettingService.UpdateUserSettingsAsync(settings, PageState.User.UserId);
|
await SettingService.UpdateUserSettingsAsync(settings, PageState.User.UserId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
19
Oqtane.Client/Modules/Admin/Users/ModuleInfo.cs
Normal file
19
Oqtane.Client/Modules/Admin/Users/ModuleInfo.cs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
using Oqtane.Documentation;
|
||||||
|
using Oqtane.Models;
|
||||||
|
using Oqtane.Shared;
|
||||||
|
|
||||||
|
namespace Oqtane.Modules.Admin.Users
|
||||||
|
{
|
||||||
|
[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 = "Users",
|
||||||
|
Description = "Manage Users",
|
||||||
|
Categories = "Admin",
|
||||||
|
Version = Constants.Version,
|
||||||
|
PermissionNames = $"{PermissionNames.View},{PermissionNames.Edit},{EntityNames.User}:{PermissionNames.Write}:{RoleNames.Admin},{EntityNames.UserRole}:{PermissionNames.Write}:{RoleNames.Admin}"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -63,7 +63,7 @@ else
|
||||||
<td>@context.EffectiveDate</td>
|
<td>@context.EffectiveDate</td>
|
||||||
<td>@context.ExpiryDate</td>
|
<td>@context.ExpiryDate</td>
|
||||||
<td>
|
<td>
|
||||||
<ActionDialog Header="Remove Role" Message="@string.Format(Localizer["Confirm.User.RemoveRole"], context.Role.Name)" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteUserRole(context.UserRoleId))" Disabled="@(context.Role.IsAutoAssigned || (context.Role.Name == RoleNames.Host && userid == PageState.User.UserId))" ResourceKey="DeleteUserRole" />
|
<ActionDialog Header="Remove Role" Message="@string.Format(Localizer["Confirm.User.RemoveRole"], context.Role.Name)" Action="Delete" Security="SecurityAccessLevel.Edit" Class="btn btn-danger" OnClick="@(async () => await DeleteUserRole(context.UserRoleId))" Disabled="@(context.Role.IsAutoAssigned || (context.Role.Name == RoleNames.Host && userid == PageState.User.UserId))" ResourceKey="DeleteUserRole" />
|
||||||
</td>
|
</td>
|
||||||
</Row>
|
</Row>
|
||||||
</Pager>
|
</Pager>
|
||||||
|
@ -79,7 +79,7 @@ else
|
||||||
private string expirydate = string.Empty;
|
private string expirydate = string.Empty;
|
||||||
private List<UserRole> userroles;
|
private List<UserRole> userroles;
|
||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit;
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
<th scope="col">@Localizer["Role"]</th>
|
<th scope="col">@Localizer["Role"]</th>
|
||||||
@foreach (PermissionString permission in _permissions)
|
@foreach (PermissionString permission in _permissions)
|
||||||
{
|
{
|
||||||
<th style="text-align: center; width: 1px;">@Localizer[permission.PermissionName]</th>
|
<th style="text-align: center; width: 1px;">@((MarkupString)GetPermissionName(permission).Replace(" ", "<br />"))</th>
|
||||||
}
|
}
|
||||||
</tr>
|
</tr>
|
||||||
@foreach (Role role in _roles)
|
@foreach (Role role in _roles)
|
||||||
|
@ -28,7 +28,7 @@
|
||||||
{
|
{
|
||||||
var p = permission;
|
var p = permission;
|
||||||
<td style="text-align: center;">
|
<td style="text-align: center;">
|
||||||
<TriStateCheckBox Value=@GetPermissionValue(p.Permissions, role.Name) Disabled=@GetPermissionDisabled(role.Name) OnChange="@(e => PermissionChanged(e, p.PermissionName, role.Name))" />
|
<TriStateCheckBox Value=@GetPermissionValue(p.Permissions, role.Name) Disabled="@GetPermissionDisabled(p.EntityName, p.PermissionName, role.Name)" OnChange="@(e => PermissionChanged(e, p.EntityName, p.PermissionName, role.Name))" />
|
||||||
</td>
|
</td>
|
||||||
}
|
}
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -66,7 +66,7 @@
|
||||||
{
|
{
|
||||||
var p = permission;
|
var p = permission;
|
||||||
<td style="text-align: center; width: 1px;">
|
<td style="text-align: center; width: 1px;">
|
||||||
<TriStateCheckBox Value=@GetPermissionValue(p.Permissions, userid) Disabled=false OnChange="@(e => PermissionChanged(e, p.PermissionName, userid))" />
|
<TriStateCheckBox Value=@GetPermissionValue(p.Permissions, userid) Disabled="@GetPermissionDisabled(p.EntityName, p.PermissionName, "")" OnChange="@(e => PermissionChanged(e, p.EntityName, p.PermissionName, userid))" />
|
||||||
</td>
|
</td>
|
||||||
}
|
}
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -129,10 +129,25 @@
|
||||||
|
|
||||||
_permissions = new List<PermissionString>();
|
_permissions = new List<PermissionString>();
|
||||||
|
|
||||||
foreach (string permissionname in _permissionnames.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
|
foreach (string permissionname in _permissionnames.Split(',', StringSplitOptions.RemoveEmptyEntries))
|
||||||
{
|
{
|
||||||
// initialize with admin role
|
// permission names can be in the form of "EntityName:PermissionName:Roles"
|
||||||
_permissions.Add(new PermissionString { PermissionName = permissionname, Permissions = RoleNames.Admin });
|
if (permissionname.Contains(":"))
|
||||||
|
{
|
||||||
|
var segments = permissionname.Split(':');
|
||||||
|
if (segments.Length == 3)
|
||||||
|
{
|
||||||
|
if (!segments[2].Contains(RoleNames.Admin))
|
||||||
|
{
|
||||||
|
segments[2] = RoleNames.Admin + ";" + segments[2]; // ensure admin access
|
||||||
|
}
|
||||||
|
_permissions.Add(new PermissionString { EntityName = segments[0], PermissionName = segments[1], Permissions = segments[2] });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_permissions.Add(new PermissionString { EntityName = EntityName, PermissionName = permissionname, Permissions = RoleNames.Admin });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(Permissions))
|
if (!string.IsNullOrEmpty(Permissions))
|
||||||
|
@ -140,14 +155,15 @@
|
||||||
// populate permissions
|
// populate permissions
|
||||||
foreach (PermissionString permissionstring in UserSecurity.GetPermissionStrings(Permissions))
|
foreach (PermissionString permissionstring in UserSecurity.GetPermissionStrings(Permissions))
|
||||||
{
|
{
|
||||||
if (_permissions.Find(item => item.PermissionName == permissionstring.PermissionName) != null)
|
int index = _permissions.FindIndex(item => item.EntityName == permissionstring.EntityName && item.PermissionName == permissionstring.PermissionName);
|
||||||
|
if (index != -1)
|
||||||
{
|
{
|
||||||
_permissions[_permissions.FindIndex(item => item.PermissionName == permissionstring.PermissionName)].Permissions = permissionstring.Permissions;
|
_permissions[index].Permissions = permissionstring.Permissions;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (permissionstring.Permissions.Contains("["))
|
if (permissionstring.Permissions.Contains("["))
|
||||||
{
|
{
|
||||||
foreach (string user in permissionstring.Permissions.Split(new char[] { '[' }, StringSplitOptions.RemoveEmptyEntries))
|
foreach (string user in permissionstring.Permissions.Split('[', StringSplitOptions.RemoveEmptyEntries))
|
||||||
{
|
{
|
||||||
if (user.Contains("]"))
|
if (user.Contains("]"))
|
||||||
{
|
{
|
||||||
|
@ -163,6 +179,16 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string GetPermissionName(PermissionString permission)
|
||||||
|
{
|
||||||
|
var permissionname = Localizer[permission.PermissionName].ToString();
|
||||||
|
if (!string.IsNullOrEmpty(EntityName))
|
||||||
|
{
|
||||||
|
permissionname += " " + Localizer[permission.EntityName].ToString();
|
||||||
|
}
|
||||||
|
return permissionname;
|
||||||
|
}
|
||||||
|
|
||||||
private bool? GetPermissionValue(string permissions, string securityKey)
|
private bool? GetPermissionValue(string permissions, string securityKey)
|
||||||
{
|
{
|
||||||
if ((";" + permissions + ";").Contains(";" + "!" + securityKey + ";"))
|
if ((";" + permissions + ";").Contains(";" + "!" + securityKey + ";"))
|
||||||
|
@ -182,8 +208,24 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool GetPermissionDisabled(string roleName)
|
private bool GetPermissionDisabled(string entityName, string permissionName, string roleName)
|
||||||
=> (roleName == RoleNames.Admin && !UserSecurity.IsAuthorized(PageState.User, RoleNames.Host)) ? true : false;
|
{
|
||||||
|
if (roleName == RoleNames.Admin && !UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (entityName != EntityName && !UserSecurity.IsAuthorized(PageState.User, RoleNames.Admin))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async Task<Dictionary<string, string>> GetUsers(string filter)
|
private async Task<Dictionary<string, string>> GetUsers(string filter)
|
||||||
{
|
{
|
||||||
|
@ -209,14 +251,15 @@
|
||||||
_user.Clear();
|
_user.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PermissionChanged(bool? value, string permissionName, string securityId)
|
private void PermissionChanged(bool? value, string entityName, string permissionName, string securityId)
|
||||||
{
|
{
|
||||||
var selected = value;
|
var selected = value;
|
||||||
var permission = _permissions.Find(item => item.PermissionName == permissionName);
|
int index = _permissions.FindIndex(item => item.EntityName == entityName && item.PermissionName == permissionName);
|
||||||
if (permission != null)
|
if (index != -1)
|
||||||
{
|
{
|
||||||
var ids = permission.Permissions.Split(';').ToList();
|
var permission = _permissions[index];
|
||||||
|
|
||||||
|
var ids = permission.Permissions.Split(';').ToList();
|
||||||
ids.Remove(securityId); // remove grant permission
|
ids.Remove(securityId); // remove grant permission
|
||||||
ids.Remove("!" + securityId); // remove deny permission
|
ids.Remove("!" + securityId); // remove deny permission
|
||||||
|
|
||||||
|
@ -232,7 +275,7 @@
|
||||||
break; // permission not specified
|
break; // permission not specified
|
||||||
}
|
}
|
||||||
|
|
||||||
_permissions[_permissions.FindIndex(item => item.PermissionName == permissionName)].Permissions = string.Join(";", ids.ToArray());
|
_permissions[index].Permissions = string.Join(";", ids.ToArray());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,9 +288,9 @@
|
||||||
private void ValidatePermissions()
|
private void ValidatePermissions()
|
||||||
{
|
{
|
||||||
PermissionString permission;
|
PermissionString permission;
|
||||||
for (int i = 0; i < _permissions.Count; i++)
|
for (int index = 0; index < _permissions.Count; index++)
|
||||||
{
|
{
|
||||||
permission = _permissions[i];
|
permission = _permissions[index];
|
||||||
List<string> ids = permission.Permissions.Split(';', StringSplitOptions.RemoveEmptyEntries).ToList();
|
List<string> ids = permission.Permissions.Split(';', StringSplitOptions.RemoveEmptyEntries).ToList();
|
||||||
ids.Remove("!" + RoleNames.Everyone); // remove deny all users
|
ids.Remove("!" + RoleNames.Everyone); // remove deny all users
|
||||||
ids.Remove("!" + RoleNames.Unauthenticated); // remove deny unauthenticated
|
ids.Remove("!" + RoleNames.Unauthenticated); // remove deny unauthenticated
|
||||||
|
@ -263,7 +306,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
permission.Permissions = string.Join(";", ids.ToArray());
|
permission.Permissions = string.Join(";", ids.ToArray());
|
||||||
_permissions[i] = permission;
|
_permissions[index] = permission;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -315,15 +315,10 @@ namespace Oqtane.Modules
|
||||||
{
|
{
|
||||||
int pageId = ModuleState.PageId;
|
int pageId = ModuleState.PageId;
|
||||||
int moduleId = ModuleState.ModuleId;
|
int moduleId = ModuleState.ModuleId;
|
||||||
int? userId = null;
|
|
||||||
if (PageState.User != null)
|
|
||||||
{
|
|
||||||
userId = PageState.User.UserId;
|
|
||||||
}
|
|
||||||
string category = GetType().AssemblyQualifiedName;
|
string category = GetType().AssemblyQualifiedName;
|
||||||
string feature = Utilities.GetTypeNameLastSegment(category, 1);
|
string feature = Utilities.GetTypeNameLastSegment(category, 1);
|
||||||
|
|
||||||
await LoggingService.Log(alias, pageId, moduleId, userId, category, feature, function, level, exception, message, args);
|
await LoggingService.Log(alias, pageId, moduleId, PageState.User?.UserId, category, feature, function, level, exception, message, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Logger
|
public class Logger
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<root>
|
<root>
|
||||||
<!--
|
<!--
|
||||||
Microsoft ResX Schema
|
Microsoft ResX Schema
|
||||||
|
@ -121,7 +121,7 @@
|
||||||
<value>User: </value>
|
<value>User: </value>
|
||||||
</data>
|
</data>
|
||||||
<data name="User.Select" xml:space="preserve">
|
<data name="User.Select" xml:space="preserve">
|
||||||
<value>Select User</value>
|
<value>Enter User's Name</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Users" xml:space="preserve">
|
<data name="Users" xml:space="preserve">
|
||||||
<value>Users</value>
|
<value>Users</value>
|
||||||
|
@ -129,9 +129,6 @@
|
||||||
<data name="Error.User.Load" xml:space="preserve">
|
<data name="Error.User.Load" xml:space="preserve">
|
||||||
<value>Error Loading Users</value>
|
<value>Error Loading Users</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Error.User.LoadRole" xml:space="preserve">
|
|
||||||
<value>Error Loading User Roles</value>
|
|
||||||
</data>
|
|
||||||
<data name="Success.User.AssignedRole" xml:space="preserve">
|
<data name="Success.User.AssignedRole" xml:space="preserve">
|
||||||
<value>User Assigned To Role</value>
|
<value>User Assigned To Role</value>
|
||||||
</data>
|
</data>
|
||||||
|
@ -151,7 +148,7 @@
|
||||||
<value>The role you are assigning users to</value>
|
<value>The role you are assigning users to</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="User.HelpText" xml:space="preserve">
|
<data name="User.HelpText" xml:space="preserve">
|
||||||
<value>Select a user</value>
|
<value>Enter the name of a user</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="EffectiveDate.HelpText" xml:space="preserve">
|
<data name="EffectiveDate.HelpText" xml:space="preserve">
|
||||||
<value>The date that this role assignment is active</value>
|
<value>The date that this role assignment is active</value>
|
||||||
|
|
|
@ -1,32 +0,0 @@
|
||||||
using System.Net.Http;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using Oqtane.Documentation;
|
|
||||||
using Oqtane.Shared;
|
|
||||||
using Oqtane.Models;
|
|
||||||
|
|
||||||
namespace Oqtane.Services
|
|
||||||
{
|
|
||||||
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
|
||||||
public class ApiService : ServiceBase, IApiService
|
|
||||||
{
|
|
||||||
public ApiService(HttpClient http, SiteState siteState) : base(http, siteState) { }
|
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl("Api");
|
|
||||||
|
|
||||||
public async Task<List<Api>> GetApisAsync(int siteId)
|
|
||||||
{
|
|
||||||
return await GetJsonAsync<List<Api>>($"{Apiurl}?siteid={siteId}");
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<Api> GetApiAsync(int siteId, string entityName)
|
|
||||||
{
|
|
||||||
return await GetJsonAsync<Api>($"{Apiurl}/{siteId}/{entityName}");
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task UpdateApiAsync(Api api)
|
|
||||||
{
|
|
||||||
await PostJsonAsync(Apiurl, api);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Oqtane.Models;
|
|
||||||
|
|
||||||
namespace Oqtane.Services
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Service to retrieve and update API information.
|
|
||||||
/// </summary>
|
|
||||||
public interface IApiService
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// returns a list of APIs
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
Task<List<Api>> GetApisAsync(int siteId);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// returns a specific API
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
Task<Api> GetApiAsync(int siteId, string entityName);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Updates an API
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="api"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
Task UpdateApiAsync(Api api);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -33,7 +33,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.Permissions))
|
@if (_canViewAdminDashboard || UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.Permissions))
|
||||||
{
|
{
|
||||||
<button type="button" class="btn @ButtonClass" data-bs-toggle="offcanvas" data-bs-target="#offcanvasControlPanel" aria-controls="offcanvasControlPanel">
|
<button type="button" class="btn @ButtonClass" data-bs-toggle="offcanvas" data-bs-target="#offcanvasControlPanel" aria-controls="offcanvasControlPanel">
|
||||||
<span class="oi oi-cog"></span>
|
<span class="oi oi-cog"></span>
|
||||||
|
@ -46,16 +46,17 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="@BodyClass">
|
<div class="@BodyClass">
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
@if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Admin))
|
@if (_canViewAdminDashboard)
|
||||||
{
|
{
|
||||||
<div class="row d-flex">
|
<div class="row d-flex">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<button type="button" data-bs-dismiss="offcanvas" class="btn btn-primary col-12" @onclick=@(async () => Navigate("Admin"))>@Localizer["AdminDash"]</button>
|
<button type="button" data-bs-dismiss="offcanvas" class="btn btn-primary col-12" @onclick=@(async () => Navigate("Admin"))>@Localizer["AdminDash"]</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<hr class="app-rule" />
|
<hr class="app-rule" />
|
||||||
|
}
|
||||||
|
@if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Admin))
|
||||||
|
{
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col text-center">
|
<div class="col text-center">
|
||||||
<label class="control-label">@Localizer["Page.Manage"] </label>
|
<label class="control-label">@Localizer["Page.Manage"] </label>
|
||||||
|
@ -80,7 +81,7 @@
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
<hr class="app-rule" />
|
||||||
|
|
||||||
@if (_deleteConfirmation)
|
@if (_deleteConfirmation)
|
||||||
{
|
{
|
||||||
|
@ -104,7 +105,10 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
<hr class="app-rule" />
|
}
|
||||||
|
|
||||||
|
@if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.Permissions))
|
||||||
|
{
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col text-center">
|
<div class="col text-center">
|
||||||
<label for="Module" class="control-label">@Localizer["Module.Manage"] </label>
|
<label for="Module" class="control-label">@Localizer["Module.Manage"] </label>
|
||||||
|
@ -212,12 +216,14 @@
|
||||||
</div>
|
</div>
|
||||||
<button type="button" class="btn btn-primary col-12 mt-4" @onclick="@AddModule">@Localizer["Page.Module.Add"]</button>
|
<button type="button" class="btn btn-primary col-12 mt-4" @onclick="@AddModule">@Localizer["Page.Module.Add"]</button>
|
||||||
@((MarkupString)Message)
|
@((MarkupString)Message)
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
@code{
|
@code{
|
||||||
|
private bool _canViewAdminDashboard = false;
|
||||||
private bool _showEditMode = false;
|
private bool _showEditMode = false;
|
||||||
private bool _deleteConfirmation = false;
|
private bool _deleteConfirmation = false;
|
||||||
private List<string> _categories = new List<string>();
|
private List<string> _categories = new List<string>();
|
||||||
|
@ -286,6 +292,7 @@
|
||||||
|
|
||||||
protected override async Task OnParametersSetAsync()
|
protected override async Task OnParametersSetAsync()
|
||||||
{
|
{
|
||||||
|
_canViewAdminDashboard = CanViewAdminDashboard();
|
||||||
_showEditMode = false;
|
_showEditMode = false;
|
||||||
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.Permissions))
|
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.Permissions))
|
||||||
{
|
{
|
||||||
|
@ -321,6 +328,22 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool CanViewAdminDashboard()
|
||||||
|
{
|
||||||
|
var admin = PageState.Pages.FirstOrDefault(item => item.Path == "admin");
|
||||||
|
if (admin != null)
|
||||||
|
{
|
||||||
|
foreach (var page in PageState.Pages.Where(item => item.ParentId == admin?.PageId))
|
||||||
|
{
|
||||||
|
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, page.Permissions))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private void CategoryChanged(ChangeEventArgs e)
|
private void CategoryChanged(ChangeEventArgs e)
|
||||||
{
|
{
|
||||||
Category = (string)e.Value;
|
Category = (string)e.Value;
|
||||||
|
@ -465,12 +488,10 @@
|
||||||
case "Admin":
|
case "Admin":
|
||||||
// get admin dashboard moduleid
|
// get admin dashboard moduleid
|
||||||
module = PageState.Modules.FirstOrDefault(item => item.ModuleDefinitionName == Constants.AdminDashboardModule);
|
module = PageState.Modules.FirstOrDefault(item => item.ModuleDefinitionName == Constants.AdminDashboardModule);
|
||||||
|
|
||||||
if (module != null)
|
if (module != null)
|
||||||
{
|
{
|
||||||
NavigationManager.NavigateTo(EditUrl(PageState.Page.Path, module.ModuleId, "Index", ""));
|
NavigationManager.NavigateTo(EditUrl(PageState.Page.Path, module.ModuleId, "Index", ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case "Add":
|
case "Add":
|
||||||
case "Edit":
|
case "Edit":
|
||||||
|
@ -551,19 +572,19 @@
|
||||||
{
|
{
|
||||||
page.IsDeleted = true;
|
page.IsDeleted = true;
|
||||||
await PageService.UpdatePageAsync(page);
|
await PageService.UpdatePageAsync(page);
|
||||||
await logger.Log(page.PageId, null, PageState.User.UserId, GetType().AssemblyQualifiedName, "ControlPanel", LogFunction.Delete, LogLevel.Information, null, "Page Deleted {Page}", page);
|
await logger.Log(page.PageId, null, PageState.User?.UserId, GetType().AssemblyQualifiedName, "ControlPanel", LogFunction.Delete, LogLevel.Information, null, "Page Deleted {Page}", page);
|
||||||
NavigationManager.NavigateTo(NavigateUrl(""));
|
NavigationManager.NavigateTo(NavigateUrl(""));
|
||||||
}
|
}
|
||||||
else // personalized page
|
else // personalized page
|
||||||
{
|
{
|
||||||
await PageService.DeletePageAsync(page.PageId);
|
await PageService.DeletePageAsync(page.PageId);
|
||||||
await logger.Log(page.PageId, null, PageState.User.UserId, GetType().AssemblyQualifiedName, "ControlPanel", LogFunction.Delete, LogLevel.Information, null, "Page Deleted {Page}", page);
|
await logger.Log(page.PageId, null, PageState.User?.UserId, GetType().AssemblyQualifiedName, "ControlPanel", LogFunction.Delete, LogLevel.Information, null, "Page Deleted {Page}", page);
|
||||||
NavigationManager.NavigateTo(NavigateUrl());
|
NavigationManager.NavigateTo(NavigateUrl());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await logger.Log(page.PageId, null, PageState.User.UserId, GetType().AssemblyQualifiedName, "ControlPanel", LogFunction.Delete, LogLevel.Information, ex, "Page Deleted {Page} {Error}", page, ex.Message);
|
await logger.Log(page.PageId, null, PageState.User?.UserId, GetType().AssemblyQualifiedName, "ControlPanel", LogFunction.Delete, LogLevel.Information, ex, "Page Deleted {Page} {Error}", page, ex.Message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -596,8 +617,8 @@
|
||||||
private async Task UpdateSettingsAsync()
|
private async Task UpdateSettingsAsync()
|
||||||
{
|
{
|
||||||
Dictionary<string, string> settings = await SettingService.GetUserSettingsAsync(PageState.User.UserId);
|
Dictionary<string, string> settings = await SettingService.GetUserSettingsAsync(PageState.User.UserId);
|
||||||
SettingService.SetSetting(settings, settingCategory, _category);
|
settings = SettingService.SetSetting(settings, settingCategory, _category);
|
||||||
SettingService.SetSetting(settings, settingPane, _pane);
|
settings = SettingService.SetSetting(settings, settingPane, _pane);
|
||||||
await SettingService.UpdateUserSettingsAsync(settings, PageState.User.UserId);
|
await SettingService.UpdateUserSettingsAsync(settings, PageState.User.UserId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ namespace Oqtane.Themes.Controls
|
||||||
|
|
||||||
protected async Task LogoutUser()
|
protected async Task LogoutUser()
|
||||||
{
|
{
|
||||||
await LoggingService.Log(PageState.Alias, PageState.Page.PageId, null, PageState.User.UserId, GetType().AssemblyQualifiedName, "Logout", LogFunction.Security, LogLevel.Information, null, "User Logout For Username {Username}", PageState.User.Username);
|
await LoggingService.Log(PageState.Alias, PageState.Page.PageId, null, PageState.User?.UserId, GetType().AssemblyQualifiedName, "Logout", LogFunction.Security, LogLevel.Information, null, "User Logout For Username {Username}", PageState.User?.Username);
|
||||||
|
|
||||||
// check if anonymous user can access page
|
// check if anonymous user can access page
|
||||||
var url = PageState.Alias.Path + "/" + PageState.Page.Path;
|
var url = PageState.Alias.Path + "/" + PageState.Page.Path;
|
||||||
|
|
|
@ -87,10 +87,9 @@ else
|
||||||
// retrieve friendly localized error
|
// retrieve friendly localized error
|
||||||
_error = Localizer["Error.Module.Exception"];
|
_error = Localizer["Error.Module.Exception"];
|
||||||
// log error
|
// log error
|
||||||
int? userId = (PageState.User != null) ? PageState.User.UserId : null;
|
|
||||||
string category = GetType().AssemblyQualifiedName;
|
string category = GetType().AssemblyQualifiedName;
|
||||||
string feature = Utilities.GetTypeNameLastSegment(category, 1);
|
string feature = Utilities.GetTypeNameLastSegment(category, 1);
|
||||||
await LoggingService.Log(null, ModuleState.PageId, ModuleState.ModuleId, userId, category, feature, LogFunction.Other, LogLevel.Error, exception, "An Unexpected Error Has Occurred In {ModuleDefinitionName}: {Error}", ModuleState.ModuleDefinitionName, exception.Message);
|
await LoggingService.Log(null, ModuleState.PageId, ModuleState.ModuleId, PageState.User?.UserId, category, feature, LogFunction.Other, LogLevel.Error, exception, "An Unexpected Error Has Occurred In {ModuleDefinitionName}: {Error}", ModuleState.ModuleDefinitionName, exception.Message);
|
||||||
await base.OnErrorAsync(exception);
|
await base.OnErrorAsync(exception);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,172 +0,0 @@
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Authorization;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using Oqtane.Shared;
|
|
||||||
using Oqtane.Models;
|
|
||||||
using Oqtane.Infrastructure;
|
|
||||||
using Oqtane.Enums;
|
|
||||||
using System.Net;
|
|
||||||
using Oqtane.Repository;
|
|
||||||
using Oqtane.Extensions;
|
|
||||||
using System.Reflection;
|
|
||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace Oqtane.Controllers
|
|
||||||
{
|
|
||||||
[Route(ControllerRoutes.ApiRoute)]
|
|
||||||
public class ApiController : Controller
|
|
||||||
{
|
|
||||||
private readonly IPermissionRepository _permissions;
|
|
||||||
private readonly IRoleRepository _roles;
|
|
||||||
private readonly ILogManager _logger;
|
|
||||||
private readonly Alias _alias;
|
|
||||||
|
|
||||||
public ApiController(IPermissionRepository permissions, IRoleRepository roles, ILogManager logger, ITenantManager tenantManager)
|
|
||||||
{
|
|
||||||
_permissions = permissions;
|
|
||||||
_roles = roles;
|
|
||||||
_logger = logger;
|
|
||||||
_alias = tenantManager.GetAlias();
|
|
||||||
}
|
|
||||||
|
|
||||||
// GET: api/<controller>?siteid=x
|
|
||||||
[HttpGet]
|
|
||||||
[Authorize(Roles = RoleNames.Admin)]
|
|
||||||
public List<Api> Get(string siteid)
|
|
||||||
{
|
|
||||||
int SiteId;
|
|
||||||
if (int.TryParse(siteid, out SiteId) && SiteId == _alias.SiteId)
|
|
||||||
{
|
|
||||||
var apis = new List<Api>();
|
|
||||||
|
|
||||||
var assemblies = AppDomain.CurrentDomain.GetOqtaneAssemblies();
|
|
||||||
foreach (var assembly in assemblies)
|
|
||||||
{
|
|
||||||
// iterate controllers
|
|
||||||
foreach (var type in assembly.GetTypes().Where(type => typeof(Controller).IsAssignableFrom(type)))
|
|
||||||
{
|
|
||||||
// iterate controller methods with authorize attribute
|
|
||||||
var actions = type.GetMethods(BindingFlags.Public | BindingFlags.Instance)
|
|
||||||
.Where(m => m.GetCustomAttributes<AuthorizeAttribute>().Any());
|
|
||||||
foreach(var action in actions)
|
|
||||||
{
|
|
||||||
// get policy
|
|
||||||
var policy = action.GetCustomAttribute<AuthorizeAttribute>().Policy;
|
|
||||||
if (!string.IsNullOrEmpty(policy) && policy.Contains(":") && !policy.Contains(Constants.RequireEntityId))
|
|
||||||
{
|
|
||||||
// parse policy
|
|
||||||
var segments = policy.Split(':');
|
|
||||||
if (!apis.Any(item => item.EntityName == segments[0]))
|
|
||||||
{
|
|
||||||
apis.Add(new Api { SiteId = SiteId, EntityName = segments[0], Permissions = segments[1] });
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// concatenate permissions
|
|
||||||
var permissions = apis.SingleOrDefault(item => item.EntityName == segments[0]).Permissions;
|
|
||||||
if (!permissions.Split(',').Contains(segments[1]))
|
|
||||||
{
|
|
||||||
apis.SingleOrDefault(item => item.EntityName == segments[0]).Permissions += "," + segments[1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return apis;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Api Get Attempt {SiteId}", siteid);
|
|
||||||
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GET: api/<controller>/1/user
|
|
||||||
[HttpGet("{siteid}/{entityname}")]
|
|
||||||
[Authorize(Roles = RoleNames.Admin)]
|
|
||||||
public Api Get(int siteid, string entityname)
|
|
||||||
{
|
|
||||||
if (siteid == _alias.SiteId)
|
|
||||||
{
|
|
||||||
var permissions = _permissions.GetPermissions(siteid, entityname);
|
|
||||||
if (permissions == null || permissions.ToList().Count == 0)
|
|
||||||
{
|
|
||||||
permissions = GetPermissions(siteid, entityname);
|
|
||||||
}
|
|
||||||
return new Api { SiteId = siteid, EntityName = entityname, Permissions = permissions.EncodePermissions() };
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Api Get Attempt {SiteId} {EntityName}", siteid, entityname);
|
|
||||||
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// POST: api/<controller>
|
|
||||||
[HttpPost]
|
|
||||||
[Authorize(Roles = RoleNames.Admin)]
|
|
||||||
public void Post([FromBody] Api api)
|
|
||||||
{
|
|
||||||
if (ModelState.IsValid && api.SiteId == _alias.SiteId)
|
|
||||||
{
|
|
||||||
_permissions.UpdatePermissions(api.SiteId, api.EntityName, -1, api.Permissions);
|
|
||||||
_logger.Log(LogLevel.Information, this, LogFunction.Update, "Api Updated {Api}", api);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Api Post Attempt {Api}", api);
|
|
||||||
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<Permission> GetPermissions(int siteid, string entityname)
|
|
||||||
{
|
|
||||||
var permissions = new List<Permission>();
|
|
||||||
|
|
||||||
var assemblies = AppDomain.CurrentDomain.GetOqtaneAssemblies();
|
|
||||||
foreach (var assembly in assemblies)
|
|
||||||
{
|
|
||||||
// iterate controllers
|
|
||||||
foreach (var type in assembly.GetTypes().Where(type => typeof(Controller).IsAssignableFrom(type)))
|
|
||||||
{
|
|
||||||
// iterate controller methods with authorize attribute
|
|
||||||
var actions = type.GetMethods(BindingFlags.Public | BindingFlags.Instance)
|
|
||||||
.Where(m => m.GetCustomAttributes<AuthorizeAttribute>().Any());
|
|
||||||
foreach (var action in actions)
|
|
||||||
{
|
|
||||||
// get policy
|
|
||||||
var policy = action.GetCustomAttribute<AuthorizeAttribute>().Policy;
|
|
||||||
if (!string.IsNullOrEmpty(policy) && policy.Contains(":") && !policy.Contains(Constants.RequireEntityId))
|
|
||||||
{
|
|
||||||
// parse policy
|
|
||||||
var segments = policy.Split(':');
|
|
||||||
// entity match
|
|
||||||
if (segments[0] == entityname && segments.Length > 2)
|
|
||||||
{
|
|
||||||
var roles = _roles.GetRoles(siteid);
|
|
||||||
foreach (var rolename in (segments[2]).Split(','))
|
|
||||||
{
|
|
||||||
var role = roles.FirstOrDefault(item => item.Name == rolename);
|
|
||||||
if (role != null)
|
|
||||||
{
|
|
||||||
if (!permissions.Any(item => item.EntityName == entityname && item.PermissionName == segments[1] && item.RoleId == role.RoleId))
|
|
||||||
{
|
|
||||||
permissions.Add(new Permission { SiteId = siteid, EntityName = entityname, EntityId = -1, PermissionName = segments[1], RoleId = role.RoleId, Role = role, UserId = null, IsAuthorized = true });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return permissions;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -47,7 +47,6 @@ namespace Oqtane.Controllers
|
||||||
int SiteId;
|
int SiteId;
|
||||||
if (int.TryParse(siteid, out SiteId) && SiteId == _alias.SiteId)
|
if (int.TryParse(siteid, out SiteId) && SiteId == _alias.SiteId)
|
||||||
{
|
{
|
||||||
List<ModuleDefinition> moduledefinitions = _moduleDefinitions.GetModuleDefinitions(SiteId).ToList();
|
|
||||||
List<Setting> settings = _settings.GetSettings(EntityNames.Module).ToList();
|
List<Setting> settings = _settings.GetSettings(EntityNames.Module).ToList();
|
||||||
|
|
||||||
foreach (PageModule pagemodule in _pageModules.GetPageModules(SiteId))
|
foreach (PageModule pagemodule in _pageModules.GetPageModules(SiteId))
|
||||||
|
@ -75,7 +74,6 @@ namespace Oqtane.Controllers
|
||||||
module.Order = pagemodule.Order;
|
module.Order = pagemodule.Order;
|
||||||
module.ContainerType = pagemodule.ContainerType;
|
module.ContainerType = pagemodule.ContainerType;
|
||||||
|
|
||||||
module.ModuleDefinition = moduledefinitions.Find(item => item.ModuleDefinitionName == module.ModuleDefinitionName);
|
|
||||||
module.Settings = settings.Where(item => item.EntityId == pagemodule.ModuleId)
|
module.Settings = settings.Where(item => item.EntityId == pagemodule.ModuleId)
|
||||||
.Where(item => !item.IsPrivate || _userPermissions.IsAuthorized(User, PermissionNames.Edit, pagemodule.Module.Permissions))
|
.Where(item => !item.IsPrivate || _userPermissions.IsAuthorized(User, PermissionNames.Edit, pagemodule.Module.Permissions))
|
||||||
.ToDictionary(setting => setting.SettingName, setting => setting.SettingValue);
|
.ToDictionary(setting => setting.SettingName, setting => setting.SettingValue);
|
||||||
|
|
|
@ -281,7 +281,7 @@ namespace Oqtane.Controllers
|
||||||
// synchronize module permissions
|
// synchronize module permissions
|
||||||
if (added.Count > 0 || removed.Count > 0)
|
if (added.Count > 0 || removed.Count > 0)
|
||||||
{
|
{
|
||||||
foreach (PageModule pageModule in _pageModules.GetPageModules(page.PageId, "").ToList())
|
foreach (PageModule pageModule in _pageModules.GetPageModules(page.SiteId).Where(item => item.PageId == page.PageId).ToList())
|
||||||
{
|
{
|
||||||
var modulePermissions = _permissionRepository.GetPermissions(pageModule.Module.SiteId, EntityNames.Module, pageModule.Module.ModuleId).ToList();
|
var modulePermissions = _permissionRepository.GetPermissions(pageModule.Module.SiteId, EntityNames.Module, pageModule.Module.ModuleId).ToList();
|
||||||
// permissions added
|
// permissions added
|
||||||
|
|
|
@ -120,7 +120,8 @@ namespace Oqtane.Controllers
|
||||||
if (page != null && page.SiteId == _alias.SiteId && _userPermissions.IsAuthorized(User, page.SiteId, EntityNames.Page, pageid, PermissionNames.Edit))
|
if (page != null && page.SiteId == _alias.SiteId && _userPermissions.IsAuthorized(User, page.SiteId, EntityNames.Page, pageid, PermissionNames.Edit))
|
||||||
{
|
{
|
||||||
int order = 1;
|
int order = 1;
|
||||||
List<PageModule> pagemodules = _pageModules.GetPageModules(pageid, pane).OrderBy(item => item.Order).ToList();
|
List<PageModule> pagemodules = _pageModules.GetPageModules(page.SiteId)
|
||||||
|
.Where(item => item.PageId == pageid && item.Pane == pane).OrderBy(item => item.Order).ToList();
|
||||||
foreach (PageModule pagemodule in pagemodules)
|
foreach (PageModule pagemodule in pagemodules)
|
||||||
{
|
{
|
||||||
if (pagemodule.Order != order)
|
if (pagemodule.Order != order)
|
||||||
|
|
|
@ -28,7 +28,7 @@ namespace Oqtane.Controllers
|
||||||
|
|
||||||
// GET: api/<controller>?siteid=x
|
// GET: api/<controller>?siteid=x
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[Authorize(Policy = $"{EntityNames.Profile}:{PermissionNames.Read}:{RoleNames.Registered}")]
|
[Authorize(Roles = RoleNames.Registered)]
|
||||||
public IEnumerable<Profile> Get(string siteid)
|
public IEnumerable<Profile> Get(string siteid)
|
||||||
{
|
{
|
||||||
int SiteId;
|
int SiteId;
|
||||||
|
@ -46,7 +46,7 @@ namespace Oqtane.Controllers
|
||||||
|
|
||||||
// GET api/<controller>/5
|
// GET api/<controller>/5
|
||||||
[HttpGet("{id}")]
|
[HttpGet("{id}")]
|
||||||
[Authorize(Policy = $"{EntityNames.Profile}:{PermissionNames.Read}:{RoleNames.Registered}")]
|
[Authorize(Roles = RoleNames.Registered)]
|
||||||
public Profile Get(int id)
|
public Profile Get(int id)
|
||||||
{
|
{
|
||||||
var profile = _profiles.GetProfile(id);
|
var profile = _profiles.GetProfile(id);
|
||||||
|
|
|
@ -28,7 +28,7 @@ namespace Oqtane.Controllers
|
||||||
|
|
||||||
// GET: api/<controller>?siteid=x&global=true/false
|
// GET: api/<controller>?siteid=x&global=true/false
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[Authorize(Policy = $"{EntityNames.Role}:{PermissionNames.Read}:{RoleNames.Registered}")]
|
[Authorize(Roles = RoleNames.Registered)]
|
||||||
public IEnumerable<Role> Get(string siteid, string global)
|
public IEnumerable<Role> Get(string siteid, string global)
|
||||||
{
|
{
|
||||||
int SiteId;
|
int SiteId;
|
||||||
|
@ -50,7 +50,7 @@ namespace Oqtane.Controllers
|
||||||
|
|
||||||
// GET api/<controller>/5
|
// GET api/<controller>/5
|
||||||
[HttpGet("{id}")]
|
[HttpGet("{id}")]
|
||||||
[Authorize(Policy = $"{EntityNames.Role}:{PermissionNames.Read}:{RoleNames.Registered}")]
|
[Authorize(Roles = RoleNames.Registered)]
|
||||||
public Role Get(int id)
|
public Role Get(int id)
|
||||||
{
|
{
|
||||||
var role = _roles.GetRole(id);
|
var role = _roles.GetRole(id);
|
||||||
|
|
|
@ -212,7 +212,7 @@ namespace Oqtane.Controllers
|
||||||
authorized = true;
|
authorized = true;
|
||||||
if (permissionName == PermissionNames.Edit)
|
if (permissionName == PermissionNames.Edit)
|
||||||
{
|
{
|
||||||
authorized = User.IsInRole(RoleNames.Admin) || (_userPermissions.GetUser(User).UserId == entityId);
|
authorized = _userPermissions.IsAuthorized(User, _alias.SiteId, entityName, -1, PermissionNames.Write, RoleNames.Admin) || (_userPermissions.GetUser(User).UserId == entityId);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case EntityNames.Visitor:
|
case EntityNames.Visitor:
|
||||||
|
@ -226,14 +226,11 @@ namespace Oqtane.Controllers
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default: // custom entity
|
default: // custom entity
|
||||||
|
authorized = true;
|
||||||
if (permissionName == PermissionNames.Edit)
|
if (permissionName == PermissionNames.Edit)
|
||||||
{
|
{
|
||||||
authorized = User.IsInRole(RoleNames.Admin) || _userPermissions.IsAuthorized(User, _alias.SiteId, entityName, entityId, permissionName);
|
authorized = User.IsInRole(RoleNames.Admin) || _userPermissions.IsAuthorized(User, _alias.SiteId, entityName, entityId, permissionName);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
authorized = true;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return authorized;
|
return authorized;
|
||||||
|
|
|
@ -29,23 +29,25 @@ namespace Oqtane.Controllers
|
||||||
private readonly ITenantManager _tenantManager;
|
private readonly ITenantManager _tenantManager;
|
||||||
private readonly INotificationRepository _notifications;
|
private readonly INotificationRepository _notifications;
|
||||||
private readonly IFolderRepository _folders;
|
private readonly IFolderRepository _folders;
|
||||||
private readonly ISyncManager _syncManager;
|
|
||||||
private readonly ISiteRepository _sites;
|
private readonly ISiteRepository _sites;
|
||||||
|
private readonly IUserPermissions _userPermissions;
|
||||||
private readonly IJwtManager _jwtManager;
|
private readonly IJwtManager _jwtManager;
|
||||||
|
private readonly ISyncManager _syncManager;
|
||||||
private readonly ILogManager _logger;
|
private readonly ILogManager _logger;
|
||||||
|
|
||||||
public UserController(IUserRepository users, IUserRoleRepository userRoles, UserManager<IdentityUser> identityUserManager, SignInManager<IdentityUser> identitySignInManager, ITenantManager tenantManager, INotificationRepository notifications, IFolderRepository folders, ISyncManager syncManager, ISiteRepository sites, IJwtManager jwtManager, ILogManager logger)
|
public UserController(IUserRepository users, IUserRoleRepository userRoles, UserManager<IdentityUser> identityUserManager, SignInManager<IdentityUser> identitySignInManager, ITenantManager tenantManager, INotificationRepository notifications, IFolderRepository folders, ISiteRepository sites, IUserPermissions userPermissions, IJwtManager jwtManager, ISyncManager syncManager, ILogManager logger)
|
||||||
{
|
{
|
||||||
_users = users;
|
_users = users;
|
||||||
_userRoles = userRoles;
|
_userRoles = userRoles;
|
||||||
_identityUserManager = identityUserManager;
|
_identityUserManager = identityUserManager;
|
||||||
_identitySignInManager = identitySignInManager;
|
_identitySignInManager = identitySignInManager;
|
||||||
_tenantManager = tenantManager;
|
_tenantManager = tenantManager;
|
||||||
_folders = folders;
|
|
||||||
_notifications = notifications;
|
_notifications = notifications;
|
||||||
_syncManager = syncManager;
|
_folders = folders;
|
||||||
_sites = sites;
|
_sites = sites;
|
||||||
|
_userPermissions = userPermissions;
|
||||||
_jwtManager = jwtManager;
|
_jwtManager = jwtManager;
|
||||||
|
_syncManager = syncManager;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,7 +107,7 @@ namespace Oqtane.Controllers
|
||||||
user.TwoFactorCode = "";
|
user.TwoFactorCode = "";
|
||||||
user.TwoFactorExpiry = null;
|
user.TwoFactorExpiry = null;
|
||||||
|
|
||||||
if (!User.IsInRole(RoleNames.Admin) && User.Identity.Name?.ToLower() != user.Username.ToLower())
|
if (!_userPermissions.IsAuthorized(User, user.SiteId, EntityNames.User, -1, PermissionNames.Write, RoleNames.Admin) && User.Identity.Name?.ToLower() != user.Username.ToLower())
|
||||||
{
|
{
|
||||||
user.Email = "";
|
user.Email = "";
|
||||||
user.PhotoFileId = null;
|
user.PhotoFileId = null;
|
||||||
|
@ -149,7 +151,7 @@ namespace Oqtane.Controllers
|
||||||
|
|
||||||
bool verified;
|
bool verified;
|
||||||
bool allowregistration;
|
bool allowregistration;
|
||||||
if (User.IsInRole(RoleNames.Admin))
|
if (_userPermissions.IsAuthorized(User, user.SiteId, EntityNames.User, -1, PermissionNames.Write, RoleNames.Admin))
|
||||||
{
|
{
|
||||||
verified = true;
|
verified = true;
|
||||||
allowregistration = true;
|
allowregistration = true;
|
||||||
|
@ -241,7 +243,8 @@ namespace Oqtane.Controllers
|
||||||
[Authorize]
|
[Authorize]
|
||||||
public async Task<User> Put(int id, [FromBody] User user)
|
public async Task<User> Put(int id, [FromBody] User user)
|
||||||
{
|
{
|
||||||
if (ModelState.IsValid && user.SiteId == _tenantManager.GetAlias().SiteId && _users.GetUser(user.UserId, false) != null && (User.IsInRole(RoleNames.Admin) || User.Identity.Name == user.Username))
|
if (ModelState.IsValid && user.SiteId == _tenantManager.GetAlias().SiteId && _users.GetUser(user.UserId, false) != null
|
||||||
|
&& (_userPermissions.IsAuthorized(User, user.SiteId, EntityNames.User, -1, PermissionNames.Write, RoleNames.Admin) || User.Identity.Name == user.Username))
|
||||||
{
|
{
|
||||||
IdentityUser identityuser = await _identityUserManager.FindByNameAsync(user.Username);
|
IdentityUser identityuser = await _identityUserManager.FindByNameAsync(user.Username);
|
||||||
if (identityuser != null)
|
if (identityuser != null)
|
||||||
|
@ -287,7 +290,7 @@ namespace Oqtane.Controllers
|
||||||
|
|
||||||
// DELETE api/<controller>/5?siteid=x
|
// DELETE api/<controller>/5?siteid=x
|
||||||
[HttpDelete("{id}")]
|
[HttpDelete("{id}")]
|
||||||
[Authorize(Roles = RoleNames.Admin)]
|
[Authorize(Policy = $"{EntityNames.User}:{PermissionNames.Write}:{RoleNames.Admin}")]
|
||||||
public async Task Delete(int id, string siteid)
|
public async Task Delete(int id, string siteid)
|
||||||
{
|
{
|
||||||
int SiteId;
|
int SiteId;
|
||||||
|
|
|
@ -10,6 +10,7 @@ using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using Oqtane.Security;
|
using Oqtane.Security;
|
||||||
using System;
|
using System;
|
||||||
|
using Oqtane.Modules.Admin.Roles;
|
||||||
|
|
||||||
namespace Oqtane.Controllers
|
namespace Oqtane.Controllers
|
||||||
{
|
{
|
||||||
|
@ -93,7 +94,7 @@ namespace Oqtane.Controllers
|
||||||
userrole.User.TwoFactorCode = "";
|
userrole.User.TwoFactorCode = "";
|
||||||
userrole.User.TwoFactorExpiry = null;
|
userrole.User.TwoFactorExpiry = null;
|
||||||
|
|
||||||
if (!User.IsInRole(RoleNames.Admin) && userid != userrole.User.UserId)
|
if (!_userPermissions.IsAuthorized(User, userrole.User.SiteId, EntityNames.User, -1, PermissionNames.Write, RoleNames.Admin) && userid != userrole.User.UserId)
|
||||||
{
|
{
|
||||||
userrole.User.Email = "";
|
userrole.User.Email = "";
|
||||||
userrole.User.PhotoFileId = null;
|
userrole.User.PhotoFileId = null;
|
||||||
|
@ -115,7 +116,7 @@ namespace Oqtane.Controllers
|
||||||
|
|
||||||
// POST api/<controller>
|
// POST api/<controller>
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
[Authorize(Roles = RoleNames.Admin)]
|
[Authorize(Policy = $"{EntityNames.UserRole}:{PermissionNames.Write}:{RoleNames.Admin}")]
|
||||||
public UserRole Post([FromBody] UserRole userRole)
|
public UserRole Post([FromBody] UserRole userRole)
|
||||||
{
|
{
|
||||||
var role = _roles.GetRole(userRole.RoleId);
|
var role = _roles.GetRole(userRole.RoleId);
|
||||||
|
@ -138,7 +139,7 @@ namespace Oqtane.Controllers
|
||||||
|
|
||||||
// PUT api/<controller>/5
|
// PUT api/<controller>/5
|
||||||
[HttpPut("{id}")]
|
[HttpPut("{id}")]
|
||||||
[Authorize(Roles = RoleNames.Admin)]
|
[Authorize(Policy = $"{EntityNames.UserRole}:{PermissionNames.Write}:{RoleNames.Admin}")]
|
||||||
public UserRole Put(int id, [FromBody] UserRole userRole)
|
public UserRole Put(int id, [FromBody] UserRole userRole)
|
||||||
{
|
{
|
||||||
var role = _roles.GetRole(userRole.RoleId);
|
var role = _roles.GetRole(userRole.RoleId);
|
||||||
|
@ -160,7 +161,7 @@ namespace Oqtane.Controllers
|
||||||
|
|
||||||
// DELETE api/<controller>/5
|
// DELETE api/<controller>/5
|
||||||
[HttpDelete("{id}")]
|
[HttpDelete("{id}")]
|
||||||
[Authorize(Roles = RoleNames.Admin)]
|
[Authorize(Policy = $"{EntityNames.UserRole}:{PermissionNames.Write}:{RoleNames.Admin}")]
|
||||||
public void Delete(int id)
|
public void Delete(int id)
|
||||||
{
|
{
|
||||||
UserRole userrole = _userRoles.GetUserRole(id);
|
UserRole userrole = _userRoles.GetUserRole(id);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
@ -11,20 +11,22 @@ namespace Oqtane.Extensions
|
||||||
public static string EncodePermissions(this IEnumerable<Permission> permissionList)
|
public static string EncodePermissions(this IEnumerable<Permission> permissionList)
|
||||||
{
|
{
|
||||||
List<PermissionString> permissionstrings = new List<PermissionString>();
|
List<PermissionString> permissionstrings = new List<PermissionString>();
|
||||||
|
string entityname = "";
|
||||||
string permissionname = "";
|
string permissionname = "";
|
||||||
string permissions = "";
|
string permissions = "";
|
||||||
StringBuilder permissionsbuilder = new StringBuilder();
|
StringBuilder permissionsbuilder = new StringBuilder();
|
||||||
string securityid = "";
|
string securityid = "";
|
||||||
foreach (Permission permission in permissionList.OrderBy(item => item.PermissionName))
|
foreach (Permission permission in permissionList.OrderBy(item => item.EntityName).ThenBy(item => item.PermissionName))
|
||||||
{
|
{
|
||||||
// permission collections are grouped by permissionname
|
// permission collections are grouped by entityname and permissionname
|
||||||
if (permissionname != permission.PermissionName)
|
if (entityname != permission.EntityName || permissionname != permission.PermissionName)
|
||||||
{
|
{
|
||||||
permissions = permissionsbuilder.ToString();
|
permissions = permissionsbuilder.ToString();
|
||||||
if (permissions != "")
|
if (permissions != "")
|
||||||
{
|
{
|
||||||
permissionstrings.Add(new PermissionString { PermissionName = permissionname, Permissions = permissions.Substring(0, permissions.Length - 1) });
|
permissionstrings.Add(new PermissionString { EntityName = entityname, PermissionName = permissionname, Permissions = permissions.Substring(0, permissions.Length - 1) });
|
||||||
}
|
}
|
||||||
|
entityname = permission.EntityName;
|
||||||
permissionname = permission.PermissionName;
|
permissionname = permission.PermissionName;
|
||||||
permissionsbuilder = new StringBuilder();
|
permissionsbuilder = new StringBuilder();
|
||||||
}
|
}
|
||||||
|
@ -56,7 +58,7 @@ namespace Oqtane.Extensions
|
||||||
permissions = permissionsbuilder.ToString();
|
permissions = permissionsbuilder.ToString();
|
||||||
if (permissions != "")
|
if (permissions != "")
|
||||||
{
|
{
|
||||||
permissionstrings.Add(new PermissionString { PermissionName = permissionname, Permissions = permissions.Substring(0, permissions.Length - 1) });
|
permissionstrings.Add(new PermissionString { EntityName = entityname, PermissionName = permissionname, Permissions = permissions.Substring(0, permissions.Length - 1) });
|
||||||
}
|
}
|
||||||
return JsonSerializer.Serialize(permissionstrings);
|
return JsonSerializer.Serialize(permissionstrings);
|
||||||
}
|
}
|
||||||
|
|
|
@ -308,43 +308,45 @@ namespace Oqtane.Infrastructure
|
||||||
|
|
||||||
private void Upgrade_3_3_0(Tenant tenant, IServiceScope scope)
|
private void Upgrade_3_3_0(Tenant tenant, IServiceScope scope)
|
||||||
{
|
{
|
||||||
var pageTemplates = new List<PageTemplate>();
|
try
|
||||||
|
|
||||||
pageTemplates.Add(new PageTemplate
|
|
||||||
{
|
{
|
||||||
Name = "API Management",
|
var roles = scope.ServiceProvider.GetRequiredService<IRoleRepository>();
|
||||||
Parent = "Admin",
|
|
||||||
Order = 35,
|
|
||||||
Path = "admin/apis",
|
|
||||||
Icon = Icons.CloudDownload,
|
|
||||||
IsNavigation = true,
|
|
||||||
IsPersonalizable = false,
|
|
||||||
PagePermissions = new List<Permission>
|
|
||||||
{
|
|
||||||
new Permission(PermissionNames.View, RoleNames.Admin, true),
|
|
||||||
new Permission(PermissionNames.Edit, RoleNames.Admin, true)
|
|
||||||
}.EncodePermissions(),
|
|
||||||
PageTemplateModules = new List<PageTemplateModule>
|
|
||||||
{
|
|
||||||
new PageTemplateModule
|
|
||||||
{
|
|
||||||
ModuleDefinitionName = typeof(Oqtane.Modules.Admin.Visitors.Index).ToModuleDefinitionName(), Title = "Visitor Management", Pane = PaneNames.Default,
|
|
||||||
ModulePermissions = new List<Permission>
|
|
||||||
{
|
|
||||||
new Permission(PermissionNames.View, RoleNames.Admin, true),
|
|
||||||
new Permission(PermissionNames.Edit, RoleNames.Admin, true)
|
|
||||||
}.EncodePermissions(),
|
|
||||||
Content = ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var pages = scope.ServiceProvider.GetRequiredService<IPageRepository>();
|
var pages = scope.ServiceProvider.GetRequiredService<IPageRepository>();
|
||||||
|
var modules = scope.ServiceProvider.GetRequiredService<IModuleRepository>();
|
||||||
var sites = scope.ServiceProvider.GetRequiredService<ISiteRepository>();
|
var permissions = scope.ServiceProvider.GetRequiredService<IPermissionRepository>();
|
||||||
foreach (Site site in sites.GetSites().ToList())
|
var siteRepository = scope.ServiceProvider.GetRequiredService<ISiteRepository>();
|
||||||
|
foreach (Site site in siteRepository.GetSites().ToList())
|
||||||
{
|
{
|
||||||
sites.CreatePages(site, pageTemplates);
|
int roleid = roles.GetRoles(site.SiteId).FirstOrDefault(item => item.Name == RoleNames.Registered).RoleId;
|
||||||
|
|
||||||
|
int pageid = pages.GetPages(site.SiteId).FirstOrDefault(item => item.Path == "admin").PageId;
|
||||||
|
var permission = new Permission
|
||||||
|
{
|
||||||
|
SiteId = site.SiteId,
|
||||||
|
EntityName = EntityNames.Page,
|
||||||
|
EntityId = pageid,
|
||||||
|
PermissionName = PermissionNames.View,
|
||||||
|
RoleId = roleid,
|
||||||
|
IsAuthorized = true
|
||||||
|
};
|
||||||
|
permissions.AddPermission(permission);
|
||||||
|
|
||||||
|
int moduleid = modules.GetModules(site.SiteId).FirstOrDefault(item => item.ModuleDefinitionName == "Oqtane.Modules.Admin.Dashboard, Oqtane.Client").ModuleId;
|
||||||
|
permission = new Permission
|
||||||
|
{
|
||||||
|
SiteId = site.SiteId,
|
||||||
|
EntityName = EntityNames.Module,
|
||||||
|
EntityId = moduleid,
|
||||||
|
PermissionName = PermissionNames.View,
|
||||||
|
RoleId = roleid,
|
||||||
|
IsAuthorized = true
|
||||||
|
};
|
||||||
|
permissions.AddPermission(permission);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Debug.WriteLine($"Oqtane Error: Error In 3.3.0 Upgrade Logic - {ex}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,6 @@ namespace Oqtane.Repository
|
||||||
public interface IPageModuleRepository
|
public interface IPageModuleRepository
|
||||||
{
|
{
|
||||||
IEnumerable<PageModule> GetPageModules(int siteId);
|
IEnumerable<PageModule> GetPageModules(int siteId);
|
||||||
IEnumerable<PageModule> GetPageModules(int pageId, string pane);
|
|
||||||
PageModule AddPageModule(PageModule pageModule);
|
PageModule AddPageModule(PageModule pageModule);
|
||||||
PageModule UpdatePageModule(PageModule pageModule);
|
PageModule UpdatePageModule(PageModule pageModule);
|
||||||
PageModule GetPageModule(int pageModuleId);
|
PageModule GetPageModule(int pageModuleId);
|
||||||
|
|
|
@ -10,46 +10,28 @@ namespace Oqtane.Repository
|
||||||
public class PageModuleRepository : IPageModuleRepository
|
public class PageModuleRepository : IPageModuleRepository
|
||||||
{
|
{
|
||||||
private TenantDBContext _db;
|
private TenantDBContext _db;
|
||||||
|
private readonly IModuleDefinitionRepository _moduleDefinitions;
|
||||||
private readonly IPermissionRepository _permissions;
|
private readonly IPermissionRepository _permissions;
|
||||||
|
|
||||||
public PageModuleRepository(TenantDBContext context, IPermissionRepository permissions)
|
public PageModuleRepository(TenantDBContext context, IModuleDefinitionRepository moduleDefinitions, IPermissionRepository permissions)
|
||||||
{
|
{
|
||||||
_db = context;
|
_db = context;
|
||||||
|
_moduleDefinitions = moduleDefinitions;
|
||||||
_permissions = permissions;
|
_permissions = permissions;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<PageModule> GetPageModules(int siteId)
|
public IEnumerable<PageModule> GetPageModules(int siteId)
|
||||||
{
|
{
|
||||||
IEnumerable<PageModule> pagemodules = _db.PageModule
|
var pagemodules = _db.PageModule
|
||||||
.Include(item => item.Module) // eager load modules
|
.Include(item => item.Module) // eager load modules
|
||||||
.Where(item => item.Module.SiteId == siteId);
|
.Where(item => item.Module.SiteId == siteId).ToList();
|
||||||
if (pagemodules.Any())
|
if (pagemodules.Any())
|
||||||
{
|
{
|
||||||
IEnumerable<Permission> permissions = _permissions.GetPermissions(siteId, EntityNames.Module).ToList();
|
var moduledefinitions = _moduleDefinitions.GetModuleDefinitions(siteId).ToList();
|
||||||
foreach (PageModule pagemodule in pagemodules)
|
var permissions = _permissions.GetPermissions(siteId, EntityNames.Module).ToList();
|
||||||
|
for (int index = 0; index < pagemodules.Count; index++)
|
||||||
{
|
{
|
||||||
pagemodule.Module.Permissions = permissions.Where(item => item.EntityId == pagemodule.ModuleId).EncodePermissions();
|
pagemodules[index] = GetPageModule(pagemodules[index], moduledefinitions, permissions);
|
||||||
}
|
|
||||||
}
|
|
||||||
return pagemodules;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<PageModule> GetPageModules(int pageId, string pane)
|
|
||||||
{
|
|
||||||
IEnumerable<PageModule> pagemodules = _db.PageModule
|
|
||||||
.Include(item => item.Module) // eager load modules
|
|
||||||
.Where(item => item.PageId == pageId);
|
|
||||||
if (pane != "" && pagemodules.Any())
|
|
||||||
{
|
|
||||||
pagemodules = pagemodules.Where(item => item.Pane == pane);
|
|
||||||
}
|
|
||||||
if (pagemodules.Any())
|
|
||||||
{
|
|
||||||
var siteId = pagemodules.FirstOrDefault().Module.SiteId;
|
|
||||||
IEnumerable<Permission> permissions = _permissions.GetPermissions(siteId, EntityNames.Module).ToList();
|
|
||||||
foreach (PageModule pagemodule in pagemodules)
|
|
||||||
{
|
|
||||||
pagemodule.Module.Permissions = permissions.Where(item => item.EntityId == pagemodule.ModuleId).EncodePermissions();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return pagemodules;
|
return pagemodules;
|
||||||
|
@ -89,7 +71,9 @@ namespace Oqtane.Repository
|
||||||
}
|
}
|
||||||
if (pagemodule != null)
|
if (pagemodule != null)
|
||||||
{
|
{
|
||||||
pagemodule.Module.Permissions = _permissions.GetPermissions(pagemodule.Module.SiteId, EntityNames.Module, pagemodule.ModuleId)?.EncodePermissions();
|
var moduledefinitions = _moduleDefinitions.GetModuleDefinitions(pagemodule.Module.SiteId).ToList();
|
||||||
|
var permissions = _permissions.GetPermissions(pagemodule.Module.SiteId, EntityNames.Module).ToList();
|
||||||
|
pagemodule = GetPageModule(pagemodule, moduledefinitions, permissions);
|
||||||
}
|
}
|
||||||
return pagemodule;
|
return pagemodule;
|
||||||
}
|
}
|
||||||
|
@ -100,7 +84,9 @@ namespace Oqtane.Repository
|
||||||
.SingleOrDefault(item => item.PageId == pageId && item.ModuleId == moduleId);
|
.SingleOrDefault(item => item.PageId == pageId && item.ModuleId == moduleId);
|
||||||
if (pagemodule != null)
|
if (pagemodule != null)
|
||||||
{
|
{
|
||||||
pagemodule.Module.Permissions = _permissions.GetPermissions(pagemodule.Module.SiteId, EntityNames.Module, pagemodule.ModuleId)?.EncodePermissions();
|
var moduledefinitions = _moduleDefinitions.GetModuleDefinitions(pagemodule.Module.SiteId).ToList();
|
||||||
|
var permissions = _permissions.GetPermissions(pagemodule.Module.SiteId, EntityNames.Module).ToList();
|
||||||
|
pagemodule = GetPageModule(pagemodule, moduledefinitions, permissions);
|
||||||
}
|
}
|
||||||
return pagemodule;
|
return pagemodule;
|
||||||
}
|
}
|
||||||
|
@ -111,5 +97,30 @@ namespace Oqtane.Repository
|
||||||
_db.PageModule.Remove(pageModule);
|
_db.PageModule.Remove(pageModule);
|
||||||
_db.SaveChanges();
|
_db.SaveChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private PageModule GetPageModule(PageModule pageModule, List<ModuleDefinition> moduleDefinitions, List<Permission> modulePermissions)
|
||||||
|
{
|
||||||
|
var permissions = modulePermissions.Where(item => item.EntityId == pageModule.ModuleId).ToList();
|
||||||
|
|
||||||
|
// moduledefinition permissionnames can specify permissions for other entities (ie. API permissions)
|
||||||
|
pageModule.Module.ModuleDefinition = moduleDefinitions.Find(item => item.ModuleDefinitionName == pageModule.Module.ModuleDefinitionName);
|
||||||
|
if (!string.IsNullOrEmpty(pageModule.Module.ModuleDefinition.PermissionNames) && pageModule.Module.ModuleDefinition.PermissionNames.Contains(":"))
|
||||||
|
{
|
||||||
|
foreach (var permissionname in pageModule.Module.ModuleDefinition.PermissionNames.Split(",", System.StringSplitOptions.RemoveEmptyEntries))
|
||||||
|
{
|
||||||
|
if (permissionname.Contains(":"))
|
||||||
|
{
|
||||||
|
// moduledefinition permissionnames can be in the form of "EntityName:PermissionName:Roles"
|
||||||
|
var segments = permissionname.Split(':');
|
||||||
|
if (segments.Length == 3 && segments[0] != EntityNames.Module)
|
||||||
|
{
|
||||||
|
permissions.AddRange(_permissions.GetPermissions(pageModule.Module.SiteId, segments[0], segments[1]).Where(item => item.EntityId == -1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pageModule.Module.Permissions = permissions?.EncodePermissions();
|
||||||
|
return pageModule;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,23 +79,52 @@ namespace Oqtane.Repository
|
||||||
|
|
||||||
public void UpdatePermissions(int siteId, string entityName, int entityId, string permissionStrings)
|
public void UpdatePermissions(int siteId, string entityName, int entityId, string permissionStrings)
|
||||||
{
|
{
|
||||||
// get current permissions and delete
|
bool modified = false;
|
||||||
IEnumerable<Permission> permissions = _db.Permission
|
var existing = new List<Permission>();
|
||||||
.Where(item => item.EntityName == entityName)
|
var permissions = DecodePermissions(permissionStrings, siteId, entityName, entityId);
|
||||||
.Where(item => item.EntityId == entityId)
|
foreach (var permission in permissions)
|
||||||
.Where(item => item.SiteId == siteId);
|
|
||||||
foreach (Permission permission in permissions)
|
|
||||||
{
|
{
|
||||||
_db.Permission.Remove(permission);
|
if (!existing.Any(item => item.EntityName == permission.EntityName && item.PermissionName == permission.PermissionName))
|
||||||
|
{
|
||||||
|
existing.AddRange(GetPermissions(siteId, permission.EntityName, permission.PermissionName)
|
||||||
|
.Where(item => item.EntityId == entityId || item.EntityId == -1));
|
||||||
}
|
}
|
||||||
// add permissions
|
|
||||||
permissions = DecodePermissions(permissionStrings, siteId, entityName, entityId);
|
var current = existing.FirstOrDefault(item => item.EntityName == permission.EntityName && item.EntityId == permission.EntityId
|
||||||
foreach (Permission permission in permissions)
|
&& item.PermissionName == permission.PermissionName && item.RoleId == permission.RoleId && item.UserId == permission.UserId);
|
||||||
|
if (current != null)
|
||||||
|
{
|
||||||
|
if (current.IsAuthorized != permission.IsAuthorized)
|
||||||
|
{
|
||||||
|
current.IsAuthorized = permission.IsAuthorized;
|
||||||
|
_db.Entry(current).State = EntityState.Modified;
|
||||||
|
modified = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
_db.Permission.Add(permission);
|
_db.Permission.Add(permission);
|
||||||
|
modified = true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
foreach (var permission in existing)
|
||||||
|
{
|
||||||
|
if (!permissions.Any(item => item.EntityName == permission.EntityName && item.PermissionName == permission.PermissionName
|
||||||
|
&& item.EntityId == permission.EntityId && item.RoleId == permission.RoleId && item.UserId == permission.UserId))
|
||||||
|
{
|
||||||
|
permission.Role = null; // remove linked reference to Role which can cause errors in EF Core change tracking
|
||||||
|
_db.Permission.Remove(permission);
|
||||||
|
modified = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (modified)
|
||||||
|
{
|
||||||
_db.SaveChanges();
|
_db.SaveChanges();
|
||||||
ClearCache(siteId, entityName);
|
foreach (var entityname in permissions.Select(item => item.EntityName).Distinct())
|
||||||
|
{
|
||||||
|
ClearCache(siteId, entityname);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Permission GetPermission(int permissionId)
|
public Permission GetPermission(int permissionId)
|
||||||
|
@ -200,8 +229,22 @@ namespace Oqtane.Repository
|
||||||
securityid = id;
|
securityid = id;
|
||||||
Permission permission = new Permission();
|
Permission permission = new Permission();
|
||||||
permission.SiteId = siteId;
|
permission.SiteId = siteId;
|
||||||
|
if (!string.IsNullOrEmpty(permissionstring.EntityName))
|
||||||
|
{
|
||||||
|
permission.EntityName = permissionstring.EntityName;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
permission.EntityName = entityName;
|
permission.EntityName = entityName;
|
||||||
|
}
|
||||||
|
if (permission.EntityName == entityName)
|
||||||
|
{
|
||||||
permission.EntityId = entityId;
|
permission.EntityId = entityId;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
permission.EntityId = -1;
|
||||||
|
}
|
||||||
permission.PermissionName = permissionstring.PermissionName;
|
permission.PermissionName = permissionstring.PermissionName;
|
||||||
permission.RoleId = null;
|
permission.RoleId = null;
|
||||||
permission.UserId = null;
|
permission.UserId = null;
|
||||||
|
|
|
@ -431,6 +431,7 @@ namespace Oqtane.Repository
|
||||||
PagePermissions = new List<Permission>
|
PagePermissions = new List<Permission>
|
||||||
{
|
{
|
||||||
new Permission(PermissionNames.View, RoleNames.Admin, true),
|
new Permission(PermissionNames.View, RoleNames.Admin, true),
|
||||||
|
new Permission(PermissionNames.View, RoleNames.Registered, true),
|
||||||
new Permission(PermissionNames.Edit, RoleNames.Admin, true)
|
new Permission(PermissionNames.Edit, RoleNames.Admin, true)
|
||||||
}.EncodePermissions(),
|
}.EncodePermissions(),
|
||||||
PageTemplateModules = new List<PageTemplateModule>
|
PageTemplateModules = new List<PageTemplateModule>
|
||||||
|
@ -441,6 +442,7 @@ namespace Oqtane.Repository
|
||||||
ModulePermissions = new List<Permission>
|
ModulePermissions = new List<Permission>
|
||||||
{
|
{
|
||||||
new Permission(PermissionNames.View, RoleNames.Admin, true),
|
new Permission(PermissionNames.View, RoleNames.Admin, true),
|
||||||
|
new Permission(PermissionNames.View, RoleNames.Registered, true),
|
||||||
new Permission(PermissionNames.Edit, RoleNames.Admin, true)
|
new Permission(PermissionNames.Edit, RoleNames.Admin, true)
|
||||||
}.EncodePermissions(),
|
}.EncodePermissions(),
|
||||||
Content = ""
|
Content = ""
|
||||||
|
|
|
@ -22,22 +22,15 @@ namespace Oqtane.Security
|
||||||
|
|
||||||
if (policy == null)
|
if (policy == null)
|
||||||
{
|
{
|
||||||
// policy names must be in the form of "EntityName:PermissionName:Roles" ie. "Module:Edit:Administrators" (roles are comma delimited)
|
// policy names must be in the form of "EntityName:PermissionName:Roles"
|
||||||
if (policyName.Contains(':'))
|
if (policyName.Contains(':'))
|
||||||
{
|
{
|
||||||
var policySegments = policyName.Split(':');
|
var segments = policyName.Split(':');
|
||||||
if (policySegments.Length >= 3)
|
if (segments.Length == 3)
|
||||||
{
|
{
|
||||||
// check for optional RequireEntityId segment
|
|
||||||
var requireEntityId = false;
|
|
||||||
if (policySegments.Length == 4 && policySegments[3] == Constants.RequireEntityId)
|
|
||||||
{
|
|
||||||
requireEntityId = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// create policy
|
// create policy
|
||||||
var builder = new AuthorizationPolicyBuilder();
|
var builder = new AuthorizationPolicyBuilder();
|
||||||
builder.AddRequirements(new PermissionRequirement(policySegments[0], policySegments[1], policySegments[2], requireEntityId));
|
builder.AddRequirements(new PermissionRequirement(segments[0], segments[1], segments[2]));
|
||||||
policy = builder.Build();
|
policy = builder.Build();
|
||||||
|
|
||||||
// add policy to the AuthorizationOptions
|
// add policy to the AuthorizationOptions
|
||||||
|
@ -59,8 +52,8 @@ namespace Oqtane.Security
|
||||||
private string GetPolicyName(string policyName)
|
private string GetPolicyName(string policyName)
|
||||||
{
|
{
|
||||||
// backward compatibility for legacy static policy names
|
// backward compatibility for legacy static policy names
|
||||||
if (policyName == PolicyNames.ViewModule) policyName = $"{EntityNames.Module}:{PermissionNames.View}:{RoleNames.Admin}:{Constants.RequireEntityId}";
|
if (policyName == PolicyNames.ViewModule) policyName = $"{EntityNames.Module}:{PermissionNames.View}:{RoleNames.Admin}";
|
||||||
if (policyName == PolicyNames.EditModule) policyName = $"{EntityNames.Module}:{PermissionNames.Edit}:{RoleNames.Admin}:{Constants.RequireEntityId}";
|
if (policyName == PolicyNames.EditModule) policyName = $"{EntityNames.Module}:{PermissionNames.Edit}:{RoleNames.Admin}";
|
||||||
return policyName;
|
return policyName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,8 +34,7 @@ namespace Oqtane.Security
|
||||||
}
|
}
|
||||||
|
|
||||||
int entityId = -1;
|
int entityId = -1;
|
||||||
if (requirement.RequireEntityId)
|
|
||||||
{
|
|
||||||
// get entityid from querystring based on a parameter format of auth{entityname}id (ie. authmoduleid )
|
// get entityid from querystring based on a parameter format of auth{entityname}id (ie. authmoduleid )
|
||||||
if (ctx.Request.Query.ContainsKey("auth" + requirement.EntityName.ToLower() + "id"))
|
if (ctx.Request.Query.ContainsKey("auth" + requirement.EntityName.ToLower() + "id"))
|
||||||
{
|
{
|
||||||
|
@ -56,7 +55,6 @@ namespace Oqtane.Security
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// validate permissions
|
// validate permissions
|
||||||
if (_userPermissions.IsAuthorized(context.User, siteId, requirement.EntityName, entityId, requirement.PermissionName, requirement.Roles))
|
if (_userPermissions.IsAuthorized(context.User, siteId, requirement.EntityName, entityId, requirement.PermissionName, requirement.Roles))
|
||||||
|
|
|
@ -8,16 +8,13 @@ namespace Oqtane.Security
|
||||||
|
|
||||||
public string PermissionName { get; }
|
public string PermissionName { get; }
|
||||||
|
|
||||||
public string Roles { get; }
|
public string Roles { get; } // semi-colon delimited
|
||||||
|
|
||||||
public bool RequireEntityId { get; }
|
public PermissionRequirement(string entityName, string permissionName, string roles)
|
||||||
|
|
||||||
public PermissionRequirement(string entityName, string permissionName, string roles, bool requireEntityId)
|
|
||||||
{
|
{
|
||||||
EntityName = entityName;
|
EntityName = entityName;
|
||||||
PermissionName = permissionName;
|
PermissionName = permissionName;
|
||||||
Roles = roles;
|
Roles = roles;
|
||||||
RequireEntityId = requireEntityId;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ namespace Oqtane.Security
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return UserSecurity.IsAuthorized(GetUser(principal), roles.Replace(",",";"));
|
return UserSecurity.IsAuthorized(GetUser(principal), roles);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
namespace Oqtane.Models
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// API management
|
|
||||||
/// </summary>
|
|
||||||
public class Api
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Reference to a <see cref="Site"/>
|
|
||||||
/// </summary>
|
|
||||||
public int SiteId { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The Entity Name
|
|
||||||
/// </summary>
|
|
||||||
public string EntityName { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The permissions for the entity
|
|
||||||
/// </summary>
|
|
||||||
public string Permissions { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -5,13 +5,18 @@ namespace Oqtane.Models
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class PermissionString
|
public class PermissionString
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A term describing the entity
|
||||||
|
/// </summary>
|
||||||
|
public string EntityName { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A term describing a set of permissions
|
/// A term describing a set of permissions
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string PermissionName { get; set; }
|
public string PermissionName { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The permissions addressed with this name
|
/// The permissions
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Permissions { get; set; }
|
public string Permissions { get; set; }
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,8 @@ namespace Oqtane.Shared
|
||||||
{
|
{
|
||||||
public class Constants
|
public class Constants
|
||||||
{
|
{
|
||||||
public static readonly string Version = "3.2.1";
|
public static readonly string Version = "3.3.0";
|
||||||
public const string ReleaseVersions = "1.0.0,1.0.1,1.0.2,1.0.3,1.0.4,2.0.0,2.0.1,2.0.2,2.1.0,2.2.0,2.3.0,2.3.1,3.0.0,3.0.1,3.0.2,3.0.3,3.1.0,3.1.1,3.1.2,3.1.3,3.1.4,3.2.0,3.2.1";
|
public const string ReleaseVersions = "1.0.0,1.0.1,1.0.2,1.0.3,1.0.4,2.0.0,2.0.1,2.0.2,2.1.0,2.2.0,2.3.0,2.3.1,3.0.0,3.0.1,3.0.2,3.0.3,3.1.0,3.1.1,3.1.2,3.1.3,3.1.4,3.2.0,3.3.0";
|
||||||
public const string PackageId = "Oqtane.Framework";
|
public const string PackageId = "Oqtane.Framework";
|
||||||
public const string ClientId = "Oqtane.Client";
|
public const string ClientId = "Oqtane.Client";
|
||||||
public const string UpdaterPackageId = "Oqtane.Updater";
|
public const string UpdaterPackageId = "Oqtane.Updater";
|
||||||
|
@ -74,8 +74,6 @@ namespace Oqtane.Shared
|
||||||
|
|
||||||
public static readonly string MauiUserAgent = "MAUI";
|
public static readonly string MauiUserAgent = "MAUI";
|
||||||
|
|
||||||
public static readonly string RequireEntityId = "RequireEntityId";
|
|
||||||
|
|
||||||
// Obsolete constants
|
// Obsolete constants
|
||||||
|
|
||||||
const string RoleObsoleteMessage = "Use the corresponding member from Oqtane.Shared.RoleNames";
|
const string RoleObsoleteMessage = "Use the corresponding member from Oqtane.Shared.RoleNames";
|
||||||
|
|
Loading…
Reference in New Issue
Block a user