Merge branch 'dev' into IdentifyServices
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Configurations>Debug;Release</Configurations>
|
||||
<Version>10.0.4</Version>
|
||||
<Version>10.1.0</Version>
|
||||
<Product>Oqtane</Product>
|
||||
<Authors>Shaun Walker</Authors>
|
||||
<Company>.NET Foundation</Company>
|
||||
@@ -10,7 +10,7 @@
|
||||
<Copyright>.NET Foundation</Copyright>
|
||||
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
||||
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v10.0.4</PackageReleaseNotes>
|
||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v10.1.0</PackageReleaseNotes>
|
||||
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
||||
<RepositoryType>Git</RepositoryType>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -12,10 +12,10 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="10.0.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="10.0.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="10.0.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http" Version="10.0.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="10.0.3" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="10.0.3" />
|
||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="10.0.3" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http" Version="10.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -23,7 +23,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Oqtane.Client" Version="10.0.4" />
|
||||
<PackageReference Include="Oqtane.Client" Version="10.1.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>Oqtane.Application.Template</id>
|
||||
<version>10.0.4</version>
|
||||
<version>10.1.0</version>
|
||||
<title>Oqtane Application Template For Blazor</title>
|
||||
<authors>Shaun Walker</authors>
|
||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||
|
||||
@@ -22,9 +22,9 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="10.0.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="10.0.2" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="10.0.3" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="10.0.3" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -33,7 +33,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Oqtane.Server" Version="10.0.4" />
|
||||
<PackageReference Include="Oqtane.Server" Version="10.1.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Oqtane.Shared" Version="10.0.4" />
|
||||
<PackageReference Include="Oqtane.Shared" Version="10.1.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -57,8 +57,8 @@ namespace Microsoft.Extensions.DependencyInjection
|
||||
services.AddScoped<ICookieConsentService, CookieConsentService>();
|
||||
services.AddScoped<ITimeZoneService, TimeZoneService>();
|
||||
services.AddScoped<IMigrationHistoryService, MigrationHistoryService>();
|
||||
services.AddScoped<ISiteGroupDefinitionService, SiteGroupDefinitionService>();
|
||||
services.AddScoped<ISiteGroupService, SiteGroupService>();
|
||||
services.AddScoped<ISiteGroupMemberService, SiteGroupMemberService>();
|
||||
services.AddScoped<IOutputCacheService, OutputCacheService>();
|
||||
|
||||
// providers
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
@inject IJobService JobService
|
||||
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
||||
@inject IOutputCacheService CacheService
|
||||
@inject ISiteGroupDefinitionService SiteGroupDefinitionService
|
||||
@inject ISiteGroupService SiteGroupService
|
||||
@inject ISiteGroupMemberService SiteGroupMemberService
|
||||
|
||||
@if (_initialized)
|
||||
{
|
||||
@@ -448,22 +448,22 @@
|
||||
</div>
|
||||
</div>
|
||||
</Section>
|
||||
<Section Name="SiteGroups" Heading="Site Groups" ResourceKey="SiteGroups">
|
||||
<Section Name="SiteGroupMembers" Heading="Site Groups" ResourceKey="SiteGroupMembers">
|
||||
<div class="container">
|
||||
@if (!_addSiteGroupDefinition)
|
||||
@if (!_addSiteGroup)
|
||||
{
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="group" HelpText="The site groups in this tenant (database)" ResourceKey="SiteGroups">Group: </Label>
|
||||
<Label Class="col-sm-3" For="group" HelpText="The site groups in this tenant (database)" ResourceKey="SiteGroupMembers">Group: </Label>
|
||||
<div class="col-sm-9">
|
||||
<div class="input-group">
|
||||
<select id="group" class="form-select" value="@_siteGroupDefinitionId" @onchange="(e => SiteGroupChanged(e))">
|
||||
<select id="group" class="form-select" value="@_siteGroupId" @onchange="(e => SiteGroupChanged(e))">
|
||||
<option value="-1"><@SharedLocalizer["Not Specified"]></option>
|
||||
@foreach (var siteGroupDefinition in _siteGroupDefinitions)
|
||||
@foreach (var siteGroup in _siteGroups)
|
||||
{
|
||||
<option value="@siteGroupDefinition.SiteGroupDefinitionId">@siteGroupDefinition.Name</option>
|
||||
<option value="@siteGroup.SiteGroupId">@siteGroup.Name</option>
|
||||
}
|
||||
</select>
|
||||
@if (!_addSiteGroupDefinition)
|
||||
@if (!_addSiteGroup)
|
||||
{
|
||||
<button type="button" class="btn btn-primary" @onclick="AddSiteGroup">@SharedLocalizer["Add"]</button>
|
||||
}
|
||||
@@ -471,109 +471,91 @@
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@if (_siteGroupDefinitionId != -1 || _addSiteGroupDefinition)
|
||||
@if (_siteGroupId != -1 || _addSiteGroup)
|
||||
{
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="groupname" HelpText="Name of the site group" ResourceKey="GroupName">Group Name: </Label>
|
||||
<Label Class="col-sm-3" For="groupname" HelpText="Name of the site group" ResourceKey="GroupName">Name: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="groupname" class="form-control" @bind="@_groupName" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="synchronization" HelpText="Specifies if the group supports content synchronization between the primary site and other sites in the group" ResourceKey="Synchronization">Synchronization? </Label>
|
||||
<Label Class="col-sm-3" For="grouptype" HelpText="The site group type (ie. synchronization, comparison, localization)" ResourceKey="GroupType">Type: </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="synchronization" class="form-select" @bind="@_synchronization">
|
||||
<option value="False">@SharedLocalizer["No"]</option>
|
||||
<option value="True">@Localizer["Yes"]</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="localization" HelpText="Specifies if the content of the sites in the group are localized" ResourceKey="Localization">Localization? </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="localization" class="form-select" @bind="@_localization">
|
||||
<option value="True">@SharedLocalizer["Yes"]</option>
|
||||
<option value="False">@SharedLocalizer["No"]</option>
|
||||
<select id="grouptype" class="form-select" @bind="@_groupType">
|
||||
<option value="@SiteGroupTypes.Synchronization">@Localizer[@SiteGroupTypes.Synchronization]</option>
|
||||
<option value="@SiteGroupTypes.Comparison">@Localizer[@SiteGroupTypes.Comparison]</option>
|
||||
<option value="@SiteGroupTypes.Localization">@Localizer[SiteGroupTypes.Localization]</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@if (_siteGroupDefinitionId != -1)
|
||||
@if (_siteGroupId != -1)
|
||||
{
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="site" HelpText="The sites in this tenant (database)" ResourceKey="Site">Site: </Label>
|
||||
<Label Class="col-sm-3" For="site" HelpText="The sites which are members of this site group" ResourceKey="Site">Members: </Label>
|
||||
<div class="col-sm-9">
|
||||
<div class="input-group">
|
||||
<select id="site" class="form-select" value="@_siteId" @onchange="(e => SiteChanged(e))">
|
||||
<option value="-1"><@SharedLocalizer["Not Specified"]></option>
|
||||
@foreach (var site in _sites)
|
||||
{
|
||||
<option value="@site.SiteId">@site.Name @((!string.IsNullOrEmpty(site.Fingerprint)) ? "(" + Localizer[site.Fingerprint] + ")" : "")</option>
|
||||
<option value="@site.SiteId">@site.Name</option>
|
||||
}
|
||||
</select>
|
||||
@if (!_addSiteGroupMember)
|
||||
{
|
||||
<button type="button" class="btn btn-primary" @onclick="AddSiteGroupMember">@SharedLocalizer["Add"]</button>
|
||||
}
|
||||
else
|
||||
{
|
||||
<button type="button" class="btn btn-primary" @onclick="AddSiteGroupMember">@SharedLocalizer["Select"]</button>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@if (_siteGroupDefinitionId != -1)
|
||||
@if (_siteGroupId != -1 && _siteId != -1)
|
||||
{
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="member" HelpText="Indicates if the current site is a member of the selected group" ResourceKey="GroupMember">Member? </Label>
|
||||
<Label Class="col-sm-3" For="primary" HelpText="Indicates if the selected member is the primary site of the site group" ResourceKey="Primary">Primary? </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="member" class="form-select" @bind="@_member">
|
||||
<select id="primary" class="form-select" @bind="@_primary">
|
||||
<option value="False">@SharedLocalizer["No"]</option>
|
||||
<option value="Primary">@Localizer["Primary"]</option>
|
||||
<option value="Secondary">@Localizer["Secondary"]</option>
|
||||
<option value="True">@SharedLocalizer["Yes"]</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
@if (_member == "Secondary" && _synchronization == "True")
|
||||
@if (_primary == "False" && (_groupType == SiteGroupTypes.Synchronization || _groupType == SiteGroupTypes.Comparison))
|
||||
{
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="synchronize" HelpText="Specifies the synchronization approach between the primary site and the selected site" ResourceKey="Synchronize">Synchronize? </Label>
|
||||
<Label Class="col-sm-3" For="synchronized" HelpText="The date/time when the site was last synchronized" ResourceKey="Synchronized">Synchronized: </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="synchronize" class="form-select" @bind="@_synchronize">
|
||||
<option value="False">@Localizer["Compare"]</option>
|
||||
@if (_localization == "False")
|
||||
{
|
||||
<option value="True">@Localizer["Update"]</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="notify" HelpText="Specifies if site administrators should be notified of any synchronization activity" ResourceKey="Notify">Notify? </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="notify" class="form-select" @bind="@_notify">
|
||||
<option value="False">@SharedLocalizer["No"]</option>
|
||||
<option value="True">@SharedLocalizer["Yes"]</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
@if (!string.IsNullOrEmpty(_synchronized))
|
||||
{
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="synchronized" HelpText="The date/time of the last synchronization for the site" ResourceKey="Synchronized">Synchronized: </Label>
|
||||
<div class="col-sm-9">
|
||||
<div class="input-group">
|
||||
<input id="synchronized" class="form-control" @bind="@_synchronized" disabled />
|
||||
</div>
|
||||
@if (!string.IsNullOrEmpty(_synchronized))
|
||||
{
|
||||
<button type="button" class="btn btn-primary" @onclick="ResetSiteGroupMember">@SharedLocalizer["Reset"]</button>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
<div class="row mb-1 align-items-center">
|
||||
<div class="col-sm-3"></div>
|
||||
<div class="col-sm-9">
|
||||
@if ((_siteGroupDefinitionId != -1 || _addSiteGroupDefinition))
|
||||
@if ((_siteGroupId != -1 || _addSiteGroup))
|
||||
{
|
||||
<button type="button" class="btn btn-success me-2" @onclick="SaveSiteGroup">@SharedLocalizer["Save"]</button>
|
||||
<button type="button" class="btn btn-success me-2" @onclick="SaveSiteGroupMember">@SharedLocalizer["Save"]</button>
|
||||
}
|
||||
@if ((_siteGroupDefinitionId != -1 && !_addSiteGroupDefinition) && _member != "False")
|
||||
@if (_siteGroupId != -1 && !_addSiteGroup && _siteId != -1 && !_addSiteGroupMember)
|
||||
{
|
||||
<ActionDialog Action="Delete" OnClick="@(async () => await DeleteSiteGroup())" ResourceKey="DeleteSiteGroup" Class="btn btn-danger" Header="Delete Site Group" Message="@string.Format(Localizer["Confirm.SiteGroup.Delete", _groupName])" />
|
||||
<ActionDialog Action="Delete" OnClick="@(async () => await DeleteSiteGroupMember())" ResourceKey="DeleteSiteGroupMember" Class="btn btn-danger" Header="Delete Site Group" Message="@Localizer["Confirm.SiteGroupMember.Delete"]" />
|
||||
}
|
||||
@if (_addSiteGroupDefinition)
|
||||
@if (_addSiteGroup)
|
||||
{
|
||||
<button type="button" class="btn btn-secondary" @onclick="CancelSiteGroup">@SharedLocalizer["Cancel"]</button>
|
||||
<button type="button" class="btn btn-secondary" @onclick="CancelSiteGroupMember">@SharedLocalizer["Cancel"]</button>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
@@ -605,10 +587,6 @@
|
||||
<br />
|
||||
<button type="button" class="btn btn-success" @onclick="SaveSite">@SharedLocalizer["Save"]</button>
|
||||
<ActionDialog Header="Delete Site" Message="@Localizer["Confirm.DeleteSite"]" Action="Delete" Security="SecurityAccessLevel.Host" Class="btn btn-danger" OnClick="@(async () => await DeleteSite())" ResourceKey="DeleteSite" />
|
||||
@if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host) && _siteGroupDefinitions.Any(item => item.PrimarySiteId == PageState.Site.SiteId && item.Synchronization))
|
||||
{
|
||||
<button type="button" class="btn btn-primary ms-1" @onclick="SynchronizeSite">@Localizer["Synchronize"]</button>
|
||||
}
|
||||
<br />
|
||||
<br />
|
||||
<AuditInfo CreatedBy="@_createdby" CreatedOn="@_createdon" ModifiedBy="@_modifiedby" ModifiedOn="@_modifiedon" DeletedBy="@_deletedby" DeletedOn="@_deletedon"></AuditInfo>
|
||||
@@ -685,18 +663,16 @@
|
||||
private string _defaultalias;
|
||||
private bool _addAlias = false;
|
||||
|
||||
private List<SiteGroupDefinition> _siteGroupDefinitions = new List<SiteGroupDefinition>();
|
||||
private List<SiteGroup> _siteGroups = new List<SiteGroup>();
|
||||
private List<Site> _sites = new List<Site>();
|
||||
private int _siteGroupDefinitionId = -1;
|
||||
private int _siteGroupId = -1;
|
||||
private int _siteId;
|
||||
private string _groupName = string.Empty;
|
||||
private string _synchronization = "True";
|
||||
private string _localization = "False";
|
||||
private string _member = "Primary";
|
||||
private string _synchronize = "True";
|
||||
private string _notify = "True";
|
||||
private string _groupType = SiteGroupTypes.Synchronization;
|
||||
private string _primary = "True";
|
||||
private string _synchronized = string.Empty;
|
||||
private bool _addSiteGroupDefinition = false;
|
||||
private bool _addSiteGroup = false;
|
||||
private bool _addSiteGroupMember = false;
|
||||
|
||||
private string _tenant = string.Empty;
|
||||
private string _database = string.Empty;
|
||||
@@ -1262,82 +1238,76 @@
|
||||
|
||||
private async Task LoadSiteGroups()
|
||||
{
|
||||
_siteGroupDefinitions = await SiteGroupDefinitionService.GetSiteGroupDefinitionsAsync();
|
||||
_siteGroupDefinitionId = -1;
|
||||
_addSiteGroupDefinition = false;
|
||||
_siteGroups = await SiteGroupService.GetSiteGroupsAsync();
|
||||
_siteGroupId = -1;
|
||||
_addSiteGroup = false;
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private async void SiteGroupChanged(ChangeEventArgs e)
|
||||
private async Task SiteGroupChanged(ChangeEventArgs e)
|
||||
{
|
||||
_siteGroupDefinitionId = int.Parse(e.Value.ToString());
|
||||
if (_siteGroupDefinitionId != -1)
|
||||
_siteGroupId = int.Parse(e.Value.ToString());
|
||||
if (_siteGroupId != -1)
|
||||
{
|
||||
var group = _siteGroupDefinitions.FirstOrDefault(item => item.SiteGroupDefinitionId == _siteGroupDefinitionId);
|
||||
var group = _siteGroups.FirstOrDefault(item => item.SiteGroupId == _siteGroupId);
|
||||
if (group != null)
|
||||
{
|
||||
_groupName = group.Name;
|
||||
_synchronization = group.Synchronization.ToString();
|
||||
_localization = group.Localization.ToString();
|
||||
_groupType = group.Type;
|
||||
_siteId = -1;
|
||||
_primary = "False";
|
||||
_addSiteGroupMember = false;
|
||||
|
||||
if (_sites.Count == 0)
|
||||
{
|
||||
_sites = await SiteService.GetSitesAsync();
|
||||
}
|
||||
_siteId = PageState.Site.SiteId;
|
||||
_member = "False";
|
||||
|
||||
var siteGroups = await SiteGroupService.GetSiteGroupsAsync(-1, _siteGroupDefinitionId);
|
||||
foreach (var site in _sites)
|
||||
{
|
||||
site.Fingerprint = ""; // used as temporary state
|
||||
var siteGroup = siteGroups.FirstOrDefault(item => item.SiteId == site.SiteId);
|
||||
if (siteGroup != null)
|
||||
{
|
||||
if (group.PrimarySiteId == site.SiteId)
|
||||
{
|
||||
site.Fingerprint = "Primary";
|
||||
}
|
||||
else
|
||||
{
|
||||
site.Fingerprint = "Secondary";
|
||||
}
|
||||
|
||||
if (siteGroup.SiteId == _siteId)
|
||||
{
|
||||
_member = site.Fingerprint;
|
||||
_synchronize = siteGroup.Synchronize.ToString();
|
||||
_notify = siteGroup.Notify.ToString();
|
||||
_synchronized = UtcToLocal(siteGroup.SynchronizedOn).ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
await LoadSites();
|
||||
}
|
||||
}
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private async void SiteChanged(ChangeEventArgs e)
|
||||
private async Task LoadSites()
|
||||
{
|
||||
_siteId = int.Parse(e.Value.ToString());
|
||||
var siteGroup = await SiteGroupService.GetSiteGroupAsync(_siteId, _siteGroupDefinitionId);
|
||||
if (siteGroup != null)
|
||||
var siteGroupMembers = await SiteGroupMemberService.GetSiteGroupMembersAsync(-1, _siteGroupId);
|
||||
|
||||
_sites = await SiteService.GetSitesAsync();
|
||||
if (_addSiteGroupMember)
|
||||
{
|
||||
if (siteGroup.SiteGroupDefinition.PrimarySiteId == _siteId)
|
||||
{
|
||||
_member = "Primary";
|
||||
}
|
||||
else
|
||||
{
|
||||
_member = "Secondary";
|
||||
}
|
||||
_synchronize = siteGroup.Synchronize.ToString();
|
||||
_notify = siteGroup.Notify.ToString();
|
||||
_synchronized = UtcToLocal(siteGroup.SynchronizedOn).ToString();
|
||||
// include sites which are not members
|
||||
_sites = _sites.ExceptBy(siteGroupMembers.Select(item => item.SiteId), item => item.SiteId).ToList();
|
||||
}
|
||||
else
|
||||
{
|
||||
_member = "False";
|
||||
// include sites which are members
|
||||
_sites = _sites.Where(item => siteGroupMembers.Any(item2 => item2.SiteId == item.SiteId)).ToList();
|
||||
var group = _siteGroups.FirstOrDefault(item => item.SiteGroupId == _siteGroupId);
|
||||
foreach (var site in _sites)
|
||||
{
|
||||
if (group.PrimarySiteId == site.SiteId)
|
||||
{
|
||||
site.Name += $" ({Localizer["Primary"]})";
|
||||
}
|
||||
else
|
||||
{
|
||||
site.Name += $" ({Localizer["Secondary"]})";
|
||||
}
|
||||
}
|
||||
|
||||
var siteGroupMember = siteGroupMembers.FirstOrDefault(item => item.SiteId == _siteId);
|
||||
if (siteGroupMember != null)
|
||||
{
|
||||
_primary = (siteGroupMember.SiteGroup.PrimarySiteId == _siteId) ? "True" : "False";
|
||||
_synchronized = UtcToLocal(siteGroupMember.SynchronizedOn).ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SiteChanged(ChangeEventArgs e)
|
||||
{
|
||||
_siteId = int.Parse(e.Value.ToString());
|
||||
var siteGroupMember = await SiteGroupMemberService.GetSiteGroupMemberAsync(_siteId, _siteGroupId);
|
||||
if (siteGroupMember != null)
|
||||
{
|
||||
_primary = (siteGroupMember.SiteGroup.PrimarySiteId == _siteId) ? "True" : "False";
|
||||
_synchronized = UtcToLocal(siteGroupMember.SynchronizedOn).ToString();
|
||||
}
|
||||
StateHasChanged();
|
||||
}
|
||||
@@ -1346,129 +1316,121 @@
|
||||
{
|
||||
_groupName = "";
|
||||
_siteId = PageState.Site.SiteId;
|
||||
_member = "Primary";
|
||||
_primary = "True";
|
||||
_synchronized = "";
|
||||
_addSiteGroupDefinition = true;
|
||||
_addSiteGroup = true;
|
||||
}
|
||||
|
||||
private async Task SaveSiteGroup()
|
||||
private async Task AddSiteGroupMember()
|
||||
{
|
||||
SiteGroupDefinition siteGroupDefinition = null;
|
||||
_addSiteGroupMember = !_addSiteGroupMember;
|
||||
_siteId = -1;
|
||||
await LoadSites();
|
||||
}
|
||||
|
||||
if (_siteGroupDefinitionId == -1)
|
||||
private async Task SaveSiteGroupMember()
|
||||
{
|
||||
if (string.IsNullOrEmpty(_groupName))
|
||||
{
|
||||
if (!string.IsNullOrEmpty(_groupName))
|
||||
AddModuleMessage(Localizer["Message.Required.GroupName"], MessageType.Warning);
|
||||
await ScrollToPageTop();
|
||||
return;
|
||||
}
|
||||
|
||||
SiteGroup siteGroup = null;
|
||||
|
||||
if (_siteGroupId == -1)
|
||||
{
|
||||
siteGroup = new SiteGroup
|
||||
{
|
||||
siteGroupDefinition = new Models.SiteGroupDefinition
|
||||
{
|
||||
Name = _groupName,
|
||||
PrimarySiteId = _siteId,
|
||||
Synchronization = bool.Parse(_synchronization),
|
||||
Localization = bool.Parse(_localization),
|
||||
Synchronize = false
|
||||
};
|
||||
siteGroupDefinition = await SiteGroupDefinitionService.AddSiteGroupDefinitionAsync(siteGroupDefinition);
|
||||
}
|
||||
Name = _groupName,
|
||||
Type = _groupType,
|
||||
PrimarySiteId = _siteId,
|
||||
Synchronize = false
|
||||
};
|
||||
siteGroup = await SiteGroupService.AddSiteGroupAsync(siteGroup);
|
||||
}
|
||||
else
|
||||
{
|
||||
siteGroupDefinition = _siteGroupDefinitions.FirstOrDefault(item => item.SiteGroupDefinitionId == _siteGroupDefinitionId);
|
||||
if (siteGroupDefinition != null && !string.IsNullOrEmpty(_groupName))
|
||||
siteGroup = _siteGroups.FirstOrDefault(item => item.SiteGroupId == _siteGroupId);
|
||||
if (siteGroup != null)
|
||||
{
|
||||
siteGroupDefinition.Name = _groupName;
|
||||
siteGroupDefinition.PrimarySiteId = (_member == "Primary") ? _siteId : siteGroupDefinition.PrimarySiteId;
|
||||
siteGroupDefinition.Synchronization = bool.Parse(_synchronization);
|
||||
siteGroupDefinition.Localization = bool.Parse(_localization);
|
||||
siteGroupDefinition = await SiteGroupDefinitionService.UpdateSiteGroupDefinitionAsync(siteGroupDefinition);
|
||||
siteGroup.Name = _groupName;
|
||||
siteGroup.Type = _groupType;
|
||||
siteGroup.PrimarySiteId = (_primary == "True") ? _siteId : siteGroup.PrimarySiteId;
|
||||
siteGroup = await SiteGroupService.UpdateSiteGroupAsync(siteGroup);
|
||||
}
|
||||
else
|
||||
{
|
||||
siteGroupDefinition = null;
|
||||
siteGroup = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (siteGroupDefinition != null)
|
||||
if (siteGroup != null)
|
||||
{
|
||||
var siteGroup = await SiteGroupService.GetSiteGroupAsync(_siteId, siteGroupDefinition.SiteGroupDefinitionId);
|
||||
if (siteGroup == null)
|
||||
if (_siteId != -1)
|
||||
{
|
||||
siteGroup = new SiteGroup
|
||||
var siteGroupMember = await SiteGroupMemberService.GetSiteGroupMemberAsync(_siteId, siteGroup.SiteGroupId);
|
||||
if (siteGroupMember == null)
|
||||
{
|
||||
SiteGroupDefinitionId = siteGroupDefinition.SiteGroupDefinitionId,
|
||||
SiteId = _siteId,
|
||||
Synchronize = bool.Parse(_synchronize),
|
||||
Notify = bool.Parse(_notify)
|
||||
};
|
||||
await SiteGroupService.AddSiteGroupAsync(siteGroup);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_member == "False")
|
||||
{
|
||||
await SiteGroupService.DeleteSiteGroupAsync(siteGroup.SiteGroupId);
|
||||
siteGroupMember = new SiteGroupMember
|
||||
{
|
||||
SiteGroupId = siteGroup.SiteGroupId,
|
||||
SiteId = _siteId
|
||||
};
|
||||
await SiteGroupMemberService.AddSiteGroupMemberAsync(siteGroupMember);
|
||||
}
|
||||
else
|
||||
{
|
||||
siteGroup.Synchronize = bool.Parse(_synchronize);
|
||||
siteGroup.Notify = bool.Parse(_notify);
|
||||
await SiteGroupService.UpdateSiteGroupAsync(siteGroup);
|
||||
siteGroupMember.SynchronizedOn = string.IsNullOrEmpty(_synchronized) ? null : siteGroupMember.SynchronizedOn;
|
||||
await SiteGroupMemberService.UpdateSiteGroupMemberAsync(siteGroupMember);
|
||||
}
|
||||
}
|
||||
|
||||
if (siteGroup.Type == SiteGroupTypes.Synchronization)
|
||||
{
|
||||
// enable synchronization job if it is not enabled already
|
||||
var jobs = await JobService.GetJobsAsync();
|
||||
var job = jobs.FirstOrDefault(item => item.JobType == "Oqtane.Infrastructure.SynchronizationJob, Oqtane.Server");
|
||||
if (job != null && !job.IsEnabled)
|
||||
{
|
||||
job.IsEnabled = true;
|
||||
await JobService.UpdateJobAsync(job);
|
||||
}
|
||||
}
|
||||
|
||||
await LoadSiteGroups();
|
||||
}
|
||||
else
|
||||
{
|
||||
AddModuleMessage(Localizer["Message.Required.GroupName"], MessageType.Warning);
|
||||
await ScrollToPageTop();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task CancelSiteGroup()
|
||||
private async Task CancelSiteGroupMember()
|
||||
{
|
||||
_groupName = "";
|
||||
await LoadSiteGroups();
|
||||
}
|
||||
|
||||
private async Task DeleteSiteGroup()
|
||||
private async Task DeleteSiteGroupMember()
|
||||
{
|
||||
if (_siteGroupDefinitionId != -1)
|
||||
if (_siteGroupId != -1)
|
||||
{
|
||||
var siteGroup = await SiteGroupService.GetSiteGroupAsync(PageState.Site.SiteId, _siteGroupDefinitionId);
|
||||
if (siteGroup != null)
|
||||
var siteGroupMember = await SiteGroupMemberService.GetSiteGroupMemberAsync(PageState.Site.SiteId, _siteGroupId);
|
||||
if (siteGroupMember != null)
|
||||
{
|
||||
await SiteGroupService.DeleteSiteGroupAsync(siteGroup.SiteGroupDefinitionId);
|
||||
await SiteGroupMemberService.DeleteSiteGroupMemberAsync(siteGroupMember.SiteGroupId);
|
||||
}
|
||||
|
||||
var siteGroups = await SiteGroupService.GetSiteGroupsAsync(-1, _siteGroupDefinitionId);
|
||||
if (!siteGroups.Any())
|
||||
var siteGroupMembers = await SiteGroupMemberService.GetSiteGroupMembersAsync(-1, _siteGroupId);
|
||||
if (!siteGroupMembers.Any())
|
||||
{
|
||||
await SiteGroupDefinitionService.DeleteSiteGroupDefinitionAsync(_siteGroupDefinitionId);
|
||||
await SiteGroupService.DeleteSiteGroupAsync(_siteGroupId);
|
||||
}
|
||||
|
||||
await LoadSiteGroups();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SynchronizeSite()
|
||||
private async Task ResetSiteGroupMember()
|
||||
{
|
||||
// enable synchronization job if it is not enabled already
|
||||
var jobs = await JobService.GetJobsAsync();
|
||||
var job = jobs.FirstOrDefault(item => item.JobType == "Oqtane.Infrastructure.SynchronizationJob, Oqtane.Server");
|
||||
if (job != null && !job.IsEnabled)
|
||||
{
|
||||
job.IsEnabled = true;
|
||||
await JobService.UpdateJobAsync(job);
|
||||
}
|
||||
|
||||
// mark secondary sites for synchronization
|
||||
foreach (var group in _siteGroupDefinitions.Where(item => item.PrimarySiteId == PageState.Site.SiteId && item.Synchronization))
|
||||
{
|
||||
group.Synchronize = true;
|
||||
await SiteGroupDefinitionService.UpdateSiteGroupDefinitionAsync(group);
|
||||
}
|
||||
|
||||
AddModuleMessage(Localizer["Message.Site.Synchronize"], MessageType.Success);
|
||||
await ScrollToPageTop();
|
||||
_synchronized = "";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,7 +224,7 @@
|
||||
{
|
||||
<button type="button" class="btn btn-primary ms-1" @onclick="ImpersonateUser">@Localizer["Impersonate"]</button>
|
||||
}
|
||||
@if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host) && _isdeleted == "True")
|
||||
@if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host) && _candelete)
|
||||
{
|
||||
<ActionDialog Header="Delete User" Message="Are You Sure You Wish To Permanently Delete This User?" Action="Delete" Security="SecurityAccessLevel.Host" Class="btn btn-danger ms-1" OnClick="@(async () => await DeleteUser())" ResourceKey="DeleteUser" />
|
||||
}
|
||||
@@ -251,6 +251,7 @@
|
||||
private string _lastlogin;
|
||||
private string _lastipaddress;
|
||||
private bool _ishost = false;
|
||||
private bool _candelete = false;
|
||||
|
||||
private string _passwordrequirements;
|
||||
private string _password = string.Empty;
|
||||
@@ -296,6 +297,7 @@
|
||||
_timezoneid = PageState.User.TimeZoneId;
|
||||
_culturecode = PageState.User.CultureCode;
|
||||
_isdeleted = user.IsDeleted.ToString();
|
||||
_candelete = user.IsDeleted;
|
||||
_lastlogin = string.Format("{0:MMM dd yyyy HH:mm:ss}", UtcToLocal(user.LastLoginOn));
|
||||
_lastipaddress = user.LastIPAddress;
|
||||
_ishost = UserSecurity.ContainsRole(user.Roles, RoleNames.Host);
|
||||
|
||||
@@ -8,11 +8,11 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="10.0.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="10.0.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="10.0.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http" Version="10.0.2" />
|
||||
<PackageReference Include="Radzen.Blazor" Version="8.6.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="10.0.3" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="10.0.3" />
|
||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="10.0.3" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http" Version="10.0.3" />
|
||||
<PackageReference Include="Radzen.Blazor" Version="9.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -498,17 +498,17 @@
|
||||
<data name="AliasName.HelpText" xml:space="preserve">
|
||||
<value>A url for this site. This can include domain names (ie. domain.com), subdomains (ie. sub.domain.com) or virtual folders (ie. domain.com/folder).</value>
|
||||
</data>
|
||||
<data name="SiteGroups.Text" xml:space="preserve">
|
||||
<data name="SiteGroupMembers.Text" xml:space="preserve">
|
||||
<value>Group:</value>
|
||||
</data>
|
||||
<data name="SiteGroups.HelpText" xml:space="preserve">
|
||||
<data name="SiteGroupMembers.HelpText" xml:space="preserve">
|
||||
<value>The site groups in this tenant (database)</value>
|
||||
</data>
|
||||
<data name="GroupMember.Text" xml:space="preserve">
|
||||
<value>Member?</value>
|
||||
<data name="Primary.Text" xml:space="preserve">
|
||||
<value>Primary?</value>
|
||||
</data>
|
||||
<data name="GroupMember.HelpText" xml:space="preserve">
|
||||
<value>Indicates if the current site is a member of the selected group</value>
|
||||
<data name="Primary.HelpText" xml:space="preserve">
|
||||
<value>Indicates if the selected member is the primary site of the site group</value>
|
||||
</data>
|
||||
<data name="GroupName.Text" xml:space="preserve">
|
||||
<value>Name:</value>
|
||||
@@ -516,18 +516,6 @@
|
||||
<data name="GroupName.HelpText" xml:space="preserve">
|
||||
<value>Name of the site group</value>
|
||||
</data>
|
||||
<data name="Synchronization.Text" xml:space="preserve">
|
||||
<value>Synchronization?</value>
|
||||
</data>
|
||||
<data name="Synchronization.HelpText" xml:space="preserve">
|
||||
<value>Specifies if the group supports content synchronization between the primary site and other sites in the group</value>
|
||||
</data>
|
||||
<data name="Localization.Text" xml:space="preserve">
|
||||
<value>Localization?</value>
|
||||
</data>
|
||||
<data name="Localization.HelpText" xml:space="preserve">
|
||||
<value>Specifies if the content of the sites in the group are localized</value>
|
||||
</data>
|
||||
<data name="Primary" xml:space="preserve">
|
||||
<value>Primary</value>
|
||||
</data>
|
||||
@@ -540,43 +528,43 @@
|
||||
<data name="Update" xml:space="preserve">
|
||||
<value>Update</value>
|
||||
</data>
|
||||
<data name="DeleteSiteGroup.Header" xml:space="preserve">
|
||||
<value>Delete Site Group</value>
|
||||
<data name="DeleteSiteGroupMember.Header" xml:space="preserve">
|
||||
<value>Delete Site Group Member</value>
|
||||
</data>
|
||||
<data name="Confirm.SiteGroup.Delete" xml:space="preserve">
|
||||
<value>Are You Sure You Wish To Delete {0}?</value>
|
||||
<data name="Confirm.SiteGroupMember.Delete" xml:space="preserve">
|
||||
<value>Are You Sure You Wish To Delete This Member From The Site Group?</value>
|
||||
</data>
|
||||
<data name="Message.Required.GroupName" xml:space="preserve">
|
||||
<value>Group Name Is Required</value>
|
||||
<value>Site Group Name Is Required</value>
|
||||
</data>
|
||||
<data name="Message.Site.Synchronize" xml:space="preserve">
|
||||
<value>Site Submitted For Synchronization</value>
|
||||
</data>
|
||||
<data name="Synchronize" xml:space="preserve">
|
||||
<value>Synchronize</value>
|
||||
</data>
|
||||
<data name="Notify.Text" xml:space="preserve">
|
||||
<value>Notify?</value>
|
||||
</data>
|
||||
<data name="Notify.HelpText" xml:space="preserve">
|
||||
<value>Specifies if site administrators should be notified of any synchronization activity</value>
|
||||
</data>
|
||||
<data name="Site.Text" xml:space="preserve">
|
||||
<value>Site:</value>
|
||||
<value>Members:</value>
|
||||
</data>
|
||||
<data name="Site.HelpText" xml:space="preserve">
|
||||
<value>The sites in this tenant (database)</value>
|
||||
<value>The sites which are members of this site group</value>
|
||||
</data>
|
||||
<data name="Synchronized.Text" xml:space="preserve">
|
||||
<value>Synchronized:</value>
|
||||
</data>
|
||||
<data name="GroupType.Text" xml:space="preserve">
|
||||
<value>Type:</value>
|
||||
</data>
|
||||
<data name="GroupType.HelpText" xml:space="preserve">
|
||||
<value>The site group type (ie. synchronization, comparison, localization)</value>
|
||||
</data>
|
||||
<data name="Synchronized.HelpText" xml:space="preserve">
|
||||
<value>The date/time of the last synchronization for the site</value>
|
||||
<value>The date/time when the site was last synchronized</value>
|
||||
</data>
|
||||
<data name="Synchronize.Text" xml:space="preserve">
|
||||
<value>Synchronize?</value>
|
||||
<data name="Synchronization" xml:space="preserve">
|
||||
<value>Synchronization</value>
|
||||
</data>
|
||||
<data name="Synchronize.HelpText" xml:space="preserve">
|
||||
<value>Specifies the synchronization approach between the primary site and the selected site</value>
|
||||
<data name="Localization" xml:space="preserve">
|
||||
<value>Localization</value>
|
||||
</data>
|
||||
<data name="Comparison" xml:space="preserve">
|
||||
<value>Comparison</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -174,9 +174,6 @@
|
||||
<data name="Title" xml:space="preserve">
|
||||
<value>Title:</value>
|
||||
</data>
|
||||
<data name="System.Update" xml:space="preserve">
|
||||
<value>Check For System Updates</value>
|
||||
</data>
|
||||
<data name="Visibility" xml:space="preserve">
|
||||
<value>Visibility:</value>
|
||||
</data>
|
||||
@@ -201,4 +198,7 @@
|
||||
<data name="Module.CopyExisting" xml:space="preserve">
|
||||
<value>Copy Existing Module</value>
|
||||
</data>
|
||||
<data name="Synchronize" xml:space="preserve">
|
||||
<value>Synchronize Site</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -1,83 +0,0 @@
|
||||
using Oqtane.Models;
|
||||
using System.Threading.Tasks;
|
||||
using System.Net.Http;
|
||||
using System.Collections.Generic;
|
||||
using Oqtane.Documentation;
|
||||
using Oqtane.Shared;
|
||||
using System.Linq;
|
||||
|
||||
namespace Oqtane.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Service to manage <see cref="Role"/>s on a <see cref="Site"/>
|
||||
/// </summary>
|
||||
public interface ISiteGroupDefinitionService
|
||||
{
|
||||
/// <summary>
|
||||
/// Get all <see cref="SiteGroupDefinition"/>s
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Task<List<SiteGroupDefinition>> GetSiteGroupDefinitionsAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Get one specific <see cref="SiteGroupDefinition"/>
|
||||
/// </summary>
|
||||
/// <param name="siteGroupDefinitionId">ID-reference of a <see cref="SiteGroupDefinition"/></param>
|
||||
/// <returns></returns>
|
||||
Task<SiteGroupDefinition> GetSiteGroupDefinitionAsync(int siteGroupDefinitionId);
|
||||
|
||||
/// <summary>
|
||||
/// Add / save a new <see cref="SiteGroupDefinition"/> to the database.
|
||||
/// </summary>
|
||||
/// <param name="group"></param>
|
||||
/// <returns></returns>
|
||||
Task<SiteGroupDefinition> AddSiteGroupDefinitionAsync(SiteGroupDefinition siteGroupDefinition);
|
||||
|
||||
/// <summary>
|
||||
/// Update a <see cref="SiteGroupDefinition"/> in the database.
|
||||
/// </summary>
|
||||
/// <param name="group"></param>
|
||||
/// <returns></returns>
|
||||
Task<SiteGroupDefinition> UpdateSiteGroupDefinitionAsync(SiteGroupDefinition siteGroupDefinition);
|
||||
|
||||
/// <summary>
|
||||
/// Delete a <see cref="SiteGroupDefinition"/> in the database.
|
||||
/// </summary>
|
||||
/// <param name="siteGroupDefinitionId">ID-reference of a <see cref="SiteGroupDefinition"/></param>
|
||||
/// <returns></returns>
|
||||
Task DeleteSiteGroupDefinitionAsync(int siteGroupDefinitionId);
|
||||
}
|
||||
|
||||
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||
public class SiteGroupDefinitionService : ServiceBase, ISiteGroupDefinitionService
|
||||
{
|
||||
public SiteGroupDefinitionService(HttpClient http, SiteState siteState) : base(http, siteState) { }
|
||||
|
||||
private string Apiurl => CreateApiUrl("SiteGroupDefinition");
|
||||
|
||||
public async Task<List<SiteGroupDefinition>> GetSiteGroupDefinitionsAsync()
|
||||
{
|
||||
return await GetJsonAsync<List<SiteGroupDefinition>>($"{Apiurl}", Enumerable.Empty<SiteGroupDefinition>().ToList());
|
||||
}
|
||||
|
||||
public async Task<SiteGroupDefinition> GetSiteGroupDefinitionAsync(int siteGroupDefinitionId)
|
||||
{
|
||||
return await GetJsonAsync<SiteGroupDefinition>($"{Apiurl}/{siteGroupDefinitionId}");
|
||||
}
|
||||
|
||||
public async Task<SiteGroupDefinition> AddSiteGroupDefinitionAsync(SiteGroupDefinition siteGroupDefinition)
|
||||
{
|
||||
return await PostJsonAsync<SiteGroupDefinition>(Apiurl, siteGroupDefinition);
|
||||
}
|
||||
|
||||
public async Task<SiteGroupDefinition> UpdateSiteGroupDefinitionAsync(SiteGroupDefinition siteGroupDefinition)
|
||||
{
|
||||
return await PutJsonAsync<SiteGroupDefinition>($"{Apiurl}/{siteGroupDefinition.SiteGroupDefinitionId}", siteGroupDefinition);
|
||||
}
|
||||
|
||||
public async Task DeleteSiteGroupDefinitionAsync(int siteGroupDefinitionId)
|
||||
{
|
||||
await DeleteAsync($"{Apiurl}/{siteGroupDefinitionId}");
|
||||
}
|
||||
}
|
||||
}
|
||||
104
Oqtane.Client/Services/SiteGroupMemberService.cs
Normal file
104
Oqtane.Client/Services/SiteGroupMemberService.cs
Normal file
@@ -0,0 +1,104 @@
|
||||
using Oqtane.Models;
|
||||
using System.Threading.Tasks;
|
||||
using System.Net.Http;
|
||||
using System.Collections.Generic;
|
||||
using Oqtane.Documentation;
|
||||
using Oqtane.Shared;
|
||||
using System.Linq;
|
||||
|
||||
namespace Oqtane.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Service to manage <see cref="Role"/>s on a <see cref="Site"/>
|
||||
/// </summary>
|
||||
public interface ISiteGroupMemberService
|
||||
{
|
||||
/// <summary>
|
||||
/// Get all <see cref="SiteGroupMember"/>s
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Task<List<SiteGroupMember>> GetSiteGroupMembersAsync(int siteId, int siteGroupId);
|
||||
|
||||
/// <summary>
|
||||
/// Get one specific <see cref="SiteGroupMember"/>
|
||||
/// </summary>
|
||||
/// <param name="siteGroupMemberId">ID-reference of a <see cref="SiteGroupMember"/></param>
|
||||
/// <returns></returns>
|
||||
Task<SiteGroupMember> GetSiteGroupMemberAsync(int siteGroupMemberId);
|
||||
|
||||
/// <summary>
|
||||
/// Get one specific <see cref="SiteGroupMember"/>
|
||||
/// </summary>
|
||||
/// <param name="siteId">ID-reference of a <see cref="Site"/></param>
|
||||
/// <param name="siteGroupId">ID-reference of a <see cref="SiteGroup"/></param>
|
||||
/// <returns></returns>
|
||||
Task<SiteGroupMember> GetSiteGroupMemberAsync(int siteId, int siteGroupId);
|
||||
|
||||
/// <summary>
|
||||
/// Add / save a new <see cref="SiteGroupMember"/> to the database.
|
||||
/// </summary>
|
||||
/// <param name="siteGroupMember"></param>
|
||||
/// <returns></returns>
|
||||
Task<SiteGroupMember> AddSiteGroupMemberAsync(SiteGroupMember siteGroupMember);
|
||||
|
||||
/// <summary>
|
||||
/// Update a <see cref="SiteGroupMember"/> in the database.
|
||||
/// </summary>
|
||||
/// <param name="siteGroupMember"></param>
|
||||
/// <returns></returns>
|
||||
Task<SiteGroupMember> UpdateSiteGroupMemberAsync(SiteGroupMember siteGroupMember);
|
||||
|
||||
/// <summary>
|
||||
/// Delete a <see cref="SiteGroupMember"/> in the database.
|
||||
/// </summary>
|
||||
/// <param name="siteGroupMemberId">ID-reference of a <see cref="SiteGroupMember"/></param>
|
||||
/// <returns></returns>
|
||||
Task DeleteSiteGroupMemberAsync(int siteGroupMemberId);
|
||||
}
|
||||
|
||||
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||
public class SiteGroupMemberService : ServiceBase, ISiteGroupMemberService
|
||||
{
|
||||
public SiteGroupMemberService(HttpClient http, SiteState siteState) : base(http, siteState) { }
|
||||
|
||||
private string Apiurl => CreateApiUrl("SiteGroupMember");
|
||||
|
||||
public async Task<List<SiteGroupMember>> GetSiteGroupMembersAsync(int siteId, int siteGroupId)
|
||||
{
|
||||
return await GetJsonAsync<List<SiteGroupMember>>($"{Apiurl}?siteid={siteId}&groupid={siteGroupId}", Enumerable.Empty<SiteGroupMember>().ToList());
|
||||
}
|
||||
|
||||
public async Task<SiteGroupMember> GetSiteGroupMemberAsync(int siteGroupMemberId)
|
||||
{
|
||||
return await GetJsonAsync<SiteGroupMember>($"{Apiurl}/{siteGroupMemberId}");
|
||||
}
|
||||
|
||||
public async Task<SiteGroupMember> GetSiteGroupMemberAsync(int siteId, int siteGroupId)
|
||||
{
|
||||
var siteGroupMembers = await GetSiteGroupMembersAsync(siteId, siteGroupId);
|
||||
if (siteGroupMembers != null && siteGroupMembers.Count > 0)
|
||||
{
|
||||
return siteGroupMembers[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<SiteGroupMember> AddSiteGroupMemberAsync(SiteGroupMember siteGroupMember)
|
||||
{
|
||||
return await PostJsonAsync<SiteGroupMember>(Apiurl, siteGroupMember);
|
||||
}
|
||||
|
||||
public async Task<SiteGroupMember> UpdateSiteGroupMemberAsync(SiteGroupMember siteGroupMember)
|
||||
{
|
||||
return await PutJsonAsync<SiteGroupMember>($"{Apiurl}/{siteGroupMember.SiteGroupId}", siteGroupMember);
|
||||
}
|
||||
|
||||
public async Task DeleteSiteGroupMemberAsync(int siteGroupMemberId)
|
||||
{
|
||||
await DeleteAsync($"{Apiurl}/{siteGroupMemberId}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,43 +17,41 @@ namespace Oqtane.Services
|
||||
/// Get all <see cref="SiteGroup"/>s
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Task<List<SiteGroup>> GetSiteGroupsAsync(int siteId, int siteGroupDefinitionId);
|
||||
Task<List<SiteGroup>> GetSiteGroupsAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Get all <see cref="SiteGroup"/>s
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Task<List<SiteGroup>> GetSiteGroupsAsync(int primarySiteId);
|
||||
|
||||
/// <summary>
|
||||
/// Get one specific <see cref="SiteGroup"/>
|
||||
/// </summary>
|
||||
/// <param name="siteSiteGroupDefinitionId">ID-reference of a <see cref="SiteGroup"/></param>
|
||||
/// <param name="siteGroupId">ID-reference of a <see cref="SiteGroup"/></param>
|
||||
/// <returns></returns>
|
||||
Task<SiteGroup> GetSiteGroupAsync(int siteSiteGroupDefinitionId);
|
||||
|
||||
/// <summary>
|
||||
/// Get one specific <see cref="SiteGroup"/>
|
||||
/// </summary>
|
||||
/// <param name="siteId">ID-reference of a <see cref="Site"/></param>
|
||||
/// <param name="siteGroupDefinitionId">ID-reference of a <see cref="SiteGroupDefinition"/></param>
|
||||
/// <returns></returns>
|
||||
Task<SiteGroup> GetSiteGroupAsync(int siteId, int siteGroupDefinitionId);
|
||||
Task<SiteGroup> GetSiteGroupAsync(int siteGroupId);
|
||||
|
||||
/// <summary>
|
||||
/// Add / save a new <see cref="SiteGroup"/> to the database.
|
||||
/// </summary>
|
||||
/// <param name="siteGroup"></param>
|
||||
/// <param name="group"></param>
|
||||
/// <returns></returns>
|
||||
Task<SiteGroup> AddSiteGroupAsync(SiteGroup siteGroup);
|
||||
|
||||
/// <summary>
|
||||
/// Update a <see cref="SiteGroup"/> in the database.
|
||||
/// </summary>
|
||||
/// <param name="siteGroup"></param>
|
||||
/// <param name="group"></param>
|
||||
/// <returns></returns>
|
||||
Task<SiteGroup> UpdateSiteGroupAsync(SiteGroup siteGroup);
|
||||
|
||||
/// <summary>
|
||||
/// Delete a <see cref="SiteGroup"/> in the database.
|
||||
/// </summary>
|
||||
/// <param name="siteSiteGroupDefinitionId">ID-reference of a <see cref="SiteGroup"/></param>
|
||||
/// <param name="siteGroupId">ID-reference of a <see cref="SiteGroup"/></param>
|
||||
/// <returns></returns>
|
||||
Task DeleteSiteGroupAsync(int siteSiteGroupDefinitionId);
|
||||
Task DeleteSiteGroupAsync(int siteGroupId);
|
||||
}
|
||||
|
||||
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||
@@ -63,27 +61,19 @@ namespace Oqtane.Services
|
||||
|
||||
private string Apiurl => CreateApiUrl("SiteGroup");
|
||||
|
||||
public async Task<List<SiteGroup>> GetSiteGroupsAsync(int siteId, int siteGroupDefinitionId)
|
||||
public async Task<List<SiteGroup>> GetSiteGroupsAsync()
|
||||
{
|
||||
return await GetJsonAsync<List<SiteGroup>>($"{Apiurl}?siteid={siteId}&groupid={siteGroupDefinitionId}", Enumerable.Empty<SiteGroup>().ToList());
|
||||
return await GetSiteGroupsAsync(-1);
|
||||
}
|
||||
|
||||
public async Task<SiteGroup> GetSiteGroupAsync(int siteSiteGroupDefinitionId)
|
||||
public async Task<List<SiteGroup>> GetSiteGroupsAsync(int primarySiteId)
|
||||
{
|
||||
return await GetJsonAsync<SiteGroup>($"{Apiurl}/{siteSiteGroupDefinitionId}");
|
||||
return await GetJsonAsync<List<SiteGroup>>($"{Apiurl}?siteid={primarySiteId}", Enumerable.Empty<SiteGroup>().ToList());
|
||||
}
|
||||
|
||||
public async Task<SiteGroup> GetSiteGroupAsync(int siteId, int siteGroupDefinitionId)
|
||||
public async Task<SiteGroup> GetSiteGroupAsync(int siteGroupId)
|
||||
{
|
||||
var siteGroups = await GetSiteGroupsAsync(siteId, siteGroupDefinitionId);
|
||||
if (siteGroups != null && siteGroups.Count > 0)
|
||||
{
|
||||
return siteGroups[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return await GetJsonAsync<SiteGroup>($"{Apiurl}/{siteGroupId}");
|
||||
}
|
||||
|
||||
public async Task<SiteGroup> AddSiteGroupAsync(SiteGroup siteGroup)
|
||||
@@ -93,12 +83,12 @@ namespace Oqtane.Services
|
||||
|
||||
public async Task<SiteGroup> UpdateSiteGroupAsync(SiteGroup siteGroup)
|
||||
{
|
||||
return await PutJsonAsync<SiteGroup>($"{Apiurl}/{siteGroup.SiteGroupDefinitionId}", siteGroup);
|
||||
return await PutJsonAsync<SiteGroup>($"{Apiurl}/{siteGroup.SiteGroupId}", siteGroup);
|
||||
}
|
||||
|
||||
public async Task DeleteSiteGroupAsync(int siteSiteGroupDefinitionId)
|
||||
public async Task DeleteSiteGroupAsync(int siteGroupId)
|
||||
{
|
||||
await DeleteAsync($"{Apiurl}/{siteSiteGroupDefinitionId}");
|
||||
await DeleteAsync($"{Apiurl}/{siteGroupId}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,11 @@
|
||||
@inject IPageService PageService
|
||||
@inject ISettingService SettingService
|
||||
|
||||
@if (ShowLanguageSwitcher)
|
||||
{
|
||||
<LanguageSwitcher ButtonClass="@ButtonClass" DropdownAlignment="@LanguageDropdownAlignment" />
|
||||
}
|
||||
|
||||
@if (ShowEditMode && (_showEditMode || (PageState.Page.IsPersonalizable && PageState.User != null && UserSecurity.IsAuthorized(PageState.User, RoleNames.Registered))))
|
||||
{
|
||||
<form method="post" class="app-form-inline" @formname="EditModeForm" @onsubmit="@(async () => await ToggleEditMode(PageState.EditMode))" data-enhance>
|
||||
@@ -48,11 +53,9 @@
|
||||
[Parameter]
|
||||
public string BodyClass { get; set; } = "offcanvas-body overflow-auto";
|
||||
|
||||
// deprecated in 10.1.0 - UI culture is set in user's profile
|
||||
[Parameter]
|
||||
public bool ShowLanguageSwitcher { get; set; } = true;
|
||||
|
||||
// deprecated in 10.1.0 - UI culture is set in user's profile
|
||||
[Parameter]
|
||||
public string LanguageDropdownAlignment { get; set; } = string.Empty; // Empty or Left or Right
|
||||
|
||||
@@ -94,6 +97,7 @@
|
||||
Alias = PageState.Alias,
|
||||
Site = new Site
|
||||
{
|
||||
SiteId = PageState.Site.SiteId,
|
||||
DefaultContainerType = PageState.Site.DefaultContainerType,
|
||||
Settings = PageState.Site.Settings,
|
||||
Themes = PageState.Site.Themes
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
@inject ILogService logger
|
||||
@inject ISettingService SettingService
|
||||
@inject IJSRuntime jsRuntime
|
||||
@inject ISiteGroupService SiteGroupService
|
||||
@inject IServiceProvider ServiceProvider
|
||||
@inject ILogService LoggingService
|
||||
@inject IStringLocalizer<ControlPanelInteractive> Localizer
|
||||
@@ -34,6 +35,11 @@
|
||||
<button type="button" data-bs-dismiss="offcanvas" class="btn btn-primary col-12" @onclick=@(async () => Navigate("Admin"))>@Localizer["AdminDash"]</button>
|
||||
</div>
|
||||
</div>
|
||||
@if (_siteGroups.Any(item => (item.Type == SiteGroupTypes.Synchronization || item.Type == SiteGroupTypes.Comparison) && item.PrimarySiteId == PageState.Site.SiteId))
|
||||
{
|
||||
<hr class="app-rule" />
|
||||
<button type="button" class="btn btn-secondary col-12 mt-1" @onclick="SynchronizeSite">@Localizer["Synchronize"]</button>
|
||||
}
|
||||
<hr class="app-rule" />
|
||||
}
|
||||
@if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.PermissionList))
|
||||
@@ -257,6 +263,7 @@
|
||||
private List<Page> _pages = new List<Page>();
|
||||
private List<Module> _modules = new List<Module>();
|
||||
private List<ThemeControl> _containers = new List<ThemeControl>();
|
||||
private List<SiteGroup> _siteGroups = new List<SiteGroup>();
|
||||
|
||||
private string _category = "Common";
|
||||
private string _pane = "";
|
||||
@@ -287,6 +294,7 @@
|
||||
_allModuleDefinitions = await ModuleDefinitionService.GetModuleDefinitionsAsync(PageState.Page.SiteId);
|
||||
_moduleDefinitions = _allModuleDefinitions.Where(item => item.Categories.Contains(_category)).ToList();
|
||||
_categories = _allModuleDefinitions.SelectMany(m => m.Categories.Split(',', StringSplitOptions.RemoveEmptyEntries)).Distinct().Where(item => item != "Headless").ToList();
|
||||
_siteGroups = await SiteGroupService.GetSiteGroupsAsync(PageState.Site.SiteId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -631,4 +639,14 @@
|
||||
{
|
||||
_message = "";
|
||||
}
|
||||
|
||||
private async Task SynchronizeSite()
|
||||
{
|
||||
foreach (var group in _siteGroups.Where(item => (item.Type == SiteGroupTypes.Synchronization || item.Type == SiteGroupTypes.Comparison) && item.PrimarySiteId == PageState.Site.SiteId))
|
||||
{
|
||||
group.Synchronize = true;
|
||||
await SiteGroupService.UpdateSiteGroupAsync(group);
|
||||
}
|
||||
NavigationManager.NavigateTo(Utilities.NavigateUrl(PageState.Alias.Path, PageState.Page.Path, ""), true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
@using System.Globalization
|
||||
@using Oqtane.Models
|
||||
@using System.Linq
|
||||
@namespace Oqtane.Themes.Controls
|
||||
@inherits ThemeControlBase
|
||||
@inject ILocalizationService LocalizationService
|
||||
@inject NavigationManager NavigationManager
|
||||
|
||||
@if (PageState.Site.Languages.Count() > 1)
|
||||
{
|
||||
<div class="app-languages btn-group pe-1" role="group">
|
||||
<button id="btnCultures" type="button" class="btn @ButtonClass dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
<span class="oi oi-globe"></span>
|
||||
</button>
|
||||
<div class="dropdown-menu @MenuAlignment">
|
||||
@foreach (var language in PageState.Site.Languages)
|
||||
{
|
||||
<a class="dropdown-item" href="@(PageState.Alias.Protocol + language.AliasName)">@language.Name</a>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@code{
|
||||
private string MenuAlignment = string.Empty;
|
||||
|
||||
[Parameter]
|
||||
public string DropdownAlignment { get; set; } = string.Empty; // Empty or Left or Right
|
||||
|
||||
[Parameter]
|
||||
public string ButtonClass { get; set; } = "btn-outline-secondary";
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
MenuAlignment = DropdownAlignment.ToLower() == "right" ? "dropdown-menu-end" : string.Empty;
|
||||
}
|
||||
}
|
||||
@@ -6,22 +6,29 @@
|
||||
@inject ILocalizationCookieService LocalizationCookieService
|
||||
@inject NavigationManager NavigationManager
|
||||
|
||||
@if (_supportedCultures?.Count() > 1)
|
||||
@if (PageState.Site.Languages.Count() > 1)
|
||||
{
|
||||
<div class="app-languages btn-group pe-1" role="group">
|
||||
<button id="btnCultures" type="button" class="btn @ButtonClass dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
<span class="oi oi-globe"></span>
|
||||
</button>
|
||||
<div class="dropdown-menu @MenuAlignment" aria-labelledby="btnCultures">
|
||||
@foreach (var culture in _supportedCultures)
|
||||
@foreach (var language in PageState.Site.Languages)
|
||||
{
|
||||
@if (PageState.RenderMode == RenderModes.Interactive)
|
||||
@if (_contentLocalization)
|
||||
{
|
||||
<a class="dropdown-item @(CultureInfo.CurrentUICulture.Name == culture.Name ? "active" : String.Empty)" href="#" @onclick="@(async e => await SetCultureAsync(culture.Name))" @onclick:preventDefault="true">@culture.DisplayName</a>
|
||||
<a class="dropdown-item @(PageState.Site.CultureCode == language.Code ? "active" : String.Empty)" href="@(PageState.Alias.Protocol + language.AliasName)" data-enhance-nav="false">@language.Name</a>
|
||||
}
|
||||
else
|
||||
{
|
||||
<a class="dropdown-item @(CultureInfo.CurrentUICulture.Name == culture.Name ? "active" : String.Empty)" href="@NavigateUrl(PageState.Page.Path, "culture=" + culture.Name)" data-enhance-nav="false">@culture.DisplayName</a>
|
||||
@if (PageState.RenderMode == RenderModes.Interactive)
|
||||
{
|
||||
<a class="dropdown-item @(CultureInfo.CurrentUICulture.Name == language.Code ? "active" : String.Empty)" href="#" @onclick="@(async e => await SetCultureAsync(language.Code))" @onclick:preventDefault="true">@language.Name</a>
|
||||
}
|
||||
else
|
||||
{
|
||||
<a class="dropdown-item @(CultureInfo.CurrentUICulture.Name == language.Code ? "active" : String.Empty)" href="@NavigateUrl(PageState.Page.Path, "culture=" + language.Code)" data-enhance-nav="false">@language.Name</a>
|
||||
}
|
||||
}
|
||||
}
|
||||
</div>
|
||||
@@ -29,7 +36,7 @@
|
||||
}
|
||||
|
||||
@code{
|
||||
private IEnumerable<Culture> _supportedCultures;
|
||||
private bool _contentLocalization;
|
||||
private string MenuAlignment = string.Empty;
|
||||
|
||||
[Parameter]
|
||||
@@ -41,12 +48,13 @@
|
||||
{
|
||||
MenuAlignment = DropdownAlignment.ToLower() == "right" ? "dropdown-menu-end" : string.Empty;
|
||||
|
||||
_supportedCultures = PageState.Languages.Select(l => new Culture { Name = l.Code, DisplayName = l.Name });
|
||||
// if AliasName is populated it means the site is using content localization
|
||||
_contentLocalization = PageState.Languages.Any(item => !string.IsNullOrEmpty(item.AliasName));
|
||||
|
||||
if (PageState.QueryString.ContainsKey("culture"))
|
||||
{
|
||||
var culture = PageState.QueryString["culture"];
|
||||
if (_supportedCultures.Any(item => item.Name == culture))
|
||||
if (PageState.Site.Languages.Any(item => item.Code == culture))
|
||||
{
|
||||
await LocalizationCookieService.SetLocalizationCookieAsync(culture);
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
<Search CssClass="me-3 text-center bg-primary" />
|
||||
<UserProfile ShowRegister="@_register" />
|
||||
<Login ShowLogin="@_login" />
|
||||
<LanguageSelector />
|
||||
<ControlPanel LanguageDropdownAlignment="right" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
<ApplicationId>com.oqtane.maui</ApplicationId>
|
||||
|
||||
<!-- Versions -->
|
||||
<ApplicationDisplayVersion>10.0.4</ApplicationDisplayVersion>
|
||||
<ApplicationDisplayVersion>10.1.0</ApplicationDisplayVersion>
|
||||
<ApplicationVersion>1</ApplicationVersion>
|
||||
|
||||
<!-- To develop, package, and publish an app to the Microsoft Store, see: https://aka.ms/MauiTemplateUnpackaged -->
|
||||
@@ -54,11 +54,11 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.Authorization" Version="10.0.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="10.0.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http" Version="10.0.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="10.0.2" />
|
||||
<PackageReference Include="System.Net.Http.Json" Version="10.0.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.Authorization" Version="10.0.3" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="10.0.3" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http" Version="10.0.3" />
|
||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="10.0.3" />
|
||||
<PackageReference Include="System.Net.Http.Json" Version="10.0.3" />
|
||||
<PackageReference Include="Microsoft.Maui.Controls" Version="$(MauiVersion)" />
|
||||
<PackageReference Include="Microsoft.Maui.Controls.Compatibility" Version="$(MauiVersion)" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebView.Maui" Version="$(MauiVersion)" />
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<package>
|
||||
<metadata>
|
||||
<id>Oqtane.Client</id>
|
||||
<version>10.0.4</version>
|
||||
<version>10.1.0</version>
|
||||
<authors>Shaun Walker</authors>
|
||||
<owners>.NET Foundation</owners>
|
||||
<title>Oqtane Framework</title>
|
||||
@@ -12,18 +12,18 @@
|
||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||
<license type="expression">MIT</license>
|
||||
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
||||
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v10.0.4</releaseNotes>
|
||||
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v10.1.0</releaseNotes>
|
||||
<readme>readme.md</readme>
|
||||
<icon>icon.png</icon>
|
||||
<tags>oqtane</tags>
|
||||
<dependencies>
|
||||
<group targetFramework="net10.0">
|
||||
<dependency id="Oqtane.Shared" version="10.0.4" exclude="Build,Analyzers" />
|
||||
<dependency id="Microsoft.AspNetCore.Components.WebAssembly" version="10.0.2" exclude="Build,Analyzers" />
|
||||
<dependency id="Microsoft.AspNetCore.Components.WebAssembly.Authentication" version="10.0.2" exclude="Build,Analyzers" />
|
||||
<dependency id="Microsoft.Extensions.Localization" version="10.0.2" exclude="Build,Analyzers" />
|
||||
<dependency id="Microsoft.Extensions.Http" version="10.0.2" exclude="Build,Analyzers" />
|
||||
<dependency id="Radzen.Blazor" version="8.6.0" exclude="Build,Analyzers" />
|
||||
<dependency id="Oqtane.Shared" version="10.1.0" exclude="Build,Analyzers" />
|
||||
<dependency id="Microsoft.AspNetCore.Components.WebAssembly" version="10.0.3" exclude="Build,Analyzers" />
|
||||
<dependency id="Microsoft.AspNetCore.Components.WebAssembly.Authentication" version="10.0.3" exclude="Build,Analyzers" />
|
||||
<dependency id="Microsoft.Extensions.Localization" version="10.0.3" exclude="Build,Analyzers" />
|
||||
<dependency id="Microsoft.Extensions.Http" version="10.0.3" exclude="Build,Analyzers" />
|
||||
<dependency id="Radzen.Blazor" version="9.0.0" exclude="Build,Analyzers" />
|
||||
</group>
|
||||
</dependencies>
|
||||
</metadata>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<package>
|
||||
<metadata>
|
||||
<id>Oqtane.Framework</id>
|
||||
<version>10.0.4</version>
|
||||
<version>10.1.0</version>
|
||||
<authors>Shaun Walker</authors>
|
||||
<owners>.NET Foundation</owners>
|
||||
<title>Oqtane Framework</title>
|
||||
@@ -11,8 +11,8 @@
|
||||
<copyright>.NET Foundation</copyright>
|
||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||
<license type="expression">MIT</license>
|
||||
<projectUrl>https://github.com/oqtane/oqtane.framework/releases/download/v10.0.4/Oqtane.Framework.10.0.4.Upgrade.zip</projectUrl>
|
||||
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v10.0.4</releaseNotes>
|
||||
<projectUrl>https://github.com/oqtane/oqtane.framework/releases/download/v10.1.0/Oqtane.Framework.10.1.0.Upgrade.zip</projectUrl>
|
||||
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v10.1.0</releaseNotes>
|
||||
<readme>readme.md</readme>
|
||||
<icon>icon.png</icon>
|
||||
<tags>oqtane framework</tags>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<package>
|
||||
<metadata>
|
||||
<id>Oqtane.Server</id>
|
||||
<version>10.0.4</version>
|
||||
<version>10.1.0</version>
|
||||
<authors>Shaun Walker</authors>
|
||||
<owners>.NET Foundation</owners>
|
||||
<title>Oqtane Framework</title>
|
||||
@@ -12,29 +12,29 @@
|
||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||
<license type="expression">MIT</license>
|
||||
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
||||
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v10.0.4</releaseNotes>
|
||||
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v10.1.0</releaseNotes>
|
||||
<readme>readme.md</readme>
|
||||
<icon>icon.png</icon>
|
||||
<tags>oqtane</tags>
|
||||
<dependencies>
|
||||
<group targetFramework="net10.0">
|
||||
<dependency id="Oqtane.Client" version="10.0.4" exclude="Build,Analyzers" />
|
||||
<dependency id="Oqtane.Shared" version="10.0.4" exclude="Build,Analyzers" />
|
||||
<dependency id="Microsoft.AspNetCore.Components.WebAssembly.Server" version="10.0.2" exclude="Build,Analyzers" />
|
||||
<dependency id="Microsoft.AspNetCore.Identity.EntityFrameworkCore" version="10.0.2" exclude="Build,Analyzers" />
|
||||
<dependency id="Microsoft.AspNetCore.Authentication.OpenIdConnect" version="10.0.2" exclude="Build,Analyzers" />
|
||||
<dependency id="Microsoft.EntityFrameworkCore.Relational" version="10.0.2" exclude="Build,Analyzers" />
|
||||
<dependency id="Oqtane.Client" version="10.1.0" exclude="Build,Analyzers" />
|
||||
<dependency id="Oqtane.Shared" version="10.1.0" exclude="Build,Analyzers" />
|
||||
<dependency id="Microsoft.AspNetCore.Components.WebAssembly.Server" version="10.0.3" exclude="Build,Analyzers" />
|
||||
<dependency id="Microsoft.AspNetCore.Identity.EntityFrameworkCore" version="10.0.3" exclude="Build,Analyzers" />
|
||||
<dependency id="Microsoft.AspNetCore.Authentication.OpenIdConnect" version="10.0.3" exclude="Build,Analyzers" />
|
||||
<dependency id="Microsoft.EntityFrameworkCore.Relational" version="10.0.3" exclude="Build,Analyzers" />
|
||||
<dependency id="SixLabors.ImageSharp" version="3.1.12" exclude="Build,Analyzers" />
|
||||
<dependency id="HtmlAgilityPack" version="1.12.4" exclude="Build,Analyzers" />
|
||||
<dependency id="Swashbuckle.AspNetCore" version="10.1.0" exclude="Build,Analyzers" />
|
||||
<dependency id="Swashbuckle.AspNetCore" version="10.1.2" exclude="Build,Analyzers" />
|
||||
<dependency id="MailKit" version="4.14.1" exclude="Build,Analyzers" />
|
||||
<dependency id="MySql.Data" version="9.5.0" exclude="Build,Analyzers" />
|
||||
<dependency id="MySql.EntityFrameworkCore" version="10.0.0-rc" exclude="Build,Analyzers" />
|
||||
<dependency id="EFCore.NamingConventions" version="10.0.0" exclude="Build,Analyzers" />
|
||||
<dependency id="MySql.Data" version="9.6.0" exclude="Build,Analyzers" />
|
||||
<dependency id="MySql.EntityFrameworkCore" version="10.0.1" exclude="Build,Analyzers" />
|
||||
<dependency id="EFCore.NamingConventions" version="10.0.1" exclude="Build,Analyzers" />
|
||||
<dependency id="Npgsql.EntityFrameworkCore.PostgreSQL" version="10.0.0" exclude="Build,Analyzers" />
|
||||
<dependency id="Microsoft.EntityFrameworkCore.Sqlite" version="10.0.2" exclude="Build,Analyzers" />
|
||||
<dependency id="Microsoft.Data.Sqlite.Core" version="10.0.2" exclude="Build,Analyzers" />
|
||||
<dependency id="Microsoft.EntityFrameworkCore.SqlServer" version="10.0.2" exclude="Build,Analyzers" />
|
||||
<dependency id="Microsoft.EntityFrameworkCore.Sqlite" version="10.0.3" exclude="Build,Analyzers" />
|
||||
<dependency id="Microsoft.Data.Sqlite.Core" version="10.0.3" exclude="Build,Analyzers" />
|
||||
<dependency id="Microsoft.EntityFrameworkCore.SqlServer" version="10.0.3" exclude="Build,Analyzers" />
|
||||
</group>
|
||||
</dependencies>
|
||||
<frameworkReferences>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<package>
|
||||
<metadata>
|
||||
<id>Oqtane.Shared</id>
|
||||
<version>10.0.4</version>
|
||||
<version>10.1.0</version>
|
||||
<authors>Shaun Walker</authors>
|
||||
<owners>.NET Foundation</owners>
|
||||
<title>Oqtane Framework</title>
|
||||
@@ -12,14 +12,14 @@
|
||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||
<license type="expression">MIT</license>
|
||||
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
||||
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v10.0.4</releaseNotes>
|
||||
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v10.1.0</releaseNotes>
|
||||
<readme>readme.md</readme>
|
||||
<icon>icon.png</icon>
|
||||
<tags>oqtane</tags>
|
||||
<dependencies>
|
||||
<group targetFramework="net10.0">
|
||||
<dependency id="Microsoft.EntityFrameworkCore" version="10.0.2" exclude="Build,Analyzers" />
|
||||
<dependency id="Microsoft.Extensions.DependencyInjection.Abstractions" version="10.0.2" exclude="Build,Analyzers" />
|
||||
<dependency id="Microsoft.EntityFrameworkCore" version="10.0.3" exclude="Build,Analyzers" />
|
||||
<dependency id="Microsoft.Extensions.DependencyInjection.Abstractions" version="10.0.3" exclude="Build,Analyzers" />
|
||||
<dependency id="NodaTime" version="3.3.0" exclude="Build,Analyzers" />
|
||||
</group>
|
||||
</dependencies>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<package>
|
||||
<metadata>
|
||||
<id>Oqtane.Updater</id>
|
||||
<version>10.0.4</version>
|
||||
<version>10.1.0</version>
|
||||
<authors>Shaun Walker</authors>
|
||||
<owners>.NET Foundation</owners>
|
||||
<title>Oqtane Framework</title>
|
||||
@@ -12,7 +12,7 @@
|
||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||
<license type="expression">MIT</license>
|
||||
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
||||
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v10.0.4</releaseNotes>
|
||||
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v10.1.0</releaseNotes>
|
||||
<readme>readme.md</readme>
|
||||
<icon>icon.png</icon>
|
||||
<tags>oqtane</tags>
|
||||
|
||||
@@ -1 +1 @@
|
||||
Compress-Archive -Path "..\Oqtane.Server\bin\Release\net10.0\publish\*" -DestinationPath "Oqtane.Framework.10.0.4.Install.zip" -Force
|
||||
Compress-Archive -Path "..\Oqtane.Server\bin\Release\net10.0\publish\*" -DestinationPath "Oqtane.Framework.10.1.0.Install.zip" -Force
|
||||
|
||||
@@ -1 +1 @@
|
||||
Compress-Archive -Path "..\Oqtane.Server\bin\Release\net10.0\publish\*" -DestinationPath "Oqtane.Framework.10.0.4.Upgrade.zip" -Force
|
||||
Compress-Archive -Path "..\Oqtane.Server\bin\Release\net10.0\publish\*" -DestinationPath "Oqtane.Framework.10.1.0.Upgrade.zip" -Force
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Security.Policy;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Oqtane.Enums;
|
||||
@@ -27,18 +28,23 @@ namespace Oqtane.Controllers
|
||||
_alias = tenantManager.GetAlias();
|
||||
}
|
||||
|
||||
// GET: api/<controller>?siteid=x&groupid=y
|
||||
// GET: api/<controller>?siteid=x
|
||||
[HttpGet]
|
||||
[Authorize(Roles = RoleNames.Host)]
|
||||
public IEnumerable<SiteGroup> Get(string siteid, string groupid)
|
||||
[Authorize(Roles = RoleNames.Admin)]
|
||||
public IEnumerable<SiteGroup> Get(string siteid)
|
||||
{
|
||||
if (int.TryParse(siteid, out int SiteId) && int.TryParse(groupid, out int SiteGroupDefinitionId))
|
||||
if (User.IsInRole(RoleNames.Host) || (int.TryParse(siteid, out int SiteId) && SiteId == _alias.SiteId))
|
||||
{
|
||||
return _siteGroupRepository.GetSiteGroups(SiteId, SiteGroupDefinitionId).ToList();
|
||||
var siteGroups = _siteGroupRepository.GetSiteGroups();
|
||||
if (!User.IsInRole(RoleNames.Host))
|
||||
{
|
||||
siteGroups = siteGroups.Where(item => item.PrimarySiteId == _alias.SiteId);
|
||||
}
|
||||
return siteGroups.ToList();
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Site Group Get Attempt for SiteId {SiteId} And SiteGroupDefinitionId {SiteGroupDefinitionId}", siteid, groupid);
|
||||
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Site Group Get Attempt {SiteId}", siteid);
|
||||
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
||||
return null;
|
||||
}
|
||||
@@ -49,10 +55,10 @@ namespace Oqtane.Controllers
|
||||
[Authorize(Roles = RoleNames.Host)]
|
||||
public SiteGroup Get(int id)
|
||||
{
|
||||
var siteGroup = _siteGroupRepository.GetSiteGroup(id);
|
||||
if (siteGroup != null)
|
||||
var group = _siteGroupRepository.GetSiteGroup(id);
|
||||
if (group != null)
|
||||
{
|
||||
return siteGroup;
|
||||
return group;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -69,12 +75,12 @@ namespace Oqtane.Controllers
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
siteGroup = _siteGroupRepository.AddSiteGroup(siteGroup);
|
||||
_syncManager.AddSyncEvent(_alias, EntityNames.SiteGroup, siteGroup.SiteGroupDefinitionId, SyncEventActions.Create);
|
||||
_logger.Log(LogLevel.Information, this, LogFunction.Create, "Site Group Added {SiteGroup}", siteGroup);
|
||||
_syncManager.AddSyncEvent(_alias, EntityNames.SiteGroup, siteGroup.SiteGroupId, SyncEventActions.Create);
|
||||
_logger.Log(LogLevel.Information, this, LogFunction.Create, "Site Group Added {Group}", siteGroup);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Site Group Post Attempt {SiteGroup}", siteGroup);
|
||||
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Site Group Post Attempt {Group}", siteGroup);
|
||||
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
||||
siteGroup = null;
|
||||
}
|
||||
@@ -83,18 +89,24 @@ namespace Oqtane.Controllers
|
||||
|
||||
// PUT api/<controller>/5
|
||||
[HttpPut("{id}")]
|
||||
[Authorize(Roles = RoleNames.Host)]
|
||||
[Authorize(Roles = RoleNames.Admin)]
|
||||
public SiteGroup Put(int id, [FromBody] SiteGroup siteGroup)
|
||||
{
|
||||
if (ModelState.IsValid && siteGroup.SiteGroupDefinitionId == id && _siteGroupRepository.GetSiteGroup(siteGroup.SiteGroupDefinitionId, false) != null)
|
||||
if (ModelState.IsValid && siteGroup.SiteGroupId == id)
|
||||
{
|
||||
if (!User.IsInRole(RoleNames.Host) && siteGroup.Synchronize)
|
||||
{
|
||||
// admins can only update the synchronize field
|
||||
siteGroup = _siteGroupRepository.GetSiteGroup(siteGroup.SiteGroupId, false);
|
||||
siteGroup.Synchronize = true;
|
||||
}
|
||||
siteGroup = _siteGroupRepository.UpdateSiteGroup(siteGroup);
|
||||
_syncManager.AddSyncEvent(_alias, EntityNames.SiteGroup, siteGroup.SiteGroupDefinitionId, SyncEventActions.Update);
|
||||
_logger.Log(LogLevel.Information, this, LogFunction.Update, "Site Group Updated {SiteGroup}", siteGroup);
|
||||
_syncManager.AddSyncEvent(_alias, EntityNames.SiteGroup, siteGroup.SiteGroupId, SyncEventActions.Update);
|
||||
_logger.Log(LogLevel.Information, this, LogFunction.Update, "Site Group Updated {Group}", siteGroup);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Site Group Put Attempt {SiteGroup}", siteGroup);
|
||||
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Site Group Put Attempt {Group}", siteGroup);
|
||||
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
||||
siteGroup = null;
|
||||
}
|
||||
@@ -111,11 +123,11 @@ namespace Oqtane.Controllers
|
||||
{
|
||||
_siteGroupRepository.DeleteSiteGroup(id);
|
||||
_syncManager.AddSyncEvent(_alias, EntityNames.SiteGroup, siteGroup.SiteGroupId, SyncEventActions.Delete);
|
||||
_logger.Log(LogLevel.Information, this, LogFunction.Delete, "Site Group Deleted {SiteGroupId}", id);
|
||||
_logger.Log(LogLevel.Information, this, LogFunction.Delete, "Site Group Deleted {siteGroupId}", id);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Site Group Delete Attempt {SiteGroupId}", id);
|
||||
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Site Group Delete Attempt {siteGroupId}", id);
|
||||
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,114 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Oqtane.Enums;
|
||||
using Oqtane.Models;
|
||||
using Oqtane.Shared;
|
||||
using Oqtane.Infrastructure;
|
||||
using Oqtane.Repository;
|
||||
using System.Net;
|
||||
using System.Linq;
|
||||
|
||||
namespace Oqtane.Controllers
|
||||
{
|
||||
[Route(ControllerRoutes.ApiRoute)]
|
||||
public class SiteGroupDefinitionController : Controller
|
||||
{
|
||||
private readonly ISiteGroupDefinitionRepository _siteGroupDefinitionRepository;
|
||||
private readonly ISyncManager _syncManager;
|
||||
private readonly ILogManager _logger;
|
||||
private readonly Alias _alias;
|
||||
|
||||
public SiteGroupDefinitionController(ISiteGroupDefinitionRepository siteGroupDefinitionRepository, ISyncManager syncManager, ILogManager logger, ITenantManager tenantManager)
|
||||
{
|
||||
_siteGroupDefinitionRepository = siteGroupDefinitionRepository;
|
||||
_syncManager = syncManager;
|
||||
_logger = logger;
|
||||
_alias = tenantManager.GetAlias();
|
||||
}
|
||||
|
||||
// GET: api/<controller>
|
||||
[HttpGet]
|
||||
[Authorize(Roles = RoleNames.Host)]
|
||||
public IEnumerable<SiteGroupDefinition> Get()
|
||||
{
|
||||
return _siteGroupDefinitionRepository.GetSiteGroupDefinitions().ToList();
|
||||
}
|
||||
|
||||
// GET api/<controller>/5
|
||||
[HttpGet("{id}")]
|
||||
[Authorize(Roles = RoleNames.Host)]
|
||||
public SiteGroupDefinition Get(int id)
|
||||
{
|
||||
var group = _siteGroupDefinitionRepository.GetSiteGroupDefinition(id);
|
||||
if (group != null)
|
||||
{
|
||||
return group;
|
||||
}
|
||||
else
|
||||
{
|
||||
HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// POST api/<controller>
|
||||
[HttpPost]
|
||||
[Authorize(Roles = RoleNames.Host)]
|
||||
public SiteGroupDefinition Post([FromBody] SiteGroupDefinition siteGroupDefinition)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
siteGroupDefinition = _siteGroupDefinitionRepository.AddSiteGroupDefinition(siteGroupDefinition);
|
||||
_syncManager.AddSyncEvent(_alias, EntityNames.SiteGroupDefinition, siteGroupDefinition.SiteGroupDefinitionId, SyncEventActions.Create);
|
||||
_logger.Log(LogLevel.Information, this, LogFunction.Create, "Site Group Definition Added {Group}", siteGroupDefinition);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Site Group Definition Post Attempt {Group}", siteGroupDefinition);
|
||||
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
||||
siteGroupDefinition = null;
|
||||
}
|
||||
return siteGroupDefinition;
|
||||
}
|
||||
|
||||
// PUT api/<controller>/5
|
||||
[HttpPut("{id}")]
|
||||
[Authorize(Roles = RoleNames.Host)]
|
||||
public SiteGroupDefinition Put(int id, [FromBody] SiteGroupDefinition siteGroupDefinition)
|
||||
{
|
||||
if (ModelState.IsValid && siteGroupDefinition.SiteGroupDefinitionId == id && _siteGroupDefinitionRepository.GetSiteGroupDefinition(siteGroupDefinition.SiteGroupDefinitionId, false) != null)
|
||||
{
|
||||
siteGroupDefinition = _siteGroupDefinitionRepository.UpdateSiteGroupDefinition(siteGroupDefinition);
|
||||
_syncManager.AddSyncEvent(_alias, EntityNames.SiteGroupDefinition, siteGroupDefinition.SiteGroupDefinitionId, SyncEventActions.Update);
|
||||
_logger.Log(LogLevel.Information, this, LogFunction.Update, "Site Group Definition Updated {Group}", siteGroupDefinition);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Site Group Definition Put Attempt {Group}", siteGroupDefinition);
|
||||
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
||||
siteGroupDefinition = null;
|
||||
}
|
||||
return siteGroupDefinition;
|
||||
}
|
||||
|
||||
// DELETE api/<controller>/5
|
||||
[HttpDelete("{id}")]
|
||||
[Authorize(Roles = RoleNames.Host)]
|
||||
public void Delete(int id)
|
||||
{
|
||||
var siteGroupDefinition = _siteGroupDefinitionRepository.GetSiteGroupDefinition(id);
|
||||
if (siteGroupDefinition != null)
|
||||
{
|
||||
_siteGroupDefinitionRepository.DeleteSiteGroupDefinition(id);
|
||||
_syncManager.AddSyncEvent(_alias, EntityNames.SiteGroupDefinition, siteGroupDefinition.SiteGroupDefinitionId, SyncEventActions.Delete);
|
||||
_logger.Log(LogLevel.Information, this, LogFunction.Delete, "Site Group Definition Deleted {siteGroupDefinitionId}", id);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Site Group Definition Delete Attempt {siteGroupDefinitionId}", id);
|
||||
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
126
Oqtane.Server/Controllers/SiteGroupMemberController.cs
Normal file
126
Oqtane.Server/Controllers/SiteGroupMemberController.cs
Normal file
@@ -0,0 +1,126 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Oqtane.Enums;
|
||||
using Oqtane.Infrastructure;
|
||||
using Oqtane.Models;
|
||||
using Oqtane.Repository;
|
||||
using Oqtane.Shared;
|
||||
|
||||
namespace Oqtane.Controllers
|
||||
{
|
||||
[Route(ControllerRoutes.ApiRoute)]
|
||||
public class SiteGroupMemberController : Controller
|
||||
{
|
||||
private readonly ISiteGroupMemberRepository _siteGroupMemberRepository;
|
||||
private readonly ISyncManager _syncManager;
|
||||
private readonly ILogManager _logger;
|
||||
private readonly Alias _alias;
|
||||
|
||||
public SiteGroupMemberController(ISiteGroupMemberRepository siteGroupMemberRepository, ISyncManager syncManager, ILogManager logger, ITenantManager tenantManager)
|
||||
{
|
||||
_siteGroupMemberRepository = siteGroupMemberRepository;
|
||||
_syncManager = syncManager;
|
||||
_logger = logger;
|
||||
_alias = tenantManager.GetAlias();
|
||||
}
|
||||
|
||||
// GET: api/<controller>?siteid=x&groupid=y
|
||||
[HttpGet]
|
||||
[Authorize(Roles = RoleNames.Host)]
|
||||
public IEnumerable<SiteGroupMember> Get(string siteid, string groupid)
|
||||
{
|
||||
if (int.TryParse(siteid, out int SiteId) && int.TryParse(groupid, out int SiteGroupId))
|
||||
{
|
||||
return _siteGroupMemberRepository.GetSiteGroupMembers(SiteId, SiteGroupId).ToList();
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Site Group Member Get Attempt for SiteId {SiteId} And SiteGroupId {SiteGroupId}", siteid, groupid);
|
||||
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// GET api/<controller>/5
|
||||
[HttpGet("{id}")]
|
||||
[Authorize(Roles = RoleNames.Host)]
|
||||
public SiteGroupMember Get(int id)
|
||||
{
|
||||
var siteGroupMember = _siteGroupMemberRepository.GetSiteGroupMember(id);
|
||||
if (siteGroupMember != null)
|
||||
{
|
||||
return siteGroupMember;
|
||||
}
|
||||
else
|
||||
{
|
||||
HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// POST api/<controller>
|
||||
[HttpPost]
|
||||
[Authorize(Roles = RoleNames.Host)]
|
||||
public SiteGroupMember Post([FromBody] SiteGroupMember siteGroupMember)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
siteGroupMember = _siteGroupMemberRepository.AddSiteGroupMember(siteGroupMember);
|
||||
_syncManager.AddSyncEvent(_alias, EntityNames.SiteGroupMember, siteGroupMember.SiteGroupId, SyncEventActions.Create);
|
||||
_syncManager.AddSyncEvent(_alias, EntityNames.Site, siteGroupMember.SiteId, SyncEventActions.Refresh);
|
||||
_logger.Log(LogLevel.Information, this, LogFunction.Create, "Site Group Member Added {SiteGroupMember}", siteGroupMember);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Site Group Member Post Attempt {SiteGroupMember}", siteGroupMember);
|
||||
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
||||
siteGroupMember = null;
|
||||
}
|
||||
return siteGroupMember;
|
||||
}
|
||||
|
||||
// PUT api/<controller>/5
|
||||
[HttpPut("{id}")]
|
||||
[Authorize(Roles = RoleNames.Host)]
|
||||
public SiteGroupMember Put(int id, [FromBody] SiteGroupMember siteGroupMember)
|
||||
{
|
||||
if (ModelState.IsValid && siteGroupMember.SiteGroupId == id && _siteGroupMemberRepository.GetSiteGroupMember(siteGroupMember.SiteGroupId, false) != null)
|
||||
{
|
||||
siteGroupMember = _siteGroupMemberRepository.UpdateSiteGroupMember(siteGroupMember);
|
||||
_syncManager.AddSyncEvent(_alias, EntityNames.SiteGroupMember, siteGroupMember.SiteGroupId, SyncEventActions.Update);
|
||||
_syncManager.AddSyncEvent(_alias, EntityNames.Site, siteGroupMember.SiteId, SyncEventActions.Refresh);
|
||||
_logger.Log(LogLevel.Information, this, LogFunction.Update, "Site Group Member Updated {SiteGroupMember}", siteGroupMember);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Site Group Member Put Attempt {SiteGroupMember}", siteGroupMember);
|
||||
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
||||
siteGroupMember = null;
|
||||
}
|
||||
return siteGroupMember;
|
||||
}
|
||||
|
||||
// DELETE api/<controller>/5
|
||||
[HttpDelete("{id}")]
|
||||
[Authorize(Roles = RoleNames.Host)]
|
||||
public void Delete(int id)
|
||||
{
|
||||
var siteGroupMember = _siteGroupMemberRepository.GetSiteGroupMember(id);
|
||||
if (siteGroupMember != null)
|
||||
{
|
||||
_siteGroupMemberRepository.DeleteSiteGroupMember(id);
|
||||
_syncManager.AddSyncEvent(_alias, EntityNames.SiteGroupMember, siteGroupMember.SiteGroupMemberId, SyncEventActions.Delete);
|
||||
_syncManager.AddSyncEvent(_alias, EntityNames.Site, siteGroupMember.SiteId, SyncEventActions.Refresh);
|
||||
_logger.Log(LogLevel.Information, this, LogFunction.Delete, "Site Group Member Deleted {SiteGroupMemberId}", id);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Site Group Member Delete Attempt {SiteGroupMemberId}", id);
|
||||
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -233,8 +233,8 @@ namespace Microsoft.Extensions.DependencyInjection
|
||||
services.AddScoped<ICookieConsentService, ServerCookieConsentService>();
|
||||
services.AddScoped<ITimeZoneService, TimeZoneService>();
|
||||
services.AddScoped<IMigrationHistoryService, MigrationHistoryService>();
|
||||
services.AddScoped<ISiteGroupDefinitionService, SiteGroupDefinitionService>();
|
||||
services.AddScoped<ISiteGroupService, SiteGroupService>();
|
||||
services.AddScoped<ISiteGroupMemberService, SiteGroupMemberService>();
|
||||
|
||||
// providers
|
||||
services.AddScoped<ITextEditor, Oqtane.Modules.Controls.QuillJSTextEditor>();
|
||||
@@ -284,8 +284,8 @@ namespace Microsoft.Extensions.DependencyInjection
|
||||
services.AddTransient<IUrlMappingRepository, UrlMappingRepository>();
|
||||
services.AddTransient<ISearchContentRepository, SearchContentRepository>();
|
||||
services.AddTransient<IMigrationHistoryRepository, MigrationHistoryRepository>();
|
||||
services.AddTransient<ISiteGroupDefinitionRepository, SiteGroupDefinitionRepository>();
|
||||
services.AddTransient<ISiteGroupRepository, SiteGroupRepository>();
|
||||
services.AddTransient<ISiteGroupMemberRepository, SiteGroupMemberRepository>();
|
||||
|
||||
// managers
|
||||
services.AddTransient<IDBContextDependencies, DBContextDependencies>();
|
||||
|
||||
@@ -16,9 +16,8 @@ namespace Oqtane.Infrastructure
|
||||
// JobType = "Oqtane.Infrastructure.SynchronizationJob, Oqtane.Server"
|
||||
|
||||
// synchronization only supports sites in the same tenant (database)
|
||||
// module title is used as a key to identify module instances on a page (ie. using "-" as a module title is problematic ie. content as configuration)
|
||||
// relies on Module.ModifiedOn to be set if the module content changes (for efficiency)
|
||||
// modules must implement ISynchronizable interface (new interface as IPortable was generally only implemented in an additive manner)
|
||||
// module title is used as a key to identify module instances on a page
|
||||
// modules must implement ISynchronizable interface
|
||||
|
||||
// define settings that should not be synchronized (should be extensible in the future)
|
||||
List<Setting> excludedSettings = new List<Setting>() {
|
||||
@@ -38,76 +37,82 @@ namespace Oqtane.Infrastructure
|
||||
{
|
||||
string log = "";
|
||||
|
||||
var siteGroupDefinitionRepository = provider.GetRequiredService<ISiteGroupDefinitionRepository>();
|
||||
var siteGroupRepository = provider.GetRequiredService<ISiteGroupRepository>();
|
||||
var siteGroupMemberRepository = provider.GetRequiredService<ISiteGroupMemberRepository>();
|
||||
var siteRepository = provider.GetRequiredService<ISiteRepository>();
|
||||
var aliasRepository = provider.GetRequiredService<IAliasRepository>();
|
||||
var tenantManager = provider.GetRequiredService<ITenantManager>();
|
||||
var settingRepository = provider.GetRequiredService<ISettingRepository>();
|
||||
|
||||
List<SiteGroup> siteGroups = null;
|
||||
List<SiteGroupMember> siteGroupMembers = null;
|
||||
List<Site> sites = null;
|
||||
List<Alias> aliases = null;
|
||||
|
||||
// get groups
|
||||
var groups = siteGroupDefinitionRepository.GetSiteGroupDefinitions();
|
||||
// get site groups
|
||||
var siteGroups = siteGroupRepository.GetSiteGroups();
|
||||
|
||||
// iterate through groups which need to be synchronized
|
||||
foreach (var group in groups.Where(item => item.Synchronization && item.Synchronize))
|
||||
// iterate through site groups which need to be synchronized
|
||||
foreach (var siteGroup in siteGroups.Where(item => item.Synchronize && (item.Type == SiteGroupTypes.Synchronization || item.Type == SiteGroupTypes.Comparison)))
|
||||
{
|
||||
// get data
|
||||
if (siteGroups == null)
|
||||
if (siteGroupMembers == null)
|
||||
{
|
||||
siteGroups = siteGroupRepository.GetSiteGroups().ToList();
|
||||
siteGroupMembers = siteGroupMemberRepository.GetSiteGroupMembers().ToList();
|
||||
sites = siteRepository.GetSites().ToList();
|
||||
aliases = aliasRepository.GetAliases().ToList();
|
||||
}
|
||||
|
||||
var aliasName = "https://" + aliases.First(item => item.TenantId == tenantManager.GetTenant().TenantId && item.SiteId == group.PrimarySiteId && item.IsDefault).Name;
|
||||
log += $"Processing Primary Site: {sites.First(item => item.SiteId == group.PrimarySiteId).Name} - {CreateLink(aliasName)}<br />";
|
||||
var primaryAliasName = "https://" + aliases.First(item => item.TenantId == tenantManager.GetTenant().TenantId && item.SiteId == siteGroup.PrimarySiteId && item.IsDefault).Name;
|
||||
log += (siteGroup.Type == SiteGroupTypes.Synchronization) ? "Synchronizing " : "Comparing ";
|
||||
log += $"Primary Site: {sites.First(item => item.SiteId == siteGroup.PrimarySiteId).Name} - {CreateLink(primaryAliasName)}<br />";
|
||||
|
||||
// get primary site
|
||||
var primarySite = sites.FirstOrDefault(item => item.SiteId == group.PrimarySiteId);
|
||||
var primarySite = sites.FirstOrDefault(item => item.SiteId == siteGroup.PrimarySiteId);
|
||||
if (primarySite != null)
|
||||
{
|
||||
// update flag to prevent job from processing group again
|
||||
group.Synchronize = false;
|
||||
siteGroupDefinitionRepository.UpdateSiteGroupDefinition(group);
|
||||
siteGroup.Synchronize = false;
|
||||
siteGroupRepository.UpdateSiteGroup(siteGroup);
|
||||
|
||||
// iterate through sites in group
|
||||
foreach (var siteGroup in siteGroups.Where(item => item.SiteGroupDefinitionId == group.SiteGroupDefinitionId && item.SiteId != group.PrimarySiteId))
|
||||
// iterate through sites in site group
|
||||
foreach (var siteGroupMember in siteGroupMembers.Where(item => item.SiteGroupId == siteGroup.SiteGroupId && item.SiteId != siteGroup.PrimarySiteId))
|
||||
{
|
||||
// get secondary site
|
||||
var secondarySite = sites.FirstOrDefault(item => item.SiteId == siteGroup.SiteId);
|
||||
var secondarySite = sites.FirstOrDefault(item => item.SiteId == siteGroupMember.SiteId);
|
||||
if (secondarySite != null)
|
||||
{
|
||||
// get default alias for site
|
||||
siteGroup.AliasName = "https://" + aliases.First(item => item.TenantId == tenantManager.GetTenant().TenantId && item.SiteId == siteGroup.SiteId && item.IsDefault).Name;
|
||||
var secondaryAliasName = "https://" + aliases.First(item => item.TenantId == tenantManager.GetTenant().TenantId && item.SiteId == siteGroupMember.SiteId && item.IsDefault).Name;
|
||||
siteGroupMember.AliasName = (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization) ? secondaryAliasName : primaryAliasName;
|
||||
|
||||
// initialize SynchronizedOn
|
||||
if (siteGroup.SynchronizedOn == null)
|
||||
if (siteGroupMember.SynchronizedOn == null)
|
||||
{
|
||||
siteGroup.SynchronizedOn = DateTime.MinValue;
|
||||
siteGroupMember.SynchronizedOn = DateTime.MinValue;
|
||||
}
|
||||
|
||||
// replicate site
|
||||
var siteLog = ReplicateSite(provider, tenantManager, settingRepository, siteGroup, primarySite, secondarySite);
|
||||
// synchronize site
|
||||
var siteLog = SynchronizeSite(provider, tenantManager, settingRepository, siteGroupMember, primarySite, secondarySite);
|
||||
if (string.IsNullOrEmpty(siteLog))
|
||||
{
|
||||
siteLog = (siteGroupMember.SynchronizedOn != DateTime.MinValue) ? "No Changes Identified<br />" : "Initialization Complete<br />";
|
||||
}
|
||||
|
||||
// set synchronized on date/time
|
||||
siteGroup.SynchronizedOn = DateTime.UtcNow;
|
||||
siteGroupRepository.UpdateSiteGroup(siteGroup);
|
||||
siteGroupMember.SynchronizedOn = DateTime.UtcNow;
|
||||
siteGroupMemberRepository.UpdateSiteGroupMember(siteGroupMember);
|
||||
|
||||
log += $"Processed Secondary Site: {secondarySite.Name} - {CreateLink(siteGroup.AliasName)}<br />" + siteLog;
|
||||
log += $"With Secondary Site: {secondarySite.Name} - {CreateLink(secondaryAliasName)}<br />" + siteLog;
|
||||
}
|
||||
else
|
||||
{
|
||||
log += $"Site Group {group.Name} Has A SiteId {siteGroup.SiteId} Which Does Not Exist<br />";
|
||||
log += $"Site Group {siteGroup.Name} Has A SiteId {siteGroupMember.SiteId} Which Does Not Exist<br />";
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
log += $"Site Group {group.Name} Has A PrimarySiteId {group.PrimarySiteId} Which Does Not Exist<br />";
|
||||
log += $"Site Group {siteGroup.Name} Has A PrimarySiteId {siteGroup.PrimarySiteId} Which Does Not Exist<br />";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,23 +124,24 @@ namespace Oqtane.Infrastructure
|
||||
return log;
|
||||
}
|
||||
|
||||
private string ReplicateSite(IServiceProvider provider, ITenantManager tenantManager, ISettingRepository settingRepository, SiteGroup siteGroup, Site primarySite, Site secondarySite)
|
||||
private string SynchronizeSite(IServiceProvider provider, ITenantManager tenantManager, ISettingRepository settingRepository, SiteGroupMember siteGroupMember, Site primarySite, Site secondarySite)
|
||||
{
|
||||
var log = "";
|
||||
|
||||
// replicate roles/users
|
||||
log += ReplicateRoles(provider, settingRepository, siteGroup, primarySite.SiteId, secondarySite.SiteId);
|
||||
// synchronize roles/users
|
||||
log += SynchronizeRoles(provider, settingRepository, siteGroupMember, primarySite.SiteId, secondarySite.SiteId);
|
||||
|
||||
// replicate folders/files
|
||||
log += ReplicateFolders(provider, settingRepository, siteGroup, primarySite.SiteId, secondarySite.SiteId);
|
||||
// synchronize folders/files
|
||||
log += SynchronizeFolders(provider, settingRepository, siteGroupMember, primarySite.SiteId, secondarySite.SiteId);
|
||||
|
||||
// replicate pages/modules
|
||||
log += ReplicatePages(provider, settingRepository, tenantManager, siteGroup, primarySite.SiteId, secondarySite.SiteId);
|
||||
// synchronize pages/modules
|
||||
log += SynchronizePages(provider, settingRepository, tenantManager, siteGroupMember, primarySite.SiteId, secondarySite.SiteId);
|
||||
|
||||
// replicate site
|
||||
if (primarySite.ModifiedOn > siteGroup.SynchronizedOn)
|
||||
// synchronize site
|
||||
if (primarySite.ModifiedOn > siteGroupMember.SynchronizedOn)
|
||||
{
|
||||
secondarySite.TimeZoneId = primarySite.TimeZoneId;
|
||||
secondarySite.CultureCode = primarySite.CultureCode;
|
||||
if (secondarySite.LogoFileId != primarySite.LogoFileId)
|
||||
{
|
||||
secondarySite.LogoFileId = ResolveFileId(provider, primarySite.LogoFileId, secondarySite.SiteId);
|
||||
@@ -176,29 +182,30 @@ namespace Oqtane.Infrastructure
|
||||
secondarySite.DeletedBy = primarySite.DeletedBy;
|
||||
secondarySite.DeletedOn = primarySite.DeletedOn;
|
||||
|
||||
var siteRepository = provider.GetRequiredService<ISiteRepository>();
|
||||
if (siteGroup.Synchronize)
|
||||
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization)
|
||||
{
|
||||
var siteRepository = provider.GetRequiredService<ISiteRepository>();
|
||||
siteRepository.UpdateSite(secondarySite);
|
||||
}
|
||||
log += Log(siteGroup, $"Secondary Site Updated: {secondarySite.Name}");
|
||||
log += Log(siteGroupMember, $"Site Updated: {secondarySite.Name} - {CreateLink(siteGroupMember.AliasName)}");
|
||||
}
|
||||
|
||||
// site settings
|
||||
log += ReplicateSettings(settingRepository, siteGroup, EntityNames.Site, primarySite.SiteId, secondarySite.SiteId);
|
||||
log += SynchronizeSettings(settingRepository, siteGroupMember, EntityNames.Site, primarySite.SiteId, secondarySite.SiteId);
|
||||
|
||||
if (siteGroup.SynchronizedOn == DateTime.MinValue || !string.IsNullOrEmpty(log))
|
||||
if (siteGroupMember.SynchronizedOn == DateTime.MinValue || !string.IsNullOrEmpty(log))
|
||||
{
|
||||
// clear cache for secondary site if any content was replicated
|
||||
// clear cache for secondary site if any content was Synchronized
|
||||
var syncManager = provider.GetRequiredService<ISyncManager>();
|
||||
var alias = new Alias { TenantId = tenantManager.GetTenant().TenantId, SiteId = secondarySite.SiteId };
|
||||
syncManager.AddSyncEvent(alias, EntityNames.Site, secondarySite.SiteId, SyncEventActions.Refresh);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(log) && siteGroup.Notify)
|
||||
if (!string.IsNullOrEmpty(log) && siteGroupMember.SiteGroup.Type == SiteGroupTypes.Comparison)
|
||||
{
|
||||
// send change log to administrators
|
||||
SendNotifications(provider, secondarySite.SiteId, secondarySite.Name, log);
|
||||
log += Log(siteGroupMember, $"Change Log Sent To Administrators");
|
||||
}
|
||||
|
||||
return log;
|
||||
@@ -215,7 +222,7 @@ namespace Oqtane.Infrastructure
|
||||
return fileId;
|
||||
}
|
||||
|
||||
private string ReplicateRoles(IServiceProvider provider, ISettingRepository settingRepository, SiteGroup siteGroup, int primarySiteId, int secondarySiteId)
|
||||
private string SynchronizeRoles(IServiceProvider provider, ISettingRepository settingRepository, SiteGroupMember siteGroupMember, int primarySiteId, int secondarySiteId)
|
||||
{
|
||||
// get roles
|
||||
var roleRepository = provider.GetRequiredService<IRoleRepository>();
|
||||
@@ -234,7 +241,7 @@ namespace Oqtane.Infrastructure
|
||||
secondaryRole.SiteId = secondarySiteId;
|
||||
}
|
||||
|
||||
if (role == null || primaryRole.ModifiedOn > siteGroup.SynchronizedOn)
|
||||
if (role == null || primaryRole.ModifiedOn > siteGroupMember.SynchronizedOn)
|
||||
{
|
||||
// set all properties
|
||||
secondaryRole.Name = primaryRole.Name;
|
||||
@@ -244,41 +251,45 @@ namespace Oqtane.Infrastructure
|
||||
|
||||
if (role == null)
|
||||
{
|
||||
if (siteGroup.Synchronize)
|
||||
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization)
|
||||
{
|
||||
roleRepository.AddRole(secondaryRole);
|
||||
}
|
||||
log += Log(siteGroup, $"Role Added: {secondaryRole.Name}");
|
||||
log += Log(siteGroupMember, $"Role Added: {secondaryRole.Name}");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (siteGroup.Synchronize)
|
||||
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization)
|
||||
{
|
||||
roleRepository.UpdateRole(secondaryRole);
|
||||
}
|
||||
log += Log(siteGroup, $"Role Updated: {secondaryRole.Name}");
|
||||
secondaryRoles.Remove(role);
|
||||
log += Log(siteGroupMember, $"Role Updated: {secondaryRole.Name}");
|
||||
}
|
||||
}
|
||||
|
||||
if (role != null)
|
||||
{
|
||||
secondaryRoles.Remove(role);
|
||||
}
|
||||
}
|
||||
|
||||
// remove roles in the secondary site which do not exist in the primary site
|
||||
foreach (var secondaryRole in secondaryRoles.Where(item => !primaryRoles.Select(item => item.Name).Contains(item.Name)))
|
||||
foreach (var secondaryRole in secondaryRoles)
|
||||
{
|
||||
if (siteGroup.Synchronize)
|
||||
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization)
|
||||
{
|
||||
roleRepository.DeleteRole(secondaryRole.RoleId);
|
||||
}
|
||||
log += Log(siteGroup, $"Role Deleted: {secondaryRole.Name}");
|
||||
log += Log(siteGroupMember, $"Role Deleted: {secondaryRole.Name}");
|
||||
}
|
||||
|
||||
// settings
|
||||
log += ReplicateSettings(settingRepository, siteGroup, EntityNames.Role, primarySiteId, secondarySiteId);
|
||||
log += SynchronizeSettings(settingRepository, siteGroupMember, EntityNames.Role, primarySiteId, secondarySiteId);
|
||||
|
||||
return log;
|
||||
}
|
||||
|
||||
private string ReplicateFolders(IServiceProvider provider, ISettingRepository settingRepository, SiteGroup siteGroup, int primarySiteId, int secondarySiteId)
|
||||
private string SynchronizeFolders(IServiceProvider provider, ISettingRepository settingRepository, SiteGroupMember siteGroupMember, int primarySiteId, int secondarySiteId)
|
||||
{
|
||||
var folderRepository = provider.GetRequiredService<IFolderRepository>();
|
||||
var fileRepository = provider.GetRequiredService<IFileRepository>();
|
||||
@@ -300,7 +311,7 @@ namespace Oqtane.Infrastructure
|
||||
secondaryFolder.SiteId = secondarySiteId;
|
||||
}
|
||||
|
||||
if (folder == null || primaryFolder.ModifiedOn > siteGroup.SynchronizedOn)
|
||||
if (folder == null || primaryFolder.ModifiedOn > siteGroupMember.SynchronizedOn)
|
||||
{
|
||||
// set all properties
|
||||
secondaryFolder.ParentId = null;
|
||||
@@ -319,29 +330,33 @@ namespace Oqtane.Infrastructure
|
||||
secondaryFolder.Capacity = primaryFolder.Capacity;
|
||||
secondaryFolder.ImageSizes = primaryFolder.ImageSizes;
|
||||
secondaryFolder.IsSystem = primaryFolder.IsSystem;
|
||||
secondaryFolder.PermissionList = ReplicatePermissions(primaryFolder.PermissionList, secondarySiteId);
|
||||
secondaryFolder.PermissionList = SynchronizePermissions(primaryFolder.PermissionList, secondarySiteId);
|
||||
|
||||
if (folder == null)
|
||||
{
|
||||
if (siteGroup.Synchronize)
|
||||
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization)
|
||||
{
|
||||
folderRepository.AddFolder(secondaryFolder);
|
||||
}
|
||||
log += Log(siteGroup, $"Folder Added: {secondaryFolder.Path}");
|
||||
log += Log(siteGroupMember, $"Folder Added: {secondaryFolder.Path}");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (siteGroup.Synchronize)
|
||||
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization)
|
||||
{
|
||||
folderRepository.UpdateFolder(secondaryFolder);
|
||||
}
|
||||
log += Log(siteGroup, $"Folder Updated: {secondaryFolder.Path}");
|
||||
secondaryFolders.Remove(folder);
|
||||
log += Log(siteGroupMember, $"Folder Updated: {secondaryFolder.Path}");
|
||||
}
|
||||
}
|
||||
|
||||
if (folder != null)
|
||||
{
|
||||
secondaryFolders.Remove(folder);
|
||||
}
|
||||
|
||||
// folder settings
|
||||
log += ReplicateSettings(settingRepository, siteGroup, EntityNames.Folder, primaryFolder.FolderId, secondaryFolder.FolderId);
|
||||
log += SynchronizeSettings(settingRepository, siteGroupMember, EntityNames.Folder, primaryFolder.FolderId, secondaryFolder.FolderId);
|
||||
|
||||
// get files for folder
|
||||
var primaryFiles = fileRepository.GetFiles(primaryFolder.FolderId);
|
||||
@@ -359,7 +374,7 @@ namespace Oqtane.Infrastructure
|
||||
secondaryFile.Name = primaryFile.Name;
|
||||
}
|
||||
|
||||
if (file == null || primaryFile.ModifiedOn > siteGroup.SynchronizedOn)
|
||||
if (file == null || primaryFile.ModifiedOn > siteGroupMember.SynchronizedOn)
|
||||
{
|
||||
// set all properties
|
||||
secondaryFile.Extension = primaryFile.Extension;
|
||||
@@ -370,53 +385,57 @@ namespace Oqtane.Infrastructure
|
||||
|
||||
if (file == null)
|
||||
{
|
||||
if (siteGroup.Synchronize)
|
||||
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization)
|
||||
{
|
||||
fileRepository.AddFile(secondaryFile);
|
||||
ReplicateFile(folderRepository, primaryFolder, primaryFile, secondaryFolder, secondaryFile);
|
||||
SynchronizeFile(folderRepository, primaryFolder, primaryFile, secondaryFolder, secondaryFile);
|
||||
}
|
||||
log += Log(siteGroup, $"File Added: {CreateLink(siteGroup.AliasName + secondaryFolder.Path + secondaryFile.Name)}");
|
||||
log += Log(siteGroupMember, $"File Added: {CreateLink(siteGroupMember.AliasName + "/" + secondaryFolder.Path + secondaryFile.Name)}");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (siteGroup.Synchronize)
|
||||
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization)
|
||||
{
|
||||
fileRepository.UpdateFile(secondaryFile);
|
||||
ReplicateFile(folderRepository, primaryFolder, primaryFile, secondaryFolder, secondaryFile);
|
||||
SynchronizeFile(folderRepository, primaryFolder, primaryFile, secondaryFolder, secondaryFile);
|
||||
}
|
||||
log += Log(siteGroup, $"File Updated: {CreateLink(siteGroup.AliasName + secondaryFolder.Path + secondaryFile.Name)}");
|
||||
secondaryFiles.Remove(file);
|
||||
log += Log(siteGroupMember, $"File Updated: {CreateLink(siteGroupMember.AliasName + "/" + secondaryFolder.Path + secondaryFile.Name)}");
|
||||
}
|
||||
}
|
||||
|
||||
if (file != null)
|
||||
{
|
||||
secondaryFiles.Remove(file);
|
||||
}
|
||||
}
|
||||
|
||||
// remove files in the secondary site which do not exist in the primary site
|
||||
foreach (var secondaryFile in secondaryFiles.Where(item => !primaryFiles.Select(item => item.Name).Contains(item.Name)))
|
||||
foreach (var secondaryFile in secondaryFiles)
|
||||
{
|
||||
if (siteGroup.Synchronize)
|
||||
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization)
|
||||
{
|
||||
fileRepository.DeleteFile(secondaryFile.FileId);
|
||||
var secondaryPath = Path.Combine(folderRepository.GetFolderPath(secondaryFolder), secondaryFile.Name);
|
||||
System.IO.File.Delete(secondaryPath);
|
||||
}
|
||||
log += Log(siteGroup, $"File Deleted: {CreateLink(siteGroup.AliasName + secondaryFolder.Path + secondaryFile.Name)}");
|
||||
log += Log(siteGroupMember, $"File Deleted: {CreateLink(siteGroupMember.AliasName + "/" + secondaryFolder.Path + secondaryFile.Name)}");
|
||||
}
|
||||
}
|
||||
|
||||
// remove folders in the secondary site which do not exist in the primary site
|
||||
foreach (var secondaryFolder in secondaryFolders.Where(item => !primaryFolders.Select(item => item.Path).Contains(item.Path)))
|
||||
foreach (var secondaryFolder in secondaryFolders)
|
||||
{
|
||||
if (siteGroup.Synchronize)
|
||||
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization)
|
||||
{
|
||||
folderRepository.DeleteFolder(secondaryFolder.FolderId);
|
||||
}
|
||||
log += Log(siteGroup, $"Folder Deleted: {secondaryFolder.Path}");
|
||||
log += Log(siteGroupMember, $"Folder Deleted: {secondaryFolder.Path}");
|
||||
}
|
||||
|
||||
return log;
|
||||
}
|
||||
|
||||
private void ReplicateFile(IFolderRepository folderRepository, Folder primaryFolder, Models.File primaryFile, Folder secondaryFolder, Models.File secondaryFile)
|
||||
private void SynchronizeFile(IFolderRepository folderRepository, Folder primaryFolder, Models.File primaryFile, Folder secondaryFolder, Models.File secondaryFile)
|
||||
{
|
||||
var primaryPath = Path.Combine(folderRepository.GetFolderPath(primaryFolder), primaryFile.Name);
|
||||
if (System.IO.File.Exists(primaryPath))
|
||||
@@ -430,7 +449,7 @@ namespace Oqtane.Infrastructure
|
||||
}
|
||||
}
|
||||
|
||||
private string ReplicatePages(IServiceProvider provider, ISettingRepository settingRepository, ITenantManager tenantManager, SiteGroup siteGroup, int primarySiteId, int secondarySiteId)
|
||||
private string SynchronizePages(IServiceProvider provider, ISettingRepository settingRepository, ITenantManager tenantManager, SiteGroupMember siteGroupMember, int primarySiteId, int secondarySiteId)
|
||||
{
|
||||
var pageRepository = provider.GetRequiredService<IPageRepository>();
|
||||
var pageModuleRepository = provider.GetRequiredService<IPageModuleRepository>();
|
||||
@@ -458,7 +477,7 @@ namespace Oqtane.Infrastructure
|
||||
secondaryPage.SiteId = secondarySiteId;
|
||||
}
|
||||
|
||||
if (page == null || primaryPage.ModifiedOn > siteGroup.SynchronizedOn)
|
||||
if (page == null || primaryPage.ModifiedOn > siteGroupMember.SynchronizedOn)
|
||||
{
|
||||
// set all properties
|
||||
secondaryPage.Path = primaryPage.Path;
|
||||
@@ -493,29 +512,33 @@ namespace Oqtane.Infrastructure
|
||||
secondaryPage.DeletedBy = primaryPage.DeletedBy;
|
||||
secondaryPage.DeletedOn = primaryPage.DeletedOn;
|
||||
secondaryPage.IsDeleted = primaryPage.IsDeleted;
|
||||
secondaryPage.PermissionList = ReplicatePermissions(primaryPage.PermissionList, secondarySiteId);
|
||||
secondaryPage.PermissionList = SynchronizePermissions(primaryPage.PermissionList, secondarySiteId);
|
||||
|
||||
if (page == null)
|
||||
{
|
||||
if (siteGroup.Synchronize)
|
||||
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization)
|
||||
{
|
||||
secondaryPage = pageRepository.AddPage(secondaryPage);
|
||||
}
|
||||
log += Log(siteGroup, $"Page Added: {CreateLink(siteGroup.AliasName + secondaryPage.Path)}");
|
||||
log += Log(siteGroupMember, $"Page Added: {CreateLink(siteGroupMember.AliasName + "/" + secondaryPage.Path)}");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (siteGroup.Synchronize)
|
||||
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization)
|
||||
{
|
||||
secondaryPage = pageRepository.UpdatePage(secondaryPage);
|
||||
}
|
||||
log += Log(siteGroup, $"Page Updated: {CreateLink(siteGroup.AliasName + secondaryPage.Path)}");
|
||||
secondaryPages.Remove(page);
|
||||
log += Log(siteGroupMember, $"Page Updated: {CreateLink(siteGroupMember.AliasName + "/" + secondaryPage.Path)}");
|
||||
}
|
||||
}
|
||||
|
||||
if (page != null)
|
||||
{
|
||||
secondaryPages.Remove(page);
|
||||
}
|
||||
|
||||
// page settings
|
||||
log += ReplicateSettings(settingRepository, siteGroup, EntityNames.Page, primaryPage.PageId, secondaryPage.PageId);
|
||||
log += SynchronizeSettings(settingRepository, siteGroupMember, EntityNames.Page, primaryPage.PageId, secondaryPage.PageId);
|
||||
|
||||
// modules
|
||||
if (primaryPageModules == null)
|
||||
@@ -542,7 +565,7 @@ namespace Oqtane.Infrastructure
|
||||
secondaryPageModule.Module.ModuleDefinitionName = primaryPageModule.Module.ModuleDefinitionName;
|
||||
}
|
||||
|
||||
if (pageModule == null || primaryPageModule.ModifiedOn > siteGroup.SynchronizedOn || primaryPageModule.Module.ModifiedOn > siteGroup.SynchronizedOn)
|
||||
if (pageModule == null || primaryPageModule.ModifiedOn > siteGroupMember.SynchronizedOn || primaryPageModule.Module.ModifiedOn > siteGroupMember.SynchronizedOn)
|
||||
{
|
||||
// set all properties
|
||||
secondaryPageModule.Title = primaryPageModule.Title;
|
||||
@@ -552,12 +575,10 @@ namespace Oqtane.Infrastructure
|
||||
secondaryPageModule.Header = primaryPageModule.Header;
|
||||
secondaryPageModule.Footer = primaryPageModule.Footer;
|
||||
secondaryPageModule.IsDeleted = primaryPageModule.IsDeleted;
|
||||
secondaryPageModule.Module.PermissionList = ReplicatePermissions(primaryPageModule.Module.PermissionList, secondarySiteId);
|
||||
secondaryPageModule.Module.PermissionList = SynchronizePermissions(primaryPageModule.Module.PermissionList, secondarySiteId);
|
||||
secondaryPageModule.Module.AllPages = false;
|
||||
secondaryPageModule.Module.IsDeleted = false;
|
||||
|
||||
var updateContent = false;
|
||||
|
||||
if (pageModule == null)
|
||||
{
|
||||
// check if module exists
|
||||
@@ -565,78 +586,79 @@ namespace Oqtane.Infrastructure
|
||||
if (module == null)
|
||||
{
|
||||
// add new module
|
||||
if (siteGroup.Synchronize)
|
||||
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization)
|
||||
{
|
||||
module = moduleRepository.AddModule(secondaryPageModule.Module);
|
||||
updateContent = true;
|
||||
}
|
||||
log += Log(siteGroup, $"Module Added: {module.Title} - {CreateLink(siteGroup.AliasName + secondaryPage.Path)}");
|
||||
log += Log(siteGroupMember, $"Module Added: {secondaryPageModule.Title} - {CreateLink(siteGroupMember.AliasName + "/" + secondaryPage.Path)}");
|
||||
}
|
||||
if (module != null)
|
||||
{
|
||||
secondaryPageModule.ModuleId = module.ModuleId;
|
||||
secondaryPageModule.Module = null; // remove tracking
|
||||
if (siteGroup.Synchronize)
|
||||
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization)
|
||||
{
|
||||
secondaryPageModule = pageModuleRepository.AddPageModule(secondaryPageModule);
|
||||
}
|
||||
log += Log(siteGroup, $"Module Instance Added: {module.Title} - {CreateLink(siteGroup.AliasName + secondaryPage.Path)}");
|
||||
log += Log(siteGroupMember, $"Module Instance Added: {secondaryPageModule.Title} - {CreateLink(siteGroupMember.AliasName + "/" + secondaryPage.Path)}");
|
||||
secondaryPageModule.Module = module;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// update existing module
|
||||
if (primaryPageModule.Module.ModifiedOn > siteGroup.SynchronizedOn)
|
||||
if (primaryPageModule.Module.ModifiedOn > siteGroupMember.SynchronizedOn)
|
||||
{
|
||||
if (siteGroup.Synchronize)
|
||||
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization)
|
||||
{
|
||||
moduleRepository.UpdateModule(secondaryPageModule.Module);
|
||||
updateContent = true;
|
||||
}
|
||||
log += Log(siteGroup, $"Module Updated: {secondaryPageModule.Title} - {CreateLink(siteGroup.AliasName + secondaryPage.Path)}");
|
||||
log += Log(siteGroupMember, $"Module Updated: {secondaryPageModule.Title} - {CreateLink(siteGroupMember.AliasName + "/" + secondaryPage.Path)}");
|
||||
}
|
||||
if (primaryPageModule.ModifiedOn > siteGroup.SynchronizedOn)
|
||||
if (primaryPageModule.ModifiedOn > siteGroupMember.SynchronizedOn)
|
||||
{
|
||||
if (siteGroup.Synchronize)
|
||||
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization)
|
||||
{
|
||||
secondaryPageModule = pageModuleRepository.UpdatePageModule(secondaryPageModule);
|
||||
}
|
||||
log += Log(siteGroup, $"Module Instance Updated: {secondaryPageModule.Title} - {CreateLink(siteGroup.AliasName + secondaryPage.Path)}");
|
||||
secondaryPageModules.Remove(pageModule);
|
||||
}
|
||||
}
|
||||
|
||||
// module content
|
||||
if (updateContent && primaryPageModule.Module.ModuleDefinition.ServerManagerType != "")
|
||||
{
|
||||
Type moduleType = Type.GetType(primaryPageModule.Module.ModuleDefinition.ServerManagerType);
|
||||
if (moduleType != null && moduleType.GetInterface(nameof(ISynchronizable)) != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var moduleObject = ActivatorUtilities.CreateInstance(provider, moduleType);
|
||||
var primaryModuleContent = ((ISynchronizable)moduleObject).ExtractModule(primaryPageModule.Module);
|
||||
var secondaryModuleContent = ((ISynchronizable)moduleObject).ExtractModule(secondaryPageModule.Module);
|
||||
if (primaryModuleContent != secondaryModuleContent)
|
||||
{
|
||||
if (siteGroup.Synchronize)
|
||||
{
|
||||
((ISynchronizable)moduleObject).LoadModule(secondaryPageModule.Module, primaryModuleContent, primaryPageModule.Module.ModuleDefinition.Version);
|
||||
}
|
||||
log += Log(siteGroup, $"Module Content Updated: {secondaryPageModule.Title} - {CreateLink(siteGroup.AliasName + secondaryPage.Path)}");
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// error exporting/importing
|
||||
}
|
||||
log += Log(siteGroupMember, $"Module Instance Updated: {secondaryPageModule.Title} - {CreateLink(siteGroupMember.AliasName + "/" + secondaryPage.Path)}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// module content
|
||||
if (primaryPageModule.Module.ModuleDefinition.ServerManagerType != "")
|
||||
{
|
||||
Type moduleType = Type.GetType(primaryPageModule.Module.ModuleDefinition.ServerManagerType);
|
||||
if (moduleType != null && moduleType.GetInterface(nameof(ISynchronizable)) != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var moduleObject = ActivatorUtilities.CreateInstance(provider, moduleType);
|
||||
var moduleContent = ((ISynchronizable)moduleObject).ExtractModule(primaryPageModule.Module, siteGroupMember.SynchronizedOn.Value);
|
||||
if (!string.IsNullOrEmpty(moduleContent))
|
||||
{
|
||||
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization)
|
||||
{
|
||||
((ISynchronizable)moduleObject).LoadModule(secondaryPageModule.Module, moduleContent);
|
||||
}
|
||||
log += Log(siteGroupMember, $"Module Content Updated: {secondaryPageModule.Title} - {CreateLink(siteGroupMember.AliasName + "/" + secondaryPage.Path)}");
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// error exporting/importing
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pageModule != null)
|
||||
{
|
||||
secondaryPageModules.Remove(pageModule);
|
||||
}
|
||||
|
||||
// module settings
|
||||
log += ReplicateSettings(settingRepository, siteGroup, EntityNames.Module, primaryPageModule.ModuleId, secondaryPageModule.ModuleId);
|
||||
log += SynchronizeSettings(settingRepository, siteGroupMember, EntityNames.Module, primaryPageModule.ModuleId, secondaryPageModule.ModuleId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -655,27 +677,27 @@ namespace Oqtane.Infrastructure
|
||||
}
|
||||
if (!primaryPageModules.Any(item => item.PageId == primaryPageId && item.Module.ModuleDefinitionName == secondaryPageModule.Module.ModuleDefinitionName && item.Title.ToLower() == secondaryPageModule.Title.ToLower()))
|
||||
{
|
||||
if (siteGroup.Synchronize)
|
||||
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization)
|
||||
{
|
||||
pageModuleRepository.DeletePageModule(secondaryPageModule.PageModuleId);
|
||||
}
|
||||
log += Log(siteGroup, $"Module Instance Deleted: {secondaryPageModule.Title} - {CreateLink(siteGroup.AliasName + secondaryPageModule.Page.Path)}");
|
||||
log += Log(siteGroupMember, $"Module Instance Deleted: {secondaryPageModule.Title} - {CreateLink(siteGroupMember.AliasName + "/" + secondaryPageModule.Page.Path)}");
|
||||
}
|
||||
}
|
||||
|
||||
// remove pages in the secondary site which do not exist in the primary site
|
||||
foreach (var secondaryPage in secondaryPages.Where(item => !primaryPages.Select(item => item.Path).Contains(item.Path)))
|
||||
foreach (var secondaryPage in secondaryPages)
|
||||
{
|
||||
if (siteGroup.Synchronize)
|
||||
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization)
|
||||
{
|
||||
pageRepository.DeletePage(secondaryPage.PageId);
|
||||
}
|
||||
log += Log(siteGroup, $"Page Deleted: {CreateLink(siteGroup.AliasName + secondaryPage.Path)}");
|
||||
log += Log(siteGroupMember, $"Page Deleted: {CreateLink(siteGroupMember.AliasName + "/" + secondaryPage.Path)}");
|
||||
}
|
||||
|
||||
if (siteGroup.SynchronizedOn == DateTime.MinValue || !string.IsNullOrEmpty(log))
|
||||
if (siteGroupMember.SynchronizedOn == DateTime.MinValue || !string.IsNullOrEmpty(log))
|
||||
{
|
||||
// clear cache for secondary site if any content was replicated
|
||||
// clear cache for secondary site if any content was Synchronized
|
||||
var syncManager = provider.GetRequiredService<ISyncManager>();
|
||||
var alias = new Alias { TenantId = tenantManager.GetTenant().TenantId, SiteId = secondarySiteId };
|
||||
syncManager.AddSyncEvent(alias, EntityNames.Site, secondarySiteId, SyncEventActions.Refresh);
|
||||
@@ -684,7 +706,7 @@ namespace Oqtane.Infrastructure
|
||||
return log;
|
||||
}
|
||||
|
||||
private List<Permission> ReplicatePermissions(List<Permission> permissionList, int siteId)
|
||||
private List<Permission> SynchronizePermissions(List<Permission> permissionList, int siteId)
|
||||
{
|
||||
return permissionList.Select(item => new Permission
|
||||
{
|
||||
@@ -700,7 +722,7 @@ namespace Oqtane.Infrastructure
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
private string ReplicateSettings(ISettingRepository settingRepository, SiteGroup siteGroup, string entityName, int primaryEntityId, int secondaryEntityId)
|
||||
private string SynchronizeSettings(ISettingRepository settingRepository, SiteGroupMember siteGroupMember, string entityName, int primaryEntityId, int secondaryEntityId)
|
||||
{
|
||||
var log = "";
|
||||
var updated = false;
|
||||
@@ -717,7 +739,7 @@ namespace Oqtane.Infrastructure
|
||||
secondarySetting.SettingName = primarySetting.SettingName;
|
||||
secondarySetting.SettingValue = primarySetting.SettingValue;
|
||||
secondarySetting.IsPrivate = primarySetting.IsPrivate;
|
||||
if (siteGroup.Synchronize && !excludedSettings.Any(item => item.EntityName == secondarySetting.EntityName && item.SettingName == secondarySetting.SettingName))
|
||||
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization && !excludedSettings.Any(item => item.EntityName == secondarySetting.EntityName && item.SettingName == secondarySetting.SettingName))
|
||||
{
|
||||
settingRepository.AddSetting(secondarySetting);
|
||||
updated = true;
|
||||
@@ -729,7 +751,7 @@ namespace Oqtane.Infrastructure
|
||||
{
|
||||
secondarySetting.SettingValue = primarySetting.SettingValue;
|
||||
secondarySetting.IsPrivate = primarySetting.IsPrivate;
|
||||
if (siteGroup.Synchronize && !excludedSettings.Any(item => item.EntityName == secondarySetting.EntityName && item.SettingName == secondarySetting.SettingName))
|
||||
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization && !excludedSettings.Any(item => item.EntityName == secondarySetting.EntityName && item.SettingName == secondarySetting.SettingName))
|
||||
{
|
||||
settingRepository.UpdateSetting(secondarySetting);
|
||||
updated = true;
|
||||
@@ -742,7 +764,7 @@ namespace Oqtane.Infrastructure
|
||||
// any remaining secondary settings need to be deleted
|
||||
foreach (var secondarySetting in secondarySettings)
|
||||
{
|
||||
if (siteGroup.Synchronize && !excludedSettings.Any(item => item.EntityName == secondarySetting.EntityName && item.SettingName == secondarySetting.SettingName))
|
||||
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization && !excludedSettings.Any(item => item.EntityName == secondarySetting.EntityName && item.SettingName == secondarySetting.SettingName))
|
||||
{
|
||||
settingRepository.DeleteSetting(secondarySetting.EntityName, secondarySetting.SettingId);
|
||||
updated = true;
|
||||
@@ -751,7 +773,7 @@ namespace Oqtane.Infrastructure
|
||||
|
||||
if (updated)
|
||||
{
|
||||
log += Log(siteGroup, $"{entityName} Settings Updated");
|
||||
log += Log(siteGroupMember, $"{entityName} Settings Updated");
|
||||
}
|
||||
|
||||
return log;
|
||||
@@ -769,10 +791,10 @@ namespace Oqtane.Infrastructure
|
||||
}
|
||||
}
|
||||
|
||||
private string Log(SiteGroup siteGroup, string content)
|
||||
private string Log(SiteGroupMember siteGroupMember, string content)
|
||||
{
|
||||
// not necessary to log initial replication
|
||||
if (siteGroup.SynchronizedOn != DateTime.MinValue)
|
||||
// not necessary to log initial synchronization
|
||||
if (siteGroupMember.SynchronizedOn != DateTime.MinValue)
|
||||
{
|
||||
return content + "<br />";
|
||||
}
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Migrations.Operations;
|
||||
using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders;
|
||||
using Oqtane.Databases.Interfaces;
|
||||
|
||||
// ReSharper disable MemberCanBePrivate.Global
|
||||
// ReSharper disable UnusedAutoPropertyAccessor.Global
|
||||
|
||||
namespace Oqtane.Migrations.EntityBuilders
|
||||
{
|
||||
public class SiteGroupDefinitionEntityBuilder : AuditableBaseEntityBuilder<SiteGroupDefinitionEntityBuilder>
|
||||
{
|
||||
private const string _entityTableName = "SiteGroupDefinition";
|
||||
private readonly PrimaryKey<SiteGroupDefinitionEntityBuilder> _primaryKey = new("PK_SiteGroupDefinition", x => x.SiteGroupDefinitionId);
|
||||
|
||||
public SiteGroupDefinitionEntityBuilder(MigrationBuilder migrationBuilder, IDatabase database) : base(migrationBuilder, database)
|
||||
{
|
||||
EntityTableName = _entityTableName;
|
||||
PrimaryKey = _primaryKey;
|
||||
}
|
||||
|
||||
protected override SiteGroupDefinitionEntityBuilder BuildTable(ColumnsBuilder table)
|
||||
{
|
||||
SiteGroupDefinitionId = AddAutoIncrementColumn(table, "SiteGroupDefinitionId");
|
||||
Name = AddStringColumn(table, "Name", 200);
|
||||
PrimarySiteId = AddIntegerColumn(table, "PrimarySiteId");
|
||||
Synchronization = AddBooleanColumn(table, "Synchronization");
|
||||
Synchronize = AddBooleanColumn(table, "Synchronize");
|
||||
Localization = AddBooleanColumn(table, "Localization");
|
||||
|
||||
AddAuditableColumns(table);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public OperationBuilder<AddColumnOperation> SiteGroupDefinitionId { get; set; }
|
||||
|
||||
public OperationBuilder<AddColumnOperation> Name { get; set; }
|
||||
|
||||
public OperationBuilder<AddColumnOperation> PrimarySiteId { get; set; }
|
||||
|
||||
public OperationBuilder<AddColumnOperation> Synchronization { get; set; }
|
||||
|
||||
public OperationBuilder<AddColumnOperation> Synchronize { get; set; }
|
||||
|
||||
public OperationBuilder<AddColumnOperation> Localization { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -12,25 +12,20 @@ namespace Oqtane.Migrations.EntityBuilders
|
||||
{
|
||||
private const string _entityTableName = "SiteGroup";
|
||||
private readonly PrimaryKey<SiteGroupEntityBuilder> _primaryKey = new("PK_SiteGroup", x => x.SiteGroupId);
|
||||
private readonly ForeignKey<SiteGroupEntityBuilder> _groupForeignKey = new("FK_SiteGroup_SiteGroupDefinition", x => x.SiteGroupDefinitionId, "SiteGroupDefinition", "SiteGroupDefinitionId", ReferentialAction.Cascade);
|
||||
private readonly ForeignKey<SiteGroupEntityBuilder> _siteForeignKey = new("FK_SiteGroup_Site", x => x.SiteId, "Site", "SiteId", ReferentialAction.Cascade);
|
||||
|
||||
public SiteGroupEntityBuilder(MigrationBuilder migrationBuilder, IDatabase database) : base(migrationBuilder, database)
|
||||
{
|
||||
EntityTableName = _entityTableName;
|
||||
PrimaryKey = _primaryKey;
|
||||
ForeignKeys.Add(_groupForeignKey);
|
||||
ForeignKeys.Add(_siteForeignKey);
|
||||
}
|
||||
|
||||
protected override SiteGroupEntityBuilder BuildTable(ColumnsBuilder table)
|
||||
{
|
||||
SiteGroupId = AddAutoIncrementColumn(table, "SiteGroupId");
|
||||
SiteGroupDefinitionId = AddIntegerColumn(table, "SiteGroupDefinitionId");
|
||||
SiteId = AddIntegerColumn(table, "SiteId");
|
||||
Name = AddStringColumn(table, "Name", 200);
|
||||
Type = AddStringColumn(table, "Type", 50);
|
||||
PrimarySiteId = AddIntegerColumn(table, "PrimarySiteId");
|
||||
Synchronize = AddBooleanColumn(table, "Synchronize");
|
||||
Notify = AddBooleanColumn(table, "Notify");
|
||||
SynchronizedOn = AddDateTimeColumn(table, "SynchronizedOn", true);
|
||||
|
||||
AddAuditableColumns(table);
|
||||
|
||||
@@ -39,14 +34,12 @@ namespace Oqtane.Migrations.EntityBuilders
|
||||
|
||||
public OperationBuilder<AddColumnOperation> SiteGroupId { get; set; }
|
||||
|
||||
public OperationBuilder<AddColumnOperation> SiteGroupDefinitionId { get; set; }
|
||||
public OperationBuilder<AddColumnOperation> Name { get; set; }
|
||||
|
||||
public OperationBuilder<AddColumnOperation> SiteId { get; set; }
|
||||
public OperationBuilder<AddColumnOperation> Type { get; set; }
|
||||
|
||||
public OperationBuilder<AddColumnOperation> PrimarySiteId { get; set; }
|
||||
|
||||
public OperationBuilder<AddColumnOperation> Synchronize { get; set; }
|
||||
|
||||
public OperationBuilder<AddColumnOperation> Notify { get; set; }
|
||||
|
||||
public OperationBuilder<AddColumnOperation> SynchronizedOn { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Migrations.Operations;
|
||||
using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders;
|
||||
using Oqtane.Databases.Interfaces;
|
||||
|
||||
// ReSharper disable MemberCanBePrivate.Global
|
||||
// ReSharper disable UnusedAutoPropertyAccessor.Global
|
||||
|
||||
namespace Oqtane.Migrations.EntityBuilders
|
||||
{
|
||||
public class SiteGroupMemberEntityBuilder : AuditableBaseEntityBuilder<SiteGroupMemberEntityBuilder>
|
||||
{
|
||||
private const string _entityTableName = "SiteGroupMember";
|
||||
private readonly PrimaryKey<SiteGroupMemberEntityBuilder> _primaryKey = new("PK_SiteGroupMember", x => x.SiteGroupMemberId);
|
||||
private readonly ForeignKey<SiteGroupMemberEntityBuilder> _groupForeignKey = new("FK_SiteGroupMember_SiteGroup", x => x.SiteGroupId, "SiteGroup", "SiteGroupId", ReferentialAction.Cascade);
|
||||
private readonly ForeignKey<SiteGroupMemberEntityBuilder> _siteForeignKey = new("FK_SiteGroupMember_Site", x => x.SiteId, "Site", "SiteId", ReferentialAction.Cascade);
|
||||
|
||||
public SiteGroupMemberEntityBuilder(MigrationBuilder migrationBuilder, IDatabase database) : base(migrationBuilder, database)
|
||||
{
|
||||
EntityTableName = _entityTableName;
|
||||
PrimaryKey = _primaryKey;
|
||||
ForeignKeys.Add(_groupForeignKey);
|
||||
ForeignKeys.Add(_siteForeignKey);
|
||||
}
|
||||
|
||||
protected override SiteGroupMemberEntityBuilder BuildTable(ColumnsBuilder table)
|
||||
{
|
||||
SiteGroupMemberId = AddAutoIncrementColumn(table, "SiteGroupMemberId");
|
||||
SiteGroupId = AddIntegerColumn(table, "SiteGroupId");
|
||||
SiteId = AddIntegerColumn(table, "SiteId");
|
||||
SynchronizedOn = AddDateTimeColumn(table, "SynchronizedOn", true);
|
||||
|
||||
AddAuditableColumns(table);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public OperationBuilder<AddColumnOperation> SiteGroupMemberId { get; set; }
|
||||
|
||||
public OperationBuilder<AddColumnOperation> SiteGroupId { get; set; }
|
||||
|
||||
public OperationBuilder<AddColumnOperation> SiteId { get; set; }
|
||||
|
||||
public OperationBuilder<AddColumnOperation> SynchronizedOn { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -16,12 +16,12 @@ namespace Oqtane.Migrations.Tenant
|
||||
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
var siteGroupDefinitionEntityBuilder = new SiteGroupDefinitionEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||
siteGroupDefinitionEntityBuilder.Create();
|
||||
|
||||
var siteGroupEntityBuilder = new SiteGroupEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||
siteGroupEntityBuilder.Create();
|
||||
siteGroupEntityBuilder.AddIndex("IX_SiteGroup", new[] { "SiteId", "SiteGroupDefinitionId" }, true);
|
||||
|
||||
var siteGroupMemberEntityBuilder = new SiteGroupMemberEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||
siteGroupMemberEntityBuilder.Create();
|
||||
siteGroupMemberEntityBuilder.AddIndex("IX_SiteGroupMember", new[] { "SiteId", "SiteGroupId" }, true);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
|
||||
@@ -59,39 +59,50 @@ namespace Oqtane.Modules.HtmlText.Manager
|
||||
|
||||
// IPortable implementation
|
||||
public string ExportModule(Module module)
|
||||
{
|
||||
return GetModuleContent(module);
|
||||
}
|
||||
|
||||
public void ImportModule(Module module, string content, string version)
|
||||
{
|
||||
SaveModuleContent(module, content, version);
|
||||
}
|
||||
|
||||
// ISynchronizable implementation
|
||||
public string ExtractModule(Module module)
|
||||
{
|
||||
return GetModuleContent(module);
|
||||
}
|
||||
|
||||
public void LoadModule(Module module, string content, string version)
|
||||
{
|
||||
SaveModuleContent(module, content, version);
|
||||
}
|
||||
|
||||
private string GetModuleContent(Module module)
|
||||
{
|
||||
string content = "";
|
||||
var htmltexts = _htmlText.GetHtmlTexts(module.ModuleId);
|
||||
if (htmltexts != null && htmltexts.Any())
|
||||
var htmltext = GetModuleContent(module.ModuleId);
|
||||
if (htmltext != null)
|
||||
{
|
||||
var htmltext = htmltexts.OrderByDescending(item => item.CreatedOn).First();
|
||||
content = WebUtility.HtmlEncode(htmltext.Content);
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
private void SaveModuleContent(Module module, string content, string version)
|
||||
public void ImportModule(Module module, string content, string version)
|
||||
{
|
||||
SaveModuleContent(module, content);
|
||||
}
|
||||
|
||||
// ISynchronizable implementation
|
||||
public string ExtractModule(Module module, DateTime lastSynchronizedOn)
|
||||
{
|
||||
string content = "";
|
||||
var htmltext = GetModuleContent(module.ModuleId);
|
||||
if (htmltext != null && htmltext.CreatedOn > lastSynchronizedOn)
|
||||
{
|
||||
content = WebUtility.HtmlEncode(htmltext.Content);
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
public void LoadModule(Module module, string content)
|
||||
{
|
||||
SaveModuleContent(module, content);
|
||||
}
|
||||
|
||||
private Models.HtmlText GetModuleContent(int moduleId)
|
||||
{
|
||||
// get the most recent htmltext record for the module
|
||||
var htmltexts = _htmlText.GetHtmlTexts(moduleId);
|
||||
if (htmltexts != null && htmltexts.Any())
|
||||
{
|
||||
return htmltexts.OrderByDescending(item => item.CreatedOn).First();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void SaveModuleContent(Module module, string content)
|
||||
{
|
||||
content = WebUtility.HtmlDecode(content);
|
||||
var htmlText = new Models.HtmlText();
|
||||
|
||||
@@ -2,7 +2,6 @@ using System.Linq;
|
||||
using Oqtane.Documentation;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Oqtane.Repository;
|
||||
|
||||
namespace Oqtane.Modules.HtmlText.Repository
|
||||
{
|
||||
@@ -19,12 +18,10 @@ namespace Oqtane.Modules.HtmlText.Repository
|
||||
public class HtmlTextRepository : IHtmlTextRepository, ITransientService
|
||||
{
|
||||
private readonly IDbContextFactory<HtmlTextContext> _factory;
|
||||
private readonly IModuleRepository _moduleRepository;
|
||||
|
||||
public HtmlTextRepository(IDbContextFactory<HtmlTextContext> factory, IModuleRepository moduleRepository)
|
||||
public HtmlTextRepository(IDbContextFactory<HtmlTextContext> factory)
|
||||
{
|
||||
_factory = factory;
|
||||
_moduleRepository = moduleRepository;
|
||||
}
|
||||
|
||||
public IEnumerable<Models.HtmlText> GetHtmlTexts(int moduleId)
|
||||
@@ -44,11 +41,6 @@ namespace Oqtane.Modules.HtmlText.Repository
|
||||
using var db = _factory.CreateDbContext();
|
||||
db.HtmlText.Add(htmlText);
|
||||
db.SaveChanges();
|
||||
|
||||
// update module ModifiedOn date
|
||||
var module = _moduleRepository.GetModule(htmlText.ModuleId);
|
||||
_moduleRepository.UpdateModule(module);
|
||||
|
||||
return htmlText;
|
||||
}
|
||||
|
||||
@@ -60,10 +52,6 @@ namespace Oqtane.Modules.HtmlText.Repository
|
||||
{
|
||||
db.HtmlText.Remove(htmlText);
|
||||
db.SaveChanges();
|
||||
|
||||
// update module ModifiedOn date
|
||||
var module = _moduleRepository.GetModule(htmlText.ModuleId);
|
||||
_moduleRepository.UpdateModule(module);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using Oqtane.Models;
|
||||
|
||||
namespace Oqtane.Modules
|
||||
@@ -6,8 +7,8 @@ namespace Oqtane.Modules
|
||||
{
|
||||
// You Must Set The "ServerManagerType" In Your IModule Interface
|
||||
|
||||
string ExtractModule(Module module);
|
||||
string ExtractModule(Module module, DateTime lastSynchronizedOn);
|
||||
|
||||
void LoadModule(Module module, string content, string version);
|
||||
void LoadModule(Module module, string content);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,28 +28,28 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="10.0.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="10.0.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="10.0.2" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="10.0.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="10.0.3" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="10.0.3" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="10.0.3" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="10.0.3" />
|
||||
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.12" />
|
||||
<PackageReference Include="HtmlAgilityPack" Version="1.12.4" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="10.1.0" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="10.1.2" />
|
||||
<PackageReference Include="MailKit" Version="4.14.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!-- MySQL Database Provider Dependencies -->
|
||||
<PackageReference Include="MySql.Data" Version="9.5.0" />
|
||||
<PackageReference Include="MySql.EntityFrameworkCore" Version="10.0.0-rc" />
|
||||
<PackageReference Include="MySql.Data" Version="9.6.0" />
|
||||
<PackageReference Include="MySql.EntityFrameworkCore" Version="10.0.1" />
|
||||
<!-- PostgreSQL Database Provider Dependencies -->
|
||||
<PackageReference Include="EFCore.NamingConventions" Version="10.0.0" />
|
||||
<PackageReference Include="EFCore.NamingConventions" Version="10.0.1" />
|
||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="10.0.0" />
|
||||
<!-- SQLite Database Provider Dependencies -->
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.2" />
|
||||
<PackageReference Include="Microsoft.Data.Sqlite.Core" Version="10.0.2" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.3" />
|
||||
<PackageReference Include="Microsoft.Data.Sqlite.Core" Version="10.0.3" />
|
||||
<!-- SQL Server Database Provider Dependencies -->
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="10.0.2" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="10.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Suppress EF Core internal warnings for Database Providers -->
|
||||
|
||||
@@ -134,7 +134,7 @@ namespace Oqtane.Repository
|
||||
public virtual DbSet<SearchContentWord> SearchContentWord { get; set; }
|
||||
public virtual DbSet<SearchWord> SearchWord { get; set; }
|
||||
public virtual DbSet<MigrationHistory> MigrationHistory { get; set; }
|
||||
public virtual DbSet<SiteGroupDefinition> SiteGroupDefinition { get; set; }
|
||||
public virtual DbSet<SiteGroup> SiteGroup { get; set; }
|
||||
public virtual DbSet<SiteGroupMember> SiteGroupMember { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Oqtane.Models;
|
||||
|
||||
namespace Oqtane.Repository
|
||||
{
|
||||
public interface ISiteGroupDefinitionRepository
|
||||
{
|
||||
IEnumerable<SiteGroupDefinition> GetSiteGroupDefinitions();
|
||||
SiteGroupDefinition AddSiteGroupDefinition(SiteGroupDefinition siteGroupDefinition);
|
||||
SiteGroupDefinition UpdateSiteGroupDefinition(SiteGroupDefinition siteGroupDefinition);
|
||||
SiteGroupDefinition GetSiteGroupDefinition(int siteGroupDefinitionId);
|
||||
SiteGroupDefinition GetSiteGroupDefinition(int siteGroupDefinitionId, bool tracking);
|
||||
void DeleteSiteGroupDefinition(int siteGroupDefinitionId);
|
||||
}
|
||||
|
||||
public class SiteGroupDefinitionRepository : ISiteGroupDefinitionRepository
|
||||
{
|
||||
private readonly IDbContextFactory<TenantDBContext> _dbContextFactory;
|
||||
|
||||
public SiteGroupDefinitionRepository(IDbContextFactory<TenantDBContext> dbContextFactory)
|
||||
{
|
||||
_dbContextFactory = dbContextFactory;
|
||||
}
|
||||
|
||||
public IEnumerable<SiteGroupDefinition> GetSiteGroupDefinitions()
|
||||
{
|
||||
using var db = _dbContextFactory.CreateDbContext();
|
||||
return db.SiteGroupDefinition.ToList();
|
||||
}
|
||||
|
||||
public SiteGroupDefinition AddSiteGroupDefinition(SiteGroupDefinition siteGroupDefinition)
|
||||
{
|
||||
using var db = _dbContextFactory.CreateDbContext();
|
||||
db.SiteGroupDefinition.Add(siteGroupDefinition);
|
||||
db.SaveChanges();
|
||||
return siteGroupDefinition;
|
||||
}
|
||||
|
||||
public SiteGroupDefinition UpdateSiteGroupDefinition(SiteGroupDefinition siteGroupDefinition)
|
||||
{
|
||||
using var db = _dbContextFactory.CreateDbContext();
|
||||
db.Entry(siteGroupDefinition).State = EntityState.Modified;
|
||||
db.SaveChanges();
|
||||
return siteGroupDefinition;
|
||||
}
|
||||
|
||||
public SiteGroupDefinition GetSiteGroupDefinition(int siteGroupDefinitionId)
|
||||
{
|
||||
return GetSiteGroupDefinition(siteGroupDefinitionId, true);
|
||||
}
|
||||
|
||||
public SiteGroupDefinition GetSiteGroupDefinition(int siteGroupDefinitionId, bool tracking)
|
||||
{
|
||||
using var db = _dbContextFactory.CreateDbContext();
|
||||
if (tracking)
|
||||
{
|
||||
return db.SiteGroupDefinition.FirstOrDefault(item => item.SiteGroupDefinitionId == siteGroupDefinitionId);
|
||||
}
|
||||
else
|
||||
{
|
||||
return db.SiteGroupDefinition.AsNoTracking().FirstOrDefault(item => item.SiteGroupDefinitionId == siteGroupDefinitionId);
|
||||
}
|
||||
}
|
||||
|
||||
public void DeleteSiteGroupDefinition(int siteGroupDefinitionId)
|
||||
{
|
||||
using var db = _dbContextFactory.CreateDbContext();
|
||||
SiteGroupDefinition group = db.SiteGroupDefinition.Find(siteGroupDefinitionId);
|
||||
db.SiteGroupDefinition.Remove(group);
|
||||
db.SaveChanges();
|
||||
}
|
||||
}
|
||||
}
|
||||
88
Oqtane.Server/Repository/SiteGroupMemberRepository.cs
Normal file
88
Oqtane.Server/Repository/SiteGroupMemberRepository.cs
Normal file
@@ -0,0 +1,88 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Oqtane.Models;
|
||||
|
||||
namespace Oqtane.Repository
|
||||
{
|
||||
public interface ISiteGroupMemberRepository
|
||||
{
|
||||
IEnumerable<SiteGroupMember> GetSiteGroupMembers();
|
||||
IEnumerable<SiteGroupMember> GetSiteGroupMembers(int siteId, int siteGroupId);
|
||||
SiteGroupMember AddSiteGroupMember(SiteGroupMember siteGroupMember);
|
||||
SiteGroupMember UpdateSiteGroupMember(SiteGroupMember siteGroupMember);
|
||||
SiteGroupMember GetSiteGroupMember(int siteGroupMemberId);
|
||||
SiteGroupMember GetSiteGroupMember(int siteGroupMemberId, bool tracking);
|
||||
void DeleteSiteGroupMember(int siteGroupMemberId);
|
||||
}
|
||||
|
||||
public class SiteGroupMemberRepository : ISiteGroupMemberRepository
|
||||
{
|
||||
private readonly IDbContextFactory<TenantDBContext> _dbContextFactory;
|
||||
|
||||
public SiteGroupMemberRepository(IDbContextFactory<TenantDBContext> dbContextFactory)
|
||||
{
|
||||
_dbContextFactory = dbContextFactory;
|
||||
}
|
||||
|
||||
public IEnumerable<SiteGroupMember> GetSiteGroupMembers()
|
||||
{
|
||||
return GetSiteGroupMembers(-1, -1);
|
||||
}
|
||||
|
||||
public IEnumerable<SiteGroupMember> GetSiteGroupMembers(int siteId, int siteGroupId)
|
||||
{
|
||||
using var db = _dbContextFactory.CreateDbContext();
|
||||
return db.SiteGroupMember
|
||||
.Where(item => (siteId == -1 || item.SiteId == siteId) && (siteGroupId == -1 || item.SiteGroupId == siteGroupId))
|
||||
.Include(item => item.SiteGroup) // eager load
|
||||
.ToList();
|
||||
}
|
||||
|
||||
public SiteGroupMember AddSiteGroupMember(SiteGroupMember siteGroupMember)
|
||||
{
|
||||
using var db = _dbContextFactory.CreateDbContext();
|
||||
db.SiteGroupMember.Add(siteGroupMember);
|
||||
db.SaveChanges();
|
||||
return siteGroupMember;
|
||||
}
|
||||
|
||||
public SiteGroupMember UpdateSiteGroupMember(SiteGroupMember siteGroupMember)
|
||||
{
|
||||
using var db = _dbContextFactory.CreateDbContext();
|
||||
db.Entry(siteGroupMember).State = EntityState.Modified;
|
||||
db.SaveChanges();
|
||||
return siteGroupMember;
|
||||
}
|
||||
|
||||
public SiteGroupMember GetSiteGroupMember(int siteGroupMemberId)
|
||||
{
|
||||
return GetSiteGroupMember(siteGroupMemberId, true);
|
||||
}
|
||||
|
||||
public SiteGroupMember GetSiteGroupMember(int siteGroupMemberId, bool tracking)
|
||||
{
|
||||
using var db = _dbContextFactory.CreateDbContext();
|
||||
if (tracking)
|
||||
{
|
||||
return db.SiteGroupMember
|
||||
.Include(item => item.SiteGroup) // eager load
|
||||
.FirstOrDefault(item => item.SiteGroupMemberId == siteGroupMemberId);
|
||||
}
|
||||
else
|
||||
{
|
||||
return db.SiteGroupMember.AsNoTracking()
|
||||
.Include(item => item.SiteGroup) // eager load
|
||||
.FirstOrDefault(item => item.SiteGroupMemberId == siteGroupMemberId);
|
||||
}
|
||||
}
|
||||
|
||||
public void DeleteSiteGroupMember(int siteGroupMemberId)
|
||||
{
|
||||
using var db = _dbContextFactory.CreateDbContext();
|
||||
SiteGroupMember SiteGroupMember = db.SiteGroupMember.Find(siteGroupMemberId);
|
||||
db.SiteGroupMember.Remove(SiteGroupMember);
|
||||
db.SaveChanges();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,12 +8,11 @@ namespace Oqtane.Repository
|
||||
public interface ISiteGroupRepository
|
||||
{
|
||||
IEnumerable<SiteGroup> GetSiteGroups();
|
||||
IEnumerable<SiteGroup> GetSiteGroups(int siteId, int siteGroupDefinitionId);
|
||||
SiteGroup AddSiteGroup(SiteGroup siteGroup);
|
||||
SiteGroup UpdateSiteGroup(SiteGroup siteGroup);
|
||||
SiteGroup GetSiteGroup(int siteSiteGroupId);
|
||||
SiteGroup GetSiteGroup(int siteSiteGroupId, bool tracking);
|
||||
void DeleteSiteGroup(int siteSiteGroupId);
|
||||
SiteGroup GetSiteGroup(int siteGroupId);
|
||||
SiteGroup GetSiteGroup(int siteGroupId, bool tracking);
|
||||
void DeleteSiteGroup(int siteGroupId);
|
||||
}
|
||||
|
||||
public class SiteGroupRepository : ISiteGroupRepository
|
||||
@@ -27,61 +26,49 @@ namespace Oqtane.Repository
|
||||
|
||||
public IEnumerable<SiteGroup> GetSiteGroups()
|
||||
{
|
||||
return GetSiteGroups(-1, -1);
|
||||
using var db = _dbContextFactory.CreateDbContext();
|
||||
return db.SiteGroup.ToList();
|
||||
}
|
||||
|
||||
public IEnumerable<SiteGroup> GetSiteGroups(int siteId, int siteGroupDefinitionId)
|
||||
public SiteGroup AddSiteGroup(SiteGroup siteGroup)
|
||||
{
|
||||
using var db = _dbContextFactory.CreateDbContext();
|
||||
return db.SiteGroup
|
||||
.Where(item => (siteId == -1 || item.SiteId == siteId) && (siteGroupDefinitionId == -1 || item.SiteGroupDefinitionId == siteGroupDefinitionId))
|
||||
.Include(item => item.SiteGroupDefinition) // eager load
|
||||
.ToList();
|
||||
}
|
||||
|
||||
public SiteGroup AddSiteGroup(SiteGroup SiteGroup)
|
||||
{
|
||||
using var db = _dbContextFactory.CreateDbContext();
|
||||
db.SiteGroup.Add(SiteGroup);
|
||||
db.SiteGroup.Add(siteGroup);
|
||||
db.SaveChanges();
|
||||
return SiteGroup;
|
||||
return siteGroup;
|
||||
}
|
||||
|
||||
public SiteGroup UpdateSiteGroup(SiteGroup SiteGroup)
|
||||
public SiteGroup UpdateSiteGroup(SiteGroup siteGroup)
|
||||
{
|
||||
using var db = _dbContextFactory.CreateDbContext();
|
||||
db.Entry(SiteGroup).State = EntityState.Modified;
|
||||
db.Entry(siteGroup).State = EntityState.Modified;
|
||||
db.SaveChanges();
|
||||
return SiteGroup;
|
||||
return siteGroup;
|
||||
}
|
||||
|
||||
public SiteGroup GetSiteGroup(int SiteGroupId)
|
||||
public SiteGroup GetSiteGroup(int siteGroupId)
|
||||
{
|
||||
return GetSiteGroup(SiteGroupId, true);
|
||||
return GetSiteGroup(siteGroupId, true);
|
||||
}
|
||||
|
||||
public SiteGroup GetSiteGroup(int SiteGroupId, bool tracking)
|
||||
public SiteGroup GetSiteGroup(int siteGroupId, bool tracking)
|
||||
{
|
||||
using var db = _dbContextFactory.CreateDbContext();
|
||||
if (tracking)
|
||||
{
|
||||
return db.SiteGroup
|
||||
.Include(item => item.SiteGroupDefinition) // eager load
|
||||
.FirstOrDefault(item => item.SiteGroupId == SiteGroupId);
|
||||
return db.SiteGroup.FirstOrDefault(item => item.SiteGroupId == siteGroupId);
|
||||
}
|
||||
else
|
||||
{
|
||||
return db.SiteGroup.AsNoTracking()
|
||||
.Include(item => item.SiteGroupDefinition) // eager load
|
||||
.FirstOrDefault(item => item.SiteGroupId == SiteGroupId);
|
||||
return db.SiteGroup.AsNoTracking().FirstOrDefault(item => item.SiteGroupId == siteGroupId);
|
||||
}
|
||||
}
|
||||
|
||||
public void DeleteSiteGroup(int SiteGroupId)
|
||||
public void DeleteSiteGroup(int siteGroupId)
|
||||
{
|
||||
using var db = _dbContextFactory.CreateDbContext();
|
||||
SiteGroup SiteGroup = db.SiteGroup.Find(SiteGroupId);
|
||||
db.SiteGroup.Remove(SiteGroup);
|
||||
SiteGroup group = db.SiteGroup.Find(siteGroupId);
|
||||
db.SiteGroup.Remove(group);
|
||||
db.SaveChanges();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace Oqtane.Services
|
||||
public class ServerSiteService : ISiteService
|
||||
{
|
||||
private readonly ISiteRepository _sites;
|
||||
private readonly ISiteGroupRepository _siteGroups;
|
||||
private readonly ISiteGroupMemberRepository _siteGroupMembers;
|
||||
private readonly IAliasRepository _aliases;
|
||||
private readonly IPageRepository _pages;
|
||||
private readonly IThemeRepository _themes;
|
||||
@@ -39,10 +39,10 @@ namespace Oqtane.Services
|
||||
private readonly IHttpContextAccessor _accessor;
|
||||
private readonly string _private = "[PRIVATE]";
|
||||
|
||||
public ServerSiteService(ISiteRepository sites, ISiteGroupRepository siteGroups, IAliasRepository aliases, IPageRepository pages, IThemeRepository themes, IPageModuleRepository pageModules, IModuleDefinitionRepository moduleDefinitions, ILanguageRepository languages, IUserManager userManager, IUserPermissions userPermissions, ISettingRepository settings, ITenantManager tenantManager, ISyncManager syncManager, IConfigManager configManager, ILogManager logger, IMemoryCache cache, IHttpContextAccessor accessor)
|
||||
public ServerSiteService(ISiteRepository sites, ISiteGroupMemberRepository siteGroupMembers, IAliasRepository aliases, IPageRepository pages, IThemeRepository themes, IPageModuleRepository pageModules, IModuleDefinitionRepository moduleDefinitions, ILanguageRepository languages, IUserManager userManager, IUserPermissions userPermissions, ISettingRepository settings, ITenantManager tenantManager, ISyncManager syncManager, IConfigManager configManager, ILogManager logger, IMemoryCache cache, IHttpContextAccessor accessor)
|
||||
{
|
||||
_sites = sites;
|
||||
_siteGroups = siteGroups;
|
||||
_siteGroupMembers = siteGroupMembers;
|
||||
_aliases = aliases;
|
||||
_pages = pages;
|
||||
_themes = themes;
|
||||
@@ -315,31 +315,39 @@ namespace Oqtane.Services
|
||||
{
|
||||
var languages = new List<Language>();
|
||||
|
||||
var siteGroups = _siteGroups.GetSiteGroups();
|
||||
if (siteGroups.Any(item => item.SiteId == siteId && item.SiteGroupDefinition.Localization))
|
||||
var siteGroupMembers = _siteGroupMembers.GetSiteGroupMembers();
|
||||
if (siteGroupMembers.Any(item => item.SiteId == siteId && item.SiteGroup.Type == SiteGroupTypes.Localization))
|
||||
{
|
||||
// site is part of a localized site group - get all languages from the site group
|
||||
var sites = _sites.GetSites().ToList();
|
||||
var aliases = _aliases.GetAliases().ToList();
|
||||
|
||||
foreach (var siteGroupDefinitionId in siteGroups.Where(item => item.SiteId == siteId && item.SiteGroupDefinition.Localization).Select(item => item.SiteGroupDefinitionId).Distinct().ToList())
|
||||
foreach (var siteGroupId in siteGroupMembers.Where(item => item.SiteId == siteId && item.SiteGroup.Type == SiteGroupTypes.Localization).Select(item => item.SiteGroupId).Distinct().ToList())
|
||||
{
|
||||
foreach (var siteGroup in siteGroups.Where(item => item.SiteGroupDefinitionId == siteGroupDefinitionId))
|
||||
foreach (var siteGroupMember in siteGroupMembers.Where(item => item.SiteGroupId == siteGroupId))
|
||||
{
|
||||
var site = sites.FirstOrDefault(item => item.SiteId == siteGroup.SiteId);
|
||||
var site = sites.FirstOrDefault(item => item.SiteId == siteGroupMember.SiteId);
|
||||
if (site != null && !string.IsNullOrEmpty(site.CultureCode))
|
||||
{
|
||||
if (!languages.Any(item => item.Code == site.CultureCode))
|
||||
var alias = aliases.FirstOrDefault(item => item.SiteId == siteGroupMember.SiteId && item.TenantId == tenantId && item.IsDefault);
|
||||
if (alias != null)
|
||||
{
|
||||
var alias = aliases.FirstOrDefault(item => item.SiteId == siteGroup.SiteId && item.TenantId == tenantId && item.IsDefault);
|
||||
if (alias != null)
|
||||
{
|
||||
languages.Add(new Language { Code = site.CultureCode, Name = "", AliasName = alias.Name, IsDefault = true });
|
||||
}
|
||||
languages.Add(new Language { Code = site.CultureCode, Name = "", AliasName = alias.Name, IsDefault = false });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// use site languages
|
||||
languages = _languages.GetLanguages(siteId).ToList();
|
||||
var defaultCulture = CultureInfo.GetCultureInfo(Constants.DefaultCulture);
|
||||
if (!languages.Exists(item => item.Code == defaultCulture.Name))
|
||||
{
|
||||
languages.Add(new Language { Code = defaultCulture.Name, Name = "", Version = Constants.Version, IsDefault = !languages.Any(l => l.IsDefault) });
|
||||
}
|
||||
}
|
||||
|
||||
return languages;
|
||||
}
|
||||
|
||||
@@ -13,10 +13,10 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="10.0.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="10.0.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="10.0.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http" Version="10.0.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="10.0.3" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="10.0.3" />
|
||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="10.0.3" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http" Version="10.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -20,10 +20,10 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="10.0.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="10.0.2" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="10.0.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="10.0.3" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="10.0.3" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.3" />
|
||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="10.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -14,9 +14,9 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="10.0.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="10.0.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="10.0.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="10.0.3" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="10.0.3" />
|
||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="10.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -1,49 +1,30 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace Oqtane.Models
|
||||
{
|
||||
public class SiteGroup : ModelBase
|
||||
{
|
||||
/// <summary>
|
||||
/// ID to identify the site group
|
||||
/// ID to identify the group
|
||||
/// </summary>
|
||||
public int SiteGroupId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Reference to the <see cref="SiteGroupDefinition"/>.
|
||||
/// Name of the group
|
||||
/// </summary>
|
||||
public int SiteGroupDefinitionId { get; set; }
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Reference to the <see cref="Site"/>.
|
||||
/// Group type ie. Synchronization, Localization
|
||||
/// </summary>
|
||||
public int SiteId { get; set; }
|
||||
public string Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the site synchronization approach (false = compare, true = update)
|
||||
/// SiteId of the primary site in the group
|
||||
/// </summary>
|
||||
public bool Synchronize { get; set; }
|
||||
public int PrimarySiteId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Indicates if the site administrator should be notified of any synchronization activity
|
||||
/// Specifies if the group should be synchronized
|
||||
/// </summary>
|
||||
public bool Notify { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The last date/time the site was synchronized
|
||||
/// </summary>
|
||||
public DateTime? SynchronizedOn { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="SiteGroupDefinition"/> itself.
|
||||
/// </summary>
|
||||
public SiteGroupDefinition SiteGroupDefinition { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The primary alias for the site
|
||||
/// </summary>
|
||||
[NotMapped]
|
||||
public string AliasName { get; set; }
|
||||
public bool Synchronize{ get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
namespace Oqtane.Models
|
||||
{
|
||||
public class SiteGroupDefinition : ModelBase
|
||||
{
|
||||
/// <summary>
|
||||
/// ID to identify the group
|
||||
/// </summary>
|
||||
public int SiteGroupDefinitionId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Name of the group
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// SiteId of the primary site in the group
|
||||
/// </summary>
|
||||
public int PrimarySiteId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Indicates if the group supports synchronization
|
||||
/// </summary>
|
||||
public bool Synchronization { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Specifies if the group needs to be synchronized
|
||||
/// </summary>
|
||||
public bool Synchronize { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Indicates if the group supports localization
|
||||
/// </summary>
|
||||
public bool Localization { get; set; }
|
||||
}
|
||||
}
|
||||
39
Oqtane.Shared/Models/SiteGroupMember.cs
Normal file
39
Oqtane.Shared/Models/SiteGroupMember.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace Oqtane.Models
|
||||
{
|
||||
public class SiteGroupMember : ModelBase
|
||||
{
|
||||
/// <summary>
|
||||
/// ID to identify the site group
|
||||
/// </summary>
|
||||
public int SiteGroupMemberId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Reference to the <see cref="SiteGroup"/>.
|
||||
/// </summary>
|
||||
public int SiteGroupId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Reference to the <see cref="Site"/>.
|
||||
/// </summary>
|
||||
public int SiteId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The last date/time the site was synchronized
|
||||
/// </summary>
|
||||
public DateTime? SynchronizedOn { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="SiteGroup"/> itself.
|
||||
/// </summary>
|
||||
public SiteGroup SiteGroup { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The primary alias for the site
|
||||
/// </summary>
|
||||
[NotMapped]
|
||||
public string AliasName { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -5,8 +5,8 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.2" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.3" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.3" />
|
||||
<PackageReference Include="NodaTime" Version="3.3.0" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace Oqtane.Shared
|
||||
public const string Setting = "Setting";
|
||||
public const string Site = "Site";
|
||||
public const string SiteGroup = "SiteGroup";
|
||||
public const string SiteGroupDefinition = "SiteGroupDefinition";
|
||||
public const string SiteGroupMember = "SiteGroupMember";
|
||||
public const string Tenant = "Tenant";
|
||||
public const string Theme = "Theme";
|
||||
public const string UrlMapping = "UrlMapping";
|
||||
|
||||
9
Oqtane.Shared/Shared/SiteGroupTypes.cs
Normal file
9
Oqtane.Shared/Shared/SiteGroupTypes.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace Oqtane.Shared
|
||||
{
|
||||
public class SiteGroupTypes
|
||||
{
|
||||
public const string Synchronization = "Synchronization";
|
||||
public const string Comparison = "Comparison";
|
||||
public const string Localization = "Localization";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user