Merge remote-tracking branch 'upstream/dev' into dev

This commit is contained in:
Leigh Pointer
2025-07-30 12:33:50 +02:00
26 changed files with 326 additions and 54 deletions

View File

@@ -53,6 +53,7 @@ namespace Microsoft.Extensions.DependencyInjection
services.AddScoped<ISyncService, SyncService>();
services.AddScoped<ILocalizationCookieService, LocalizationCookieService>();
services.AddScoped<ICookieConsentService, CookieConsentService>();
services.AddScoped<ITimeZoneService, TimeZoneService>();
services.AddScoped<IOutputCacheService, OutputCacheService>();
// providers

View File

@@ -9,6 +9,7 @@
@inject INotificationService NotificationService
@inject IFileService FileService
@inject IFolderService FolderService
@inject ITimeZoneService TimeZoneService
@inject IJSRuntime jsRuntime
@inject IServiceProvider ServiceProvider
@inject IStringLocalizer<Index> Localizer
@@ -366,7 +367,6 @@
}
@code {
private List<Models.TimeZone> _timezones;
private bool _initialized = false;
private string _passwordrequirements;
private string _username = string.Empty;
@@ -380,6 +380,7 @@
private string _displayname = string.Empty;
private FileManager _filemanager;
private int _folderid = -1;
private List<Models.TimeZone> _timezones;
private string _timezoneid = string.Empty;
private int _photofileid = -1;
private File _photo = null;
@@ -403,7 +404,7 @@
_togglepassword = SharedLocalizer["ShowPassword"];
_allowtwofactor = (SettingService.GetSetting(PageState.Site.Settings, "LoginOptions:TwoFactor", "false") == "true");
_profiles = await ProfileService.GetProfilesAsync(ModuleState.SiteId);
_timezones = Utilities.GetTimeZones();
_timezones = TimeZoneService.GetTimeZones();
if (PageState.User != null)
{

View File

@@ -0,0 +1,129 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Universal" xml:space="preserve">
<value>(UTC) Coordinated Universal Time</value>
</data>
<data name="US/Eastern" xml:space="preserve">
<value>(UTC-05:00) Eastern Time (US &amp; Canada)</value>
</data>
<data name="US/Pacific" xml:space="preserve">
<value>(UTC-08:00) Pacific Time (US &amp; Canada)</value>
</data>
</root>

View File

@@ -0,0 +1,17 @@
using System.Collections.Generic;
using Oqtane.Models;
namespace Oqtane.Services
{
/// <summary>
/// Service to retrieve <see cref="TimeZone"/> entries
/// </summary>
public interface ITimeZoneService
{
/// <summary>
/// Get the list of time zones
/// </summary>
/// <returns></returns>
List<TimeZone> GetTimeZones();
}
}

View File

@@ -0,0 +1,34 @@
using System.Collections.Generic;
using System.Linq;
using Microsoft.Extensions.Localization;
using Oqtane.Documentation;
using Oqtane.Models;
using Oqtane.Shared;
namespace Oqtane.Services
{
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
public class TimeZoneService : ITimeZoneService
{
private readonly IStringLocalizer<TimeZoneResources> _TimeZoneLocalizer;
public TimeZoneService(IStringLocalizer<TimeZoneResources> TimeZoneLocalizer)
{
_TimeZoneLocalizer = TimeZoneLocalizer;
}
public List<TimeZone> GetTimeZones()
{
var _timezones = new List<TimeZone>();
foreach (var timezone in Utilities.GetTimeZones())
{
_timezones.Add(new TimeZone
{
Id = timezone.Id,
DisplayName = _TimeZoneLocalizer[timezone.Id]
});
}
return _timezones.OrderBy(item => item.DisplayName).ToList();
}
}
}

View File

@@ -0,0 +1,14 @@
namespace Oqtane
{
/// <summary>
/// Dummy class used to collect shared resource strings for this application
/// </summary>
/// <remarks>
/// This class is mostly used with IStringLocalizer and IHtmlLocalizer interfaces.
/// The class must reside at the project root.
/// </remarks>
public class TimeZoneResources
{
}
}

View File

@@ -75,13 +75,9 @@ namespace Oqtane.Database.MySQL
return dr;
}
public override string RewriteName(string name, bool isQuery)
public override string DelimitName(string name)
{
if (name.ToLower() == "rows" && isQuery)
{
name = $"`{name}`"; // escape reserved word in SQL query
}
return name;
return $"`{name}`";
}
public override DbContextOptionsBuilder UseDatabase(DbContextOptionsBuilder optionsBuilder, string connectionString)

View File

@@ -87,9 +87,9 @@ namespace Oqtane.Database.PostgreSQL
return _rewriter.RewriteName(name);
}
public override string RewriteName(string name, bool isQuery)
public override string DelimitName(string name)
{
return _rewriter.RewriteName(name);
return $"\"{name}\"";
}
public override string RewriteValue(string value, string type)

