Compare commits
187 Commits
Author | SHA1 | Date | |
---|---|---|---|
43627d4bb8 | |||
5d7b276cd1 | |||
23597eb997 | |||
b6948367f8 | |||
aaaf5683a5 | |||
92aa2236c0 | |||
d2592f72d6 | |||
27120d6cc9 | |||
a2669d35c3 | |||
574164081b | |||
00c2f8dcd8 | |||
0202bf60e5 | |||
16436a171b | |||
4cf4e0eabd | |||
5edb98dfb4 | |||
899bf22e15 | |||
9a33167a6c | |||
2dc068aa21 | |||
0f2aa4d2e1 | |||
a699f5c7bc | |||
ab807de3c0 | |||
68514bcb36 | |||
422bf8da59 | |||
de92dc93dd | |||
5a91b143b6 | |||
c745e85706 | |||
0f698e0c50 | |||
cd16d77bf0 | |||
fdbdd0ef4c | |||
71485f4a82 | |||
013056a6e5 | |||
263498fbdc | |||
f46ac2c007 | |||
c23841b6db | |||
18b1b5fca5 | |||
6707ac2697 | |||
d85a2fc8ce | |||
a8997e8f17 | |||
c8a22d9537 | |||
910669f786 | |||
89312c6796 | |||
a6aa96fdb0 | |||
7deb0b06af | |||
002f8117cb | |||
0dfdb12431 | |||
22e3161a9b | |||
b0c8203b24 | |||
5ee1731c92 | |||
06e8d3b660 | |||
f09709aedb | |||
598d5decac | |||
7832a6053e | |||
588748230e | |||
8668165c72 | |||
a967332f89 | |||
6719d242bd | |||
3565185808 | |||
ce51262197 | |||
992a786c2b | |||
038df95aa0 | |||
4ebd660de2 | |||
a9ea41a488 | |||
196594b490 | |||
1516d5af10 | |||
ffcd1595a9 | |||
42e5c6e111 | |||
8a9651dc50 | |||
4be2f4f2d9 | |||
369bf7a235 | |||
136545b404 | |||
73ea17ae0f | |||
23010acef4 | |||
4f74962ce2 | |||
7f978c7845 | |||
731fd46ea2 | |||
859759d691 | |||
5e9567158f | |||
51d244f3aa | |||
4c5a07edd5 | |||
8113a754a1 | |||
3cd40c6195 | |||
56cfb2ce06 | |||
72087823ac | |||
bcf7866fe2 | |||
b64772e484 | |||
088d665942 | |||
7d6c10befb | |||
f88e3d04b8 | |||
f57676a22b | |||
8618cb62e4 | |||
c31c88ed1f | |||
6022acd21f | |||
b3071b9272 | |||
ec6a6d6653 | |||
52f552b4de | |||
2643d3396b | |||
62d59a09cf | |||
a68ff8a4f0 | |||
93d4bfcd7a | |||
5fb80c1a7b | |||
04b38444ce | |||
ca3df02002 | |||
d952c33fab | |||
93bc1cd5af | |||
0e5b370ee8 | |||
f4fd4e28c9 | |||
ec8433eb45 | |||
0d4a40e9bb | |||
c3668f4179 | |||
3adb7ecb1c | |||
aa5b84a214 | |||
3d83fccbf1 | |||
4c4255be6b | |||
ed6054b082 | |||
f60f7a4dc1 | |||
998dc95cb2 | |||
12f5d7b846 | |||
906ae0a43e | |||
485b774876 | |||
3121cf5b75 | |||
ce7570dae2 | |||
b5ea0dfbc7 | |||
dd0f8f4772 | |||
9d0ab34274 | |||
e6038be6f7 | |||
bd2153a0ed | |||
e526deac20 | |||
b65f165dcf | |||
f9fbe5adc2 | |||
d1e73571a1 | |||
1047058676 | |||
29a1e77da8 | |||
290547e482 | |||
3df45ca20f | |||
cc06258484 | |||
2c262d0655 | |||
1875e1e158 | |||
1c95967b31 | |||
2ae98929de | |||
6a1dd38cbb | |||
c458a77d27 | |||
352c23f389 | |||
6c5a1dc2e1 | |||
004ff1e91d | |||
f7de4c567b | |||
b2ad1010ac | |||
660e164ff8 | |||
eb6dc80b50 | |||
a9882cc96a | |||
fb5a2ce178 | |||
d441b31dc7 | |||
d4239fe7e0 | |||
6a98999105 | |||
5caa1fe7d4 | |||
ef33bdb65e | |||
14a463382b | |||
1ad79874c8 | |||
1a61a58d28 | |||
3e3c973679 | |||
9dede84d20 | |||
e78b11cf62 | |||
341ca5a330 | |||
e5d8c02def | |||
947aa08c42 | |||
9a04d436bd | |||
be0754f568 | |||
93c4bbc0d1 | |||
b98535810b | |||
393cf8da1f | |||
ea2846973a | |||
3398c1cbfe | |||
39c79ea68e | |||
66900f4a32 | |||
df71dd14f7 | |||
8113ca3069 | |||
d468e675c2 | |||
1e84cedf82 | |||
7f4087e3de | |||
facd3c8956 | |||
3e50deecb7 | |||
628c504f84 | |||
e1ada78c1f | |||
09fa1e365c | |||
28b6b03d06 | |||
a4395b62ff | |||
4511acf273 | |||
fde53a2d83 |
3
.gitignore
vendored
3
.gitignore
vendored
@ -22,6 +22,9 @@ Oqtane.Server/Packages
|
|||||||
Oqtane.Server/wwwroot/Content
|
Oqtane.Server/wwwroot/Content
|
||||||
Oqtane.Server/wwwroot/Packages/*.log
|
Oqtane.Server/wwwroot/Packages/*.log
|
||||||
|
|
||||||
|
Oqtane.Server/wwwroot/_content/*
|
||||||
|
!Oqtane.Server/wwwroot/_content/Placeholder.txt
|
||||||
|
|
||||||
Oqtane.Server/wwwroot/Modules/*
|
Oqtane.Server/wwwroot/Modules/*
|
||||||
!Oqtane.Server/wwwroot/Modules/Oqtane.Modules.*
|
!Oqtane.Server/wwwroot/Modules/Oqtane.Modules.*
|
||||||
!Oqtane.Server/wwwroot/Modules/Templates
|
!Oqtane.Server/wwwroot/Modules/Templates
|
||||||
|
@ -51,6 +51,7 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||||||
services.AddScoped<IUrlMappingService, UrlMappingService>();
|
services.AddScoped<IUrlMappingService, UrlMappingService>();
|
||||||
services.AddScoped<IVisitorService, VisitorService>();
|
services.AddScoped<IVisitorService, VisitorService>();
|
||||||
services.AddScoped<ISyncService, SyncService>();
|
services.AddScoped<ISyncService, SyncService>();
|
||||||
|
services.AddScoped<ILocalizationCookieService, LocalizationCookieService>();
|
||||||
|
|
||||||
// providers
|
// providers
|
||||||
services.AddScoped<ITextEditor, Oqtane.Modules.Controls.QuillJSTextEditor>();
|
services.AddScoped<ITextEditor, Oqtane.Modules.Controls.QuillJSTextEditor>();
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="mx-auto text-center">
|
<div class="mx-auto text-center">
|
||||||
<img src="oqtane-black.png" />
|
<img src="oqtane-black.png" />
|
||||||
<div style="font-weight: bold">@SharedLocalizer["Version"] @Constants.Version (.NET 8)</div>
|
<div style="font-weight: bold">@SharedLocalizer["Version"] @Constants.Version (.NET 9)</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<hr class="app-rule" />
|
<hr class="app-rule" />
|
||||||
@ -238,7 +238,8 @@
|
|||||||
|
|
||||||
if (connectionString != "" && !string.IsNullOrEmpty(_hostUsername) && !string.IsNullOrEmpty(_hostPassword) && _hostPassword == _confirmPassword && !string.IsNullOrEmpty(_hostEmail) && _hostEmail.Contains("@"))
|
if (connectionString != "" && !string.IsNullOrEmpty(_hostUsername) && !string.IsNullOrEmpty(_hostPassword) && _hostPassword == _confirmPassword && !string.IsNullOrEmpty(_hostEmail) && _hostEmail.Contains("@"))
|
||||||
{
|
{
|
||||||
if (await UserService.ValidatePasswordAsync(_hostPassword))
|
var result = await UserService.ValidateUserAsync(_hostUsername, _hostEmail, _hostPassword);
|
||||||
|
if (result.Succeeded)
|
||||||
{
|
{
|
||||||
_loadingDisplay = "";
|
_loadingDisplay = "";
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
@ -278,7 +279,7 @@
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_message = Localizer["Message.Password.Invalid"];
|
_message = string.Join("<br />", result.Errors.Select(i => !string.IsNullOrEmpty(i.Value) ? i.Value : Localizer[i.Key]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
@namespace Oqtane.Modules.Admin.Languages
|
@namespace Oqtane.Modules.Admin.Languages
|
||||||
@inherits ModuleBase
|
@inherits ModuleBase
|
||||||
@using System.Globalization
|
@using System.Globalization
|
||||||
@using Microsoft.AspNetCore.Localization
|
|
||||||
@inject NavigationManager NavigationManager
|
@inject NavigationManager NavigationManager
|
||||||
@inject ILocalizationService LocalizationService
|
@inject ILocalizationService LocalizationService
|
||||||
@inject ILanguageService LanguageService
|
@inject ILanguageService LanguageService
|
||||||
@ -94,7 +93,6 @@ else
|
|||||||
var language = new Language
|
var language = new Language
|
||||||
{
|
{
|
||||||
SiteId = PageState.Page.SiteId,
|
SiteId = PageState.Page.SiteId,
|
||||||
Name = CultureInfo.GetCultureInfo(_code).DisplayName,
|
|
||||||
Code = _code,
|
Code = _code,
|
||||||
IsDefault = (_default == null ? false : Boolean.Parse(_default))
|
IsDefault = (_default == null ? false : Boolean.Parse(_default))
|
||||||
};
|
};
|
||||||
@ -130,7 +128,7 @@ else
|
|||||||
{
|
{
|
||||||
var interop = new Interop(JSRuntime);
|
var interop = new Interop(JSRuntime);
|
||||||
var localizationCookieValue = CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture));
|
var localizationCookieValue = CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture));
|
||||||
await interop.SetCookie(CookieRequestCultureProvider.DefaultCookieName, localizationCookieValue, 360);
|
await interop.SetCookie(CookieRequestCultureProvider.DefaultCookieName, localizationCookieValue, 360, true, "Lax");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
@namespace Oqtane.Modules.Admin.Languages
|
@namespace Oqtane.Modules.Admin.Languages
|
||||||
@inherits ModuleBase
|
@inherits ModuleBase
|
||||||
@using System.Globalization
|
@using System.Globalization
|
||||||
@using Microsoft.AspNetCore.Localization
|
|
||||||
@inject NavigationManager NavigationManager
|
@inject NavigationManager NavigationManager
|
||||||
@inject ILocalizationService LocalizationService
|
@inject ILocalizationService LocalizationService
|
||||||
@inject ILanguageService LanguageService
|
@inject ILanguageService LanguageService
|
||||||
@ -103,7 +102,7 @@ else
|
|||||||
{
|
{
|
||||||
var interop = new Interop(JSRuntime);
|
var interop = new Interop(JSRuntime);
|
||||||
var localizationCookieValue = CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture));
|
var localizationCookieValue = CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture));
|
||||||
await interop.SetCookie(CookieRequestCultureProvider.DefaultCookieName, localizationCookieValue, 360);
|
await interop.SetCookie(CookieRequestCultureProvider.DefaultCookieName, localizationCookieValue, 360, true, "Lax");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="description" HelpText="Enter a short description for the module" ResourceKey="Description">Description: </Label>
|
<Label Class="col-sm-3" For="description" HelpText="Enter a short description for the module" ResourceKey="Description">Description: </Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<textarea id="description" class="form-control" @bind="@_description" rows="3" maxlength="2000" required></textarea>
|
<textarea id="description" class="form-control" @bind="@_description" rows="3" maxlength="2000"></textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
@ -118,6 +118,7 @@
|
|||||||
{
|
{
|
||||||
if (IsValid(_owner) && IsValid(_module) && _owner != _module && _template != "-")
|
if (IsValid(_owner) && IsValid(_module) && _owner != _module && _template != "-")
|
||||||
{
|
{
|
||||||
|
if (string.IsNullOrEmpty(_description)) _description = _module;
|
||||||
if (IsValidXML(_description))
|
if (IsValidXML(_description))
|
||||||
{
|
{
|
||||||
var template = _templates.FirstOrDefault(item => item.Name == _template);
|
var template = _templates.FirstOrDefault(item => item.Name == _template);
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
@namespace Oqtane.Modules.Admin.ModuleDefinitions
|
@namespace Oqtane.Modules.Admin.ModuleDefinitions
|
||||||
@inherits ModuleBase
|
@inherits ModuleBase
|
||||||
@using System.Globalization
|
@using System.Globalization
|
||||||
@using Microsoft.AspNetCore.Localization
|
|
||||||
@inject IModuleDefinitionService ModuleDefinitionService
|
@inject IModuleDefinitionService ModuleDefinitionService
|
||||||
@inject IPackageService PackageService
|
@inject IPackageService PackageService
|
||||||
@inject ILanguageService LanguageService
|
@inject ILanguageService LanguageService
|
||||||
|
@ -22,7 +22,7 @@ else
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
<Pager Items="@_pages.Where(item => item.IsDeleted)" CurrentPage="@_pagePage.ToString()" OnPageChange="OnPageChangePage">
|
<Pager Items="@_pages.Where(item => item.IsDeleted).OrderByDescending(item => item.DeletedOn)" CurrentPage="@_pagePage.ToString()" OnPageChange="OnPageChangePage">
|
||||||
<Header>
|
<Header>
|
||||||
<th style="width: 1px;"> </th>
|
<th style="width: 1px;"> </th>
|
||||||
<th style="width: 1px;"> </th>
|
<th style="width: 1px;"> </th>
|
||||||
@ -50,7 +50,7 @@ else
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
<Pager Items="@_modules.Where(item => item.IsDeleted)" CurrentPage="@_pageModule.ToString()" OnPageChange="OnPageChangeModule">
|
<Pager Items="@_modules.Where(item => item.IsDeleted).OrderByDescending(item => item.DeletedOn)" CurrentPage="@_pageModule.ToString()" OnPageChange="OnPageChangeModule">
|
||||||
<Header>
|
<Header>
|
||||||
<th style="width: 1px;"> </th>
|
<th style="width: 1px;"> </th>
|
||||||
<th style="width: 1px;"> </th>
|
<th style="width: 1px;"> </th>
|
||||||
|
@ -63,7 +63,7 @@
|
|||||||
private string _enabled = "True";
|
private string _enabled = "True";
|
||||||
private string _lastIndexedOn = "";
|
private string _lastIndexedOn = "";
|
||||||
private string _ignorePages = "";
|
private string _ignorePages = "";
|
||||||
private string _ignoreEntities = "";
|
private string _ignoreEntities = "File";
|
||||||
private string _minimumWordLength = "3";
|
private string _minimumWordLength = "3";
|
||||||
private string _ignoreWords = "the,be,to,of,and,a,i,in,that,have,it,for,not,on,with,he,as,you,do,at,this,but,his,by,from,they,we,say,her,she,or,an,will,my,one,all,would,there,their,what,so,up,out,if,about,who,get,which,go,me,when,make,can,like,time,no,just,him,know,take,people,into,year,your,good,some,could,them,see,other,than,then,now,look,only,come,its,over,think,also,back,after,use,two,how,our,work,first,well,way,even,new,want,because,any,these,give,day,most,us";
|
private string _ignoreWords = "the,be,to,of,and,a,i,in,that,have,it,for,not,on,with,he,as,you,do,at,this,but,his,by,from,they,we,say,her,she,or,an,will,my,one,all,would,there,their,what,so,up,out,if,about,who,get,which,go,me,when,make,can,like,time,no,just,him,know,take,people,into,year,your,good,some,could,them,see,other,than,then,now,look,only,come,its,over,think,also,back,after,use,two,how,our,work,first,well,way,even,new,want,because,any,these,give,day,most,us";
|
||||||
|
|
||||||
@ -85,7 +85,7 @@
|
|||||||
{
|
{
|
||||||
var settings = await SettingService.GetSiteSettingsAsync(PageState.Site.SiteId);
|
var settings = await SettingService.GetSiteSettingsAsync(PageState.Site.SiteId);
|
||||||
settings = SettingService.SetSetting(settings, "Search_SearchProvider", _searchProvider);
|
settings = SettingService.SetSetting(settings, "Search_SearchProvider", _searchProvider);
|
||||||
settings = SettingService.SetSetting(settings, "Search_Enabled", _enabled, true);
|
settings = SettingService.SetSetting(settings, "Search_Enabled", _enabled);
|
||||||
settings = SettingService.SetSetting(settings, "Search_LastIndexedOn", _lastIndexedOn, true);
|
settings = SettingService.SetSetting(settings, "Search_LastIndexedOn", _lastIndexedOn, true);
|
||||||
settings = SettingService.SetSetting(settings, "Search_IgnorePages", _ignorePages, true);
|
settings = SettingService.SetSetting(settings, "Search_IgnorePages", _ignorePages, true);
|
||||||
settings = SettingService.SetSetting(settings, "Search_IgnoreEntities", _ignoreEntities, true);
|
settings = SettingService.SetSetting(settings, "Search_IgnoreEntities", _ignoreEntities, true);
|
||||||
@ -106,9 +106,7 @@
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
_lastIndexedOn = DateTime.MinValue.ToString();
|
_lastIndexedOn = DateTime.MinValue.ToString();
|
||||||
var settings = await SettingService.GetSiteSettingsAsync(PageState.Site.SiteId);
|
await Save();
|
||||||
settings = SettingService.SetSetting(settings, "Search_LastIndexedOn", _lastIndexedOn, true);
|
|
||||||
await SettingService.UpdateSiteSettingsAsync(settings, PageState.Site.SiteId);
|
|
||||||
AddModuleMessage(Localizer["Message.Reindex"], MessageType.Success);
|
AddModuleMessage(Localizer["Message.Reindex"], MessageType.Success);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
@ -376,7 +376,7 @@
|
|||||||
<Section Name="TenantInformation" Heading="Database" ResourceKey="TenantInformation">
|
<Section Name="TenantInformation" Heading="Database" ResourceKey="TenantInformation">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="tenant" HelpText="The name of the database used for the site" ResourceKey="Tenant">Database: </Label>
|
<Label Class="col-sm-3" For="tenant" HelpText="The name of the database used for the site. 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">
|
<div class="col-sm-9">
|
||||||
<input id="tenant" class="form-control" @bind="@_tenant" readonly />
|
<input id="tenant" class="form-control" @bind="@_tenant" readonly />
|
||||||
</div>
|
</div>
|
||||||
@ -388,7 +388,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="connectionstring" HelpText="The connection information for the database" ResourceKey="ConnectionString">Connection: </Label>
|
<Label Class="col-sm-3" For="connectionstring" HelpText="The name of the connection string in appsettings.json which will be used to connect to the database" ResourceKey="ConnectionString">Connection: </Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<input id="connectionstring" class="form-control" @bind="@_connectionstring" readonly />
|
<input id="connectionstring" class="form-control" @bind="@_connectionstring" readonly />
|
||||||
</div>
|
</div>
|
||||||
@ -571,7 +571,7 @@
|
|||||||
if (tenant != null)
|
if (tenant != null)
|
||||||
{
|
{
|
||||||
_tenant = tenant.Name;
|
_tenant = tenant.Name;
|
||||||
_database = _databases.Find(item => item.DBType == tenant.DBType)?.Name;
|
_database = _databases.Find(item => item.DBType == tenant.DBType && item.Name != "LocalDB")?.Name;
|
||||||
_connectionstring = tenant.DBConnectionString;
|
_connectionstring = tenant.DBConnectionString;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -109,7 +109,7 @@ else
|
|||||||
<hr class="app-rule" />
|
<hr class="app-rule" />
|
||||||
</div>
|
</div>
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="name" HelpText="Enter the name for the database" ResourceKey="TenantName">Name: </Label>
|
<Label Class="col-sm-3" For="name" HelpText="Enter the name for the database. Note that this will be the tenant name which is used within the framework to identify the database." ResourceKey="TenantName">Name: </Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<input id="name" class="form-control" @bind="@_tenantName" maxlength="100" required />
|
<input id="name" class="form-control" @bind="@_tenantName" maxlength="100" required />
|
||||||
</div>
|
</div>
|
||||||
|
@ -83,23 +83,14 @@ else
|
|||||||
{
|
{
|
||||||
@if (_connection != "-")
|
@if (_connection != "-")
|
||||||
{
|
{
|
||||||
|
@if (!string.IsNullOrEmpty(_tenant))
|
||||||
|
{
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="databasetype" HelpText="The database type" ResourceKey="DatabaseType">Type: </Label>
|
<Label Class="col-sm-3" For="databasetype" HelpText="The database type" ResourceKey="DatabaseType">Type: </Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
@if (_databases != null)
|
<input id="databasetype" class="form-control" @bind="@_databasetype" readonly />
|
||||||
{
|
|
||||||
<select id="databasetype" class="form-select" @bind="@_databasetype" required>
|
|
||||||
<option value="-"><@Localizer["Type.Select"]></option>
|
|
||||||
@foreach (var database in _databases)
|
|
||||||
{
|
|
||||||
<option value="@database.Name">@Localizer[@database.Name]</option>
|
|
||||||
}
|
|
||||||
</select>
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@if (!string.IsNullOrEmpty(_tenant))
|
|
||||||
{
|
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="tenant" HelpText="The database using this connection" ResourceKey="Tenant">Database: </Label>
|
<Label Class="col-sm-3" For="tenant" HelpText="The database using this connection" ResourceKey="Tenant">Database: </Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
@ -204,12 +195,12 @@ else
|
|||||||
{
|
{
|
||||||
_connectionstring = _connections[_connection].ToString();
|
_connectionstring = _connections[_connection].ToString();
|
||||||
_tenant = "";
|
_tenant = "";
|
||||||
_databasetype = "-";
|
_databasetype = "";
|
||||||
var tenant = _tenants.FirstOrDefault(item => item.DBConnectionString == _connection);
|
var tenant = _tenants.FirstOrDefault(item => item.DBConnectionString == _connection);
|
||||||
if (tenant != null)
|
if (tenant != null)
|
||||||
{
|
{
|
||||||
_tenant = tenant.Name;
|
_tenant = tenant.Name;
|
||||||
_databasetype = _databases.FirstOrDefault(item => item.DBType == tenant.DBType).Name;
|
_databasetype = _databases.FirstOrDefault(item => item.DBType == tenant.DBType && item.Name != "LocalDB").Name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -54,6 +54,8 @@
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
AddModuleMessage(Localizer["Disclaimer.Text"], MessageType.Warning);
|
||||||
|
|
||||||
List<Package> packages = await PackageService.GetPackagesAsync("framework", "", "", "");
|
List<Package> packages = await PackageService.GetPackagesAsync("framework", "", "", "");
|
||||||
if (packages != null)
|
if (packages != null)
|
||||||
{
|
{
|
||||||
@ -97,13 +99,16 @@
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
ShowProgressIndicator();
|
||||||
await PackageService.DownloadPackageAsync(packageid, version);
|
await PackageService.DownloadPackageAsync(packageid, version);
|
||||||
await PackageService.DownloadPackageAsync(Constants.UpdaterPackageId, version);
|
await PackageService.DownloadPackageAsync(Constants.UpdaterPackageId, version);
|
||||||
|
HideProgressIndicator();
|
||||||
AddModuleMessage(Localizer["Success.Framework.Download"], MessageType.Success);
|
AddModuleMessage(Localizer["Success.Framework.Download"], MessageType.Success);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await logger.LogError(ex, "Error Downloading Framework Package {Error}", ex.Message);
|
await logger.LogError(ex, "Error Downloading Framework Package {Error}", ex.Message);
|
||||||
|
HideProgressIndicator();
|
||||||
AddModuleMessage(Localizer["Error.Framework.Download"], MessageType.Error);
|
AddModuleMessage(Localizer["Error.Framework.Download"], MessageType.Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -182,13 +182,31 @@ else
|
|||||||
</div>
|
</div>
|
||||||
</Section>
|
</Section>
|
||||||
<Section Name="ExternalLogin" Heading="External Login Settings" ResourceKey="ExternalLoginSettings">
|
<Section Name="ExternalLogin" Heading="External Login Settings" ResourceKey="ExternalLoginSettings">
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="provider" HelpText="Select the external login provider" ResourceKey="Provider">Provider:</Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<div class="input-group">
|
||||||
|
<select id="provider" class="form-select" value="@_provider" @onchange="(e => ProviderChanged(e))">
|
||||||
|
@foreach (var provider in Shared.ExternalLoginProviders.Providers)
|
||||||
|
{
|
||||||
|
<option value="@provider.Name">@Localizer[provider.Name]</option>
|
||||||
|
}
|
||||||
|
</select>
|
||||||
|
@if (!string.IsNullOrEmpty(_providerurl))
|
||||||
|
{
|
||||||
|
<a href="@_providerurl" class="btn btn-secondary" target="_new">@Localizer["Info"]</a>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="providertype" HelpText="Select the external login provider type" ResourceKey="ProviderType">Provider Type:</Label>
|
<Label Class="col-sm-3" For="providertype" HelpText="Select the external login provider type" ResourceKey="ProviderType">Provider Type:</Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<select id="providertype" class="form-select" value="@_providertype" @onchange="(e => ProviderTypeChanged(e))">
|
<select id="providertype" class="form-select" value="@_providertype" @onchange="(e => ProviderTypeChanged(e))">
|
||||||
<option value="" selected>@Localizer["Not Specified"]</option>
|
<option value="" selected><@Localizer["Not Specified"]></option>
|
||||||
<option value="@AuthenticationProviderTypes.OpenIDConnect">@Localizer["OpenID Connect"]</option>
|
<option value="@AuthenticationProviderTypes.OpenIDConnect">@Localizer["OIDC"]</option>
|
||||||
<option value="@AuthenticationProviderTypes.OAuth2">@Localizer["OAuth 2.0"]</option>
|
<option value="@AuthenticationProviderTypes.OAuth2">@Localizer["OAuth2"]</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -452,6 +470,8 @@ else
|
|||||||
private string _maximumfailures;
|
private string _maximumfailures;
|
||||||
private string _lockoutduration;
|
private string _lockoutduration;
|
||||||
|
|
||||||
|
private string _provider;
|
||||||
|
private string _providerurl;
|
||||||
private string _providertype;
|
private string _providertype;
|
||||||
private string _providername;
|
private string _providername;
|
||||||
private string _authority;
|
private string _authority;
|
||||||
@ -519,6 +539,20 @@ else
|
|||||||
_maximumfailures = SettingService.GetSetting(settings, "IdentityOptions:Lockout:MaxFailedAccessAttempts", "5");
|
_maximumfailures = SettingService.GetSetting(settings, "IdentityOptions:Lockout:MaxFailedAccessAttempts", "5");
|
||||||
_lockoutduration = TimeSpan.Parse(SettingService.GetSetting(settings, "IdentityOptions:Lockout:DefaultLockoutTimeSpan", "00:05:00")).TotalMinutes.ToString();
|
_lockoutduration = TimeSpan.Parse(SettingService.GetSetting(settings, "IdentityOptions:Lockout:DefaultLockoutTimeSpan", "00:05:00")).TotalMinutes.ToString();
|
||||||
|
|
||||||
|
LoadExternalLoginSettings(settings);
|
||||||
|
|
||||||
|
_secret = SettingService.GetSetting(settings, "JwtOptions:Secret", "");
|
||||||
|
_togglesecret = SharedLocalizer["ShowPassword"];
|
||||||
|
_issuer = SettingService.GetSetting(settings, "JwtOptions:Issuer", PageState.Uri.Scheme + "://" + PageState.Alias.Name);
|
||||||
|
_audience = SettingService.GetSetting(settings, "JwtOptions:Audience", "");
|
||||||
|
_lifetime = SettingService.GetSetting(settings, "JwtOptions:Lifetime", "20");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadExternalLoginSettings(Dictionary<string, string> settings)
|
||||||
|
{
|
||||||
|
_provider = SettingService.GetSetting(settings, "ExternalLogin:Provider", "<Custom>");
|
||||||
|
_providerurl = SettingService.GetSetting(settings, "ExternalLogin:ProviderUrl", "");
|
||||||
_providertype = SettingService.GetSetting(settings, "ExternalLogin:ProviderType", "");
|
_providertype = SettingService.GetSetting(settings, "ExternalLogin:ProviderType", "");
|
||||||
_providername = SettingService.GetSetting(settings, "ExternalLogin:ProviderName", "");
|
_providername = SettingService.GetSetting(settings, "ExternalLogin:ProviderName", "");
|
||||||
_authority = SettingService.GetSetting(settings, "ExternalLogin:Authority", "");
|
_authority = SettingService.GetSetting(settings, "ExternalLogin:Authority", "");
|
||||||
@ -546,13 +580,6 @@ else
|
|||||||
_domainfilter = SettingService.GetSetting(settings, "ExternalLogin:DomainFilter", "");
|
_domainfilter = SettingService.GetSetting(settings, "ExternalLogin:DomainFilter", "");
|
||||||
_createusers = SettingService.GetSetting(settings, "ExternalLogin:CreateUsers", "true");
|
_createusers = SettingService.GetSetting(settings, "ExternalLogin:CreateUsers", "true");
|
||||||
_verifyusers = SettingService.GetSetting(settings, "ExternalLogin:VerifyUsers", "true");
|
_verifyusers = SettingService.GetSetting(settings, "ExternalLogin:VerifyUsers", "true");
|
||||||
|
|
||||||
_secret = SettingService.GetSetting(settings, "JwtOptions:Secret", "");
|
|
||||||
_togglesecret = SharedLocalizer["ShowPassword"];
|
|
||||||
_issuer = SettingService.GetSetting(settings, "JwtOptions:Issuer", PageState.Uri.Scheme + "://" + PageState.Alias.Name);
|
|
||||||
_audience = SettingService.GetSetting(settings, "JwtOptions:Audience", "");
|
|
||||||
_lifetime = SettingService.GetSetting(settings, "JwtOptions:Lifetime", "20");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task LoadUsersAsync(bool load)
|
private async Task LoadUsersAsync(bool load)
|
||||||
@ -617,6 +644,7 @@ else
|
|||||||
settings = SettingService.SetSetting(settings, "IdentityOptions:Lockout:MaxFailedAccessAttempts", _maximumfailures, true);
|
settings = SettingService.SetSetting(settings, "IdentityOptions:Lockout:MaxFailedAccessAttempts", _maximumfailures, true);
|
||||||
settings = SettingService.SetSetting(settings, "IdentityOptions:Lockout:DefaultLockoutTimeSpan", TimeSpan.FromMinutes(Convert.ToInt64(_lockoutduration)).ToString(), true);
|
settings = SettingService.SetSetting(settings, "IdentityOptions:Lockout:DefaultLockoutTimeSpan", TimeSpan.FromMinutes(Convert.ToInt64(_lockoutduration)).ToString(), true);
|
||||||
|
|
||||||
|
settings = SettingService.SetSetting(settings, "ExternalLogin:Provider", _provider, false);
|
||||||
settings = SettingService.SetSetting(settings, "ExternalLogin:ProviderType", _providertype, false);
|
settings = SettingService.SetSetting(settings, "ExternalLogin:ProviderType", _providertype, false);
|
||||||
settings = SettingService.SetSetting(settings, "ExternalLogin:ProviderName", _providername, false);
|
settings = SettingService.SetSetting(settings, "ExternalLogin:ProviderName", _providername, false);
|
||||||
settings = SettingService.SetSetting(settings, "ExternalLogin:Authority", _authority, true);
|
settings = SettingService.SetSetting(settings, "ExternalLogin:Authority", _authority, true);
|
||||||
@ -663,6 +691,21 @@ else
|
|||||||
await logger.LogError(ex, "Error Saving Site Settings {Error}", ex.Message);
|
await logger.LogError(ex, "Error Saving Site Settings {Error}", ex.Message);
|
||||||
AddModuleMessage(Localizer["Error.SaveSiteSettings"], MessageType.Error);
|
AddModuleMessage(Localizer["Error.SaveSiteSettings"], MessageType.Error);
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
await ScrollToPageTop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ProviderChanged(ChangeEventArgs e)
|
||||||
|
{
|
||||||
|
_provider = (string)e.Value;
|
||||||
|
var provider = Shared.ExternalLoginProviders.Providers.FirstOrDefault(item => item.Name == _provider);
|
||||||
|
if (provider != null)
|
||||||
|
{
|
||||||
|
LoadExternalLoginSettings(provider.Settings);
|
||||||
|
}
|
||||||
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ProviderTypeChanged(ChangeEventArgs e)
|
private void ProviderTypeChanged(ChangeEventArgs e)
|
||||||
|
@ -226,9 +226,9 @@
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FileId = -1; // file does not exist
|
|
||||||
_message = "FileId " + FileId.ToString() + " Does Not Exist";
|
_message = "FileId " + FileId.ToString() + " Does Not Exist";
|
||||||
_messagetype = MessageType.Error;
|
_messagetype = MessageType.Error;
|
||||||
|
FileId = -1; // file does not exist
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,6 +10,8 @@
|
|||||||
{
|
{
|
||||||
<NavLink class="ms-2" href="@NavigateUrl("admin/log")">View Details</NavLink>
|
<NavLink class="ms-2" href="@NavigateUrl("admin/log")">View Details</NavLink>
|
||||||
}
|
}
|
||||||
|
@if (ModuleState != null)
|
||||||
|
{
|
||||||
@if (ModuleState.RenderMode == RenderModes.Static)
|
@if (ModuleState.RenderMode == RenderModes.Static)
|
||||||
{
|
{
|
||||||
<a href="@NavigationManager.Uri" class="btn-close" data-dismiss="alert" aria-label="close"></a>
|
<a href="@NavigationManager.Uri" class="btn-close" data-dismiss="alert" aria-label="close"></a>
|
||||||
@ -18,6 +20,7 @@
|
|||||||
{
|
{
|
||||||
<button type="button" class="btn-close" data-dismiss="alert" aria-label="close" @onclick="CloseMessage"></button>
|
<button type="button" class="btn-close" data-dismiss="alert" aria-label="close" @onclick="CloseMessage"></button>
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -452,9 +452,9 @@
|
|||||||
_displayPages = int.Parse(DisplayPages);
|
_displayPages = int.Parse(DisplayPages);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PageState.QueryString.ContainsKey("page"))
|
if (PageState.QueryString.ContainsKey("page") && int.TryParse(PageState.QueryString["page"], out int page))
|
||||||
{
|
{
|
||||||
_page = int.Parse(PageState.QueryString["page"]);
|
_page = page;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
|
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<Configurations>Debug;Release</Configurations>
|
<Configurations>Debug;Release</Configurations>
|
||||||
<Version>5.2.3</Version>
|
<Version>6.0.0</Version>
|
||||||
<Product>Oqtane</Product>
|
<Product>Oqtane</Product>
|
||||||
<Authors>Shaun Walker</Authors>
|
<Authors>Shaun Walker</Authors>
|
||||||
<Company>.NET Foundation</Company>
|
<Company>.NET Foundation</Company>
|
||||||
@ -12,7 +12,7 @@
|
|||||||
<Copyright>.NET Foundation</Copyright>
|
<Copyright>.NET Foundation</Copyright>
|
||||||
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
||||||
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
||||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.2.3</PackageReleaseNotes>
|
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v6.0.0</PackageReleaseNotes>
|
||||||
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
||||||
<RepositoryType>Git</RepositoryType>
|
<RepositoryType>Git</RepositoryType>
|
||||||
<RootNamespace>Oqtane</RootNamespace>
|
<RootNamespace>Oqtane</RootNamespace>
|
||||||
@ -22,11 +22,10 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="8.0.8" />
|
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="9.0.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="8.0.8" />
|
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="9.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="8.0.8" />
|
<PackageReference Include="Microsoft.Extensions.Localization" Version="9.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Http" Version="8.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Http" Version="9.0.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Localization" Version="2.2.0" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.IO.Compression;
|
using System.IO.Compression;
|
||||||
@ -13,13 +12,13 @@ using System.Text.Json;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Components;
|
using Microsoft.AspNetCore.Components;
|
||||||
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
|
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
|
||||||
using Microsoft.AspNetCore.Localization;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.JSInterop;
|
using Microsoft.JSInterop;
|
||||||
using Oqtane.Documentation;
|
using Oqtane.Documentation;
|
||||||
using Oqtane.Models;
|
using Oqtane.Models;
|
||||||
using Oqtane.Modules;
|
using Oqtane.Modules;
|
||||||
using Oqtane.Services;
|
using Oqtane.Services;
|
||||||
|
using Oqtane.Shared;
|
||||||
using Oqtane.UI;
|
using Oqtane.UI;
|
||||||
|
|
||||||
namespace Oqtane.Client
|
namespace Oqtane.Client
|
||||||
@ -258,7 +257,7 @@ namespace Oqtane.Client
|
|||||||
var jsRuntime = serviceProvider.GetRequiredService<IJSRuntime>();
|
var jsRuntime = serviceProvider.GetRequiredService<IJSRuntime>();
|
||||||
var interop = new Interop(jsRuntime);
|
var interop = new Interop(jsRuntime);
|
||||||
var localizationCookie = await interop.GetCookie(CookieRequestCultureProvider.DefaultCookieName);
|
var localizationCookie = await interop.GetCookie(CookieRequestCultureProvider.DefaultCookieName);
|
||||||
var culture = CookieRequestCultureProvider.ParseCookieValue(localizationCookie)?.UICultures?[0].Value;
|
var culture = CookieRequestCultureProvider.ParseCookieValue(localizationCookie)?.UICulture.Name;
|
||||||
var localizationService = serviceProvider.GetRequiredService<ILocalizationService>();
|
var localizationService = serviceProvider.GetRequiredService<ILocalizationService>();
|
||||||
var cultures = await localizationService.GetCulturesAsync(false);
|
var cultures = await localizationService.GetCulturesAsync(false);
|
||||||
|
|
||||||
|
@ -183,4 +183,7 @@
|
|||||||
<data name="Template" xml:space="preserve">
|
<data name="Template" xml:space="preserve">
|
||||||
<value>Select a site template</value>
|
<value>Select a site template</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Message.Username.Invalid" xml:space="preserve">
|
||||||
|
<value>The Username Provided Does Not Meet The System Requirement, It Can Only Contains Letters Or Digits.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
@ -139,7 +139,7 @@
|
|||||||
<value>Ignore Entities: </value>
|
<value>Ignore Entities: </value>
|
||||||
</data>
|
</data>
|
||||||
<data name="IgnoreEntities.HelpText" xml:space="preserve">
|
<data name="IgnoreEntities.HelpText" xml:space="preserve">
|
||||||
<value>Comma delimited list of entities which should be ignored</value>
|
<value>Comma delimited list of entities which should be ignored. By default File entities are ignored.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MinimumWordLength.Text" xml:space="preserve">
|
<data name="MinimumWordLength.Text" xml:space="preserve">
|
||||||
<value>Word Length: </value>
|
<value>Word Length: </value>
|
||||||
@ -154,7 +154,7 @@
|
|||||||
<value>Comma delimited list of words which should be ignored</value>
|
<value>Comma delimited list of words which should be ignored</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Success.Save" xml:space="preserve">
|
<data name="Success.Save" xml:space="preserve">
|
||||||
<value>Search Settings Saved Successfully</value>
|
<value>Search Settings Saved Successfully. You Will Need Reindex For Your Changes To Be Reflected In The Search Results.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Error.Save" xml:space="preserve">
|
<data name="Error.Save" xml:space="preserve">
|
||||||
<value>Error Saving Search Settings</value>
|
<value>Error Saving Search Settings</value>
|
||||||
|
@ -163,7 +163,7 @@
|
|||||||
<value>Enter the site name</value>
|
<value>Enter the site name</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Tenant.HelpText" xml:space="preserve">
|
<data name="Tenant.HelpText" xml:space="preserve">
|
||||||
<value>The name of the database used for the site</value>
|
<value>The name of the database used for the site. 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>
|
</data>
|
||||||
<data name="Aliases.HelpText" xml:space="preserve">
|
<data name="Aliases.HelpText" xml:space="preserve">
|
||||||
<value>The urls for the site. This can include domain names (ie. domain.com), subdomains (ie. sub.domain.com) or virtual folders (ie. domain.com/folder).</value>
|
<value>The urls for the site. This can include domain names (ie. domain.com), subdomains (ie. sub.domain.com) or virtual folders (ie. domain.com/folder).</value>
|
||||||
@ -307,7 +307,7 @@
|
|||||||
<value>Type:</value>
|
<value>Type:</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ConnectionString.HelpText" xml:space="preserve">
|
<data name="ConnectionString.HelpText" xml:space="preserve">
|
||||||
<value>The connection information for the database</value>
|
<value>The name of the connection string in appsettings.json which will be used to connect to the database</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Database.HelpText" xml:space="preserve">
|
<data name="Database.HelpText" xml:space="preserve">
|
||||||
<value>The type of database</value>
|
<value>The type of database</value>
|
||||||
|
@ -187,7 +187,7 @@
|
|||||||
<value>Select the database for the site</value>
|
<value>Select the database for the site</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TenantName.HelpText" xml:space="preserve">
|
<data name="TenantName.HelpText" xml:space="preserve">
|
||||||
<value>Enter the name for the database</value>
|
<value>Enter the name for the database. Note that this will be the tenant name which is used within the framework to identify the database.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="DatabaseType.HelpText" xml:space="preserve">
|
<data name="DatabaseType.HelpText" xml:space="preserve">
|
||||||
<value>Select the database type</value>
|
<value>Select the database type</value>
|
||||||
|
@ -150,4 +150,7 @@
|
|||||||
<data name="Localhost.Text" xml:space="preserve">
|
<data name="Localhost.Text" xml:space="preserve">
|
||||||
<value>You Cannot Perform A System Update In A Development Environment</value>
|
<value>You Cannot Perform A System Update In A Development Environment</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Disclaimer.Text" xml:space="preserve">
|
||||||
|
<value>Please Note That The System Update Capability Is A Simplified Upgrade Process Intended For Small To Medium Sized Installations. For Larger Enterprise Installations You Will Want To Use A Manual Upgrade Process. Also Note That The System Update Capability Is Not Recommended When Using Microsoft Azure Due To The Limitations Of That Environment. </value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
@ -480,4 +480,19 @@
|
|||||||
<data name="NameClaimType.Text" xml:space="preserve">
|
<data name="NameClaimType.Text" xml:space="preserve">
|
||||||
<value>Name Claim:</value>
|
<value>Name Claim:</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Provider.HelpText" xml:space="preserve">
|
||||||
|
<value>Select the external login provider</value>
|
||||||
|
</data>
|
||||||
|
<data name="Provider.Text" xml:space="preserve">
|
||||||
|
<value>Provider:</value>
|
||||||
|
</data>
|
||||||
|
<data name="Info" xml:space="preserve">
|
||||||
|
<value>Info</value>
|
||||||
|
</data>
|
||||||
|
<data name="OAuth2" xml:space="preserve">
|
||||||
|
<value>OAuth 2.0</value>
|
||||||
|
</data>
|
||||||
|
<data name="OIDC" xml:space="preserve">
|
||||||
|
<value>OpenID Connect (OIDC)</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
@ -0,0 +1,17 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Oqtane.Services
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Service to set localization cookie
|
||||||
|
/// </summary>
|
||||||
|
public interface ILocalizationCookieService
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Set the localization cookie
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="culture"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task SetLocalizationCookieAsync(string culture);
|
||||||
|
}
|
||||||
|
}
|
@ -113,6 +113,15 @@ namespace Oqtane.Services
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<User> VerifyTwoFactorAsync(User user, string token);
|
Task<User> VerifyTwoFactorAsync(User user, string token);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Validate identity user info.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="username"></param>
|
||||||
|
/// <param name="email"></param>
|
||||||
|
/// <param name="password"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<UserValidateResult> ValidateUserAsync(string username, string email, string password);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Validate a users password against the password policy
|
/// Validate a users password against the password policy
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
18
Oqtane.Client/Services/LocalizationCookieService.cs
Normal file
18
Oqtane.Client/Services/LocalizationCookieService.cs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Oqtane.Documentation;
|
||||||
|
using Oqtane.Shared;
|
||||||
|
|
||||||
|
namespace Oqtane.Services
|
||||||
|
{
|
||||||
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
|
public class LocalizationCookieService : ServiceBase, ILocalizationCookieService
|
||||||
|
{
|
||||||
|
public LocalizationCookieService(HttpClient http, SiteState siteState) : base(http, siteState) { }
|
||||||
|
|
||||||
|
public Task SetLocalizationCookieAsync(string culture)
|
||||||
|
{
|
||||||
|
return Task.CompletedTask; // only used in server side rendering
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -4,7 +4,6 @@ using System.Net.Http;
|
|||||||
using System.Net.Http.Json;
|
using System.Net.Http.Json;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.Net.Http.Headers;
|
|
||||||
using Oqtane.Shared;
|
using Oqtane.Shared;
|
||||||
|
|
||||||
namespace Oqtane.Services
|
namespace Oqtane.Services
|
||||||
@ -28,9 +27,9 @@ namespace Oqtane.Services
|
|||||||
private HttpClient GetHttpClient(string AuthorizationToken)
|
private HttpClient GetHttpClient(string AuthorizationToken)
|
||||||
{
|
{
|
||||||
var httpClient = _httpClientFactory.CreateClient("Remote");
|
var httpClient = _httpClientFactory.CreateClient("Remote");
|
||||||
if (!httpClient.DefaultRequestHeaders.Contains(HeaderNames.Authorization) && !string.IsNullOrEmpty(AuthorizationToken))
|
if (!httpClient.DefaultRequestHeaders.Contains("Authorization") && !string.IsNullOrEmpty(AuthorizationToken))
|
||||||
{
|
{
|
||||||
httpClient.DefaultRequestHeaders.Add(HeaderNames.Authorization, "Bearer " + AuthorizationToken);
|
httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + AuthorizationToken);
|
||||||
}
|
}
|
||||||
return httpClient;
|
return httpClient;
|
||||||
}
|
}
|
||||||
|
@ -89,6 +89,11 @@ namespace Oqtane.Services
|
|||||||
return await PostJsonAsync<User>($"{Apiurl}/twofactor?token={token}", user);
|
return await PostJsonAsync<User>($"{Apiurl}/twofactor?token={token}", user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<UserValidateResult> ValidateUserAsync(string username, string email, string password)
|
||||||
|
{
|
||||||
|
return await GetJsonAsync<UserValidateResult>($"{Apiurl}/validateuser?username={WebUtility.UrlEncode(username)}&email={WebUtility.UrlEncode(email)}&password={WebUtility.UrlEncode(password)}");
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<bool> ValidatePasswordAsync(string password)
|
public async Task<bool> ValidatePasswordAsync(string password)
|
||||||
{
|
{
|
||||||
return await GetJsonAsync<bool>($"{Apiurl}/validate/{WebUtility.UrlEncode(password)}");
|
return await GetJsonAsync<bool>($"{Apiurl}/validate/{WebUtility.UrlEncode(password)}");
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
@using System.Globalization
|
@using System.Globalization
|
||||||
@using Microsoft.AspNetCore.Localization
|
|
||||||
@using Microsoft.AspNetCore.Http
|
|
||||||
@using Oqtane.Models
|
@using Oqtane.Models
|
||||||
@namespace Oqtane.Themes.Controls
|
@namespace Oqtane.Themes.Controls
|
||||||
@inherits ThemeControlBase
|
@inherits ThemeControlBase
|
||||||
@inject ILanguageService LanguageService
|
@inject ILanguageService LanguageService
|
||||||
|
@inject ILocalizationCookieService LocalizationCookieService
|
||||||
@inject NavigationManager NavigationManager
|
@inject NavigationManager NavigationManager
|
||||||
|
|
||||||
@if (_supportedCultures?.Count() > 1)
|
@if (_supportedCultures?.Count() > 1)
|
||||||
@ -22,7 +21,7 @@
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
<a class="dropdown-item @(CultureInfo.CurrentUICulture.Name == culture.Name ? "active" : String.Empty)" href="@NavigateUrl(PageState.Page.Path, "culture=" + culture.Name)">@culture.DisplayName</a>
|
<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>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
@ -38,25 +37,20 @@
|
|||||||
[Parameter]
|
[Parameter]
|
||||||
public string ButtonClass { get; set; } = "btn-outline-secondary";
|
public string ButtonClass { get; set; } = "btn-outline-secondary";
|
||||||
|
|
||||||
[CascadingParameter]
|
protected override async Task OnParametersSetAsync()
|
||||||
HttpContext HttpContext { get; set; }
|
|
||||||
|
|
||||||
protected override void OnParametersSet()
|
|
||||||
{
|
{
|
||||||
MenuAlignment = DropdownAlignment.ToLower() == "right" ? "dropdown-menu-end" : string.Empty;
|
MenuAlignment = DropdownAlignment.ToLower() == "right" ? "dropdown-menu-end" : string.Empty;
|
||||||
|
|
||||||
var languages = PageState.Languages;
|
_supportedCultures = PageState.Languages.Select(l => new Culture { Name = l.Code, DisplayName = l.Name });
|
||||||
_supportedCultures = languages.Select(l => new Culture { Name = l.Code, DisplayName = l.Name });
|
|
||||||
|
|
||||||
if (PageState.QueryString.ContainsKey("culture"))
|
if (PageState.QueryString.ContainsKey("culture"))
|
||||||
{
|
{
|
||||||
var culture = PageState.QueryString["culture"];
|
var culture = PageState.QueryString["culture"];
|
||||||
if (_supportedCultures.Any(item => item.Name == culture))
|
if (_supportedCultures.Any(item => item.Name == culture))
|
||||||
{
|
{
|
||||||
var localizationCookieValue = CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture));
|
await LocalizationCookieService.SetLocalizationCookieAsync(culture);
|
||||||
HttpContext.Response.Cookies.Append(CookieRequestCultureProvider.DefaultCookieName, localizationCookieValue, new CookieOptions { Path = "/", Expires = DateTimeOffset.UtcNow.AddYears(365) });
|
|
||||||
}
|
}
|
||||||
NavigationManager.NavigateTo(NavigationManager.Uri.Replace($"?culture={culture}", ""), forceLoad: true);
|
NavigationManager.NavigateTo(NavigationManager.Uri.Replace($"?culture={culture}", ""));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,8 +60,8 @@
|
|||||||
{
|
{
|
||||||
var localizationCookieValue = CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture));
|
var localizationCookieValue = CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture));
|
||||||
var interop = new Interop(JSRuntime);
|
var interop = new Interop(JSRuntime);
|
||||||
await interop.SetCookie(CookieRequestCultureProvider.DefaultCookieName, localizationCookieValue, 360);
|
await interop.SetCookie(CookieRequestCultureProvider.DefaultCookieName, localizationCookieValue, 360, true, "Lax");
|
||||||
NavigationManager.NavigateTo(NavigationManager.Uri, forceLoad: true);
|
NavigationManager.NavigateTo(NavigationManager.Uri, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
placeholder="@Localizer["SearchPlaceHolder"]"
|
placeholder="@Localizer["SearchPlaceHolder"]"
|
||||||
aria-label="Search" />
|
aria-label="Search" />
|
||||||
}
|
}
|
||||||
<button type="submit" class="btn btn-search">
|
<button type="submit" class="btn btn-search" aria-label="Search Button">
|
||||||
<span class="oi oi-magnifying-glass align-middle"></span>
|
<span class="oi oi-magnifying-glass align-middle"></span>
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
@ -16,13 +16,18 @@ namespace Oqtane.UI
|
|||||||
_jsRuntime = jsRuntime;
|
_jsRuntime = jsRuntime;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task SetCookie(string name, string value, int days)
|
public async Task SetCookie(string name, string value, int days)
|
||||||
|
{
|
||||||
|
await SetCookie(name, value, days, true, "Lax");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task SetCookie(string name, string value, int days, bool secure, string sameSite)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_jsRuntime.InvokeVoidAsync(
|
_jsRuntime.InvokeVoidAsync(
|
||||||
"Oqtane.Interop.setCookie",
|
"Oqtane.Interop.setCookie",
|
||||||
name, value, days);
|
name, value, days, secure, sameSite);
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
@namespace Oqtane.UI
|
@namespace Oqtane.UI
|
||||||
@using Microsoft.AspNetCore.Http
|
|
||||||
@inject IInstallationService InstallationService
|
@inject IInstallationService InstallationService
|
||||||
@inject IJSRuntime JSRuntime
|
|
||||||
@inject SiteState SiteState
|
@inject SiteState SiteState
|
||||||
|
|
||||||
@if (_initialized)
|
@if (_initialized)
|
||||||
@ -48,9 +46,6 @@
|
|||||||
[Parameter]
|
[Parameter]
|
||||||
public string Platform { get; set; } = "";
|
public string Platform { get; set; } = "";
|
||||||
|
|
||||||
[CascadingParameter]
|
|
||||||
HttpContext HttpContext { get; set; }
|
|
||||||
|
|
||||||
private bool _initialized = false;
|
private bool _initialized = false;
|
||||||
private bool _installed = false;
|
private bool _installed = false;
|
||||||
private string _display = "display: none;";
|
private string _display = "display: none;";
|
||||||
@ -62,7 +57,7 @@
|
|||||||
SiteState.AntiForgeryToken = AntiForgeryToken;
|
SiteState.AntiForgeryToken = AntiForgeryToken;
|
||||||
SiteState.AuthorizationToken = AuthorizationToken;
|
SiteState.AuthorizationToken = AuthorizationToken;
|
||||||
SiteState.Platform = Platform;
|
SiteState.Platform = Platform;
|
||||||
SiteState.IsPrerendering = (HttpContext != null) ? true : false;
|
SiteState.IsPrerendering = !RendererInfo.IsInteractive;
|
||||||
|
|
||||||
if (Runtime == Runtimes.Hybrid)
|
if (Runtime == Runtimes.Hybrid)
|
||||||
{
|
{
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
@using System.Diagnostics.CodeAnalysis
|
@using System.Diagnostics.CodeAnalysis
|
||||||
@using System.Net
|
@using System.Net
|
||||||
@using Microsoft.AspNetCore.Http
|
|
||||||
@using System.Globalization
|
@using System.Globalization
|
||||||
@using System.Security.Claims
|
@using System.Security.Claims
|
||||||
@namespace Oqtane.UI
|
@namespace Oqtane.UI
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
<Version>5.2.3</Version>
|
<Version>6.0.0</Version>
|
||||||
<Product>Oqtane</Product>
|
<Product>Oqtane</Product>
|
||||||
<Authors>Shaun Walker</Authors>
|
<Authors>Shaun Walker</Authors>
|
||||||
<Company>.NET Foundation</Company>
|
<Company>.NET Foundation</Company>
|
||||||
@ -10,7 +10,7 @@
|
|||||||
<Copyright>.NET Foundation</Copyright>
|
<Copyright>.NET Foundation</Copyright>
|
||||||
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
||||||
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
||||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.2.3</PackageReleaseNotes>
|
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v6.0.0</PackageReleaseNotes>
|
||||||
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
||||||
<RepositoryType>Git</RepositoryType>
|
<RepositoryType>Git</RepositoryType>
|
||||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||||
@ -33,8 +33,8 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="MySql.EntityFrameworkCore" Version="8.0.5" />
|
<PackageReference Include="MySql.EntityFrameworkCore" Version="9.0.0-preview" />
|
||||||
<PackageReference Include="MySql.Data" Version="9.0.0" />
|
<PackageReference Include="MySql.Data" Version="9.1.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@ -42,7 +42,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<MySQLFiles Include="$(OutputPath)Oqtane.Database.MySQL.dll;$(OutputPath)Oqtane.Database.MySQL.pdb;$(OutputPath)MySql.EntityFrameworkCore.dll;$(OutputPath)MySql.Data.dll" DestinationPath="..\Oqtane.Server\bin\$(Configuration)\net8.0\%(Filename)%(Extension)" />
|
<MySQLFiles Include="$(OutputPath)Oqtane.Database.MySQL.dll;$(OutputPath)Oqtane.Database.MySQL.pdb;$(OutputPath)MySql.EntityFrameworkCore.dll;$(OutputPath)MySql.Data.dll" DestinationPath="..\Oqtane.Server\bin\$(Configuration)\net9.0\%(Filename)%(Extension)" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<Target Name="PublishProvider" AfterTargets="PostBuildEvent" Inputs="@(MySQLFiles)" Outputs="@(MySQLFiles->'%(DestinationPath)')">
|
<Target Name="PublishProvider" AfterTargets="PostBuildEvent" Inputs="@(MySQLFiles)" Outputs="@(MySQLFiles->'%(DestinationPath)')">
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
<Version>5.2.3</Version>
|
<Version>6.0.0</Version>
|
||||||
<Product>Oqtane</Product>
|
<Product>Oqtane</Product>
|
||||||
<Authors>Shaun Walker</Authors>
|
<Authors>Shaun Walker</Authors>
|
||||||
<Company>.NET Foundation</Company>
|
<Company>.NET Foundation</Company>
|
||||||
@ -10,7 +10,7 @@
|
|||||||
<Copyright>.NET Foundation</Copyright>
|
<Copyright>.NET Foundation</Copyright>
|
||||||
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
||||||
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
||||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.2.3</PackageReleaseNotes>
|
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v6.0.0</PackageReleaseNotes>
|
||||||
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
||||||
<RepositoryType>Git</RepositoryType>
|
<RepositoryType>Git</RepositoryType>
|
||||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||||
@ -25,17 +25,18 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
<NoWarn>1701;1702;EF1001;AD0001</NoWarn>
|
<NoWarn>1701;1702;EF1001;AD0001;NU1608</NoWarn>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||||
<NoWarn>1701;1702;EF1001;AD0001</NoWarn>
|
<NoWarn>1701;1702;EF1001;AD0001;NU1608</NoWarn>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="EFCore.NamingConventions" Version="8.0.3" />
|
<PackageReference Include="EFCore.NamingConventions" Version="8.0.3" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="8.0.8" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.0" />
|
||||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.4" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="9.0.0" />
|
||||||
|
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.0-rc.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@ -43,7 +44,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PostgreSQLFiles Include="$(OutputPath)Oqtane.Database.PostgreSQL.dll;$(OutputPath)Oqtane.Database.PostgreSQL.pdb;$(OutputPath)EFCore.NamingConventions.dll;$(OutputPath)Npgsql.EntityFrameworkCore.PostgreSQL.dll;$(OutputPath)Npgsql.dll" DestinationPath="..\Oqtane.Server\bin\$(Configuration)\net8.0\%(Filename)%(Extension)" />
|
<PostgreSQLFiles Include="$(OutputPath)Oqtane.Database.PostgreSQL.dll;$(OutputPath)Oqtane.Database.PostgreSQL.pdb;$(OutputPath)EFCore.NamingConventions.dll;$(OutputPath)Npgsql.EntityFrameworkCore.PostgreSQL.dll;$(OutputPath)Npgsql.dll" DestinationPath="..\Oqtane.Server\bin\$(Configuration)\net9.0\%(Filename)%(Extension)" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<Target Name="PublishProvider" AfterTargets="PostBuildEvent" Inputs="@(PostgreSQLFiles)" Outputs="@(PostgreSQLFiles->'%(DestinationPath)')">
|
<Target Name="PublishProvider" AfterTargets="PostBuildEvent" Inputs="@(PostgreSQLFiles)" Outputs="@(PostgreSQLFiles->'%(DestinationPath)')">
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
<Version>5.2.3</Version>
|
<Version>6.0.0</Version>
|
||||||
<Product>Oqtane</Product>
|
<Product>Oqtane</Product>
|
||||||
<Authors>Shaun Walker</Authors>
|
<Authors>Shaun Walker</Authors>
|
||||||
<Company>.NET Foundation</Company>
|
<Company>.NET Foundation</Company>
|
||||||
@ -10,7 +10,7 @@
|
|||||||
<Copyright>.NET Foundation</Copyright>
|
<Copyright>.NET Foundation</Copyright>
|
||||||
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
||||||
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
||||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.2.3</PackageReleaseNotes>
|
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v6.0.0</PackageReleaseNotes>
|
||||||
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
||||||
<RepositoryType>Git</RepositoryType>
|
<RepositoryType>Git</RepositoryType>
|
||||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||||
@ -33,7 +33,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.8" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@ -41,7 +41,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<SqlServerFiles Include="$(OutputPath)Oqtane.Database.SqlServer.dll;$(OutputPath)Oqtane.Database.SqlServer.pdb;$(OutputPath)Microsoft.EntityFrameworkCore.SqlServer.dll" DestinationPath="..\Oqtane.Server\bin\$(Configuration)\net8.0\%(Filename)%(Extension)" />
|
<SqlServerFiles Include="$(OutputPath)Oqtane.Database.SqlServer.dll;$(OutputPath)Oqtane.Database.SqlServer.pdb;$(OutputPath)Microsoft.EntityFrameworkCore.SqlServer.dll" DestinationPath="..\Oqtane.Server\bin\$(Configuration)\net9.0\%(Filename)%(Extension)" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<Target Name="PublishProvider" AfterTargets="PostBuildEvent" Inputs="@(SqlServerFiles)" Outputs="@(SqlServerFiles->'%(DestinationPath)')">
|
<Target Name="PublishProvider" AfterTargets="PostBuildEvent" Inputs="@(SqlServerFiles)" Outputs="@(SqlServerFiles->'%(DestinationPath)')">
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
<Version>5.2.3</Version>
|
<Version>6.0.0</Version>
|
||||||
<Product>Oqtane</Product>
|
<Product>Oqtane</Product>
|
||||||
<Authors>Shaun Walker</Authors>
|
<Authors>Shaun Walker</Authors>
|
||||||
<Company>.NET Foundation</Company>
|
<Company>.NET Foundation</Company>
|
||||||
@ -10,7 +10,7 @@
|
|||||||
<Copyright>.NET Foundation</Copyright>
|
<Copyright>.NET Foundation</Copyright>
|
||||||
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
||||||
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
||||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.2.3</PackageReleaseNotes>
|
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v6.0.0</PackageReleaseNotes>
|
||||||
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
||||||
<RepositoryType>Git</RepositoryType>
|
<RepositoryType>Git</RepositoryType>
|
||||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||||
@ -33,7 +33,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.8" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="9.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@ -41,7 +41,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<SqliteFiles Include="$(OutputPath)Oqtane.Database.Sqlite.dll;$(OutputPath)Oqtane.Database.Sqlite.pdb;$(OutputPath)Microsoft.EntityFrameworkCore.Sqlite.dll" DestinationPath="..\Oqtane.Server\bin\$(Configuration)\net8.0\%(Filename)%(Extension)" />
|
<SqliteFiles Include="$(OutputPath)Oqtane.Database.Sqlite.dll;$(OutputPath)Oqtane.Database.Sqlite.pdb;$(OutputPath)Microsoft.EntityFrameworkCore.Sqlite.dll" DestinationPath="..\Oqtane.Server\bin\$(Configuration)\net9.0\%(Filename)%(Extension)" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<Target Name="PublishProvider" AfterTargets="PostBuildEvent" Inputs="@(SqliteFiles)" Outputs="@(SqliteFiles->'%(DestinationPath)')">
|
<Target Name="PublishProvider" AfterTargets="PostBuildEvent" Inputs="@(SqliteFiles)" Outputs="@(SqliteFiles->'%(DestinationPath)')">
|
||||||
|
@ -5,7 +5,10 @@ public partial class App : Application
|
|||||||
public App()
|
public App()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
MainPage = new MainPage();
|
protected override Window CreateWindow(IActivationState activationState)
|
||||||
|
{
|
||||||
|
return new Window(new MainPage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk.Razor">
|
<Project Sdk="Microsoft.NET.Sdk.Razor">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net8.0-windows10.0.19041.0</TargetFrameworks>
|
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net9.0-windows10.0.19041.0</TargetFrameworks>
|
||||||
<!-- Uncomment to also build the tizen app. You will need to install tizen by following this: https://github.com/Samsung/Tizen.NET -->
|
<!-- Uncomment to also build the tizen app. You will need to install tizen by following this: https://github.com/Samsung/Tizen.NET -->
|
||||||
<!-- <TargetFrameworks>net8.0-android;net8.0-ios;net8.0-maccatalyst</TargetFrameworks> -->
|
<!-- <TargetFrameworks>net9.0-android;net9.0-ios;net9.0-maccatalyst</TargetFrameworks> -->
|
||||||
<!-- <TargetFrameworks>$(TargetFrameworks);net8.0-tizen</TargetFrameworks> -->
|
<!-- <TargetFrameworks>$(TargetFrameworks);net9.0-tizen</TargetFrameworks> -->
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<Version>5.2.3</Version>
|
<Version>6.0.0</Version>
|
||||||
<Product>Oqtane</Product>
|
<Product>Oqtane</Product>
|
||||||
<Authors>Shaun Walker</Authors>
|
<Authors>Shaun Walker</Authors>
|
||||||
<Company>.NET Foundation</Company>
|
<Company>.NET Foundation</Company>
|
||||||
@ -14,7 +14,7 @@
|
|||||||
<Copyright>.NET Foundation</Copyright>
|
<Copyright>.NET Foundation</Copyright>
|
||||||
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
||||||
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
||||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.2.3</PackageReleaseNotes>
|
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v6.0.0</PackageReleaseNotes>
|
||||||
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
||||||
<RepositoryType>Git</RepositoryType>
|
<RepositoryType>Git</RepositoryType>
|
||||||
<RootNamespace>Oqtane.Maui</RootNamespace>
|
<RootNamespace>Oqtane.Maui</RootNamespace>
|
||||||
@ -28,14 +28,16 @@
|
|||||||
|
|
||||||
<!-- App Identifier -->
|
<!-- App Identifier -->
|
||||||
<ApplicationId>com.oqtane.maui</ApplicationId>
|
<ApplicationId>com.oqtane.maui</ApplicationId>
|
||||||
<ApplicationIdGuid>0E29FC31-1B83-48ED-B6E0-9F3C67B775D4</ApplicationIdGuid>
|
|
||||||
|
|
||||||
<!-- Versions -->
|
<!-- Versions -->
|
||||||
<ApplicationDisplayVersion>5.2.3</ApplicationDisplayVersion>
|
<ApplicationDisplayVersion>6.0.0</ApplicationDisplayVersion>
|
||||||
<ApplicationVersion>1</ApplicationVersion>
|
<ApplicationVersion>1</ApplicationVersion>
|
||||||
|
|
||||||
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">14.2</SupportedOSPlatformVersion>
|
<!-- To develop, package, and publish an app to the Microsoft Store, see: https://aka.ms/MauiTemplateUnpackaged -->
|
||||||
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">14.0</SupportedOSPlatformVersion>
|
<WindowsPackageType>None</WindowsPackageType>
|
||||||
|
|
||||||
|
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">15.0</SupportedOSPlatformVersion>
|
||||||
|
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">15.0</SupportedOSPlatformVersion>
|
||||||
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">24.0</SupportedOSPlatformVersion>
|
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">24.0</SupportedOSPlatformVersion>
|
||||||
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</SupportedOSPlatformVersion>
|
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</SupportedOSPlatformVersion>
|
||||||
<TargetPlatformMinVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</TargetPlatformMinVersion>
|
<TargetPlatformMinVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</TargetPlatformMinVersion>
|
||||||
@ -65,23 +67,22 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Components.Authorization" Version="8.0.8" />
|
<PackageReference Include="Microsoft.AspNetCore.Components.Authorization" Version="9.0.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="8.0.8" />
|
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="9.0.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Localization" Version="2.2.0" />
|
<PackageReference Include="Microsoft.Extensions.Http" Version="9.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Http" Version="8.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Localization" Version="9.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="8.0.8" />
|
<PackageReference Include="System.Net.Http.Json" Version="9.0.0" />
|
||||||
<PackageReference Include="System.Net.Http.Json" Version="8.0.0" />
|
<PackageReference Include="Microsoft.Maui.Controls" Version="9.0.0" />
|
||||||
<PackageReference Include="Microsoft.Maui.Controls" Version="8.0.80" />
|
<PackageReference Include="Microsoft.Maui.Controls.Compatibility" Version="9.0.0" />
|
||||||
<PackageReference Include="Microsoft.Maui.Controls.Compatibility" Version="8.0.80" />
|
<PackageReference Include="Microsoft.AspNetCore.Components.WebView.Maui" Version="9.0.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebView.Maui" Version="8.0.80" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="Oqtane.Client">
|
<Reference Include="Oqtane.Client">
|
||||||
<HintPath>..\Oqtane.Server\bin\Debug\net8.0\Oqtane.Client.dll</HintPath>
|
<HintPath>..\Oqtane.Server\bin\Debug\net9.0\Oqtane.Client.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Oqtane.Shared">
|
<Reference Include="Oqtane.Shared">
|
||||||
<HintPath>..\Oqtane.Server\bin\Debug\net8.0\Oqtane.Shared.dll</HintPath>
|
<HintPath>..\Oqtane.Server\bin\Debug\net9.0\Oqtane.Shared.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"profiles": {
|
"profiles": {
|
||||||
"Windows Machine": {
|
"Windows Machine": {
|
||||||
"commandName": "MsixPackage",
|
"commandName": "Project",
|
||||||
"nativeDebugging": false
|
"nativeDebugging": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,18 @@
|
|||||||
var Oqtane = Oqtane || {};
|
var Oqtane = Oqtane || {};
|
||||||
|
|
||||||
Oqtane.Interop = {
|
Oqtane.Interop = {
|
||||||
setCookie: function (name, value, days) {
|
setCookie: function (name, value, days, secure, sameSite) {
|
||||||
var d = new Date();
|
var d = new Date();
|
||||||
d.setTime(d.getTime() + (days * 24 * 60 * 60 * 1000));
|
d.setTime(d.getTime() + (days * 24 * 60 * 60 * 1000));
|
||||||
var expires = "expires=" + d.toUTCString();
|
var expires = "expires=" + d.toUTCString();
|
||||||
document.cookie = name + "=" + value + ";" + expires + ";path=/";
|
var cookieString = name + "=" + value + ";" + expires + ";path=/";
|
||||||
|
if (secure) {
|
||||||
|
cookieString += "; secure";
|
||||||
|
}
|
||||||
|
if (sameSite === "Lax" || sameSite === "Strict" || sameSite === "None") {
|
||||||
|
cookieString += "; SameSite=" + sameSite;
|
||||||
|
}
|
||||||
|
document.cookie = cookieString;
|
||||||
},
|
},
|
||||||
getCookie: function (name) {
|
getCookie: function (name) {
|
||||||
name = name + "=";
|
name = name + "=";
|
||||||
@ -410,11 +417,20 @@ Oqtane.Interop = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
scrollTo: function (top, left, behavior) {
|
scrollTo: function (top, left, behavior) {
|
||||||
|
const modal = document.querySelector('.modal');
|
||||||
|
if (modal) {
|
||||||
|
modal.scrollTo({
|
||||||
|
top: top,
|
||||||
|
left: left,
|
||||||
|
behavior: behavior
|
||||||
|
});
|
||||||
|
} else {
|
||||||
window.scrollTo({
|
window.scrollTo({
|
||||||
top: top,
|
top: top,
|
||||||
left: left,
|
left: left,
|
||||||
behavior: behavior
|
behavior: behavior
|
||||||
});
|
});
|
||||||
|
}
|
||||||
},
|
},
|
||||||
scrollToId: function (id) {
|
scrollToId: function (id) {
|
||||||
var element = document.getElementById(id);
|
var element = document.getElementById(id);
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<package>
|
<package>
|
||||||
<metadata>
|
<metadata>
|
||||||
<id>Oqtane.Client</id>
|
<id>Oqtane.Client</id>
|
||||||
<version>5.2.3</version>
|
<version>6.0.0</version>
|
||||||
<authors>Shaun Walker</authors>
|
<authors>Shaun Walker</authors>
|
||||||
<owners>.NET Foundation</owners>
|
<owners>.NET Foundation</owners>
|
||||||
<title>Oqtane Framework</title>
|
<title>Oqtane Framework</title>
|
||||||
@ -12,14 +12,14 @@
|
|||||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||||
<license type="expression">MIT</license>
|
<license type="expression">MIT</license>
|
||||||
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
||||||
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.2.3</releaseNotes>
|
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v6.0.0</releaseNotes>
|
||||||
<readme>readme.md</readme>
|
<readme>readme.md</readme>
|
||||||
<icon>icon.png</icon>
|
<icon>icon.png</icon>
|
||||||
<tags>oqtane</tags>
|
<tags>oqtane</tags>
|
||||||
</metadata>
|
</metadata>
|
||||||
<files>
|
<files>
|
||||||
<file src="..\Oqtane.Client\bin\Release\net8.0\Oqtane.Client.dll" target="lib\net8.0" />
|
<file src="..\Oqtane.Client\bin\Release\net8.0\Oqtane.Client.dll" target="lib\net9.0" />
|
||||||
<file src="..\Oqtane.Client\bin\Release\net8.0\Oqtane.Client.pdb" target="lib\net8.0" />
|
<file src="..\Oqtane.Client\bin\Release\net8.0\Oqtane.Client.pdb" target="lib\net9.0" />
|
||||||
<file src="icon.png" target="" />
|
<file src="icon.png" target="" />
|
||||||
<file src="readme.md" target="" />
|
<file src="readme.md" target="" />
|
||||||
</files>
|
</files>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<package>
|
<package>
|
||||||
<metadata>
|
<metadata>
|
||||||
<id>Oqtane.Framework</id>
|
<id>Oqtane.Framework</id>
|
||||||
<version>5.2.3</version>
|
<version>6.0.0</version>
|
||||||
<authors>Shaun Walker</authors>
|
<authors>Shaun Walker</authors>
|
||||||
<owners>.NET Foundation</owners>
|
<owners>.NET Foundation</owners>
|
||||||
<title>Oqtane Framework</title>
|
<title>Oqtane Framework</title>
|
||||||
@ -11,8 +11,8 @@
|
|||||||
<copyright>.NET Foundation</copyright>
|
<copyright>.NET Foundation</copyright>
|
||||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||||
<license type="expression">MIT</license>
|
<license type="expression">MIT</license>
|
||||||
<projectUrl>https://github.com/oqtane/oqtane.framework/releases/download/v5.2.3/Oqtane.Framework.5.2.3.Upgrade.zip</projectUrl>
|
<projectUrl>https://github.com/oqtane/oqtane.framework/releases/download/v6.0.0/Oqtane.Framework.6.0.0.Upgrade.zip</projectUrl>
|
||||||
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.2.3</releaseNotes>
|
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v6.0.0</releaseNotes>
|
||||||
<readme>readme.md</readme>
|
<readme>readme.md</readme>
|
||||||
<icon>icon.png</icon>
|
<icon>icon.png</icon>
|
||||||
<tags>oqtane framework</tags>
|
<tags>oqtane framework</tags>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<package>
|
<package>
|
||||||
<metadata>
|
<metadata>
|
||||||
<id>Oqtane.Server</id>
|
<id>Oqtane.Server</id>
|
||||||
<version>5.2.3</version>
|
<version>6.0.0</version>
|
||||||
<authors>Shaun Walker</authors>
|
<authors>Shaun Walker</authors>
|
||||||
<owners>.NET Foundation</owners>
|
<owners>.NET Foundation</owners>
|
||||||
<title>Oqtane Framework</title>
|
<title>Oqtane Framework</title>
|
||||||
@ -12,14 +12,14 @@
|
|||||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||||
<license type="expression">MIT</license>
|
<license type="expression">MIT</license>
|
||||||
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
||||||
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.2.3</releaseNotes>
|
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v6.0.0</releaseNotes>
|
||||||
<readme>readme.md</readme>
|
<readme>readme.md</readme>
|
||||||
<icon>icon.png</icon>
|
<icon>icon.png</icon>
|
||||||
<tags>oqtane</tags>
|
<tags>oqtane</tags>
|
||||||
</metadata>
|
</metadata>
|
||||||
<files>
|
<files>
|
||||||
<file src="..\Oqtane.Server\bin\Release\net8.0\Oqtane.Server.dll" target="lib\net8.0" />
|
<file src="..\Oqtane.Server\bin\Release\net8.0\Oqtane.Server.dll" target="lib\net9.0" />
|
||||||
<file src="..\Oqtane.Server\bin\Release\net8.0\Oqtane.Server.pdb" target="lib\net8.0" />
|
<file src="..\Oqtane.Server\bin\Release\net8.0\Oqtane.Server.pdb" target="lib\net9.0" />
|
||||||
<file src="icon.png" target="" />
|
<file src="icon.png" target="" />
|
||||||
<file src="readme.md" target="" />
|
<file src="readme.md" target="" />
|
||||||
</files>
|
</files>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<package>
|
<package>
|
||||||
<metadata>
|
<metadata>
|
||||||
<id>Oqtane.Shared</id>
|
<id>Oqtane.Shared</id>
|
||||||
<version>5.2.3</version>
|
<version>6.0.0</version>
|
||||||
<authors>Shaun Walker</authors>
|
<authors>Shaun Walker</authors>
|
||||||
<owners>.NET Foundation</owners>
|
<owners>.NET Foundation</owners>
|
||||||
<title>Oqtane Framework</title>
|
<title>Oqtane Framework</title>
|
||||||
@ -12,14 +12,14 @@
|
|||||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||||
<license type="expression">MIT</license>
|
<license type="expression">MIT</license>
|
||||||
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
||||||
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.2.3</releaseNotes>
|
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v6.0.0</releaseNotes>
|
||||||
<readme>readme.md</readme>
|
<readme>readme.md</readme>
|
||||||
<icon>icon.png</icon>
|
<icon>icon.png</icon>
|
||||||
<tags>oqtane</tags>
|
<tags>oqtane</tags>
|
||||||
</metadata>
|
</metadata>
|
||||||
<files>
|
<files>
|
||||||
<file src="..\Oqtane.Shared\bin\Release\net8.0\Oqtane.Shared.dll" target="lib\net8.0" />
|
<file src="..\Oqtane.Shared\bin\Release\net8.0\Oqtane.Shared.dll" target="lib\net9.0" />
|
||||||
<file src="..\Oqtane.Shared\bin\Release\net8.0\Oqtane.Shared.pdb" target="lib\net8.0" />
|
<file src="..\Oqtane.Shared\bin\Release\net8.0\Oqtane.Shared.pdb" target="lib\net9.0" />
|
||||||
<file src="icon.png" target="" />
|
<file src="icon.png" target="" />
|
||||||
<file src="readme.md" target="" />
|
<file src="readme.md" target="" />
|
||||||
</files>
|
</files>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<package>
|
<package>
|
||||||
<metadata>
|
<metadata>
|
||||||
<id>Oqtane.Updater</id>
|
<id>Oqtane.Updater</id>
|
||||||
<version>5.2.3</version>
|
<version>6.0.0</version>
|
||||||
<authors>Shaun Walker</authors>
|
<authors>Shaun Walker</authors>
|
||||||
<owners>.NET Foundation</owners>
|
<owners>.NET Foundation</owners>
|
||||||
<title>Oqtane Framework</title>
|
<title>Oqtane Framework</title>
|
||||||
@ -12,13 +12,13 @@
|
|||||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||||
<license type="expression">MIT</license>
|
<license type="expression">MIT</license>
|
||||||
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
||||||
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.2.3</releaseNotes>
|
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v6.0.0</releaseNotes>
|
||||||
<readme>readme.md</readme>
|
<readme>readme.md</readme>
|
||||||
<icon>icon.png</icon>
|
<icon>icon.png</icon>
|
||||||
<tags>oqtane</tags>
|
<tags>oqtane</tags>
|
||||||
</metadata>
|
</metadata>
|
||||||
<files>
|
<files>
|
||||||
<file src="..\Oqtane.Updater\bin\Release\net8.0\publish\*.*" target="lib\net8.0" />
|
<file src="..\Oqtane.Updater\bin\Release\net8.0\publish\*.*" target="lib\net9.0" />
|
||||||
<file src="icon.png" target="" />
|
<file src="icon.png" target="" />
|
||||||
<file src="readme.md" target="" />
|
<file src="readme.md" target="" />
|
||||||
</files>
|
</files>
|
||||||
|
@ -1 +1 @@
|
|||||||
Compress-Archive -Path "..\Oqtane.Server\bin\Release\net8.0\publish\*" -DestinationPath "Oqtane.Framework.5.2.3.Install.zip" -Force
|
Compress-Archive -Path "..\Oqtane.Server\bin\Release\net9.0\publish\*" -DestinationPath "Oqtane.Framework.6.0.0.Install.zip" -Force
|
||||||
|
@ -6,14 +6,22 @@ nuget.exe pack Oqtane.Client.nuspec
|
|||||||
nuget.exe pack Oqtane.Server.nuspec
|
nuget.exe pack Oqtane.Server.nuspec
|
||||||
nuget.exe pack Oqtane.Shared.nuspec
|
nuget.exe pack Oqtane.Shared.nuspec
|
||||||
nuget.exe pack Oqtane.Framework.nuspec
|
nuget.exe pack Oqtane.Framework.nuspec
|
||||||
del /F/Q/S "..\Oqtane.Server\bin\Release\net8.0\publish" > NUL
|
del /F/Q/S "..\Oqtane.Server\bin\Release\net9.0\publish" > NUL
|
||||||
rmdir /Q/S "..\Oqtane.Server\bin\Release\net8.0\publish"
|
rmdir /Q/S "..\Oqtane.Server\bin\Release\net9.0\publish"
|
||||||
dotnet publish ..\Oqtane.Server\Oqtane.Server.csproj /p:Configuration=Release
|
dotnet publish ..\Oqtane.Server\Oqtane.Server.csproj /p:Configuration=Release
|
||||||
del /F/Q/S "..\Oqtane.Server\bin\Release\net8.0\publish\wwwroot\Content" > NUL
|
del /F/Q/S "..\Oqtane.Server\bin\Release\net9.0\publish\wwwroot\Content" > NUL
|
||||||
rmdir /Q/S "..\Oqtane.Server\bin\Release\net8.0\publish\wwwroot\Content"
|
rmdir /Q/S "..\Oqtane.Server\bin\Release\net9.0\publish\wwwroot\Content"
|
||||||
setlocal ENABLEDELAYEDEXPANSION
|
setlocal ENABLEDELAYEDEXPANSION
|
||||||
|
set retain=Placeholder.txt
|
||||||
|
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
|
set retain=Oqtane.Modules.Admin.Login,Oqtane.Modules.HtmlText
|
||||||
for /D %%i in ("..\Oqtane.Server\bin\Release\net8.0\publish\wwwroot\Modules\*") do (
|
for /D %%i in ("..\Oqtane.Server\bin\Release\net9.0\publish\wwwroot\Modules\*") do (
|
||||||
set /A found=0
|
set /A found=0
|
||||||
for %%j in (%retain%) do (
|
for %%j in (%retain%) do (
|
||||||
if "%%~nxi" == "%%j" set /A found=1
|
if "%%~nxi" == "%%j" set /A found=1
|
||||||
@ -21,18 +29,18 @@ if "%%~nxi" == "%%j" set /A found=1
|
|||||||
if not !found! == 1 rmdir /Q/S "%%i"
|
if not !found! == 1 rmdir /Q/S "%%i"
|
||||||
)
|
)
|
||||||
set retain=Oqtane.Themes.BlazorTheme,Oqtane.Themes.OqtaneTheme
|
set retain=Oqtane.Themes.BlazorTheme,Oqtane.Themes.OqtaneTheme
|
||||||
for /D %%i in ("..\Oqtane.Server\bin\Release\net8.0\publish\wwwroot\Themes\*") do (
|
for /D %%i in ("..\Oqtane.Server\bin\Release\net9.0\publish\wwwroot\Themes\*") do (
|
||||||
set /A found=0
|
set /A found=0
|
||||||
for %%j in (%retain%) do (
|
for %%j in (%retain%) do (
|
||||||
if "%%~nxi" == "%%j" set /A found=1
|
if "%%~nxi" == "%%j" set /A found=1
|
||||||
)
|
)
|
||||||
if not !found! == 1 rmdir /Q/S "%%i"
|
if not !found! == 1 rmdir /Q/S "%%i"
|
||||||
)
|
)
|
||||||
del "..\Oqtane.Server\bin\Release\net8.0\publish\appsettings.json"
|
del "..\Oqtane.Server\bin\Release\net9.0\publish\appsettings.json"
|
||||||
ren "..\Oqtane.Server\bin\Release\net8.0\publish\appsettings.release.json" "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"
|
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe ".\install.ps1"
|
||||||
del "..\Oqtane.Server\bin\Release\net8.0\publish\appsettings.json"
|
del "..\Oqtane.Server\bin\Release\net9.0\publish\appsettings.json"
|
||||||
del "..\Oqtane.Server\bin\Release\net8.0\publish\web.config"
|
del "..\Oqtane.Server\bin\Release\net9.0\publish\web.config"
|
||||||
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe ".\upgrade.ps1"
|
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe ".\upgrade.ps1"
|
||||||
dotnet clean -c Release ..\Oqtane.Updater.sln
|
dotnet clean -c Release ..\Oqtane.Updater.sln
|
||||||
dotnet build -c Release ..\Oqtane.Updater.sln
|
dotnet build -c Release ..\Oqtane.Updater.sln
|
||||||
|
@ -1 +1 @@
|
|||||||
Compress-Archive -Path "..\Oqtane.Server\bin\Release\net8.0\publish\*" -DestinationPath "Oqtane.Framework.5.2.3.Upgrade.zip" -Force
|
Compress-Archive -Path "..\Oqtane.Server\bin\Release\net9.0\publish\*" -DestinationPath "Oqtane.Framework.6.0.0.Upgrade.zip" -Force
|
||||||
|
@ -179,10 +179,6 @@
|
|||||||
ManageScripts(resources, alias);
|
ManageScripts(resources, alias);
|
||||||
|
|
||||||
// generate scripts
|
// generate scripts
|
||||||
if (_renderMode == RenderModes.Interactive && _runtime == Runtimes.Server)
|
|
||||||
{
|
|
||||||
_scripts += CreateReconnectScript();
|
|
||||||
}
|
|
||||||
if (site.PwaIsEnabled && site.PwaAppIconFileId != null && site.PwaSplashIconFileId != null)
|
if (site.PwaIsEnabled && site.PwaAppIconFileId != null && site.PwaSplashIconFileId != null)
|
||||||
{
|
{
|
||||||
_scripts += CreatePWAScript(alias, site, route);
|
_scripts += CreatePWAScript(alias, site, route);
|
||||||
@ -196,28 +192,29 @@
|
|||||||
_bodyResources += ParseScripts(site.BodyContent);
|
_bodyResources += ParseScripts(site.BodyContent);
|
||||||
|
|
||||||
// set culture if not specified
|
// set culture if not specified
|
||||||
string culture = Context.Request.Cookies[CookieRequestCultureProvider.DefaultCookieName];
|
string cultureCookie = Context.Request.Cookies[Shared.CookieRequestCultureProvider.DefaultCookieName];
|
||||||
if (culture == null)
|
if (cultureCookie == null)
|
||||||
{
|
{
|
||||||
// get default language for site
|
// get default language for site
|
||||||
if (site.Languages.Any())
|
if (site.Languages.Any())
|
||||||
{
|
{
|
||||||
// use default language if specified otherwise use first language in collection
|
// use default language if specified otherwise use first language in collection
|
||||||
culture = (site.Languages.Where(l => l.IsDefault).SingleOrDefault() ?? site.Languages.First()).Code;
|
cultureCookie = (site.Languages.Where(l => l.IsDefault).SingleOrDefault() ?? site.Languages.First()).Code;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
culture = LocalizationManager.GetDefaultCulture();
|
// fallback language
|
||||||
|
cultureCookie = LocalizationManager.GetDefaultCulture();
|
||||||
}
|
}
|
||||||
SetLocalizationCookie(culture);
|
// convert language code to culture cookie format (ie. "c=en|uic=en")
|
||||||
|
cultureCookie = Shared.CookieRequestCultureProvider.MakeCookieValue(new Models.RequestCulture(cultureCookie));
|
||||||
|
SetLocalizationCookie(cultureCookie);
|
||||||
}
|
}
|
||||||
|
|
||||||
// set language for page
|
// set language for page
|
||||||
if (!string.IsNullOrEmpty(culture))
|
if (!string.IsNullOrEmpty(cultureCookie))
|
||||||
{
|
{
|
||||||
// localization cookie value in form of c=en|uic=en
|
_language = Shared.CookieRequestCultureProvider.ParseCookieValue(cultureCookie).Culture.Name;
|
||||||
_language = culture.Split('|')[0];
|
|
||||||
_language = _language.Replace("c=", "");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// create initial PageState
|
// create initial PageState
|
||||||
@ -494,25 +491,6 @@
|
|||||||
"</script>" + Environment.NewLine;
|
"</script>" + Environment.NewLine;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string CreateReconnectScript()
|
|
||||||
{
|
|
||||||
return Environment.NewLine +
|
|
||||||
"<script>" + Environment.NewLine +
|
|
||||||
" // Interactive Blazor Server Reconnect" + Environment.NewLine +
|
|
||||||
" new MutationObserver((mutations, observer) => {" + Environment.NewLine +
|
|
||||||
" if (document.querySelector('#components-reconnect-modal h5 a')) {" + Environment.NewLine +
|
|
||||||
" async function attemptReload() {" + Environment.NewLine +
|
|
||||||
" await fetch('');" + Environment.NewLine +
|
|
||||||
" location.reload();" + Environment.NewLine +
|
|
||||||
" }" + Environment.NewLine +
|
|
||||||
" observer.disconnect();" + Environment.NewLine +
|
|
||||||
" attemptReload();" + Environment.NewLine +
|
|
||||||
" setInterval(attemptReload, 5000);" + Environment.NewLine +
|
|
||||||
" }" + Environment.NewLine +
|
|
||||||
" }).observe(document.body, { childList: true, subtree: true });" + Environment.NewLine +
|
|
||||||
"</script>" + Environment.NewLine;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string CreateScrollPositionScript()
|
private string CreateScrollPositionScript()
|
||||||
{
|
{
|
||||||
return Environment.NewLine +
|
return Environment.NewLine +
|
||||||
@ -522,7 +500,7 @@
|
|||||||
" let currentUrl = window.location.pathname;" + Environment.NewLine +
|
" let currentUrl = window.location.pathname;" + Environment.NewLine +
|
||||||
" Blazor.addEventListener('enhancedload', () => {" + Environment.NewLine +
|
" Blazor.addEventListener('enhancedload', () => {" + Environment.NewLine +
|
||||||
" let newUrl = window.location.pathname;" + Environment.NewLine +
|
" let newUrl = window.location.pathname;" + Environment.NewLine +
|
||||||
" if (currentUrl !== newUrl || window.location.hash === '') {" + Environment.NewLine +
|
" if (currentUrl !== newUrl || window.location.hash === '#top') {" + Environment.NewLine +
|
||||||
" window.scrollTo({ top: 0, left: 0, behavior: 'instant' });" + Environment.NewLine +
|
" window.scrollTo({ top: 0, left: 0, behavior: 'instant' });" + Environment.NewLine +
|
||||||
" }" + Environment.NewLine +
|
" }" + Environment.NewLine +
|
||||||
" currentUrl = newUrl;" + Environment.NewLine +
|
" currentUrl = newUrl;" + Environment.NewLine +
|
||||||
@ -602,19 +580,19 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetLocalizationCookie(string culture)
|
private void SetLocalizationCookie(string cookieValue)
|
||||||
{
|
{
|
||||||
var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions
|
var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions
|
||||||
{
|
{
|
||||||
Expires = DateTimeOffset.UtcNow.AddYears(1),
|
Expires = DateTimeOffset.UtcNow.AddYears(1),
|
||||||
SameSite = Microsoft.AspNetCore.Http.SameSiteMode.Lax, // Set SameSite attribute
|
SameSite = Microsoft.AspNetCore.Http.SameSiteMode.Lax, // Set SameSite attribute
|
||||||
Secure = true, // Ensure the cookie is only sent over HTTPS
|
Secure = true, // Ensure the cookie is only sent over HTTPS
|
||||||
HttpOnly = true // Optional: Helps mitigate XSS attacks
|
HttpOnly = false // cookie is updated using JS Interop in Interactive render mode
|
||||||
};
|
};
|
||||||
|
|
||||||
Context.Response.Cookies.Append(
|
Context.Response.Cookies.Append(
|
||||||
CookieRequestCultureProvider.DefaultCookieName,
|
Shared.CookieRequestCultureProvider.DefaultCookieName,
|
||||||
CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture)),
|
cookieValue,
|
||||||
cookieOptions
|
cookieOptions
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -17,11 +17,10 @@ using Oqtane.Infrastructure;
|
|||||||
using Oqtane.Repository;
|
using Oqtane.Repository;
|
||||||
using Oqtane.Extensions;
|
using Oqtane.Extensions;
|
||||||
using SixLabors.ImageSharp;
|
using SixLabors.ImageSharp;
|
||||||
using SixLabors.ImageSharp.Processing;
|
|
||||||
using SixLabors.ImageSharp.Formats.Png;
|
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using Microsoft.AspNetCore.Cors;
|
using Microsoft.AspNetCore.Cors;
|
||||||
using System.IO.Compression;
|
using System.IO.Compression;
|
||||||
|
using Oqtane.Services;
|
||||||
|
|
||||||
// ReSharper disable StringIndexOfIsCultureSpecific.1
|
// ReSharper disable StringIndexOfIsCultureSpecific.1
|
||||||
|
|
||||||
@ -38,7 +37,9 @@ namespace Oqtane.Controllers
|
|||||||
private readonly ILogManager _logger;
|
private readonly ILogManager _logger;
|
||||||
private readonly Alias _alias;
|
private readonly Alias _alias;
|
||||||
private readonly ISettingRepository _settingRepository;
|
private readonly ISettingRepository _settingRepository;
|
||||||
public FileController(IWebHostEnvironment environment, IFileRepository files, IFolderRepository folders, IUserPermissions userPermissions, ISettingRepository settingRepository, ISyncManager syncManager, ILogManager logger, ITenantManager tenantManager)
|
private readonly IImageService _imageService;
|
||||||
|
|
||||||
|
public FileController(IWebHostEnvironment environment, IFileRepository files, IFolderRepository folders, IUserPermissions userPermissions, ISettingRepository settingRepository, ISyncManager syncManager, ILogManager logger, ITenantManager tenantManager, IImageService imageService)
|
||||||
{
|
{
|
||||||
_environment = environment;
|
_environment = environment;
|
||||||
_files = files;
|
_files = files;
|
||||||
@ -48,6 +49,7 @@ namespace Oqtane.Controllers
|
|||||||
_logger = logger;
|
_logger = logger;
|
||||||
_alias = tenantManager.GetAlias();
|
_alias = tenantManager.GetAlias();
|
||||||
_settingRepository = settingRepository;
|
_settingRepository = settingRepository;
|
||||||
|
_imageService = imageService;
|
||||||
}
|
}
|
||||||
|
|
||||||
// GET: api/<controller>?folder=x
|
// GET: api/<controller>?folder=x
|
||||||
@ -515,7 +517,7 @@ namespace Oqtane.Controllers
|
|||||||
bool success = true;
|
bool success = true;
|
||||||
using (var stream = new FileStream(Path.Combine(folder, filename + ".tmp"), FileMode.Create))
|
using (var stream = new FileStream(Path.Combine(folder, filename + ".tmp"), FileMode.Create))
|
||||||
{
|
{
|
||||||
foreach (string filepart in fileparts)
|
foreach (string filepart in fileparts.Order())
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -681,22 +683,18 @@ namespace Oqtane.Controllers
|
|||||||
var filepath = _files.GetFilePath(file);
|
var filepath = _files.GetFilePath(file);
|
||||||
if (System.IO.File.Exists(filepath))
|
if (System.IO.File.Exists(filepath))
|
||||||
{
|
{
|
||||||
// validation
|
|
||||||
if (!Enum.TryParse(mode, true, out ResizeMode _)) mode = "crop";
|
|
||||||
if (!Enum.TryParse(position, true, out AnchorPositionMode _)) position = "center";
|
|
||||||
if (!Color.TryParseHex("#" + background, out _)) background = "transparent";
|
|
||||||
if (!int.TryParse(rotate, out _)) rotate = "0";
|
|
||||||
rotate = (int.Parse(rotate) < 0 || int.Parse(rotate) > 360) ? "0" : rotate;
|
|
||||||
if (!bool.TryParse(recreate, out _)) recreate = "false";
|
if (!bool.TryParse(recreate, out _)) recreate = "false";
|
||||||
|
|
||||||
string imagepath = filepath.Replace(Path.GetExtension(filepath), "." + width.ToString() + "x" + height.ToString() + ".png");
|
string format = "png";
|
||||||
|
|
||||||
|
string imagepath = filepath.Replace(Path.GetExtension(filepath), "." + width.ToString() + "x" + height.ToString() + "." + format);
|
||||||
if (!System.IO.File.Exists(imagepath) || bool.Parse(recreate))
|
if (!System.IO.File.Exists(imagepath) || bool.Parse(recreate))
|
||||||
{
|
{
|
||||||
// user has edit access to folder or folder supports the image size being created
|
// user has edit access to folder or folder supports the image size being created
|
||||||
if (_userPermissions.IsAuthorized(User, PermissionNames.Edit, file.Folder.PermissionList) ||
|
if (_userPermissions.IsAuthorized(User, PermissionNames.Edit, file.Folder.PermissionList) ||
|
||||||
(!string.IsNullOrEmpty(file.Folder.ImageSizes) && (file.Folder.ImageSizes == "*" || file.Folder.ImageSizes.ToLower().Split(",").Contains(width.ToString() + "x" + height.ToString()))))
|
(!string.IsNullOrEmpty(file.Folder.ImageSizes) && (file.Folder.ImageSizes == "*" || file.Folder.ImageSizes.ToLower().Split(",").Contains(width.ToString() + "x" + height.ToString()))))
|
||||||
{
|
{
|
||||||
imagepath = CreateImage(filepath, width, height, mode, position, background, rotate, imagepath);
|
imagepath = _imageService.CreateImage(filepath, width, height, mode, position, background, rotate, format, imagepath);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -743,70 +741,6 @@ namespace Oqtane.Controllers
|
|||||||
return System.IO.File.Exists(errorPath) ? PhysicalFile(errorPath, MimeUtilities.GetMimeType(errorPath)) : null;
|
return System.IO.File.Exists(errorPath) ? PhysicalFile(errorPath, MimeUtilities.GetMimeType(errorPath)) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string CreateImage(string filepath, int width, int height, string mode, string position, string background, string rotate, string imagepath)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using (var stream = new FileStream(filepath, FileMode.Open, FileAccess.Read))
|
|
||||||
{
|
|
||||||
stream.Position = 0;
|
|
||||||
using (var image = Image.Load(stream))
|
|
||||||
{
|
|
||||||
int.TryParse(rotate, out int angle);
|
|
||||||
Enum.TryParse(mode, true, out ResizeMode resizemode);
|
|
||||||
Enum.TryParse(position, true, out AnchorPositionMode anchorpositionmode);
|
|
||||||
|
|
||||||
PngEncoder encoder;
|
|
||||||
|
|
||||||
if (background != "transparent")
|
|
||||||
{
|
|
||||||
image.Mutate(x => x
|
|
||||||
.AutoOrient() // auto orient the image
|
|
||||||
.Rotate(angle)
|
|
||||||
.Resize(new ResizeOptions
|
|
||||||
{
|
|
||||||
Mode = resizemode,
|
|
||||||
Position = anchorpositionmode,
|
|
||||||
Size = new Size(width, height),
|
|
||||||
PadColor = Color.ParseHex("#" + background)
|
|
||||||
}));
|
|
||||||
|
|
||||||
encoder = new PngEncoder();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
image.Mutate(x => x
|
|
||||||
.AutoOrient() // auto orient the image
|
|
||||||
.Rotate(angle)
|
|
||||||
.Resize(new ResizeOptions
|
|
||||||
{
|
|
||||||
Mode = resizemode,
|
|
||||||
Position = anchorpositionmode,
|
|
||||||
Size = new Size(width, height)
|
|
||||||
}));
|
|
||||||
|
|
||||||
encoder = new PngEncoder
|
|
||||||
{
|
|
||||||
ColorType = PngColorType.RgbWithAlpha,
|
|
||||||
TransparentColorMode = PngTransparentColorMode.Preserve,
|
|
||||||
BitDepth = PngBitDepth.Bit8,
|
|
||||||
CompressionLevel = PngCompressionLevel.BestSpeed
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
image.Save(imagepath, encoder);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_logger.Log(LogLevel.Error, this, LogFunction.Security, ex, "Error Creating Image For File {FilePath} {Width} {Height} {Mode} {Rotate} {Error}", filepath, width, height, mode, rotate, ex.Message);
|
|
||||||
imagepath = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
return imagepath;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string GetFolderPath(string folder)
|
private string GetFolderPath(string folder)
|
||||||
{
|
{
|
||||||
return Utilities.PathCombine(_environment.ContentRootPath, folder);
|
return Utilities.PathCombine(_environment.ContentRootPath, folder);
|
||||||
|
@ -55,6 +55,10 @@ namespace Oqtane.Controllers
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
languages = _languages.GetLanguages(SiteId).ToList();
|
languages = _languages.GetLanguages(SiteId).ToList();
|
||||||
|
foreach (Language language in languages)
|
||||||
|
{
|
||||||
|
language.Name = CultureInfo.GetCultureInfo(language.Code).DisplayName;
|
||||||
|
}
|
||||||
if (!string.IsNullOrEmpty(packagename))
|
if (!string.IsNullOrEmpty(packagename))
|
||||||
{
|
{
|
||||||
foreach (var file in Directory.EnumerateFiles(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), $"{packagename}*{Constants.SatelliteAssemblyExtension}", SearchOption.AllDirectories))
|
foreach (var file in Directory.EnumerateFiles(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), $"{packagename}*{Constants.SatelliteAssemblyExtension}", SearchOption.AllDirectories))
|
||||||
@ -85,6 +89,7 @@ namespace Oqtane.Controllers
|
|||||||
var language = _languages.GetLanguage(id);
|
var language = _languages.GetLanguage(id);
|
||||||
if (language != null && language.SiteId == _alias.SiteId)
|
if (language != null && language.SiteId == _alias.SiteId)
|
||||||
{
|
{
|
||||||
|
language.Name = CultureInfo.GetCultureInfo(language.Code).DisplayName;
|
||||||
return language;
|
return language;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -351,9 +351,9 @@ namespace Oqtane.Controllers
|
|||||||
return new Dictionary<string, object>()
|
return new Dictionary<string, object>()
|
||||||
{
|
{
|
||||||
{ "FrameworkVersion", Constants.Version },
|
{ "FrameworkVersion", Constants.Version },
|
||||||
{ "ClientReference", $"<Reference Include=\"Oqtane.Client\"><HintPath>..\\..\\{rootFolder}\\Oqtane.Server\\bin\\Debug\\net8.0\\Oqtane.Client.dll</HintPath></Reference>" },
|
{ "ClientReference", $"<Reference Include=\"Oqtane.Client\"><HintPath>..\\..\\{rootFolder}\\Oqtane.Server\\bin\\Debug\\net9.0\\Oqtane.Client.dll</HintPath></Reference>" },
|
||||||
{ "ServerReference", $"<Reference Include=\"Oqtane.Server\"><HintPath>..\\..\\{rootFolder}\\Oqtane.Server\\bin\\Debug\\net8.0\\Oqtane.Server.dll</HintPath></Reference>" },
|
{ "ServerReference", $"<Reference Include=\"Oqtane.Server\"><HintPath>..\\..\\{rootFolder}\\Oqtane.Server\\bin\\Debug\\net9.0\\Oqtane.Server.dll</HintPath></Reference>" },
|
||||||
{ "SharedReference", $"<Reference Include=\"Oqtane.Shared\"><HintPath>..\\..\\{rootFolder}\\Oqtane.Server\\bin\\Debug\\net8.0\\Oqtane.Shared.dll</HintPath></Reference>" },
|
{ "SharedReference", $"<Reference Include=\"Oqtane.Shared\"><HintPath>..\\..\\{rootFolder}\\Oqtane.Server\\bin\\Debug\\net9.0\\Oqtane.Shared.dll</HintPath></Reference>" },
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -8,10 +8,6 @@ using Oqtane.Infrastructure;
|
|||||||
using Oqtane.Repository;
|
using Oqtane.Repository;
|
||||||
using Oqtane.Security;
|
using Oqtane.Security;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Reflection.Metadata;
|
|
||||||
using Microsoft.Extensions.Localization;
|
|
||||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace Oqtane.Controllers
|
namespace Oqtane.Controllers
|
||||||
{
|
{
|
||||||
|
@ -189,7 +189,7 @@ namespace Oqtane.Controllers
|
|||||||
public void Delete(string entityName, int entityId, string settingName)
|
public void Delete(string entityName, int entityId, string settingName)
|
||||||
{
|
{
|
||||||
Setting setting = _settings.GetSetting(entityName, entityId, settingName);
|
Setting setting = _settings.GetSetting(entityName, entityId, settingName);
|
||||||
if (IsAuthorized(setting.EntityName, setting.EntityId, PermissionNames.Edit))
|
if (setting != null && IsAuthorized(setting.EntityName, setting.EntityId, PermissionNames.Edit))
|
||||||
{
|
{
|
||||||
_settings.DeleteSetting(setting.EntityName, setting.SettingId);
|
_settings.DeleteSetting(setting.EntityName, setting.SettingId);
|
||||||
AddSyncEvent(setting.EntityName, setting.EntityId, setting.SettingId, SyncEventActions.Delete);
|
AddSyncEvent(setting.EntityName, setting.EntityId, setting.SettingId, SyncEventActions.Delete);
|
||||||
@ -199,7 +199,7 @@ namespace Oqtane.Controllers
|
|||||||
{
|
{
|
||||||
if (entityName != EntityNames.Visitor)
|
if (entityName != EntityNames.Visitor)
|
||||||
{
|
{
|
||||||
_logger.Log(LogLevel.Error, this, LogFunction.Delete, "User Not Authorized To Delete Setting {Setting}", setting);
|
_logger.Log(LogLevel.Error, this, LogFunction.Delete, "Setting Does Not Exist Or User Not Authorized To Delete Setting For Entity {EntityName} Id {EntityId} Name {SettingName}", entityName, entityId, settingName);
|
||||||
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -267,8 +267,8 @@ namespace Oqtane.Controllers
|
|||||||
return new Dictionary<string, object>()
|
return new Dictionary<string, object>()
|
||||||
{
|
{
|
||||||
{ "FrameworkVersion", Constants.Version },
|
{ "FrameworkVersion", Constants.Version },
|
||||||
{ "ClientReference", $"<Reference Include=\"Oqtane.Client\"><HintPath>..\\..\\{rootFolder}\\Oqtane.Server\\bin\\Debug\\net8.0\\Oqtane.Client.dll</HintPath></Reference>" },
|
{ "ClientReference", $"<Reference Include=\"Oqtane.Client\"><HintPath>..\\..\\{rootFolder}\\Oqtane.Server\\bin\\Debug\\net9.0\\Oqtane.Client.dll</HintPath></Reference>" },
|
||||||
{ "SharedReference", $"<Reference Include=\"Oqtane.Shared\"><HintPath>..\\..\\{rootFolder}\\Oqtane.Server\\bin\\Debug\\net8.0\\Oqtane.Shared.dll</HintPath></Reference>" },
|
{ "SharedReference", $"<Reference Include=\"Oqtane.Shared\"><HintPath>..\\..\\{rootFolder}\\Oqtane.Server\\bin\\Debug\\net9.0\\Oqtane.Shared.dll</HintPath></Reference>" },
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -347,6 +347,13 @@ namespace Oqtane.Controllers
|
|||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GET api/<controller>/validate/x
|
||||||
|
[HttpGet("validateuser")]
|
||||||
|
public async Task<UserValidateResult> ValidateUser(string username, string email, string password)
|
||||||
|
{
|
||||||
|
return await _userManager.ValidateUser(username, email, password);
|
||||||
|
}
|
||||||
|
|
||||||
// GET api/<controller>/validate/x
|
// GET api/<controller>/validate/x
|
||||||
[HttpGet("validate/{password}")]
|
[HttpGet("validate/{password}")]
|
||||||
public async Task<bool> Validate(string password)
|
public async Task<bool> Validate(string password)
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using Oqtane.Databases.Interfaces;
|
using Oqtane.Databases.Interfaces;
|
||||||
using Oqtane.Interfaces;
|
|
||||||
|
|
||||||
namespace Oqtane.Repository.Databases.Interfaces
|
namespace Oqtane.Repository.Databases.Interfaces
|
||||||
{
|
{
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Diagnostics;
|
||||||
using Oqtane.Databases.Interfaces;
|
using Oqtane.Databases.Interfaces;
|
||||||
// ReSharper disable ConvertToUsingDeclaration
|
// ReSharper disable ConvertToUsingDeclaration
|
||||||
|
|
||||||
@ -9,7 +10,8 @@ namespace Oqtane.Extensions
|
|||||||
{
|
{
|
||||||
public static DbContextOptionsBuilder UseOqtaneDatabase([NotNull] this DbContextOptionsBuilder optionsBuilder, IDatabase database, string connectionString)
|
public static DbContextOptionsBuilder UseOqtaneDatabase([NotNull] this DbContextOptionsBuilder optionsBuilder, IDatabase database, string connectionString)
|
||||||
{
|
{
|
||||||
database.UseDatabase(optionsBuilder, connectionString);
|
database.UseDatabase(optionsBuilder, connectionString)
|
||||||
|
.ConfigureWarnings(warnings => warnings.Log(RelationalEventId.PendingModelChangesWarning));
|
||||||
|
|
||||||
return optionsBuilder;
|
return optionsBuilder;
|
||||||
}
|
}
|
||||||
|
@ -102,6 +102,7 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||||||
services.AddScoped<ISearchResultsService, SearchResultsService>();
|
services.AddScoped<ISearchResultsService, SearchResultsService>();
|
||||||
services.AddScoped<ISearchService, SearchService>();
|
services.AddScoped<ISearchService, SearchService>();
|
||||||
services.AddScoped<ISearchProvider, DatabaseSearchProvider>();
|
services.AddScoped<ISearchProvider, DatabaseSearchProvider>();
|
||||||
|
services.AddScoped<IImageService, ImageService>();
|
||||||
|
|
||||||
// providers
|
// providers
|
||||||
services.AddScoped<ITextEditor, Oqtane.Modules.Controls.QuillJSTextEditor>();
|
services.AddScoped<ITextEditor, Oqtane.Modules.Controls.QuillJSTextEditor>();
|
||||||
@ -112,8 +113,11 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||||||
|
|
||||||
internal static IServiceCollection AddOqtaneTransientServices(this IServiceCollection services)
|
internal static IServiceCollection AddOqtaneTransientServices(this IServiceCollection services)
|
||||||
{
|
{
|
||||||
// repositories
|
// services
|
||||||
services.AddTransient<ISiteService, ServerSiteService>();
|
services.AddTransient<ISiteService, ServerSiteService>();
|
||||||
|
services.AddTransient<ILocalizationCookieService, ServerLocalizationCookieService>();
|
||||||
|
|
||||||
|
// repositories
|
||||||
services.AddTransient<IModuleDefinitionRepository, ModuleDefinitionRepository>();
|
services.AddTransient<IModuleDefinitionRepository, ModuleDefinitionRepository>();
|
||||||
services.AddTransient<IThemeRepository, ThemeRepository>();
|
services.AddTransient<IThemeRepository, ThemeRepository>();
|
||||||
services.AddTransient<IAliasRepository, AliasRepository>();
|
services.AddTransient<IAliasRepository, AliasRepository>();
|
||||||
@ -129,7 +133,6 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||||||
services.AddTransient<IPermissionRepository, PermissionRepository>();
|
services.AddTransient<IPermissionRepository, PermissionRepository>();
|
||||||
services.AddTransient<ISettingRepository, SettingRepository>();
|
services.AddTransient<ISettingRepository, SettingRepository>();
|
||||||
services.AddTransient<ILogRepository, LogRepository>();
|
services.AddTransient<ILogRepository, LogRepository>();
|
||||||
services.AddTransient<ILocalizationManager, LocalizationManager>();
|
|
||||||
services.AddTransient<IJobRepository, JobRepository>();
|
services.AddTransient<IJobRepository, JobRepository>();
|
||||||
services.AddTransient<IJobLogRepository, JobLogRepository>();
|
services.AddTransient<IJobLogRepository, JobLogRepository>();
|
||||||
services.AddTransient<INotificationRepository, NotificationRepository>();
|
services.AddTransient<INotificationRepository, NotificationRepository>();
|
||||||
@ -152,12 +155,12 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||||||
services.AddTransient<ILogManager, LogManager>();
|
services.AddTransient<ILogManager, LogManager>();
|
||||||
services.AddTransient<IUpgradeManager, UpgradeManager>();
|
services.AddTransient<IUpgradeManager, UpgradeManager>();
|
||||||
services.AddTransient<IUserManager, UserManager>();
|
services.AddTransient<IUserManager, UserManager>();
|
||||||
|
services.AddTransient<ILocalizationManager, LocalizationManager>();
|
||||||
// obsolete - replaced by ITenantManager
|
|
||||||
services.AddTransient<ITenantResolver, TenantResolver>();
|
|
||||||
|
|
||||||
services.AddTransient<ITokenReplace, TokenReplace>();
|
services.AddTransient<ITokenReplace, TokenReplace>();
|
||||||
|
|
||||||
|
// obsolete
|
||||||
|
services.AddTransient<ITenantResolver, TenantResolver>(); // replaced by ITenantManager
|
||||||
|
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,6 +172,7 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||||||
options.Cookie.HttpOnly = true;
|
options.Cookie.HttpOnly = true;
|
||||||
options.Cookie.SameSite = SameSiteMode.Lax;
|
options.Cookie.SameSite = SameSiteMode.Lax;
|
||||||
options.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest;
|
options.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest;
|
||||||
|
options.LoginPath = "/login"; // overrides .NET Identity default of /Account/Login
|
||||||
options.Events.OnRedirectToLogin = context =>
|
options.Events.OnRedirectToLogin = context =>
|
||||||
{
|
{
|
||||||
context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
||||||
|
@ -592,7 +592,7 @@ namespace Oqtane.Extensions
|
|||||||
}
|
}
|
||||||
|
|
||||||
// create claims identity
|
// create claims identity
|
||||||
identityuser = await _identityUserManager.FindByEmailAsync(user.Username);
|
identityuser = await _identityUserManager.FindByNameAsync(user.Username);
|
||||||
user.SecurityStamp = identityuser.SecurityStamp;
|
user.SecurityStamp = identityuser.SecurityStamp;
|
||||||
identity = UserSecurity.CreateClaimsIdentity(alias, user, userRoles);
|
identity = UserSecurity.CreateClaimsIdentity(alias, user, userRoles);
|
||||||
identity.Label = ExternalLoginStatus.Success;
|
identity.Label = ExternalLoginStatus.Success;
|
||||||
@ -645,13 +645,13 @@ namespace Oqtane.Extensions
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.Log(LogLevel.Information, "ExternalLogin", Enums.LogFunction.Security, "External User Login Successful For {Username} From IP Address {IPAddress} Using Provider {Provider}", user.Username, httpContext.Connection.RemoteIpAddress, providerName);
|
_logger.Log(LogLevel.Information, "ExternalLogin", Enums.LogFunction.Security, "External User Login Successful For {Username} From IP Address {IPAddress} Using Provider {Provider}", user.Username, httpContext.Connection.RemoteIpAddress.ToString(), providerName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else // claims invalid
|
else // claims invalid
|
||||||
{
|
{
|
||||||
identity.Label = ExternalLoginStatus.MissingClaims;
|
identity.Label = ExternalLoginStatus.MissingClaims;
|
||||||
_logger.Log(LogLevel.Error, "ExternalLogin", Enums.LogFunction.Security, "Provider Did Not Return All Of The Claims Types Specified Or Email Address Does Not Saitisfy Domain Filter. The Actual Claims Returned Were {Claims}. Login Was Denied.", claims);
|
_logger.Log(LogLevel.Error, "ExternalLogin", Enums.LogFunction.Security, "Provider Did Not Return All Of The Claims Types Specified Or Email Address Does Not Satisfy Domain Filter. The Actual Claims Returned Were {Claims}. Login Was Denied.", claims);
|
||||||
}
|
}
|
||||||
|
|
||||||
return identity;
|
return identity;
|
||||||
|
@ -155,7 +155,7 @@ namespace Oqtane.Infrastructure
|
|||||||
// add new site
|
// add new site
|
||||||
if (install.TenantName != TenantNames.Master && install.ConnectionString.Contains("="))
|
if (install.TenantName != TenantNames.Master && install.ConnectionString.Contains("="))
|
||||||
{
|
{
|
||||||
_configManager.AddOrUpdateSetting($"{SettingKeys.ConnectionStringsSection}:{install.TenantName}", install.ConnectionString, false);
|
_configManager.AddOrUpdateSetting($"{SettingKeys.ConnectionStringsSection}:{install.TenantName}", install.ConnectionString, true);
|
||||||
}
|
}
|
||||||
if (install.TenantName == TenantNames.Master && !install.ConnectionString.Contains("="))
|
if (install.TenantName == TenantNames.Master && !install.ConnectionString.Contains("="))
|
||||||
{
|
{
|
||||||
@ -375,7 +375,6 @@ namespace Oqtane.Infrastructure
|
|||||||
AddEFMigrationsHistory(sql, _configManager.GetSetting($"{SettingKeys.ConnectionStringsSection}:{tenant.DBConnectionString}", ""), tenant.DBType, tenant.Version, false);
|
AddEFMigrationsHistory(sql, _configManager.GetSetting($"{SettingKeys.ConnectionStringsSection}:{tenant.DBConnectionString}", ""), tenant.DBType, tenant.Version, false);
|
||||||
// push latest model into database
|
// push latest model into database
|
||||||
tenantDbContext.Database.Migrate();
|
tenantDbContext.Database.Migrate();
|
||||||
result.Success = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@ -384,6 +383,8 @@ namespace Oqtane.Infrastructure
|
|||||||
_filelogger.LogError(Utilities.LogMessage(this, result.Message));
|
_filelogger.LogError(Utilities.LogMessage(this, result.Message));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(result.Message))
|
||||||
|
{
|
||||||
// execute any version specific upgrade logic
|
// execute any version specific upgrade logic
|
||||||
var version = tenant.Version;
|
var version = tenant.Version;
|
||||||
var index = Array.FindIndex(versions, item => item == version);
|
var index = Array.FindIndex(versions, item => item == version);
|
||||||
@ -408,12 +409,10 @@ namespace Oqtane.Infrastructure
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(result.Message))
|
|
||||||
{
|
|
||||||
result.Success = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result.Success = string.IsNullOrEmpty(result.Message);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -588,7 +587,7 @@ namespace Oqtane.Infrastructure
|
|||||||
|
|
||||||
// add host role
|
// add host role
|
||||||
var hostRoleId = roles.GetRoles(user.SiteId, true).FirstOrDefault(item => item.Name == RoleNames.Host)?.RoleId ?? 0;
|
var hostRoleId = roles.GetRoles(user.SiteId, true).FirstOrDefault(item => item.Name == RoleNames.Host)?.RoleId ?? 0;
|
||||||
var userRole = new UserRole { UserId = user.UserId, RoleId = hostRoleId, EffectiveDate = null, ExpiryDate = null };
|
var userRole = new UserRole { UserId = user.UserId, RoleId = hostRoleId, EffectiveDate = null, ExpiryDate = null, IgnoreSecurityStamp = true };
|
||||||
userRoles.AddUserRole(userRole);
|
userRoles.AddUserRole(userRole);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -89,9 +89,9 @@ namespace Oqtane.Infrastructure
|
|||||||
}
|
}
|
||||||
|
|
||||||
// validate recipient
|
// validate recipient
|
||||||
if (string.IsNullOrEmpty(notification.ToEmail))
|
if (string.IsNullOrEmpty(notification.ToEmail) || !MailAddress.TryCreate(notification.ToEmail, out _))
|
||||||
{
|
{
|
||||||
log += "Recipient Missing For NotificationId: " + notification.NotificationId + "<br />";
|
log += $"NotificationId: {notification.NotificationId} - Has Missing Or Invalid Recipient {notification.ToEmail}<br />";
|
||||||
notification.IsDeleted = true;
|
notification.IsDeleted = true;
|
||||||
notificationRepository.UpdateNotification(notification);
|
notificationRepository.UpdateNotification(notification);
|
||||||
}
|
}
|
||||||
|
@ -59,8 +59,15 @@ namespace Oqtane.Infrastructure
|
|||||||
var currentTime = DateTime.UtcNow;
|
var currentTime = DateTime.UtcNow;
|
||||||
var lastIndexedOn = Convert.ToDateTime(siteSettings.GetValue(SearchLastIndexedOnSetting, DateTime.MinValue.ToString()));
|
var lastIndexedOn = Convert.ToDateTime(siteSettings.GetValue(SearchLastIndexedOnSetting, DateTime.MinValue.ToString()));
|
||||||
|
|
||||||
|
if (lastIndexedOn == DateTime.MinValue)
|
||||||
|
{
|
||||||
|
// reset index
|
||||||
|
log += $"*Site Index Reset*<br />";
|
||||||
|
await searchService.DeleteSearchContentsAsync(site.SiteId);
|
||||||
|
}
|
||||||
|
|
||||||
var ignorePages = siteSettings.GetValue(SearchIgnorePagesSetting, "").Split(',');
|
var ignorePages = siteSettings.GetValue(SearchIgnorePagesSetting, "").Split(',');
|
||||||
var ignoreEntities = siteSettings.GetValue(SearchIgnoreEntitiesSetting, "").Split(',');
|
var ignoreEntities = siteSettings.GetValue(SearchIgnoreEntitiesSetting, "File").Split(',');
|
||||||
|
|
||||||
var pages = pageRepository.GetPages(site.SiteId);
|
var pages = pageRepository.GetPages(site.SiteId);
|
||||||
var pageModules = pageModuleRepository.GetPageModules(site.SiteId);
|
var pageModules = pageModuleRepository.GetPageModules(site.SiteId);
|
||||||
|
@ -19,6 +19,7 @@ namespace Oqtane.Managers
|
|||||||
Task<User> ResetPassword(User user, string token);
|
Task<User> ResetPassword(User user, string token);
|
||||||
User VerifyTwoFactor(User user, string token);
|
User VerifyTwoFactor(User user, string token);
|
||||||
Task<User> LinkExternalAccount(User user, string token, string type, string key, string name);
|
Task<User> LinkExternalAccount(User user, string token, string type, string key, string name);
|
||||||
|
Task<UserValidateResult> ValidateUser(string username, string email, string password);
|
||||||
Task<bool> ValidatePassword(string password);
|
Task<bool> ValidatePassword(string password);
|
||||||
Task<Dictionary<string, string>> ImportUsers(int siteId, string filePath, bool notify);
|
Task<Dictionary<string, string>> ImportUsers(int siteId, string filePath, bool notify);
|
||||||
}
|
}
|
||||||
|
@ -540,6 +540,30 @@ namespace Oqtane.Managers
|
|||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<UserValidateResult> ValidateUser(string username, string email, string password)
|
||||||
|
{
|
||||||
|
var validateResult = new UserValidateResult { Succeeded = true };
|
||||||
|
|
||||||
|
//validate username
|
||||||
|
var allowedChars = _identityUserManager.Options.User.AllowedUserNameCharacters;
|
||||||
|
if (string.IsNullOrWhiteSpace(username) || (!string.IsNullOrEmpty(allowedChars) && username.Any(c => !allowedChars.Contains(c))))
|
||||||
|
{
|
||||||
|
validateResult.Succeeded = false;
|
||||||
|
validateResult.Errors.Add("Message.Username.Invalid", string.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
//validate password
|
||||||
|
var passwordValidator = new PasswordValidator<IdentityUser>();
|
||||||
|
var passwordResult = await passwordValidator.ValidateAsync(_identityUserManager, null, password);
|
||||||
|
if (!passwordResult.Succeeded)
|
||||||
|
{
|
||||||
|
validateResult.Succeeded = false;
|
||||||
|
validateResult.Errors.Add("Message.Password.Invalid", string.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
return validateResult;
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<bool> ValidatePassword(string password)
|
public async Task<bool> ValidatePassword(string password)
|
||||||
{
|
{
|
||||||
var validator = new PasswordValidator<IdentityUser>();
|
var validator = new PasswordValidator<IdentityUser>();
|
||||||
|
@ -319,6 +319,19 @@ namespace Oqtane.Migrations.EntityBuilders
|
|||||||
schema: Schema);
|
schema: Schema);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual void AddForeignKey(string foreignKeyName, string columnName, string principalTable, string principalColumn, string principalSchema, ReferentialAction onDelete)
|
||||||
|
{
|
||||||
|
_migrationBuilder.AddForeignKey(
|
||||||
|
name: RewriteName(foreignKeyName),
|
||||||
|
table: RewriteName(EntityTableName),
|
||||||
|
column: RewriteName(columnName),
|
||||||
|
principalTable: RewriteName(principalTable),
|
||||||
|
principalColumn: RewriteName(principalColumn),
|
||||||
|
principalSchema: RewriteName(principalSchema),
|
||||||
|
onDelete: onDelete,
|
||||||
|
schema: Schema);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a Migration to add an Index to the Entity (table)
|
/// Creates a Migration to add an Index to the Entity (table)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -368,6 +381,7 @@ namespace Oqtane.Migrations.EntityBuilders
|
|||||||
column: foreignKey.Column,
|
column: foreignKey.Column,
|
||||||
principalTable: RewriteName(foreignKey.PrincipalTable),
|
principalTable: RewriteName(foreignKey.PrincipalTable),
|
||||||
principalColumn: RewriteName(foreignKey.PrincipalColumn),
|
principalColumn: RewriteName(foreignKey.PrincipalColumn),
|
||||||
|
principalSchema: RewriteName(foreignKey.PrincipalSchema),
|
||||||
onDelete: foreignKey.OnDeleteAction);
|
onDelete: foreignKey.OnDeleteAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -381,6 +395,7 @@ namespace Oqtane.Migrations.EntityBuilders
|
|||||||
column: RewriteName(foreignKey.ColumnName),
|
column: RewriteName(foreignKey.ColumnName),
|
||||||
principalTable: RewriteName(foreignKey.PrincipalTable),
|
principalTable: RewriteName(foreignKey.PrincipalTable),
|
||||||
principalColumn: RewriteName(foreignKey.PrincipalColumn),
|
principalColumn: RewriteName(foreignKey.PrincipalColumn),
|
||||||
|
principalSchema: RewriteName(foreignKey.PrincipalSchema),
|
||||||
onDelete: foreignKey.OnDeleteAction,
|
onDelete: foreignKey.OnDeleteAction,
|
||||||
schema: Schema);
|
schema: Schema);
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,16 @@ namespace Oqtane.Migrations
|
|||||||
OnDeleteAction = onDeleteAction;
|
OnDeleteAction = onDeleteAction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ForeignKey(string name, Expression<Func<TEntityBuilder, object>> column, string principalTable, string principalColumn, string principalSchema, ReferentialAction onDeleteAction)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
Column = column;
|
||||||
|
PrincipalTable = principalTable;
|
||||||
|
PrincipalColumn = principalColumn;
|
||||||
|
PrincipalSchema = principalSchema;
|
||||||
|
OnDeleteAction = onDeleteAction;
|
||||||
|
}
|
||||||
|
|
||||||
public string Name { get; }
|
public string Name { get; }
|
||||||
|
|
||||||
public Expression<Func<TEntityBuilder, object>> Column { get;}
|
public Expression<Func<TEntityBuilder, object>> Column { get;}
|
||||||
@ -34,6 +44,8 @@ namespace Oqtane.Migrations
|
|||||||
|
|
||||||
public string PrincipalColumn { get; }
|
public string PrincipalColumn { get; }
|
||||||
|
|
||||||
|
public string PrincipalSchema { get; } = "";
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,28 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Oqtane.Databases.Interfaces;
|
||||||
|
using Oqtane.Migrations.EntityBuilders;
|
||||||
|
using Oqtane.Repository;
|
||||||
|
|
||||||
|
namespace Oqtane.Migrations.Tenant
|
||||||
|
{
|
||||||
|
[DbContext(typeof(TenantDBContext))]
|
||||||
|
[Migration("Tenant.05.02.04.01")]
|
||||||
|
public class RemoveLanguageName : MultiDatabaseMigration
|
||||||
|
{
|
||||||
|
public RemoveLanguageName(IDatabase database) : base(database)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
var languageEntityBuilder = new LanguageEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
languageEntityBuilder.DropColumn("Name");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
// not implemented
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -45,11 +45,26 @@ namespace Oqtane.Modules.Admin.Files.Manager
|
|||||||
var path = folder.Path + file.Name;
|
var path = folder.Path + file.Name;
|
||||||
|
|
||||||
var body = "";
|
var body = "";
|
||||||
|
if (System.IO.File.Exists(_fileRepository.GetFilePath(file)))
|
||||||
|
{
|
||||||
|
// only non-binary files can be indexed
|
||||||
if (DocumentExtensions.Contains(Path.GetExtension(file.Name)))
|
if (DocumentExtensions.Contains(Path.GetExtension(file.Name)))
|
||||||
{
|
{
|
||||||
// get the contents of the file
|
// get the contents of the file
|
||||||
|
try
|
||||||
|
{
|
||||||
body = System.IO.File.ReadAllText(_fileRepository.GetFilePath(file));
|
body = System.IO.File.ReadAllText(_fileRepository.GetFilePath(file));
|
||||||
}
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// could not read the file
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
removed = true; // file does not exist on disk
|
||||||
|
}
|
||||||
|
|
||||||
var searchContent = new SearchContent
|
var searchContent = new SearchContent
|
||||||
{
|
{
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
<Configurations>Debug;Release</Configurations>
|
<Configurations>Debug;Release</Configurations>
|
||||||
<Version>5.2.3</Version>
|
<Version>6.0.0</Version>
|
||||||
<Product>Oqtane</Product>
|
<Product>Oqtane</Product>
|
||||||
<Authors>Shaun Walker</Authors>
|
<Authors>Shaun Walker</Authors>
|
||||||
<Company>.NET Foundation</Company>
|
<Company>.NET Foundation</Company>
|
||||||
@ -11,7 +11,7 @@
|
|||||||
<Copyright>.NET Foundation</Copyright>
|
<Copyright>.NET Foundation</Copyright>
|
||||||
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
||||||
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
||||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v5.2.3</PackageReleaseNotes>
|
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v6.0.0</PackageReleaseNotes>
|
||||||
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
||||||
<RepositoryType>Git</RepositoryType>
|
<RepositoryType>Git</RepositoryType>
|
||||||
<RootNamespace>Oqtane</RootNamespace>
|
<RootNamespace>Oqtane</RootNamespace>
|
||||||
@ -33,21 +33,21 @@
|
|||||||
<EmbeddedResource Include="Scripts\MigrateTenant.sql" />
|
<EmbeddedResource Include="Scripts\MigrateTenant.sql" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="HtmlAgilityPack" Version="1.11.62" />
|
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="9.0.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="8.0.8" />
|
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="9.0.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="8.0.8" />
|
<PackageReference Include="Microsoft.Data.SqlClient" Version="6.0.0-preview2.24304.8" />
|
||||||
<PackageReference Include="Microsoft.Data.SqlClient" Version="5.2.1" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.0" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.8" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.0">
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.8">
|
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="8.0.8" />
|
<PackageReference Include="Microsoft.Extensions.Localization" Version="9.0.0" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="9.0.0" />
|
||||||
|
<PackageReference Include="Microsoft.Data.Sqlite.Core" Version="9.0.0" />
|
||||||
|
<PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="2.1.10" />
|
||||||
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.5" />
|
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.5" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.7.0" />
|
<PackageReference Include="HtmlAgilityPack" Version="1.11.71" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="8.0.8" />
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="7.0.0" />
|
||||||
<PackageReference Include="Microsoft.Data.Sqlite.Core" Version="8.0.8" />
|
|
||||||
<PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="2.1.9" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Oqtane.Client\Oqtane.Client.csproj" />
|
<ProjectReference Include="..\Oqtane.Client\Oqtane.Client.csproj" />
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
@ -14,6 +15,7 @@ using Oqtane.Infrastructure;
|
|||||||
using Oqtane.Models;
|
using Oqtane.Models;
|
||||||
using Oqtane.Repository;
|
using Oqtane.Repository;
|
||||||
using Oqtane.Security;
|
using Oqtane.Security;
|
||||||
|
using Oqtane.Services;
|
||||||
using Oqtane.Shared;
|
using Oqtane.Shared;
|
||||||
|
|
||||||
namespace Oqtane.Pages
|
namespace Oqtane.Pages
|
||||||
@ -28,8 +30,10 @@ namespace Oqtane.Pages
|
|||||||
private readonly ISyncManager _syncManager;
|
private readonly ISyncManager _syncManager;
|
||||||
private readonly ILogManager _logger;
|
private readonly ILogManager _logger;
|
||||||
private readonly Alias _alias;
|
private readonly Alias _alias;
|
||||||
|
private readonly IImageService _imageService;
|
||||||
|
private readonly ISettingRepository _settingRepository;
|
||||||
|
|
||||||
public FilesModel(IWebHostEnvironment environment, IFileRepository files, IUserPermissions userPermissions, IUrlMappingRepository urlMappings, ISyncManager syncManager, ILogManager logger, ITenantManager tenantManager)
|
public FilesModel(IWebHostEnvironment environment, IFileRepository files, IUserPermissions userPermissions, IUrlMappingRepository urlMappings, ISyncManager syncManager, ILogManager logger, ITenantManager tenantManager, IImageService imageService, ISettingRepository settingRepository)
|
||||||
{
|
{
|
||||||
_environment = environment;
|
_environment = environment;
|
||||||
_files = files;
|
_files = files;
|
||||||
@ -38,12 +42,19 @@ namespace Oqtane.Pages
|
|||||||
_syncManager = syncManager;
|
_syncManager = syncManager;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_alias = tenantManager.GetAlias();
|
_alias = tenantManager.GetAlias();
|
||||||
|
_imageService = imageService;
|
||||||
|
_settingRepository = settingRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IActionResult OnGet(string path)
|
public IActionResult OnGet(string path)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(path))
|
if (string.IsNullOrWhiteSpace(path))
|
||||||
{
|
{
|
||||||
|
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized File Access Attempt - Path Not Specified For Site {SiteId}", _alias.SiteId);
|
||||||
|
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
||||||
|
return BrokenFile();
|
||||||
|
}
|
||||||
|
|
||||||
path = path.Replace("\\", "/");
|
path = path.Replace("\\", "/");
|
||||||
var folderpath = "";
|
var folderpath = "";
|
||||||
var filename = "";
|
var filename = "";
|
||||||
@ -74,56 +85,10 @@ namespace Oqtane.Pages
|
|||||||
file = _files.GetFile(_alias.SiteId, folderpath, filename);
|
file = _files.GetFile(_alias.SiteId, folderpath, filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (file != null)
|
if (file == null)
|
||||||
{
|
|
||||||
if (file.Folder.SiteId == _alias.SiteId && _userPermissions.IsAuthorized(User, PermissionNames.View, file.Folder.PermissionList))
|
|
||||||
{
|
|
||||||
// calculate ETag using last modified date and file size
|
|
||||||
var etag = Convert.ToString(file.ModifiedOn.Ticks ^ file.Size, 16);
|
|
||||||
|
|
||||||
var header = "";
|
|
||||||
if (HttpContext.Request.Headers.ContainsKey(HeaderNames.IfNoneMatch))
|
|
||||||
{
|
|
||||||
header = HttpContext.Request.Headers[HeaderNames.IfNoneMatch].ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!header.Equals(etag))
|
|
||||||
{
|
|
||||||
var filepath = _files.GetFilePath(file);
|
|
||||||
if (System.IO.File.Exists(filepath))
|
|
||||||
{
|
|
||||||
if (download)
|
|
||||||
{
|
|
||||||
_syncManager.AddSyncEvent(_alias, EntityNames.File, file.FileId, "Download");
|
|
||||||
return PhysicalFile(filepath, file.GetMimeType(), file.Name);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
HttpContext.Response.Headers.Append(HeaderNames.ETag, etag);
|
|
||||||
return PhysicalFile(filepath, file.GetMimeType());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_logger.Log(LogLevel.Error, this, LogFunction.Read, "File Does Not Exist {FilePath}", filepath);
|
|
||||||
HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
HttpContext.Response.StatusCode = (int)HttpStatusCode.NotModified;
|
|
||||||
return Content(String.Empty);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized File Access Attempt For Site {SiteId} And Path {Path}", _alias.SiteId, path);
|
|
||||||
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
// look for url mapping
|
// look for url mapping
|
||||||
|
|
||||||
var urlMapping = _urlMappings.GetUrlMapping(_alias.SiteId, "files/" + folderpath + filename);
|
var urlMapping = _urlMappings.GetUrlMapping(_alias.SiteId, "files/" + folderpath + filename);
|
||||||
if (urlMapping != null && !string.IsNullOrEmpty(urlMapping.MappedUrl))
|
if (urlMapping != null && !string.IsNullOrEmpty(urlMapping.MappedUrl))
|
||||||
{
|
{
|
||||||
@ -133,16 +98,172 @@ namespace Oqtane.Pages
|
|||||||
var uri = new Uri(HttpContext.Request.GetEncodedUrl());
|
var uri = new Uri(HttpContext.Request.GetEncodedUrl());
|
||||||
url = uri.Scheme + "://" + uri.Authority + ((!string.IsNullOrEmpty(_alias.Path)) ? "/" + _alias.Path : "") + "/" + url;
|
url = uri.Scheme + "://" + uri.Authority + ((!string.IsNullOrEmpty(_alias.Path)) ? "/" + _alias.Path : "") + "/" + url;
|
||||||
}
|
}
|
||||||
return RedirectPermanent(url);
|
|
||||||
}
|
// appends the query string to the redirect url
|
||||||
}
|
if (Request.QueryString.HasValue && !string.IsNullOrWhiteSpace(Request.QueryString.Value))
|
||||||
|
{
|
||||||
|
if (url.Contains('?'))
|
||||||
|
{
|
||||||
|
url += "&";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized File Access Attempt - Path Not Specified For Site {SiteId}", _alias.SiteId);
|
url += "?";
|
||||||
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
url += Request.QueryString.Value.Substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return RedirectPermanent(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
return BrokenFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file.Folder.SiteId != _alias.SiteId || !_userPermissions.IsAuthorized(User, PermissionNames.View, file.Folder.PermissionList))
|
||||||
|
{
|
||||||
|
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized File Access Attempt For Site {SiteId} And Path {Path}", _alias.SiteId, path);
|
||||||
|
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
||||||
|
return BrokenFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
string etag;
|
||||||
|
string downloadName = file.Name;
|
||||||
|
string filepath = _files.GetFilePath(file);
|
||||||
|
|
||||||
|
var etagValue = file.ModifiedOn.Ticks ^ file.Size;
|
||||||
|
|
||||||
|
bool isRequestingImageManipulation = false;
|
||||||
|
|
||||||
|
int width = 0;
|
||||||
|
int height = 0;
|
||||||
|
if (Request.Query.TryGetValue("width", out var widthStr) && int.TryParse(widthStr, out width) && width > 0)
|
||||||
|
{
|
||||||
|
isRequestingImageManipulation = true;
|
||||||
|
etagValue ^= (width * 31);
|
||||||
|
}
|
||||||
|
if (Request.Query.TryGetValue("height", out var heightStr) && int.TryParse(heightStr, out height) && height > 0)
|
||||||
|
{
|
||||||
|
isRequestingImageManipulation = true;
|
||||||
|
etagValue ^= (height * 17);
|
||||||
|
}
|
||||||
|
|
||||||
|
Request.Query.TryGetValue("mode", out var mode);
|
||||||
|
Request.Query.TryGetValue("position", out var position);
|
||||||
|
Request.Query.TryGetValue("background", out var background);
|
||||||
|
|
||||||
|
if (width > 0 || height > 0)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrWhiteSpace(mode)) etagValue ^= mode.ToString().GetHashCode();
|
||||||
|
if (!string.IsNullOrWhiteSpace(position)) etagValue ^= position.ToString().GetHashCode();
|
||||||
|
if (!string.IsNullOrWhiteSpace(background)) etagValue ^= background.ToString().GetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
int rotate;
|
||||||
|
if (Request.Query.TryGetValue("rotate", out var rotateStr) && int.TryParse(rotateStr, out rotate) && 360 > rotate && rotate > 0)
|
||||||
|
{
|
||||||
|
isRequestingImageManipulation = true;
|
||||||
|
etagValue ^= (rotate * 13);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Request.Query.TryGetValue("format", out var format) && _imageService.GetAvailableFormats().Contains(format.ToString()))
|
||||||
|
{
|
||||||
|
isRequestingImageManipulation = true;
|
||||||
|
etagValue ^= format.ToString().GetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
etag = Convert.ToString(etagValue, 16);
|
||||||
|
|
||||||
|
var header = "";
|
||||||
|
if (HttpContext.Request.Headers.TryGetValue(HeaderNames.IfNoneMatch, out var ifNoneMatch))
|
||||||
|
{
|
||||||
|
header = ifNoneMatch.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (header.Equals(etag))
|
||||||
|
{
|
||||||
|
HttpContext.Response.StatusCode = (int)HttpStatusCode.NotModified;
|
||||||
|
return Content(String.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!System.IO.File.Exists(filepath))
|
||||||
|
{
|
||||||
|
_logger.Log(LogLevel.Error, this, LogFunction.Read, "File Does Not Exist {FilePath}", filepath);
|
||||||
|
HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound;
|
||||||
|
return BrokenFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isRequestingImageManipulation)
|
||||||
|
{
|
||||||
|
var _ImageFiles = _settingRepository.GetSetting(EntityNames.Site, _alias.SiteId, "ImageFiles")?.SettingValue;
|
||||||
|
_ImageFiles = (string.IsNullOrEmpty(_ImageFiles)) ? Constants.ImageFiles : _ImageFiles;
|
||||||
|
|
||||||
|
if (!_ImageFiles.Split(',').Contains(file.Extension.ToLower()))
|
||||||
|
{
|
||||||
|
_logger.Log(LogLevel.Error, this, LogFunction.Security, "File Is Not An Image {File}", file);
|
||||||
|
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
||||||
|
return BrokenFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
Request.Query.TryGetValue("recreate", out var recreate);
|
||||||
|
|
||||||
|
if (!bool.TryParse(recreate, out _)) recreate = "false";
|
||||||
|
if (!_imageService.GetAvailableFormats().Contains(format.ToString())) format = "png";
|
||||||
|
if (width == 0 && height == 0)
|
||||||
|
{
|
||||||
|
width = file.ImageWidth;
|
||||||
|
height = file.ImageHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
string imagepath = filepath.Replace(Path.GetExtension(filepath), "." + width.ToString() + "x" + height.ToString() + "." + format);
|
||||||
|
if (!System.IO.File.Exists(imagepath) || bool.Parse(recreate))
|
||||||
|
{
|
||||||
|
// user has edit access to folder or folder supports the image size being created
|
||||||
|
if (_userPermissions.IsAuthorized(User, PermissionNames.Edit, file.Folder.PermissionList) ||
|
||||||
|
(!string.IsNullOrEmpty(file.Folder.ImageSizes) && (file.Folder.ImageSizes == "*" || file.Folder.ImageSizes.ToLower().Split(",").Contains(width.ToString() + "x" + height.ToString()))))
|
||||||
|
{
|
||||||
|
imagepath = _imageService.CreateImage(filepath, width, height, mode, position, background, rotateStr, format, imagepath);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Invalid Image Size For Folder {Folder} {Width} {Height}", file.Folder, width, height);
|
||||||
|
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
||||||
|
return BrokenFile();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(imagepath))
|
||||||
|
{
|
||||||
|
_logger.Log(LogLevel.Error, this, LogFunction.Create, "Error Displaying Image For File {File} {Width} {Height}", file, widthStr, heightStr);
|
||||||
|
HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound;
|
||||||
|
return BrokenFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
downloadName = file.Name.Replace(Path.GetExtension(filepath), "." + width.ToString() + "x" + height.ToString() + "." + format);
|
||||||
|
filepath = imagepath;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!System.IO.File.Exists(filepath))
|
||||||
|
{
|
||||||
|
_logger.Log(LogLevel.Error, this, LogFunction.Read, "File Does Not Exist {FilePath}", filepath);
|
||||||
|
HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound;
|
||||||
|
return BrokenFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (download)
|
||||||
|
{
|
||||||
|
_syncManager.AddSyncEvent(_alias, EntityNames.File, file.FileId, "Download");
|
||||||
|
return PhysicalFile(filepath, file.GetMimeType(), downloadName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
HttpContext.Response.Headers.Append(HeaderNames.ETag, etag);
|
||||||
|
return PhysicalFile(filepath, file.GetMimeType());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private PhysicalFileResult BrokenFile()
|
||||||
|
{
|
||||||
// broken link
|
// broken link
|
||||||
string errorPath = Path.Combine(Utilities.PathCombine(_environment.ContentRootPath, "wwwroot/images"), "error.png");
|
string errorPath = Path.Combine(Utilities.PathCombine(_environment.ContentRootPath, "wwwroot/images"), "error.png");
|
||||||
return PhysicalFile(errorPath, MimeUtilities.GetMimeType(errorPath));
|
return PhysicalFile(errorPath, MimeUtilities.GetMimeType(errorPath));
|
||||||
|
@ -235,9 +235,9 @@ namespace Oqtane.Providers
|
|||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task ResetIndex()
|
public Task DeleteSearchContent(int siteId)
|
||||||
{
|
{
|
||||||
_searchContentRepository.DeleteAllSearchContent();
|
_searchContentRepository.DeleteAllSearchContent(siteId);
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ namespace Oqtane.Repository
|
|||||||
void DeleteSearchContent(int searchContentId);
|
void DeleteSearchContent(int searchContentId);
|
||||||
void DeleteSearchContent(string entityName, string entryId);
|
void DeleteSearchContent(string entityName, string entryId);
|
||||||
void DeleteSearchContent(string uniqueKey);
|
void DeleteSearchContent(string uniqueKey);
|
||||||
void DeleteAllSearchContent();
|
void DeleteAllSearchContent(int siteId);
|
||||||
|
|
||||||
SearchWord GetSearchWord(string word);
|
SearchWord GetSearchWord(string word);
|
||||||
SearchWord AddSearchWord(SearchWord searchWord);
|
SearchWord AddSearchWord(SearchWord searchWord);
|
||||||
|
@ -91,6 +91,7 @@ namespace Oqtane.Repository
|
|||||||
public void DeletePage(int pageId)
|
public void DeletePage(int pageId)
|
||||||
{
|
{
|
||||||
using var db = _dbContextFactory.CreateDbContext();
|
using var db = _dbContextFactory.CreateDbContext();
|
||||||
|
{
|
||||||
var page = db.Page.Find(pageId);
|
var page = db.Page.Find(pageId);
|
||||||
_permissions.DeletePermissions(page.SiteId, EntityNames.Page, pageId);
|
_permissions.DeletePermissions(page.SiteId, EntityNames.Page, pageId);
|
||||||
_settings.DeleteSettings(EntityNames.Page, pageId);
|
_settings.DeleteSettings(EntityNames.Page, pageId);
|
||||||
@ -100,9 +101,19 @@ namespace Oqtane.Repository
|
|||||||
{
|
{
|
||||||
_pageModules.DeletePageModule(pageModule.PageModuleId);
|
_pageModules.DeletePageModule(pageModule.PageModuleId);
|
||||||
}
|
}
|
||||||
// must occur after page modules are deleted because of cascading delete relationship
|
|
||||||
db.Page.Remove(page);
|
// At this point the page item is unaware of changes happened in other
|
||||||
db.SaveChanges();
|
// contexts (i.e.: the contex opened and closed in each DeletePageModule).
|
||||||
|
// Workin on page item may result in unxpected behaviour:
|
||||||
|
// better close and reopen context to work on a fresh page item.
|
||||||
|
}
|
||||||
|
|
||||||
|
using var dbContext = _dbContextFactory.CreateDbContext();
|
||||||
|
{
|
||||||
|
var page = dbContext.Page.Find(pageId);
|
||||||
|
dbContext.Page.Remove(page);
|
||||||
|
dbContext.SaveChanges();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -152,11 +152,17 @@ namespace Oqtane.Repository
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DeleteAllSearchContent()
|
public void DeleteAllSearchContent(int siteId)
|
||||||
{
|
{
|
||||||
using var db = _dbContextFactory.CreateDbContext();
|
using var db = _dbContextFactory.CreateDbContext();
|
||||||
db.SearchContent.RemoveRange(db.SearchContent);
|
// delete in batches of 100 records
|
||||||
|
var searchContents = db.SearchContent.Where(item => item.SiteId == siteId).Take(100).ToList();
|
||||||
|
while (searchContents.Count > 0)
|
||||||
|
{
|
||||||
|
db.SearchContent.RemoveRange(searchContents);
|
||||||
db.SaveChanges();
|
db.SaveChanges();
|
||||||
|
searchContents = db.SearchContent.Where(item => item.SiteId == siteId).Take(100).ToList();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public SearchWord GetSearchWord(string word)
|
public SearchWord GetSearchWord(string word)
|
||||||
|
@ -75,6 +75,7 @@ namespace Oqtane.Repository
|
|||||||
userrole.RoleId = role.RoleId;
|
userrole.RoleId = role.RoleId;
|
||||||
userrole.EffectiveDate = null;
|
userrole.EffectiveDate = null;
|
||||||
userrole.ExpiryDate = null;
|
userrole.ExpiryDate = null;
|
||||||
|
userrole.IgnoreSecurityStamp = true;
|
||||||
_userroles.AddUserRole(userrole);
|
_userroles.AddUserRole(userrole);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,7 +72,12 @@ namespace Oqtane.Repository
|
|||||||
DeleteUserRoles(userRole.UserId);
|
DeleteUserRoles(userRole.UserId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!userRole.IgnoreSecurityStamp)
|
||||||
|
{
|
||||||
UpdateSecurityStamp(userRole.UserId);
|
UpdateSecurityStamp(userRole.UserId);
|
||||||
|
}
|
||||||
|
|
||||||
|
RefreshCache(userRole.UserId);
|
||||||
|
|
||||||
return userRole;
|
return userRole;
|
||||||
}
|
}
|
||||||
@ -83,7 +88,12 @@ namespace Oqtane.Repository
|
|||||||
db.Entry(userRole).State = EntityState.Modified;
|
db.Entry(userRole).State = EntityState.Modified;
|
||||||
db.SaveChanges();
|
db.SaveChanges();
|
||||||
|
|
||||||
|
if (!userRole.IgnoreSecurityStamp)
|
||||||
|
{
|
||||||
UpdateSecurityStamp(userRole.UserId);
|
UpdateSecurityStamp(userRole.UserId);
|
||||||
|
}
|
||||||
|
|
||||||
|
RefreshCache(userRole.UserId);
|
||||||
|
|
||||||
return userRole;
|
return userRole;
|
||||||
}
|
}
|
||||||
@ -144,6 +154,7 @@ namespace Oqtane.Repository
|
|||||||
db.SaveChanges();
|
db.SaveChanges();
|
||||||
|
|
||||||
UpdateSecurityStamp(userRole.UserId);
|
UpdateSecurityStamp(userRole.UserId);
|
||||||
|
RefreshCache(userRole.UserId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DeleteUserRoles(int userId)
|
public void DeleteUserRoles(int userId)
|
||||||
@ -156,11 +167,11 @@ namespace Oqtane.Repository
|
|||||||
db.SaveChanges();
|
db.SaveChanges();
|
||||||
|
|
||||||
UpdateSecurityStamp(userId);
|
UpdateSecurityStamp(userId);
|
||||||
|
RefreshCache(userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateSecurityStamp(int userId)
|
private void UpdateSecurityStamp(int userId)
|
||||||
{
|
{
|
||||||
// update user security stamp
|
|
||||||
using var db = _dbContextFactory.CreateDbContext();
|
using var db = _dbContextFactory.CreateDbContext();
|
||||||
var user = db.User.Find(userId);
|
var user = db.User.Find(userId);
|
||||||
if (user != null)
|
if (user != null)
|
||||||
@ -168,11 +179,13 @@ namespace Oqtane.Repository
|
|||||||
var identityuser = _identityUserManager.FindByNameAsync(user.Username).GetAwaiter().GetResult();
|
var identityuser = _identityUserManager.FindByNameAsync(user.Username).GetAwaiter().GetResult();
|
||||||
if (identityuser != null)
|
if (identityuser != null)
|
||||||
{
|
{
|
||||||
_identityUserManager.UpdateSecurityStampAsync(identityuser);
|
_identityUserManager.UpdateSecurityStampAsync(identityuser).GetAwaiter().GetResult();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// refresh cache
|
private void RefreshCache(int userId)
|
||||||
|
{
|
||||||
var alias = _tenantManager.GetAlias();
|
var alias = _tenantManager.GetAlias();
|
||||||
if (alias != null)
|
if (alias != null)
|
||||||
{
|
{
|
||||||
|
@ -7,13 +7,13 @@ using Oqtane.Models;
|
|||||||
using Oqtane.Extensions;
|
using Oqtane.Extensions;
|
||||||
using Oqtane.Shared;
|
using Oqtane.Shared;
|
||||||
using Oqtane.Managers;
|
using Oqtane.Managers;
|
||||||
|
using Microsoft.AspNetCore.Authentication;
|
||||||
|
|
||||||
namespace Oqtane.Security
|
namespace Oqtane.Security
|
||||||
{
|
{
|
||||||
public static class PrincipalValidator
|
public static class PrincipalValidator
|
||||||
{
|
{
|
||||||
public static Task ValidateAsync(CookieValidatePrincipalContext context)
|
public static async Task ValidateAsync(CookieValidatePrincipalContext context)
|
||||||
{
|
{
|
||||||
if (context != null && context.Principal.Identity.IsAuthenticated && context.Principal.Identity.Name != null)
|
if (context != null && context.Principal.Identity.IsAuthenticated && context.Principal.Identity.Name != null)
|
||||||
{
|
{
|
||||||
@ -49,6 +49,7 @@ namespace Oqtane.Security
|
|||||||
// remove principal (ie. log user out)
|
// remove principal (ie. log user out)
|
||||||
Log(_logger, alias, "Permissions Removed For User {Username} Accessing {Url}", context.Principal.Identity.Name, path);
|
Log(_logger, alias, "Permissions Removed For User {Username} Accessing {Url}", context.Principal.Identity.Name, path);
|
||||||
context.RejectPrincipal();
|
context.RejectPrincipal();
|
||||||
|
await context.HttpContext.SignOutAsync(Constants.AuthenticationScheme);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -58,7 +59,6 @@ namespace Oqtane.Security
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void Log (ILogManager logger, Alias alias, string message, string username, string path)
|
private static void Log (ILogManager logger, Alias alias, string message, string username, string path)
|
||||||
|
124
Oqtane.Server/Services/ImageService.cs
Normal file
124
Oqtane.Server/Services/ImageService.cs
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
using Oqtane.Enums;
|
||||||
|
using SixLabors.ImageSharp.Formats.Png;
|
||||||
|
using SixLabors.ImageSharp.Processing;
|
||||||
|
using System.IO;
|
||||||
|
using System;
|
||||||
|
using SixLabors.ImageSharp;
|
||||||
|
using Oqtane.Infrastructure;
|
||||||
|
using Oqtane.Shared;
|
||||||
|
using SixLabors.ImageSharp.Formats;
|
||||||
|
using SixLabors.ImageSharp.Formats.Webp;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Oqtane.Services
|
||||||
|
{
|
||||||
|
public class ImageService : IImageService
|
||||||
|
{
|
||||||
|
private readonly ILogManager _logger;
|
||||||
|
private static readonly string[] _formats = ["png", "webp"];
|
||||||
|
|
||||||
|
public ImageService(ILogManager logger)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string[] GetAvailableFormats()
|
||||||
|
{
|
||||||
|
return _formats;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string CreateImage(string filepath, int width, int height, string mode, string position, string background, string rotate, string format, string imagepath)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// params validation
|
||||||
|
if (!Enum.TryParse(mode, true, out ResizeMode _)) mode = "crop";
|
||||||
|
if (!Enum.TryParse(position, true, out AnchorPositionMode _)) position = "center";
|
||||||
|
if (!Color.TryParseHex("#" + background, out _)) background = "transparent";
|
||||||
|
if (!int.TryParse(rotate, out _)) rotate = "0";
|
||||||
|
rotate = (int.Parse(rotate) < 0 || int.Parse(rotate) > 360) ? "0" : rotate;
|
||||||
|
if (!_formats.Contains(format)) format = "png";
|
||||||
|
|
||||||
|
using (var stream = new FileStream(filepath, FileMode.Open, FileAccess.Read))
|
||||||
|
{
|
||||||
|
stream.Position = 0;
|
||||||
|
using (var image = Image.Load(stream))
|
||||||
|
{
|
||||||
|
int.TryParse(rotate, out int angle);
|
||||||
|
Enum.TryParse(mode, true, out ResizeMode resizemode);
|
||||||
|
Enum.TryParse(position, true, out AnchorPositionMode anchorpositionmode);
|
||||||
|
|
||||||
|
if (width == 0 && height == 0)
|
||||||
|
{
|
||||||
|
width = image.Width;
|
||||||
|
height = image.Height;
|
||||||
|
}
|
||||||
|
|
||||||
|
IImageEncoder encoder;
|
||||||
|
var resizeOptions = new ResizeOptions
|
||||||
|
{
|
||||||
|
Mode = resizemode,
|
||||||
|
Position = anchorpositionmode,
|
||||||
|
Size = new Size(width, height)
|
||||||
|
};
|
||||||
|
|
||||||
|
if (background != "transparent")
|
||||||
|
{
|
||||||
|
resizeOptions.PadColor = Color.ParseHex("#" + background);
|
||||||
|
encoder = GetEncoder(format, transparent: false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
encoder = GetEncoder(format, transparent: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
image.Mutate(x => x
|
||||||
|
.AutoOrient() // auto orient the image
|
||||||
|
.Rotate(angle)
|
||||||
|
.Resize(resizeOptions));
|
||||||
|
|
||||||
|
image.Save(imagepath, encoder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.Log(LogLevel.Error, this, LogFunction.Security, ex, "Error Creating Image For File {FilePath} {Width} {Height} {Mode} {Rotate} {Error}", filepath, width, height, mode, rotate, ex.Message);
|
||||||
|
imagepath = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return imagepath;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IImageEncoder GetEncoder(string format, bool transparent)
|
||||||
|
{
|
||||||
|
return format switch
|
||||||
|
{
|
||||||
|
"png" => GetPngEncoder(transparent),
|
||||||
|
"webp" => GetWebpEncoder(transparent),
|
||||||
|
_ => GetPngEncoder(transparent),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static PngEncoder GetPngEncoder(bool transparent)
|
||||||
|
{
|
||||||
|
return new PngEncoder()
|
||||||
|
{
|
||||||
|
ColorType = transparent ? PngColorType.RgbWithAlpha : PngColorType.Rgb,
|
||||||
|
TransparentColorMode = transparent ? PngTransparentColorMode.Preserve : PngTransparentColorMode.Clear,
|
||||||
|
BitDepth = PngBitDepth.Bit8,
|
||||||
|
CompressionLevel = PngCompressionLevel.BestSpeed
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static WebpEncoder GetWebpEncoder(bool transparent)
|
||||||
|
{
|
||||||
|
return new WebpEncoder()
|
||||||
|
{
|
||||||
|
FileFormat = WebpFileFormatType.Lossy,
|
||||||
|
Quality = 60,
|
||||||
|
TransparentColorMode = transparent ? WebpTransparentColorMode.Preserve : WebpTransparentColorMode.Clear,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
35
Oqtane.Server/Services/LocalizationCookieService.cs
Normal file
35
Oqtane.Server/Services/LocalizationCookieService.cs
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Localization;
|
||||||
|
using Oqtane.Documentation;
|
||||||
|
|
||||||
|
namespace Oqtane.Services
|
||||||
|
{
|
||||||
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
|
public class ServerLocalizationCookieService : ILocalizationCookieService
|
||||||
|
{
|
||||||
|
private readonly IHttpContextAccessor _accessor;
|
||||||
|
|
||||||
|
public ServerLocalizationCookieService(IHttpContextAccessor accessor)
|
||||||
|
{
|
||||||
|
_accessor = accessor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task SetLocalizationCookieAsync(string culture)
|
||||||
|
{
|
||||||
|
var localizationCookieValue = CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture));
|
||||||
|
|
||||||
|
_accessor.HttpContext.Response.Cookies.Append(CookieRequestCultureProvider.DefaultCookieName, localizationCookieValue, new CookieOptions
|
||||||
|
{
|
||||||
|
Path = "/",
|
||||||
|
Expires = DateTimeOffset.UtcNow.AddYears(365),
|
||||||
|
SameSite = SameSiteMode.Lax,
|
||||||
|
Secure = true, // Ensure the cookie is only sent over HTTPS
|
||||||
|
HttpOnly = false // cookie is updated using JS Interop in Interactive render mode
|
||||||
|
});
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -149,6 +149,12 @@ namespace Oqtane.Services
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task DeleteSearchContentsAsync(int siteId)
|
||||||
|
{
|
||||||
|
var searchProvider = GetSearchProvider(siteId);
|
||||||
|
await searchProvider.DeleteSearchContent(siteId);
|
||||||
|
}
|
||||||
|
|
||||||
private ISearchProvider GetSearchProvider(int siteId)
|
private ISearchProvider GetSearchProvider(int siteId)
|
||||||
{
|
{
|
||||||
var providerName = GetSearchProviderSetting(siteId);
|
var providerName = GetSearchProviderSetting(siteId);
|
||||||
|
@ -92,6 +92,13 @@ namespace Oqtane.Services
|
|||||||
}
|
}
|
||||||
site.Pages = pages;
|
site.Pages = pages;
|
||||||
|
|
||||||
|
// get language display name for user
|
||||||
|
foreach (Language language in site.Languages)
|
||||||
|
{
|
||||||
|
language.Name = CultureInfo.GetCultureInfo(language.Code).DisplayName;
|
||||||
|
}
|
||||||
|
site.Languages = site.Languages.OrderBy(item => item.Name).ToList();
|
||||||
|
|
||||||
return Task.FromResult(site);
|
return Task.FromResult(site);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,7 +137,10 @@ namespace Oqtane.Services
|
|||||||
// languages
|
// languages
|
||||||
site.Languages = _languages.GetLanguages(site.SiteId).ToList();
|
site.Languages = _languages.GetLanguages(site.SiteId).ToList();
|
||||||
var defaultCulture = CultureInfo.GetCultureInfo(Constants.DefaultCulture);
|
var defaultCulture = CultureInfo.GetCultureInfo(Constants.DefaultCulture);
|
||||||
site.Languages.Add(new Language { Code = defaultCulture.Name, Name = defaultCulture.DisplayName, Version = Constants.Version, IsDefault = !site.Languages.Any(l => l.IsDefault) });
|
if (!site.Languages.Exists(item => item.Code == defaultCulture.Name))
|
||||||
|
{
|
||||||
|
site.Languages.Add(new Language { Code = defaultCulture.Name, Name = "", Version = Constants.Version, IsDefault = !site.Languages.Any(l => l.IsDefault) });
|
||||||
|
}
|
||||||
|
|
||||||
// themes
|
// themes
|
||||||
site.Themes = _themes.FilterThemes(_themes.GetThemes().ToList());
|
site.Themes = _themes.FilterThemes(_themes.GetThemes().ToList());
|
||||||
|
@ -159,7 +159,7 @@ namespace Oqtane
|
|||||||
}
|
}
|
||||||
}).AddHubOptions(options =>
|
}).AddHubOptions(options =>
|
||||||
{
|
{
|
||||||
options.MaximumReceiveMessageSize = null; // no limit (for large amnounts of data ie. textarea components)
|
options.MaximumReceiveMessageSize = null; // no limit (for large amounts of data ie. textarea components)
|
||||||
})
|
})
|
||||||
.AddInteractiveWebAssemblyComponents();
|
.AddInteractiveWebAssemblyComponents();
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ namespace [Owner].Module.[Module].Services
|
|||||||
{
|
{
|
||||||
public class [Module]Service : ServiceBase, I[Module]Service
|
public class [Module]Service : ServiceBase, I[Module]Service
|
||||||
{
|
{
|
||||||
public [Module]Service(IHttpClientFactory http, SiteState siteState) : base(http, siteState) { }
|
public [Module]Service(HttpClient http, SiteState siteState) : base(http, siteState) { }
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl("[Module]");
|
private string Apiurl => CreateApiUrl("[Module]");
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk.Razor">
|
<Project Sdk="Microsoft.NET.Sdk.Razor">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
<Version>1.0.0</Version>
|
<Version>1.0.0</Version>
|
||||||
<Authors>[Owner]</Authors>
|
<Authors>[Owner]</Authors>
|
||||||
<Company>[Owner]</Company>
|
<Company>[Owner]</Company>
|
||||||
@ -13,12 +13,11 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="8.0.8" />
|
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="9.0.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="8.0.8" />
|
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="9.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="8.0.8" />
|
<PackageReference Include="Microsoft.Extensions.Localization" Version="9.0.0" />
|
||||||
<PackageReference Include="System.Net.Http.Json" Version="8.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Http" Version="9.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Http" Version="8.0.0" />
|
<PackageReference Include="System.Net.Http.Json" Version="9.0.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Localization" Version="2.2.0" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
|
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
|
||||||
<AccelerateBuildsInVisualStudio>false</AccelerateBuildsInVisualStudio>
|
<AccelerateBuildsInVisualStudio>false</AccelerateBuildsInVisualStudio>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
@ -20,12 +20,12 @@
|
|||||||
</dependencies>
|
</dependencies>
|
||||||
</metadata>
|
</metadata>
|
||||||
<files>
|
<files>
|
||||||
<file src="..\Client\bin\Release\net8.0\[Owner].Module.[Module].Client.Oqtane.dll" target="lib\net8.0" />
|
<file src="..\Client\bin\Release\net9.0\[Owner].Module.[Module].Client.Oqtane.dll" target="lib\net9.0" />
|
||||||
<file src="..\Client\bin\Release\net8.0\[Owner].Module.[Module].Client.Oqtane.pdb" target="lib\net8.0" />
|
<file src="..\Client\bin\Release\net9.0\[Owner].Module.[Module].Client.Oqtane.pdb" target="lib\net9.0" />
|
||||||
<file src="..\Server\bin\Release\net8.0\[Owner].Module.[Module].Server.Oqtane.dll" target="lib\net8.0" />
|
<file src="..\Server\bin\Release\net9.0\[Owner].Module.[Module].Server.Oqtane.dll" target="lib\net9.0" />
|
||||||
<file src="..\Server\bin\Release\net8.0\[Owner].Module.[Module].Server.Oqtane.pdb" target="lib\net8.0" />
|
<file src="..\Server\bin\Release\net9.0\[Owner].Module.[Module].Server.Oqtane.pdb" target="lib\net9.0" />
|
||||||
<file src="..\Shared\bin\Release\net8.0\[Owner].Module.[Module].Shared.Oqtane.dll" target="lib\net8.0" />
|
<file src="..\Shared\bin\Release\net9.0\[Owner].Module.[Module].Shared.Oqtane.dll" target="lib\net9.0" />
|
||||||
<file src="..\Shared\bin\Release\net8.0\[Owner].Module.[Module].Shared.Oqtane.pdb" target="lib\net8.0" />
|
<file src="..\Shared\bin\Release\net9.0\[Owner].Module.[Module].Shared.Oqtane.pdb" target="lib\net9.0" />
|
||||||
<file src="..\Server\wwwroot\**\*.*" target="wwwroot" />
|
<file src="..\Server\wwwroot\**\*.*" target="wwwroot" />
|
||||||
<file src="icon.png" target="" />
|
<file src="icon.png" target="" />
|
||||||
</files>
|
</files>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
XCOPY "..\Client\bin\Debug\net8.0\[Owner].Module.[Module].Client.Oqtane.dll" "..\..\[RootFolder]\Oqtane.Server\bin\Debug\net8.0\" /Y
|
XCOPY "..\Client\bin\Debug\net9.0\[Owner].Module.[Module].Client.Oqtane.dll" "..\..\[RootFolder]\Oqtane.Server\bin\Debug\net9.0\" /Y
|
||||||
XCOPY "..\Client\bin\Debug\net8.0\[Owner].Module.[Module].Client.Oqtane.pdb" "..\..\[RootFolder]\Oqtane.Server\bin\Debug\net8.0\" /Y
|
XCOPY "..\Client\bin\Debug\net9.0\[Owner].Module.[Module].Client.Oqtane.pdb" "..\..\[RootFolder]\Oqtane.Server\bin\Debug\net9.0\" /Y
|
||||||
XCOPY "..\Server\bin\Debug\net8.0\[Owner].Module.[Module].Server.Oqtane.dll" "..\..\[RootFolder]\Oqtane.Server\bin\Debug\net8.0\" /Y
|
XCOPY "..\Server\bin\Debug\net9.0\[Owner].Module.[Module].Server.Oqtane.dll" "..\..\[RootFolder]\Oqtane.Server\bin\Debug\net9.0\" /Y
|
||||||
XCOPY "..\Server\bin\Debug\net8.0\[Owner].Module.[Module].Server.Oqtane.pdb" "..\..\[RootFolder]\Oqtane.Server\bin\Debug\net8.0\" /Y
|
XCOPY "..\Server\bin\Debug\net9.0\[Owner].Module.[Module].Server.Oqtane.pdb" "..\..\[RootFolder]\Oqtane.Server\bin\Debug\net9.0\" /Y
|
||||||
XCOPY "..\Shared\bin\Debug\net8.0\[Owner].Module.[Module].Shared.Oqtane.dll" "..\..\[RootFolder]\Oqtane.Server\bin\Debug\net8.0\" /Y
|
XCOPY "..\Shared\bin\Debug\net9.0\[Owner].Module.[Module].Shared.Oqtane.dll" "..\..\[RootFolder]\Oqtane.Server\bin\Debug\net9.0\" /Y
|
||||||
XCOPY "..\Shared\bin\Debug\net8.0\[Owner].Module.[Module].Shared.Oqtane.pdb" "..\..\[RootFolder]\Oqtane.Server\bin\Debug\net8.0\" /Y
|
XCOPY "..\Shared\bin\Debug\net9.0\[Owner].Module.[Module].Shared.Oqtane.pdb" "..\..\[RootFolder]\Oqtane.Server\bin\Debug\net9.0\" /Y
|
||||||
XCOPY "..\Server\wwwroot\*" "..\..\[RootFolder]\Oqtane.Server\wwwroot\" /Y /S /I
|
XCOPY "..\Server\wwwroot\*" "..\..\[RootFolder]\Oqtane.Server\wwwroot\" /Y /S /I
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
cp -f "../Client/bin/Debug/net8.0/[Owner].Module.[Module].Client.Oqtane.dll" "../../oqtane.framework/Oqtane.Server/bin/Debug/net8.0/"
|
cp -f "../Client/bin/Debug/net9.0/[Owner].Module.[Module].Client.Oqtane.dll" "../../oqtane.framework/Oqtane.Server/bin/Debug/net9.0/"
|
||||||
cp -f "../Client/bin/Debug/net8.0/[Owner].Module.[Module].Client.Oqtane.pdb" "../../oqtane.framework/Oqtane.Server/bin/Debug/net8.0/"
|
cp -f "../Client/bin/Debug/net9.0/[Owner].Module.[Module].Client.Oqtane.pdb" "../../oqtane.framework/Oqtane.Server/bin/Debug/net9.0/"
|
||||||
cp -f "../Server/bin/Debug/net8.0/[Owner].Module.[Module].Server.Oqtane.dll" "../../oqtane.framework/Oqtane.Server/bin/Debug/net8.0/"
|
cp -f "../Server/bin/Debug/net9.0/[Owner].Module.[Module].Server.Oqtane.dll" "../../oqtane.framework/Oqtane.Server/bin/Debug/net9.0/"
|
||||||
cp -f "../Server/bin/Debug/net8.0/[Owner].Module.[Module].Server.Oqtane.pdb" "../../oqtane.framework/Oqtane.Server/bin/Debug/net8.0/"
|
cp -f "../Server/bin/Debug/net9.0/[Owner].Module.[Module].Server.Oqtane.pdb" "../../oqtane.framework/Oqtane.Server/bin/Debug/net9.0/"
|
||||||
cp -f "../Shared/bin/Debug/net8.0/[Owner].Module.[Module].Shared.Oqtane.dll" "../../oqtane.framework/Oqtane.Server/bin/Debug/net8.0/"
|
cp -f "../Shared/bin/Debug/net9.0/[Owner].Module.[Module].Shared.Oqtane.dll" "../../oqtane.framework/Oqtane.Server/bin/Debug/net9.0/"
|
||||||
cp -f "../Shared/bin/Debug/net8.0/[Owner].Module.[Module].Shared.Oqtane.pdb" "../../oqtane.framework/Oqtane.Server/bin/Debug/net8.0/"
|
cp -f "../Shared/bin/Debug/net9.0/[Owner].Module.[Module].Shared.Oqtane.pdb" "../../oqtane.framework/Oqtane.Server/bin/Debug/net9.0/"
|
||||||
cp -rf "../Server/wwwroot/"* "../../oqtane.framework/Oqtane.Server/wwwroot/"
|
cp -rf "../Server/wwwroot/"* "../../oqtane.framework/Oqtane.Server/wwwroot/"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk.Razor">
|
<Project Sdk="Microsoft.NET.Sdk.Razor">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
<AddRazorSupportForMvc>true</AddRazorSupportForMvc>
|
<AddRazorSupportForMvc>true</AddRazorSupportForMvc>
|
||||||
<Version>1.0.0</Version>
|
<Version>1.0.0</Version>
|
||||||
<Product>[Owner].Module.[Module]</Product>
|
<Product>[Owner].Module.[Module]</Product>
|
||||||
@ -19,10 +19,10 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="8.0.8" />
|
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="9.0.0" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.8" />
|
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="9.0.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="8.0.8" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="8.0.8" />
|
<PackageReference Include="Microsoft.Extensions.Localization" Version="9.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
<Version>1.0.0</Version>
|
<Version>1.0.0</Version>
|
||||||
<Product>[Owner].Module.[Module]</Product>
|
<Product>[Owner].Module.[Module]</Product>
|
||||||
<Authors>[Owner]</Authors>
|
<Authors>[Owner]</Authors>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk.Razor">
|
<Project Sdk="Microsoft.NET.Sdk.Razor">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
<Version>1.0.0</Version>
|
<Version>1.0.0</Version>
|
||||||
<Authors>[Owner]</Authors>
|
<Authors>[Owner]</Authors>
|
||||||
<Company>[Owner]</Company>
|
<Company>[Owner]</Company>
|
||||||
@ -13,9 +13,9 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="8.0.8" />
|
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="9.0.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="8.0.8" />
|
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="9.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="8.0.8" />
|
<PackageReference Include="Microsoft.Extensions.Localization" Version="9.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
|
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
|
||||||
<AccelerateBuildsInVisualStudio>false</AccelerateBuildsInVisualStudio>
|
<AccelerateBuildsInVisualStudio>false</AccelerateBuildsInVisualStudio>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
@ -20,8 +20,8 @@
|
|||||||
</dependencies>
|
</dependencies>
|
||||||
</metadata>
|
</metadata>
|
||||||
<files>
|
<files>
|
||||||
<file src="..\Client\bin\Release\net8.0\[Owner].Theme.[Theme].Client.Oqtane.dll" target="lib\net8.0" />
|
<file src="..\Client\bin\Release\net9.0\[Owner].Theme.[Theme].Client.Oqtane.dll" target="lib\net9.0" />
|
||||||
<file src="..\Client\bin\Release\net8.0\[Owner].Theme.[Theme].Client.Oqtane.pdb" target="lib\net8.0" />
|
<file src="..\Client\bin\Release\net9.0\[Owner].Theme.[Theme].Client.Oqtane.pdb" target="lib\net9.0" />
|
||||||
<file src="..\Client\wwwroot\**\*.*" target="wwwroot" />
|
<file src="..\Client\wwwroot\**\*.*" target="wwwroot" />
|
||||||
<file src="icon.png" target="" />
|
<file src="icon.png" target="" />
|
||||||
</files>
|
</files>
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
XCOPY "..\Client\bin\Debug\net8.0\[Owner].Theme.[Theme].Client.Oqtane.dll" "..\..\[RootFolder]\Oqtane.Server\bin\Debug\net8.0\" /Y
|
XCOPY "..\Client\bin\Debug\net9.0\[Owner].Theme.[Theme].Client.Oqtane.dll" "..\..\[RootFolder]\Oqtane.Server\bin\Debug\net9.0\" /Y
|
||||||
XCOPY "..\Client\bin\Debug\net8.0\[Owner].Theme.[Theme].Client.Oqtane.pdb" "..\..\[RootFolder]\Oqtane.Server\bin\Debug\net8.0\" /Y
|
XCOPY "..\Client\bin\Debug\net9.0\[Owner].Theme.[Theme].Client.Oqtane.pdb" "..\..\[RootFolder]\Oqtane.Server\bin\Debug\net9.0\" /Y
|
||||||
XCOPY "..\Client\wwwroot\*" "..\..\[RootFolder]\Oqtane.Server\wwwroot\" /Y /S /I
|
XCOPY "..\Client\wwwroot\*" "..\..\[RootFolder]\Oqtane.Server\wwwroot\" /Y /S /I
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
cp -f "../Client/bin/Debug/net8.0/[Owner].Theme.[Theme].Client.Oqtane.dll" "../../oqtane.framework/Oqtane.Server/bin/Debug/net8.0/"
|
cp -f "../Client/bin/Debug/net9.0/[Owner].Theme.[Theme].Client.Oqtane.dll" "../../oqtane.framework/Oqtane.Server/bin/Debug/net9.0/"
|
||||||
cp -f "../Client/bin/Debug/net8.0/[Owner].Theme.[Theme].Client.Oqtane.pdb" "../../oqtane.framework/Oqtane.Server/bin/Debug/net8.0/"
|
cp -f "../Client/bin/Debug/net9.0/[Owner].Theme.[Theme].Client.Oqtane.pdb" "../../oqtane.framework/Oqtane.Server/bin/Debug/net9.0/"
|
||||||
cp -rf "../Server/wwwroot/"* "../../oqtane.framework/Oqtane.Server/wwwroot/"
|
cp -rf "../Server/wwwroot/"* "../../oqtane.framework/Oqtane.Server/wwwroot/"
|
||||||
|
@ -1,11 +1,18 @@
|
|||||||
var Oqtane = Oqtane || {};
|
var Oqtane = Oqtane || {};
|
||||||
|
|
||||||
Oqtane.Interop = {
|
Oqtane.Interop = {
|
||||||
setCookie: function (name, value, days) {
|
setCookie: function (name, value, days, secure, sameSite) {
|
||||||
var d = new Date();
|
var d = new Date();
|
||||||
d.setTime(d.getTime() + (days * 24 * 60 * 60 * 1000));
|
d.setTime(d.getTime() + (days * 24 * 60 * 60 * 1000));
|
||||||
var expires = "expires=" + d.toUTCString();
|
var expires = "expires=" + d.toUTCString();
|
||||||
document.cookie = name + "=" + value + ";" + expires + ";path=/";
|
var cookieString = name + "=" + value + ";" + expires + ";path=/";
|
||||||
|
if (secure) {
|
||||||
|
cookieString += "; secure";
|
||||||
|
}
|
||||||
|
if (sameSite === "Lax" || sameSite === "Strict" || sameSite === "None") {
|
||||||
|
cookieString += "; SameSite=" + sameSite;
|
||||||
|
}
|
||||||
|
document.cookie = cookieString;
|
||||||
},
|
},
|
||||||
getCookie: function (name) {
|
getCookie: function (name) {
|
||||||
name = name + "=";
|
name = name + "=";
|
||||||
@ -410,11 +417,20 @@ Oqtane.Interop = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
scrollTo: function (top, left, behavior) {
|
scrollTo: function (top, left, behavior) {
|
||||||
|
const modal = document.querySelector('.modal');
|
||||||
|
if (modal) {
|
||||||
|
modal.scrollTo({
|
||||||
|
top: top,
|
||||||
|
left: left,
|
||||||
|
behavior: behavior
|
||||||
|
});
|
||||||
|
} else {
|
||||||
window.scrollTo({
|
window.scrollTo({
|
||||||
top: top,
|
top: top,
|
||||||
left: left,
|
left: left,
|
||||||
behavior: behavior
|
behavior: behavior
|
||||||
});
|
});
|
||||||
|
}
|
||||||
},
|
},
|
||||||
scrollToId: function (id) {
|
scrollToId: function (id) {
|
||||||
var element = document.getElementById(id);
|
var element = document.getElementById(id);
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user