Merge remote-tracking branch 'upstream/dev' into dev
This commit is contained in:
@@ -2,12 +2,14 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<OutputType>Exe</OutputType>
|
||||
<Version>1.0.0</Version>
|
||||
<AssemblyName>Oqtane.Application.Client.Oqtane</AssemblyName>
|
||||
<NoDefaultLaunchSettingsFile>true</NoDefaultLaunchSettingsFile>
|
||||
<IsPackable>true</IsPackable>
|
||||
<StaticWebAssetProjectMode>Default</StaticWebAssetProjectMode>
|
||||
<BlazorWebAssemblyEnableLinking>false</BlazorWebAssemblyEnableLinking>
|
||||
<BlazorWebAssemblyLoadAllGlobalizationData>true</BlazorWebAssemblyLoadAllGlobalizationData>
|
||||
<PublishTrimmed>false</PublishTrimmed>
|
||||
<BlazorEnableCompression>false</BlazorEnableCompression>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<Version>1.0.0</Version>
|
||||
<AssemblyName>Oqtane.Application.Server.Oqtane</AssemblyName>
|
||||
<IsPackable>true</IsPackable>
|
||||
<PreserveCompilationContext>true</PreserveCompilationContext>
|
||||
<SatelliteResourceLanguages>none</SatelliteResourceLanguages>
|
||||
<CompressionEnabled>false</CompressionEnabled>
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<Version>1.0.0</Version>
|
||||
<AssemblyName>Oqtane.Application.Shared.Oqtane</AssemblyName>
|
||||
<IsPackable>true</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -56,6 +56,7 @@ namespace Microsoft.Extensions.DependencyInjection
|
||||
services.AddScoped<ILocalizationCookieService, LocalizationCookieService>();
|
||||
services.AddScoped<ICookieConsentService, CookieConsentService>();
|
||||
services.AddScoped<ITimeZoneService, TimeZoneService>();
|
||||
services.AddScoped<IMigrationHistoryService, MigrationHistoryService>();
|
||||
services.AddScoped<IOutputCacheService, OutputCacheService>();
|
||||
|
||||
// providers
|
||||
|
||||
@@ -2,241 +2,280 @@
|
||||
@inherits ModuleBase
|
||||
@inject ISystemService SystemService
|
||||
@inject IInstallationService InstallationService
|
||||
@inject IMigrationHistoryService MigrationHistoryService
|
||||
@inject ITenantService TenantService
|
||||
@inject IStringLocalizer<Index> Localizer
|
||||
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
||||
|
||||
<TabStrip>
|
||||
<TabPanel Name="Info" Heading="Info" ResourceKey="Info">
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="version" HelpText="Framework Version" ResourceKey="FrameworkVersion">Framework Version: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="version" class="form-control" @bind="@_version" readonly />
|
||||
@if (_initialized)
|
||||
{
|
||||
<TabStrip>
|
||||
<TabPanel Name="Info" Heading="Info" ResourceKey="Info">
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="version" HelpText="Framework Version" ResourceKey="FrameworkVersion">Framework Version: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="version" class="form-control" @bind="@_version" readonly />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="clrversion" HelpText="Common Language Runtime Version" ResourceKey="CLRVersion">CLR Version: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="clrversion" class="form-control" @bind="@_clrversion" readonly />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="osversion" HelpText="Operating System Version" ResourceKey="OSVersion">OS Version: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="osversion" class="form-control" @bind="@_osversion" readonly />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="process" HelpText="Indicates if the current process is 32 bit or 64 bit" ResourceKey="Process">Process: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="process" class="form-control" @bind="@_process" readonly />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="machinename" HelpText="Machine Name" ResourceKey="MachineName">Machine Name: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="machinename" class="form-control" @bind="@_machinename" readonly />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="ipaddress" HelpText="Server IP Address" ResourceKey="IPAddress">IP Address: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="ipaddress" class="form-control" @bind="@_ipaddress" readonly />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="environment" HelpText="Environment name" ResourceKey="Environment">Environment: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="environment" class="form-control" @bind="@_environment" readonly />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="contentrootpath" HelpText="Root Path" ResourceKey="ContentRootPath">Root Path: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="contentrootpath" class="form-control" @bind="@_contentrootpath" readonly />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="webrootpath" HelpText="Web Path" ResourceKey="WebRootPath">Web Path: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="webrootpath" class="form-control" @bind="@_webrootpath" readonly />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="servertime" HelpText="Server Date/Time (in UTC)" ResourceKey="ServerTime">Server Date/Time: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="servertime" class="form-control" @bind="@_servertime" readonly />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="workingset" HelpText="Memory Allocation Of Service (in MB)" ResourceKey="WorkingSet">Memory Allocation: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="workingset" class="form-control" @bind="@_workingset" readonly />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="installationid" HelpText="The Unique Identifier For Your Installation" ResourceKey="InstallationId">Installation ID: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="installationid" class="form-control" @bind="@_installationid" readonly />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="clrversion" HelpText="Common Language Runtime Version" ResourceKey="CLRVersion">CLR Version: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="clrversion" class="form-control" @bind="@_clrversion" readonly />
|
||||
<br /><br />
|
||||
<ActionDialog Header="Restart Application" Message="Are You Sure You Wish To Restart The Application?" Action="Restart Application" Security="SecurityAccessLevel.Host" Class="btn btn-danger" OnClick="@(async () => await RestartApplication())" ResourceKey="RestartApplication" />
|
||||
</TabPanel>
|
||||
<TabPanel Name="Options" Heading="Options" ResourceKey="Options">
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="detailederrors" HelpText="Specify If Detailed Errors Are Enabled For Blazor. This Option Should Not Not Be Enabled In Production." ResourceKey="DetailedErrors">Detailed Errors? </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="detailederrors" class="form-select" @bind="@_detailederrors">
|
||||
<option value="true">@SharedLocalizer["True"]</option>
|
||||
<option value="false">@SharedLocalizer["False"]</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="logginglevel" HelpText="The Minimum Logging Level For The Event Log. This Option Can Be Used To Control The Volume Of Items Stored In Your Event Log." ResourceKey="LoggingLevel">Logging Level: </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="logginglevel" class="form-select" @bind="@_logginglevel">
|
||||
<option value="Trace">@Localizer["Trace"]</option>
|
||||
<option value="Debug">@Localizer["Debug"]</option>
|
||||
<option value="Information">@Localizer["Information"]</option>
|
||||
<option value="Warning">@Localizer["Warning"]</option>
|
||||
<option value="Error">@Localizer["Error"]</option>
|
||||
<option value="Critical">@Localizer["Critical"]</option>
|
||||
<option value="None">@Localizer["None"]</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="notificationlevel" HelpText="The Minimum Logging Level For Which Notifications Should Be Sent To Host Users." ResourceKey="NotificationLevel">Notification Level: </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="notificationlevel" class="form-select" @bind="@_notificationlevel">
|
||||
<option value="Trace">@Localizer["Trace"]</option>
|
||||
<option value="Debug">@Localizer["Debug"]</option>
|
||||
<option value="Information">@Localizer["Information"]</option>
|
||||
<option value="Warning">@Localizer["Warning"]</option>
|
||||
<option value="Error">@Localizer["Error"]</option>
|
||||
<option value="Critical">@Localizer["Critical"]</option>
|
||||
<option value="None">@Localizer["None"]</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="swagger" HelpText="Specify If Swagger Is Enabled For Your Server API" ResourceKey="Swagger">Swagger Enabled? </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="swagger" class="form-select" @bind="@_swagger">
|
||||
<option value="true">@SharedLocalizer["True"]</option>
|
||||
<option value="false">@SharedLocalizer["False"]</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="cachecontrol" HelpText="Provide a Cache-Control directive for static assets. For example 'public, max-age=60' indicates that static assets should be cached for 60 seconds. A blank value indicates caching is not enabled." ResourceKey="CacheControl">Static Asset Caching: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="cachecontrol" class="form-control" @bind="@_cachecontrol" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="packageregistryurl" HelpText="Specify The Url Of The Package Manager Service For Installing Modules, Themes, And Translations. If This Field Is Blank It Means The Package Manager Service Is Disabled For This Installation." ResourceKey="PackageManager">Package Manager Url: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="packageregistryurl" class="form-control" @bind="@_packageregistryurl" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="packageregistryemail" HelpText="Specify The Email Address Of The User Account Used For Interacting With The Package Manager Service. This Account Is Used For Managing Packages Across Multiple Installations." ResourceKey="PackageManagerEmail">Package Manager Email: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="packageregistryemail" class="form-control" @bind="@_packageregistryemail" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="osversion" HelpText="Operating System Version" ResourceKey="OSVersion">OS Version: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="osversion" class="form-control" @bind="@_osversion" readonly />
|
||||
<br /><br />
|
||||
<button type="button" class="btn btn-success" @onclick="SaveConfig">@SharedLocalizer["Save"]</button>
|
||||
<ActionDialog Header="Restart Application" Message="Are You Sure You Wish To Restart The Application?" Action="Restart Application" Security="SecurityAccessLevel.Host" Class="btn btn-danger" OnClick="@(async () => await RestartApplication())" ResourceKey="RestartApplication" />
|
||||
<br /><br />
|
||||
<a class="btn btn-primary" href="swagger/index.html" target="_new">@Localizer["Swagger"]</a>
|
||||
<a class="btn btn-secondary" href="api/endpoint" target="_new">@Localizer["Endpoints"]</a>
|
||||
</TabPanel>
|
||||
<TabPanel Name="Log" Heading="Log" ResourceKey="Log">
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="log" HelpText="System log information for current day" ResourceKey="Log">Log: </Label>
|
||||
<div class="col-sm-9">
|
||||
<textarea id="log" class="form-control" rows="10" @bind="@_log" readonly />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="process" HelpText="Indicates if the current process is 32 bit or 64 bit" ResourceKey="Process">Process: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="process" class="form-control" @bind="@_process" readonly />
|
||||
<br /><br />
|
||||
<button type="button" class="btn btn-danger" @onclick="ClearLog">@Localizer["Clear"]</button>
|
||||
</TabPanel>
|
||||
<TabPanel Name="Migrations" Heading="Migrations" ResourceKey="Migrations">
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="tenant" HelpText="The name of the current database. Note that this is not the physical database name but rather the tenant name which is used within the framework to identify a database." ResourceKey="Tenant">Database: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="tenant" class="form-control" @bind="@_tenant" readonly />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="machinename" HelpText="Machine Name" ResourceKey="MachineName">Machine Name: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="machinename" class="form-control" @bind="@_machinename" readonly />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="ipaddress" HelpText="Server IP Address" ResourceKey="IPAddress">IP Address: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="ipaddress" class="form-control" @bind="@_ipaddress" readonly />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="environment" HelpText="Environment name" ResourceKey="Environment">Environment: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="environment" class="form-control" @bind="@_environment" readonly />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="contentrootpath" HelpText="Root Path" ResourceKey="ContentRootPath">Root Path: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="contentrootpath" class="form-control" @bind="@_contentrootpath" readonly />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="webrootpath" HelpText="Web Path" ResourceKey="WebRootPath">Web Path: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="webrootpath" class="form-control" @bind="@_webrootpath" readonly />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="servertime" HelpText="Server Date/Time (in UTC)" ResourceKey="ServerTime">Server Date/Time: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="servertime" class="form-control" @bind="@_servertime" readonly />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="workingset" HelpText="Memory Allocation Of Service (in MB)" ResourceKey="WorkingSet">Memory Allocation: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="workingset" class="form-control" @bind="@_workingset" readonly />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="installationid" HelpText="The Unique Identifier For Your Installation" ResourceKey="InstallationId">Installation ID: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="installationid" class="form-control" @bind="@_installationid" readonly />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<br /><br />
|
||||
<ActionDialog Header="Restart Application" Message="Are You Sure You Wish To Restart The Application?" Action="Restart Application" Security="SecurityAccessLevel.Host" Class="btn btn-danger" OnClick="@(async () => await RestartApplication())" ResourceKey="RestartApplication" />
|
||||
</TabPanel>
|
||||
<TabPanel Name="Options" Heading="Options" ResourceKey="Options">
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="detailederrors" HelpText="Specify If Detailed Errors Are Enabled For Blazor. This Option Should Not Not Be Enabled In Production." ResourceKey="DetailedErrors">Detailed Errors? </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="detailederrors" class="form-select" @bind="@_detailederrors">
|
||||
<option value="true">@SharedLocalizer["True"]</option>
|
||||
<option value="false">@SharedLocalizer["False"]</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="logginglevel" HelpText="The Minimum Logging Level For The Event Log. This Option Can Be Used To Control The Volume Of Items Stored In Your Event Log." ResourceKey="LoggingLevel">Logging Level: </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="logginglevel" class="form-select" @bind="@_logginglevel">
|
||||
<option value="Trace">@Localizer["Trace"]</option>
|
||||
<option value="Debug">@Localizer["Debug"]</option>
|
||||
<option value="Information">@Localizer["Information"]</option>
|
||||
<option value="Warning">@Localizer["Warning"]</option>
|
||||
<option value="Error">@Localizer["Error"]</option>
|
||||
<option value="Critical">@Localizer["Critical"]</option>
|
||||
<option value="None">@Localizer["None"]</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="notificationlevel" HelpText="The Minimum Logging Level For Which Notifications Should Be Sent To Host Users." ResourceKey="NotificationLevel">Notification Level: </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="notificationlevel" class="form-select" @bind="@_notificationlevel">
|
||||
<option value="Trace">@Localizer["Trace"]</option>
|
||||
<option value="Debug">@Localizer["Debug"]</option>
|
||||
<option value="Information">@Localizer["Information"]</option>
|
||||
<option value="Warning">@Localizer["Warning"]</option>
|
||||
<option value="Error">@Localizer["Error"]</option>
|
||||
<option value="Critical">@Localizer["Critical"]</option>
|
||||
<option value="None">@Localizer["None"]</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="swagger" HelpText="Specify If Swagger Is Enabled For Your Server API" ResourceKey="Swagger">Swagger Enabled? </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="swagger" class="form-select" @bind="@_swagger">
|
||||
<option value="true">@SharedLocalizer["True"]</option>
|
||||
<option value="false">@SharedLocalizer["False"]</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="cachecontrol" HelpText="Provide a Cache-Control directive for static assets. For example 'public, max-age=60' indicates that static assets should be cached for 60 seconds. A blank value indicates caching is not enabled." ResourceKey="CacheControl">Static Asset Caching: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="cachecontrol" class="form-control" @bind="@_cachecontrol" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="packageregistryurl" HelpText="Specify The Url Of The Package Manager Service For Installing Modules, Themes, And Translations. If This Field Is Blank It Means The Package Manager Service Is Disabled For This Installation." ResourceKey="PackageManager">Package Manager Url: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="packageregistryurl" class="form-control" @bind="@_packageregistryurl" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="packageregistryemail" HelpText="Specify The Email Address Of The User Account Used For Interacting With The Package Manager Service. This Account Is Used For Managing Packages Across Multiple Installations." ResourceKey="PackageManagerEmail">Package Manager Email: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="packageregistryemail" class="form-control" @bind="@_packageregistryemail" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<br /><br />
|
||||
<button type="button" class="btn btn-success" @onclick="SaveConfig">@SharedLocalizer["Save"]</button>
|
||||
<ActionDialog Header="Restart Application" Message="Are You Sure You Wish To Restart The Application?" Action="Restart Application" Security="SecurityAccessLevel.Host" Class="btn btn-danger" OnClick="@(async () => await RestartApplication())" ResourceKey="RestartApplication" />
|
||||
<br /><br />
|
||||
<a class="btn btn-primary" href="swagger/index.html" target="_new">@Localizer["Swagger"]</a>
|
||||
<a class="btn btn-secondary" href="api/endpoint" target="_new">@Localizer["Endpoints"]</a>
|
||||
</TabPanel>
|
||||
<TabPanel Name="Log" Heading="Log" ResourceKey="Log">
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="log" HelpText="System log information for current day" ResourceKey="Log">Log: </Label>
|
||||
<div class="col-sm-9">
|
||||
<textarea id="log" class="form-control" rows="10" @bind="@_log" readonly />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<br /><br />
|
||||
<button type="button" class="btn btn-danger" @onclick="ClearLog">@Localizer["Clear"]</button>
|
||||
</TabPanel>
|
||||
</TabStrip>
|
||||
<br /><br />
|
||||
<br />
|
||||
<Pager Items="@_history" SearchProperties="MigrationId">
|
||||
<Header>
|
||||
<th>@Localizer["Migration"]</th>
|
||||
<th>@Localizer["Date"]</th>
|
||||
<th>@Localizer["Version"]</th>
|
||||
</Header>
|
||||
<Row>
|
||||
<td>@context.MigrationId</td>
|
||||
<td>@UtcToLocal(context.AppliedDate)</td>
|
||||
<td>@context.AppliedVersion</td>
|
||||
</Row>
|
||||
</Pager>
|
||||
</TabPanel>
|
||||
</TabStrip>
|
||||
<br /><br />
|
||||
}
|
||||
|
||||
@code {
|
||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
|
||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
|
||||
|
||||
private string _version = string.Empty;
|
||||
private string _clrversion = string.Empty;
|
||||
private string _osversion = string.Empty;
|
||||
private bool _initialized = false;
|
||||
|
||||
private string _version = string.Empty;
|
||||
private string _clrversion = string.Empty;
|
||||
private string _osversion = string.Empty;
|
||||
private string _process = string.Empty;
|
||||
private string _machinename = string.Empty;
|
||||
private string _ipaddress = string.Empty;
|
||||
private string _environment = string.Empty;
|
||||
private string _contentrootpath = string.Empty;
|
||||
private string _webrootpath = string.Empty;
|
||||
private string _servertime = string.Empty;
|
||||
private string _workingset = string.Empty;
|
||||
private string _installationid = string.Empty;
|
||||
private string _ipaddress = string.Empty;
|
||||
private string _environment = string.Empty;
|
||||
private string _contentrootpath = string.Empty;
|
||||
private string _webrootpath = string.Empty;
|
||||
private string _servertime = string.Empty;
|
||||
private string _workingset = string.Empty;
|
||||
private string _installationid = string.Empty;
|
||||
|
||||
private string _detailederrors = string.Empty;
|
||||
private string _logginglevel = string.Empty;
|
||||
private string _notificationlevel = string.Empty;
|
||||
private string _swagger = string.Empty;
|
||||
private string _detailederrors = string.Empty;
|
||||
private string _logginglevel = string.Empty;
|
||||
private string _notificationlevel = string.Empty;
|
||||
private string _swagger = string.Empty;
|
||||
private string _cachecontrol = string.Empty;
|
||||
private string _packageregistryurl = string.Empty;
|
||||
private string _packageregistryemail = string.Empty;
|
||||
|
||||
private string _log = string.Empty;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
_version = Constants.Version;
|
||||
private string _tenant = string.Empty;
|
||||
private List<MigrationHistory> _history;
|
||||
|
||||
var systeminfo = await SystemService.GetSystemInfoAsync("environment");
|
||||
if (systeminfo != null)
|
||||
{
|
||||
_clrversion = systeminfo["CLRVersion"].ToString();
|
||||
_osversion = systeminfo["OSVersion"].ToString();
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
_version = Constants.Version;
|
||||
|
||||
var systeminfo = await SystemService.GetSystemInfoAsync("environment");
|
||||
if (systeminfo != null)
|
||||
{
|
||||
_clrversion = systeminfo["CLRVersion"].ToString();
|
||||
_osversion = systeminfo["OSVersion"].ToString();
|
||||
_process = systeminfo["Process"].ToString();
|
||||
_machinename = systeminfo["MachineName"].ToString();
|
||||
_ipaddress = systeminfo["IPAddress"].ToString();
|
||||
_environment = systeminfo["Environment"].ToString();
|
||||
_contentrootpath = systeminfo["ContentRootPath"].ToString();
|
||||
_webrootpath = systeminfo["WebRootPath"].ToString();
|
||||
_servertime = systeminfo["ServerTime"].ToString() + " UTC";
|
||||
_workingset = (Convert.ToInt64(systeminfo["WorkingSet"].ToString()) / 1000000).ToString() + " MB";
|
||||
}
|
||||
_ipaddress = systeminfo["IPAddress"].ToString();
|
||||
_environment = systeminfo["Environment"].ToString();
|
||||
_contentrootpath = systeminfo["ContentRootPath"].ToString();
|
||||
_webrootpath = systeminfo["WebRootPath"].ToString();
|
||||
_servertime = systeminfo["ServerTime"].ToString() + " UTC";
|
||||
_workingset = (Convert.ToInt64(systeminfo["WorkingSet"].ToString()) / 1000000).ToString() + " MB";
|
||||
}
|
||||
|
||||
systeminfo = await SystemService.GetSystemInfoAsync("configuration");
|
||||
if (systeminfo != null)
|
||||
{
|
||||
_installationid = systeminfo["InstallationId"].ToString();
|
||||
_detailederrors = systeminfo["DetailedErrors"].ToString();
|
||||
_logginglevel = systeminfo["Logging:LogLevel:Default"].ToString();
|
||||
_notificationlevel = systeminfo["Logging:LogLevel:Notify"].ToString();
|
||||
systeminfo = await SystemService.GetSystemInfoAsync("configuration");
|
||||
if (systeminfo != null)
|
||||
{
|
||||
_installationid = systeminfo["InstallationId"].ToString();
|
||||
_detailederrors = systeminfo["DetailedErrors"].ToString();
|
||||
_logginglevel = systeminfo["Logging:LogLevel:Default"].ToString();
|
||||
_notificationlevel = systeminfo["Logging:LogLevel:Notify"].ToString();
|
||||
_swagger = systeminfo["UseSwagger"].ToString();
|
||||
_cachecontrol = systeminfo["CacheControl"].ToString();
|
||||
_packageregistryurl = systeminfo["PackageRegistryUrl"].ToString();
|
||||
_packageregistryemail = systeminfo["PackageRegistryEmail"].ToString();
|
||||
}
|
||||
|
||||
systeminfo = await SystemService.GetSystemInfoAsync("log");
|
||||
if (systeminfo != null)
|
||||
{
|
||||
_log = systeminfo["Log"].ToString();
|
||||
}
|
||||
}
|
||||
systeminfo = await SystemService.GetSystemInfoAsync("log");
|
||||
if (systeminfo != null)
|
||||
{
|
||||
_log = systeminfo["Log"].ToString();
|
||||
}
|
||||
|
||||
var tenants = await TenantService.GetTenantsAsync();
|
||||
_tenant = tenants.Find(item => item.TenantId == PageState.Site.TenantId).Name;
|
||||
_history = await MigrationHistoryService.GetMigrationHistoryAsync();
|
||||
|
||||
_initialized = true;
|
||||
}
|
||||
|
||||
private async Task SaveConfig()
|
||||
{
|
||||
|
||||
@@ -309,4 +309,19 @@
|
||||
<data name="Endpoints" xml:space="preserve">
|
||||
<value>API Endpoints</value>
|
||||
</data>
|
||||
<data name="Migration" xml:space="preserve">
|
||||
<value>Migration</value>
|
||||
</data>
|
||||
<data name="Date" xml:space="preserve">
|
||||
<value>Date</value>
|
||||
</data>
|
||||
<data name="Version" xml:space="preserve">
|
||||
<value>Framework Version</value>
|
||||
</data>
|
||||
<data name="Tenant.Text" xml:space="preserve">
|
||||
<value>Database:</value>
|
||||
</data>
|
||||
<data name="Tenant.HelpText" xml:space="preserve">
|
||||
<value>The name of the current database. Note that this is not the physical database name but rather the tenant name which is used within the framework to identify a database.</value>
|
||||
</data>
|
||||
</root>
|
||||
34
Oqtane.Client/Services/MigrationHistoryService.cs
Normal file
34
Oqtane.Client/Services/MigrationHistoryService.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using Oqtane.Models;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections.Generic;
|
||||
using Oqtane.Documentation;
|
||||
using Oqtane.Shared;
|
||||
|
||||
namespace Oqtane.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Service to manage <see cref="MigrationHistory/>s on the Oqtane installation.
|
||||
/// </summary>
|
||||
public interface IMigrationHistoryService
|
||||
{
|
||||
/// <summary>
|
||||
/// Get all <see cref="MigrationHistory"/>s
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Task<List<MigrationHistory>> GetMigrationHistoryAsync();
|
||||
}
|
||||
|
||||
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||
public class MigrationHistoryService : ServiceBase, IMigrationHistoryService
|
||||
{
|
||||
public MigrationHistoryService(HttpClient http, SiteState siteState) : base(http, siteState) { }
|
||||
|
||||
private string Apiurl => CreateApiUrl("MigrationHistory");
|
||||
|
||||
public async Task<List<MigrationHistory>> GetMigrationHistoryAsync()
|
||||
{
|
||||
return await GetJsonAsync<List<MigrationHistory>>(Apiurl);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,42 +4,19 @@ nuget.exe pack Oqtane.Server.nuspec
|
||||
nuget.exe pack Oqtane.Shared.nuspec
|
||||
nuget.exe pack Oqtane.Framework.nuspec
|
||||
dotnet publish ..\Oqtane.Server\Oqtane.Server.csproj /p:Configuration=Release
|
||||
rmdir /Q/S "..\Oqtane.Server\bin\Release\net9.0\publish\Content"
|
||||
rmdir /Q/S "..\Oqtane.Server\bin\Release\net9.0\publish\wwwroot\Content"
|
||||
rmdir /Q/S "..\Oqtane.Server\bin\Release\net9.0\publish\runtimes\android-arm"
|
||||
rmdir /Q/S "..\Oqtane.Server\bin\Release\net9.0\publish\runtimes\android-arm64"
|
||||
rmdir /Q/S "..\Oqtane.Server\bin\Release\net9.0\publish\runtimes\android-x64"
|
||||
rmdir /Q/S "..\Oqtane.Server\bin\Release\net9.0\publish\runtimes\android-x86"
|
||||
rmdir /Q/S "..\Oqtane.Server\bin\Release\net9.0\publish\runtimes\ios-arm"
|
||||
rmdir /Q/S "..\Oqtane.Server\bin\Release\net9.0\publish\runtimes\ios-arm64"
|
||||
rmdir /Q/S "..\Oqtane.Server\bin\Release\net9.0\publish\runtimes\iossimulator-arm64"
|
||||
rmdir /Q/S "..\Oqtane.Server\bin\Release\net9.0\publish\runtimes\iossimulator-x64"
|
||||
rmdir /Q/S "..\Oqtane.Server\bin\Release\net9.0\publish\runtimes\iossimulator-x86"
|
||||
setlocal ENABLEDELAYEDEXPANSION
|
||||
set retain=Radzen.Blazor
|
||||
for /D %%i in ("..\Oqtane.Server\bin\Release\net9.0\publish\wwwroot\_content\*") do (
|
||||
set /A found=0
|
||||
for %%j in (%retain%) do (
|
||||
if "%%~nxi" == "%%j" set /A found=1
|
||||
)
|
||||
if not !found! == 1 rmdir /Q/S "%%i"
|
||||
)
|
||||
set retain=Oqtane.Modules.Admin.Login,Oqtane.Modules.HtmlText
|
||||
for /D %%i in ("..\Oqtane.Server\bin\Release\net9.0\publish\wwwroot\Modules\*") do (
|
||||
set /A found=0
|
||||
for %%j in (%retain%) do (
|
||||
if "%%~nxi" == "%%j" set /A found=1
|
||||
)
|
||||
if not !found! == 1 rmdir /Q/S "%%i"
|
||||
)
|
||||
set retain=Oqtane.Themes.BlazorTheme,Oqtane.Themes.OqtaneTheme
|
||||
for /D %%i in ("..\Oqtane.Server\bin\Release\net9.0\publish\wwwroot\Themes\*") do (
|
||||
set /A found=0
|
||||
for %%j in (%retain%) do (
|
||||
if "%%~nxi" == "%%j" set /A found=1
|
||||
)
|
||||
if not !found! == 1 rmdir /Q/S "%%i"
|
||||
)
|
||||
rmdir /Q /S "..\Oqtane.Server\bin\Release\net9.0\publish\Content"
|
||||
rmdir /Q /S "..\Oqtane.Server\bin\Release\net9.0\publish\wwwroot\Content"
|
||||
rmdir /Q /S "..\Oqtane.Server\bin\Release\net9.0\publish\runtimes\android-arm"
|
||||
rmdir /Q /S "..\Oqtane.Server\bin\Release\net9.0\publish\runtimes\android-arm64"
|
||||
rmdir /Q /S "..\Oqtane.Server\bin\Release\net9.0\publish\runtimes\android-x64"
|
||||
rmdir /Q /S "..\Oqtane.Server\bin\Release\net9.0\publish\runtimes\android-x86"
|
||||
rmdir /Q /S "..\Oqtane.Server\bin\Release\net9.0\publish\runtimes\ios-arm"
|
||||
rmdir /Q /S "..\Oqtane.Server\bin\Release\net9.0\publish\runtimes\ios-arm64"
|
||||
rmdir /Q /S "..\Oqtane.Server\bin\Release\net9.0\publish\runtimes\iossimulator-arm64"
|
||||
rmdir /Q /S "..\Oqtane.Server\bin\Release\net9.0\publish\runtimes\iossimulator-x64"
|
||||
rmdir /Q /S "..\Oqtane.Server\bin\Release\net9.0\publish\runtimes\iossimulator-x86"
|
||||
rmdir /Q /S "..\Oqtane.Server\bin\Release\net9.0\publish\wwwroot\Modules\Templates"
|
||||
rmdir /Q /S "..\Oqtane.Server\bin\Release\net9.0\publish\wwwroot\Themes\Templates"
|
||||
del "..\Oqtane.Server\bin\Release\net9.0\publish\appsettings.json"
|
||||
ren "..\Oqtane.Server\bin\Release\net9.0\publish\appsettings.release.json" "appsettings.json"
|
||||
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe ".\install.ps1"
|
||||
|
||||
28
Oqtane.Server/Controllers/MigrationHistoryController.cs
Normal file
28
Oqtane.Server/Controllers/MigrationHistoryController.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Oqtane.Models;
|
||||
using System.Collections.Generic;
|
||||
using Oqtane.Shared;
|
||||
using Oqtane.Repository;
|
||||
|
||||
namespace Oqtane.Controllers
|
||||
{
|
||||
[Route(ControllerRoutes.ApiRoute)]
|
||||
public class MigrationHistoryController : Controller
|
||||
{
|
||||
private readonly IMigrationHistoryRepository _history;
|
||||
|
||||
public MigrationHistoryController(IMigrationHistoryRepository history)
|
||||
{
|
||||
_history = history;
|
||||
}
|
||||
|
||||
// GET: api/<controller>
|
||||
[HttpGet]
|
||||
[Authorize(Roles = RoleNames.Host)]
|
||||
public IEnumerable<MigrationHistory> Get()
|
||||
{
|
||||
return _history.GetMigrationHistory();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -228,6 +228,7 @@ namespace Microsoft.Extensions.DependencyInjection
|
||||
services.AddScoped<IImageService, ImageService>();
|
||||
services.AddScoped<ICookieConsentService, ServerCookieConsentService>();
|
||||
services.AddScoped<ITimeZoneService, TimeZoneService>();
|
||||
services.AddScoped<IMigrationHistoryService, MigrationHistoryService>();
|
||||
|
||||
// providers
|
||||
services.AddScoped<ITextEditor, Oqtane.Modules.Controls.QuillJSTextEditor>();
|
||||
@@ -276,6 +277,7 @@ namespace Microsoft.Extensions.DependencyInjection
|
||||
services.AddTransient<IVisitorRepository, VisitorRepository>();
|
||||
services.AddTransient<IUrlMappingRepository, UrlMappingRepository>();
|
||||
services.AddTransient<ISearchContentRepository, SearchContentRepository>();
|
||||
services.AddTransient<IMigrationHistoryRepository, MigrationHistoryRepository>();
|
||||
|
||||
// managers
|
||||
services.AddTransient<IDBContextDependencies, DBContextDependencies>();
|
||||
|
||||
@@ -103,7 +103,7 @@ namespace Oqtane.Infrastructure
|
||||
break;
|
||||
}
|
||||
|
||||
await client.ConnectAsync(settingRepository.GetSettingValue(settings, "SMTPHost", ""),
|
||||
await client.ConnectAsync(settingRepository.GetSettingValue(settings, "SMTPHost", ""),
|
||||
int.Parse(settingRepository.GetSettingValue(settings, "SMTPPort", "")),
|
||||
secureSocketOptions);
|
||||
|
||||
@@ -143,69 +143,90 @@ namespace Oqtane.Infrastructure
|
||||
List<Notification> notifications = notificationRepository.GetNotifications(site.SiteId, -1, -1).ToList();
|
||||
foreach (Notification notification in notifications)
|
||||
{
|
||||
// get sender and receiver information from user object if not provided
|
||||
if ((string.IsNullOrEmpty(notification.FromEmail) || string.IsNullOrEmpty(notification.FromDisplayName)) && notification.FromUserId != null)
|
||||
var fromEmail = notification.FromEmail ?? "";
|
||||
var fromName = notification.FromDisplayName ?? "";
|
||||
var toEmail = notification.ToEmail ?? "";
|
||||
var toName = notification.ToDisplayName ?? "";
|
||||
|
||||
// get sender and receiver information from user information if available
|
||||
if ((string.IsNullOrEmpty(fromEmail) || string.IsNullOrEmpty(fromName)) && notification.FromUserId != null)
|
||||
{
|
||||
var user = userRepository.GetUser(notification.FromUserId.Value);
|
||||
if (user != null)
|
||||
{
|
||||
notification.FromEmail = (string.IsNullOrEmpty(notification.FromEmail)) ? user.Email : notification.FromEmail;
|
||||
notification.FromDisplayName = (string.IsNullOrEmpty(notification.FromDisplayName)) ? user.DisplayName : notification.FromDisplayName;
|
||||
fromEmail = string.IsNullOrEmpty(fromEmail) ? user.Email ?? "" : fromEmail;
|
||||
fromName = string.IsNullOrEmpty(fromName) ? user.DisplayName ?? "" : fromName;
|
||||
}
|
||||
}
|
||||
if ((string.IsNullOrEmpty(notification.ToEmail) || string.IsNullOrEmpty(notification.ToDisplayName)) && notification.ToUserId != null)
|
||||
if ((string.IsNullOrEmpty(toEmail) || string.IsNullOrEmpty(toName)) && notification.ToUserId != null)
|
||||
{
|
||||
var user = userRepository.GetUser(notification.ToUserId.Value);
|
||||
if (user != null)
|
||||
{
|
||||
notification.ToEmail = (string.IsNullOrEmpty(notification.ToEmail)) ? user.Email : notification.ToEmail;
|
||||
notification.ToDisplayName = (string.IsNullOrEmpty(notification.ToDisplayName)) ? user.DisplayName : notification.ToDisplayName;
|
||||
toEmail = string.IsNullOrEmpty(toEmail) ? user.Email ?? "" : toEmail;
|
||||
toName = string.IsNullOrEmpty(toName) ? user.DisplayName ?? "" : toName;
|
||||
}
|
||||
}
|
||||
|
||||
// validate recipient
|
||||
if (string.IsNullOrEmpty(notification.ToEmail) || !MailboxAddress.TryParse(notification.ToEmail, out _))
|
||||
// create mailbox addresses
|
||||
MailboxAddress to = null;
|
||||
MailboxAddress from = null;
|
||||
var mailboxAddressValidationError = "";
|
||||
|
||||
// sender
|
||||
if (settingRepository.GetSettingValue(settings, "SMTPRelay", "False") != "True")
|
||||
{
|
||||
log += $"NotificationId: {notification.NotificationId} - Has Missing Or Invalid Recipient {notification.ToEmail}<br />";
|
||||
notification.IsDeleted = true;
|
||||
notificationRepository.UpdateNotification(notification);
|
||||
fromEmail = settingRepository.GetSettingValue(settings, "SMTPSender", "");
|
||||
fromName = string.IsNullOrEmpty(fromName) ? site.Name : fromName;
|
||||
}
|
||||
else
|
||||
try
|
||||
{
|
||||
// exception handler is necessary because of https://github.com/jstedfast/MimeKit/issues/1186
|
||||
if (MailboxAddress.TryParse(fromEmail, out _))
|
||||
{
|
||||
from = new MailboxAddress(fromName, fromEmail);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// parse error creating sender mailbox address
|
||||
}
|
||||
if (from == null)
|
||||
{
|
||||
|
||||
mailboxAddressValidationError += $" Invalid Sender: {fromName} <{fromEmail}>";
|
||||
}
|
||||
|
||||
// recipient
|
||||
try
|
||||
{
|
||||
// exception handler is necessary because of https://github.com/jstedfast/MimeKit/issues/1186
|
||||
if (MailboxAddress.TryParse(toEmail, out _))
|
||||
{
|
||||
to = new MailboxAddress(toName, toEmail);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// parse error creating recipient mailbox address
|
||||
}
|
||||
if (to == null)
|
||||
{
|
||||
mailboxAddressValidationError += $" Invalid Recipient: {toName} <{toEmail}>";
|
||||
}
|
||||
|
||||
// if mailbox addresses are valid
|
||||
if (from != null && to != null)
|
||||
{
|
||||
// create mail message
|
||||
MimeMessage mailMessage = new MimeMessage();
|
||||
|
||||
// sender
|
||||
if (settingRepository.GetSettingValue(settings, "SMTPRelay", "False") == "True" && !string.IsNullOrEmpty(notification.FromEmail))
|
||||
{
|
||||
if (!string.IsNullOrEmpty(notification.FromDisplayName))
|
||||
{
|
||||
mailMessage.From.Add(new MailboxAddress(notification.FromDisplayName, notification.FromEmail));
|
||||
}
|
||||
else
|
||||
{
|
||||
mailMessage.From.Add(new MailboxAddress("", notification.FromEmail));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mailMessage.From.Add(new MailboxAddress((!string.IsNullOrEmpty(notification.FromDisplayName)) ? notification.FromDisplayName : site.Name,
|
||||
settingRepository.GetSettingValue(settings, "SMTPSender", "")));
|
||||
}
|
||||
|
||||
// recipient
|
||||
if (!string.IsNullOrEmpty(notification.ToDisplayName))
|
||||
{
|
||||
mailMessage.To.Add(new MailboxAddress(notification.ToDisplayName, notification.ToEmail));
|
||||
}
|
||||
else
|
||||
{
|
||||
mailMessage.To.Add(new MailboxAddress("", notification.ToEmail));
|
||||
}
|
||||
mailMessage.From.Add(from);
|
||||
mailMessage.To.Add(to);
|
||||
|
||||
// subject
|
||||
mailMessage.Subject = notification.Subject;
|
||||
|
||||
//body
|
||||
// body
|
||||
var bodyText = notification.Body;
|
||||
|
||||
if (!bodyText.Contains('<') || !bodyText.Contains('>'))
|
||||
@@ -230,14 +251,22 @@ namespace Oqtane.Infrastructure
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// error
|
||||
log += $"NotificationId: {notification.NotificationId} - {ex.Message}<br />";
|
||||
log += $"Error Sending Notification Id: {notification.NotificationId} - {ex.Message}<br />";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// invalid mailbox address
|
||||
log += $"Notification Id: {notification.NotificationId} Has An {mailboxAddressValidationError} And Has Been Deleted<br />";
|
||||
notification.IsDeleted = true;
|
||||
notificationRepository.UpdateNotification(notification);
|
||||
}
|
||||
}
|
||||
await client.DisconnectAsync(true);
|
||||
|
||||
log += "Notifications Delivered: " + sent + "<br />";
|
||||
}
|
||||
|
||||
await client.DisconnectAsync(true);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -33,5 +33,6 @@ namespace Oqtane.Repository
|
||||
public virtual DbSet<SearchContentProperty> SearchContentProperty { get; set; }
|
||||
public virtual DbSet<SearchContentWord> SearchContentWord { get; set; }
|
||||
public virtual DbSet<SearchWord> SearchWord { get; set; }
|
||||
public virtual DbSet<MigrationHistory> MigrationHistory { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
27
Oqtane.Server/Repository/MigrationHistoryRepository.cs
Normal file
27
Oqtane.Server/Repository/MigrationHistoryRepository.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Oqtane.Models;
|
||||
|
||||
namespace Oqtane.Repository
|
||||
{
|
||||
public interface IMigrationHistoryRepository
|
||||
{
|
||||
IEnumerable<MigrationHistory> GetMigrationHistory();
|
||||
}
|
||||
public class MigrationHistoryRepository : IMigrationHistoryRepository
|
||||
{
|
||||
private readonly IDbContextFactory<TenantDBContext> _dbContextFactory;
|
||||
|
||||
public MigrationHistoryRepository(IDbContextFactory<TenantDBContext> dbContextFactory)
|
||||
{
|
||||
_dbContextFactory = dbContextFactory;
|
||||
}
|
||||
|
||||
public IEnumerable<MigrationHistory> GetMigrationHistory()
|
||||
{
|
||||
using var db = _dbContextFactory.CreateDbContext();
|
||||
return db.MigrationHistory.ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -144,14 +144,14 @@ namespace Oqtane.Repository
|
||||
// delete notifications in batches of 100 records
|
||||
var count = 0;
|
||||
var purgedate = DateTime.UtcNow.AddDays(-age);
|
||||
var notifications = db.Notification.Where(item => item.SiteId == siteId && item.FromUserId == null && item.IsDelivered && item.DeliveredOn < purgedate)
|
||||
var notifications = db.Notification.Where(item => item.SiteId == siteId && item.FromUserId == null && (item.IsDeleted || item.IsDelivered && item.DeliveredOn < purgedate))
|
||||
.OrderBy(item => item.DeliveredOn).Take(100).ToList();
|
||||
while (notifications.Count > 0)
|
||||
{
|
||||
count += notifications.Count;
|
||||
db.Notification.RemoveRange(notifications);
|
||||
db.SaveChanges();
|
||||
notifications = db.Notification.Where(item => item.SiteId == siteId && item.FromUserId == null && item.IsDelivered && item.DeliveredOn < purgedate)
|
||||
notifications = db.Notification.Where(item => item.SiteId == siteId && item.FromUserId == null && (item.IsDeleted || item.IsDelivered && item.DeliveredOn < purgedate))
|
||||
.OrderBy(item => item.DeliveredOn).Take(100).ToList();
|
||||
}
|
||||
return count;
|
||||
|
||||
16
Oqtane.Shared/Models/MigrationHistory.cs
Normal file
16
Oqtane.Shared/Models/MigrationHistory.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Oqtane.Models
|
||||
{
|
||||
[Table("__EFMigrationsHistory")]
|
||||
[Keyless]
|
||||
public class MigrationHistory
|
||||
{
|
||||
public string MigrationId { get; set; }
|
||||
public string ProductVersion { get; set; }
|
||||
public DateTime AppliedDate { get; set; }
|
||||
public string AppliedVersion { get; set; }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user