View File

@@ -46,6 +46,11 @@ namespace Oqtane.Database.SqlServer
}
}
public override string DelimitName(string name)
{
return $"[{name}]";
}
public override int ExecuteNonQuery(string connectionString, string query)
{
var conn = new SqlConnection(FormatConnectionString(connectionString));

View File

@@ -84,6 +84,11 @@ namespace Oqtane.Database.Sqlite
return dr;
}
public override string DelimitName(string name)
{
return $"\"{name}\"";
}
public override DbContextOptionsBuilder UseDatabase(DbContextOptionsBuilder optionsBuilder, string connectionString)
{
return optionsBuilder.UseSqlite(connectionString)

View File

@@ -61,12 +61,12 @@ namespace Oqtane.Databases
public abstract IDataReader ExecuteReader(string connectionString, string query);
public virtual string RewriteName(string name)
public virtual string DelimitName(string name)
{
return name;
}
public virtual string RewriteName(string name, bool isQuery)
public virtual string RewriteName(string name)
{
return name;
}

View File

@@ -26,9 +26,9 @@ namespace Oqtane.Databases.Interfaces
public IDataReader ExecuteReader(string connectionString, string query);
public string RewriteName(string name);
public string DelimitName(string name); // only used in conjunction with method using MigrationBuilder.Sql()
public string RewriteName(string name, bool isQuery);
public string RewriteName(string name);
public string RewriteValue(string value, string type);

View File

@@ -104,6 +104,7 @@ namespace Microsoft.Extensions.DependencyInjection
services.AddScoped<ISearchProvider, DatabaseSearchProvider>();
services.AddScoped<IImageService, ImageService>();
services.AddScoped<ICookieConsentService, ServerCookieConsentService>();
services.AddScoped<ITimeZoneService, TimeZoneService>();
// providers
services.AddScoped<ITextEditor, Oqtane.Modules.Controls.QuillJSTextEditor>();

View File

@@ -738,7 +738,7 @@ namespace Oqtane.Infrastructure
databases += "{ \"Name\": \"LocalDB\", \"ControlType\": \"Oqtane.Installer.Controls.LocalDBConfig, Oqtane.Client\", \"DBTYpe\": \"Oqtane.Database.SqlServer.SqlServerDatabase, Oqtane.Database.SqlServer\" },";
databases += "{ \"Name\": \"SQL Server\", \"ControlType\": \"Oqtane.Installer.Controls.SqlServerConfig, Oqtane.Client\", \"DBTYpe\": \"Oqtane.Database.SqlServer.SqlServerDatabase, Oqtane.Database.SqlServer\" },";
databases += "{ \"Name\": \"SQLite\", \"ControlType\": \"Oqtane.Installer.Controls.SqliteConfig, Oqtane.Client\", \"DBTYpe\": \"Oqtane.Database.Sqlite.SqliteDatabase, Oqtane.Database.Sqlite\" },";
databases += "{ \"Name\": \"MySQL\", \"ControlType\": \"Oqtane.Installer.Controls.MySQLConfig, Oqtane.Client\", \"DBTYpe\": \"Oqtane.Database.MySQL.SqlServerDatabase, Oqtane.Database.MySQL\" },";
databases += "{ \"Name\": \"MySQL\", \"ControlType\": \"Oqtane.Installer.Controls.MySQLConfig, Oqtane.Client\", \"DBTYpe\": \"Oqtane.Database.MySQL.MySQLDatabase, Oqtane.Database.MySQL\" },";
databases += "{ \"Name\": \"PostgreSQL\", \"ControlType\": \"Oqtane.Installer.Controls.PostgreSQLConfig, Oqtane.Client\", \"DBTYpe\": \"Oqtane.Database.PostgreSQL.PostgreSQLDatabase, Oqtane.Database.PostgreSQL\" }";
databases += "]";
_configManager.AddOrUpdateSetting(SettingKeys.AvailableDatabasesSection, databases, true);

View File

@@ -33,28 +33,28 @@ namespace Oqtane.Migrations.EntityBuilders
protected string Schema { get; init; }
private string RewriteSqlEntityTableName(string name)
private string AddSchema(string name)
{
if (Schema == null)
if (string.IsNullOrEmpty(Schema))
{
return RewriteName(name);
return name;
}
else
{
return $"{Schema}.{RewriteName(name)}";
return $"{Schema}.{name}";
}
}
private string DelimitName(string name)
{
return ActiveDatabase.DelimitName(name);
}
private string RewriteName(string name)
{
return ActiveDatabase.RewriteName(name);
}
private string RewriteName(string name, bool isQuery)
{
return ActiveDatabase.RewriteName(name, isQuery);
}
private string RewriteValue(string value, string type)
{
return ActiveDatabase.RewriteValue(value, type);
@@ -468,9 +468,10 @@ namespace Oqtane.Migrations.EntityBuilders
public void DeleteFromTable(string condition = "")
{
var deleteSql = $"DELETE FROM {RewriteSqlEntityTableName(EntityTableName)} ";
var deleteSql = $"DELETE FROM {AddSchema(DelimitName(RewriteName(EntityTableName)))} ";
if(!string.IsNullOrEmpty(condition))
{
// note that condition values must be created using RewriteName(), DelimitName(), RewriteValue() if targeting multiple database platforms
deleteSql += $"WHERE {condition}";
}
_migrationBuilder.Sql(deleteSql);
@@ -488,9 +489,10 @@ namespace Oqtane.Migrations.EntityBuilders
public void UpdateColumn(string columnName, string value, string type, string condition)
{
var updateSql = $"UPDATE {RewriteSqlEntityTableName(EntityTableName)} SET {RewriteName(columnName, true)} = {RewriteValue(value, type)} ";
var updateSql = $"UPDATE {AddSchema(DelimitName(RewriteName(EntityTableName)))} SET {DelimitName(RewriteName(columnName))} = {RewriteValue(value, type)} ";
if (!string.IsNullOrEmpty(condition))
{
// note that condition values must be created using RewriteName(), DelimitName(), RewriteValue() if targeting multiple database platforms
updateSql += $"WHERE {condition}";
}
_migrationBuilder.Sql(updateSql);

View File

@@ -12,14 +12,19 @@ namespace Oqtane.Migrations
protected IDatabase ActiveDatabase { get; }
protected string RewriteName(string name)
protected string DelimitName(string name)
{
return ActiveDatabase.RewriteName(name, false);
return ActiveDatabase.DelimitName(name);
}
protected string RewriteName(string name, bool isQuery)
protected string RewriteName(string name)
{
return ActiveDatabase.RewriteName(name, isQuery);
return ActiveDatabase.RewriteName(name);
}
protected string RewriteValue(string value, string type)
{
return ActiveDatabase.RewriteValue(value, type);
}
}
}

View File

@@ -21,7 +21,7 @@ namespace Oqtane.Migrations.Tenant
notificationEntityBuilder.AddDateTimeColumn("SendOn", true);
//Update new Column
notificationEntityBuilder.UpdateColumn("SendOn", $"{ActiveDatabase.RewriteName("CreatedOn")}", $"{ActiveDatabase.RewriteName("SendOn")} IS NULL");
notificationEntityBuilder.UpdateColumn("SendOn", $"{RewriteName("CreatedOn")}", $"{DelimitName(RewriteName("SendOn"))} IS NULL");
}
protected override void Down(MigrationBuilder migrationBuilder)

View File

@@ -18,8 +18,8 @@ namespace Oqtane.Migrations.Tenant
{
///Update Icon Field in Page
var pageEntityBuilder = new PageEntityBuilder(migrationBuilder, ActiveDatabase);
var updateSql = ActiveDatabase.ConcatenateSql("'oi oi-'", $"{ActiveDatabase.RewriteName("Icon")}");
pageEntityBuilder.UpdateColumn("Icon", updateSql, $"{ActiveDatabase.RewriteName("Icon")} <> ''" );
var updateSql = ActiveDatabase.ConcatenateSql("'oi oi-'", $"{DelimitName(RewriteName("Icon"))}");
pageEntityBuilder.UpdateColumn("Icon", updateSql, $"{DelimitName(RewriteName("Icon"))} <> ''" );
}
}
}

