Merge pull request #1239 from cnurse/dev
Implement Database Migrations and add Multi-Database Support
This commit is contained in:
commit
40f8436947
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -13,6 +13,7 @@ msbuild.binlog
|
||||||
Oqtane.Server/appsettings.json
|
Oqtane.Server/appsettings.json
|
||||||
Oqtane.Server/Data/*.mdf
|
Oqtane.Server/Data/*.mdf
|
||||||
Oqtane.Server/Data/*.ldf
|
Oqtane.Server/Data/*.ldf
|
||||||
|
Oqtane.Server/Data/*.db
|
||||||
|
|
||||||
/Oqtane.Server/Properties/PublishProfiles/FolderProfile.pubxml
|
/Oqtane.Server/Properties/PublishProfiles/FolderProfile.pubxml
|
||||||
Oqtane.Server/Content
|
Oqtane.Server/Content
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
@namespace Oqtane.Modules.Admin.Sites
|
@namespace Oqtane.Modules.Admin.Sites
|
||||||
|
@using Oqtane.Interfaces
|
||||||
@inherits ModuleBase
|
@inherits ModuleBase
|
||||||
@inject NavigationManager NavigationManager
|
@inject NavigationManager NavigationManager
|
||||||
@inject ITenantService TenantService
|
@inject ITenantService TenantService
|
||||||
|
@ -9,6 +10,7 @@
|
||||||
@inject IUserService UserService
|
@inject IUserService UserService
|
||||||
@inject IInstallationService InstallationService
|
@inject IInstallationService InstallationService
|
||||||
@inject IStringLocalizer<Add> Localizer
|
@inject IStringLocalizer<Add> Localizer
|
||||||
|
@inject IEnumerable<IOqtaneDatabase> Databases
|
||||||
|
|
||||||
@if (_tenants == null)
|
@if (_tenants == null)
|
||||||
{
|
{
|
||||||
|
@ -117,7 +119,7 @@ else
|
||||||
<Label For="name" HelpText="Enter the name for the tenant" ResourceKey="TenantName">Tenant Name: </Label>
|
<Label For="name" HelpText="Enter the name for the tenant" ResourceKey="TenantName">Tenant Name: </Label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<input id="name" class="form-control" @bind="@_tenantname" />
|
<input id="name" class="form-control" @bind="@_tenantName" />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -125,64 +127,67 @@ else
|
||||||
<Label For="databaseType" HelpText="Select the database type for the tenant" ResourceKey="DatabaseType">Database Type: </Label>
|
<Label For="databaseType" HelpText="Select the database type for the tenant" ResourceKey="DatabaseType">Database Type: </Label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<select id="databaseType" class="custom-select" @bind="@_databasetype">
|
<select id="databaseType" class="custom-select" @bind="@_databaseType">
|
||||||
<option value="LocalDB">@Localizer["Local Database"]</option>
|
@{
|
||||||
<option value="SQLServer">@Localizer["SQL Server"]</option>
|
foreach (var database in Databases)
|
||||||
|
{
|
||||||
|
<option value="@database.Name">@Localizer[@database.FriendlyName]</option>
|
||||||
|
}
|
||||||
|
}
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<Label For="server" HelpText="Enter the server for the tenant" ResourceKey="DatabaseServer">Server: </Label>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<input id="server" type="text" class="form-control" @bind="@_server" />
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<Label For="database" HelpText="Enter the database for the tenant" ResourceKey="Database">Database: </Label>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<input id="database" type="text" class="form-control" @bind="@_database" />
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<Label For="integratedSecurity" HelpText="Select if you want integrated security or not" ResourceKey="IntegratedSecurity">Integrated Security: </Label>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<select id="integratedSecurity" class="custom-select" @onchange="SetIntegratedSecurity">
|
|
||||||
<option value="true" selected>@Localizer["True"]</option>
|
|
||||||
<option value="false">@Localizer["False"]</option>
|
|
||||||
</select>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
@if (!_integratedsecurity)
|
|
||||||
{
|
{
|
||||||
<tr>
|
_selectedDatabase = Databases.Single(d => d.Name == _databaseType);
|
||||||
<td>
|
foreach (var field in _selectedDatabase.ConnectionStringFields)
|
||||||
<Label For="username" HelpText="Enter the username for the integrated security" ResourceKey="DatabaseUsername">Database Username: </Label>
|
{
|
||||||
</td>
|
var fieldId = field.Name.ToLowerInvariant();
|
||||||
<td>
|
if (field.Name != "IntegratedSecurity")
|
||||||
<input id="username" type="text" class="form-control" @bind="@_username" />
|
{
|
||||||
</td>
|
var isVisible = "";
|
||||||
</tr>
|
var fieldType = (field.Name == "Pwd") ? "password" : "text";
|
||||||
<tr>
|
if ((field.Name == "Uid" || field.Name == "Pwd") && _selectedDatabase.Name != "MySQL" )
|
||||||
<td>
|
{
|
||||||
<Label For="password" HelpText="Enter the password for the integrated security" ResourceKey="DatabasePassword">Database Password: </Label>
|
var intSecurityField = _selectedDatabase.ConnectionStringFields.Single(f => f.Name == "IntegratedSecurity");
|
||||||
</td>
|
if (intSecurityField != null)
|
||||||
<td>
|
{
|
||||||
<input id="password" type="password" class="form-control" @bind="@_password" />
|
isVisible = (Convert.ToBoolean(intSecurityField.Value)) ? "display: none;" : "";
|
||||||
</td>
|
}
|
||||||
</tr>
|
}
|
||||||
|
|
||||||
|
field.Value = field.Value.Replace("{{Date}}", DateTime.UtcNow.ToString("yyyyMMddHHmm"));
|
||||||
|
|
||||||
|
<tr style="@isVisible">
|
||||||
|
<td>
|
||||||
|
<Label For="@fieldId" HelpText="@field.HelpText" ResourceKey="@field.Name">@Localizer[$"{field.FriendlyName}:"]</Label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input id="@fieldId" type="@fieldType" class="form-control" @bind="@field.Value" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<Label For="@fieldId" HelpText="@field.HelpText" ResourceKey="@field.Name">@Localizer[$"{field.FriendlyName}:"]</Label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<select id="@fieldId" class="custom-select" @bind="@field.Value">
|
||||||
|
<option value="true" selected>@Localizer["True"]</option>
|
||||||
|
<option value="false">@Localizer["False"]</option>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<Label For="hostUsername" HelpText="Enter the username of the host for this site" ResourceKey="HostUsername">Host Username:</Label>
|
<Label For="hostUsername" HelpText="Enter the username of the host for this site" ResourceKey="HostUsername">Host Username:</Label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<input id="hostUsername" class="form-control" @bind="@_hostusername" readonly />
|
<input id="hostUsername" class="form-control" @bind="@_hostUserName" readonly />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -207,14 +212,11 @@ else
|
||||||
private List<Tenant> _tenants;
|
private List<Tenant> _tenants;
|
||||||
private string _tenantid = "-";
|
private string _tenantid = "-";
|
||||||
|
|
||||||
private string _tenantname = string.Empty;
|
private string _tenantName = string.Empty;
|
||||||
private string _databasetype = "LocalDB";
|
private IOqtaneDatabase _selectedDatabase;
|
||||||
private string _server = "(LocalDb)\\MSSQLLocalDB";
|
private string _databaseType = "LocalDB";
|
||||||
private string _database = "Oqtane-" + DateTime.UtcNow.ToString("yyyyMMddHHmm");
|
|
||||||
private string _username = string.Empty;
|
private string _hostUserName = UserNames.Host;
|
||||||
private string _password = string.Empty;
|
|
||||||
private bool _integratedsecurity = true;
|
|
||||||
private string _hostusername = UserNames.Host;
|
|
||||||
private string _hostpassword = string.Empty;
|
private string _hostpassword = string.Empty;
|
||||||
|
|
||||||
private string _name = string.Empty;
|
private string _name = string.Empty;
|
||||||
|
@ -238,22 +240,9 @@ else
|
||||||
private void TenantChanged(ChangeEventArgs e)
|
private void TenantChanged(ChangeEventArgs e)
|
||||||
{
|
{
|
||||||
_tenantid = (string)e.Value;
|
_tenantid = (string)e.Value;
|
||||||
if (string.IsNullOrEmpty(_tenantname))
|
if (string.IsNullOrEmpty(_tenantName))
|
||||||
{
|
{
|
||||||
_tenantname = _name;
|
_tenantName = _name;
|
||||||
}
|
|
||||||
StateHasChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SetIntegratedSecurity(ChangeEventArgs e)
|
|
||||||
{
|
|
||||||
if (Convert.ToBoolean((string)e.Value))
|
|
||||||
{
|
|
||||||
_integratedsecurity = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_integratedsecurity = false;
|
|
||||||
}
|
}
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
|
@ -302,7 +291,7 @@ else
|
||||||
|
|
||||||
if (_tenantid == "+")
|
if (_tenantid == "+")
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(_tenantname) && _tenants.FirstOrDefault(item => item.Name == _tenantname) == null)
|
if (!string.IsNullOrEmpty(_tenantName) && _tenants.FirstOrDefault(item => item.Name == _tenantName) == null)
|
||||||
{
|
{
|
||||||
// validate host credentials
|
// validate host credentials
|
||||||
var user = new User();
|
var user = new User();
|
||||||
|
@ -312,32 +301,15 @@ else
|
||||||
user = await UserService.LoginUserAsync(user, false, false);
|
user = await UserService.LoginUserAsync(user, false, false);
|
||||||
if (user.IsAuthenticated)
|
if (user.IsAuthenticated)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(_server) && !string.IsNullOrEmpty(_database))
|
var connectionString = _selectedDatabase.BuildConnectionString();
|
||||||
|
if (connectionString != "")
|
||||||
{
|
{
|
||||||
var connectionString = string.Empty;
|
config.DatabaseType = _databaseType;
|
||||||
if (_databasetype == "LocalDB")
|
|
||||||
{
|
|
||||||
connectionString = "Data Source=" + _server + ";AttachDbFilename=|DataDirectory|\\" + _database + ".mdf;Initial Catalog=" + _database + ";Integrated Security=SSPI;";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
connectionString = "Data Source=" + _server + ";Initial Catalog=" + _database + ";";
|
|
||||||
|
|
||||||
if (_integratedsecurity)
|
|
||||||
{
|
|
||||||
connectionString += "Integrated Security=SSPI;";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
connectionString += "User ID=" + _username + ";Password=" + _password;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
config.ConnectionString = connectionString;
|
config.ConnectionString = connectionString;
|
||||||
config.HostPassword = _hostpassword;
|
config.HostPassword = _hostpassword;
|
||||||
config.HostEmail = user.Email;
|
config.HostEmail = user.Email;
|
||||||
config.HostName = user.DisplayName;
|
config.HostName = user.DisplayName;
|
||||||
config.TenantName = _tenantname;
|
config.TenantName = _tenantName;
|
||||||
config.IsNewTenant = true;
|
config.IsNewTenant = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -84,7 +84,7 @@
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
htmltext = new HtmlTextInfo();
|
htmltext = new HtmlText();
|
||||||
htmltext.ModuleId = ModuleState.ModuleId;
|
htmltext.ModuleId = ModuleState.ModuleId;
|
||||||
htmltext.Content = content;
|
htmltext.Content = content;
|
||||||
await HtmlTextService.AddHtmlTextAsync(htmltext);
|
await HtmlTextService.AddHtmlTextAsync(htmltext);
|
||||||
|
|
|
@ -19,18 +19,18 @@ namespace Oqtane.Modules.HtmlText.Services
|
||||||
|
|
||||||
private string ApiUrl => CreateApiUrl(_siteState.Alias, "HtmlText");
|
private string ApiUrl => CreateApiUrl(_siteState.Alias, "HtmlText");
|
||||||
|
|
||||||
public async Task<HtmlTextInfo> GetHtmlTextAsync(int moduleId)
|
public async Task<Models.HtmlText> GetHtmlTextAsync(int moduleId)
|
||||||
{
|
{
|
||||||
var htmltext = await GetJsonAsync<List<HtmlTextInfo>>(CreateAuthorizationPolicyUrl($"{ApiUrl}/{moduleId}", moduleId));
|
var htmltext = await GetJsonAsync<List<Models.HtmlText>>(CreateAuthorizationPolicyUrl($"{ApiUrl}/{moduleId}", moduleId));
|
||||||
return htmltext.FirstOrDefault();
|
return htmltext.FirstOrDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task AddHtmlTextAsync(HtmlTextInfo htmlText)
|
public async Task AddHtmlTextAsync(Models.HtmlText htmlText)
|
||||||
{
|
{
|
||||||
await PostJsonAsync(CreateAuthorizationPolicyUrl($"{ApiUrl}", htmlText.ModuleId), htmlText);
|
await PostJsonAsync(CreateAuthorizationPolicyUrl($"{ApiUrl}", htmlText.ModuleId), htmlText);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task UpdateHtmlTextAsync(HtmlTextInfo htmlText)
|
public async Task UpdateHtmlTextAsync(Models.HtmlText htmlText)
|
||||||
{
|
{
|
||||||
await PutJsonAsync(CreateAuthorizationPolicyUrl($"{ApiUrl}/{htmlText.HtmlTextId}", htmlText.ModuleId), htmlText);
|
await PutJsonAsync(CreateAuthorizationPolicyUrl($"{ApiUrl}/{htmlText.HtmlTextId}", htmlText.ModuleId), htmlText);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,11 +6,11 @@ namespace Oqtane.Modules.HtmlText.Services
|
||||||
{
|
{
|
||||||
public interface IHtmlTextService
|
public interface IHtmlTextService
|
||||||
{
|
{
|
||||||
Task<HtmlTextInfo> GetHtmlTextAsync(int ModuleId);
|
Task<Models.HtmlText> GetHtmlTextAsync(int ModuleId);
|
||||||
|
|
||||||
Task AddHtmlTextAsync(HtmlTextInfo htmltext);
|
Task AddHtmlTextAsync(Models.HtmlText htmltext);
|
||||||
|
|
||||||
Task UpdateHtmlTextAsync(HtmlTextInfo htmltext);
|
Task UpdateHtmlTextAsync(Models.HtmlText htmltext);
|
||||||
|
|
||||||
Task DeleteHtmlTextAsync(int ModuleId);
|
Task DeleteHtmlTextAsync(int ModuleId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,11 +21,11 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="5.0.0" />
|
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="5.0.4" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="5.0.0" PrivateAssets="all" />
|
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="5.0.4" PrivateAssets="all" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="5.0.0" />
|
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="5.0.4" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Localization" Version="2.2.0" />
|
<PackageReference Include="Microsoft.AspNetCore.Localization" Version="2.2.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="5.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Localization" Version="5.0.4" />
|
||||||
<PackageReference Include="System.Net.Http.Json" Version="5.0.0" />
|
<PackageReference Include="System.Net.Http.Json" Version="5.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
|
||||||
using Microsoft.AspNetCore.Localization;
|
using Microsoft.AspNetCore.Localization;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.JSInterop;
|
using Microsoft.JSInterop;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
using Oqtane.Modules;
|
using Oqtane.Modules;
|
||||||
using Oqtane.Providers;
|
using Oqtane.Providers;
|
||||||
using Oqtane.Services;
|
using Oqtane.Services;
|
||||||
|
@ -85,6 +86,17 @@ namespace Oqtane.Client
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// dynamically register database providers
|
||||||
|
var databaseTypes = assembly.GetInterfaces<IOqtaneDatabase>();
|
||||||
|
foreach (var databaseType in databaseTypes)
|
||||||
|
{
|
||||||
|
if (databaseType.AssemblyQualifiedName != null)
|
||||||
|
{
|
||||||
|
var serviceType = Type.GetType("Oqtane.Interfaces.IDatabase, Oqtane.Shared");
|
||||||
|
builder.Services.AddScoped(serviceType ?? databaseType, databaseType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// register client startup services
|
// register client startup services
|
||||||
var startUps = assembly.GetInstances<IClientStartup>();
|
var startUps = assembly.GetInstances<IClientStartup>();
|
||||||
foreach (var startup in startUps)
|
foreach (var startup in startUps)
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
@using Oqtane.Interfaces
|
||||||
|
@using System.Reflection
|
||||||
@namespace Oqtane.UI
|
@namespace Oqtane.UI
|
||||||
@inject NavigationManager NavigationManager
|
@inject NavigationManager NavigationManager
|
||||||
@inject IInstallationService InstallationService
|
@inject IInstallationService InstallationService
|
||||||
|
@ -5,6 +7,7 @@
|
||||||
@inject IUserService UserService
|
@inject IUserService UserService
|
||||||
@inject IJSRuntime JSRuntime
|
@inject IJSRuntime JSRuntime
|
||||||
@inject IStringLocalizer<Installer> Localizer
|
@inject IStringLocalizer<Installer> Localizer
|
||||||
|
@inject IEnumerable<IOqtaneDatabase> Databases
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
@ -25,54 +28,59 @@
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<select class="custom-select" @bind="@_databaseType">
|
<select class="custom-select" @bind="@_databaseType">
|
||||||
<option value="LocalDB">@Localizer["Local Database"]</option>
|
@{
|
||||||
<option value="SQLServer">@Localizer["SQL Server"]</option>
|
foreach (var database in Databases)
|
||||||
|
{
|
||||||
|
<option value="@database.Name">@Localizer[@database.FriendlyName]</option>
|
||||||
|
}
|
||||||
|
}
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
@{
|
||||||
<td>
|
_selectedDatabase = Databases.Single(d => d.Name == _databaseType);
|
||||||
<label class="control-label" style="font-weight: bold">@Localizer["Server:"] </label>
|
foreach (var field in _selectedDatabase.ConnectionStringFields)
|
||||||
</td>
|
{
|
||||||
<td>
|
if (field.Name != "IntegratedSecurity")
|
||||||
<input type="text" class="form-control" @bind="@_serverName" />
|
{
|
||||||
</td>
|
var isVisible = "";
|
||||||
</tr>
|
var fieldType = (field.Name == "Pwd") ? "password" : "text";
|
||||||
<tr>
|
if ((field.Name == "Uid" || field.Name == "Pwd") && _selectedDatabase.Name != "MySQL" )
|
||||||
<td>
|
{
|
||||||
<label class="control-label" style="font-weight: bold">@Localizer["Database:"] </label>
|
var intSecurityField = _selectedDatabase.ConnectionStringFields.Single(f => f.Name == "IntegratedSecurity");
|
||||||
</td>
|
if (intSecurityField != null)
|
||||||
<td>
|
{
|
||||||
<input type="text" class="form-control" @bind="@_databaseName" />
|
isVisible = (Convert.ToBoolean(intSecurityField.Value)) ? "display: none;" : "";
|
||||||
</td>
|
}
|
||||||
</tr>
|
}
|
||||||
<tr>
|
|
||||||
<td>
|
field.Value = field.Value.Replace("{{Date}}", DateTime.UtcNow.ToString("yyyyMMddHHmm"));
|
||||||
<label class="control-label" style="font-weight: bold">@Localizer["Integrated Security:"] </label>
|
|
||||||
</td>
|
<tr style="@isVisible">
|
||||||
<td>
|
<td>
|
||||||
<select class="custom-select" @onchange="SetIntegratedSecurity">
|
<label class="control-label" style="font-weight: bold">@Localizer[$"{field.FriendlyName}:"]</label>
|
||||||
<option value="true" selected>@Localizer["True"]</option>
|
</td>
|
||||||
<option value="false">@Localizer["False"]</option>
|
<td>
|
||||||
</select>
|
<input type="@fieldType" class="form-control" @bind="@field.Value" />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr style="@_integratedSecurityDisplay">
|
}
|
||||||
<td>
|
else
|
||||||
<label class="control-label" style="font-weight: bold">@Localizer["Username:"] </label>
|
{
|
||||||
</td>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<input type="text" class="form-control" @bind="@_username" />
|
<label class="control-label" style="font-weight: bold">@Localizer[$"{field.FriendlyName}:"]</label>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
<td>
|
||||||
<tr style="@_integratedSecurityDisplay">
|
<select class="custom-select" @bind="@field.Value">
|
||||||
<td>
|
<option value="true" selected>@Localizer["True"]</option>
|
||||||
<label class="control-label" style="font-weight: bold">@Localizer["Password:"] </label>
|
<option value="false">@Localizer["False"]</option>
|
||||||
</td>
|
</select>
|
||||||
<td>
|
</td>
|
||||||
<input type="password" class="form-control" @bind="@_password" />
|
</tr>
|
||||||
</td>
|
}
|
||||||
</tr>
|
}
|
||||||
|
}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
@ -127,17 +135,13 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
|
private IOqtaneDatabase _selectedDatabase;
|
||||||
private string _databaseType = "LocalDB";
|
private string _databaseType = "LocalDB";
|
||||||
private string _serverName = "(LocalDb)\\MSSQLLocalDB";
|
|
||||||
private string _databaseName = "Oqtane-" + DateTime.UtcNow.ToString("yyyyMMddHHmm");
|
|
||||||
private string _username = string.Empty;
|
|
||||||
private string _password = string.Empty;
|
|
||||||
private string _hostUsername = UserNames.Host;
|
private string _hostUsername = UserNames.Host;
|
||||||
private string _hostPassword = string.Empty;
|
private string _hostPassword = string.Empty;
|
||||||
private string _confirmPassword = string.Empty;
|
private string _confirmPassword = string.Empty;
|
||||||
private string _hostEmail = string.Empty;
|
private string _hostEmail = string.Empty;
|
||||||
private string _message = string.Empty;
|
private string _message = string.Empty;
|
||||||
private string _integratedSecurityDisplay = "display: none;";
|
|
||||||
private string _loadingDisplay = "display: none;";
|
private string _loadingDisplay = "display: none;";
|
||||||
|
|
||||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||||
|
@ -149,43 +153,21 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetIntegratedSecurity(ChangeEventArgs e)
|
|
||||||
{
|
|
||||||
_integratedSecurityDisplay = Convert.ToBoolean((string)e.Value)
|
|
||||||
? "display: none;"
|
|
||||||
: string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task Install()
|
private async Task Install()
|
||||||
{
|
{
|
||||||
if (_serverName != "" && _databaseName != "" && _hostUsername != "" && _hostPassword.Length >= 6 && _hostPassword == _confirmPassword && _hostEmail != "")
|
var connectionString = _selectedDatabase.BuildConnectionString();
|
||||||
|
|
||||||
|
if (connectionString != "" && _hostUsername != "" && _hostPassword.Length >= 6 && _hostPassword == _confirmPassword && _hostEmail != "")
|
||||||
{
|
{
|
||||||
_loadingDisplay = "";
|
_loadingDisplay = "";
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
|
|
||||||
var connectionstring = "";
|
|
||||||
if (_databaseType == "LocalDB")
|
|
||||||
{
|
|
||||||
connectionstring = "Data Source=" + _serverName + ";AttachDbFilename=|DataDirectory|\\" + _databaseName + ".mdf;Initial Catalog=" + _databaseName + ";Integrated Security=SSPI;";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
connectionstring = "Data Source=" + _serverName + ";Initial Catalog=" + _databaseName + ";";
|
|
||||||
if (_integratedSecurityDisplay == "display: none;")
|
|
||||||
{
|
|
||||||
connectionstring += "Integrated Security=SSPI;";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
connectionstring += "User ID=" + _username + ";Password=" + _password;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Uri uri = new Uri(NavigationManager.Uri);
|
Uri uri = new Uri(NavigationManager.Uri);
|
||||||
|
|
||||||
var config = new InstallConfig
|
var config = new InstallConfig
|
||||||
{
|
{
|
||||||
ConnectionString = connectionstring,
|
DatabaseType = _databaseType,
|
||||||
|
ConnectionString = connectionString,
|
||||||
Aliases = uri.Authority,
|
Aliases = uri.Authority,
|
||||||
HostEmail = _hostEmail,
|
HostEmail = _hostEmail,
|
||||||
HostPassword = _hostPassword,
|
HostPassword = _hostPassword,
|
||||||
|
|
81
Oqtane.Database.MySQL/MySQLDatabase.cs
Normal file
81
Oqtane.Database.MySQL/MySQLDatabase.cs
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders;
|
||||||
|
using MySql.EntityFrameworkCore.Metadata;
|
||||||
|
using Oqtane.Models;
|
||||||
|
using Oqtane.Shared;
|
||||||
|
|
||||||
|
namespace Oqtane.Database.MySQL
|
||||||
|
{
|
||||||
|
public class MySQLDatabase : OqtaneDatabaseBase
|
||||||
|
{
|
||||||
|
private static string _friendlyName => "MySQL";
|
||||||
|
|
||||||
|
private static string _name => "MySQL";
|
||||||
|
|
||||||
|
private static readonly List<ConnectionStringField> _connectionStringFields = new()
|
||||||
|
{
|
||||||
|
new() {Name = "Server", FriendlyName = "Server", Value = "127.0.0.1", HelpText="Enter the database server"},
|
||||||
|
new() {Name = "Port", FriendlyName = "Port", Value = "3306", HelpText="Enter the port used to connect to the server"},
|
||||||
|
new() {Name = "Database", FriendlyName = "Database", Value = "Oqtane-{{Date}}", HelpText="Enter the name of the database"},
|
||||||
|
new() {Name = "Uid", FriendlyName = "User Id", Value = "", HelpText="Enter the username to use for the database"},
|
||||||
|
new() {Name = "Pwd", FriendlyName = "Password", Value = "", HelpText="Enter the password to use for the database"}
|
||||||
|
};
|
||||||
|
|
||||||
|
public MySQLDatabase() :base(_name, _friendlyName, _connectionStringFields) { }
|
||||||
|
|
||||||
|
public override string Provider => "MySql.EntityFrameworkCore";
|
||||||
|
|
||||||
|
public override OperationBuilder<AddColumnOperation> AddAutoIncrementColumn(ColumnsBuilder table, string name)
|
||||||
|
{
|
||||||
|
return table.Column<int>(name: name, nullable: false).Annotation("MySQL:ValueGenerationStrategy", MySQLValueGenerationStrategy.IdentityColumn);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string BuildConnectionString()
|
||||||
|
{
|
||||||
|
var connectionString = String.Empty;
|
||||||
|
|
||||||
|
var server = ConnectionStringFields[0].Value;
|
||||||
|
var port = ConnectionStringFields[1].Value;
|
||||||
|
var database = ConnectionStringFields[2].Value;
|
||||||
|
var userId = ConnectionStringFields[3].Value;
|
||||||
|
var password = ConnectionStringFields[4].Value;
|
||||||
|
|
||||||
|
if (!String.IsNullOrEmpty(server) && !String.IsNullOrEmpty(database) && !String.IsNullOrEmpty(userId) && !String.IsNullOrEmpty(password))
|
||||||
|
{
|
||||||
|
connectionString = $"Server={server};Database={database};Uid={userId};Pwd={password};";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!String.IsNullOrEmpty(port))
|
||||||
|
{
|
||||||
|
connectionString += $"Port={port};";
|
||||||
|
}
|
||||||
|
return connectionString;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ConcatenateSql(params string[] values)
|
||||||
|
{
|
||||||
|
var returnValue = "CONCAT(";
|
||||||
|
for (var i = 0; i < values.Length; i++)
|
||||||
|
{
|
||||||
|
if (i > 0)
|
||||||
|
{
|
||||||
|
returnValue += ",";
|
||||||
|
}
|
||||||
|
returnValue += values[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
returnValue += ")";
|
||||||
|
|
||||||
|
return returnValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public override DbContextOptionsBuilder UseDatabase(DbContextOptionsBuilder optionsBuilder, string connectionString)
|
||||||
|
{
|
||||||
|
return optionsBuilder.UseMySQL(connectionString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
16
Oqtane.Database.MySQL/Oqtane.Database.MySQL.csproj
Normal file
16
Oqtane.Database.MySQL/Oqtane.Database.MySQL.csproj
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
|
<LangVersion>9</LangVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="MySql.EntityFrameworkCore" Version="5.0.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Oqtane.Shared\Oqtane.Shared.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
18
Oqtane.Database.PostgreSQL/Oqtane.Database.PostgreSQL.csproj
Normal file
18
Oqtane.Database.PostgreSQL/Oqtane.Database.PostgreSQL.csproj
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<LangVersion>9</LangVersion>
|
||||||
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="EFCore.NamingConventions" Version="5.0.2" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="5.0.4" />
|
||||||
|
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="5.0.2" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Oqtane.Shared\Oqtane.Shared.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
134
Oqtane.Database.PostgreSQL/PostgreSQLDatabase.cs
Normal file
134
Oqtane.Database.PostgreSQL/PostgreSQLDatabase.cs
Normal file
|
@ -0,0 +1,134 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
|
using EFCore.NamingConventions.Internal;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Internal;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders;
|
||||||
|
using Oqtane.Models;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
|
using Oqtane.Shared;
|
||||||
|
|
||||||
|
namespace Oqtane.Database.PostgreSQL
|
||||||
|
{
|
||||||
|
public class PostgreSQLDatabase : OqtaneDatabaseBase
|
||||||
|
{
|
||||||
|
private static string _friendlyName => "PostgreSQL";
|
||||||
|
|
||||||
|
private static string _name => "PostgreSQL";
|
||||||
|
|
||||||
|
private readonly INameRewriter _rewriter;
|
||||||
|
|
||||||
|
private static readonly List<ConnectionStringField> _connectionStringFields = new()
|
||||||
|
{
|
||||||
|
new() {Name = "Server", FriendlyName = "Server", Value = "127.0.0.1", HelpText="Enter the database server"},
|
||||||
|
new() {Name = "Port", FriendlyName = "Port", Value = "5432", HelpText="Enter the port used to connect to the server"},
|
||||||
|
new() {Name = "Database", FriendlyName = "Database", Value = "Oqtane-{{Date}}", HelpText="Enter the name of the database"},
|
||||||
|
new() {Name = "IntegratedSecurity", FriendlyName = "Integrated Security", Value = "true", HelpText="Select if you want integrated security or not"},
|
||||||
|
new() {Name = "Uid", FriendlyName = "User Id", Value = "", HelpText="Enter the username to use for the database"},
|
||||||
|
new() {Name = "Pwd", FriendlyName = "Password", Value = "", HelpText="Enter the password to use for the database"}
|
||||||
|
};
|
||||||
|
|
||||||
|
public PostgreSQLDatabase() : base(_name, _friendlyName, _connectionStringFields)
|
||||||
|
{
|
||||||
|
_rewriter = new SnakeCaseNameRewriter(CultureInfo.InvariantCulture);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Provider => "Npgsql.EntityFrameworkCore.PostgreSQL";
|
||||||
|
|
||||||
|
public override OperationBuilder<AddColumnOperation> AddAutoIncrementColumn(ColumnsBuilder table, string name)
|
||||||
|
{
|
||||||
|
return table.Column<int>(name: name, nullable: false).Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityAlwaysColumn);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string BuildConnectionString()
|
||||||
|
{
|
||||||
|
var connectionString = String.Empty;
|
||||||
|
|
||||||
|
var server = ConnectionStringFields[0].Value;
|
||||||
|
var port = ConnectionStringFields[1].Value;
|
||||||
|
var database = ConnectionStringFields[2].Value;
|
||||||
|
var integratedSecurity = Boolean.Parse(ConnectionStringFields[3].Value);
|
||||||
|
var userId = ConnectionStringFields[4].Value;
|
||||||
|
var password = ConnectionStringFields[5].Value;
|
||||||
|
|
||||||
|
if (!String.IsNullOrEmpty(server) && !String.IsNullOrEmpty(database) && !String.IsNullOrEmpty(port))
|
||||||
|
{
|
||||||
|
connectionString = $"Server={server};Port={port};Database={database};";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (integratedSecurity)
|
||||||
|
{
|
||||||
|
connectionString += "Integrated Security=true;";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!String.IsNullOrEmpty(userId) && !String.IsNullOrEmpty(password))
|
||||||
|
{
|
||||||
|
connectionString += $"User ID={userId};Password={password};";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
connectionString = String.Empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return connectionString;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ConcatenateSql(params string[] values)
|
||||||
|
{
|
||||||
|
var returnValue = String.Empty;
|
||||||
|
for (var i = 0; i < values.Length; i++)
|
||||||
|
{
|
||||||
|
if (i > 0)
|
||||||
|
{
|
||||||
|
returnValue += " || ";
|
||||||
|
}
|
||||||
|
returnValue += values[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string RewriteName(string name)
|
||||||
|
{
|
||||||
|
return _rewriter.RewriteName(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void UpdateIdentityStoreTableNames(ModelBuilder builder)
|
||||||
|
{
|
||||||
|
foreach(var entity in builder.Model.GetEntityTypes())
|
||||||
|
{
|
||||||
|
var tableName = entity.GetTableName();
|
||||||
|
if (tableName.StartsWith("AspNetUser"))
|
||||||
|
{
|
||||||
|
// Replace table names
|
||||||
|
entity.SetTableName(RewriteName(entity.GetTableName()));
|
||||||
|
|
||||||
|
// Replace column names
|
||||||
|
foreach(var property in entity.GetProperties())
|
||||||
|
{
|
||||||
|
property.SetColumnName(RewriteName(property.GetColumnName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach(var key in entity.GetKeys())
|
||||||
|
{
|
||||||
|
key.SetName(RewriteName(key.GetName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach(var index in entity.GetIndexes())
|
||||||
|
{
|
||||||
|
index.SetName(RewriteName(index.GetName()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override DbContextOptionsBuilder UseDatabase(DbContextOptionsBuilder optionsBuilder, string connectionString)
|
||||||
|
{
|
||||||
|
return optionsBuilder.UseNpgsql(connectionString).UseSnakeCaseNamingConvention();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
15
Oqtane.Database.Sqlite/Oqtane.Database.Sqlite.csproj
Normal file
15
Oqtane.Database.Sqlite/Oqtane.Database.Sqlite.csproj
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="5.0.4" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Oqtane.Shared\Oqtane.Shared.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
65
Oqtane.Database.Sqlite/SqliteDatabase.cs
Normal file
65
Oqtane.Database.Sqlite/SqliteDatabase.cs
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders;
|
||||||
|
using Oqtane.Models;
|
||||||
|
using Oqtane.Shared;
|
||||||
|
|
||||||
|
namespace Oqtane.Repository.Databases
|
||||||
|
{
|
||||||
|
public class SqliteDatabase : OqtaneDatabaseBase
|
||||||
|
{
|
||||||
|
private static string _friendlyName => "Sqlite";
|
||||||
|
|
||||||
|
private static string _name => "Sqlite";
|
||||||
|
|
||||||
|
private static readonly List<ConnectionStringField> _connectionStringFields = new()
|
||||||
|
{
|
||||||
|
new() {Name = "Server", FriendlyName = "File Name", Value = "Oqtane-{{Date}}.db", HelpText="Enter the file name to use for the database"}
|
||||||
|
};
|
||||||
|
|
||||||
|
public SqliteDatabase() :base(_name, _friendlyName, _connectionStringFields) { }
|
||||||
|
|
||||||
|
public override string Provider => "Microsoft.EntityFrameworkCore.Sqlite";
|
||||||
|
|
||||||
|
public override OperationBuilder<AddColumnOperation> AddAutoIncrementColumn(ColumnsBuilder table, string name)
|
||||||
|
{
|
||||||
|
return table.Column<int>(name: name, nullable: false).Annotation("Sqlite:Autoincrement", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string BuildConnectionString()
|
||||||
|
{
|
||||||
|
var connectionstring = String.Empty;
|
||||||
|
|
||||||
|
var server = ConnectionStringFields[0].Value;
|
||||||
|
|
||||||
|
if (!String.IsNullOrEmpty(server))
|
||||||
|
{
|
||||||
|
connectionstring = $"Data Source={server};";
|
||||||
|
}
|
||||||
|
|
||||||
|
return connectionstring;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ConcatenateSql(params string[] values)
|
||||||
|
{
|
||||||
|
var returnValue = String.Empty;
|
||||||
|
for (var i = 0; i < values.Length; i++)
|
||||||
|
{
|
||||||
|
if (i > 0)
|
||||||
|
{
|
||||||
|
returnValue += " || ";
|
||||||
|
}
|
||||||
|
returnValue += values[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override DbContextOptionsBuilder UseDatabase(DbContextOptionsBuilder optionsBuilder, string connectionString)
|
||||||
|
{
|
||||||
|
return optionsBuilder.UseSqlite(connectionString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,11 +6,8 @@ using Oqtane.Shared;
|
||||||
using Oqtane.Infrastructure;
|
using Oqtane.Infrastructure;
|
||||||
using Oqtane.Repository;
|
using Oqtane.Repository;
|
||||||
using Oqtane.Enums;
|
using Oqtane.Enums;
|
||||||
using System.Data.SqlClient;
|
|
||||||
using System.Data;
|
|
||||||
using System.Dynamic;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using System;
|
using System;
|
||||||
|
using Microsoft.Data.SqlClient;
|
||||||
|
|
||||||
namespace Oqtane.Controllers
|
namespace Oqtane.Controllers
|
||||||
{
|
{
|
||||||
|
|
10
Oqtane.Server/Databases/Interfaces/IMultiDatabase.cs
Normal file
10
Oqtane.Server/Databases/Interfaces/IMultiDatabase.cs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
|
||||||
|
namespace Oqtane.Repository.Databases.Interfaces
|
||||||
|
{
|
||||||
|
public interface IMultiDatabase
|
||||||
|
{
|
||||||
|
public IEnumerable<IOqtaneDatabase> Databases { get; }
|
||||||
|
}
|
||||||
|
}
|
36
Oqtane.Server/Databases/LocalDbDatabase.cs
Normal file
36
Oqtane.Server/Databases/LocalDbDatabase.cs
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Oqtane.Models;
|
||||||
|
using Oqtane.Repository.Databases;
|
||||||
|
|
||||||
|
namespace Oqtane.Databases
|
||||||
|
{
|
||||||
|
public class LocalDbDatabase : SqlServerDatabaseBase
|
||||||
|
{
|
||||||
|
private static string _friendlyName => "Local Database";
|
||||||
|
private static string _name => "LocalDB";
|
||||||
|
|
||||||
|
private static readonly List<ConnectionStringField> _connectionStringFields = new()
|
||||||
|
{
|
||||||
|
new() {Name = "Server", FriendlyName = "Server", Value = "(LocalDb)\\MSSQLLocalDB", HelpText="Enter the database server"},
|
||||||
|
new() {Name = "Database", FriendlyName = "Database", Value = "Oqtane-{{Date}}", HelpText="Enter the name of the database"}
|
||||||
|
};
|
||||||
|
|
||||||
|
public LocalDbDatabase() :base(_name, _friendlyName, _connectionStringFields) { }
|
||||||
|
|
||||||
|
public override string BuildConnectionString()
|
||||||
|
{
|
||||||
|
var connectionString = String.Empty;
|
||||||
|
|
||||||
|
var server = ConnectionStringFields[0].Value;
|
||||||
|
var database = ConnectionStringFields[1].Value;
|
||||||
|
|
||||||
|
if (!String.IsNullOrEmpty(server) && !String.IsNullOrEmpty(database))
|
||||||
|
{
|
||||||
|
connectionString = $"Data Source={server};AttachDbFilename=|DataDirectory|\\{database}.mdf;Initial Catalog={database};Integrated Security=SSPI;";
|
||||||
|
}
|
||||||
|
|
||||||
|
return connectionString;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
62
Oqtane.Server/Databases/SqlServerDatabase.cs
Normal file
62
Oqtane.Server/Databases/SqlServerDatabase.cs
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Oqtane.Models;
|
||||||
|
using Oqtane.Repository.Databases;
|
||||||
|
|
||||||
|
// ReSharper disable ArrangeObjectCreationWhenTypeNotEvident
|
||||||
|
|
||||||
|
namespace Oqtane.Databases
|
||||||
|
{
|
||||||
|
public class SqlServerDatabase : SqlServerDatabaseBase
|
||||||
|
{
|
||||||
|
private static string _friendlyName => "SQL Server";
|
||||||
|
|
||||||
|
private static string _name => "SqlServer";
|
||||||
|
|
||||||
|
private static readonly List<ConnectionStringField> _connectionStringFields = new()
|
||||||
|
{
|
||||||
|
new() {Name = "Server", FriendlyName = "Server", Value = ".", HelpText="Enter the database server"},
|
||||||
|
new() {Name = "Database", FriendlyName = "Database", Value = "Oqtane-{{Date}}", HelpText="Enter the name of the database"},
|
||||||
|
new() {Name = "IntegratedSecurity", FriendlyName = "Integrated Security", Value = "true", HelpText="Select if you want integrated security or not"},
|
||||||
|
new() {Name = "Uid", FriendlyName = "User Id", Value = "", HelpText="Enter the username to use for the database"},
|
||||||
|
new() {Name = "Pwd", FriendlyName = "Password", Value = "", HelpText="Enter the password to use for the database"}
|
||||||
|
};
|
||||||
|
|
||||||
|
public SqlServerDatabase() :base(_name, _friendlyName, _connectionStringFields) { }
|
||||||
|
|
||||||
|
public override string BuildConnectionString()
|
||||||
|
{
|
||||||
|
var connectionString = String.Empty;
|
||||||
|
|
||||||
|
var server = ConnectionStringFields[0].Value;
|
||||||
|
var database = ConnectionStringFields[1].Value;
|
||||||
|
var integratedSecurity = Boolean.Parse(ConnectionStringFields[2].Value);
|
||||||
|
var userId = ConnectionStringFields[3].Value;
|
||||||
|
var password = ConnectionStringFields[4].Value;
|
||||||
|
|
||||||
|
if (!String.IsNullOrEmpty(server) && !String.IsNullOrEmpty(database))
|
||||||
|
{
|
||||||
|
connectionString = $"Data Source={server};Initial Catalog={database};";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (integratedSecurity)
|
||||||
|
{
|
||||||
|
connectionString += "Integrated Security=SSPI;";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!String.IsNullOrEmpty(userId) && !String.IsNullOrEmpty(password))
|
||||||
|
{
|
||||||
|
connectionString += $"User ID={userId};Password={password};";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
connectionString = String.Empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return connectionString;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
30
Oqtane.Server/Databases/SqlServerDatabaseBase.cs
Normal file
30
Oqtane.Server/Databases/SqlServerDatabaseBase.cs
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders;
|
||||||
|
using Oqtane.Databases;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
using Oqtane.Models;
|
||||||
|
using Oqtane.Shared;
|
||||||
|
|
||||||
|
namespace Oqtane.Repository.Databases
|
||||||
|
{
|
||||||
|
public abstract class SqlServerDatabaseBase : OqtaneDatabaseBase
|
||||||
|
{
|
||||||
|
protected SqlServerDatabaseBase(string name, string friendlyName, List<ConnectionStringField> connectionStringFields) : base(name, friendlyName, connectionStringFields)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Provider => "Microsoft.EntityFrameworkCore.SqlServer";
|
||||||
|
|
||||||
|
public override OperationBuilder<AddColumnOperation> AddAutoIncrementColumn(ColumnsBuilder table, string name)
|
||||||
|
{
|
||||||
|
return table.Column<int>(name: name, nullable: false).Annotation("SqlServer:Identity", "1, 1");
|
||||||
|
}
|
||||||
|
|
||||||
|
public override DbContextOptionsBuilder UseDatabase(DbContextOptionsBuilder optionsBuilder, string connectionString)
|
||||||
|
{
|
||||||
|
return optionsBuilder.UseSqlServer(connectionString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,15 +1,29 @@
|
||||||
|
using System;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
// ReSharper disable ConvertToUsingDeclaration
|
||||||
|
|
||||||
namespace Oqtane.Extensions
|
namespace Oqtane.Extensions
|
||||||
{
|
{
|
||||||
public static class DbContextOptionsBuilderExtensions
|
public static class DbContextOptionsBuilderExtensions
|
||||||
{
|
{
|
||||||
public static DbContextOptionsBuilder UseOqtaneDatabase([NotNull] this DbContextOptionsBuilder optionsBuilder, string connectionString)
|
public static DbContextOptionsBuilder UseOqtaneDatabase([NotNull] this DbContextOptionsBuilder optionsBuilder, IOqtaneDatabase database, string connectionString)
|
||||||
{
|
{
|
||||||
optionsBuilder.UseSqlServer(connectionString);
|
database.UseDatabase(optionsBuilder, connectionString);
|
||||||
|
|
||||||
return optionsBuilder;
|
return optionsBuilder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static DbContextOptionsBuilder UseOqtaneDatabase([NotNull] this DbContextOptionsBuilder optionsBuilder, string databaseType, string connectionString)
|
||||||
|
{
|
||||||
|
var type = Type.GetType(databaseType);
|
||||||
|
var database = Activator.CreateInstance(type) as IOqtaneDatabase;
|
||||||
|
|
||||||
|
database.UseDatabase(optionsBuilder, connectionString);
|
||||||
|
|
||||||
|
return optionsBuilder;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ using System.Reflection;
|
||||||
using System.Runtime.Loader;
|
using System.Runtime.Loader;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using Oqtane.Infrastructure;
|
using Oqtane.Infrastructure;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
using Oqtane.Modules;
|
using Oqtane.Modules;
|
||||||
using Oqtane.Services;
|
using Oqtane.Services;
|
||||||
using Oqtane.Shared;
|
using Oqtane.Shared;
|
||||||
|
@ -46,6 +47,17 @@ namespace Microsoft.Extensions.DependencyInjection
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// dynamically register database providers
|
||||||
|
var databaseTypes = assembly.GetInterfaces<IOqtaneDatabase>();
|
||||||
|
foreach (var databaseType in databaseTypes)
|
||||||
|
{
|
||||||
|
if (databaseType.AssemblyQualifiedName != null)
|
||||||
|
{
|
||||||
|
var serviceType = Type.GetType("Oqtane.Interfaces.IOqtaneDatabase, Oqtane.Shared");
|
||||||
|
services.AddScoped(serviceType ?? databaseType, databaseType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// dynamically register hosted services
|
// dynamically register hosted services
|
||||||
var serviceTypes = assembly.GetTypes(hostedServiceType);
|
var serviceTypes = assembly.GetTypes(hostedServiceType);
|
||||||
foreach (var serviceType in serviceTypes)
|
foreach (var serviceType in serviceTypes)
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Data;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using DbUp;
|
|
||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.Caching.Memory;
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
|
@ -16,8 +14,14 @@ using Oqtane.Models;
|
||||||
using Oqtane.Repository;
|
using Oqtane.Repository;
|
||||||
using Oqtane.Shared;
|
using Oqtane.Shared;
|
||||||
using Oqtane.Enums;
|
using Oqtane.Enums;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
using File = System.IO.File;
|
using File = System.IO.File;
|
||||||
|
|
||||||
|
// ReSharper disable MemberCanBePrivate.Global
|
||||||
|
// ReSharper disable ConvertToUsingDeclaration
|
||||||
|
// ReSharper disable BuiltInTypeReferenceStyleForMemberAccess
|
||||||
|
// ReSharper disable UseIndexFromEndExpression
|
||||||
|
|
||||||
namespace Oqtane.Infrastructure
|
namespace Oqtane.Infrastructure
|
||||||
{
|
{
|
||||||
public class DatabaseManager : IDatabaseManager
|
public class DatabaseManager : IDatabaseManager
|
||||||
|
@ -75,7 +79,13 @@ namespace Oqtane.Infrastructure
|
||||||
if (install == null)
|
if (install == null)
|
||||||
{
|
{
|
||||||
// startup or silent installation
|
// startup or silent installation
|
||||||
install = new InstallConfig { ConnectionString = _config.GetConnectionString(SettingKeys.ConnectionStringKey), TenantName = TenantNames.Master, IsNewTenant = false };
|
install = new InstallConfig
|
||||||
|
{
|
||||||
|
ConnectionString = _config.GetConnectionString(SettingKeys.ConnectionStringKey),
|
||||||
|
TenantName = TenantNames.Master,
|
||||||
|
DatabaseType = _config.GetSection(SettingKeys.DatabaseSection)[SettingKeys.DatabaseTypeKey],
|
||||||
|
IsNewTenant = false
|
||||||
|
};
|
||||||
|
|
||||||
var installation = IsInstalled();
|
var installation = IsInstalled();
|
||||||
if (!installation.Success)
|
if (!installation.Success)
|
||||||
|
@ -173,14 +183,20 @@ namespace Oqtane.Infrastructure
|
||||||
{
|
{
|
||||||
//create data directory if does not exist
|
//create data directory if does not exist
|
||||||
var dataDirectory = AppDomain.CurrentDomain.GetData("DataDirectory")?.ToString();
|
var dataDirectory = AppDomain.CurrentDomain.GetData("DataDirectory")?.ToString();
|
||||||
if (!Directory.Exists(dataDirectory)) Directory.CreateDirectory(dataDirectory);
|
if (!Directory.Exists(dataDirectory)) Directory.CreateDirectory(dataDirectory ?? String.Empty);
|
||||||
|
|
||||||
var connectionString = NormalizeConnectionString(install.ConnectionString);
|
var connectionString = NormalizeConnectionString(install.ConnectionString);
|
||||||
using (var dbc = new DbContext(new DbContextOptionsBuilder().UseOqtaneDatabase(connectionString).Options))
|
var databaseType = install.DatabaseType;
|
||||||
|
using (var scope = _serviceScopeFactory.CreateScope())
|
||||||
{
|
{
|
||||||
// create empty database if it does not exist
|
var databases = scope.ServiceProvider.GetServices<IOqtaneDatabase>();
|
||||||
dbc.Database.EnsureCreated();
|
|
||||||
result.Success = true;
|
using (var dbc = new DbContext(new DbContextOptionsBuilder().UseOqtaneDatabase(databases.Single(d => d.Name == databaseType), connectionString).Options))
|
||||||
|
{
|
||||||
|
// create empty database if it does not exist
|
||||||
|
dbc.Database.EnsureCreated();
|
||||||
|
result.Success = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
@ -202,31 +218,37 @@ namespace Oqtane.Infrastructure
|
||||||
|
|
||||||
if (install.TenantName == TenantNames.Master)
|
if (install.TenantName == TenantNames.Master)
|
||||||
{
|
{
|
||||||
MigrateScriptNamingConvention("Master", install.ConnectionString);
|
using (var scope = _serviceScopeFactory.CreateScope())
|
||||||
|
|
||||||
var upgradeConfig = DeployChanges
|
|
||||||
.To
|
|
||||||
.SqlDatabase(NormalizeConnectionString(install.ConnectionString))
|
|
||||||
.WithScriptsEmbeddedInAssembly(Assembly.GetExecutingAssembly(), s => s.Contains("Master.") && s.EndsWith(".sql",StringComparison.OrdinalIgnoreCase));
|
|
||||||
|
|
||||||
var upgrade = upgradeConfig.Build();
|
|
||||||
if (upgrade.IsUpgradeRequired())
|
|
||||||
{
|
{
|
||||||
var upgradeResult = upgrade.PerformUpgrade();
|
var databases = scope.ServiceProvider.GetServices<IOqtaneDatabase>();
|
||||||
result.Success = upgradeResult.Successful;
|
var sql = scope.ServiceProvider.GetRequiredService<ISqlRepository>();
|
||||||
if (!result.Success)
|
|
||||||
|
try
|
||||||
{
|
{
|
||||||
result.Message = upgradeResult.Error.Message;
|
var dbConfig = new DbConfig(null, null, databases) {ConnectionString = install.ConnectionString, DatabaseType = install.DatabaseType};
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result.Success = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result.Success)
|
using (var masterDbContext = new MasterDBContext(new DbContextOptions<MasterDBContext>(), dbConfig))
|
||||||
{
|
{
|
||||||
UpdateConnectionString(install.ConnectionString);
|
var installation = IsInstalled();
|
||||||
|
if (installation.Success && (install.DatabaseType == "SqlServer" || install.DatabaseType == "LocalDB"))
|
||||||
|
{
|
||||||
|
UpgradeSqlServer(sql, install.ConnectionString, true);
|
||||||
|
}
|
||||||
|
// Push latest model into database
|
||||||
|
masterDbContext.Database.Migrate();
|
||||||
|
result.Success = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
result.Message = ex.Message;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.Success)
|
||||||
|
{
|
||||||
|
UpdateConnectionString(install.ConnectionString);
|
||||||
|
UpdateDatabaseType(install.DatabaseType);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -243,28 +265,56 @@ namespace Oqtane.Infrastructure
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(install.TenantName) && !string.IsNullOrEmpty(install.Aliases))
|
if (!string.IsNullOrEmpty(install.TenantName) && !string.IsNullOrEmpty(install.Aliases))
|
||||||
{
|
{
|
||||||
using (var db = new InstallationContext(NormalizeConnectionString(_config.GetConnectionString(SettingKeys.ConnectionStringKey))))
|
using (var scope = _serviceScopeFactory.CreateScope())
|
||||||
{
|
{
|
||||||
Tenant tenant;
|
var databases = scope.ServiceProvider.GetServices<IOqtaneDatabase>();
|
||||||
if (install.IsNewTenant)
|
|
||||||
{
|
|
||||||
tenant = new Tenant { Name = install.TenantName, DBConnectionString = DenormalizeConnectionString(install.ConnectionString), CreatedBy = "", CreatedOn = DateTime.UtcNow, ModifiedBy = "", ModifiedOn = DateTime.UtcNow };
|
|
||||||
db.Tenant.Add(tenant);
|
|
||||||
db.SaveChanges();
|
|
||||||
_cache.Remove("tenants");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tenant = db.Tenant.FirstOrDefault(item => item.Name == install.TenantName);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (string aliasname in install.Aliases.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
|
using (var db = GetInstallationContext(databases))
|
||||||
{
|
{
|
||||||
var alias = new Alias { Name = aliasname, TenantId = tenant.TenantId, SiteId = -1, CreatedBy = "", CreatedOn = DateTime.UtcNow, ModifiedBy = "", ModifiedOn = DateTime.UtcNow };
|
Tenant tenant;
|
||||||
db.Alias.Add(alias);
|
if (install.IsNewTenant)
|
||||||
db.SaveChanges();
|
{
|
||||||
|
tenant = new Tenant
|
||||||
|
{
|
||||||
|
Name = install.TenantName,
|
||||||
|
DBConnectionString = DenormalizeConnectionString(install.ConnectionString),
|
||||||
|
DBType = install.DatabaseType,
|
||||||
|
CreatedBy = "",
|
||||||
|
CreatedOn = DateTime.UtcNow,
|
||||||
|
ModifiedBy = "",
|
||||||
|
ModifiedOn = DateTime.UtcNow
|
||||||
|
};
|
||||||
|
db.Tenant.Add(tenant);
|
||||||
|
db.SaveChanges();
|
||||||
|
_cache.Remove("tenants");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tenant = db.Tenant.FirstOrDefault(item => item.Name == install.TenantName);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var aliasName in install.Aliases.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries))
|
||||||
|
{
|
||||||
|
if (tenant != null)
|
||||||
|
{
|
||||||
|
var alias = new Alias
|
||||||
|
{
|
||||||
|
Name = aliasName,
|
||||||
|
TenantId = tenant.TenantId,
|
||||||
|
SiteId = -1,
|
||||||
|
CreatedBy = "",
|
||||||
|
CreatedOn = DateTime.UtcNow,
|
||||||
|
ModifiedBy = "",
|
||||||
|
ModifiedOn = DateTime.UtcNow
|
||||||
|
};
|
||||||
|
db.Alias.Add(alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
db.SaveChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
_cache.Remove("aliases");
|
||||||
}
|
}
|
||||||
_cache.Remove("aliases");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,39 +327,45 @@ namespace Oqtane.Infrastructure
|
||||||
{
|
{
|
||||||
var result = new Installation { Success = false, Message = string.Empty };
|
var result = new Installation { Success = false, Message = string.Empty };
|
||||||
|
|
||||||
string[] versions = Constants.ReleaseVersions.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
var versions = Constants.ReleaseVersions.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
|
||||||
using (var scope = _serviceScopeFactory.CreateScope())
|
using (var scope = _serviceScopeFactory.CreateScope())
|
||||||
{
|
{
|
||||||
var upgrades = scope.ServiceProvider.GetRequiredService<IUpgradeManager>();
|
var upgrades = scope.ServiceProvider.GetRequiredService<IUpgradeManager>();
|
||||||
|
var databases = scope.ServiceProvider.GetServices<IOqtaneDatabase>();
|
||||||
|
var sql = scope.ServiceProvider.GetRequiredService<ISqlRepository>();
|
||||||
|
|
||||||
using (var db = new InstallationContext(NormalizeConnectionString(_config.GetConnectionString(SettingKeys.ConnectionStringKey))))
|
using (var db = GetInstallationContext(databases))
|
||||||
{
|
{
|
||||||
foreach (var tenant in db.Tenant.ToList())
|
foreach (var tenant in db.Tenant.ToList())
|
||||||
{
|
{
|
||||||
MigrateScriptNamingConvention("Tenant", tenant.DBConnectionString);
|
try
|
||||||
|
|
||||||
var upgradeConfig = DeployChanges.To.SqlDatabase(NormalizeConnectionString(tenant.DBConnectionString))
|
|
||||||
.WithScriptsEmbeddedInAssembly(Assembly.GetExecutingAssembly(), s => s.Contains("Tenant.") && s.EndsWith(".sql", StringComparison.OrdinalIgnoreCase));
|
|
||||||
|
|
||||||
var upgrade = upgradeConfig.Build();
|
|
||||||
if (upgrade.IsUpgradeRequired())
|
|
||||||
{
|
{
|
||||||
var upgradeResult = upgrade.PerformUpgrade();
|
var dbConfig = new DbConfig(null, null, databases) {ConnectionString = tenant.DBConnectionString, DatabaseType = tenant.DBType};
|
||||||
result.Success = upgradeResult.Successful;
|
using (var tenantDbContext = new TenantDBContext(dbConfig, null))
|
||||||
if (!result.Success)
|
|
||||||
{
|
{
|
||||||
result.Message = upgradeResult.Error.Message;
|
if (install.DatabaseType == "SqlServer" || install.DatabaseType == "LocalDB")
|
||||||
|
{
|
||||||
|
UpgradeSqlServer(sql, tenant.DBConnectionString, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Push latest model into database
|
||||||
|
tenantDbContext.Database.Migrate();
|
||||||
|
result.Success = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
result.Message = ex.Message;
|
||||||
|
}
|
||||||
|
|
||||||
// execute any version specific upgrade logic
|
// execute any version specific upgrade logic
|
||||||
string version = tenant.Version;
|
var version = tenant.Version;
|
||||||
int index = Array.FindIndex(versions, item => item == version);
|
var index = Array.FindIndex(versions, item => item == version);
|
||||||
if (index != (versions.Length - 1))
|
if (index != (versions.Length - 1))
|
||||||
{
|
{
|
||||||
if (index == -1) index = 0;
|
if (index == -1) index = 0;
|
||||||
for (int i = index; i < versions.Length; i++)
|
for (var i = index; i < versions.Length; i++)
|
||||||
{
|
{
|
||||||
upgrades.Upgrade(tenant, versions[i]);
|
upgrades.Upgrade(tenant, versions[i]);
|
||||||
}
|
}
|
||||||
|
@ -335,21 +391,23 @@ namespace Oqtane.Infrastructure
|
||||||
|
|
||||||
using (var scope = _serviceScopeFactory.CreateScope())
|
using (var scope = _serviceScopeFactory.CreateScope())
|
||||||
{
|
{
|
||||||
var moduledefinitions = scope.ServiceProvider.GetRequiredService<IModuleDefinitionRepository>();
|
var moduleDefinitions = scope.ServiceProvider.GetRequiredService<IModuleDefinitionRepository>();
|
||||||
var sql = scope.ServiceProvider.GetRequiredService<ISqlRepository>();
|
var sql = scope.ServiceProvider.GetRequiredService<ISqlRepository>();
|
||||||
foreach (var moduledefinition in moduledefinitions.GetModuleDefinitions())
|
var databases = scope.ServiceProvider.GetServices<IOqtaneDatabase>();
|
||||||
|
|
||||||
|
foreach (var moduleDefinition in moduleDefinitions.GetModuleDefinitions())
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(moduledefinition.ReleaseVersions) && !string.IsNullOrEmpty(moduledefinition.ServerManagerType))
|
if (!string.IsNullOrEmpty(moduleDefinition.ReleaseVersions) && !string.IsNullOrEmpty(moduleDefinition.ServerManagerType))
|
||||||
{
|
{
|
||||||
Type moduletype = Type.GetType(moduledefinition.ServerManagerType);
|
var moduleType = Type.GetType(moduleDefinition.ServerManagerType);
|
||||||
if (moduletype != null)
|
if (moduleType != null)
|
||||||
{
|
{
|
||||||
string[] versions = moduledefinition.ReleaseVersions.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
var versions = moduleDefinition.ReleaseVersions.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
using (var db = new InstallationContext(NormalizeConnectionString(_config.GetConnectionString(SettingKeys.ConnectionStringKey))))
|
using (var db = GetInstallationContext(databases))
|
||||||
{
|
{
|
||||||
foreach (var tenant in db.Tenant.ToList())
|
foreach (var tenant in db.Tenant.ToList())
|
||||||
{
|
{
|
||||||
int index = Array.FindIndex(versions, item => item == moduledefinition.Version);
|
var index = Array.FindIndex(versions, item => item == moduleDefinition.Version);
|
||||||
if (tenant.Name == install.TenantName && install.TenantName != TenantNames.Master)
|
if (tenant.Name == install.TenantName && install.TenantName != TenantNames.Master)
|
||||||
{
|
{
|
||||||
index = -1;
|
index = -1;
|
||||||
|
@ -357,31 +415,31 @@ namespace Oqtane.Infrastructure
|
||||||
if (index != (versions.Length - 1))
|
if (index != (versions.Length - 1))
|
||||||
{
|
{
|
||||||
if (index == -1) index = 0;
|
if (index == -1) index = 0;
|
||||||
for (int i = index; i < versions.Length; i++)
|
for (var i = index; i < versions.Length; i++)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (moduletype.GetInterface("IInstallable") != null)
|
if (moduleType.GetInterface("IInstallable") != null)
|
||||||
{
|
{
|
||||||
var moduleobject = ActivatorUtilities.CreateInstance(scope.ServiceProvider, moduletype);
|
var moduleObject = ActivatorUtilities.CreateInstance(scope.ServiceProvider, moduleType) as IInstallable;
|
||||||
((IInstallable)moduleobject).Install(tenant, versions[i]);
|
moduleObject?.Install(tenant, versions[i]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sql.ExecuteScript(tenant, moduletype.Assembly, Utilities.GetTypeName(moduledefinition.ModuleDefinitionName) + "." + versions[i] + ".sql");
|
sql.ExecuteScript(tenant, moduleType.Assembly, Utilities.GetTypeName(moduleDefinition.ModuleDefinitionName) + "." + versions[i] + ".sql");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
result.Message = "An Error Occurred Installing " + moduledefinition.Name + " Version " + versions[i] + " - " + ex.Message.ToString();
|
result.Message = "An Error Occurred Installing " + moduleDefinition.Name + " Version " + versions[i] + " - " + ex.Message;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (string.IsNullOrEmpty(result.Message) && moduledefinition.Version != versions[versions.Length - 1])
|
if (string.IsNullOrEmpty(result.Message) && moduleDefinition.Version != versions[versions.Length - 1])
|
||||||
{
|
{
|
||||||
moduledefinition.Version = versions[versions.Length - 1];
|
moduleDefinition.Version = versions[versions.Length - 1];
|
||||||
db.Entry(moduledefinition).State = EntityState.Modified;
|
db.Entry(moduleDefinition).State = EntityState.Modified;
|
||||||
db.SaveChanges();
|
db.SaveChanges();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -408,8 +466,8 @@ namespace Oqtane.Infrastructure
|
||||||
{
|
{
|
||||||
// use the SiteState to set the Alias explicitly so the tenant can be resolved
|
// use the SiteState to set the Alias explicitly so the tenant can be resolved
|
||||||
var aliases = scope.ServiceProvider.GetRequiredService<IAliasRepository>();
|
var aliases = scope.ServiceProvider.GetRequiredService<IAliasRepository>();
|
||||||
string firstalias = install.Aliases.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)[0];
|
var firstAlias = install.Aliases.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)[0];
|
||||||
var alias = aliases.GetAliases().FirstOrDefault(item => item.Name == firstalias);
|
var alias = aliases.GetAliases().FirstOrDefault(item => item.Name == firstAlias);
|
||||||
var siteState = scope.ServiceProvider.GetRequiredService<SiteState>();
|
var siteState = scope.ServiceProvider.GetRequiredService<SiteState>();
|
||||||
siteState.Alias = alias;
|
siteState.Alias = alias;
|
||||||
|
|
||||||
|
@ -420,7 +478,7 @@ namespace Oqtane.Infrastructure
|
||||||
var tenants = scope.ServiceProvider.GetRequiredService<ITenantRepository>();
|
var tenants = scope.ServiceProvider.GetRequiredService<ITenantRepository>();
|
||||||
var users = scope.ServiceProvider.GetRequiredService<IUserRepository>();
|
var users = scope.ServiceProvider.GetRequiredService<IUserRepository>();
|
||||||
var roles = scope.ServiceProvider.GetRequiredService<IRoleRepository>();
|
var roles = scope.ServiceProvider.GetRequiredService<IRoleRepository>();
|
||||||
var userroles = scope.ServiceProvider.GetRequiredService<IUserRoleRepository>();
|
var userRoles = scope.ServiceProvider.GetRequiredService<IUserRoleRepository>();
|
||||||
var folders = scope.ServiceProvider.GetRequiredService<IFolderRepository>();
|
var folders = scope.ServiceProvider.GetRequiredService<IFolderRepository>();
|
||||||
var log = scope.ServiceProvider.GetRequiredService<ILogManager>();
|
var log = scope.ServiceProvider.GetRequiredService<ILogManager>();
|
||||||
var identityUserManager = scope.ServiceProvider.GetRequiredService<UserManager<IdentityUser>>();
|
var identityUserManager = scope.ServiceProvider.GetRequiredService<UserManager<IdentityUser>>();
|
||||||
|
@ -438,10 +496,10 @@ namespace Oqtane.Infrastructure
|
||||||
};
|
};
|
||||||
site = sites.AddSite(site);
|
site = sites.AddSite(site);
|
||||||
|
|
||||||
IdentityUser identityUser = identityUserManager.FindByNameAsync(UserNames.Host).GetAwaiter().GetResult();
|
var identityUser = identityUserManager.FindByNameAsync(UserNames.Host).GetAwaiter().GetResult();
|
||||||
if (identityUser == null)
|
if (identityUser == null)
|
||||||
{
|
{
|
||||||
identityUser = new IdentityUser { UserName = UserNames.Host, Email = install.HostEmail, EmailConfirmed = true };
|
identityUser = new IdentityUser {UserName = UserNames.Host, Email = install.HostEmail, EmailConfirmed = true};
|
||||||
var create = identityUserManager.CreateAsync(identityUser, install.HostPassword).GetAwaiter().GetResult();
|
var create = identityUserManager.CreateAsync(identityUser, install.HostPassword).GetAwaiter().GetResult();
|
||||||
if (create.Succeeded)
|
if (create.Succeeded)
|
||||||
{
|
{
|
||||||
|
@ -458,8 +516,8 @@ namespace Oqtane.Infrastructure
|
||||||
|
|
||||||
user = users.AddUser(user);
|
user = users.AddUser(user);
|
||||||
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};
|
||||||
userroles.AddUserRole(userRole);
|
userRoles.AddUserRole(userRole);
|
||||||
|
|
||||||
// add user folder
|
// add user folder
|
||||||
var folder = folders.GetFolder(user.SiteId, Utilities.PathCombine("Users", Path.DirectorySeparatorChar.ToString()));
|
var folder = folders.GetFolder(user.SiteId, Utilities.PathCombine("Users", Path.DirectorySeparatorChar.ToString()));
|
||||||
|
@ -484,17 +542,20 @@ namespace Oqtane.Infrastructure
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (string aliasname in install.Aliases.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
|
foreach (var aliasName in install.Aliases.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries))
|
||||||
{
|
{
|
||||||
alias = aliases.GetAliases().FirstOrDefault(item => item.Name == aliasname);
|
alias = aliases.GetAliases().FirstOrDefault(item => item.Name == aliasName);
|
||||||
alias.SiteId = site.SiteId;
|
if (alias != null)
|
||||||
aliases.UpdateAlias(alias);
|
{
|
||||||
|
alias.SiteId = site.SiteId;
|
||||||
|
aliases.UpdateAlias(alias);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tenant.Version = Constants.Version;
|
tenant.Version = Constants.Version;
|
||||||
tenants.UpdateTenant(tenant);
|
tenants.UpdateTenant(tenant);
|
||||||
|
|
||||||
log.Log(site.SiteId, LogLevel.Trace, this, LogFunction.Create, "Site Created {Site}", site);
|
if (site != null) log.Log(site.SiteId, LogLevel.Trace, this, LogFunction.Create, "Site Created {Site}", site);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -504,30 +565,6 @@ namespace Oqtane.Infrastructure
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string NormalizeConnectionString(string connectionString)
|
|
||||||
{
|
|
||||||
var dataDirectory = AppDomain.CurrentDomain.GetData("DataDirectory")?.ToString();
|
|
||||||
connectionString = connectionString.Replace("|DataDirectory|", dataDirectory);
|
|
||||||
return connectionString;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string DenormalizeConnectionString(string connectionString)
|
|
||||||
{
|
|
||||||
var dataDirectory = AppDomain.CurrentDomain.GetData("DataDirectory")?.ToString();
|
|
||||||
connectionString = connectionString.Replace(dataDirectory, "|DataDirectory|");
|
|
||||||
return connectionString;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdateConnectionString(string connectionString)
|
|
||||||
{
|
|
||||||
connectionString = DenormalizeConnectionString(connectionString);
|
|
||||||
if (_config.GetConnectionString(SettingKeys.ConnectionStringKey) != connectionString)
|
|
||||||
{
|
|
||||||
AddOrUpdateAppSetting($"ConnectionStrings:{SettingKeys.ConnectionStringKey}", connectionString);
|
|
||||||
_config.Reload();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddOrUpdateAppSetting<T>(string sectionPathKey, T value)
|
public void AddOrUpdateAppSetting<T>(string sectionPathKey, T value)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -547,6 +584,36 @@ namespace Oqtane.Infrastructure
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string DenormalizeConnectionString(string connectionString)
|
||||||
|
{
|
||||||
|
var dataDirectory = AppDomain.CurrentDomain.GetData("DataDirectory")?.ToString();
|
||||||
|
connectionString = connectionString.Replace(dataDirectory ?? String.Empty, "|DataDirectory|");
|
||||||
|
return connectionString;
|
||||||
|
}
|
||||||
|
|
||||||
|
private InstallationContext GetInstallationContext(IEnumerable<IOqtaneDatabase> databases)
|
||||||
|
{
|
||||||
|
var databaseType = _config.GetSection(SettingKeys.DatabaseSection)[SettingKeys.DatabaseTypeKey];
|
||||||
|
var connectionString = NormalizeConnectionString(_config.GetConnectionString(SettingKeys.ConnectionStringKey));
|
||||||
|
|
||||||
|
return new InstallationContext(databases.Single(d => d.Name == databaseType), connectionString);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetInstallationConfig(string key, string defaultValue)
|
||||||
|
{
|
||||||
|
var value = _config.GetSection(SettingKeys.InstallationSection).GetValue(key, defaultValue);
|
||||||
|
// double fallback to default value - allow hold sample keys in config
|
||||||
|
if (string.IsNullOrEmpty(value)) value = defaultValue;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string NormalizeConnectionString(string connectionString)
|
||||||
|
{
|
||||||
|
var dataDirectory = AppDomain.CurrentDomain.GetData("DataDirectory")?.ToString();
|
||||||
|
connectionString = connectionString.Replace("|DataDirectory|", dataDirectory);
|
||||||
|
return connectionString;
|
||||||
|
}
|
||||||
|
|
||||||
private void SetValueRecursively<T>(string sectionPathKey, dynamic jsonObj, T value)
|
private void SetValueRecursively<T>(string sectionPathKey, dynamic jsonObj, T value)
|
||||||
{
|
{
|
||||||
// split the string at the first ':' character
|
// split the string at the first ':' character
|
||||||
|
@ -566,25 +633,27 @@ namespace Oqtane.Infrastructure
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetInstallationConfig(string key, string defaultValue)
|
public void UpdateConnectionString(string connectionString)
|
||||||
{
|
{
|
||||||
var value = _config.GetSection(SettingKeys.InstallationSection).GetValue(key, defaultValue);
|
connectionString = DenormalizeConnectionString(connectionString);
|
||||||
// double fallback to default value - allow hold sample keys in config
|
if (_config.GetConnectionString(SettingKeys.ConnectionStringKey) != connectionString)
|
||||||
if (string.IsNullOrEmpty(value)) value = defaultValue;
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void MigrateScriptNamingConvention(string scriptType, string connectionString)
|
|
||||||
{
|
|
||||||
// migrate to new naming convention for scripts
|
|
||||||
var migrateConfig = DeployChanges.To.SqlDatabase(NormalizeConnectionString(connectionString))
|
|
||||||
.WithScriptsEmbeddedInAssembly(Assembly.GetExecutingAssembly(), s => s == scriptType + ".00.00.00.00.sql");
|
|
||||||
var migrate = migrateConfig.Build();
|
|
||||||
if (migrate.IsUpgradeRequired())
|
|
||||||
{
|
{
|
||||||
migrate.PerformUpgrade();
|
AddOrUpdateAppSetting($"{SettingKeys.ConnectionStringsSection}:{SettingKeys.ConnectionStringKey}", connectionString);
|
||||||
|
_config.Reload();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void UpdateDatabaseType(string databaseType)
|
||||||
|
{
|
||||||
|
AddOrUpdateAppSetting($"{SettingKeys.DatabaseSection}:{SettingKeys.DatabaseTypeKey}", databaseType);
|
||||||
|
_config.Reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpgradeSqlServer(ISqlRepository sql, string connectionString, bool isMaster)
|
||||||
|
{
|
||||||
|
var script = (isMaster) ? "MigrateMaster.sql" : "MigrateTenant.sql";
|
||||||
|
|
||||||
|
sql.ExecuteScript(connectionString, Assembly.GetExecutingAssembly(), script);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.Extensions.Caching.Memory;
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using Oqtane.Shared;
|
using Oqtane.Shared;
|
||||||
|
// ReSharper disable AssignNullToNotNullAttribute
|
||||||
|
|
||||||
namespace Oqtane.Infrastructure
|
namespace Oqtane.Infrastructure
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
using Oqtane.Models;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Oqtane.Enums;
|
||||||
|
using Oqtane.Models;
|
||||||
|
|
||||||
namespace Oqtane.Infrastructure
|
namespace Oqtane.Infrastructure
|
||||||
{
|
{
|
||||||
public interface IInstallable
|
public interface IInstallable
|
||||||
{
|
{
|
||||||
bool Install(Tenant tenant, string version);
|
bool Install(Tenant tenant, string version);
|
||||||
|
|
||||||
bool Uninstall(Tenant tenant);
|
bool Uninstall(Tenant tenant);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
65
Oqtane.Server/Migrations/01000000_InitializeMaster.cs
Normal file
65
Oqtane.Server/Migrations/01000000_InitializeMaster.cs
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
using Oqtane.Migrations.EntityBuilders;
|
||||||
|
using Oqtane.Repository;
|
||||||
|
|
||||||
|
namespace Oqtane.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(MasterDBContext))]
|
||||||
|
[Migration("Master.01.00.00.00")]
|
||||||
|
public class InitializeMaster : MultiDatabaseMigration
|
||||||
|
{
|
||||||
|
public InitializeMaster(IEnumerable<IOqtaneDatabase> databases) : base(databases)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
//Create Tenant table
|
||||||
|
var tenantEntityBuilder = new TenantEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
tenantEntityBuilder.Create();
|
||||||
|
|
||||||
|
//Create Alias table
|
||||||
|
var aliasEntityBuilder = new AliasEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
aliasEntityBuilder.Create();
|
||||||
|
|
||||||
|
//Create ModuleDefinitions Table
|
||||||
|
var moduleDefinitionsEntityBuilder = new ModuleDefinitionsEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
moduleDefinitionsEntityBuilder.Create();
|
||||||
|
|
||||||
|
//Create Job Table
|
||||||
|
var jobEntityBuilder = new JobEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
jobEntityBuilder.Create();
|
||||||
|
|
||||||
|
//Create JobLog Table
|
||||||
|
var jobLogEntityBuilder = new JobLogEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
jobLogEntityBuilder.Create();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
//Drop Alias table
|
||||||
|
var aliasEntityBuilder = new AliasEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
aliasEntityBuilder.Drop();
|
||||||
|
|
||||||
|
//Drop JobLog Table
|
||||||
|
var jobLogEntityBuilder = new JobLogEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
jobLogEntityBuilder.Drop();
|
||||||
|
|
||||||
|
//Drop Tenant table
|
||||||
|
var tenantEntityBuilder = new TenantEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
tenantEntityBuilder.Drop();
|
||||||
|
|
||||||
|
//Drop ModuleDefinitions Table
|
||||||
|
var moduleDefinitionsEntityBuilder = new ModuleDefinitionsEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
moduleDefinitionsEntityBuilder.Drop();
|
||||||
|
|
||||||
|
//Drop Job Table
|
||||||
|
var jobEntityBuilder = new JobEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
jobEntityBuilder.Drop();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
169
Oqtane.Server/Migrations/01000000_InitializeTenant.cs
Normal file
169
Oqtane.Server/Migrations/01000000_InitializeTenant.cs
Normal file
|
@ -0,0 +1,169 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
using Oqtane.Migrations.EntityBuilders;
|
||||||
|
using Oqtane.Repository;
|
||||||
|
|
||||||
|
|
||||||
|
namespace Oqtane.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(TenantDBContext))]
|
||||||
|
[Migration("Tenant.01.00.00.00")]
|
||||||
|
public class InitializeTenant : MultiDatabaseMigration
|
||||||
|
{
|
||||||
|
public InitializeTenant(IEnumerable<IOqtaneDatabase> databases) : base(databases)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
//Create Site table
|
||||||
|
var siteEntityBuilder = new SiteEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
siteEntityBuilder.Create();
|
||||||
|
|
||||||
|
//Create Page table
|
||||||
|
var pageEntityBuilder = new PageEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
pageEntityBuilder.Create();
|
||||||
|
pageEntityBuilder.AddIndex("IX_Page", new [] {"SiteId", "Path", "UserId"}, true);
|
||||||
|
|
||||||
|
//Add Column to Page table (for Sql Server only) we will drop it later for Sql Server only
|
||||||
|
if (ActiveDatabase.Name == "SqlServer" || ActiveDatabase.Name == "LocalDB")
|
||||||
|
{
|
||||||
|
pageEntityBuilder.AddBooleanColumn("EditMode");
|
||||||
|
}
|
||||||
|
|
||||||
|
//Create Module table
|
||||||
|
var moduleEntityBuilder = new ModuleEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
moduleEntityBuilder.Create();
|
||||||
|
|
||||||
|
//Create PageModule table
|
||||||
|
var pageModuleEntityBuilder = new PageModuleEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
pageModuleEntityBuilder.Create();
|
||||||
|
|
||||||
|
//Create User table
|
||||||
|
var userEntityBuilder = new UserEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
userEntityBuilder.Create();
|
||||||
|
userEntityBuilder.AddIndex("IX_User", "Username", true);
|
||||||
|
|
||||||
|
//Create Role table
|
||||||
|
var roleEntityBuilder = new RoleEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
roleEntityBuilder.Create();
|
||||||
|
|
||||||
|
//Create UserRole table
|
||||||
|
var userRoleEntityBuilder = new UserRoleEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
userRoleEntityBuilder.Create();
|
||||||
|
userRoleEntityBuilder.AddIndex("IX_UserRole", new [] {"RoleId", "UserId"}, true);
|
||||||
|
|
||||||
|
//Create Permission table
|
||||||
|
var permissionEntityBuilder = new PermissionEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
permissionEntityBuilder.Create();
|
||||||
|
permissionEntityBuilder.AddIndex("IX_Permission", new [] {"SiteId", "EntityName", "EntityId", "PermissionName", "RoleId", "UserId"}, true);
|
||||||
|
|
||||||
|
//Create Setting table
|
||||||
|
var settingEntityBuilder = new SettingEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
settingEntityBuilder.Create();
|
||||||
|
settingEntityBuilder.AddIndex("IX_Setting", new [] {"EntityName", "EntityId", "SettingName"}, true);
|
||||||
|
|
||||||
|
//Create Profile table
|
||||||
|
var profileEntityBuilder = new ProfileEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
profileEntityBuilder.Create();
|
||||||
|
|
||||||
|
//Create Log table
|
||||||
|
var logEntityBuilder = new LogEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
logEntityBuilder.Create();
|
||||||
|
|
||||||
|
//Create Notification table
|
||||||
|
var notificationEntityBuilder = new NotificationEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
notificationEntityBuilder.Create();
|
||||||
|
|
||||||
|
//Create Folder table
|
||||||
|
var folderEntityBuilder = new FolderEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
folderEntityBuilder.Create();
|
||||||
|
folderEntityBuilder.AddIndex("IX_Folder", new [] {"SiteId", "Path"}, true);
|
||||||
|
|
||||||
|
//Create File table
|
||||||
|
var fileEntityBuilder = new FileEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
fileEntityBuilder.Create();
|
||||||
|
|
||||||
|
//Create AspNetUsers table
|
||||||
|
var aspNetUsersEntityBuilder = new AspNetUsersEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
aspNetUsersEntityBuilder.Create();
|
||||||
|
aspNetUsersEntityBuilder.AddIndex("EmailIndex", "NormalizedEmail", true);
|
||||||
|
aspNetUsersEntityBuilder.AddIndex("UserNameIndex", "NormalizedUserName", true);
|
||||||
|
|
||||||
|
//Create AspNetUserClaims table
|
||||||
|
var aspNetUserClaimsEntityBuilder = new AspNetUserClaimsEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
aspNetUserClaimsEntityBuilder.Create();
|
||||||
|
aspNetUserClaimsEntityBuilder.AddIndex("IX_AspNetUserClaims_UserId", "UserId", true);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
//Drop AspNetUserClaims table
|
||||||
|
var aspNetUserClaimsEntityBuilder = new AspNetUserClaimsEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
aspNetUserClaimsEntityBuilder.Drop();
|
||||||
|
|
||||||
|
//Drop AspNetUsers table
|
||||||
|
var aspNetUsersEntityBuilder = new AspNetUsersEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
aspNetUsersEntityBuilder.Drop();
|
||||||
|
|
||||||
|
//Drop File table
|
||||||
|
var fileEntityBuilder = new FileEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
fileEntityBuilder.Drop();
|
||||||
|
|
||||||
|
//Drop Folder table
|
||||||
|
var folderEntityBuilder = new FolderEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
folderEntityBuilder.Drop();
|
||||||
|
|
||||||
|
//Drop Notification table
|
||||||
|
var notificationEntityBuilder = new NotificationEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
notificationEntityBuilder.Drop();
|
||||||
|
|
||||||
|
//Drop Log table
|
||||||
|
var logEntityBuilder = new LogEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
logEntityBuilder.Drop();
|
||||||
|
|
||||||
|
//Drop Profile table
|
||||||
|
var profileEntityBuilder = new ProfileEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
profileEntityBuilder.Drop();
|
||||||
|
|
||||||
|
//Drop Setting table
|
||||||
|
var settingEntityBuilder = new SettingEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
settingEntityBuilder.Drop();
|
||||||
|
|
||||||
|
//Drop Permission table
|
||||||
|
var permissionEntityBuilder = new PermissionEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
permissionEntityBuilder.Drop();
|
||||||
|
|
||||||
|
//Drop UserRole table
|
||||||
|
var userRoleEntityBuilder = new UserRoleEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
userRoleEntityBuilder.Drop();
|
||||||
|
|
||||||
|
//Drop Role table
|
||||||
|
var roleEntityBuilder = new RoleEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
roleEntityBuilder.Drop();
|
||||||
|
|
||||||
|
//Drop User table
|
||||||
|
var userEntityBuilder = new UserEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
userEntityBuilder.Drop();
|
||||||
|
|
||||||
|
//Drop PageModule table
|
||||||
|
var pageModuleEntityBuilder = new PageModuleEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
pageModuleEntityBuilder.Drop();
|
||||||
|
|
||||||
|
//Drop Module table
|
||||||
|
var moduleEntityBuilder = new ModuleEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
moduleEntityBuilder.Drop();
|
||||||
|
|
||||||
|
//Drop Page table
|
||||||
|
var pageEntityBuilder = new PageEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
pageEntityBuilder.Drop();
|
||||||
|
|
||||||
|
//Drop Site table
|
||||||
|
var siteEntityBuilder = new SiteEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
siteEntityBuilder.Drop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
using Oqtane.Migrations.EntityBuilders;
|
||||||
|
using Oqtane.Repository;
|
||||||
|
|
||||||
|
namespace Oqtane.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(MasterDBContext))]
|
||||||
|
[Migration("Master.01.00.01.00")]
|
||||||
|
public class AddAdditionalIndexesInMaster : MultiDatabaseMigration
|
||||||
|
{
|
||||||
|
public AddAdditionalIndexesInMaster(IEnumerable<IOqtaneDatabase> databases) : base(databases)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
//Update Tenant table
|
||||||
|
var tenantEntityBuilder = new TenantEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
tenantEntityBuilder.AddIndex("IX_Tenant", "Name");
|
||||||
|
|
||||||
|
//Update Alias table
|
||||||
|
var aliasEntityBuilder = new AliasEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
aliasEntityBuilder.AddIndex("IX_Alias", "Name");
|
||||||
|
|
||||||
|
//Update ModuleDefinitions Table
|
||||||
|
var moduleDefinitionsEntityBuilder = new ModuleDefinitionsEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
moduleDefinitionsEntityBuilder.AddIndex("IX_ModuleDefinition", "ModuleDefinitionName");
|
||||||
|
|
||||||
|
//Update Job Table
|
||||||
|
var jobEntityBuilder = new JobEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
jobEntityBuilder.AddIndex("IX_Job", "JobType");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
//Update Tenant table
|
||||||
|
var tenantEntityBuilder = new TenantEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
tenantEntityBuilder.DropIndex("IX_Tenant");
|
||||||
|
|
||||||
|
//Update Alias table
|
||||||
|
var aliasEntityBuilder = new AliasEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
aliasEntityBuilder.DropIndex("IX_Alias");
|
||||||
|
|
||||||
|
//Update ModuleDefinitions Table
|
||||||
|
var moduleDefinitionsEntityBuilder = new ModuleDefinitionsEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
moduleDefinitionsEntityBuilder.DropIndex("IX_ModuleDefinition");
|
||||||
|
|
||||||
|
//Update Job Table
|
||||||
|
var jobEntityBuilder = new JobEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
jobEntityBuilder.DropIndex("IX_Job");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
using Oqtane.Migrations.EntityBuilders;
|
||||||
|
using Oqtane.Repository;
|
||||||
|
|
||||||
|
namespace Oqtane.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(TenantDBContext))]
|
||||||
|
[Migration("Tenant.01.00.01.00")]
|
||||||
|
public class AddAdditionalIndexesInTenant : MultiDatabaseMigration
|
||||||
|
{
|
||||||
|
public AddAdditionalIndexesInTenant(IEnumerable<IOqtaneDatabase> databases) : base(databases)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
//Create Index on Site
|
||||||
|
var siteEntityBuilder = new SiteEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
siteEntityBuilder.AddIndex("IX_Site", new [] {"TenantId", "Name"}, true);
|
||||||
|
|
||||||
|
//Create Index on Role table
|
||||||
|
var roleEntityBuilder = new RoleEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
roleEntityBuilder.AddIndex("IX_Role", new [] {"SiteId", "Name"}, true);
|
||||||
|
|
||||||
|
//Create Index on Profile table
|
||||||
|
var profileEntityBuilder = new ProfileEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
profileEntityBuilder.AddIndex("IX_Profile", new [] {"SiteId", "Name"}, true);
|
||||||
|
|
||||||
|
//Create Index on File table
|
||||||
|
var fileEntityBuilder = new FileEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
fileEntityBuilder.AddIndex("IX_File", new [] {"FolderId", "Name"}, true);
|
||||||
|
|
||||||
|
//Add Columns to Notification table
|
||||||
|
var notificationEntityBuilder = new NotificationEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
notificationEntityBuilder.AddStringColumn("FromDisplayName", 50, true);
|
||||||
|
notificationEntityBuilder.AddStringColumn("FromEmail", 256, true);
|
||||||
|
notificationEntityBuilder.AddStringColumn("ToDisplayName", 50, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
//Drop Index on Site table
|
||||||
|
var siteEntityBuilder = new SiteEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
siteEntityBuilder.DropIndex("IX_Site");
|
||||||
|
|
||||||
|
//Drop Index on Role table
|
||||||
|
var roleEntityBuilder = new RoleEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
roleEntityBuilder.DropIndex("IX_Role");
|
||||||
|
|
||||||
|
//Drop Index on Profile table
|
||||||
|
var profileEntityBuilder = new ProfileEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
profileEntityBuilder.DropIndex("IX_Profile");
|
||||||
|
|
||||||
|
//Drop Index on File table
|
||||||
|
var fileEntityBuilder = new FileEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
fileEntityBuilder.DropIndex("IX_File");
|
||||||
|
|
||||||
|
//Drop Columns from Notification table
|
||||||
|
var notificationEntityBuilder = new NotificationEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
notificationEntityBuilder.DropColumn("FromDisplayName");
|
||||||
|
notificationEntityBuilder.DropColumn("FromEmail");
|
||||||
|
notificationEntityBuilder.DropColumn("ToDisplayName");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
using Oqtane.Migrations.EntityBuilders;
|
||||||
|
using Oqtane.Repository;
|
||||||
|
|
||||||
|
namespace Oqtane.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(TenantDBContext))]
|
||||||
|
[Migration("Tenant.01.00.01.01")]
|
||||||
|
public class AddAdditionColumnToNotifications : MultiDatabaseMigration
|
||||||
|
{
|
||||||
|
public AddAdditionColumnToNotifications(IEnumerable<IOqtaneDatabase> databases) : base(databases)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
//Add Column to Notification table
|
||||||
|
var notificationEntityBuilder = new NotificationEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
notificationEntityBuilder.AddDateTimeColumn("SendOn", true);
|
||||||
|
|
||||||
|
//Update new Column
|
||||||
|
notificationEntityBuilder.UpdateColumn("SendOn", $"{ActiveDatabase.RewriteName("CreatedOn")}", $"{ActiveDatabase.RewriteName("SendOn")} IS NULL");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
//Drop Column from Notification table
|
||||||
|
var notificationEntityBuilder = new NotificationEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
notificationEntityBuilder.DropColumn("SendOn");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
35
Oqtane.Server/Migrations/01000201_DropColumnFromPage.cs
Normal file
35
Oqtane.Server/Migrations/01000201_DropColumnFromPage.cs
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
using Oqtane.Migrations.EntityBuilders;
|
||||||
|
using Oqtane.Repository;
|
||||||
|
|
||||||
|
namespace Oqtane.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(TenantDBContext))]
|
||||||
|
[Migration("Tenant.01.00.02.01")]
|
||||||
|
public class DropColumnFromPage : MultiDatabaseMigration
|
||||||
|
{
|
||||||
|
public DropColumnFromPage(IEnumerable<IOqtaneDatabase> databases) : base(databases)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
//Drop Column from Page table
|
||||||
|
if (ActiveDatabase.Name == "SqlServer" || ActiveDatabase.Name == "LocalDB")
|
||||||
|
{
|
||||||
|
var pageEntityBuilder = new PageEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
pageEntityBuilder.DropColumn("EditMode");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
//Add Column to Page table
|
||||||
|
var pageEntityBuilder = new PageEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
pageEntityBuilder.AddBooleanColumn("EditMode");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
using Oqtane.Migrations.EntityBuilders;
|
||||||
|
using Oqtane.Repository;
|
||||||
|
|
||||||
|
namespace Oqtane.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(TenantDBContext))]
|
||||||
|
[Migration("Tenant.02.00.00.01")]
|
||||||
|
public class AddColumnToProfileAndUpdatePage : MultiDatabaseMigration
|
||||||
|
{
|
||||||
|
public AddColumnToProfileAndUpdatePage(IEnumerable<IOqtaneDatabase> databases) : base(databases)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
//Add Column to Profile table
|
||||||
|
var profileEntityBuilder = new ProfileEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
profileEntityBuilder.AddStringColumn("Options", 2000, true);
|
||||||
|
|
||||||
|
//Update new column
|
||||||
|
profileEntityBuilder.UpdateColumn("Options", "''");
|
||||||
|
|
||||||
|
//Alter Column in Page table for Sql Server
|
||||||
|
if (ActiveDatabase.Name == "SqlServer" || ActiveDatabase.Name == "LocalDB")
|
||||||
|
{
|
||||||
|
var pageEntityBuilder = new PageEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
pageEntityBuilder.DropIndex("IX_Page");
|
||||||
|
pageEntityBuilder.AlterStringColumn("Path", 256);
|
||||||
|
pageEntityBuilder.AddIndex("IX_Page", new [] {"SiteId", "Path", "UserId"}, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
//Drop Column from Profile table
|
||||||
|
var profileEntityBuilder = new ProfileEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
profileEntityBuilder.DropColumn("Options");
|
||||||
|
|
||||||
|
//Alter Column in Page table
|
||||||
|
if (ActiveDatabase.Name == "SqlServer" || ActiveDatabase.Name == "LocalDB")
|
||||||
|
{
|
||||||
|
var pageEntityBuilder = new PageEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
pageEntityBuilder.DropIndex("IX_Page");
|
||||||
|
pageEntityBuilder.AlterStringColumn("Path", 50);
|
||||||
|
pageEntityBuilder.AddIndex("IX_Page", new [] {"SiteId", "Path", "UserId"}, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
26
Oqtane.Server/Migrations/02000101_UpdateIconColumnInPage.cs
Normal file
26
Oqtane.Server/Migrations/02000101_UpdateIconColumnInPage.cs
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
using Oqtane.Migrations.EntityBuilders;
|
||||||
|
using Oqtane.Repository;
|
||||||
|
|
||||||
|
namespace Oqtane.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(TenantDBContext))]
|
||||||
|
[Migration("Tenant.02.00.01.01")]
|
||||||
|
public class UpdateIconColumnInPage : MultiDatabaseMigration
|
||||||
|
{
|
||||||
|
public UpdateIconColumnInPage(IEnumerable<IOqtaneDatabase> databases) : base(databases)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
///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")} <> ''" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
32
Oqtane.Server/Migrations/02000102_AddLanguageTable.cs
Normal file
32
Oqtane.Server/Migrations/02000102_AddLanguageTable.cs
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
using Oqtane.Migrations.EntityBuilders;
|
||||||
|
using Oqtane.Repository;
|
||||||
|
|
||||||
|
namespace Oqtane.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(TenantDBContext))]
|
||||||
|
[Migration("Tenant.02.00.01.02")]
|
||||||
|
public class AddLanguageTable : MultiDatabaseMigration
|
||||||
|
{
|
||||||
|
public AddLanguageTable(IEnumerable<IOqtaneDatabase> databases) : base(databases)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
//Create Language table
|
||||||
|
var languageEntityBuilder = new LanguageEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
languageEntityBuilder.Create();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
//Drop Language table
|
||||||
|
var languageEntityBuilder = new LanguageEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
languageEntityBuilder.Drop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
using Oqtane.Migrations.EntityBuilders;
|
||||||
|
using Oqtane.Repository;
|
||||||
|
|
||||||
|
namespace Oqtane.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(TenantDBContext))]
|
||||||
|
[Migration("Tenant.02.00.01.03")]
|
||||||
|
public class UpdatePageAndAddColumnToSite : MultiDatabaseMigration
|
||||||
|
{
|
||||||
|
public UpdatePageAndAddColumnToSite(IEnumerable<IOqtaneDatabase> databases) : base(databases)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
//Add Column to Site table
|
||||||
|
var siteEntityBuilder = new SiteEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
siteEntityBuilder.AddStringColumn("AdminContainerType", 200, true);
|
||||||
|
|
||||||
|
//Update new column
|
||||||
|
siteEntityBuilder.UpdateColumn("AdminContainerType", "''");
|
||||||
|
|
||||||
|
|
||||||
|
//Delete records from Page
|
||||||
|
var pageEntityBuilder = new PageEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
pageEntityBuilder.DeleteFromTable($"{ActiveDatabase.RewriteName("Path")} = 'admin/tenants'");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
//Drop Column from Site table
|
||||||
|
var siteEntityBuilder = new SiteEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
siteEntityBuilder.DropColumn("AdminContainerType");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
34
Oqtane.Server/Migrations/02000201_AddSiteGuidToSite.cs
Normal file
34
Oqtane.Server/Migrations/02000201_AddSiteGuidToSite.cs
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
using Oqtane.Migrations.EntityBuilders;
|
||||||
|
using Oqtane.Repository;
|
||||||
|
|
||||||
|
namespace Oqtane.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(TenantDBContext))]
|
||||||
|
[Migration("Tenant.02.00.02.01")]
|
||||||
|
|
||||||
|
public class AddSiteGuidToSite : MultiDatabaseMigration
|
||||||
|
{
|
||||||
|
public AddSiteGuidToSite(IEnumerable<IOqtaneDatabase> databases) : base(databases)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
//Add Column to Site table
|
||||||
|
var siteEntityBuilder = new SiteEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
siteEntityBuilder.AddStringColumn("SiteGuid", 36, true, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
//Drop Column from Site table
|
||||||
|
var siteEntityBuilder = new SiteEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
siteEntityBuilder.DropColumn("SiteGuid");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
using Oqtane.Migrations.EntityBuilders;
|
||||||
|
using Oqtane.Repository;
|
||||||
|
|
||||||
|
namespace Oqtane.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(TenantDBContext))]
|
||||||
|
[Migration("Tenant.02.01.00.00")]
|
||||||
|
|
||||||
|
public class AddAppVersionsTable : MultiDatabaseMigration
|
||||||
|
{
|
||||||
|
public AddAppVersionsTable(IEnumerable<IOqtaneDatabase> databases) : base(databases)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
//Create AppVersions table
|
||||||
|
var appVersionsEntityBuilder = new AppVersionsEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
appVersionsEntityBuilder.Create();
|
||||||
|
|
||||||
|
//Finish SqlServer Migration from DbUp
|
||||||
|
if (ActiveDatabase.Name == "SqlServer" || ActiveDatabase.Name == "LocalDB")
|
||||||
|
{
|
||||||
|
//Version 1.0.0
|
||||||
|
InsertVersion(migrationBuilder, "01.00.00", "Oqtane.Scripts.Master.00.09.00.00.sql");
|
||||||
|
|
||||||
|
//Version 1.0.1
|
||||||
|
InsertVersion(migrationBuilder, "01.00.01", "Oqtane.Scripts.Master.01.00.01.00.sql");
|
||||||
|
|
||||||
|
//Version 1.0.2
|
||||||
|
InsertVersion(migrationBuilder, "01.00.02", "Oqtane.Scripts.Tenant.01.00.02.01.sql");
|
||||||
|
|
||||||
|
//Version 2.0.0
|
||||||
|
InsertVersion(migrationBuilder, "02.00.00", "Oqtane.Scripts.Tenant.02.00.00.01.sql");
|
||||||
|
|
||||||
|
//Version 2.0.1
|
||||||
|
InsertVersion(migrationBuilder, "02.00.01", "Oqtane.Scripts.Tenant.02.00.01.03.sql");
|
||||||
|
|
||||||
|
//Version 2.0.2
|
||||||
|
InsertVersion(migrationBuilder, "02.00.02", "Oqtane.Scripts.Tenant.02.00.02.01.sql");
|
||||||
|
|
||||||
|
//Drop SchemaVersions
|
||||||
|
migrationBuilder.Sql(@"
|
||||||
|
IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'dbo.SchemaVersions') AND OBJECTPROPERTY(id, N'IsTable') = 1)
|
||||||
|
BEGIN
|
||||||
|
DROP TABLE SchemaVersions
|
||||||
|
END");
|
||||||
|
}
|
||||||
|
|
||||||
|
//Version 2.1.0
|
||||||
|
var appVersions = RewriteName("AppVersions");
|
||||||
|
var version = RewriteName("Version");
|
||||||
|
var appledDate = RewriteName("AppliedDate");
|
||||||
|
|
||||||
|
migrationBuilder.Sql($@"
|
||||||
|
INSERT INTO {appVersions}({version}, {appledDate})
|
||||||
|
VALUES('02.01.00', '{DateTime.UtcNow:u}')
|
||||||
|
");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InsertVersion(MigrationBuilder migrationBuilder, string version, string scriptName)
|
||||||
|
{
|
||||||
|
migrationBuilder.Sql($@"
|
||||||
|
IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'dbo.SchemaVersions') AND OBJECTPROPERTY(id, N'IsTable') = 1)
|
||||||
|
BEGIN
|
||||||
|
INSERT INTO AppVersions(Version, AppliedDate)
|
||||||
|
SELECT Version = '{version}', Applied As AppliedDate
|
||||||
|
FROM SchemaVersions
|
||||||
|
WHERE ScriptName = '{scriptName}'
|
||||||
|
END
|
||||||
|
");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
using Oqtane.Migrations.EntityBuilders;
|
||||||
|
using Oqtane.Repository;
|
||||||
|
|
||||||
|
namespace Oqtane.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(MasterDBContext))]
|
||||||
|
[Migration("Master.02.01.00.00")]
|
||||||
|
public class AddIndexesForForeignKeyInMaster : MultiDatabaseMigration
|
||||||
|
{
|
||||||
|
public AddIndexesForForeignKeyInMaster(IEnumerable<IOqtaneDatabase> databases) : base(databases)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
//Update JobLog table
|
||||||
|
var jobLogEntityBuilder = new JobLogEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
jobLogEntityBuilder.AddIndex("IX_JobLog_JobId", "JobId");
|
||||||
|
|
||||||
|
//Update Alias table
|
||||||
|
var aliasEntityBuilder = new AliasEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
aliasEntityBuilder.AddIndex("IX_Alias_TenantId", "TenantId");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
//Update JobLog table
|
||||||
|
var jobLogEntityBuilder = new JobLogEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
jobLogEntityBuilder.DropIndex("IX_JobLog_JobId");
|
||||||
|
|
||||||
|
//Update Alias table
|
||||||
|
var aliasEntityBuilder = new AliasEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
aliasEntityBuilder.DropIndex("IX_Alias_TenantId");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
using Oqtane.Migrations.EntityBuilders;
|
||||||
|
using Oqtane.Repository;
|
||||||
|
|
||||||
|
namespace Oqtane.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(MasterDBContext))]
|
||||||
|
[Migration("Master.02.01.00.01")]
|
||||||
|
public class AddDatabaseTypeColumnToTenant : MultiDatabaseMigration
|
||||||
|
{
|
||||||
|
public AddDatabaseTypeColumnToTenant(IEnumerable<IOqtaneDatabase> databases) : base(databases)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
//Add Column to Site table
|
||||||
|
var tenantEntityBuilder = new TenantEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
tenantEntityBuilder.AddStringColumn("DBType", 200, true);
|
||||||
|
|
||||||
|
//Update new column if SqlServer (Other Databases will not have any records yet)
|
||||||
|
if (ActiveDatabase.Name == "SqlServer" || ActiveDatabase.Name == "LocalDB")
|
||||||
|
{
|
||||||
|
tenantEntityBuilder.UpdateColumn("DBType", "'SqlServer'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
|
||||||
|
// ReSharper disable MemberCanBePrivate.Global
|
||||||
|
// ReSharper disable UnusedAutoPropertyAccessor.Global
|
||||||
|
|
||||||
|
namespace Oqtane.Migrations.EntityBuilders
|
||||||
|
{
|
||||||
|
public class AliasEntityBuilder : AuditableBaseEntityBuilder<AliasEntityBuilder>
|
||||||
|
{
|
||||||
|
private const string _entityTableName = "Alias";
|
||||||
|
private readonly PrimaryKey<AliasEntityBuilder> _primaryKey = new("PK_Alias", x => x.AliasId);
|
||||||
|
private readonly ForeignKey<AliasEntityBuilder> _tenantForeignKey = new("FK_Alias_Tenant", x => x.TenantId, "Tenant", "TenantId", ReferentialAction.Cascade);
|
||||||
|
|
||||||
|
public AliasEntityBuilder(MigrationBuilder migrationBuilder, IOqtaneDatabase database) : base(migrationBuilder, database)
|
||||||
|
{
|
||||||
|
EntityTableName = _entityTableName;
|
||||||
|
PrimaryKey = _primaryKey;
|
||||||
|
ForeignKeys.Add(_tenantForeignKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override AliasEntityBuilder BuildTable(ColumnsBuilder table)
|
||||||
|
{
|
||||||
|
AliasId = AddAutoIncrementColumn(table,"AliasId");
|
||||||
|
Name = AddStringColumn(table, "Name", 200);
|
||||||
|
TenantId = AddIntegerColumn(table, "TenantId");
|
||||||
|
SiteId = AddIntegerColumn(table, "SiteId");
|
||||||
|
|
||||||
|
AddAuditableColumns(table);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> AliasId { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> Name { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> SiteId { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> TenantId { get; private set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
|
||||||
|
namespace Oqtane.Migrations.EntityBuilders
|
||||||
|
{
|
||||||
|
public class AppVersionsEntityBuilder : BaseEntityBuilder<AppVersionsEntityBuilder>
|
||||||
|
{
|
||||||
|
private const string _entityTableName = "AppVersions";
|
||||||
|
private readonly PrimaryKey<AppVersionsEntityBuilder> _primaryKey = new("PK_AppVersions", x => x.Id);
|
||||||
|
|
||||||
|
public AppVersionsEntityBuilder(MigrationBuilder migrationBuilder, IOqtaneDatabase database) : base(migrationBuilder, database)
|
||||||
|
{
|
||||||
|
EntityTableName = _entityTableName;
|
||||||
|
PrimaryKey = _primaryKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override AppVersionsEntityBuilder BuildTable(ColumnsBuilder table)
|
||||||
|
{
|
||||||
|
Id = AddAutoIncrementColumn(table,"Id");
|
||||||
|
Version = AddStringColumn(table,"Version", 10);
|
||||||
|
AppliedDate = AddDateTimeColumn(table,"AppliedDate");
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> Id { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> Version { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> AppliedDate { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
|
||||||
|
// ReSharper disable MemberCanBePrivate.Global
|
||||||
|
// ReSharper disable UnusedAutoPropertyAccessor.Global
|
||||||
|
|
||||||
|
namespace Oqtane.Migrations.EntityBuilders
|
||||||
|
{
|
||||||
|
public class AspNetUserClaimsEntityBuilder : BaseEntityBuilder<AspNetUserClaimsEntityBuilder>
|
||||||
|
{
|
||||||
|
private const string _entityTableName = "AspNetUserClaims";
|
||||||
|
private readonly PrimaryKey<AspNetUserClaimsEntityBuilder> _primaryKey = new("PK_AspNetUserClaims", x => x.Id);
|
||||||
|
private readonly ForeignKey<AspNetUserClaimsEntityBuilder> _aspNetUsersForeignKey = new("FK_AspNetUserClaims_AspNetUsers_UserId", x => x.UserId, "AspNetUsers", "Id", ReferentialAction.Cascade);
|
||||||
|
|
||||||
|
public AspNetUserClaimsEntityBuilder(MigrationBuilder migrationBuilder, IOqtaneDatabase database) : base(migrationBuilder, database)
|
||||||
|
{
|
||||||
|
EntityTableName = _entityTableName;
|
||||||
|
PrimaryKey = _primaryKey;
|
||||||
|
ForeignKeys.Add(_aspNetUsersForeignKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override AspNetUserClaimsEntityBuilder BuildTable(ColumnsBuilder table)
|
||||||
|
{
|
||||||
|
Id = AddAutoIncrementColumn(table,"Id");
|
||||||
|
UserId = AddStringColumn(table,"UserId", 450);
|
||||||
|
ClaimType = AddMaxStringColumn(table,"ClaimType", true);
|
||||||
|
ClaimValue = AddMaxStringColumn(table,"ClaimValue", true);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> Id { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> UserId { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> ClaimType { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> ClaimValue { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
|
||||||
|
// ReSharper disable MemberCanBePrivate.Global
|
||||||
|
// ReSharper disable UnusedAutoPropertyAccessor.Global
|
||||||
|
|
||||||
|
namespace Oqtane.Migrations.EntityBuilders
|
||||||
|
{
|
||||||
|
public class AspNetUsersEntityBuilder : BaseEntityBuilder<AspNetUsersEntityBuilder>
|
||||||
|
{
|
||||||
|
private const string _entityTableName = "AspNetUsers";
|
||||||
|
private readonly PrimaryKey<AspNetUsersEntityBuilder> _primaryKey = new("PK_AspNetUsers", x => x.Id);
|
||||||
|
|
||||||
|
public AspNetUsersEntityBuilder(MigrationBuilder migrationBuilder, IOqtaneDatabase database) : base(migrationBuilder, database)
|
||||||
|
{
|
||||||
|
EntityTableName = _entityTableName;
|
||||||
|
PrimaryKey = _primaryKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override AspNetUsersEntityBuilder BuildTable(ColumnsBuilder table)
|
||||||
|
{
|
||||||
|
Id = AddStringColumn(table,"Id", 450);
|
||||||
|
UserName = AddStringColumn(table,"UserName", 256, true);
|
||||||
|
NormalizedUserName = AddStringColumn(table,"NormalizedUserName", 256, true);
|
||||||
|
Email = AddStringColumn(table,"Email", 256, true);
|
||||||
|
NormalizedEmail = AddStringColumn(table,"NormalizedEmail", 256, true);
|
||||||
|
EmailConfirmed = AddBooleanColumn(table,"EmailConfirmed");
|
||||||
|
PasswordHash = AddMaxStringColumn(table,"PasswordHash", true);
|
||||||
|
SecurityStamp = AddMaxStringColumn(table,"SecurityStamp", true);
|
||||||
|
ConcurrencyStamp = AddMaxStringColumn(table,"ConcurrencyStamp", true);
|
||||||
|
PhoneNumber = AddMaxStringColumn(table,"PhoneNumber", true);
|
||||||
|
PhoneNumberConfirmed = AddBooleanColumn(table,"PhoneNumberConfirmed");
|
||||||
|
TwoFactorEnabled = AddBooleanColumn(table,"TwoFactorEnabled");
|
||||||
|
LockoutEnd = AddDateTimeOffsetColumn(table,"LockoutEnd", true);
|
||||||
|
LockoutEnabled = AddBooleanColumn(table,"LockoutEnabled");
|
||||||
|
AccessFailedCount = AddIntegerColumn(table,"AccessFailedCount");
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> Id { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> UserName { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> NormalizedUserName { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> Email { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> NormalizedEmail { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> EmailConfirmed { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> PasswordHash { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> SecurityStamp { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> ConcurrencyStamp { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> PhoneNumber { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> PhoneNumberConfirmed { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> TwoFactorEnabled { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> LockoutEnd { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> LockoutEnabled { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> AccessFailedCount { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
|
||||||
|
// ReSharper disable UnusedAutoPropertyAccessor.Global
|
||||||
|
// ReSharper disable MemberCanBePrivate.Global
|
||||||
|
|
||||||
|
namespace Oqtane.Migrations.EntityBuilders
|
||||||
|
{
|
||||||
|
public abstract class AuditableBaseEntityBuilder<TEntityBuilder> : BaseEntityBuilder<TEntityBuilder> where TEntityBuilder : BaseEntityBuilder<TEntityBuilder>
|
||||||
|
{
|
||||||
|
protected AuditableBaseEntityBuilder(MigrationBuilder migrationBuilder, IOqtaneDatabase database) : base (migrationBuilder, database)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void AddAuditableColumns(ColumnsBuilder table)
|
||||||
|
{
|
||||||
|
CreatedBy = AddStringColumn(table,"CreatedBy", 256);
|
||||||
|
CreatedOn = AddDateTimeColumn(table,"CreatedOn");
|
||||||
|
ModifiedBy = AddStringColumn(table,"ModifiedBy", 256);
|
||||||
|
ModifiedOn = AddDateTimeColumn(table,"ModifiedOn");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> CreatedBy { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> CreatedOn { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> ModifiedBy { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> ModifiedOn { get; private set; }
|
||||||
|
}
|
||||||
|
}
|
242
Oqtane.Server/Migrations/EntityBuilders/BaseEntityBuilder.cs
Normal file
242
Oqtane.Server/Migrations/EntityBuilders/BaseEntityBuilder.cs
Normal file
|
@ -0,0 +1,242 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
// ReSharper disable BuiltInTypeReferenceStyleForMemberAccess
|
||||||
|
|
||||||
|
namespace Oqtane.Migrations.EntityBuilders
|
||||||
|
{
|
||||||
|
public abstract class BaseEntityBuilder<TEntityBuilder> where TEntityBuilder : BaseEntityBuilder<TEntityBuilder>
|
||||||
|
{
|
||||||
|
private readonly MigrationBuilder _migrationBuilder;
|
||||||
|
|
||||||
|
protected BaseEntityBuilder(MigrationBuilder migrationBuilder, IOqtaneDatabase database)
|
||||||
|
{
|
||||||
|
_migrationBuilder = migrationBuilder;
|
||||||
|
ActiveDatabase = database;
|
||||||
|
ForeignKeys = new List<ForeignKey<TEntityBuilder>>();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected IOqtaneDatabase ActiveDatabase { get; }
|
||||||
|
|
||||||
|
protected abstract TEntityBuilder BuildTable(ColumnsBuilder table);
|
||||||
|
|
||||||
|
protected string EntityTableName { get; init; }
|
||||||
|
|
||||||
|
protected PrimaryKey<TEntityBuilder> PrimaryKey { get; init; }
|
||||||
|
|
||||||
|
protected List<ForeignKey<TEntityBuilder>> ForeignKeys { get; }
|
||||||
|
|
||||||
|
private string RewriteName(string name)
|
||||||
|
{
|
||||||
|
return ActiveDatabase.RewriteName(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Column Operations
|
||||||
|
|
||||||
|
protected OperationBuilder<AddColumnOperation> AddAutoIncrementColumn(ColumnsBuilder table, string name)
|
||||||
|
{
|
||||||
|
return ActiveDatabase.AddAutoIncrementColumn(table, RewriteName(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddBooleanColumn(string name)
|
||||||
|
{
|
||||||
|
_migrationBuilder.AddColumn<bool>(RewriteName(name), RewriteName(EntityTableName));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected OperationBuilder<AddColumnOperation> AddBooleanColumn(ColumnsBuilder table, string name, bool nullable = false)
|
||||||
|
{
|
||||||
|
return table.Column<bool>(name: RewriteName(name), nullable: nullable);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddDateTimeColumn(string name, bool nullable = false)
|
||||||
|
{
|
||||||
|
_migrationBuilder.AddColumn<DateTime>(RewriteName(name), RewriteName(EntityTableName), nullable: nullable);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected OperationBuilder<AddColumnOperation> AddDateTimeColumn(ColumnsBuilder table, string name, bool nullable = false)
|
||||||
|
{
|
||||||
|
return table.Column<DateTime>(name: RewriteName(name), nullable: nullable);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddDateTimeOffsetColumn(string name, bool nullable = false)
|
||||||
|
{
|
||||||
|
_migrationBuilder.AddColumn<DateTimeOffset>(RewriteName(name), RewriteName(EntityTableName), nullable: nullable);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected OperationBuilder<AddColumnOperation> AddDateTimeOffsetColumn(ColumnsBuilder table, string name, bool nullable = false)
|
||||||
|
{
|
||||||
|
return table.Column<DateTimeOffset>(name: RewriteName(name), nullable: nullable);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddIntegerColumn(string name, bool nullable = false)
|
||||||
|
{
|
||||||
|
_migrationBuilder.AddColumn<int>(RewriteName(name), RewriteName(EntityTableName), nullable: nullable);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected OperationBuilder<AddColumnOperation> AddIntegerColumn(ColumnsBuilder table, string name, bool nullable = false)
|
||||||
|
{
|
||||||
|
return table.Column<int>(name: RewriteName(name), nullable: nullable);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddMaxStringColumn(string name, int length, bool nullable = false, bool unicode = true)
|
||||||
|
{
|
||||||
|
_migrationBuilder.AddColumn<string>(RewriteName(name), RewriteName(EntityTableName), nullable: nullable, unicode: unicode);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected OperationBuilder<AddColumnOperation> AddMaxStringColumn(ColumnsBuilder table, string name, bool nullable = false, bool unicode = true)
|
||||||
|
{
|
||||||
|
return table.Column<string>(name: RewriteName(name), nullable: nullable, unicode: unicode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddStringColumn(string name, int length, bool nullable = false, bool unicode = true)
|
||||||
|
{
|
||||||
|
_migrationBuilder.AddColumn<string>(RewriteName(name), RewriteName(EntityTableName), maxLength: length, nullable: nullable, unicode: unicode);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected OperationBuilder<AddColumnOperation> AddStringColumn(ColumnsBuilder table, string name, int length, bool nullable = false, bool unicode = true)
|
||||||
|
{
|
||||||
|
return table.Column<string>(name: RewriteName(name), maxLength: length, nullable: nullable, unicode: unicode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AlterStringColumn(string name, int length, bool nullable = false, bool unicode = true)
|
||||||
|
{
|
||||||
|
_migrationBuilder.AlterColumn<string>(RewriteName(name), RewriteName(EntityTableName), maxLength: length, nullable: nullable, unicode: unicode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DropColumn(string name)
|
||||||
|
{
|
||||||
|
_migrationBuilder.DropColumn(RewriteName(name), RewriteName(EntityTableName));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//Index Operations
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a Migration to add an Index to the Entity (table)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="indexName">The name of the Index to create</param>
|
||||||
|
/// <param name="columnName">The name of the column to add to the index</param>
|
||||||
|
/// <param name="isUnique">A flag that determines if the Index should be Unique</param>
|
||||||
|
public virtual void AddIndex(string indexName, string columnName, bool isUnique = false)
|
||||||
|
{
|
||||||
|
_migrationBuilder.CreateIndex(
|
||||||
|
name: RewriteName(indexName),
|
||||||
|
table: RewriteName(EntityTableName),
|
||||||
|
column: RewriteName(columnName),
|
||||||
|
unique: isUnique);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a Migration to add an Index to the Entity (table)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="indexName">The name of the Index to create</param>
|
||||||
|
/// <param name="columnNames">The names of the columns to add to the index</param>
|
||||||
|
/// <param name="isUnique">A flag that determines if the Index should be Unique</param>
|
||||||
|
public virtual void AddIndex(string indexName, string[] columnNames, bool isUnique = false)
|
||||||
|
{
|
||||||
|
_migrationBuilder.CreateIndex(
|
||||||
|
name: RewriteName(indexName),
|
||||||
|
table: RewriteName(EntityTableName),
|
||||||
|
columns: columnNames.Select(RewriteName).ToArray(),
|
||||||
|
unique: isUnique);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a Migration to drop an Index from the Entity (table)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="indexName">The name of the Index to drop</param>
|
||||||
|
public virtual void DropIndex(string indexName)
|
||||||
|
{
|
||||||
|
_migrationBuilder.DropIndex(RewriteName(indexName), RewriteName(EntityTableName));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Key Operations
|
||||||
|
|
||||||
|
private void AddKeys(CreateTableBuilder<TEntityBuilder> table)
|
||||||
|
{
|
||||||
|
AddPrimaryKey(table, PrimaryKey);
|
||||||
|
foreach (var foreignKey in ForeignKeys)
|
||||||
|
{
|
||||||
|
AddForeignKey(table, foreignKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddPrimaryKey(CreateTableBuilder<TEntityBuilder> table, PrimaryKey<TEntityBuilder> primaryKey)
|
||||||
|
{
|
||||||
|
table.PrimaryKey(RewriteName(primaryKey.Name), primaryKey.Columns);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddForeignKey(CreateTableBuilder<TEntityBuilder> table, ForeignKey<TEntityBuilder> foreignKey)
|
||||||
|
{
|
||||||
|
table.ForeignKey(
|
||||||
|
name: RewriteName(foreignKey.Name),
|
||||||
|
column: foreignKey.Column,
|
||||||
|
principalTable: RewriteName(foreignKey.PrincipalTable),
|
||||||
|
principalColumn: RewriteName(foreignKey.PrincipalColumn),
|
||||||
|
onDelete: foreignKey.OnDeleteAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DropForeignKey(ForeignKey<TEntityBuilder> foreignKey)
|
||||||
|
{
|
||||||
|
DropForeignKey(RewriteName(foreignKey.Name));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DropForeignKey(string keyName)
|
||||||
|
{
|
||||||
|
_migrationBuilder.DropForeignKey(RewriteName(keyName), RewriteName(EntityTableName));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Table Operations
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a Migration to Create the Entity (table)
|
||||||
|
/// </summary>
|
||||||
|
public void Create()
|
||||||
|
{
|
||||||
|
_migrationBuilder.CreateTable(RewriteName(EntityTableName), BuildTable, null, AddKeys);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a Migration to Drop the Entity (table)
|
||||||
|
/// </summary>
|
||||||
|
public void Drop()
|
||||||
|
{
|
||||||
|
_migrationBuilder.DropTable(RewriteName(EntityTableName));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//Sql Operations
|
||||||
|
|
||||||
|
public void DeleteFromTable(string condition = "")
|
||||||
|
{
|
||||||
|
var deleteSql = $"DELETE FROM {RewriteName(EntityTableName)} ";
|
||||||
|
|
||||||
|
if(!string.IsNullOrEmpty(condition))
|
||||||
|
{
|
||||||
|
deleteSql += $"WHERE {condition}";
|
||||||
|
}
|
||||||
|
_migrationBuilder.Sql(deleteSql);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateColumn(string columnName, string value, string condition = "")
|
||||||
|
{
|
||||||
|
var updateValue = value;
|
||||||
|
|
||||||
|
var updateSql = $"UPDATE {RewriteName(EntityTableName)} SET {RewriteName(columnName)} = {value} ";
|
||||||
|
|
||||||
|
if(!string.IsNullOrEmpty(condition))
|
||||||
|
{
|
||||||
|
updateSql += $"WHERE {condition}";
|
||||||
|
}
|
||||||
|
_migrationBuilder.Sql(updateSql);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
|
||||||
|
// ReSharper disable UnusedAutoPropertyAccessor.Global
|
||||||
|
// ReSharper disable MemberCanBePrivate.Global
|
||||||
|
|
||||||
|
namespace Oqtane.Migrations.EntityBuilders
|
||||||
|
{
|
||||||
|
public abstract class DeletableAuditableBaseEntityBuilder<TEntityBuilder> : AuditableBaseEntityBuilder<TEntityBuilder> where TEntityBuilder : BaseEntityBuilder<TEntityBuilder>
|
||||||
|
{
|
||||||
|
protected DeletableAuditableBaseEntityBuilder(MigrationBuilder migrationBuilder, IOqtaneDatabase database) : base(migrationBuilder, database)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void AddDeletableColumns(ColumnsBuilder table)
|
||||||
|
{
|
||||||
|
DeletedBy = AddStringColumn(table,"DeletedBy", 256, true);
|
||||||
|
DeletedOn = AddDateTimeColumn(table,"DeletedOn", true);
|
||||||
|
IsDeleted = AddBooleanColumn(table,"IsDeleted");
|
||||||
|
}
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> DeletedBy { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> DeletedOn { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> IsDeleted { get; private set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
|
||||||
|
// ReSharper disable UnusedAutoPropertyAccessor.Global
|
||||||
|
// ReSharper disable MemberCanBePrivate.Global
|
||||||
|
|
||||||
|
namespace Oqtane.Migrations.EntityBuilders
|
||||||
|
{
|
||||||
|
public abstract class DeletableBaseEntityBuilder<TEntityBuilder> : BaseEntityBuilder<TEntityBuilder> where TEntityBuilder : BaseEntityBuilder<TEntityBuilder>
|
||||||
|
{
|
||||||
|
protected DeletableBaseEntityBuilder(MigrationBuilder migrationBuilder, IOqtaneDatabase database) : base(migrationBuilder, database)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void AddDeletableColumns(ColumnsBuilder table)
|
||||||
|
{
|
||||||
|
DeletedBy = AddStringColumn(table,"DeletedBy", 256, true);
|
||||||
|
DeletedOn = AddDateTimeColumn(table,"DeletedOn", true);
|
||||||
|
IsDeleted = AddBooleanColumn(table,"IsDeleted");
|
||||||
|
}
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> DeletedBy { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> DeletedOn { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> IsDeleted { get; private set; }
|
||||||
|
}
|
||||||
|
}
|
54
Oqtane.Server/Migrations/EntityBuilders/FileEntityBuilder.cs
Normal file
54
Oqtane.Server/Migrations/EntityBuilders/FileEntityBuilder.cs
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
|
||||||
|
// ReSharper disable MemberCanBePrivate.Global
|
||||||
|
// ReSharper disable UnusedAutoPropertyAccessor.Global
|
||||||
|
|
||||||
|
namespace Oqtane.Migrations.EntityBuilders
|
||||||
|
{
|
||||||
|
public class FileEntityBuilder : DeletableAuditableBaseEntityBuilder<FileEntityBuilder>
|
||||||
|
{
|
||||||
|
private const string _entityTableName = "File";
|
||||||
|
private readonly PrimaryKey<FileEntityBuilder> _primaryKey = new("PK_File", x => x.FileId);
|
||||||
|
private readonly ForeignKey<FileEntityBuilder> _folderForeignKey = new("FK_File_Folder", x => x.FolderId, "Folder", "FolderId", ReferentialAction.Cascade);
|
||||||
|
|
||||||
|
public FileEntityBuilder(MigrationBuilder migrationBuilder, IOqtaneDatabase database) : base(migrationBuilder, database)
|
||||||
|
{
|
||||||
|
EntityTableName = _entityTableName;
|
||||||
|
PrimaryKey = _primaryKey;
|
||||||
|
ForeignKeys.Add(_folderForeignKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override FileEntityBuilder BuildTable(ColumnsBuilder table)
|
||||||
|
{
|
||||||
|
FileId = AddAutoIncrementColumn(table,"FileId");
|
||||||
|
FolderId = AddIntegerColumn(table,"FolderId");
|
||||||
|
Name = AddStringColumn(table,"Name", 50);
|
||||||
|
Extension = AddStringColumn(table,"Extension", 50);
|
||||||
|
Size = AddIntegerColumn(table,"Size");
|
||||||
|
ImageHeight = AddIntegerColumn(table,"ImageHeight");
|
||||||
|
ImageWidth = AddIntegerColumn(table,"ImageWidth");
|
||||||
|
|
||||||
|
AddAuditableColumns(table);
|
||||||
|
AddDeletableColumns(table);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> FileId { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> FolderId { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> Name { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> Extension { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> Size { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> ImageHeight { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> ImageWidth { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
|
||||||
|
// ReSharper disable MemberCanBePrivate.Global
|
||||||
|
// ReSharper disable UnusedAutoPropertyAccessor.Global
|
||||||
|
|
||||||
|
namespace Oqtane.Migrations.EntityBuilders
|
||||||
|
{
|
||||||
|
public class FolderEntityBuilder : DeletableAuditableBaseEntityBuilder<FolderEntityBuilder>
|
||||||
|
{
|
||||||
|
private const string _entityTableName = "Folder";
|
||||||
|
private readonly PrimaryKey<FolderEntityBuilder> _primaryKey = new("PK_Folder", x => x.FolderId);
|
||||||
|
private readonly ForeignKey<FolderEntityBuilder> _siteForeignKey = new("FK_Folder_Site", x => x.SiteId, "Site", "SiteId", ReferentialAction.Cascade);
|
||||||
|
|
||||||
|
public FolderEntityBuilder(MigrationBuilder migrationBuilder, IOqtaneDatabase database) : base(migrationBuilder, database)
|
||||||
|
{
|
||||||
|
EntityTableName = _entityTableName;
|
||||||
|
PrimaryKey = _primaryKey;
|
||||||
|
ForeignKeys.Add(_siteForeignKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override FolderEntityBuilder BuildTable(ColumnsBuilder table)
|
||||||
|
{
|
||||||
|
FolderId = AddAutoIncrementColumn(table,"FolderId");
|
||||||
|
SiteId = AddIntegerColumn(table,"SiteId");
|
||||||
|
ParentId = AddIntegerColumn(table,"ParentId", true);
|
||||||
|
Name = AddStringColumn(table,"Name", 50);
|
||||||
|
Path = AddStringColumn(table,"Path", 50);
|
||||||
|
Order = AddIntegerColumn(table,"Order");
|
||||||
|
IsSystem = AddBooleanColumn(table,"IsSystem");
|
||||||
|
|
||||||
|
AddAuditableColumns(table);
|
||||||
|
AddDeletableColumns(table);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> FolderId { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> SiteId { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> ParentId { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> Name { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> Path { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> Order { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> IsSystem { get; set; }
|
||||||
|
}
|
||||||
|
}
|
66
Oqtane.Server/Migrations/EntityBuilders/JobEntityBuilder.cs
Normal file
66
Oqtane.Server/Migrations/EntityBuilders/JobEntityBuilder.cs
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
|
||||||
|
// ReSharper disable MemberCanBePrivate.Global
|
||||||
|
// ReSharper disable UnusedAutoPropertyAccessor.Global
|
||||||
|
|
||||||
|
namespace Oqtane.Migrations.EntityBuilders
|
||||||
|
{
|
||||||
|
public class JobEntityBuilder : AuditableBaseEntityBuilder<JobEntityBuilder>
|
||||||
|
{
|
||||||
|
private const string _entityTableName = "Job";
|
||||||
|
private readonly PrimaryKey<JobEntityBuilder> _primaryKey = new("PK_Job", x => x.JobId);
|
||||||
|
|
||||||
|
public JobEntityBuilder(MigrationBuilder migrationBuilder, IOqtaneDatabase database) : base(migrationBuilder, database)
|
||||||
|
{
|
||||||
|
EntityTableName = _entityTableName;
|
||||||
|
PrimaryKey = _primaryKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override JobEntityBuilder BuildTable(ColumnsBuilder table)
|
||||||
|
{
|
||||||
|
JobId = AddAutoIncrementColumn(table,"JobId");
|
||||||
|
Name = AddStringColumn(table,"Name", 200);
|
||||||
|
JobType = AddStringColumn(table,"JobType", 200);
|
||||||
|
Frequency = AddStringColumn(table,"Frequency", 1);
|
||||||
|
Interval = AddIntegerColumn(table,"Interval");
|
||||||
|
StartDate = AddDateTimeColumn(table,"StartDate", true);
|
||||||
|
EndDate = AddDateTimeColumn(table,"EndDate", true);
|
||||||
|
IsEnabled = AddBooleanColumn(table,"IsEnabled");
|
||||||
|
IsStarted = AddBooleanColumn(table,"IsStarted");
|
||||||
|
IsExecuting = AddBooleanColumn(table,"IsExecuting");
|
||||||
|
NextExecution = AddDateTimeColumn(table,"NextExecution", true);
|
||||||
|
RetentionHistory = AddIntegerColumn(table,"RetentionHistory");
|
||||||
|
|
||||||
|
AddAuditableColumns(table);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> JobId { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> Name { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> JobType { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> Frequency { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> Interval { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> StartDate { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> EndDate { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> IsEnabled { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> IsStarted { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> IsExecuting { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> NextExecution { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> RetentionHistory { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
|
||||||
|
// ReSharper disable MemberCanBePrivate.Global
|
||||||
|
// ReSharper disable UnusedAutoPropertyAccessor.Global
|
||||||
|
|
||||||
|
namespace Oqtane.Migrations.EntityBuilders
|
||||||
|
{
|
||||||
|
public class JobLogEntityBuilder : BaseEntityBuilder<JobLogEntityBuilder>
|
||||||
|
{
|
||||||
|
private const string _entityTableName = "JobLog";
|
||||||
|
private readonly PrimaryKey<JobLogEntityBuilder> _primaryKey = new("PK_JobLog", x => x.JobLogId);
|
||||||
|
private readonly ForeignKey<JobLogEntityBuilder> _jobLogForeignKey = new("FK_JobLog_Job", x => x.JobId, "Job", "JobId", ReferentialAction.Cascade);
|
||||||
|
|
||||||
|
public JobLogEntityBuilder(MigrationBuilder migrationBuilder, IOqtaneDatabase database) : base(migrationBuilder, database)
|
||||||
|
{
|
||||||
|
EntityTableName = _entityTableName;
|
||||||
|
PrimaryKey = _primaryKey;
|
||||||
|
ForeignKeys.Add(_jobLogForeignKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override JobLogEntityBuilder BuildTable(ColumnsBuilder table)
|
||||||
|
{
|
||||||
|
JobLogId = AddAutoIncrementColumn(table,"JobLogId");
|
||||||
|
JobId = AddIntegerColumn(table,"JobId");
|
||||||
|
StartDate = AddDateTimeColumn(table,"StartDate");
|
||||||
|
FinishDate = AddDateTimeColumn(table,"FinishDate", true);
|
||||||
|
Succeeded = AddBooleanColumn(table,"Succeeded", true);
|
||||||
|
Notes = AddMaxStringColumn(table,"Notes", true);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> JobLogId { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> JobId { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> StartDate { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> FinishDate { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> Succeeded { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> Notes { get; private set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
|
||||||
|
// ReSharper disable MemberCanBePrivate.Global
|
||||||
|
// ReSharper disable UnusedAutoPropertyAccessor.Global
|
||||||
|
|
||||||
|
namespace Oqtane.Migrations.EntityBuilders
|
||||||
|
{
|
||||||
|
public class LanguageEntityBuilder : AuditableBaseEntityBuilder<LanguageEntityBuilder>
|
||||||
|
{
|
||||||
|
private const string _entityTableName = "Language";
|
||||||
|
private readonly PrimaryKey<LanguageEntityBuilder> _primaryKey = new("PK_Language", x => x.LanguageId);
|
||||||
|
private readonly ForeignKey<LanguageEntityBuilder> _siteForeignKey = new("FK_Language_Site", x => x.SiteId, "Site", "SiteId", ReferentialAction.Cascade);
|
||||||
|
|
||||||
|
public LanguageEntityBuilder(MigrationBuilder migrationBuilder, IOqtaneDatabase database) : base(migrationBuilder, database)
|
||||||
|
{
|
||||||
|
EntityTableName = _entityTableName;
|
||||||
|
PrimaryKey = _primaryKey;
|
||||||
|
ForeignKeys.Add(_siteForeignKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override LanguageEntityBuilder BuildTable(ColumnsBuilder table)
|
||||||
|
{
|
||||||
|
LanguageId = AddAutoIncrementColumn(table,"LanguageId");
|
||||||
|
SiteId = AddIntegerColumn(table,"SiteId");
|
||||||
|
Name = AddStringColumn(table,"Name", 100);
|
||||||
|
Code = AddStringColumn(table,"Code", 10);
|
||||||
|
IsDefault = AddBooleanColumn(table,"IsDefault");
|
||||||
|
|
||||||
|
AddAuditableColumns(table);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> LanguageId { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> SiteId { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> Name { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> Code { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> IsDefault { get; set; }
|
||||||
|
}
|
||||||
|
}
|
78
Oqtane.Server/Migrations/EntityBuilders/LogEntityBuilder.cs
Normal file
78
Oqtane.Server/Migrations/EntityBuilders/LogEntityBuilder.cs
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
|
||||||
|
// ReSharper disable MemberCanBePrivate.Global
|
||||||
|
// ReSharper disable UnusedAutoPropertyAccessor.Global
|
||||||
|
|
||||||
|
namespace Oqtane.Migrations.EntityBuilders
|
||||||
|
{
|
||||||
|
public class LogEntityBuilder : BaseEntityBuilder<LogEntityBuilder>
|
||||||
|
{
|
||||||
|
private const string _entityTableName = "Log";
|
||||||
|
private readonly PrimaryKey<LogEntityBuilder> _primaryKey = new("PK_Log", x => x.LogId);
|
||||||
|
private readonly ForeignKey<LogEntityBuilder> _siteForeignKey = new("FK_Log_Site", x => x.SiteId, "Site", "SiteId", ReferentialAction.Cascade);
|
||||||
|
|
||||||
|
public LogEntityBuilder(MigrationBuilder migrationBuilder, IOqtaneDatabase database) : base(migrationBuilder, database)
|
||||||
|
{
|
||||||
|
EntityTableName = _entityTableName;
|
||||||
|
PrimaryKey = _primaryKey;
|
||||||
|
ForeignKeys.Add(_siteForeignKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override LogEntityBuilder BuildTable(ColumnsBuilder table)
|
||||||
|
{
|
||||||
|
LogId = AddAutoIncrementColumn(table,"LogId");
|
||||||
|
SiteId = AddIntegerColumn(table,"SiteId", true);
|
||||||
|
LogDate = AddDateTimeColumn(table,"LogDate");
|
||||||
|
PageId = AddIntegerColumn(table,"PageId", true);
|
||||||
|
ModuleId = AddIntegerColumn(table,"ModuleId", true);
|
||||||
|
UserId = AddIntegerColumn(table,"UserId", true);
|
||||||
|
Url = AddStringColumn(table,"Url", 2048);
|
||||||
|
Server = AddStringColumn(table,"Server", 200);
|
||||||
|
Category = AddStringColumn(table,"Category", 200);
|
||||||
|
Feature = AddStringColumn(table,"Feature", 200);
|
||||||
|
Function = AddStringColumn(table,"Function", 20);
|
||||||
|
Level = AddStringColumn(table,"Level", 20);
|
||||||
|
Message = AddMaxStringColumn(table,"Message");
|
||||||
|
MessageTemplate = AddMaxStringColumn(table,"MessageTemplate");
|
||||||
|
Exception = AddMaxStringColumn(table,"Exception", true);
|
||||||
|
Properties = AddMaxStringColumn(table,"Properties", true);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> LogId { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> SiteId { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> LogDate { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> PageId { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> ModuleId { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> UserId { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> Url { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> Server { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> Category { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> Feature { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> Function { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> Level { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> Message { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> MessageTemplate { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> Exception { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> Properties { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
|
||||||
|
// ReSharper disable MemberCanBePrivate.Global
|
||||||
|
// ReSharper disable UnusedAutoPropertyAccessor.Global
|
||||||
|
|
||||||
|
namespace Oqtane.Migrations.EntityBuilders
|
||||||
|
{
|
||||||
|
public class ModuleDefinitionsEntityBuilder : AuditableBaseEntityBuilder<ModuleDefinitionsEntityBuilder>
|
||||||
|
{
|
||||||
|
private const string _entityTableName = "ModuleDefinition";
|
||||||
|
private readonly PrimaryKey<ModuleDefinitionsEntityBuilder> _primaryKey = new("PK_ModuleDefinition", x => x.ModuleDefinitionId);
|
||||||
|
|
||||||
|
public ModuleDefinitionsEntityBuilder(MigrationBuilder migrationBuilder, IOqtaneDatabase database) : base(migrationBuilder, database)
|
||||||
|
{
|
||||||
|
EntityTableName = _entityTableName;
|
||||||
|
PrimaryKey = _primaryKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override ModuleDefinitionsEntityBuilder BuildTable(ColumnsBuilder table)
|
||||||
|
{
|
||||||
|
ModuleDefinitionId = AddAutoIncrementColumn(table,"ModuleDefinitionId");
|
||||||
|
ModuleDefinitionName = AddStringColumn(table,"ModuleDefinitionName", 200);
|
||||||
|
Name = AddStringColumn(table,"Name", 200, true);
|
||||||
|
Description = AddStringColumn(table,"Description", 2000, true);
|
||||||
|
Categories = AddStringColumn(table,"Categories", 200, true);
|
||||||
|
Version = AddStringColumn(table,"Version", 50, true);
|
||||||
|
|
||||||
|
AddAuditableColumns(table);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> ModuleDefinitionId { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> ModuleDefinitionName { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> Name { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> Description { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> Categories { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> Version { get; private set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
|
||||||
|
// ReSharper disable MemberCanBePrivate.Global
|
||||||
|
// ReSharper disable UnusedAutoPropertyAccessor.Global
|
||||||
|
|
||||||
|
namespace Oqtane.Migrations.EntityBuilders
|
||||||
|
{
|
||||||
|
public class ModuleEntityBuilder : AuditableBaseEntityBuilder<ModuleEntityBuilder>
|
||||||
|
{
|
||||||
|
private const string _entityTableName = "Module";
|
||||||
|
private readonly PrimaryKey<ModuleEntityBuilder> _primaryKey = new("PK_Module", x => x.ModuleId);
|
||||||
|
private readonly ForeignKey<ModuleEntityBuilder> _siteForeignKey = new("FK_Module_Site", x => x.SiteId, "Site", "SiteId", ReferentialAction.Cascade);
|
||||||
|
|
||||||
|
public ModuleEntityBuilder(MigrationBuilder migrationBuilder, IOqtaneDatabase database) : base(migrationBuilder, database)
|
||||||
|
{
|
||||||
|
EntityTableName = _entityTableName;
|
||||||
|
PrimaryKey = _primaryKey;
|
||||||
|
ForeignKeys.Add(_siteForeignKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override ModuleEntityBuilder BuildTable(ColumnsBuilder table)
|
||||||
|
{
|
||||||
|
ModuleId = AddAutoIncrementColumn(table,"ModuleId");
|
||||||
|
SiteId = AddIntegerColumn(table,"SiteId");
|
||||||
|
ModuleDefinitionName = AddStringColumn(table,"ModuleDefinitionName", 200);
|
||||||
|
AllPages = AddBooleanColumn(table,"AllPages");
|
||||||
|
|
||||||
|
AddAuditableColumns(table);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> ModuleId { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> SiteId { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> ModuleDefinitionName { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> AllPages { get; private set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
|
||||||
|
// ReSharper disable MemberCanBePrivate.Global
|
||||||
|
// ReSharper disable UnusedAutoPropertyAccessor.Global
|
||||||
|
|
||||||
|
namespace Oqtane.Migrations.EntityBuilders
|
||||||
|
{
|
||||||
|
public class NotificationEntityBuilder : DeletableBaseEntityBuilder<NotificationEntityBuilder>
|
||||||
|
{
|
||||||
|
private const string _entityTableName = "Notification";
|
||||||
|
private readonly PrimaryKey<NotificationEntityBuilder> _primaryKey = new("PK_Notification", x => x.NotificationId);
|
||||||
|
private readonly ForeignKey<NotificationEntityBuilder> _siteForeignKey = new("FK_Notification_Site", x => x.SiteId, "Site", "SiteId", ReferentialAction.Cascade);
|
||||||
|
|
||||||
|
public NotificationEntityBuilder(MigrationBuilder migrationBuilder, IOqtaneDatabase database) : base(migrationBuilder, database)
|
||||||
|
{
|
||||||
|
EntityTableName = _entityTableName;
|
||||||
|
PrimaryKey = _primaryKey;
|
||||||
|
ForeignKeys.Add(_siteForeignKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override NotificationEntityBuilder BuildTable(ColumnsBuilder table)
|
||||||
|
{
|
||||||
|
NotificationId = AddAutoIncrementColumn(table,"NotificationId");
|
||||||
|
SiteId = AddIntegerColumn(table,"SiteId");
|
||||||
|
FromUserId = AddIntegerColumn(table,"FromUserId", true);
|
||||||
|
ToUserId = AddIntegerColumn(table,"ToUserId", true);
|
||||||
|
ToEmail = AddStringColumn(table,"ToEmail", 256);
|
||||||
|
ParentId = AddIntegerColumn(table,"ParentId", true);
|
||||||
|
Subject = AddStringColumn(table,"Subject", 256);
|
||||||
|
Body = AddMaxStringColumn(table,"Body");
|
||||||
|
CreatedOn = AddDateTimeColumn(table,"CreatedOn");
|
||||||
|
IsDelivered = AddBooleanColumn(table,"IsDelivered");
|
||||||
|
DeliveredOn = AddDateTimeColumn(table,"DeliveredOn", true);
|
||||||
|
|
||||||
|
AddDeletableColumns(table);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> NotificationId { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> SiteId { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> FromUserId { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> ToUserId { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> ToEmail { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> ParentId { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> Subject { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> Body { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> CreatedOn { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> IsDelivered { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> DeliveredOn { get; set; }
|
||||||
|
}
|
||||||
|
}
|
84
Oqtane.Server/Migrations/EntityBuilders/PageEntityBuilder.cs
Normal file
84
Oqtane.Server/Migrations/EntityBuilders/PageEntityBuilder.cs
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
|
||||||
|
// ReSharper disable MemberCanBePrivate.Global
|
||||||
|
// ReSharper disable UnusedAutoPropertyAccessor.Global
|
||||||
|
|
||||||
|
namespace Oqtane.Migrations.EntityBuilders
|
||||||
|
{
|
||||||
|
public class PageEntityBuilder : DeletableAuditableBaseEntityBuilder<PageEntityBuilder>
|
||||||
|
{
|
||||||
|
private const string _entityTableName = "Page";
|
||||||
|
private readonly PrimaryKey<PageEntityBuilder> _primaryKey = new("PK_Page", x => x.PageId);
|
||||||
|
private readonly ForeignKey<PageEntityBuilder> _siteForeignKey = new("FK_Page_Site", x => x.SiteId, "Site", "SiteId", ReferentialAction.Cascade);
|
||||||
|
|
||||||
|
public PageEntityBuilder(MigrationBuilder migrationBuilder, IOqtaneDatabase database) : base(migrationBuilder, database)
|
||||||
|
{
|
||||||
|
EntityTableName = _entityTableName;
|
||||||
|
PrimaryKey = _primaryKey;
|
||||||
|
ForeignKeys.Add(_siteForeignKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override PageEntityBuilder BuildTable(ColumnsBuilder table)
|
||||||
|
{
|
||||||
|
PageId = AddAutoIncrementColumn(table,"PageId");
|
||||||
|
SiteId = AddIntegerColumn(table,"SiteId");
|
||||||
|
if (ActiveDatabase.Name == "SqlServer" || ActiveDatabase.Name == "LocalDB")
|
||||||
|
{
|
||||||
|
Path = AddStringColumn(table,"Path", 50);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Path = AddStringColumn(table,"Path", 256);
|
||||||
|
}
|
||||||
|
Name = AddStringColumn(table,"Name", 50);
|
||||||
|
Title = AddStringColumn(table,"Title", 200, true);
|
||||||
|
ThemeType = AddStringColumn(table,"ThemeType", 200, true);
|
||||||
|
Icon = AddStringColumn(table,"Icon", 50);
|
||||||
|
ParentId = AddIntegerColumn(table,"ParentId", true);
|
||||||
|
Order = AddIntegerColumn(table,"Order");
|
||||||
|
IsNavigation = AddBooleanColumn(table,"IsNavigation");
|
||||||
|
Url = AddStringColumn(table,"Url", 500, true);
|
||||||
|
LayoutType = AddStringColumn(table,"LayoutType", 200);
|
||||||
|
UserId = AddIntegerColumn(table,"UserId", true);
|
||||||
|
IsPersonalizable = AddBooleanColumn(table,"IsPersonalizable");
|
||||||
|
DefaultContainerType = AddStringColumn(table,"DefaultContainerType", 200, true);
|
||||||
|
|
||||||
|
AddAuditableColumns(table);
|
||||||
|
AddDeletableColumns(table);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> PageId { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> SiteId { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> Path { get; private set; }
|
||||||
|
public OperationBuilder<AddColumnOperation> Name { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> Title { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> ThemeType { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> Icon { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> ParentId { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> Order { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> IsNavigation { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> Url { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> LayoutType { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> UserId { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> IsPersonalizable { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> DefaultContainerType { get; private set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
|
||||||
|
// ReSharper disable MemberCanBePrivate.Global
|
||||||
|
// ReSharper disable UnusedAutoPropertyAccessor.Global
|
||||||
|
|
||||||
|
namespace Oqtane.Migrations.EntityBuilders
|
||||||
|
{
|
||||||
|
public class PageModuleEntityBuilder : DeletableAuditableBaseEntityBuilder<PageModuleEntityBuilder>
|
||||||
|
{
|
||||||
|
private const string _entityTableName = "PageModule";
|
||||||
|
private readonly PrimaryKey<PageModuleEntityBuilder> _primaryKey = new("PK_PageModule", x => x.PageModuleId);
|
||||||
|
private readonly ForeignKey<PageModuleEntityBuilder> _moduleForeignKey = new("FK_PageModule_Module", x => x.ModuleId, "Module", "ModuleId", ReferentialAction.NoAction);
|
||||||
|
private readonly ForeignKey<PageModuleEntityBuilder> _pageForeignKey = new("FK_PageModule_Page", x => x.PageId, "Page", "PageId", ReferentialAction.Cascade);
|
||||||
|
|
||||||
|
public PageModuleEntityBuilder(MigrationBuilder migrationBuilder, IOqtaneDatabase database) : base(migrationBuilder, database)
|
||||||
|
{
|
||||||
|
EntityTableName = _entityTableName;
|
||||||
|
PrimaryKey = _primaryKey;
|
||||||
|
ForeignKeys.Add(_moduleForeignKey);
|
||||||
|
ForeignKeys.Add(_pageForeignKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override PageModuleEntityBuilder BuildTable(ColumnsBuilder table)
|
||||||
|
{
|
||||||
|
PageModuleId = AddAutoIncrementColumn(table,"PageModuleId");
|
||||||
|
PageId = AddIntegerColumn(table,"PageId");
|
||||||
|
ModuleId = AddIntegerColumn(table,"ModuleId");
|
||||||
|
Title = AddStringColumn(table,"Title", 200);
|
||||||
|
Pane = AddStringColumn(table,"Pane", 50);
|
||||||
|
Order = AddIntegerColumn(table,"Order");
|
||||||
|
ContainerType = AddStringColumn(table,"ContainerType", 200);
|
||||||
|
|
||||||
|
AddAuditableColumns(table);
|
||||||
|
AddDeletableColumns(table);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> PageModuleId { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> PageId { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> ModuleId { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> Title { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> Pane { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> Order { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> ContainerType { get; private set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
|
||||||
|
// ReSharper disable MemberCanBePrivate.Global
|
||||||
|
// ReSharper disable UnusedAutoPropertyAccessor.Global
|
||||||
|
|
||||||
|
namespace Oqtane.Migrations.EntityBuilders
|
||||||
|
{
|
||||||
|
public class PermissionEntityBuilder : AuditableBaseEntityBuilder<PermissionEntityBuilder>
|
||||||
|
{
|
||||||
|
private const string _entityTableName = "Permission";
|
||||||
|
private readonly PrimaryKey<PermissionEntityBuilder> _primaryKey = new("PK_Permission", x => x.PermissionId);
|
||||||
|
private readonly ForeignKey<PermissionEntityBuilder> _siteForeignKey = new("FK_Permission_Site", x => x.SiteId, "Site", "SiteId", ReferentialAction.Cascade);
|
||||||
|
private readonly ForeignKey<PermissionEntityBuilder> _userForeignKey = new("FK_Permission_User", x => x.UserId, "User", "UserId", ReferentialAction.NoAction);
|
||||||
|
private readonly ForeignKey<PermissionEntityBuilder> _roleForeignKey = new("FK_Permission_Role", x => x.RoleId, "Role", "RoleId", ReferentialAction.NoAction);
|
||||||
|
|
||||||
|
public PermissionEntityBuilder(MigrationBuilder migrationBuilder, IOqtaneDatabase database) : base(migrationBuilder, database)
|
||||||
|
{
|
||||||
|
EntityTableName = _entityTableName;
|
||||||
|
PrimaryKey = _primaryKey;
|
||||||
|
ForeignKeys.Add(_siteForeignKey);
|
||||||
|
ForeignKeys.Add(_userForeignKey);
|
||||||
|
ForeignKeys.Add(_roleForeignKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override PermissionEntityBuilder BuildTable(ColumnsBuilder table)
|
||||||
|
{
|
||||||
|
PermissionId = AddAutoIncrementColumn(table,"PermissionId");
|
||||||
|
SiteId = AddIntegerColumn(table,"SiteId");
|
||||||
|
EntityName = AddStringColumn(table,"EntityName", 50);
|
||||||
|
EntityId = AddIntegerColumn(table,"EntityId");
|
||||||
|
PermissionName = AddStringColumn(table,"PermissionName", 50);
|
||||||
|
RoleId = AddIntegerColumn(table,"RoleId", true);
|
||||||
|
UserId = AddIntegerColumn(table,"UserId", true);
|
||||||
|
IsAuthorized = AddBooleanColumn(table,"IsAuthorized");
|
||||||
|
|
||||||
|
AddAuditableColumns(table);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> PermissionId { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> SiteId { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> EntityName { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> EntityId { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> PermissionName { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> RoleId { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> UserId { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> IsAuthorized { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
|
||||||
|
// ReSharper disable MemberCanBePrivate.Global
|
||||||
|
// ReSharper disable UnusedAutoPropertyAccessor.Global
|
||||||
|
|
||||||
|
namespace Oqtane.Migrations.EntityBuilders
|
||||||
|
{
|
||||||
|
public class ProfileEntityBuilder : AuditableBaseEntityBuilder<ProfileEntityBuilder>
|
||||||
|
{
|
||||||
|
private const string _entityTableName = "Profile";
|
||||||
|
private readonly PrimaryKey<ProfileEntityBuilder> _primaryKey = new("PK_Profile", x => x.ProfileId);
|
||||||
|
private readonly ForeignKey<ProfileEntityBuilder> _siteForeignKey = new("FK_Profile_Sites", x => x.SiteId, "Site", "SiteId", ReferentialAction.Cascade);
|
||||||
|
|
||||||
|
public ProfileEntityBuilder(MigrationBuilder migrationBuilder, IOqtaneDatabase database) : base(migrationBuilder, database)
|
||||||
|
{
|
||||||
|
EntityTableName = _entityTableName;
|
||||||
|
PrimaryKey = _primaryKey;
|
||||||
|
ForeignKeys.Add(_siteForeignKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override ProfileEntityBuilder BuildTable(ColumnsBuilder table)
|
||||||
|
{
|
||||||
|
ProfileId = AddAutoIncrementColumn(table,"ProfileId");
|
||||||
|
SiteId = AddIntegerColumn(table,"SiteId", true);
|
||||||
|
Name = AddStringColumn(table,"Name", 50);
|
||||||
|
Title = AddStringColumn(table,"Title", 50);
|
||||||
|
Description = AddStringColumn(table,"Description", 256, true);
|
||||||
|
Category = AddStringColumn(table,"Category", 50);
|
||||||
|
ViewOrder = AddIntegerColumn(table,"ViewOrder");
|
||||||
|
MaxLength = AddIntegerColumn(table,"MaxLength");
|
||||||
|
DefaultValue = AddStringColumn(table,"DefaultValue", 2000, true);
|
||||||
|
IsRequired = AddBooleanColumn(table,"IsRequired");
|
||||||
|
IsPrivate = AddBooleanColumn(table,"IsPrivate");
|
||||||
|
|
||||||
|
AddAuditableColumns(table);
|
||||||
|
|
||||||
|
return this; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> ProfileId { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> SiteId { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> Name { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> Title { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> Description { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> Category { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> ViewOrder { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> MaxLength { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> DefaultValue { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> IsRequired { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> IsPrivate { get; set; }
|
||||||
|
}
|
||||||
|
}
|
50
Oqtane.Server/Migrations/EntityBuilders/RoleEntityBuilder.cs
Normal file
50
Oqtane.Server/Migrations/EntityBuilders/RoleEntityBuilder.cs
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
|
||||||
|
// ReSharper disable MemberCanBePrivate.Global
|
||||||
|
// ReSharper disable UnusedAutoPropertyAccessor.Global
|
||||||
|
|
||||||
|
namespace Oqtane.Migrations.EntityBuilders
|
||||||
|
{
|
||||||
|
public class RoleEntityBuilder : AuditableBaseEntityBuilder<RoleEntityBuilder>
|
||||||
|
{
|
||||||
|
private const string _entityTableName = "Role";
|
||||||
|
private readonly PrimaryKey<RoleEntityBuilder> _primaryKey = new("PK_Role", x => x.RoleId);
|
||||||
|
private readonly ForeignKey<RoleEntityBuilder> _siteForeignKey = new("FK_Role_Site", x => x.SiteId, "Site", "SiteId", ReferentialAction.Cascade);
|
||||||
|
|
||||||
|
public RoleEntityBuilder(MigrationBuilder migrationBuilder, IOqtaneDatabase database) : base(migrationBuilder, database)
|
||||||
|
{
|
||||||
|
EntityTableName = _entityTableName;
|
||||||
|
PrimaryKey = _primaryKey;
|
||||||
|
ForeignKeys.Add(_siteForeignKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override RoleEntityBuilder BuildTable(ColumnsBuilder table)
|
||||||
|
{
|
||||||
|
RoleId = AddAutoIncrementColumn(table,"RoleId");
|
||||||
|
SiteId = AddIntegerColumn(table,"SiteId", true);
|
||||||
|
Name = AddStringColumn(table,"Name", 256);
|
||||||
|
Description = AddStringColumn(table,"Description", 256);
|
||||||
|
IsAutoAssigned = AddBooleanColumn(table,"IsAutoAssigned");
|
||||||
|
IsSystem = AddBooleanColumn(table,"IsSystem");
|
||||||
|
|
||||||
|
AddAuditableColumns(table);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> RoleId { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> SiteId { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> Name { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> Description { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> IsAutoAssigned { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> IsSystem { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
|
||||||
|
// ReSharper disable MemberCanBePrivate.Global
|
||||||
|
// ReSharper disable UnusedAutoPropertyAccessor.Global
|
||||||
|
|
||||||
|
namespace Oqtane.Migrations.EntityBuilders
|
||||||
|
{
|
||||||
|
public class SettingEntityBuilder : AuditableBaseEntityBuilder<SettingEntityBuilder>
|
||||||
|
{
|
||||||
|
private const string _entityTableName = "Setting";
|
||||||
|
private readonly PrimaryKey<SettingEntityBuilder> _primaryKey = new("PK_Setting", x => x.SettingId);
|
||||||
|
|
||||||
|
public SettingEntityBuilder(MigrationBuilder migrationBuilder, IOqtaneDatabase database) : base(migrationBuilder, database)
|
||||||
|
{
|
||||||
|
EntityTableName = _entityTableName;
|
||||||
|
PrimaryKey = _primaryKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override SettingEntityBuilder BuildTable(ColumnsBuilder table)
|
||||||
|
{
|
||||||
|
SettingId = AddAutoIncrementColumn(table,"SettingId");
|
||||||
|
EntityName = AddStringColumn(table,"EntityName", 50);
|
||||||
|
EntityId = AddIntegerColumn(table,"EntityId");
|
||||||
|
SettingName = AddStringColumn(table,"SettingName", 50);
|
||||||
|
SettingValue = AddMaxStringColumn(table,"SettingValue");
|
||||||
|
|
||||||
|
AddAuditableColumns(table);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> SettingId { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> EntityName { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> EntityId { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> SettingName { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> SettingValue { get; set; }
|
||||||
|
}
|
||||||
|
}
|
67
Oqtane.Server/Migrations/EntityBuilders/SiteEntityBuilder.cs
Normal file
67
Oqtane.Server/Migrations/EntityBuilders/SiteEntityBuilder.cs
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
|
||||||
|
// ReSharper disable MemberCanBePrivate.Global
|
||||||
|
// ReSharper disable UnusedAutoPropertyAccessor.Global
|
||||||
|
|
||||||
|
namespace Oqtane.Migrations.EntityBuilders
|
||||||
|
{
|
||||||
|
public class SiteEntityBuilder : DeletableAuditableBaseEntityBuilder<SiteEntityBuilder>
|
||||||
|
{
|
||||||
|
private const string _entityTableName = "Site";
|
||||||
|
private readonly PrimaryKey<SiteEntityBuilder> _primaryKey = new("PK_Site", x => x.SiteId);
|
||||||
|
|
||||||
|
public SiteEntityBuilder(MigrationBuilder migrationBuilder, IOqtaneDatabase database) : base(migrationBuilder, database)
|
||||||
|
{
|
||||||
|
EntityTableName = _entityTableName;
|
||||||
|
PrimaryKey = _primaryKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override SiteEntityBuilder BuildTable(ColumnsBuilder table)
|
||||||
|
{
|
||||||
|
SiteId = AddAutoIncrementColumn(table,"SiteId");
|
||||||
|
TenantId = AddIntegerColumn(table,"TenantId");
|
||||||
|
Name = AddStringColumn(table,"Name", 200);
|
||||||
|
LogoFileId = AddIntegerColumn(table,"LogoFileId", true);
|
||||||
|
FaviconFileId = AddIntegerColumn(table,"FaviconFileId", true);
|
||||||
|
DefaultThemeType = AddStringColumn(table,"DefaultThemeType", 200);
|
||||||
|
DefaultLayoutType = AddStringColumn(table,"DefaultLayoutType", 200);
|
||||||
|
DefaultContainerType = AddStringColumn(table,"DefaultContainerType", 200);
|
||||||
|
PwaIsEnabled = AddBooleanColumn(table,"PwaIsEnabled");
|
||||||
|
PwaAppIconFileId = AddIntegerColumn(table,"PwaAppIconFileId", true);
|
||||||
|
PwaSplashIconFileId = AddIntegerColumn(table,"PwaSplashIconFileId", true);
|
||||||
|
AllowRegistration = AddBooleanColumn(table,"AllowRegistration");
|
||||||
|
|
||||||
|
AddAuditableColumns(table);
|
||||||
|
AddDeletableColumns(table);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> SiteId { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> TenantId { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> Name { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> LogoFileId { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> FaviconFileId { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> DefaultThemeType { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> DefaultLayoutType { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> DefaultContainerType { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> PwaIsEnabled { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> PwaAppIconFileId { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> PwaSplashIconFileId { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> AllowRegistration { get; private set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
|
||||||
|
// ReSharper disable MemberCanBePrivate.Global
|
||||||
|
// ReSharper disable UnusedAutoPropertyAccessor.Global
|
||||||
|
|
||||||
|
namespace Oqtane.Migrations.EntityBuilders
|
||||||
|
{
|
||||||
|
public class TenantEntityBuilder : AuditableBaseEntityBuilder<TenantEntityBuilder>
|
||||||
|
{
|
||||||
|
private const string _entityTableName = "Tenant";
|
||||||
|
private readonly PrimaryKey<TenantEntityBuilder> _primaryKey = new("PK_Tenant", x => x.TenantId);
|
||||||
|
|
||||||
|
public TenantEntityBuilder(MigrationBuilder migrationBuilder, IOqtaneDatabase database): base(migrationBuilder, database)
|
||||||
|
{
|
||||||
|
EntityTableName = _entityTableName;
|
||||||
|
PrimaryKey = _primaryKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override TenantEntityBuilder BuildTable(ColumnsBuilder table)
|
||||||
|
{
|
||||||
|
TenantId = AddAutoIncrementColumn(table,"TenantId");
|
||||||
|
Name = AddStringColumn(table,"Name", 100);
|
||||||
|
DBConnectionString = AddStringColumn(table,"DBConnectionString", 1024);
|
||||||
|
Version = AddStringColumn(table,"Version", 50, true);
|
||||||
|
|
||||||
|
AddAuditableColumns(table);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> TenantId { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> Name { get;private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> DBConnectionString { get; private set;}
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> Version { get; private set; }
|
||||||
|
}
|
||||||
|
}
|
52
Oqtane.Server/Migrations/EntityBuilders/UserEntityBuilder.cs
Normal file
52
Oqtane.Server/Migrations/EntityBuilders/UserEntityBuilder.cs
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
|
||||||
|
// ReSharper disable MemberCanBePrivate.Global
|
||||||
|
// ReSharper disable UnusedAutoPropertyAccessor.Global
|
||||||
|
|
||||||
|
namespace Oqtane.Migrations.EntityBuilders
|
||||||
|
{
|
||||||
|
public class UserEntityBuilder : DeletableAuditableBaseEntityBuilder<UserEntityBuilder>
|
||||||
|
{
|
||||||
|
private const string _entityTableName = "User";
|
||||||
|
private readonly PrimaryKey<UserEntityBuilder> _primaryKey = new("PK_User", x => x.UserId);
|
||||||
|
|
||||||
|
public UserEntityBuilder(MigrationBuilder migrationBuilder, IOqtaneDatabase database) : base(migrationBuilder, database)
|
||||||
|
{
|
||||||
|
EntityTableName = _entityTableName;
|
||||||
|
PrimaryKey = _primaryKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override UserEntityBuilder BuildTable(ColumnsBuilder table)
|
||||||
|
{
|
||||||
|
UserId = AddAutoIncrementColumn(table,"UserId");
|
||||||
|
Username = AddStringColumn(table,"Username", 256);
|
||||||
|
DisplayName = AddStringColumn(table,"DisplayName", 50);
|
||||||
|
Email = AddStringColumn(table,"Email", 256);
|
||||||
|
PhotoFileId = AddIntegerColumn(table,"PhotoFileId", true);
|
||||||
|
LastLoginOn = AddDateTimeColumn(table,"LastLoginOn", true);
|
||||||
|
LastIPAddress = AddStringColumn(table,"LastIpAddress", 50);
|
||||||
|
|
||||||
|
AddAuditableColumns(table);
|
||||||
|
AddDeletableColumns(table);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> UserId { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> Username { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> DisplayName { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> Email { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> PhotoFileId { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> LastLoginOn { get; private set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> LastIPAddress { get; private set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
|
||||||
|
// ReSharper disable MemberCanBePrivate.Global
|
||||||
|
// ReSharper disable UnusedAutoPropertyAccessor.Global
|
||||||
|
|
||||||
|
namespace Oqtane.Migrations.EntityBuilders
|
||||||
|
{
|
||||||
|
public class UserRoleEntityBuilder : AuditableBaseEntityBuilder<UserRoleEntityBuilder>
|
||||||
|
{
|
||||||
|
private const string _entityTableName = "UserRole";
|
||||||
|
private readonly PrimaryKey<UserRoleEntityBuilder> _primaryKey = new("PK_UserRole", x => x.UserRoleId);
|
||||||
|
private readonly ForeignKey<UserRoleEntityBuilder> _userForeignKey = new("FK_UserRole_User", x => x.UserId, "User", "UserId", ReferentialAction.Cascade);
|
||||||
|
private readonly ForeignKey<UserRoleEntityBuilder> _roleForeignKey = new("FK_UserRole_Role", x => x.RoleId, "Role", "RoleId", ReferentialAction.NoAction);
|
||||||
|
|
||||||
|
public UserRoleEntityBuilder(MigrationBuilder migrationBuilder, IOqtaneDatabase database) : base(migrationBuilder, database)
|
||||||
|
{
|
||||||
|
EntityTableName = _entityTableName;
|
||||||
|
PrimaryKey = _primaryKey;
|
||||||
|
ForeignKeys.Add(_userForeignKey);
|
||||||
|
ForeignKeys.Add(_roleForeignKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override UserRoleEntityBuilder BuildTable(ColumnsBuilder table)
|
||||||
|
{
|
||||||
|
UserRoleId = AddAutoIncrementColumn(table,"UserRoleId");
|
||||||
|
UserId = AddIntegerColumn(table,"UserId");
|
||||||
|
RoleId = AddIntegerColumn(table,"RoleId");
|
||||||
|
EffectiveDate = AddDateTimeColumn(table,"EffectiveDate", true);
|
||||||
|
ExpiryDate = AddDateTimeColumn(table,"ExpiryDate", true);
|
||||||
|
|
||||||
|
AddAuditableColumns(table);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> UserRoleId { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> UserId { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> RoleId { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> EffectiveDate { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> ExpiryDate { get; set; }
|
||||||
|
}
|
||||||
|
}
|
31
Oqtane.Server/Migrations/Framework/ForeignKey.cs
Normal file
31
Oqtane.Server/Migrations/Framework/ForeignKey.cs
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
using System;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Oqtane.Migrations.EntityBuilders;
|
||||||
|
|
||||||
|
namespace Oqtane.Migrations
|
||||||
|
{
|
||||||
|
public readonly struct ForeignKey<TEntityBuilder> where TEntityBuilder : BaseEntityBuilder<TEntityBuilder>
|
||||||
|
{
|
||||||
|
public ForeignKey(string name, Expression<Func<TEntityBuilder, object>> column, string principalTable, string principalColumn, ReferentialAction onDeleteAction)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
Column = column;
|
||||||
|
PrincipalTable = principalTable;
|
||||||
|
PrincipalColumn = principalColumn;
|
||||||
|
OnDeleteAction = onDeleteAction;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name { get; }
|
||||||
|
|
||||||
|
public Expression<Func<TEntityBuilder, object>> Column { get;}
|
||||||
|
|
||||||
|
public ReferentialAction OnDeleteAction { get; }
|
||||||
|
|
||||||
|
public string PrincipalTable { get; }
|
||||||
|
|
||||||
|
public string PrincipalColumn { get; }
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
24
Oqtane.Server/Migrations/Framework/MultiDatabaseMigration.cs
Normal file
24
Oqtane.Server/Migrations/Framework/MultiDatabaseMigration.cs
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
|
||||||
|
namespace Oqtane.Migrations
|
||||||
|
{
|
||||||
|
public abstract class MultiDatabaseMigration : Migration
|
||||||
|
{
|
||||||
|
private readonly IEnumerable<IOqtaneDatabase> _databases;
|
||||||
|
|
||||||
|
protected MultiDatabaseMigration(IEnumerable<IOqtaneDatabase> databases)
|
||||||
|
{
|
||||||
|
_databases = databases;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected IOqtaneDatabase ActiveDatabase => _databases.FirstOrDefault(d => d.Provider == ActiveProvider);
|
||||||
|
|
||||||
|
protected string RewriteName(string name)
|
||||||
|
{
|
||||||
|
return ActiveDatabase.RewriteName(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Diagnostics;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Internal;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
using Oqtane.Repository.Databases.Interfaces;
|
||||||
|
|
||||||
|
namespace Oqtane.Migrations.Framework
|
||||||
|
{
|
||||||
|
public class MultiDatabaseMigrationsAssembly: MigrationsAssembly
|
||||||
|
{
|
||||||
|
private readonly IEnumerable<IOqtaneDatabase> _databases;
|
||||||
|
|
||||||
|
public MultiDatabaseMigrationsAssembly(
|
||||||
|
ICurrentDbContext currentContext,
|
||||||
|
IDbContextOptions options,
|
||||||
|
IMigrationsIdGenerator idGenerator,
|
||||||
|
IDiagnosticsLogger<DbLoggerCategory.Migrations> logger)
|
||||||
|
: base(currentContext, options, idGenerator, logger)
|
||||||
|
{
|
||||||
|
var multiDatabaseContext = currentContext.Context as IMultiDatabase;
|
||||||
|
if (multiDatabaseContext != null) _databases = multiDatabaseContext.Databases;
|
||||||
|
}
|
||||||
|
public override Migration CreateMigration(TypeInfo migrationClass, string activeProvider)
|
||||||
|
{
|
||||||
|
var hasCtorWithCacheOptions = migrationClass.GetConstructor(new[] { typeof(IEnumerable<IOqtaneDatabase>) }) != null;
|
||||||
|
|
||||||
|
if (hasCtorWithCacheOptions)
|
||||||
|
{
|
||||||
|
var migration = (Migration)Activator.CreateInstance(migrationClass.AsType(), _databases);
|
||||||
|
if (migration != null)
|
||||||
|
{
|
||||||
|
migration.ActiveProvider = activeProvider;
|
||||||
|
return migration;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return base.CreateMigration(migrationClass, activeProvider);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
21
Oqtane.Server/Migrations/Framework/PrimaryKey.cs
Normal file
21
Oqtane.Server/Migrations/Framework/PrimaryKey.cs
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
using System;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
using Oqtane.Migrations.EntityBuilders;
|
||||||
|
|
||||||
|
namespace Oqtane.Migrations
|
||||||
|
{
|
||||||
|
public readonly struct PrimaryKey<TEntityBuilder> where TEntityBuilder : BaseEntityBuilder<TEntityBuilder>
|
||||||
|
{
|
||||||
|
public PrimaryKey(string name, Expression<Func<TEntityBuilder, object>> columns)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
Columns = columns;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name { get; }
|
||||||
|
|
||||||
|
public Expression<Func<TEntityBuilder, object>> Columns { get;}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -25,12 +25,12 @@ namespace Oqtane.Modules.HtmlText.Controllers
|
||||||
// GET api/<controller>/5
|
// GET api/<controller>/5
|
||||||
[HttpGet("{id}")]
|
[HttpGet("{id}")]
|
||||||
[Authorize(Policy = PolicyNames.ViewModule)]
|
[Authorize(Policy = PolicyNames.ViewModule)]
|
||||||
public List<HtmlTextInfo> Get(int id)
|
public List<Models.HtmlText> Get(int id)
|
||||||
{
|
{
|
||||||
var list = new List<HtmlTextInfo>();
|
var list = new List<Models.HtmlText>();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
HtmlTextInfo htmlText = null;
|
Models.HtmlText htmlText = null;
|
||||||
if (_entityId == id)
|
if (_entityId == id)
|
||||||
{
|
{
|
||||||
htmlText = _htmlText.GetHtmlText(id);
|
htmlText = _htmlText.GetHtmlText(id);
|
||||||
|
@ -48,7 +48,7 @@ namespace Oqtane.Modules.HtmlText.Controllers
|
||||||
// POST api/<controller>
|
// POST api/<controller>
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
[Authorize(Policy = PolicyNames.EditModule)]
|
[Authorize(Policy = PolicyNames.EditModule)]
|
||||||
public HtmlTextInfo Post([FromBody] HtmlTextInfo htmlText)
|
public Models.HtmlText Post([FromBody] Models.HtmlText htmlText)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -69,7 +69,7 @@ namespace Oqtane.Modules.HtmlText.Controllers
|
||||||
// PUT api/<controller>/5
|
// PUT api/<controller>/5
|
||||||
[HttpPut("{id}")]
|
[HttpPut("{id}")]
|
||||||
[Authorize(Policy = PolicyNames.EditModule)]
|
[Authorize(Policy = PolicyNames.EditModule)]
|
||||||
public HtmlTextInfo Put(int id, [FromBody] HtmlTextInfo htmlText)
|
public Models.HtmlText Put(int id, [FromBody] Models.HtmlText htmlText)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,40 +1,38 @@
|
||||||
using Oqtane.Infrastructure;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Oqtane.Infrastructure;
|
||||||
using Oqtane.Models;
|
using Oqtane.Models;
|
||||||
using Oqtane.Repository;
|
using Oqtane.Repository;
|
||||||
using Oqtane.Modules.HtmlText.Models;
|
using Oqtane.Modules.HtmlText.Models;
|
||||||
using Oqtane.Modules.HtmlText.Repository;
|
using Oqtane.Modules.HtmlText.Repository;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Oqtane.Enums;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
|
||||||
|
// ReSharper disable ConvertToUsingDeclaration
|
||||||
|
|
||||||
namespace Oqtane.Modules.HtmlText.Manager
|
namespace Oqtane.Modules.HtmlText.Manager
|
||||||
{
|
{
|
||||||
public class HtmlTextManager : IInstallable, IPortable
|
public class HtmlTextManager : MigratableModuleBase, IInstallable, IPortable
|
||||||
{
|
{
|
||||||
private IHtmlTextRepository _htmlTexts;
|
private readonly IHtmlTextRepository _htmlText;
|
||||||
private ISqlRepository _sql;
|
private readonly IEnumerable<IOqtaneDatabase> _databases;
|
||||||
|
|
||||||
public HtmlTextManager(IHtmlTextRepository htmltexts, ISqlRepository sql)
|
public HtmlTextManager(IHtmlTextRepository htmlText, IEnumerable<IOqtaneDatabase> databases)
|
||||||
{
|
{
|
||||||
_htmlTexts = htmltexts;
|
_htmlText = htmlText;
|
||||||
_sql = sql;
|
_databases = databases;
|
||||||
}
|
|
||||||
|
|
||||||
public bool Install(Tenant tenant, string version)
|
|
||||||
{
|
|
||||||
return _sql.ExecuteScript(tenant, GetType().Assembly, "HtmlText." + version + ".sql");
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Uninstall(Tenant tenant)
|
|
||||||
{
|
|
||||||
return _sql.ExecuteScript(tenant, GetType().Assembly, "HtmlText.Uninstall.sql");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public string ExportModule(Module module)
|
public string ExportModule(Module module)
|
||||||
{
|
{
|
||||||
string content = "";
|
string content = "";
|
||||||
HtmlTextInfo htmltext = _htmlTexts.GetHtmlText(module.ModuleId);
|
var htmlText = _htmlText.GetHtmlText(module.ModuleId);
|
||||||
if (htmltext != null)
|
if (htmlText != null)
|
||||||
{
|
{
|
||||||
content = WebUtility.HtmlEncode(htmltext.Content);
|
content = WebUtility.HtmlEncode(htmlText.Content);
|
||||||
}
|
}
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
@ -42,19 +40,31 @@ namespace Oqtane.Modules.HtmlText.Manager
|
||||||
public void ImportModule(Module module, string content, string version)
|
public void ImportModule(Module module, string content, string version)
|
||||||
{
|
{
|
||||||
content = WebUtility.HtmlDecode(content);
|
content = WebUtility.HtmlDecode(content);
|
||||||
HtmlTextInfo htmltext = _htmlTexts.GetHtmlText(module.ModuleId);
|
var htmlText = _htmlText.GetHtmlText(module.ModuleId);
|
||||||
if (htmltext != null)
|
if (htmlText != null)
|
||||||
{
|
{
|
||||||
htmltext.Content = content;
|
htmlText.Content = content;
|
||||||
_htmlTexts.UpdateHtmlText(htmltext);
|
_htmlText.UpdateHtmlText(htmlText);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
htmltext = new HtmlTextInfo();
|
htmlText = new Models.HtmlText();
|
||||||
htmltext.ModuleId = module.ModuleId;
|
htmlText.ModuleId = module.ModuleId;
|
||||||
htmltext.Content = content;
|
htmlText.Content = content;
|
||||||
_htmlTexts.AddHtmlText(htmltext);
|
_htmlText.AddHtmlText(htmlText);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool Install(Tenant tenant, string version)
|
||||||
|
{
|
||||||
|
var dbConfig = new DbConfig(null, null, _databases) {ConnectionString = tenant.DBConnectionString, DatabaseType = tenant.DBType};
|
||||||
|
return Migrate(new HtmlTextContext(dbConfig, null), tenant, MigrationType.Up);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Uninstall(Tenant tenant)
|
||||||
|
{
|
||||||
|
var dbConfig = new DbConfig(null, null, _databases) {ConnectionString = tenant.DBConnectionString, DatabaseType = tenant.DBType};
|
||||||
|
return Migrate(new HtmlTextContext(dbConfig, null), tenant, MigrationType.Down);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
using Oqtane.Migrations;
|
||||||
|
using Oqtane.Modules.HtmlText.Migrations.EntityBuilders;
|
||||||
|
using Oqtane.Modules.HtmlText.Repository;
|
||||||
|
|
||||||
|
namespace Oqtane.Modules.HtmlText.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(HtmlTextContext))]
|
||||||
|
[Migration("HtmlText.01.00.00.00")]
|
||||||
|
public class InitializeModule : MultiDatabaseMigration
|
||||||
|
{
|
||||||
|
public InitializeModule(IEnumerable<IOqtaneDatabase> databases) : base(databases)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
//Create HtmlText table
|
||||||
|
var entityBuilder = new HtmlTextEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
entityBuilder.Create();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
//Drop HtmlText table
|
||||||
|
var entityBuilder = new HtmlTextEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
entityBuilder.Drop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
using Oqtane.Migrations;
|
||||||
|
using Oqtane.Migrations.EntityBuilders;
|
||||||
|
|
||||||
|
// ReSharper disable MemberCanBePrivate.Global
|
||||||
|
// ReSharper disable UnusedAutoPropertyAccessor.Global
|
||||||
|
|
||||||
|
namespace Oqtane.Modules.HtmlText.Migrations.EntityBuilders
|
||||||
|
{
|
||||||
|
public class HtmlTextEntityBuilder : AuditableBaseEntityBuilder<HtmlTextEntityBuilder>
|
||||||
|
{
|
||||||
|
private const string _entityTableName = "HtmlText";
|
||||||
|
private readonly PrimaryKey<HtmlTextEntityBuilder> _primaryKey = new("PK_HtmlText", x => x.HtmlTextId);
|
||||||
|
private readonly ForeignKey<HtmlTextEntityBuilder> _moduleForeignKey = new("FK_HtmlText_Module", x => x.ModuleId, "Module", "ModuleId", ReferentialAction.Cascade);
|
||||||
|
|
||||||
|
public HtmlTextEntityBuilder(MigrationBuilder migrationBuilder, IOqtaneDatabase database) : base(migrationBuilder, database)
|
||||||
|
{
|
||||||
|
EntityTableName = _entityTableName;
|
||||||
|
PrimaryKey = _primaryKey;
|
||||||
|
ForeignKeys.Add(_moduleForeignKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override HtmlTextEntityBuilder BuildTable(ColumnsBuilder table)
|
||||||
|
{
|
||||||
|
HtmlTextId = AddAutoIncrementColumn(table,"HtmlTextId");
|
||||||
|
ModuleId = AddIntegerColumn(table,"ModuleId");
|
||||||
|
Content = AddMaxStringColumn(table,"Content");
|
||||||
|
|
||||||
|
AddAuditableColumns(table);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> HtmlTextId { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> ModuleId { get; set; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> Content { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,17 +1,21 @@
|
||||||
using Microsoft.EntityFrameworkCore;
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Oqtane.Modules.HtmlText.Models;
|
using Oqtane.Modules.HtmlText.Models;
|
||||||
using Oqtane.Repository;
|
using Oqtane.Repository;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Oqtane.Interfaces;
|
||||||
|
using Oqtane.Repository.Databases.Interfaces;
|
||||||
|
|
||||||
|
// ReSharper disable MemberCanBePrivate.Global
|
||||||
|
// ReSharper disable UnusedAutoPropertyAccessor.Global
|
||||||
|
|
||||||
namespace Oqtane.Modules.HtmlText.Repository
|
namespace Oqtane.Modules.HtmlText.Repository
|
||||||
{
|
{
|
||||||
public class HtmlTextContext : DBContextBase, IService
|
public class HtmlTextContext : DBContextBase, IService, IMultiDatabase
|
||||||
{
|
{
|
||||||
public virtual DbSet<HtmlTextInfo> HtmlText { get; set; }
|
public HtmlTextContext(IDbConfig dbConfig, ITenantResolver tenantResolver) : base(dbConfig, tenantResolver)
|
||||||
|
|
||||||
public HtmlTextContext(ITenantResolver tenantResolver, IHttpContextAccessor accessor) : base(tenantResolver, accessor)
|
|
||||||
{
|
{
|
||||||
// ContextBase handles multi-tenant database connections
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual DbSet<Models.HtmlText> HtmlText { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,20 +13,20 @@ namespace Oqtane.Modules.HtmlText.Repository
|
||||||
_db = context;
|
_db = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
public HtmlTextInfo GetHtmlText(int moduleId)
|
public Models.HtmlText GetHtmlText(int moduleId)
|
||||||
{
|
{
|
||||||
return _db.HtmlText.FirstOrDefault(item => item.ModuleId == moduleId);
|
return _db.HtmlText.FirstOrDefault(item => item.ModuleId == moduleId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public HtmlTextInfo AddHtmlText(HtmlTextInfo htmlText)
|
public Models.HtmlText AddHtmlText(Models.HtmlText htmlText)
|
||||||
{
|
{
|
||||||
_db.HtmlText.Add(htmlText);
|
_db.HtmlText.Add(htmlText);
|
||||||
_db.SaveChanges();
|
_db.SaveChanges();
|
||||||
return htmlText;
|
return htmlText;
|
||||||
}
|
}
|
||||||
|
|
||||||
public HtmlTextInfo UpdateHtmlText(HtmlTextInfo htmlText)
|
public Models.HtmlText UpdateHtmlText(Models.HtmlText htmlText)
|
||||||
{
|
{
|
||||||
_db.Entry(htmlText).State = EntityState.Modified;
|
_db.Entry(htmlText).State = EntityState.Modified;
|
||||||
_db.SaveChanges();
|
_db.SaveChanges();
|
||||||
|
@ -35,7 +35,7 @@ namespace Oqtane.Modules.HtmlText.Repository
|
||||||
|
|
||||||
public void DeleteHtmlText(int moduleId)
|
public void DeleteHtmlText(int moduleId)
|
||||||
{
|
{
|
||||||
HtmlTextInfo htmlText = _db.HtmlText.FirstOrDefault(item => item.ModuleId == moduleId);
|
Models.HtmlText htmlText = _db.HtmlText.FirstOrDefault(item => item.ModuleId == moduleId);
|
||||||
if (htmlText != null) _db.HtmlText.Remove(htmlText);
|
if (htmlText != null) _db.HtmlText.Remove(htmlText);
|
||||||
_db.SaveChanges();
|
_db.SaveChanges();
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,9 +4,9 @@ namespace Oqtane.Modules.HtmlText.Repository
|
||||||
{
|
{
|
||||||
public interface IHtmlTextRepository
|
public interface IHtmlTextRepository
|
||||||
{
|
{
|
||||||
HtmlTextInfo GetHtmlText(int moduleId);
|
Models.HtmlText GetHtmlText(int moduleId);
|
||||||
HtmlTextInfo AddHtmlText(HtmlTextInfo htmlText);
|
Models.HtmlText AddHtmlText(Models.HtmlText htmlText);
|
||||||
HtmlTextInfo UpdateHtmlText(HtmlTextInfo htmlText);
|
Models.HtmlText UpdateHtmlText(Models.HtmlText htmlText);
|
||||||
void DeleteHtmlText(int moduleId);
|
void DeleteHtmlText(int moduleId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
CREATE TABLE [dbo].[HtmlText](
|
CREATE TABLE [dbo].[HtmlText](
|
||||||
[HtmlTextId] [int] IDENTITY(1,1) NOT NULL,
|
[HtmlTextId] [int] IDENTITY(1,1) NOT NULL,
|
||||||
[ModuleId] [int] NOT NULL,
|
[ModuleId] [int] NOT NULL,
|
||||||
[Content] [nvarchar](max) NOT NULL,
|
[Content] [nvarchar](max) NOT NULL,
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
DROP TABLE [dbo].[HtmlText]
|
DROP TABLE [dbo].[HtmlText]
|
||||||
GO
|
GO
|
||||||
|
|
42
Oqtane.Server/Modules/MigratableModuleBase.cs
Normal file
42
Oqtane.Server/Modules/MigratableModuleBase.cs
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Oqtane.Enums;
|
||||||
|
using Oqtane.Models;
|
||||||
|
using Oqtane.Modules.HtmlText.Repository;
|
||||||
|
using Oqtane.Repository;
|
||||||
|
|
||||||
|
namespace Oqtane.Modules
|
||||||
|
{
|
||||||
|
public class MigratableModuleBase
|
||||||
|
{
|
||||||
|
public bool Migrate(DBContextBase dbContext, Tenant tenant, MigrationType migrationType)
|
||||||
|
{
|
||||||
|
var result = true;
|
||||||
|
|
||||||
|
using (dbContext)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var migrator = dbContext.GetService<IMigrator>();
|
||||||
|
if (migrationType == MigrationType.Down)
|
||||||
|
{
|
||||||
|
migrator.Migrate(Migration.InitialDatabase);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
migrator.Migrate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Console.WriteLine(e);
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -44,20 +44,29 @@
|
||||||
<EmbeddedResource Include="Scripts\Tenant.02.00.02.03.sql" />
|
<EmbeddedResource Include="Scripts\Tenant.02.00.02.03.sql" />
|
||||||
<EmbeddedResource Include="Modules\HtmlText\Scripts\HtmlText.1.0.0.sql" />
|
<EmbeddedResource Include="Modules\HtmlText\Scripts\HtmlText.1.0.0.sql" />
|
||||||
<EmbeddedResource Include="Modules\HtmlText\Scripts\HtmlText.Uninstall.sql" />
|
<EmbeddedResource Include="Modules\HtmlText\Scripts\HtmlText.Uninstall.sql" />
|
||||||
|
<EmbeddedResource Include="Scripts\MigrateMaster.sql" />
|
||||||
|
<EmbeddedResource Include="Scripts\MigrateTenant.sql" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="dbup" Version="4.4.0" />
|
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="5.0.4" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="5.0.0" />
|
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="5.0.4" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="5.0.0" />
|
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="5.0.4" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="5.0.0" />
|
<PackageReference Include="Microsoft.Data.SqlClient" Version="2.0.1" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.0" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.4" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="5.0.0" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="5.0.4">
|
||||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="5.0.0" />
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="5.0.4" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Localization" Version="5.0.4" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.6.3" />
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.6.3" />
|
||||||
<PackageReference Include="System.Drawing.Common" Version="5.0.0" />
|
<PackageReference Include="System.Drawing.Common" Version="5.0.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Oqtane.Client\Oqtane.Client.csproj" />
|
<ProjectReference Include="..\Oqtane.Client\Oqtane.Client.csproj" />
|
||||||
|
<ProjectReference Include="..\Oqtane.Database.MySQL\Oqtane.Database.MySQL.csproj" />
|
||||||
|
<ProjectReference Include="..\Oqtane.Database.PostgreSQL\Oqtane.Database.PostgreSQL.csproj" />
|
||||||
|
<ProjectReference Include="..\Oqtane.Database.Sqlite\Oqtane.Database.Sqlite.csproj" />
|
||||||
<ProjectReference Include="..\Oqtane.Shared\Oqtane.Shared.csproj" />
|
<ProjectReference Include="..\Oqtane.Shared\Oqtane.Shared.csproj" />
|
||||||
<ProjectReference Include="..\Oqtane.Upgrade\Oqtane.Upgrade.csproj" />
|
<ProjectReference Include="..\Oqtane.Upgrade\Oqtane.Upgrade.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
@ -1,37 +1,102 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
using Oqtane.Extensions;
|
using Oqtane.Extensions;
|
||||||
using Oqtane.Models;
|
using Oqtane.Interfaces;
|
||||||
|
using Oqtane.Migrations.Framework;
|
||||||
|
using Oqtane.Repository.Databases.Interfaces;
|
||||||
|
using Oqtane.Shared;
|
||||||
|
|
||||||
|
// ReSharper disable BuiltInTypeReferenceStyleForMemberAccess
|
||||||
|
|
||||||
namespace Oqtane.Repository
|
namespace Oqtane.Repository
|
||||||
{
|
{
|
||||||
public class DBContextBase : IdentityUserContext<IdentityUser>
|
public class DBContextBase : IdentityUserContext<IdentityUser>
|
||||||
{
|
{
|
||||||
private ITenantResolver _tenantResolver;
|
private readonly ITenantResolver _tenantResolver;
|
||||||
private IHttpContextAccessor _accessor;
|
private readonly IHttpContextAccessor _accessor;
|
||||||
|
private readonly IConfiguration _configuration;
|
||||||
|
private string _connectionString;
|
||||||
|
private string _databaseType;
|
||||||
|
|
||||||
public DBContextBase(ITenantResolver tenantResolver, IHttpContextAccessor accessor)
|
public DBContextBase(ITenantResolver tenantResolver, IHttpContextAccessor httpContextAccessor)
|
||||||
{
|
{
|
||||||
|
_connectionString = String.Empty;
|
||||||
_tenantResolver = tenantResolver;
|
_tenantResolver = tenantResolver;
|
||||||
_accessor = accessor;
|
_accessor = httpContextAccessor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DBContextBase(IDbConfig dbConfig, ITenantResolver tenantResolver)
|
||||||
|
{
|
||||||
|
_accessor = dbConfig.Accessor;
|
||||||
|
_configuration = dbConfig.Configuration;
|
||||||
|
_connectionString = dbConfig.ConnectionString;
|
||||||
|
_databaseType = dbConfig.DatabaseType;
|
||||||
|
Databases = dbConfig.Databases;
|
||||||
|
_tenantResolver = tenantResolver;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<IOqtaneDatabase> Databases { get; }
|
||||||
|
|
||||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||||
{
|
{
|
||||||
var tenant = _tenantResolver.GetTenant();
|
optionsBuilder.ReplaceService<IMigrationsAssembly, MultiDatabaseMigrationsAssembly>();
|
||||||
if (tenant != null)
|
|
||||||
|
if (string.IsNullOrEmpty(_connectionString) && _tenantResolver != null)
|
||||||
{
|
{
|
||||||
var connectionString = tenant.DBConnectionString
|
var tenant = _tenantResolver.GetTenant();
|
||||||
.Replace("|DataDirectory|", AppDomain.CurrentDomain.GetData("DataDirectory")?.ToString());
|
|
||||||
optionsBuilder.UseOqtaneDatabase(connectionString);
|
if (tenant != null)
|
||||||
|
{
|
||||||
|
_connectionString = tenant.DBConnectionString
|
||||||
|
.Replace("|DataDirectory|", AppDomain.CurrentDomain.GetData("DataDirectory")?.ToString());
|
||||||
|
_databaseType = tenant.DBType;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!String.IsNullOrEmpty(_configuration.GetConnectionString("DefaultConnection")))
|
||||||
|
{
|
||||||
|
_connectionString = _configuration.GetConnectionString("DefaultConnection")
|
||||||
|
.Replace("|DataDirectory|", AppDomain.CurrentDomain.GetData("DataDirectory")?.ToString());
|
||||||
|
}
|
||||||
|
_databaseType = _configuration.GetSection(SettingKeys.DatabaseSection)[SettingKeys.DatabaseTypeKey];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(_connectionString) && !string.IsNullOrEmpty(_databaseType))
|
||||||
|
{
|
||||||
|
if (Databases != null)
|
||||||
|
{
|
||||||
|
optionsBuilder.UseOqtaneDatabase(Databases.Single(d => d.Name == _databaseType), _connectionString);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
optionsBuilder.UseOqtaneDatabase(_databaseType, _connectionString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
base.OnConfiguring(optionsBuilder);
|
base.OnConfiguring(optionsBuilder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void OnModelCreating(ModelBuilder builder)
|
||||||
|
{
|
||||||
|
base.OnModelCreating(builder);
|
||||||
|
|
||||||
|
if (Databases != null)
|
||||||
|
{
|
||||||
|
var database = Databases.Single(d => d.Name == _databaseType);
|
||||||
|
|
||||||
|
database.UpdateIdentityStoreTableNames(builder);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public override int SaveChanges()
|
public override int SaveChanges()
|
||||||
{
|
{
|
||||||
DbContextUtils.SaveChanges(this, _accessor);
|
DbContextUtils.SaveChanges(this, _accessor);
|
||||||
|
|
27
Oqtane.Server/Repository/Context/DbConfig.cs
Normal file
27
Oqtane.Server/Repository/Context/DbConfig.cs
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
|
||||||
|
namespace Oqtane.Repository
|
||||||
|
{
|
||||||
|
public class DbConfig : IDbConfig
|
||||||
|
{
|
||||||
|
public DbConfig(IHttpContextAccessor accessor, IConfiguration configuration, IEnumerable<IOqtaneDatabase> databases)
|
||||||
|
{
|
||||||
|
Accessor = accessor;
|
||||||
|
Configuration = configuration;
|
||||||
|
Databases = databases;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IHttpContextAccessor Accessor { get; }
|
||||||
|
|
||||||
|
public IConfiguration Configuration { get; }
|
||||||
|
|
||||||
|
public IEnumerable<IOqtaneDatabase> Databases { get; set; }
|
||||||
|
|
||||||
|
public string ConnectionString { get; set; }
|
||||||
|
|
||||||
|
public string DatabaseType { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,7 +6,7 @@ using Oqtane.Models;
|
||||||
|
|
||||||
namespace Oqtane.Repository
|
namespace Oqtane.Repository
|
||||||
{
|
{
|
||||||
public class DbContextUtils
|
public static class DbContextUtils
|
||||||
{
|
{
|
||||||
public static void SaveChanges(DbContext context, IHttpContextAccessor accessor)
|
public static void SaveChanges(DbContext context, IHttpContextAccessor accessor)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,26 +1,36 @@
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore.Storage;
|
||||||
using Oqtane.Extensions;
|
using Oqtane.Extensions;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
using Oqtane.Models;
|
using Oqtane.Models;
|
||||||
|
|
||||||
|
// ReSharper disable CheckNamespace
|
||||||
|
// ReSharper disable MemberCanBePrivate.Global
|
||||||
|
// ReSharper disable UnusedAutoPropertyAccessor.Global
|
||||||
|
|
||||||
namespace Oqtane.Repository
|
namespace Oqtane.Repository
|
||||||
{
|
{
|
||||||
|
|
||||||
public class InstallationContext : DbContext
|
public class InstallationContext : DbContext
|
||||||
{
|
{
|
||||||
private readonly string _connectionString;
|
private readonly string _connectionString;
|
||||||
|
private readonly IOqtaneDatabase _database;
|
||||||
|
|
||||||
public InstallationContext(string connectionString)
|
public InstallationContext(IOqtaneDatabase database, string connectionString)
|
||||||
{
|
{
|
||||||
_connectionString = connectionString;
|
_connectionString = connectionString;
|
||||||
|
_database = database;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||||
=> optionsBuilder.UseOqtaneDatabase(_connectionString);
|
=> optionsBuilder.UseOqtaneDatabase(_database, _connectionString);
|
||||||
|
|
||||||
public virtual DbSet<Alias> Alias { get; set; }
|
public virtual DbSet<Alias> Alias { get; set; }
|
||||||
public virtual DbSet<Tenant> Tenant { get; set; }
|
public virtual DbSet<Tenant> Tenant { get; set; }
|
||||||
public virtual DbSet<ModuleDefinition> ModuleDefinition { get; set; }
|
public virtual DbSet<ModuleDefinition> ModuleDefinition { get; set; }
|
||||||
public virtual DbSet<Job> Job { get; set; }
|
public virtual DbSet<Job> Job { get; set; }
|
||||||
|
public virtual DbSet<JobLog> JobLog { get; set; }
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,33 +1,65 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
using Oqtane.Models;
|
using Oqtane.Models;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Oqtane.Extensions;
|
using Oqtane.Extensions;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
using Oqtane.Migrations.Framework;
|
||||||
|
using Oqtane.Repository.Databases.Interfaces;
|
||||||
|
using Oqtane.Shared;
|
||||||
|
|
||||||
|
// ReSharper disable BuiltInTypeReferenceStyleForMemberAccess
|
||||||
|
// ReSharper disable UnusedAutoPropertyAccessor.Global
|
||||||
|
// ReSharper disable CheckNamespace
|
||||||
|
|
||||||
namespace Oqtane.Repository
|
namespace Oqtane.Repository
|
||||||
{
|
{
|
||||||
public class MasterDBContext : DbContext
|
public class MasterDBContext : DbContext, IMultiDatabase
|
||||||
{
|
{
|
||||||
private readonly IHttpContextAccessor _accessor;
|
private readonly IDbConfig _dbConfig;
|
||||||
private readonly IConfiguration _configuration;
|
|
||||||
|
|
||||||
public MasterDBContext(DbContextOptions<MasterDBContext> options, IHttpContextAccessor accessor, IConfiguration configuration) : base(options)
|
public MasterDBContext(DbContextOptions<MasterDBContext> options, IDbConfig dbConfig) : base(options)
|
||||||
{
|
{
|
||||||
_accessor = accessor;
|
_dbConfig = dbConfig;
|
||||||
_configuration = configuration;
|
Databases = dbConfig.Databases;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IEnumerable<IOqtaneDatabase> Databases { get; }
|
||||||
|
|
||||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||||
{
|
{
|
||||||
if (!String.IsNullOrEmpty(_configuration.GetConnectionString("DefaultConnection")))
|
optionsBuilder.ReplaceService<IMigrationsAssembly, MultiDatabaseMigrationsAssembly>();
|
||||||
{
|
|
||||||
var connectionString = _configuration.GetConnectionString("DefaultConnection")
|
|
||||||
.Replace("|DataDirectory|", AppDomain.CurrentDomain.GetData("DataDirectory")?.ToString());
|
|
||||||
|
|
||||||
optionsBuilder.UseOqtaneDatabase(connectionString);
|
var connectionString = _dbConfig.ConnectionString;
|
||||||
|
var configuration = _dbConfig.Configuration;
|
||||||
|
var databaseType = _dbConfig.DatabaseType;
|
||||||
|
|
||||||
|
if(string.IsNullOrEmpty(connectionString) && configuration != null)
|
||||||
|
{
|
||||||
|
if (!String.IsNullOrEmpty(configuration.GetConnectionString("DefaultConnection")))
|
||||||
|
{
|
||||||
|
connectionString = configuration.GetConnectionString("DefaultConnection")
|
||||||
|
.Replace("|DataDirectory|", AppDomain.CurrentDomain.GetData("DataDirectory")?.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
databaseType = configuration.GetSection(SettingKeys.DatabaseSection)[SettingKeys.DatabaseTypeKey];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(connectionString) && !string.IsNullOrEmpty(databaseType))
|
||||||
|
{
|
||||||
|
if (Databases != null)
|
||||||
|
{
|
||||||
|
optionsBuilder.UseOqtaneDatabase(Databases.Single(d => d.Name == databaseType), connectionString);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
optionsBuilder.UseOqtaneDatabase(databaseType, connectionString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
base.OnConfiguring(optionsBuilder);
|
base.OnConfiguring(optionsBuilder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,7 +71,7 @@ namespace Oqtane.Repository
|
||||||
|
|
||||||
public override int SaveChanges()
|
public override int SaveChanges()
|
||||||
{
|
{
|
||||||
DbContextUtils.SaveChanges(this, _accessor);
|
DbContextUtils.SaveChanges(this, _dbConfig.Accessor);
|
||||||
|
|
||||||
return base.SaveChanges();
|
return base.SaveChanges();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,19 @@
|
||||||
using Microsoft.AspNetCore.Http;
|
using System.Collections.Generic;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
using Oqtane.Models;
|
using Oqtane.Models;
|
||||||
|
using Oqtane.Repository.Databases.Interfaces;
|
||||||
|
|
||||||
|
// ReSharper disable CheckNamespace
|
||||||
|
// ReSharper disable MemberCanBePrivate.Global
|
||||||
|
// ReSharper disable UnusedAutoPropertyAccessor.Global
|
||||||
|
|
||||||
namespace Oqtane.Repository
|
namespace Oqtane.Repository
|
||||||
{
|
{
|
||||||
public class TenantDBContext : DBContextBase
|
public class TenantDBContext : DBContextBase, IMultiDatabase
|
||||||
{
|
{
|
||||||
|
public TenantDBContext(IDbConfig dbConfig, ITenantResolver tenantResolver) : base(dbConfig, tenantResolver) { }
|
||||||
|
|
||||||
public virtual DbSet<Site> Site { get; set; }
|
public virtual DbSet<Site> Site { get; set; }
|
||||||
public virtual DbSet<Page> Page { get; set; }
|
public virtual DbSet<Page> Page { get; set; }
|
||||||
public virtual DbSet<PageModule> PageModule { get; set; }
|
public virtual DbSet<PageModule> PageModule { get; set; }
|
||||||
|
@ -20,13 +28,6 @@ namespace Oqtane.Repository
|
||||||
public virtual DbSet<Notification> Notification { get; set; }
|
public virtual DbSet<Notification> Notification { get; set; }
|
||||||
public virtual DbSet<Folder> Folder { get; set; }
|
public virtual DbSet<Folder> Folder { get; set; }
|
||||||
public virtual DbSet<File> File { get; set; }
|
public virtual DbSet<File> File { get; set; }
|
||||||
|
|
||||||
public virtual DbSet<Language> Language { get; set; }
|
public virtual DbSet<Language> Language { get; set; }
|
||||||
|
|
||||||
public TenantDBContext(ITenantResolver tenantResolver, IHttpContextAccessor accessor) : base(tenantResolver, accessor)
|
|
||||||
{
|
|
||||||
// DBContextBase handles multi-tenant database connections
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
20
Oqtane.Server/Repository/Interfaces/IDbConfig.cs
Normal file
20
Oqtane.Server/Repository/Interfaces/IDbConfig.cs
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Oqtane.Interfaces;
|
||||||
|
|
||||||
|
namespace Oqtane.Repository
|
||||||
|
{
|
||||||
|
public interface IDbConfig
|
||||||
|
{
|
||||||
|
public IHttpContextAccessor Accessor { get; }
|
||||||
|
|
||||||
|
public IConfiguration Configuration { get; }
|
||||||
|
|
||||||
|
public IEnumerable<IOqtaneDatabase> Databases { get; set; }
|
||||||
|
|
||||||
|
public string ConnectionString { get; set; }
|
||||||
|
|
||||||
|
public string DatabaseType { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
using System.Data.SqlClient;
|
using System.Reflection;
|
||||||
using System.Reflection;
|
using Microsoft.Data.SqlClient;
|
||||||
using Oqtane.Models;
|
using Oqtane.Models;
|
||||||
|
|
||||||
namespace Oqtane.Repository
|
namespace Oqtane.Repository
|
||||||
|
@ -7,8 +7,13 @@ namespace Oqtane.Repository
|
||||||
public interface ISqlRepository
|
public interface ISqlRepository
|
||||||
{
|
{
|
||||||
void ExecuteScript(Tenant tenant, string script);
|
void ExecuteScript(Tenant tenant, string script);
|
||||||
|
|
||||||
|
bool ExecuteScript(string connectionString, Assembly assembly, string filename);
|
||||||
|
|
||||||
bool ExecuteScript(Tenant tenant, Assembly assembly, string filename);
|
bool ExecuteScript(Tenant tenant, Assembly assembly, string filename);
|
||||||
|
|
||||||
int ExecuteNonQuery(Tenant tenant, string query);
|
int ExecuteNonQuery(Tenant tenant, string query);
|
||||||
|
|
||||||
SqlDataReader ExecuteReader(Tenant tenant, string query);
|
SqlDataReader ExecuteReader(Tenant tenant, string query);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Data;
|
using System.Data;
|
||||||
using System.Data.SqlClient;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using Microsoft.Data.SqlClient;
|
||||||
using Oqtane.Models;
|
using Oqtane.Models;
|
||||||
|
// ReSharper disable ConvertToUsingDeclaration
|
||||||
|
// ReSharper disable InvertIf
|
||||||
|
// ReSharper disable BuiltInTypeReferenceStyleForMemberAccess
|
||||||
|
|
||||||
namespace Oqtane.Repository
|
namespace Oqtane.Repository
|
||||||
{
|
{
|
||||||
|
@ -13,35 +16,41 @@ namespace Oqtane.Repository
|
||||||
|
|
||||||
public void ExecuteScript(Tenant tenant, string script)
|
public void ExecuteScript(Tenant tenant, string script)
|
||||||
{
|
{
|
||||||
// execute script in curent tenant
|
// execute script in current tenant
|
||||||
foreach (string query in script.Split("GO", StringSplitOptions.RemoveEmptyEntries))
|
foreach (var query in script.Split("GO", StringSplitOptions.RemoveEmptyEntries))
|
||||||
{
|
{
|
||||||
ExecuteNonQuery(tenant, query);
|
ExecuteNonQuery(tenant, query);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ExecuteScript(Tenant tenant, Assembly assembly, string filename)
|
public bool ExecuteScript(string connectionString, Assembly assembly, string fileName)
|
||||||
{
|
{
|
||||||
// script must be included as an Embedded Resource within an assembly
|
var success = true;
|
||||||
bool success = true;
|
var script = GetScriptFromAssembly(assembly, fileName);
|
||||||
string script = "";
|
|
||||||
|
|
||||||
if (assembly != null)
|
if (!string.IsNullOrEmpty(script))
|
||||||
{
|
{
|
||||||
string name = assembly.GetManifestResourceNames().FirstOrDefault(item => item.EndsWith("." + filename));
|
try
|
||||||
if (name != null)
|
|
||||||
{
|
{
|
||||||
Stream resourceStream = assembly.GetManifestResourceStream(name);
|
foreach (var query in script.Split("GO", StringSplitOptions.RemoveEmptyEntries))
|
||||||
if (resourceStream != null)
|
|
||||||
{
|
{
|
||||||
using (var reader = new StreamReader(resourceStream))
|
ExecuteNonQuery(connectionString, query);
|
||||||
{
|
|
||||||
script = reader.ReadToEnd();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ExecuteScript(Tenant tenant, Assembly assembly, string fileName)
|
||||||
|
{
|
||||||
|
var success = true;
|
||||||
|
var script = GetScriptFromAssembly(assembly, fileName);
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(script))
|
if (!string.IsNullOrEmpty(script))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -58,13 +67,27 @@ namespace Oqtane.Repository
|
||||||
}
|
}
|
||||||
|
|
||||||
public int ExecuteNonQuery(Tenant tenant, string query)
|
public int ExecuteNonQuery(Tenant tenant, string query)
|
||||||
|
{
|
||||||
|
return ExecuteNonQuery(tenant.DBConnectionString, query);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SqlDataReader ExecuteReader(Tenant tenant, string query)
|
||||||
{
|
{
|
||||||
SqlConnection conn = new SqlConnection(FormatConnectionString(tenant.DBConnectionString));
|
SqlConnection conn = new SqlConnection(FormatConnectionString(tenant.DBConnectionString));
|
||||||
SqlCommand cmd = conn.CreateCommand();
|
SqlCommand cmd = conn.CreateCommand();
|
||||||
|
PrepareCommand(conn, cmd, query);
|
||||||
|
var dr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
|
||||||
|
return dr;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int ExecuteNonQuery(string connectionString, string query)
|
||||||
|
{
|
||||||
|
var conn = new SqlConnection(FormatConnectionString(connectionString));
|
||||||
|
var cmd = conn.CreateCommand();
|
||||||
using (conn)
|
using (conn)
|
||||||
{
|
{
|
||||||
PrepareCommand(conn, cmd, query);
|
PrepareCommand(conn, cmd, query);
|
||||||
int val = -1;
|
var val = -1;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
val = cmd.ExecuteNonQuery();
|
val = cmd.ExecuteNonQuery();
|
||||||
|
@ -77,13 +100,28 @@ namespace Oqtane.Repository
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public SqlDataReader ExecuteReader(Tenant tenant, string query)
|
private string GetScriptFromAssembly(Assembly assembly, string fileName)
|
||||||
{
|
{
|
||||||
SqlConnection conn = new SqlConnection(FormatConnectionString(tenant.DBConnectionString));
|
// script must be included as an Embedded Resource within an assembly
|
||||||
SqlCommand cmd = conn.CreateCommand();
|
var script = "";
|
||||||
PrepareCommand(conn, cmd, query);
|
|
||||||
var dr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
|
if (assembly != null)
|
||||||
return dr;
|
{
|
||||||
|
var name = assembly.GetManifestResourceNames().FirstOrDefault(item => item.EndsWith("." + fileName));
|
||||||
|
if (name != null)
|
||||||
|
{
|
||||||
|
var resourceStream = assembly.GetManifestResourceStream(name);
|
||||||
|
if (resourceStream != null)
|
||||||
|
{
|
||||||
|
using (var reader = new StreamReader(resourceStream))
|
||||||
|
{
|
||||||
|
script = reader.ReadToEnd();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return script;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PrepareCommand(SqlConnection conn, SqlCommand cmd, string query)
|
private void PrepareCommand(SqlConnection conn, SqlCommand cmd, string query)
|
||||||
|
|
17
Oqtane.Server/Scripts/MigrateMaster.sql
Normal file
17
Oqtane.Server/Scripts/MigrateMaster.sql
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'dbo.SchemaVersions') AND OBJECTPROPERTY(id, N'IsTable') = 1)
|
||||||
|
BEGIN
|
||||||
|
IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'dbo.__EFMigrationsHistory') AND OBJECTPROPERTY(id, N'IsTable') = 1)
|
||||||
|
BEGIN
|
||||||
|
CREATE TABLE __EFMigrationsHistory
|
||||||
|
(
|
||||||
|
MigrationId nvarchar(150) NOT NULL CONSTRAINT PK___EFMigrationsHistory PRIMARY KEY,
|
||||||
|
ProductVersion nvarchar(32) NOT NULL
|
||||||
|
)
|
||||||
|
END
|
||||||
|
INSERT INTO __EFMigrationsHistory(MigrationId, ProductVersion)
|
||||||
|
VALUES ('Master.01.00.00.00', '5.0.0')
|
||||||
|
INSERT INTO __EFMigrationsHistory(MigrationId, ProductVersion)
|
||||||
|
SELECT REPLACE(REPLACE(ScriptName, 'Oqtane.Scripts.', ''), '.sql', '') As MigrationId, ProductVersion = '5.0.0'
|
||||||
|
FROM SchemaVersions
|
||||||
|
WHERE ScriptName LIKE 'Oqtane.Scripts.Master.01%'
|
||||||
|
END
|
20
Oqtane.Server/Scripts/MigrateTenant.sql
Normal file
20
Oqtane.Server/Scripts/MigrateTenant.sql
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'dbo.SchemaVersions') AND OBJECTPROPERTY(id, N'IsTable') = 1)
|
||||||
|
BEGIN
|
||||||
|
IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'dbo.__EFMigrationsHistory') AND OBJECTPROPERTY(id, N'IsTable') = 1)
|
||||||
|
BEGIN
|
||||||
|
CREATE TABLE __EFMigrationsHistory
|
||||||
|
(
|
||||||
|
MigrationId nvarchar(150) NOT NULL CONSTRAINT PK___EFMigrationsHistory PRIMARY KEY,
|
||||||
|
ProductVersion nvarchar(32) NOT NULL
|
||||||
|
)
|
||||||
|
END
|
||||||
|
INSERT INTO __EFMigrationsHistory(MigrationId, ProductVersion)
|
||||||
|
VALUES ('Tenant.01.00.00.00', '5.0.0')
|
||||||
|
INSERT INTO __EFMigrationsHistory(MigrationId, ProductVersion)
|
||||||
|
SELECT REPLACE(REPLACE(ScriptName, 'Oqtane.Scripts.', ''), '.sql', '') As MigrationId, ProductVersion = '5.0.0'
|
||||||
|
FROM SchemaVersions
|
||||||
|
WHERE ScriptName LIKE 'Oqtane.Scripts.Tenant.01%'
|
||||||
|
OR ScriptName LIKE 'Oqtane.Scripts.Tenant.02%'
|
||||||
|
INSERT INTO __EFMigrationsHistory(MigrationId, ProductVersion)
|
||||||
|
VALUES ('HtmlText.01.00.00.00', '5.0.0')
|
||||||
|
END
|
|
@ -129,9 +129,6 @@ namespace Oqtane
|
||||||
|
|
||||||
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
|
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
|
||||||
|
|
||||||
services.AddDbContext<MasterDBContext>(options => { });
|
|
||||||
services.AddDbContext<TenantDBContext>(options => { });
|
|
||||||
|
|
||||||
services.AddIdentityCore<IdentityUser>(options => { })
|
services.AddIdentityCore<IdentityUser>(options => { })
|
||||||
.AddEntityFrameworkStores<TenantDBContext>()
|
.AddEntityFrameworkStores<TenantDBContext>()
|
||||||
.AddSignInManager()
|
.AddSignInManager()
|
||||||
|
@ -212,6 +209,10 @@ namespace Oqtane
|
||||||
|
|
||||||
// load the external assemblies into the app domain, install services
|
// load the external assemblies into the app domain, install services
|
||||||
services.AddOqtane(_runtime, _supportedCultures);
|
services.AddOqtane(_runtime, _supportedCultures);
|
||||||
|
services.AddScoped<IDbConfig, DbConfig>();
|
||||||
|
services.AddDbContext<MasterDBContext>(options => { });
|
||||||
|
services.AddDbContext<TenantDBContext>(options => { });
|
||||||
|
|
||||||
|
|
||||||
services.AddMvc()
|
services.AddMvc()
|
||||||
.AddNewtonsoftJson()
|
.AddNewtonsoftJson()
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
{
|
{
|
||||||
|
"Database": {
|
||||||
|
"DatabaseType": ""
|
||||||
|
},
|
||||||
"ConnectionStrings": {
|
"ConnectionStrings": {
|
||||||
"DefaultConnection": ""
|
"DefaultConnection": ""
|
||||||
},
|
},
|
||||||
|
|
1
Oqtane.Server/wwwroot/Modules/Oqtane.Blogs/Module.css
Normal file
1
Oqtane.Server/wwwroot/Modules/Oqtane.Blogs/Module.css
Normal file
|
@ -0,0 +1 @@
|
||||||
|
/* Module Custom Styles */
|
1
Oqtane.Server/wwwroot/Modules/Oqtane.Blogs/Module.js
Normal file
1
Oqtane.Server/wwwroot/Modules/Oqtane.Blogs/Module.js
Normal file
|
@ -0,0 +1 @@
|
||||||
|
/* Module Script */
|
1
Oqtane.Server/wwwroot/Modules/Oqtane.Blogs/assets.json
Normal file
1
Oqtane.Server/wwwroot/Modules/Oqtane.Blogs/assets.json
Normal file
|
@ -0,0 +1 @@
|
||||||
|
["\\bin\\Debug\\net5.0\\Oqtane.Blogs.Client.Oqtane.dll","\\bin\\Debug\\net5.0\\Oqtane.Blogs.Client.Oqtane.pdb","\\bin\\Debug\\net5.0\\Oqtane.Blogs.Server.Oqtane.dll","\\bin\\Debug\\net5.0\\Oqtane.Blogs.Server.Oqtane.pdb","\\bin\\Debug\\net5.0\\Oqtane.Blogs.Shared.Oqtane.dll","\\bin\\Debug\\net5.0\\Oqtane.Blogs.Shared.Oqtane.pdb","\\wwwroot\\Modules\\Oqtane.Blogs\\Module.css","\\wwwroot\\Modules\\Oqtane.Blogs\\Module.js"]
|
8
Oqtane.Shared/Enums/MigrationType.cs
Normal file
8
Oqtane.Shared/Enums/MigrationType.cs
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
namespace Oqtane.Enums
|
||||||
|
{
|
||||||
|
public enum MigrationType
|
||||||
|
{
|
||||||
|
Up,
|
||||||
|
Down
|
||||||
|
}
|
||||||
|
}
|
31
Oqtane.Shared/Interfaces/IOqtaneDatabase.cs
Normal file
31
Oqtane.Shared/Interfaces/IOqtaneDatabase.cs
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders;
|
||||||
|
using Oqtane.Models;
|
||||||
|
|
||||||
|
namespace Oqtane.Interfaces
|
||||||
|
{
|
||||||
|
public interface IOqtaneDatabase
|
||||||
|
{
|
||||||
|
public string FriendlyName { get; }
|
||||||
|
|
||||||
|
public string Name { get; }
|
||||||
|
|
||||||
|
public string Provider { get; }
|
||||||
|
|
||||||
|
public List<ConnectionStringField> ConnectionStringFields { get; }
|
||||||
|
|
||||||
|
public OperationBuilder<AddColumnOperation> AddAutoIncrementColumn(ColumnsBuilder table, string name);
|
||||||
|
|
||||||
|
public string BuildConnectionString();
|
||||||
|
|
||||||
|
public string ConcatenateSql(params string[] values);
|
||||||
|
|
||||||
|
public string RewriteName(string name);
|
||||||
|
|
||||||
|
public void UpdateIdentityStoreTableNames(ModelBuilder builder);
|
||||||
|
|
||||||
|
public DbContextOptionsBuilder UseDatabase(DbContextOptionsBuilder optionsBuilder, string connectionString);
|
||||||
|
}
|
||||||
|
}
|
13
Oqtane.Shared/Models/ConnectionStringField.cs
Normal file
13
Oqtane.Shared/Models/ConnectionStringField.cs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
namespace Oqtane.Models
|
||||||
|
{
|
||||||
|
public class ConnectionStringField
|
||||||
|
{
|
||||||
|
public string FriendlyName { get; set; }
|
||||||
|
|
||||||
|
public string HelpText { get; set; }
|
||||||
|
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
public string Value { get; set; }
|
||||||
|
}
|
||||||
|
}
|
9
Oqtane.Shared/Models/Database.cs
Normal file
9
Oqtane.Shared/Models/Database.cs
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
namespace Oqtane.Models
|
||||||
|
{
|
||||||
|
public class Database
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
public string Type { get; set; }
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user