Merge remote-tracking branch 'oqtane/dev' into dev
This commit is contained in:
commit
c49af06e57
2
LICENSE
2
LICENSE
|
@ -1,6 +1,6 @@
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2018-2022 .NET Foundation
|
Copyright (c) 2018-2023 .NET Foundation
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
@using System.Net
|
||||||
@namespace Oqtane.Modules.Admin.Login
|
@namespace Oqtane.Modules.Admin.Login
|
||||||
@inherits ModuleBase
|
@inherits ModuleBase
|
||||||
@inject NavigationManager NavigationManager
|
@inject NavigationManager NavigationManager
|
||||||
|
@ -205,7 +206,7 @@
|
||||||
var authstateprovider = (IdentityAuthenticationStateProvider)ServiceProvider
|
var authstateprovider = (IdentityAuthenticationStateProvider)ServiceProvider
|
||||||
.GetService(typeof(IdentityAuthenticationStateProvider));
|
.GetService(typeof(IdentityAuthenticationStateProvider));
|
||||||
authstateprovider.NotifyAuthenticationChanged();
|
authstateprovider.NotifyAuthenticationChanged();
|
||||||
NavigationManager.NavigateTo(NavigateUrl(_returnUrl, true));
|
NavigationManager.NavigateTo(NavigateUrl(WebUtility.UrlDecode(_returnUrl), true));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -106,12 +106,6 @@ else
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// external link to log item will display Details component
|
|
||||||
if (PageState.QueryString.ContainsKey("id") && int.TryParse(PageState.QueryString["id"], out int id))
|
|
||||||
{
|
|
||||||
NavigationManager.NavigateTo(EditUrl(PageState.Page.Path, ModuleState.ModuleId, "Detail", $"/{id}"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (UrlParameters.ContainsKey("level"))
|
if (UrlParameters.ContainsKey("level"))
|
||||||
{
|
{
|
||||||
_level = UrlParameters["level"];
|
_level = UrlParameters["level"];
|
||||||
|
@ -241,4 +235,15 @@ else
|
||||||
_page = page;
|
_page = page;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void OnAfterRender(bool firstRender)
|
||||||
|
{
|
||||||
|
if (firstRender)
|
||||||
|
{
|
||||||
|
// external link to log item will display Details component
|
||||||
|
if (PageState.QueryString.ContainsKey("id") && int.TryParse(PageState.QueryString["id"], out int id))
|
||||||
|
{
|
||||||
|
NavigationManager.NavigateTo(EditUrl(PageState.Page.Path, ModuleState.ModuleId, "Detail", $"/{id}"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
@ -174,7 +174,7 @@ else
|
||||||
private bool IsValid(string name)
|
private bool IsValid(string name)
|
||||||
{
|
{
|
||||||
// must contain letters, underscores and digits and first character must be letter or underscore
|
// must contain letters, underscores and digits and first character must be letter or underscore
|
||||||
return !string.IsNullOrEmpty(name) && name.ToLower() != "module" && Regex.IsMatch(name, "^[A-Za-z_][A-Za-z0-9_]*$");
|
return !string.IsNullOrEmpty(name) && name.ToLower() != "module" && !name.ToLower().Contains("oqtane") && Regex.IsMatch(name, "^[A-Za-z_][A-Za-z0-9_]*$");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void TemplateChanged(ChangeEventArgs e)
|
private void TemplateChanged(ChangeEventArgs e)
|
||||||
|
|
|
@ -139,7 +139,7 @@
|
||||||
private bool IsValid(string name)
|
private bool IsValid(string name)
|
||||||
{
|
{
|
||||||
// must contain letters, underscores and digits and first character must be letter or underscore
|
// must contain letters, underscores and digits and first character must be letter or underscore
|
||||||
return !string.IsNullOrEmpty(name) && name.ToLower() != "module" && Regex.IsMatch(name, "^[A-Za-z_][A-Za-z0-9_]*$");
|
return !string.IsNullOrEmpty(name) && name.ToLower() != "module" && !name.ToLower().Contains("oqtane") && Regex.IsMatch(name, "^[A-Za-z_][A-Za-z0-9_]*$");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void TemplateChanged(ChangeEventArgs e)
|
private void TemplateChanged(ChangeEventArgs e)
|
||||||
|
|
|
@ -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>
|
||||||
|
|
20
Oqtane.Client/Modules/Admin/Profiles/ModuleInfo.cs
Normal file
20
Oqtane.Client/Modules/Admin/Profiles/ModuleInfo.cs
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
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()
|
||||||
{
|
{
|
||||||
|
|
21
Oqtane.Client/Modules/Admin/Roles/ModuleInfo.cs
Normal file
21
Oqtane.Client/Modules/Admin/Roles/ModuleInfo.cs
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
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
|
||||||
|
|
|
@ -127,7 +127,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="username" HelpText="Enter the username for your SMTP account" ResourceKey="SmptUsername">Username: </Label>
|
<Label Class="col-sm-3" For="username" HelpText="Enter the username for your SMTP account" ResourceKey="SmtpUsername">Username: </Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<input id="username" class="form-control" @bind="@_smtpusername" />
|
<input id="username" class="form-control" @bind="@_smtpusername" />
|
||||||
</div>
|
</div>
|
||||||
|
@ -142,10 +142,19 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="sender" HelpText="Enter the email which emails will be sent from. Please note that this email address may need to be authorized with the SMTP server." ResourceKey="SmptSender">Email Sender: </Label>
|
<Label Class="col-sm-3" For="sender" HelpText="Enter the email which emails will be sent from. Please note that this email address may need to be authorized with the SMTP server." ResourceKey="SmtpSender">Email Sender: </Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<input id="sender" class="form-control" @bind="@_smtpsender" />
|
<input id="sender" class="form-control" @bind="@_smtpsender" />
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="relay" HelpText="Only specify this option if you have properly configured an SMTP Relay Service to route your outgoing mail. This option will send notifications from the user's email rather than from the Email Sender specified above." ResourceKey="SmtpRelay">Relay Configured? </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<select id="relay" class="form-select" @bind="@_smtprelay" required>
|
||||||
|
<option value="True">@SharedLocalizer["Yes"]</option>
|
||||||
|
<option value="False">@SharedLocalizer["No"]</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="retention" HelpText="Number of days of notifications to retain" ResourceKey="Retention">Retention (Days): </Label>
|
<Label Class="col-sm-3" For="retention" HelpText="Number of days of notifications to retain" ResourceKey="Retention">Retention (Days): </Label>
|
||||||
|
@ -275,7 +284,10 @@
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="connectionstring" HelpText="The connection information for the database" ResourceKey="ConnectionString">Connection: </Label>
|
<Label Class="col-sm-3" For="connectionstring" HelpText="The connection information for the database" ResourceKey="ConnectionString">Connection: </Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<textarea id="connectionstring" class="form-control" @bind="@_connectionstring" rows="2" readonly></textarea>
|
<div class="input-group">
|
||||||
|
<input id="connectionstring" type="@_connectionstringtype" class="form-control" @bind="@_connectionstring" readonly />
|
||||||
|
<button type="button" class="btn btn-secondary" @onclick="@ToggleConnectionString">@_connectionstringtoggle</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -320,6 +332,7 @@
|
||||||
private string _smtppasswordtype = "password";
|
private string _smtppasswordtype = "password";
|
||||||
private string _togglesmtppassword = string.Empty;
|
private string _togglesmtppassword = string.Empty;
|
||||||
private string _smtpsender = string.Empty;
|
private string _smtpsender = string.Empty;
|
||||||
|
private string _smtprelay = "False";
|
||||||
private string _retention = string.Empty;
|
private string _retention = string.Empty;
|
||||||
private string _pwaisenabled;
|
private string _pwaisenabled;
|
||||||
private int _pwaappiconfileid = -1;
|
private int _pwaappiconfileid = -1;
|
||||||
|
@ -329,6 +342,8 @@
|
||||||
private string _tenant = string.Empty;
|
private string _tenant = string.Empty;
|
||||||
private string _database = string.Empty;
|
private string _database = string.Empty;
|
||||||
private string _connectionstring = string.Empty;
|
private string _connectionstring = string.Empty;
|
||||||
|
private string _connectionstringtype = "password";
|
||||||
|
private string _connectionstringtoggle = string.Empty;
|
||||||
private string _createdby;
|
private string _createdby;
|
||||||
private DateTime _createdon;
|
private DateTime _createdon;
|
||||||
private string _modifiedby;
|
private string _modifiedby;
|
||||||
|
@ -343,6 +358,7 @@
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
_connectionstringtoggle = SharedLocalizer["ShowPassword"];
|
||||||
_themeList = await ThemeService.GetThemesAsync();
|
_themeList = await ThemeService.GetThemesAsync();
|
||||||
Site site = await SiteService.GetSiteAsync(PageState.Site.SiteId);
|
Site site = await SiteService.GetSiteAsync(PageState.Site.SiteId);
|
||||||
if (site != null)
|
if (site != null)
|
||||||
|
@ -393,6 +409,7 @@
|
||||||
_smtppassword = SettingService.GetSetting(settings, "SMTPPassword", string.Empty);
|
_smtppassword = SettingService.GetSetting(settings, "SMTPPassword", string.Empty);
|
||||||
_togglesmtppassword = SharedLocalizer["ShowPassword"];
|
_togglesmtppassword = SharedLocalizer["ShowPassword"];
|
||||||
_smtpsender = SettingService.GetSetting(settings, "SMTPSender", string.Empty);
|
_smtpsender = SettingService.GetSetting(settings, "SMTPSender", string.Empty);
|
||||||
|
_smtprelay = SettingService.GetSetting(settings, "SMTPRelay", "False");
|
||||||
_retention = SettingService.GetSetting(settings, "NotificationRetention", "30");
|
_retention = SettingService.GetSetting(settings, "NotificationRetention", "30");
|
||||||
|
|
||||||
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
||||||
|
@ -449,6 +466,20 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ToggleConnectionString()
|
||||||
|
{
|
||||||
|
if (_connectionstringtype == "password")
|
||||||
|
{
|
||||||
|
_connectionstringtype = "text";
|
||||||
|
_connectionstringtoggle = SharedLocalizer["HidePassword"];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_connectionstringtype = "password";
|
||||||
|
_connectionstringtoggle = SharedLocalizer["ShowPassword"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async Task SaveSite()
|
private async Task SaveSite()
|
||||||
{
|
{
|
||||||
validated = true;
|
validated = true;
|
||||||
|
@ -532,6 +563,7 @@
|
||||||
settings = SettingService.SetSetting(settings, "SMTPUsername", _smtpusername, true);
|
settings = SettingService.SetSetting(settings, "SMTPUsername", _smtpusername, true);
|
||||||
settings = SettingService.SetSetting(settings, "SMTPPassword", _smtppassword, true);
|
settings = SettingService.SetSetting(settings, "SMTPPassword", _smtppassword, true);
|
||||||
settings = SettingService.SetSetting(settings, "SMTPSender", _smtpsender, true);
|
settings = SettingService.SetSetting(settings, "SMTPSender", _smtpsender, true);
|
||||||
|
settings = SettingService.SetSetting(settings, "SMTPRelay", _smtprelay, true);
|
||||||
settings = SettingService.SetSetting(settings, "NotificationRetention", _retention, true);
|
settings = SettingService.SetSetting(settings, "NotificationRetention", _retention, true);
|
||||||
await SettingService.UpdateSiteSettingsAsync(settings, site.SiteId);
|
await SettingService.UpdateSiteSettingsAsync(settings, site.SiteId);
|
||||||
|
|
||||||
|
@ -602,12 +634,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");
|
||||||
|
|
||||||
|
|
|
@ -315,7 +315,7 @@ else
|
||||||
_urls = Regex.Replace(_urls, @"\r\n?|\n", ",");
|
_urls = Regex.Replace(_urls, @"\r\n?|\n", ",");
|
||||||
var duplicates = new List<string>();
|
var duplicates = new List<string>();
|
||||||
var aliases = await AliasService.GetAliasesAsync();
|
var aliases = await AliasService.GetAliasesAsync();
|
||||||
foreach (string name in _urls.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
|
foreach (string name in _urls.Split(',', StringSplitOptions.RemoveEmptyEntries))
|
||||||
{
|
{
|
||||||
if (aliases.Exists(item => item.Name == name))
|
if (aliases.Exists(item => item.Name == name))
|
||||||
{
|
{
|
||||||
|
|
|
@ -16,7 +16,7 @@ else
|
||||||
<div class="container">
|
<div class="container">
|
||||||
|
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="tenant" HelpText="Select the tenant for the SQL server" ResourceKey="Tenant">Tenant: </Label>
|
<Label Class="col-sm-3" For="tenant" HelpText="Select the tenant associated with the database server" ResourceKey="Tenant">Tenant: </Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<select id="tenant" class="form-select" value="@_tenantid" @onchange="(e => TenantChanged(e))">
|
<select id="tenant" class="form-select" value="@_tenantid" @onchange="(e => TenantChanged(e))">
|
||||||
<option value="-1"><@Localizer["Tenant.Select"]></option>
|
<option value="-1"><@Localizer["Tenant.Select"]></option>
|
||||||
|
@ -45,9 +45,9 @@ else
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="sqlQeury" HelpText="Enter the query for the SQL server" ResourceKey="SqlQuery">SQL Query: </Label>
|
<Label Class="col-sm-3" For="sqlQuery" HelpText="Enter the SQL query for the database server" ResourceKey="SqlQuery">SQL Query: </Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<textarea id="sqlQeury" class="form-control" @bind="@_sql" rows="3"></textarea>
|
<textarea id="sqlQuery" class="form-control" @bind="@_sql" rows="3"></textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
|
@ -147,6 +147,18 @@
|
||||||
<a class="btn btn-primary" href="swagger/index.html" target="_new">@Localizer["Access.ApiFramework"]</a>
|
<a class="btn btn-primary" href="swagger/index.html" target="_new">@Localizer["Access.ApiFramework"]</a>
|
||||||
<ActionDialog Header="Restart Application" Message="Are You Sure You Wish To Restart The Application?" Action="Restart Application" Security="SecurityAccessLevel.Host" Class="btn btn-danger" OnClick="@(async () => await RestartApplication())" ResourceKey="RestartApplication" />
|
<ActionDialog Header="Restart Application" Message="Are You Sure You Wish To Restart The Application?" Action="Restart Application" Security="SecurityAccessLevel.Host" Class="btn btn-danger" OnClick="@(async () => await RestartApplication())" ResourceKey="RestartApplication" />
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
|
<TabPanel Name="Log" Heading="Log" ResourceKey="Log">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="log" HelpText="System log information for current day" ResourceKey="Log">Log: </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<textarea id="log" class="form-control" rows="10" @bind="@_log" readonly />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<br /><br />
|
||||||
|
<button type="button" class="btn btn-danger" @onclick="ClearLog">@Localizer["Clear"]</button>
|
||||||
|
</TabPanel>
|
||||||
</TabStrip>
|
</TabStrip>
|
||||||
<br /><br />
|
<br /><br />
|
||||||
|
|
||||||
|
@ -172,6 +184,8 @@
|
||||||
private string _swagger = string.Empty;
|
private string _swagger = string.Empty;
|
||||||
private string _packageservice = string.Empty;
|
private string _packageservice = string.Empty;
|
||||||
|
|
||||||
|
private string _log = string.Empty;
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
_version = Constants.Version;
|
_version = Constants.Version;
|
||||||
|
@ -191,7 +205,7 @@
|
||||||
_workingset = (Convert.ToInt64(systeminfo["WorkingSet"].ToString()) / 1000000).ToString() + " MB";
|
_workingset = (Convert.ToInt64(systeminfo["WorkingSet"].ToString()) / 1000000).ToString() + " MB";
|
||||||
}
|
}
|
||||||
|
|
||||||
systeminfo = await SystemService.GetSystemInfoAsync();
|
systeminfo = await SystemService.GetSystemInfoAsync("configuration");
|
||||||
if (systeminfo != null)
|
if (systeminfo != null)
|
||||||
{
|
{
|
||||||
_installationid = systeminfo["InstallationId"].ToString();
|
_installationid = systeminfo["InstallationId"].ToString();
|
||||||
|
@ -201,6 +215,12 @@
|
||||||
_swagger = systeminfo["UseSwagger"].ToString();
|
_swagger = systeminfo["UseSwagger"].ToString();
|
||||||
_packageservice = systeminfo["PackageService"].ToString();
|
_packageservice = systeminfo["PackageService"].ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
systeminfo = await SystemService.GetSystemInfoAsync("log");
|
||||||
|
if (systeminfo != null)
|
||||||
|
{
|
||||||
|
_log = systeminfo["Log"].ToString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task SaveConfig()
|
private async Task SaveConfig()
|
||||||
|
@ -223,6 +243,21 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task ClearLog()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await SystemService.UpdateSystemInfoAsync("Log", "Clear");
|
||||||
|
_log = string.Empty;
|
||||||
|
AddModuleMessage(Localizer["Success.ClearLog"], MessageType.Success);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await logger.LogError(ex, "Error Clearing Log");
|
||||||
|
AddModuleMessage(Localizer["Error.ClearLog"], MessageType.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async Task RestartApplication()
|
private async Task RestartApplication()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|
|
@ -121,7 +121,7 @@
|
||||||
private bool IsValid(string name)
|
private bool IsValid(string name)
|
||||||
{
|
{
|
||||||
// must contain letters, underscores and digits and first character must be letter or underscore
|
// must contain letters, underscores and digits and first character must be letter or underscore
|
||||||
return !string.IsNullOrEmpty(name) && name.ToLower() != "theme" && Regex.IsMatch(name, "^[A-Za-z_][A-Za-z0-9_]*$");
|
return !string.IsNullOrEmpty(name) && name.ToLower() != "theme" && !name.ToLower().Contains("oqtane") && Regex.IsMatch(name, "^[A-Za-z_][A-Za-z0-9_]*$");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void TemplateChanged(ChangeEventArgs e)
|
private void TemplateChanged(ChangeEventArgs e)
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
21
Oqtane.Client/Modules/Admin/Users/ModuleInfo.cs
Normal file
21
Oqtane.Client/Modules/Admin/Users/ModuleInfo.cs
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
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()
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
@inject IStringLocalizer<FileManager> Localizer
|
@inject IStringLocalizer<FileManager> Localizer
|
||||||
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
||||||
|
|
||||||
@if (_folders != null)
|
@if (_initialized)
|
||||||
{
|
{
|
||||||
<div id="@Id" class="container-fluid px-0">
|
<div id="@Id" class="container-fluid px-0">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
@ -87,6 +87,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
|
private bool _initialized = false;
|
||||||
private List<Folder> _folders;
|
private List<Folder> _folders;
|
||||||
private List<File> _files = new List<File>();
|
private List<File> _files = new List<File>();
|
||||||
private string _fileinputid = string.Empty;
|
private string _fileinputid = string.Empty;
|
||||||
|
@ -205,6 +206,8 @@
|
||||||
_fileinputid = "FileInput_" + _guid;
|
_fileinputid = "FileInput_" + _guid;
|
||||||
_progressinfoid = "ProgressInfo_" + _guid;
|
_progressinfoid = "ProgressInfo_" + _guid;
|
||||||
_progressbarid = "ProgressBar_" + _guid;
|
_progressbarid = "ProgressBar_" + _guid;
|
||||||
|
|
||||||
|
_initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task GetFiles()
|
private async Task GetFiles()
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<RazorLangVersion>3.0</RazorLangVersion>
|
<RazorLangVersion>3.0</RazorLangVersion>
|
||||||
<Configurations>Debug;Release</Configurations>
|
<Configurations>Debug;Release</Configurations>
|
||||||
<Version>3.2.1</Version>
|
<Version>3.3.1</Version>
|
||||||
<Product>Oqtane</Product>
|
<Product>Oqtane</Product>
|
||||||
<Authors>Shaun Walker</Authors>
|
<Authors>Shaun Walker</Authors>
|
||||||
<Company>.NET Foundation</Company>
|
<Company>.NET Foundation</Company>
|
||||||
|
@ -13,7 +13,7 @@
|
||||||
<Copyright>.NET Foundation</Copyright>
|
<Copyright>.NET Foundation</Copyright>
|
||||||
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
||||||
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
||||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.2.1</PackageReleaseNotes>
|
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.3.1</PackageReleaseNotes>
|
||||||
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
||||||
<RepositoryType>Git</RepositoryType>
|
<RepositoryType>Git</RepositoryType>
|
||||||
<RootNamespace>Oqtane</RootNamespace>
|
<RootNamespace>Oqtane</RootNamespace>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -195,13 +195,13 @@
|
||||||
<data name="UseSsl.HelpText" xml:space="preserve">
|
<data name="UseSsl.HelpText" xml:space="preserve">
|
||||||
<value>Specify if SSL is required for your SMTP server</value>
|
<value>Specify if SSL is required for your SMTP server</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SmptUsername.HelpText" xml:space="preserve">
|
<data name="SmtpUsername.HelpText" xml:space="preserve">
|
||||||
<value>Enter the username for your SMTP account</value>
|
<value>Enter the username for your SMTP account</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SmtpPassword.HelpText" xml:space="preserve">
|
<data name="SmtpPassword.HelpText" xml:space="preserve">
|
||||||
<value>Enter the password for your SMTP account</value>
|
<value>Enter the password for your SMTP account</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SmptSender.HelpText" xml:space="preserve">
|
<data name="SmtpSender.HelpText" xml:space="preserve">
|
||||||
<value>Enter the email which emails will be sent from. Please note that this email address may need to be authorized with the SMTP server.</value>
|
<value>Enter the email which emails will be sent from. Please note that this email address may need to be authorized with the SMTP server.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="EnablePWA.HelpText" xml:space="preserve">
|
<data name="EnablePWA.HelpText" xml:space="preserve">
|
||||||
|
@ -243,13 +243,13 @@
|
||||||
<data name="UseSsl.Text" xml:space="preserve">
|
<data name="UseSsl.Text" xml:space="preserve">
|
||||||
<value>SSL Enabled: </value>
|
<value>SSL Enabled: </value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SmptUsername.Text" xml:space="preserve">
|
<data name="SmtpUsername.Text" xml:space="preserve">
|
||||||
<value>Username: </value>
|
<value>Username: </value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SmtpPassword.Text" xml:space="preserve">
|
<data name="SmtpPassword.Text" xml:space="preserve">
|
||||||
<value>Password: </value>
|
<value>Password: </value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SmptSender.Text" xml:space="preserve">
|
<data name="SmtpSender.Text" xml:space="preserve">
|
||||||
<value>Email Sender: </value>
|
<value>Email Sender: </value>
|
||||||
</data>
|
</data>
|
||||||
<data name="EnablePWA.Text" xml:space="preserve">
|
<data name="EnablePWA.Text" xml:space="preserve">
|
||||||
|
@ -339,4 +339,10 @@
|
||||||
<data name="HomePage.Text" xml:space="preserve">
|
<data name="HomePage.Text" xml:space="preserve">
|
||||||
<value>Home Page:</value>
|
<value>Home Page:</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SmtpRelay.HelpText" xml:space="preserve">
|
||||||
|
<value>Only specify this option if you have properly configured an SMTP Relay Service to route your outgoing mail. This option will send notifications from the user's email rather than from the Email Sender specified above.</value>
|
||||||
|
</data>
|
||||||
|
<data name="SmtpRelay.Text" xml:space="preserve">
|
||||||
|
<value>Relay Configured?</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
|
@ -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
|
||||||
|
@ -133,10 +133,10 @@
|
||||||
<value>No Results Returned</value>
|
<value>No Results Returned</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Tenant.HelpText" xml:space="preserve">
|
<data name="Tenant.HelpText" xml:space="preserve">
|
||||||
<value>Select the tenant for the SQL server</value>
|
<value>Select the tenant associated with the database server</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SqlQuery.HelpText" xml:space="preserve">
|
<data name="SqlQuery.HelpText" xml:space="preserve">
|
||||||
<value>Enter the query for the SQL server</value>
|
<value>Enter the SQL query for the database server</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SqlQuery.Text" xml:space="preserve">
|
<data name="SqlQuery.Text" xml:space="preserve">
|
||||||
<value>SQL Query: </value>
|
<value>SQL Query: </value>
|
||||||
|
|
|
@ -209,6 +209,9 @@
|
||||||
</data>
|
</data>
|
||||||
<data name="Options.Heading" xml:space="preserve">
|
<data name="Options.Heading" xml:space="preserve">
|
||||||
<value>Options</value>
|
<value>Options</value>
|
||||||
|
</data>
|
||||||
|
<data name="Log.Heading" xml:space="preserve">
|
||||||
|
<value>Log</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Register" xml:space="preserve">
|
<data name="Register" xml:space="preserve">
|
||||||
<value>Please Register Me For Major Product Updates And Security Bulletins</value>
|
<value>Please Register Me For Major Product Updates And Security Bulletins</value>
|
||||||
|
@ -276,4 +279,19 @@
|
||||||
<data name="Environment.Text" xml:space="preserve">
|
<data name="Environment.Text" xml:space="preserve">
|
||||||
<value>Environment:</value>
|
<value>Environment:</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Log.Text" xml:space="preserve">
|
||||||
|
<value>Log:</value>
|
||||||
|
</data>
|
||||||
|
<data name="Log.HelpText" xml:space="preserve">
|
||||||
|
<value>System log information for current day</value>
|
||||||
|
</data>
|
||||||
|
<data name="Clear" xml:space="preserve">
|
||||||
|
<value>Clear</value>
|
||||||
|
</data>
|
||||||
|
<data name="Success.ClearLog" xml:space="preserve">
|
||||||
|
<value>System Log Has Been Successfully Cleared</value>
|
||||||
|
</data>
|
||||||
|
<data name="Error.ClearLog" xml:space="preserve">
|
||||||
|
<value>Ann Error Occurred Clearing The System Log</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -62,7 +62,7 @@ namespace Oqtane.Services
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns a key-value dictionary of all page module settings for the given page module
|
/// Returns a key-value dictionary of all page module settings for the given page module
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="pageId"></param>
|
/// <param name="pageModuleId"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<Dictionary<string, string>> GetPageModuleSettingsAsync(int pageModuleId);
|
Task<Dictionary<string, string>> GetPageModuleSettingsAsync(int pageModuleId);
|
||||||
|
|
||||||
|
@ -107,7 +107,7 @@ namespace Oqtane.Services
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns a key-value dictionary of all user settings for the given user
|
/// Returns a key-value dictionary of all user settings for the given user
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="pageId"></param>
|
/// <param name="userId"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<Dictionary<string, string>> GetUserSettingsAsync(int userId);
|
Task<Dictionary<string, string>> GetUserSettingsAsync(int userId);
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ namespace Oqtane.Services
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns a key-value dictionary of all folder settings for the given folder
|
/// Returns a key-value dictionary of all folder settings for the given folder
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="pageId"></param>
|
/// <param name="folderId"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<Dictionary<string, string>> GetFolderSettingsAsync(int folderId);
|
Task<Dictionary<string, string>> GetFolderSettingsAsync(int folderId);
|
||||||
|
|
||||||
|
@ -148,6 +148,21 @@ namespace Oqtane.Services
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task UpdateHostSettingsAsync(Dictionary<string, string> hostSettings);
|
Task UpdateHostSettingsAsync(Dictionary<string, string> hostSettings);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a key-value dictionary of all settings for the given visitor
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="visitorId"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<Dictionary<string, string>> GetVisitorSettingsAsync(int visitorId);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates a visitor setting
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="visitorSettings"></param>
|
||||||
|
/// <param name="visitorId"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task UpdateVisitorSettingsAsync(Dictionary<string, string> visitorSettings, int visitorId);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns a key-value dictionary of all settings for the given entityName
|
/// Returns a key-value dictionary of all settings for the given entityName
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -111,6 +111,26 @@ namespace Oqtane.Services
|
||||||
await UpdateSettingsAsync(hostSettings, EntityNames.Host, -1);
|
await UpdateSettingsAsync(hostSettings, EntityNames.Host, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<Dictionary<string, string>> GetVisitorSettingsAsync(int visitorId)
|
||||||
|
{
|
||||||
|
if (visitorId != -1)
|
||||||
|
{
|
||||||
|
return await GetSettingsAsync(EntityNames.Visitor, visitorId);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return new Dictionary<string, string>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task UpdateVisitorSettingsAsync(Dictionary<string, string> visitorSettings, int visitorId)
|
||||||
|
{
|
||||||
|
if (visitorId != -1)
|
||||||
|
{
|
||||||
|
await UpdateSettingsAsync(visitorSettings, EntityNames.Visitor, visitorId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<Dictionary<string, string>> GetSettingsAsync(string entityName, int entityId)
|
public async Task<Dictionary<string, string>> GetSettingsAsync(string entityName, int entityId)
|
||||||
{
|
{
|
||||||
var dictionary = new Dictionary<string, string>();
|
var dictionary = new Dictionary<string, string>();
|
||||||
|
|
|
@ -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>
|
||||||
|
@ -211,13 +215,15 @@
|
||||||
</div>
|
</div>
|
||||||
</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;
|
||||||
|
@ -380,6 +403,8 @@
|
||||||
// set module view permissions to page edit permissions
|
// set module view permissions to page edit permissions
|
||||||
permissions.Find(p => p.PermissionName == PermissionNames.View).Permissions = permissions.Find(p => p.PermissionName == PermissionNames.Edit).Permissions;
|
permissions.Find(p => p.PermissionName == PermissionNames.View).Permissions = permissions.Find(p => p.PermissionName == PermissionNames.Edit).Permissions;
|
||||||
}
|
}
|
||||||
|
// set entityname
|
||||||
|
permissions.ForEach(item => item.EntityName = EntityNames.Module);
|
||||||
module.Permissions = UserSecurity.SetPermissionStrings(permissions);
|
module.Permissions = UserSecurity.SetPermissionStrings(permissions);
|
||||||
|
|
||||||
module = await ModuleService.AddModuleAsync(module);
|
module = await ModuleService.AddModuleAsync(module);
|
||||||
|
@ -465,12 +490,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 +574,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 +619,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Net;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Components;
|
using Microsoft.AspNetCore.Components;
|
||||||
using Microsoft.JSInterop;
|
using Microsoft.JSInterop;
|
||||||
using Oqtane.Enums;
|
using Oqtane.Enums;
|
||||||
|
using Oqtane.Models;
|
||||||
using Oqtane.Providers;
|
using Oqtane.Providers;
|
||||||
using Oqtane.Security;
|
using Oqtane.Security;
|
||||||
using Oqtane.Services;
|
using Oqtane.Services;
|
||||||
|
@ -22,20 +24,18 @@ namespace Oqtane.Themes.Controls
|
||||||
|
|
||||||
protected void LoginUser()
|
protected void LoginUser()
|
||||||
{
|
{
|
||||||
var returnurl = PageState.Alias.Path;
|
Route route = new Route(PageState.Uri.AbsoluteUri, PageState.Alias.Path);
|
||||||
if (PageState.Page.Path != "/")
|
NavigationManager.NavigateTo(NavigateUrl("login", "?returnurl=" + WebUtility.UrlEncode(route.PathAndQuery)));
|
||||||
{
|
|
||||||
returnurl += "/" + PageState.Page.Path;
|
|
||||||
}
|
|
||||||
NavigationManager.NavigateTo(NavigateUrl("login", "?returnurl=" + returnurl));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
Route route = new Route(PageState.Uri.AbsoluteUri, PageState.Alias.Path);
|
||||||
var url = PageState.Alias.Path + "/" + PageState.Page.Path;
|
var url = route.PathAndQuery;
|
||||||
|
|
||||||
|
// verify if anonymous users can access page
|
||||||
if (!UserSecurity.IsAuthorized(null, PermissionNames.View, PageState.Page.Permissions))
|
if (!UserSecurity.IsAuthorized(null, PermissionNames.View, PageState.Page.Permissions))
|
||||||
{
|
{
|
||||||
url = PageState.Alias.Path;
|
url = PageState.Alias.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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -250,7 +250,7 @@
|
||||||
if (user == null)
|
if (user == null)
|
||||||
{
|
{
|
||||||
// redirect to login page if user not logged in as they may need to be authenticated
|
// redirect to login page if user not logged in as they may need to be authenticated
|
||||||
NavigationManager.NavigateTo(Utilities.NavigateUrl(SiteState.Alias.Path, "login", "?returnurl=" + route.AbsolutePath));
|
NavigationManager.NavigateTo(Utilities.NavigateUrl(SiteState.Alias.Path, "login", "?returnurl=" + WebUtility.UrlEncode(route.PathAndQuery)));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -299,22 +299,28 @@
|
||||||
{
|
{
|
||||||
query = query.Substring(1); // ignore "?"
|
query = query.Substring(1); // ignore "?"
|
||||||
}
|
}
|
||||||
foreach (string kvp in query.Split(new[] { '&' }, StringSplitOptions.RemoveEmptyEntries))
|
foreach (string kvp in query.Split('&', StringSplitOptions.RemoveEmptyEntries))
|
||||||
{
|
{
|
||||||
if (kvp != "")
|
if (kvp != "")
|
||||||
{
|
{
|
||||||
if (kvp.Contains("="))
|
if (kvp.Contains("="))
|
||||||
{
|
{
|
||||||
string[] pair = kvp.Split('=');
|
string[] pair = kvp.Split('=');
|
||||||
|
if (!querystring.ContainsKey(pair[0]))
|
||||||
|
{
|
||||||
querystring.Add(pair[0], pair[1]);
|
querystring.Add(pair[0], pair[1]);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
if (!querystring.ContainsKey(kvp))
|
||||||
{
|
{
|
||||||
querystring.Add(kvp, "true"); // default parameter when no value is provided
|
querystring.Add(kvp, "true"); // default parameter when no value is provided
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return querystring;
|
return querystring;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -358,7 +364,7 @@
|
||||||
}
|
}
|
||||||
if (!string.IsNullOrEmpty(panes))
|
if (!string.IsNullOrEmpty(panes))
|
||||||
{
|
{
|
||||||
page.Panes = panes.Replace(";", ",").Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList();
|
page.Panes = panes.Replace(";", ",").Split(',', StringSplitOptions.RemoveEmptyEntries).ToList();
|
||||||
if (!page.Panes.Contains(PaneNames.Default) && !page.Panes.Contains(PaneNames.Admin))
|
if (!page.Panes.Contains(PaneNames.Default) && !page.Panes.Contains(PaneNames.Admin))
|
||||||
{
|
{
|
||||||
_error = "The Current Theme Does Not Contain A Default Or Admin Pane";
|
_error = "The Current Theme Does Not Contain A Default Or Admin Pane";
|
||||||
|
@ -407,7 +413,7 @@
|
||||||
// check if the module defines custom action routes
|
// check if the module defines custom action routes
|
||||||
if (module.ModuleDefinition.ControlTypeRoutes != "")
|
if (module.ModuleDefinition.ControlTypeRoutes != "")
|
||||||
{
|
{
|
||||||
foreach (string route in module.ModuleDefinition.ControlTypeRoutes.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
|
foreach (string route in module.ModuleDefinition.ControlTypeRoutes.Split(';', StringSplitOptions.RemoveEmptyEntries))
|
||||||
{
|
{
|
||||||
if (route.StartsWith(action + "="))
|
if (route.StartsWith(action + "="))
|
||||||
{
|
{
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<Version>3.2.1</Version>
|
<Version>3.3.1</Version>
|
||||||
<Product>Oqtane</Product>
|
<Product>Oqtane</Product>
|
||||||
<Authors>Shaun Walker</Authors>
|
<Authors>Shaun Walker</Authors>
|
||||||
<Company>.NET Foundation</Company>
|
<Company>.NET Foundation</Company>
|
||||||
|
@ -10,7 +10,7 @@
|
||||||
<Copyright>.NET Foundation</Copyright>
|
<Copyright>.NET Foundation</Copyright>
|
||||||
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
||||||
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
||||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.2.1</PackageReleaseNotes>
|
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.3.1</PackageReleaseNotes>
|
||||||
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
||||||
<RepositoryType>Git</RepositoryType>
|
<RepositoryType>Git</RepositoryType>
|
||||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||||
<metadata>
|
<metadata>
|
||||||
<id>Oqtane.Database.MySQL</id>
|
<id>Oqtane.Database.MySQL</id>
|
||||||
<version>3.2.1</version>
|
<version>3.3.1</version>
|
||||||
<authors>Shaun Walker</authors>
|
<authors>Shaun Walker</authors>
|
||||||
<owners>.NET Foundation</owners>
|
<owners>.NET Foundation</owners>
|
||||||
<title>Oqtane MySQL Provider</title>
|
<title>Oqtane MySQL Provider</title>
|
||||||
|
@ -12,7 +12,7 @@
|
||||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||||
<license type="expression">MIT</license>
|
<license type="expression">MIT</license>
|
||||||
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
||||||
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.2.1</releaseNotes>
|
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.3.1</releaseNotes>
|
||||||
<icon>icon.png</icon>
|
<icon>icon.png</icon>
|
||||||
<tags>oqtane</tags>
|
<tags>oqtane</tags>
|
||||||
</metadata>
|
</metadata>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<Version>3.2.1</Version>
|
<Version>3.3.1</Version>
|
||||||
<Product>Oqtane</Product>
|
<Product>Oqtane</Product>
|
||||||
<Authors>Shaun Walker</Authors>
|
<Authors>Shaun Walker</Authors>
|
||||||
<Company>.NET Foundation</Company>
|
<Company>.NET Foundation</Company>
|
||||||
|
@ -10,7 +10,7 @@
|
||||||
<Copyright>.NET Foundation</Copyright>
|
<Copyright>.NET Foundation</Copyright>
|
||||||
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
||||||
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
||||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.2.1</PackageReleaseNotes>
|
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.3.1</PackageReleaseNotes>
|
||||||
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
||||||
<RepositoryType>Git</RepositoryType>
|
<RepositoryType>Git</RepositoryType>
|
||||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||||
<metadata>
|
<metadata>
|
||||||
<id>Oqtane.Database.PostgreSQL</id>
|
<id>Oqtane.Database.PostgreSQL</id>
|
||||||
<version>3.2.1</version>
|
<version>3.3.1</version>
|
||||||
<authors>Shaun Walker</authors>
|
<authors>Shaun Walker</authors>
|
||||||
<owners>.NET Foundation</owners>
|
<owners>.NET Foundation</owners>
|
||||||
<title>Oqtane PostgreSQL Provider</title>
|
<title>Oqtane PostgreSQL Provider</title>
|
||||||
|
@ -12,7 +12,7 @@
|
||||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||||
<license type="expression">MIT</license>
|
<license type="expression">MIT</license>
|
||||||
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
||||||
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.2.1</releaseNotes>
|
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.3.1</releaseNotes>
|
||||||
<icon>icon.png</icon>
|
<icon>icon.png</icon>
|
||||||
<tags>oqtane</tags>
|
<tags>oqtane</tags>
|
||||||
</metadata>
|
</metadata>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<Version>3.2.1</Version>
|
<Version>3.3.1</Version>
|
||||||
<Product>Oqtane</Product>
|
<Product>Oqtane</Product>
|
||||||
<Authors>Shaun Walker</Authors>
|
<Authors>Shaun Walker</Authors>
|
||||||
<Company>.NET Foundation</Company>
|
<Company>.NET Foundation</Company>
|
||||||
|
@ -10,7 +10,7 @@
|
||||||
<Copyright>.NET Foundation</Copyright>
|
<Copyright>.NET Foundation</Copyright>
|
||||||
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
||||||
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
||||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.2.1</PackageReleaseNotes>
|
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.3.1</PackageReleaseNotes>
|
||||||
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
||||||
<RepositoryType>Git</RepositoryType>
|
<RepositoryType>Git</RepositoryType>
|
||||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||||
<metadata>
|
<metadata>
|
||||||
<id>Oqtane.Database.SqlServer</id>
|
<id>Oqtane.Database.SqlServer</id>
|
||||||
<version>3.2.1</version>
|
<version>3.3.1</version>
|
||||||
<authors>Shaun Walker</authors>
|
<authors>Shaun Walker</authors>
|
||||||
<owners>.NET Foundation</owners>
|
<owners>.NET Foundation</owners>
|
||||||
<title>Oqtane SQL Server Provider</title>
|
<title>Oqtane SQL Server Provider</title>
|
||||||
|
@ -12,7 +12,7 @@
|
||||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||||
<license type="expression">MIT</license>
|
<license type="expression">MIT</license>
|
||||||
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
||||||
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.2.1</releaseNotes>
|
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.3.1</releaseNotes>
|
||||||
<icon>icon.png</icon>
|
<icon>icon.png</icon>
|
||||||
<tags>oqtane</tags>
|
<tags>oqtane</tags>
|
||||||
</metadata>
|
</metadata>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<Version>3.2.1</Version>
|
<Version>3.3.1</Version>
|
||||||
<Product>Oqtane</Product>
|
<Product>Oqtane</Product>
|
||||||
<Authors>Shaun Walker</Authors>
|
<Authors>Shaun Walker</Authors>
|
||||||
<Company>.NET Foundation</Company>
|
<Company>.NET Foundation</Company>
|
||||||
|
@ -10,7 +10,7 @@
|
||||||
<Copyright>.NET Foundation</Copyright>
|
<Copyright>.NET Foundation</Copyright>
|
||||||
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
||||||
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
||||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.2.1</PackageReleaseNotes>
|
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.3.1</PackageReleaseNotes>
|
||||||
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
||||||
<RepositoryType>Git</RepositoryType>
|
<RepositoryType>Git</RepositoryType>
|
||||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||||
<metadata>
|
<metadata>
|
||||||
<id>Oqtane.Database.Sqlite</id>
|
<id>Oqtane.Database.Sqlite</id>
|
||||||
<version>3.2.1</version>
|
<version>3.3.1</version>
|
||||||
<authors>Shaun Walker</authors>
|
<authors>Shaun Walker</authors>
|
||||||
<owners>.NET Foundation</owners>
|
<owners>.NET Foundation</owners>
|
||||||
<title>Oqtane SQLite Provider</title>
|
<title>Oqtane SQLite Provider</title>
|
||||||
|
@ -12,7 +12,7 @@
|
||||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||||
<license type="expression">MIT</license>
|
<license type="expression">MIT</license>
|
||||||
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
||||||
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.2.1</releaseNotes>
|
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.3.1</releaseNotes>
|
||||||
<icon>icon.png</icon>
|
<icon>icon.png</icon>
|
||||||
<tags>oqtane</tags>
|
<tags>oqtane</tags>
|
||||||
</metadata>
|
</metadata>
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<!-- Uncomment to also build the tizen app. You will need to install tizen by following this: https://github.com/Samsung/Tizen.NET -->
|
<!-- Uncomment to also build the tizen app. You will need to install tizen by following this: https://github.com/Samsung/Tizen.NET -->
|
||||||
<!-- <TargetFrameworks>$(TargetFrameworks);net6.0-tizen</TargetFrameworks> -->
|
<!-- <TargetFrameworks>$(TargetFrameworks);net6.0-tizen</TargetFrameworks> -->
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<Version>3.2.1</Version>
|
<Version>3.3.1</Version>
|
||||||
<Product>Oqtane</Product>
|
<Product>Oqtane</Product>
|
||||||
<Authors>Shaun Walker</Authors>
|
<Authors>Shaun Walker</Authors>
|
||||||
<Company>.NET Foundation</Company>
|
<Company>.NET Foundation</Company>
|
||||||
|
@ -14,7 +14,7 @@
|
||||||
<Copyright>.NET Foundation</Copyright>
|
<Copyright>.NET Foundation</Copyright>
|
||||||
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
||||||
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
||||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.2.1</PackageReleaseNotes>
|
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.3.1</PackageReleaseNotes>
|
||||||
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
||||||
<RepositoryType>Git</RepositoryType>
|
<RepositoryType>Git</RepositoryType>
|
||||||
<RootNamespace>Oqtane.Maui</RootNamespace>
|
<RootNamespace>Oqtane.Maui</RootNamespace>
|
||||||
|
@ -31,7 +31,7 @@
|
||||||
<ApplicationIdGuid>0E29FC31-1B83-48ED-B6E0-9F3C67B775D4</ApplicationIdGuid>
|
<ApplicationIdGuid>0E29FC31-1B83-48ED-B6E0-9F3C67B775D4</ApplicationIdGuid>
|
||||||
|
|
||||||
<!-- Versions -->
|
<!-- Versions -->
|
||||||
<ApplicationDisplayVersion>3.2.1</ApplicationDisplayVersion>
|
<ApplicationDisplayVersion>3.3.1</ApplicationDisplayVersion>
|
||||||
<ApplicationVersion>1</ApplicationVersion>
|
<ApplicationVersion>1</ApplicationVersion>
|
||||||
|
|
||||||
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">14.2</SupportedOSPlatformVersion>
|
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">14.2</SupportedOSPlatformVersion>
|
||||||
|
@ -71,8 +71,8 @@
|
||||||
<PackageReference Include="Microsoft.Extensions.Http" Version="6.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Http" Version="6.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="6.0.3" />
|
<PackageReference Include="Microsoft.Extensions.Localization" Version="6.0.3" />
|
||||||
<PackageReference Include="System.Net.Http.Json" Version="6.0.0" />
|
<PackageReference Include="System.Net.Http.Json" Version="6.0.0" />
|
||||||
<PackageReference Include="Oqtane.Client" Version="3.2.1" />
|
<PackageReference Include="Oqtane.Client" Version="3.3.1" />
|
||||||
<PackageReference Include="Oqtane.Shared" Version="3.2.1" />
|
<PackageReference Include="Oqtane.Shared" Version="3.3.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||||
<metadata>
|
<metadata>
|
||||||
<id>Oqtane.Client</id>
|
<id>Oqtane.Client</id>
|
||||||
<version>3.2.1</version>
|
<version>3.3.1</version>
|
||||||
<authors>Shaun Walker</authors>
|
<authors>Shaun Walker</authors>
|
||||||
<owners>.NET Foundation</owners>
|
<owners>.NET Foundation</owners>
|
||||||
<title>Oqtane Framework</title>
|
<title>Oqtane Framework</title>
|
||||||
|
@ -12,7 +12,7 @@
|
||||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||||
<license type="expression">MIT</license>
|
<license type="expression">MIT</license>
|
||||||
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
||||||
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.2.1</releaseNotes>
|
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.3.1</releaseNotes>
|
||||||
<icon>icon.png</icon>
|
<icon>icon.png</icon>
|
||||||
<tags>oqtane</tags>
|
<tags>oqtane</tags>
|
||||||
</metadata>
|
</metadata>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||||
<metadata>
|
<metadata>
|
||||||
<id>Oqtane.Framework</id>
|
<id>Oqtane.Framework</id>
|
||||||
<version>3.2.1</version>
|
<version>3.3.1</version>
|
||||||
<authors>Shaun Walker</authors>
|
<authors>Shaun Walker</authors>
|
||||||
<owners>.NET Foundation</owners>
|
<owners>.NET Foundation</owners>
|
||||||
<title>Oqtane Framework</title>
|
<title>Oqtane Framework</title>
|
||||||
|
@ -11,8 +11,8 @@
|
||||||
<copyright>.NET Foundation</copyright>
|
<copyright>.NET Foundation</copyright>
|
||||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||||
<license type="expression">MIT</license>
|
<license type="expression">MIT</license>
|
||||||
<projectUrl>https://github.com/oqtane/oqtane.framework/releases/download/v3.2.1/Oqtane.Framework.3.2.1.Upgrade.zip</projectUrl>
|
<projectUrl>https://github.com/oqtane/oqtane.framework/releases/download/v3.3.1/Oqtane.Framework.3.3.1.Upgrade.zip</projectUrl>
|
||||||
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.2.1</releaseNotes>
|
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.3.1</releaseNotes>
|
||||||
<icon>icon.png</icon>
|
<icon>icon.png</icon>
|
||||||
<tags>oqtane framework</tags>
|
<tags>oqtane framework</tags>
|
||||||
</metadata>
|
</metadata>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||||
<metadata>
|
<metadata>
|
||||||
<id>Oqtane.Server</id>
|
<id>Oqtane.Server</id>
|
||||||
<version>3.2.1</version>
|
<version>3.3.1</version>
|
||||||
<authors>Shaun Walker</authors>
|
<authors>Shaun Walker</authors>
|
||||||
<owners>.NET Foundation</owners>
|
<owners>.NET Foundation</owners>
|
||||||
<title>Oqtane Framework</title>
|
<title>Oqtane Framework</title>
|
||||||
|
@ -12,7 +12,7 @@
|
||||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||||
<license type="expression">MIT</license>
|
<license type="expression">MIT</license>
|
||||||
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
||||||
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.2.1</releaseNotes>
|
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.3.1</releaseNotes>
|
||||||
<icon>icon.png</icon>
|
<icon>icon.png</icon>
|
||||||
<tags>oqtane</tags>
|
<tags>oqtane</tags>
|
||||||
</metadata>
|
</metadata>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||||
<metadata>
|
<metadata>
|
||||||
<id>Oqtane.Shared</id>
|
<id>Oqtane.Shared</id>
|
||||||
<version>3.2.1</version>
|
<version>3.3.1</version>
|
||||||
<authors>Shaun Walker</authors>
|
<authors>Shaun Walker</authors>
|
||||||
<owners>.NET Foundation</owners>
|
<owners>.NET Foundation</owners>
|
||||||
<title>Oqtane Framework</title>
|
<title>Oqtane Framework</title>
|
||||||
|
@ -12,7 +12,7 @@
|
||||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||||
<license type="expression">MIT</license>
|
<license type="expression">MIT</license>
|
||||||
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
||||||
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.2.1</releaseNotes>
|
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.3.1</releaseNotes>
|
||||||
<icon>icon.png</icon>
|
<icon>icon.png</icon>
|
||||||
<tags>oqtane</tags>
|
<tags>oqtane</tags>
|
||||||
</metadata>
|
</metadata>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||||
<metadata>
|
<metadata>
|
||||||
<id>Oqtane.Updater</id>
|
<id>Oqtane.Updater</id>
|
||||||
<version>3.2.1</version>
|
<version>3.3.1</version>
|
||||||
<authors>Shaun Walker</authors>
|
<authors>Shaun Walker</authors>
|
||||||
<owners>.NET Foundation</owners>
|
<owners>.NET Foundation</owners>
|
||||||
<title>Oqtane Framework</title>
|
<title>Oqtane Framework</title>
|
||||||
|
@ -12,7 +12,7 @@
|
||||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||||
<license type="expression">MIT</license>
|
<license type="expression">MIT</license>
|
||||||
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
||||||
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.2.1</releaseNotes>
|
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.3.1</releaseNotes>
|
||||||
<icon>icon.png</icon>
|
<icon>icon.png</icon>
|
||||||
<tags>oqtane</tags>
|
<tags>oqtane</tags>
|
||||||
</metadata>
|
</metadata>
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Compress-Archive -Path "..\Oqtane.Server\bin\Release\net6.0\publish\*" -DestinationPath "Oqtane.Framework.3.2.1.Install.zip" -Force
|
Compress-Archive -Path "..\Oqtane.Server\bin\Release\net6.0\publish\*" -DestinationPath "Oqtane.Framework.3.3.1.Install.zip" -Force
|
|
@ -13,6 +13,23 @@ rmdir /Q/S "..\Oqtane.Server\bin\Release\net6.0\publish"
|
||||||
dotnet publish ..\Oqtane.Server\Oqtane.Server.csproj /p:Configuration=Release
|
dotnet publish ..\Oqtane.Server\Oqtane.Server.csproj /p:Configuration=Release
|
||||||
del /F/Q/S "..\Oqtane.Server\bin\Release\net6.0\publish\wwwroot\Content" > NUL
|
del /F/Q/S "..\Oqtane.Server\bin\Release\net6.0\publish\wwwroot\Content" > NUL
|
||||||
rmdir /Q/S "..\Oqtane.Server\bin\Release\net6.0\publish\wwwroot\Content"
|
rmdir /Q/S "..\Oqtane.Server\bin\Release\net6.0\publish\wwwroot\Content"
|
||||||
|
setlocal ENABLEDELAYEDEXPANSION
|
||||||
|
set retain=Oqtane.Modules.Admin.Login,Oqtane.Modules.HtmlText,Templates
|
||||||
|
for /D %%i in ("..\Oqtane.Server\bin\Release\net6.0\publish\wwwroot\Modules\*") do (
|
||||||
|
set /A found=0
|
||||||
|
for %%j in (%retain%) do (
|
||||||
|
if "%%~nxi" == "%%j" set /A found=1
|
||||||
|
)
|
||||||
|
if not !found! == 1 rmdir /Q/S "%%i"
|
||||||
|
)
|
||||||
|
set retain=Oqtane.Themes.BlazorTheme,Oqtane.Themes.OqtaneTheme,Templates
|
||||||
|
for /D %%i in ("..\Oqtane.Server\bin\Release\net6.0\publish\wwwroot\Themes\*") do (
|
||||||
|
set /A found=0
|
||||||
|
for %%j in (%retain%) do (
|
||||||
|
if "%%~nxi" == "%%j" set /A found=1
|
||||||
|
)
|
||||||
|
if not !found! == 1 rmdir /Q/S "%%i"
|
||||||
|
)
|
||||||
del "..\Oqtane.Server\bin\Release\net6.0\publish\appsettings.json"
|
del "..\Oqtane.Server\bin\Release\net6.0\publish\appsettings.json"
|
||||||
ren "..\Oqtane.Server\bin\Release\net6.0\publish\appsettings.release.json" "appsettings.json"
|
ren "..\Oqtane.Server\bin\Release\net6.0\publish\appsettings.release.json" "appsettings.json"
|
||||||
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe ".\install.ps1"
|
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe ".\install.ps1"
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Compress-Archive -Path "..\Oqtane.Server\bin\Release\net6.0\publish\*" -DestinationPath "Oqtane.Framework.3.2.1.Upgrade.zip" -Force
|
Compress-Archive -Path "..\Oqtane.Server\bin\Release\net6.0\publish\*" -DestinationPath "Oqtane.Framework.3.3.1.Upgrade.zip" -Force
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -20,7 +20,6 @@ using SixLabors.ImageSharp;
|
||||||
using SixLabors.ImageSharp.Processing;
|
using SixLabors.ImageSharp.Processing;
|
||||||
using SixLabors.ImageSharp.Formats.Png;
|
using SixLabors.ImageSharp.Formats.Png;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using Oqtane.Migrations.Tenant;
|
|
||||||
|
|
||||||
// ReSharper disable StringIndexOfIsCultureSpecific.1
|
// ReSharper disable StringIndexOfIsCultureSpecific.1
|
||||||
|
|
||||||
|
@ -142,7 +141,7 @@ namespace Oqtane.Controllers
|
||||||
{
|
{
|
||||||
if (File.Name != file.Name || File.FolderId != file.FolderId)
|
if (File.Name != file.Name || File.FolderId != file.FolderId)
|
||||||
{
|
{
|
||||||
file.Folder = _folders.GetFolder(file.FolderId);
|
file.Folder = _folders.GetFolder(file.FolderId, false);
|
||||||
string folderpath = _folders.GetFolderPath(file.Folder);
|
string folderpath = _folders.GetFolderPath(file.Folder);
|
||||||
if (!Directory.Exists(folderpath))
|
if (!Directory.Exists(folderpath))
|
||||||
{
|
{
|
||||||
|
@ -151,7 +150,7 @@ namespace Oqtane.Controllers
|
||||||
System.IO.File.Move(_files.GetFilePath(File), Path.Combine(folderpath, file.Name));
|
System.IO.File.Move(_files.GetFilePath(File), Path.Combine(folderpath, file.Name));
|
||||||
}
|
}
|
||||||
|
|
||||||
var newfile = CreateFile(file.Name, file.Folder.FolderId, _files.GetFilePath(file));
|
var newfile = CreateFile(File.Name, file.Folder.FolderId, _files.GetFilePath(file));
|
||||||
if (newfile != null)
|
if (newfile != null)
|
||||||
{
|
{
|
||||||
file.Extension = newfile.Extension;
|
file.Extension = newfile.Extension;
|
||||||
|
@ -659,10 +658,10 @@ namespace Oqtane.Controllers
|
||||||
var file = _files.GetFile(folderid, filename);
|
var file = _files.GetFile(folderid, filename);
|
||||||
|
|
||||||
int size = 0;
|
int size = 0;
|
||||||
var folder = _folders.GetFolder(folderid);
|
var folder = _folders.GetFolder(folderid, false);
|
||||||
if (folder.Capacity != 0)
|
if (folder.Capacity != 0)
|
||||||
{
|
{
|
||||||
foreach (var f in _files.GetFiles(folderid))
|
foreach (var f in _files.GetFiles(folderid, false))
|
||||||
{
|
{
|
||||||
size += f.Size;
|
size += f.Size;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -46,7 +46,7 @@ namespace Oqtane.Controllers
|
||||||
_identityCache = identityCache;
|
_identityCache = identityCache;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_alias = tenantManager.GetAlias();
|
_alias = tenantManager.GetAlias();
|
||||||
_visitorCookie = "APP_VISITOR_" + _alias.SiteId.ToString();
|
_visitorCookie = Constants.VisitorCookiePrefix + _alias.SiteId.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
// GET: api/<controller>
|
// GET: api/<controller>
|
||||||
|
@ -63,10 +63,14 @@ namespace Oqtane.Controllers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
// suppress unauthorized visitor logging as it is usually caused by clients that do not support cookies
|
||||||
|
if (entityName != EntityNames.Visitor)
|
||||||
{
|
{
|
||||||
_logger.Log(LogLevel.Error, this, LogFunction.Read, "User Not Authorized To Access Settings {EntityName} {EntityId}", entityName, entityId);
|
_logger.Log(LogLevel.Error, this, LogFunction.Read, "User Not Authorized To Access Settings {EntityName} {EntityId}", entityName, entityId);
|
||||||
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return settings;
|
return settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,9 +88,12 @@ namespace Oqtane.Controllers
|
||||||
return setting;
|
return setting;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
if (entityName != EntityNames.Visitor)
|
||||||
{
|
{
|
||||||
_logger.Log(LogLevel.Error, this, LogFunction.Read, "User Not Authorized To Access Setting {EntityName} {SettingId}", entityName, id);
|
_logger.Log(LogLevel.Error, this, LogFunction.Read, "User Not Authorized To Access Setting {EntityName} {SettingId}", entityName, id);
|
||||||
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -102,9 +109,12 @@ namespace Oqtane.Controllers
|
||||||
_logger.Log(LogLevel.Information, this, LogFunction.Create, "Setting Added {Setting}", setting);
|
_logger.Log(LogLevel.Information, this, LogFunction.Create, "Setting Added {Setting}", setting);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
if (setting.EntityName != EntityNames.Visitor)
|
||||||
{
|
{
|
||||||
_logger.Log(LogLevel.Error, this, LogFunction.Create, "User Not Authorized To Add Setting {Setting}", setting);
|
_logger.Log(LogLevel.Error, this, LogFunction.Create, "User Not Authorized To Add Setting {Setting}", setting);
|
||||||
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
||||||
|
}
|
||||||
setting = null;
|
setting = null;
|
||||||
}
|
}
|
||||||
return setting;
|
return setting;
|
||||||
|
@ -121,9 +131,12 @@ namespace Oqtane.Controllers
|
||||||
_logger.Log(LogLevel.Information, this, LogFunction.Update, "Setting Updated {Setting}", setting);
|
_logger.Log(LogLevel.Information, this, LogFunction.Update, "Setting Updated {Setting}", setting);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
if (setting.EntityName != EntityNames.Visitor)
|
||||||
{
|
{
|
||||||
_logger.Log(LogLevel.Error, this, LogFunction.Update, "User Not Authorized To Update Setting {Setting}", setting);
|
_logger.Log(LogLevel.Error, this, LogFunction.Update, "User Not Authorized To Update Setting {Setting}", setting);
|
||||||
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
||||||
|
}
|
||||||
setting = null;
|
setting = null;
|
||||||
}
|
}
|
||||||
return setting;
|
return setting;
|
||||||
|
@ -141,11 +154,14 @@ namespace Oqtane.Controllers
|
||||||
_logger.Log(LogLevel.Information, this, LogFunction.Delete, "Setting Deleted {Setting}", setting);
|
_logger.Log(LogLevel.Information, this, LogFunction.Delete, "Setting Deleted {Setting}", setting);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
if (entityName != EntityNames.Visitor)
|
||||||
{
|
{
|
||||||
_logger.Log(LogLevel.Error, this, LogFunction.Delete, "User Not Authorized To Delete Setting {Setting}", setting);
|
_logger.Log(LogLevel.Error, this, LogFunction.Delete, "User Not Authorized To Delete Setting {Setting}", setting);
|
||||||
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// DELETE api/<controller>/clear
|
// DELETE api/<controller>/clear
|
||||||
[HttpDelete("clear")]
|
[HttpDelete("clear")]
|
||||||
|
@ -212,13 +228,14 @@ 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:
|
||||||
authorized = User.IsInRole(RoleNames.Admin);
|
authorized = User.IsInRole(RoleNames.Admin);
|
||||||
if (!authorized)
|
if (!authorized)
|
||||||
{
|
{
|
||||||
|
// a visitor may have cookies disabled
|
||||||
if (int.TryParse(Request.Cookies[_visitorCookie], out int visitorId))
|
if (int.TryParse(Request.Cookies[_visitorCookie], out int visitorId))
|
||||||
{
|
{
|
||||||
authorized = (visitorId == entityId);
|
authorized = (visitorId == entityId);
|
||||||
|
@ -226,13 +243,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 = _userPermissions.IsAuthorized(User, _alias.SiteId, entityName, entityId, permissionName) ||
|
||||||
}
|
_userPermissions.IsAuthorized(User, _alias.SiteId, entityName, -1, PermissionNames.Write, RoleNames.Admin);
|
||||||
else
|
|
||||||
{
|
|
||||||
authorized = true;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,7 @@ namespace Oqtane.Controllers
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
results.Add(new Dictionary<string, string>() { { "Error", ex.Message } });
|
results.Add(new Dictionary<string, string>() { { "Error", ex.Message } });
|
||||||
_logger.Log(LogLevel.Error, this, LogFunction.Other, ex, "Sql Query {Query} Executed on Tenant {TenantId} Resulted In An Error {Error}", sqlquery.Query, sqlquery.TenantId, ex.Message);
|
_logger.Log(LogLevel.Warning, this, LogFunction.Other, "Sql Query {Query} Executed on Tenant {TenantId} Resulted In An Error {Error}", sqlquery.Query, sqlquery.TenantId, ex.Message);
|
||||||
}
|
}
|
||||||
sqlquery.Results = results;
|
sqlquery.Results = results;
|
||||||
return sqlquery;
|
return sqlquery;
|
||||||
|
|
|
@ -6,6 +6,7 @@ using System;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Oqtane.Infrastructure;
|
using Oqtane.Infrastructure;
|
||||||
using Microsoft.AspNetCore.Http.Features;
|
using Microsoft.AspNetCore.Http.Features;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
namespace Oqtane.Controllers
|
namespace Oqtane.Controllers
|
||||||
{
|
{
|
||||||
|
@ -53,6 +54,15 @@ namespace Oqtane.Controllers
|
||||||
systeminfo.Add("UseSwagger", _configManager.GetSetting("UseSwagger", "true"));
|
systeminfo.Add("UseSwagger", _configManager.GetSetting("UseSwagger", "true"));
|
||||||
systeminfo.Add("PackageService", _configManager.GetSetting("PackageService", "true"));
|
systeminfo.Add("PackageService", _configManager.GetSetting("PackageService", "true"));
|
||||||
break;
|
break;
|
||||||
|
case "log":
|
||||||
|
string log = "";
|
||||||
|
string path = Path.Combine(_environment.ContentRootPath, "Content", "Log", "error.log");
|
||||||
|
if (System.IO.File.Exists(path))
|
||||||
|
{
|
||||||
|
log = System.IO.File.ReadAllText(path);
|
||||||
|
}
|
||||||
|
systeminfo.Add("Log", log);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return systeminfo;
|
return systeminfo;
|
||||||
|
@ -74,7 +84,7 @@ namespace Oqtane.Controllers
|
||||||
{
|
{
|
||||||
foreach(KeyValuePair<string, object> kvp in settings)
|
foreach(KeyValuePair<string, object> kvp in settings)
|
||||||
{
|
{
|
||||||
_configManager.AddOrUpdateSetting(kvp.Key, kvp.Value, false);
|
UpdateSetting(kvp.Key, kvp.Value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,7 +93,24 @@ namespace Oqtane.Controllers
|
||||||
[Authorize(Roles = RoleNames.Host)]
|
[Authorize(Roles = RoleNames.Host)]
|
||||||
public void Put(string key, object value)
|
public void Put(string key, object value)
|
||||||
{
|
{
|
||||||
|
UpdateSetting(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateSetting(string key, object value)
|
||||||
|
{
|
||||||
|
switch (key)
|
||||||
|
{
|
||||||
|
case "Log":
|
||||||
|
string path = Path.Combine(_environment.ContentRootPath, "Content", "Log", "error.log");
|
||||||
|
if (System.IO.File.Exists(path))
|
||||||
|
{
|
||||||
|
System.IO.File.Delete(path);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
_configManager.AddOrUpdateSetting(key, value, false);
|
_configManager.AddOrUpdateSetting(key, value, false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -50,7 +50,7 @@ namespace Oqtane.Controllers
|
||||||
bool authorized = User.IsInRole(RoleNames.Admin);
|
bool authorized = User.IsInRole(RoleNames.Admin);
|
||||||
if (!authorized)
|
if (!authorized)
|
||||||
{
|
{
|
||||||
var visitorCookie = "APP_VISITOR_" + _alias.SiteId.ToString();
|
var visitorCookie = Constants.VisitorCookiePrefix + _alias.SiteId.ToString();
|
||||||
if (int.TryParse(Request.Cookies[visitorCookie], out int visitorId))
|
if (int.TryParse(Request.Cookies[visitorCookie], out int visitorId))
|
||||||
{
|
{
|
||||||
authorized = (visitorId == id);
|
authorized = (visitorId == 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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,7 +62,7 @@ namespace Oqtane.Infrastructure
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
result.Message = "Master Database Not Installed Correctly. " + ex.Message;
|
result.Message = "Master Database Not Installed Correctly. " + ex.ToString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else // cannot connect
|
else // cannot connect
|
||||||
|
@ -74,7 +74,7 @@ namespace Oqtane.Infrastructure
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
result.Message = "Cannot Connect To Master Database. " + ex.Message;
|
result.Message = "Cannot Connect To Master Database. " + ex.ToString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -247,7 +247,7 @@ namespace Oqtane.Infrastructure
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
result.Message = ex.Message;
|
result.Message = ex.ToString();
|
||||||
_filelogger.LogError(Utilities.LogMessage(this, result.Message));
|
_filelogger.LogError(Utilities.LogMessage(this, result.Message));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -286,7 +286,7 @@ namespace Oqtane.Infrastructure
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
result.Message = "An Error Occurred Creating The Database. This Is Usually Related To Your User Not Having Sufficient Rights To Perform This Operation. Please Note That You Can Also Create The Database Manually Prior To Initiating The Install Wizard. " + ex.Message;
|
result.Message = "An Error Occurred Creating The Database. This Is Usually Related To Your User Not Having Sufficient Rights To Perform This Operation. Please Note That You Can Also Create The Database Manually Prior To Initiating The Install Wizard. " + ex.ToString();
|
||||||
_filelogger.LogError(Utilities.LogMessage(this, result.Message));
|
_filelogger.LogError(Utilities.LogMessage(this, result.Message));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -327,7 +327,7 @@ namespace Oqtane.Infrastructure
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
result.Message = "An Error Occurred Provisioning The Master Database. This Is Usually Related To The Master Database Not Being In A Supported State. " + ex.Message;
|
result.Message = "An Error Occurred Provisioning The Master Database. This Is Usually Related To The Master Database Not Being In A Supported State. " + ex.ToString();
|
||||||
_filelogger.LogError(Utilities.LogMessage(this, result.Message));
|
_filelogger.LogError(Utilities.LogMessage(this, result.Message));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -370,7 +370,7 @@ namespace Oqtane.Infrastructure
|
||||||
tenant = db.Tenant.FirstOrDefault(item => item.Name == install.TenantName);
|
tenant = db.Tenant.FirstOrDefault(item => item.Name == install.TenantName);
|
||||||
}
|
}
|
||||||
|
|
||||||
var aliasNames = install.Aliases.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(sValue => sValue.Trim()).ToArray();
|
var aliasNames = install.Aliases.Split(',', StringSplitOptions.RemoveEmptyEntries).Select(sValue => sValue.Trim()).ToArray();
|
||||||
var firstAlias = aliasNames[0];
|
var firstAlias = aliasNames[0];
|
||||||
foreach (var aliasName in aliasNames)
|
foreach (var aliasName in aliasNames)
|
||||||
{
|
{
|
||||||
|
@ -406,7 +406,7 @@ namespace Oqtane.Infrastructure
|
||||||
{
|
{
|
||||||
var result = new Installation { Success = false, Message = string.Empty };
|
var result = new Installation { Success = false, Message = string.Empty };
|
||||||
|
|
||||||
var versions = Constants.ReleaseVersions.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
var versions = Constants.ReleaseVersions.Split(',', StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
|
||||||
using (var scope = _serviceScopeFactory.CreateScope())
|
using (var scope = _serviceScopeFactory.CreateScope())
|
||||||
{
|
{
|
||||||
|
@ -435,7 +435,7 @@ namespace Oqtane.Infrastructure
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
result.Message = "An Error Occurred Migrating A Tenant Database. This Is Usually Related To A Tenant Database Not Being In A Supported State. " + ex.Message;
|
result.Message = "An Error Occurred Migrating A Tenant Database. This Is Usually Related To A Tenant Database Not Being In A Supported State. " + ex.ToString();
|
||||||
_filelogger.LogError(Utilities.LogMessage(this, result.Message));
|
_filelogger.LogError(Utilities.LogMessage(this, result.Message));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -456,7 +456,7 @@ namespace Oqtane.Infrastructure
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
result.Message = "An Error Occurred Executing Upgrade Logic. " + ex.Message;
|
result.Message = "An Error Occurred Executing Upgrade Logic. " + ex.ToString();
|
||||||
_filelogger.LogError(Utilities.LogMessage(this, result.Message));
|
_filelogger.LogError(Utilities.LogMessage(this, result.Message));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -486,7 +486,7 @@ namespace Oqtane.Infrastructure
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(moduleDefinition.ReleaseVersions))
|
if (!string.IsNullOrEmpty(moduleDefinition.ReleaseVersions))
|
||||||
{
|
{
|
||||||
var versions = moduleDefinition.ReleaseVersions.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
var versions = moduleDefinition.ReleaseVersions.Split(',', StringSplitOptions.RemoveEmptyEntries);
|
||||||
using (var db = GetInstallationContext())
|
using (var db = GetInstallationContext())
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(moduleDefinition.ServerManagerType))
|
if (!string.IsNullOrEmpty(moduleDefinition.ServerManagerType))
|
||||||
|
@ -526,7 +526,7 @@ namespace Oqtane.Infrastructure
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
result.Message = "An Error Occurred Installing " + moduleDefinition.Name + " Version " + versions[i] + " - " + ex.Message;
|
result.Message = "An Error Occurred Installing " + moduleDefinition.Name + " Version " + versions[i] + " - " + ex.ToString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -575,7 +575,7 @@ namespace Oqtane.Infrastructure
|
||||||
{
|
{
|
||||||
// set the alias explicitly so the tenant can be resolved
|
// set the alias explicitly so the tenant can be resolved
|
||||||
var aliases = scope.ServiceProvider.GetRequiredService<IAliasRepository>();
|
var aliases = scope.ServiceProvider.GetRequiredService<IAliasRepository>();
|
||||||
var aliasNames = install.Aliases.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(sValue => sValue.Trim()).ToArray();
|
var aliasNames = install.Aliases.Split(',', StringSplitOptions.RemoveEmptyEntries).Select(sValue => sValue.Trim()).ToArray();
|
||||||
var firstAlias = aliasNames[0];
|
var firstAlias = aliasNames[0];
|
||||||
var alias = aliases.GetAliases().FirstOrDefault(item => item.Name == firstAlias);
|
var alias = aliases.GetAliases().FirstOrDefault(item => item.Name == firstAlias);
|
||||||
var tenantManager = scope.ServiceProvider.GetRequiredService<ITenantManager>();
|
var tenantManager = scope.ServiceProvider.GetRequiredService<ITenantManager>();
|
||||||
|
@ -664,7 +664,7 @@ namespace Oqtane.Infrastructure
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
result.Message = "An Error Occurred Creating Site. " + ex.Message;
|
result.Message = "An Error Occurred Creating Site. " + ex.ToString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -737,7 +737,7 @@ namespace Oqtane.Infrastructure
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.Log(alias.SiteId, Shared.LogLevel.Error, "Site Migration", LogFunction.Other, "An Error Occurred Executing Site Migration {Type} For {Alias} And Version {Version} {Error}", upgrade.Value, alias.Name, version, ex.Message);
|
logger.Log(alias.SiteId, Shared.LogLevel.Error, "Site Migration", LogFunction.Other, ex, "An Error Occurred Executing Site Migration {Type} For {Alias} And Version {Version}", upgrade.Value, alias.Name, version);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,7 +66,7 @@ namespace Oqtane.Infrastructure
|
||||||
List<Notification> notifications = notificationRepository.GetNotifications(site.SiteId, -1, -1).ToList();
|
List<Notification> notifications = notificationRepository.GetNotifications(site.SiteId, -1, -1).ToList();
|
||||||
foreach (Notification notification in notifications)
|
foreach (Notification notification in notifications)
|
||||||
{
|
{
|
||||||
// get sender and receiver information if not provided
|
// get sender and receiver information from user object if not provided
|
||||||
if ((string.IsNullOrEmpty(notification.FromEmail) || string.IsNullOrEmpty(notification.FromDisplayName)) && notification.FromUserId != null)
|
if ((string.IsNullOrEmpty(notification.FromEmail) || string.IsNullOrEmpty(notification.FromDisplayName)) && notification.FromUserId != null)
|
||||||
{
|
{
|
||||||
var user = userRepository.GetUser(notification.FromUserId.Value);
|
var user = userRepository.GetUser(notification.FromUserId.Value);
|
||||||
|
@ -96,31 +96,41 @@ namespace Oqtane.Infrastructure
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
MailMessage mailMessage = new MailMessage();
|
MailMessage mailMessage = new MailMessage();
|
||||||
mailMessage.From = new MailAddress(settings["SMTPSender"], site.Name);
|
|
||||||
mailMessage.Subject = notification.Subject;
|
// sender
|
||||||
if (!string.IsNullOrEmpty(notification.FromEmail) && !string.IsNullOrEmpty(notification.FromDisplayName))
|
if (settings.ContainsKey("SMTPRelay") && settings["SMTPRelay"] == "True" && !string.IsNullOrEmpty(notification.FromEmail))
|
||||||
{
|
{
|
||||||
mailMessage.Body = "From: " + notification.FromDisplayName + "<" + notification.FromEmail + ">" + "\n";
|
if (!string.IsNullOrEmpty(notification.FromDisplayName))
|
||||||
|
{
|
||||||
|
mailMessage.From = new MailAddress(notification.FromEmail, notification.FromDisplayName);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mailMessage.Body = "From: " + site.Name + "\n";
|
mailMessage.From = new MailAddress(notification.FromEmail);
|
||||||
}
|
}
|
||||||
mailMessage.Body += "Sent: " + notification.CreatedOn + "\n";
|
}
|
||||||
if (!string.IsNullOrEmpty(notification.ToEmail) && !string.IsNullOrEmpty(notification.ToDisplayName))
|
else
|
||||||
|
{
|
||||||
|
mailMessage.From = new MailAddress(settings["SMTPSender"], (!string.IsNullOrEmpty(notification.FromDisplayName)) ? notification.FromDisplayName : site.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// recipient
|
||||||
|
if (!string.IsNullOrEmpty(notification.ToDisplayName))
|
||||||
{
|
{
|
||||||
mailMessage.To.Add(new MailAddress(notification.ToEmail, notification.ToDisplayName));
|
mailMessage.To.Add(new MailAddress(notification.ToEmail, notification.ToDisplayName));
|
||||||
mailMessage.Body += "To: " + notification.ToDisplayName + "<" + notification.ToEmail + ">" + "\n";
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mailMessage.To.Add(new MailAddress(notification.ToEmail));
|
mailMessage.To.Add(new MailAddress(notification.ToEmail));
|
||||||
mailMessage.Body += "To: " + notification.ToEmail + "\n";
|
|
||||||
}
|
}
|
||||||
mailMessage.Body += "Subject: " + notification.Subject + "\n\n";
|
|
||||||
mailMessage.Body += notification.Body;
|
|
||||||
|
|
||||||
// set encoding
|
// subject
|
||||||
|
mailMessage.Subject = notification.Subject;
|
||||||
|
|
||||||
|
//body
|
||||||
|
mailMessage.Body = notification.Body;
|
||||||
|
|
||||||
|
// encoding
|
||||||
mailMessage.SubjectEncoding = System.Text.Encoding.UTF8;
|
mailMessage.SubjectEncoding = System.Text.Encoding.UTF8;
|
||||||
mailMessage.BodyEncoding = System.Text.Encoding.UTF8;
|
mailMessage.BodyEncoding = System.Text.Encoding.UTF8;
|
||||||
|
|
||||||
|
|
|
@ -43,10 +43,10 @@ namespace Oqtane.Infrastructure
|
||||||
});
|
});
|
||||||
context.Items.Add(Constants.HttpContextSiteSettingsKey, sitesettings);
|
context.Items.Add(Constants.HttpContextSiteSettingsKey, sitesettings);
|
||||||
|
|
||||||
// rewrite path by removing alias path prefix from api and pages requests (for consistent routing)
|
// rewrite path by removing alias path prefix from reserved route (api,pages,files) requests for consistent routes
|
||||||
if (!string.IsNullOrEmpty(alias.Path))
|
if (!string.IsNullOrEmpty(alias.Path))
|
||||||
{
|
{
|
||||||
if (path.StartsWith("/" + alias.Path) && (path.Contains("/api/") || path.Contains("/pages/")))
|
if (path.StartsWith("/" + alias.Path) && (Constants.ReservedRoutes.Any(item => path.Contains("/" + item + "/"))))
|
||||||
{
|
{
|
||||||
context.Request.Path = path.Replace("/" + alias.Path, "");
|
context.Request.Path = path.Replace("/" + alias.Path, "");
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,7 +68,7 @@ namespace Oqtane.SiteTemplates
|
||||||
new Permission(PermissionNames.View, RoleNames.Admin, true),
|
new Permission(PermissionNames.View, RoleNames.Admin, true),
|
||||||
new Permission(PermissionNames.Edit, RoleNames.Admin, true)
|
new Permission(PermissionNames.Edit, RoleNames.Admin, true)
|
||||||
}.EncodePermissions(),
|
}.EncodePermissions(),
|
||||||
Content = "<p>Copyright (c) 2018-2022 .NET Foundation</p>" +
|
Content = "<p>Copyright (c) 2018-2023 .NET Foundation</p>" +
|
||||||
"<p>Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:</p>" +
|
"<p>Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:</p>" +
|
||||||
"<p>The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.</p>" +
|
"<p>The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.</p>" +
|
||||||
"<p>THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.</p>"
|
"<p>THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.</p>"
|
||||||
|
|
|
@ -37,7 +37,7 @@ namespace Oqtane.Infrastructure
|
||||||
{
|
{
|
||||||
// legacy support for client api requests which would include the alias as a path prefix ( ie. {alias}/api/[controller] )
|
// legacy support for client api requests which would include the alias as a path prefix ( ie. {alias}/api/[controller] )
|
||||||
int aliasId;
|
int aliasId;
|
||||||
string[] segments = httpcontext.Request.Path.Value.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
|
string[] segments = httpcontext.Request.Path.Value.Split('/', StringSplitOptions.RemoveEmptyEntries);
|
||||||
if (segments.Length > 1 && Shared.Constants.ReservedRoutes.Contains(segments[1]) && int.TryParse(segments[0], out aliasId))
|
if (segments.Length > 1 && Shared.Constants.ReservedRoutes.Contains(segments[1]) && int.TryParse(segments[0], out aliasId))
|
||||||
{
|
{
|
||||||
alias = _aliasRepository.GetAliases().ToList().FirstOrDefault(item => item.AliasId == aliasId);
|
alias = _aliasRepository.GetAliases().ToList().FirstOrDefault(item => item.AliasId == aliasId);
|
||||||
|
|
|
@ -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}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Oqtane.Databases.Interfaces;
|
||||||
|
using Oqtane.Migrations.EntityBuilders;
|
||||||
|
using Oqtane.Repository;
|
||||||
|
|
||||||
|
namespace Oqtane.Migrations.Tenant
|
||||||
|
{
|
||||||
|
[DbContext(typeof(TenantDBContext))]
|
||||||
|
[Migration("Tenant.03.03.02.01")]
|
||||||
|
public class AddFolderFileIsDeletedColumns : MultiDatabaseMigration
|
||||||
|
{
|
||||||
|
public AddFolderFileIsDeletedColumns(IDatabase database) : base(database)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
// IsDeleted columns were removed in 3.2.2 however SQLite does not support column removal so they had to be restored
|
||||||
|
if (ActiveDatabase.Name != "Sqlite")
|
||||||
|
{
|
||||||
|
var folderEntityBuilder = new FolderEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
folderEntityBuilder.AddBooleanColumn("IsDeleted", true);
|
||||||
|
|
||||||
|
var fileEntityBuilder = new FileEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
fileEntityBuilder.AddBooleanColumn("IsDeleted", true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
// not implemented
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,7 +3,7 @@
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<Configurations>Debug;Release</Configurations>
|
<Configurations>Debug;Release</Configurations>
|
||||||
<Version>3.2.1</Version>
|
<Version>3.3.1</Version>
|
||||||
<Product>Oqtane</Product>
|
<Product>Oqtane</Product>
|
||||||
<Authors>Shaun Walker</Authors>
|
<Authors>Shaun Walker</Authors>
|
||||||
<Company>.NET Foundation</Company>
|
<Company>.NET Foundation</Company>
|
||||||
|
@ -11,7 +11,7 @@
|
||||||
<Copyright>.NET Foundation</Copyright>
|
<Copyright>.NET Foundation</Copyright>
|
||||||
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
||||||
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
||||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.2.1</PackageReleaseNotes>
|
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.3.1</PackageReleaseNotes>
|
||||||
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
||||||
<RepositoryType>Git</RepositoryType>
|
<RepositoryType>Git</RepositoryType>
|
||||||
<RootNamespace>Oqtane</RootNamespace>
|
<RootNamespace>Oqtane</RootNamespace>
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
using System.Net;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
|
@ -43,6 +44,10 @@ namespace Oqtane.Pages
|
||||||
{
|
{
|
||||||
returnurl = "";
|
returnurl = "";
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
returnurl = WebUtility.UrlDecode(returnurl);
|
||||||
|
}
|
||||||
if (!returnurl.StartsWith("/"))
|
if (!returnurl.StartsWith("/"))
|
||||||
{
|
{
|
||||||
returnurl = "/" + returnurl;
|
returnurl = "/" + returnurl;
|
||||||
|
|
|
@ -20,7 +20,6 @@ using Oqtane.Enums;
|
||||||
using Oqtane.Security;
|
using Oqtane.Security;
|
||||||
using Oqtane.Extensions;
|
using Oqtane.Extensions;
|
||||||
using Oqtane.Themes;
|
using Oqtane.Themes;
|
||||||
using Oqtane.UI;
|
|
||||||
|
|
||||||
namespace Oqtane.Pages
|
namespace Oqtane.Pages
|
||||||
{
|
{
|
||||||
|
@ -285,7 +284,7 @@ namespace Oqtane.Pages
|
||||||
// check if cookie already exists
|
// check if cookie already exists
|
||||||
Visitor visitor = null;
|
Visitor visitor = null;
|
||||||
bool addcookie = false;
|
bool addcookie = false;
|
||||||
var VisitorCookie = "APP_VISITOR_" + SiteId.ToString();
|
var VisitorCookie = Constants.VisitorCookiePrefix + SiteId.ToString();
|
||||||
if (!int.TryParse(Request.Cookies[VisitorCookie], out VisitorId))
|
if (!int.TryParse(Request.Cookies[VisitorCookie], out VisitorId))
|
||||||
{
|
{
|
||||||
// if enabled use IP Address correlation
|
// if enabled use IP Address correlation
|
||||||
|
|
|
@ -67,7 +67,7 @@ namespace Oqtane.Repository
|
||||||
Alias alias = null;
|
Alias alias = null;
|
||||||
|
|
||||||
List<Alias> aliases = GetAliases().ToList();
|
List<Alias> aliases = GetAliases().ToList();
|
||||||
var segments = url.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
|
var segments = url.Split('/', StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
|
||||||
// iterate segments to find keywords
|
// iterate segments to find keywords
|
||||||
int start = segments.Length;
|
int start = segments.Length;
|
||||||
|
|
|
@ -31,7 +31,7 @@ namespace Oqtane.Repository
|
||||||
_accessor = httpContextAccessor;
|
_accessor = httpContextAccessor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IDatabase ActiveDatabase { get; private set; }
|
public IDatabase ActiveDatabase { get; set; }
|
||||||
|
|
||||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
@ -27,10 +26,23 @@ namespace Oqtane.Repository
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<File> GetFiles(int folderId)
|
public IEnumerable<File> GetFiles(int folderId)
|
||||||
|
{
|
||||||
|
return GetFiles(folderId, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<File> GetFiles(int folderId, bool tracking)
|
||||||
{
|
{
|
||||||
var alias = _tenants.GetAlias();
|
var alias = _tenants.GetAlias();
|
||||||
IEnumerable<Permission> permissions = _permissions.GetPermissions(alias.SiteId, EntityNames.Folder, folderId).ToList();
|
IEnumerable<Permission> permissions = _permissions.GetPermissions(alias.SiteId, EntityNames.Folder, folderId).ToList();
|
||||||
IEnumerable<File> files = _db.File.Where(item => item.FolderId == folderId).Include(item => item.Folder);
|
IEnumerable<File> files;
|
||||||
|
if (tracking)
|
||||||
|
{
|
||||||
|
files = _db.File.Where(item => item.FolderId == folderId).Include(item => item.Folder);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
files = _db.File.AsNoTracking().Where(item => item.FolderId == folderId).Include(item => item.Folder);
|
||||||
|
}
|
||||||
foreach (File file in files)
|
foreach (File file in files)
|
||||||
{
|
{
|
||||||
file.Folder.Permissions = permissions.EncodePermissions();
|
file.Folder.Permissions = permissions.EncodePermissions();
|
||||||
|
@ -41,6 +53,7 @@ namespace Oqtane.Repository
|
||||||
|
|
||||||
public File AddFile(File file)
|
public File AddFile(File file)
|
||||||
{
|
{
|
||||||
|
file.IsDeleted = false;
|
||||||
_db.File.Add(file);
|
_db.File.Add(file);
|
||||||
_db.SaveChanges();
|
_db.SaveChanges();
|
||||||
file.Folder = _folderRepository.GetFolder(file.FolderId);
|
file.Folder = _folderRepository.GetFolder(file.FolderId);
|
||||||
|
@ -134,7 +147,7 @@ namespace Oqtane.Repository
|
||||||
public string GetFilePath(File file)
|
public string GetFilePath(File file)
|
||||||
{
|
{
|
||||||
if (file == null) return null;
|
if (file == null) return null;
|
||||||
var folder = file.Folder ?? _db.Folder.Find(file.FolderId);
|
var folder = file.Folder ?? _db.Folder.AsNoTracking().FirstOrDefault(item => item.FolderId == file.FolderId);
|
||||||
var filepath = Path.Combine(_folderRepository.GetFolderPath(folder), file.Name);
|
var filepath = Path.Combine(_folderRepository.GetFolderPath(folder), file.Name);
|
||||||
return filepath;
|
return filepath;
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,7 @@ namespace Oqtane.Repository
|
||||||
|
|
||||||
public Folder AddFolder(Folder folder)
|
public Folder AddFolder(Folder folder)
|
||||||
{
|
{
|
||||||
|
folder.IsDeleted = false;
|
||||||
_db.Folder.Add(folder);
|
_db.Folder.Add(folder);
|
||||||
_db.SaveChanges();
|
_db.SaveChanges();
|
||||||
_permissions.UpdatePermissions(folder.SiteId, EntityNames.Folder, folder.FolderId, folder.Permissions);
|
_permissions.UpdatePermissions(folder.SiteId, EntityNames.Folder, folder.FolderId, folder.Permissions);
|
||||||
|
|
|
@ -6,6 +6,7 @@ namespace Oqtane.Repository
|
||||||
public interface IFileRepository
|
public interface IFileRepository
|
||||||
{
|
{
|
||||||
IEnumerable<File> GetFiles(int folderId);
|
IEnumerable<File> GetFiles(int folderId);
|
||||||
|
IEnumerable<File> GetFiles(int folderId, bool tracking);
|
||||||
File AddFile(File file);
|
File AddFile(File file);
|
||||||
File UpdateFile(File file);
|
File UpdateFile(File file);
|
||||||
File GetFile(int fileId);
|
File GetFile(int fileId);
|
||||||
|
|
|
@ -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 (pageModule.Module.ModuleDefinition != null && !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,53 @@ 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;
|
||||||
|
current.Role = null; // remove linked reference to Role which can cause errors in EF Core change tracking
|
||||||
|
_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)
|
||||||
|
@ -195,13 +225,27 @@ namespace Oqtane.Repository
|
||||||
string securityid = "";
|
string securityid = "";
|
||||||
foreach (PermissionString permissionstring in JsonSerializer.Deserialize<List<PermissionString>>(permissionStrings))
|
foreach (PermissionString permissionstring in JsonSerializer.Deserialize<List<PermissionString>>(permissionStrings))
|
||||||
{
|
{
|
||||||
foreach (string id in permissionstring.Permissions.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
|
foreach (string id in permissionstring.Permissions.Split(';', StringSplitOptions.RemoveEmptyEntries))
|
||||||
{
|
{
|
||||||
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 = ""
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.Extensions.Configuration;
|
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using Oqtane.Shared;
|
using Oqtane.Shared;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
@ -17,31 +16,33 @@ namespace Oqtane.Security
|
||||||
|
|
||||||
public override async Task<AuthorizationPolicy> GetPolicyAsync(string policyName)
|
public override async Task<AuthorizationPolicy> GetPolicyAsync(string policyName)
|
||||||
{
|
{
|
||||||
// check static policies first
|
// get policy
|
||||||
policyName = GetPolicyName(policyName);
|
policyName = GetPolicyName(policyName);
|
||||||
var policy = await base.GetPolicyAsync(policyName);
|
var policy = await base.GetPolicyAsync(policyName);
|
||||||
|
|
||||||
if (policy == null)
|
if (policy == null)
|
||||||
{
|
{
|
||||||
|
// policy names must be in the form of "EntityName:PermissionName:Roles"
|
||||||
if (policyName.Contains(':'))
|
if (policyName.Contains(':'))
|
||||||
{
|
{
|
||||||
// policy names must be in the form of "EntityName:PermissionName:Roles" ie. "Module:Edit:Administrators" (roles are comma delimited)
|
var segments = policyName.Split(':');
|
||||||
var policySegments = policyName.Split(':');
|
if (segments.Length == 3)
|
||||||
if (policySegments.Length >= 3)
|
|
||||||
{
|
{
|
||||||
// check for optional RequireEntityId segment
|
// create policy
|
||||||
var requireEntityId = false;
|
var builder = new AuthorizationPolicyBuilder();
|
||||||
if (policySegments.Length == 4 && policySegments[3] == Constants.RequireEntityId)
|
builder.AddRequirements(new PermissionRequirement(segments[0], segments[1], segments[2]));
|
||||||
{
|
policy = builder.Build();
|
||||||
requireEntityId = true;
|
|
||||||
}
|
|
||||||
policy = new AuthorizationPolicyBuilder()
|
|
||||||
.AddRequirements(new PermissionRequirement(policySegments[0], policySegments[1], policySegments[2], requireEntityId))
|
|
||||||
.Build();
|
|
||||||
|
|
||||||
// add policy to the AuthorizationOptions
|
// add policy to the AuthorizationOptions
|
||||||
|
try
|
||||||
|
{
|
||||||
_options.AddPolicy(policyName, policy);
|
_options.AddPolicy(policyName, policy);
|
||||||
}
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// race condition - policy already added by another thread
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,8 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio Version 16
|
# Visual Studio Version 16
|
||||||
VisualStudioVersion = 16.0.28621.142
|
VisualStudioVersion = 16.0.28621.142
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Oqtane.Server", "..\oqtane.framework\Oqtane.Server\Oqtane.Server.csproj", "{3AB6FCC9-EFEB-4C0E-A2CF-8103914C5196}"
|
||||||
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "[Owner].[Module].Client", "Client\[Owner].[Module].Client.csproj", "{AA8E58A1-CD09-4208-BF66-A8BB341FD669}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "[Owner].[Module].Client", "Client\[Owner].[Module].Client.csproj", "{AA8E58A1-CD09-4208-BF66-A8BB341FD669}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "[Owner].[Module].Server", "Server\[Owner].[Module].Server.csproj", "{04B05448-788F-433D-92C0-FED35122D45A}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "[Owner].[Module].Server", "Server\[Owner].[Module].Server.csproj", "{04B05448-788F-433D-92C0-FED35122D45A}"
|
||||||
|
@ -17,6 +19,10 @@ Global
|
||||||
Release|Any CPU = Release|Any CPU
|
Release|Any CPU = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{3AB6FCC9-EFEB-4C0E-A2CF-8103914C5196}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{3AB6FCC9-EFEB-4C0E-A2CF-8103914C5196}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{3AB6FCC9-EFEB-4C0E-A2CF-8103914C5196}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{3AB6FCC9-EFEB-4C0E-A2CF-8103914C5196}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{AA8E58A1-CD09-4208-BF66-A8BB341FD669}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{AA8E58A1-CD09-4208-BF66-A8BB341FD669}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{AA8E58A1-CD09-4208-BF66-A8BB341FD669}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{AA8E58A1-CD09-4208-BF66-A8BB341FD669}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{AA8E58A1-CD09-4208-BF66-A8BB341FD669}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{AA8E58A1-CD09-4208-BF66-A8BB341FD669}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
|
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user