View File

@@ -20,18 +20,18 @@ namespace Oqtane.Migrations.Tenant
{
//Update DefaultContainerType In Site
var siteEntityBuilder = new SiteEntityBuilder(migrationBuilder, ActiveDatabase);
siteEntityBuilder.UpdateColumn("DefaultContainerType", "'Oqtane.Themes.OqtaneTheme.DefaultTitle, Oqtane.Client'", "DefaultContainerType = 'Oqtane.Themes.OqtaneTheme.Container, Oqtane.Client'");
siteEntityBuilder.UpdateColumn("DefaultContainerType", "'Oqtane.Themes.OqtaneTheme.DefaultNoTitle, Oqtane.Client'", "DefaultContainerType = 'Oqtane.Themes.OqtaneTheme.NoTitle, Oqtane.Client'");
siteEntityBuilder.UpdateColumn("DefaultContainerType", "'Oqtane.Themes.OqtaneTheme.DefaultTitle, Oqtane.Client'", $"{DelimitName(RewriteName("DefaultContainerType"))} = 'Oqtane.Themes.OqtaneTheme.Container, Oqtane.Client'");
siteEntityBuilder.UpdateColumn("DefaultContainerType", "'Oqtane.Themes.OqtaneTheme.DefaultNoTitle, Oqtane.Client'", $"{DelimitName(RewriteName("DefaultContainerType"))} = 'Oqtane.Themes.OqtaneTheme.NoTitle, Oqtane.Client'");
//Update DefaultContainerType in Page
var pageEntityBuilder = new PageEntityBuilder(migrationBuilder, ActiveDatabase);
pageEntityBuilder.UpdateColumn("DefaultContainerType", "'Oqtane.Themes.OqtaneTheme.DefaultTitle, Oqtane.Client'", "DefaultContainerType = 'Oqtane.Themes.OqtaneTheme.Container, Oqtane.Client'");
pageEntityBuilder.UpdateColumn("DefaultContainerType", "'Oqtane.Themes.OqtaneTheme.DefaultNoTitle, Oqtane.Client'", "DefaultContainerType = 'Oqtane.Themes.OqtaneTheme.NoTitle, Oqtane.Client'");
pageEntityBuilder.UpdateColumn("DefaultContainerType", "'Oqtane.Themes.OqtaneTheme.DefaultTitle, Oqtane.Client'", $"{DelimitName(RewriteName("DefaultContainerType"))} = 'Oqtane.Themes.OqtaneTheme.Container, Oqtane.Client'");
pageEntityBuilder.UpdateColumn("DefaultContainerType", "'Oqtane.Themes.OqtaneTheme.DefaultNoTitle, Oqtane.Client'", $"{DelimitName(RewriteName("DefaultContainerType"))} = 'Oqtane.Themes.OqtaneTheme.NoTitle, Oqtane.Client'");
//Update ContainerType in PageModule
var pageModuleEntityBuilder = new PageModuleEntityBuilder(migrationBuilder, ActiveDatabase);
pageModuleEntityBuilder.UpdateColumn("ContainerType", "'Oqtane.Themes.OqtaneTheme.DefaultTitle, Oqtane.Client'", "ContainerType = 'Oqtane.Themes.OqtaneTheme.Container, Oqtane.Client'");
pageModuleEntityBuilder.UpdateColumn("ContainerType", "'Oqtane.Themes.OqtaneTheme.DefaultNoTitle, Oqtane.Client'", "ContainerType = 'Oqtane.Themes.OqtaneTheme.NoTitle, Oqtane.Client'");
pageModuleEntityBuilder.UpdateColumn("ContainerType", "'Oqtane.Themes.OqtaneTheme.DefaultTitle, Oqtane.Client'", $"{DelimitName(RewriteName("ContainerType"))} = 'Oqtane.Themes.OqtaneTheme.Container, Oqtane.Client'");
pageModuleEntityBuilder.UpdateColumn("ContainerType", "'Oqtane.Themes.OqtaneTheme.DefaultNoTitle, Oqtane.Client'", $"{DelimitName(RewriteName("ContainerType"))} = 'Oqtane.Themes.OqtaneTheme.NoTitle, Oqtane.Client'");
}
}

View File

@@ -29,22 +29,22 @@ namespace Oqtane.Migrations.Tenant
siteEntityBuilder.DropColumn("DefaultLayoutType");
//Update DefaultContainerType In Site
siteEntityBuilder.UpdateColumn("DefaultContainerType", "'Oqtane.Themes.OqtaneTheme.Container, Oqtane.Client'", "DefaultContainerType = 'Oqtane.Themes.OqtaneTheme.DefaultTitle, Oqtane.Client'");
siteEntityBuilder.UpdateColumn("DefaultContainerType", "'Oqtane.Themes.OqtaneTheme.Container, Oqtane.Client'", "DefaultContainerType = 'Oqtane.Themes.OqtaneTheme.DefaultNoTitle, Oqtane.Client'");
siteEntityBuilder.UpdateColumn("DefaultContainerType", "'Oqtane.Themes.OqtaneTheme.Container, Oqtane.Client'", $"{DelimitName(RewriteName("DefaultContainerType"))} = 'Oqtane.Themes.OqtaneTheme.DefaultTitle, Oqtane.Client'");
siteEntityBuilder.UpdateColumn("DefaultContainerType", "'Oqtane.Themes.OqtaneTheme.Container, Oqtane.Client'", $"{DelimitName(RewriteName("DefaultContainerType"))} = 'Oqtane.Themes.OqtaneTheme.DefaultNoTitle, Oqtane.Client'");
//Drop Column from Page Table
var pageEntityBuilder = new PageEntityBuilder(migrationBuilder, ActiveDatabase);
pageEntityBuilder.DropColumn("LayoutType");
//Update DefaultContainerType in Page
pageEntityBuilder.UpdateColumn("DefaultContainerType", "'Oqtane.Themes.OqtaneTheme.Container, Oqtane.Client'", "DefaultContainerType = 'Oqtane.Themes.OqtaneTheme.DefaultTitle, Oqtane.Client'");
pageEntityBuilder.UpdateColumn("DefaultContainerType", "'Oqtane.Themes.OqtaneTheme.Container, Oqtane.Client'", "DefaultContainerType = 'Oqtane.Themes.OqtaneTheme.DefaultNoTitle, Oqtane.Client'");
pageEntityBuilder.UpdateColumn("DefaultContainerType", "'Oqtane.Themes.OqtaneTheme.Container, Oqtane.Client'", $"{DelimitName(RewriteName("DefaultContainerType"))} = 'Oqtane.Themes.OqtaneTheme.DefaultTitle, Oqtane.Client'");
pageEntityBuilder.UpdateColumn("DefaultContainerType", "'Oqtane.Themes.OqtaneTheme.Container, Oqtane.Client'", $"{DelimitName(RewriteName("DefaultContainerType"))} = 'Oqtane.Themes.OqtaneTheme.DefaultNoTitle, Oqtane.Client'");
//Update ContainerType in PageModule
var pageModuleEntityBuilder = new PageModuleEntityBuilder(migrationBuilder, ActiveDatabase);
pageModuleEntityBuilder.UpdateColumn("ContainerType", "'Oqtane.Themes.OqtaneTheme.Container, Oqtane.Client'", "ContainerType = 'Oqtane.Themes.OqtaneTheme.DefaultTitle, Oqtane.Client'");
pageModuleEntityBuilder.UpdateColumn("ContainerType", "'Oqtane.Themes.OqtaneTheme.Container, Oqtane.Client'", "ContainerType = 'Oqtane.Themes.OqtaneTheme.DefaultNoTitle, Oqtane.Client'");
pageModuleEntityBuilder.UpdateColumn("ContainerType", "'Oqtane.Themes.OqtaneTheme.Container, Oqtane.Client'", $"{DelimitName(RewriteName("ContainerType"))} = 'Oqtane.Themes.OqtaneTheme.DefaultTitle, Oqtane.Client'");
pageModuleEntityBuilder.UpdateColumn("ContainerType", "'Oqtane.Themes.OqtaneTheme.Container, Oqtane.Client'", $"{DelimitName(RewriteName("ContainerType"))} = 'Oqtane.Themes.OqtaneTheme.DefaultNoTitle, Oqtane.Client'");
}
}

View File

@@ -20,7 +20,7 @@ namespace Oqtane.Migrations.Tenant
var folderEntityBuilder = new FolderEntityBuilder(migrationBuilder, ActiveDatabase);
folderEntityBuilder.AddIntegerColumn("Capacity", true);
folderEntityBuilder.UpdateColumn("Capacity", "0");
folderEntityBuilder.UpdateColumn("Capacity", Constants.UserFolderCapacity.ToString(), $"{ActiveDatabase.RewriteName("Name")} = 'My Folder'");
folderEntityBuilder.UpdateColumn("Capacity", Constants.UserFolderCapacity.ToString(), $"{DelimitName(RewriteName("Name"))} = 'My Folder'");
folderEntityBuilder.AddStringColumn("ImageSizes", 512, true, true);
var fileEntityBuilder = new FileEntityBuilder(migrationBuilder, ActiveDatabase);

View File

@@ -18,13 +18,13 @@ namespace Oqtane.Migrations.Tenant
protected override void Up(MigrationBuilder migrationBuilder)
{
var settingEntityBuilder = new SettingEntityBuilder(migrationBuilder, ActiveDatabase);
settingEntityBuilder.UpdateColumn("IsPublic", "1", "bool", $"{RewriteName("SettingName")} NOT LIKE 'SMTP%'");
settingEntityBuilder.UpdateColumn("IsPublic", "1", "bool", $"{DelimitName(RewriteName("SettingName"))} NOT LIKE 'SMTP%'");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
var settingEntityBuilder = new SettingEntityBuilder(migrationBuilder, ActiveDatabase);
settingEntityBuilder.UpdateColumn("IsPublic", "0", "bool", $"{RewriteName("SettingName")} NOT LIKE 'SMTP%'");
settingEntityBuilder.UpdateColumn("IsPublic", "0", "bool", $"{DelimitName(RewriteName("SettingName"))} NOT LIKE 'SMTP%'");
}
}
}

View File

@@ -20,7 +20,7 @@ namespace Oqtane.Migrations.Tenant
var settingEntityBuilder = new SettingEntityBuilder(migrationBuilder, ActiveDatabase);
settingEntityBuilder.AddBooleanColumn("IsPrivate", true);
settingEntityBuilder.UpdateColumn("IsPrivate", "0", "bool", "");
settingEntityBuilder.UpdateColumn("IsPrivate", "1", "bool", $"{RewriteName("EntityName")} = 'Site' AND { RewriteName("SettingName")} LIKE 'SMTP%'");
settingEntityBuilder.UpdateColumn("IsPrivate", "1", "bool", $"{DelimitName(RewriteName("EntityName"))} = 'Site' AND { DelimitName(RewriteName("SettingName"))} LIKE 'SMTP%'");
settingEntityBuilder.DropColumn("IsPublic");
}

View File

@@ -0,0 +1,30 @@
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.06.01.04.01")]
public class RemoveUniqueEmailIndex : MultiDatabaseMigration
{
public RemoveUniqueEmailIndex(IDatabase database) : base(database)
{
}
protected override void Up(MigrationBuilder migrationBuilder)
{
// framework uses RequireUniqueEmail = False in .NET Identity configuration
var aspNetUsersEntityBuilder = new AspNetUsersEntityBuilder(migrationBuilder, ActiveDatabase);
aspNetUsersEntityBuilder.DropIndex("EmailIndex");
aspNetUsersEntityBuilder.AddIndex("EmailIndex", "NormalizedEmail", false);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
// not implemented
}
}
}

View File

@@ -0,0 +1,32 @@
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.06.01.04.02")]
public class ResetTimeZone : MultiDatabaseMigration
{
public ResetTimeZone(IDatabase database) : base(database)
{
}
protected override void Up(MigrationBuilder migrationBuilder)
{
// resetting value as framework now uses IANA ID consistently for time zones
var siteEntityBuilder = new SiteEntityBuilder(migrationBuilder, ActiveDatabase);
siteEntityBuilder.UpdateColumn("TimeZoneId", "''");
var userEntityBuilder = new UserEntityBuilder(migrationBuilder, ActiveDatabase);
userEntityBuilder.UpdateColumn("TimeZoneId", "''");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
// not implemented
}
}
}

View File

@@ -695,11 +695,11 @@ namespace Oqtane.Shared
public static List<TimeZone> GetTimeZones()
{
return [.. DateTimeZoneProviders.Tzdb.GetAllZones()
.Select(tz => new TimeZone()
{
Id = tz.Id,
DisplayName = tz.ToString()
})];
.Select(tz => new TimeZone()
{
Id = tz.Id,
DisplayName = tz.Id
})];
}
public static bool IsEffectiveAndNotExpired(DateTime? effectiveDate, DateTime? expiryDate)