Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add database options like TablePrefixSeparator, Schema, IdentityColumnType, and DocumentTable #12683

Merged
merged 48 commits into from
Jan 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
828512c
Add support for configuring database options like DocumentTable, Sche…
MikeAlhayek Oct 21, 2022
4042ae8
Fix unit tests and some cleanup
MikeAlhayek Oct 21, 2022
688a7c4
Cleanup
MikeAlhayek Oct 22, 2022
a344040
Add database ptions to the setup screen
MikeAlhayek Oct 22, 2022
1d7d900
Update src/OrchardCore/OrchardCore.Abstractions/Setup/SetupConstants.cs
MikeAlhayek Oct 23, 2022
6a40640
clean up
MikeAlhayek Oct 23, 2022
673def9
Clean up
MikeAlhayek Oct 23, 2022
f96bd15
Update src/OrchardCore.Modules/OrchardCore.AutoSetup/AutoSetupMiddlew…
MikeAlhayek Oct 24, 2022
2eaf317
Update src/OrchardCore.Modules/OrchardCore.AutoSetup/AutoSetupMiddlew…
MikeAlhayek Oct 24, 2022
1a6550b
More clean up and add field to the setup/create activities
MikeAlhayek Oct 24, 2022
ecace50
Merge branch 'YesSqlOptionsEnhancements' of https://github.com/CrestA…
MikeAlhayek Oct 24, 2022
95680f4
Work in progress
jtkech Oct 25, 2022
7209251
WIP
jtkech Oct 26, 2022
a758c8a
Should use Enum.IsDefined() as by default ColSize is neither "Int32" …
jtkech Oct 26, 2022
6b1d243
Wip
jtkech Oct 27, 2022
52b94a6
Fix Tests build
jtkech Oct 27, 2022
1096720
Minor changes
jtkech Oct 27, 2022
0d9f7de
Update regular expression
jtkech Oct 27, 2022
41d2a6e
Merge remote-tracking branch 'origin/main' into YesSqlOptionsEnhancem…
jtkech Oct 27, 2022
4e29139
Minor change
jtkech Oct 27, 2022
57eb090
Merge remote-tracking branch 'origin/main' into YesSqlOptionsEnhancem…
jtkech Dec 24, 2022
6f61e68
Update after merging dev
jtkech Dec 24, 2022
cb18b95
WIP
jtkech Dec 26, 2022
4c1c753
wip
jtkech Dec 27, 2022
fcfc978
wip
jtkech Dec 27, 2022
3aea8bc
wip and doc
jtkech Dec 28, 2022
ace7b33
Missing changes
jtkech Dec 28, 2022
804839b
wip
jtkech Dec 29, 2022
7baa301
tweaks
jtkech Dec 30, 2022
b9a1a7b
minor changes
jtkech Dec 30, 2022
09aabfb
Little revert
jtkech Dec 30, 2022
bb83861
Last tweaks
jtkech Dec 31, 2022
424987a
Minor changes
jtkech Jan 1, 2023
199b675
Anticipate #13021
jtkech Jan 2, 2023
d82dd6c
Limit re-evals / allocs while checking urlHosts with all other tenants
jtkech Jan 2, 2023
77f1a9a
Minor change
jtkech Jan 2, 2023
a9f6764
Update src/OrchardCore.Modules/OrchardCore.Tenants/Controllers/AdminC…
MikeAlhayek Jan 3, 2023
8e5b6ed
React to review
jtkech Jan 3, 2023
e5d262c
Update src/OrchardCore.Modules/OrchardCore.AutoSetup/Options/TenantSe…
MikeAlhayek Jan 3, 2023
812c26e
Update src/OrchardCore/OrchardCore.Data.Abstractions/ShellSettingsExt…
MikeAlhayek Jan 3, 2023
ffebf50
Update src/OrchardCore.Modules/OrchardCore.Tenants/ViewModels/SetupAp…
MikeAlhayek Jan 3, 2023
f6ff29e
Update src/OrchardCore.Modules/OrchardCore.Tenants/Controllers/AdminC…
MikeAlhayek Jan 3, 2023
880bcb7
Update src/OrchardCore.Modules/OrchardCore.Setup/Controllers/SetupCon…
MikeAlhayek Jan 3, 2023
b1cbfcb
Update src/OrchardCore.Modules/OrchardCore.Tenants/Controllers/AdminC…
MikeAlhayek Jan 3, 2023
82aeb8a
Minor cleanup
MikeAlhayek Jan 3, 2023
536ff5a
Update src/OrchardCore.Modules/OrchardCore.Tenants/Controllers/AdminC…
MikeAlhayek Jan 3, 2023
5b8fb5b
Fix build error
MikeAlhayek Jan 3, 2023
fd5a136
Remove useless project reference and minor changes
jtkech Jan 3, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/OrchardCore.Cms.Web/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,16 @@
//"OrchardCore_ContentLocalization_CulturePickerOptions": {
// "CookieLifeTime": 14 // Set the culture picker cookie life time (in days).
//},
// See https://docs.orchardcore.net/en/latest/docs/reference/core/Data/#sqlite.
//"OrchardCore_Data_Sqlite": {
// "UseConnectionPooling": false
//},
// See https://docs.orchardcore.net/en/latest/docs/reference/core/Data/#database-table to configure database table presets used before a given tenant is setup.
//"OrchardCore_Data_TableOptions": {
// "DefaultDocumentTable": "Document", // Document table name, defaults to 'Document'.
// "DefaultTableNameSeparator": "_", // Table name separator, one or multiple '_', "NULL" means no separator, defaults to '_'.
// "DefaultIdentityColumnSize": "Int64" // Identity column size, 'Int32' or 'Int64', defaults to 'Int64'.
//},
// See https://docs.orchardcore.net/en/latest/docs/reference/modules/DataProtection.Azure/#configuration to configure data protection key storage in Azure Blob Storage.
//"OrchardCore_DataProtection_Azure": {
// "ConnectionString": "", // Set to your Azure Storage account connection string.
Expand Down Expand Up @@ -145,6 +152,7 @@
// "DatabaseProvider": "Sqlite",
// "DatabaseConnectionString": "",
// "DatabaseTablePrefix": "",
// "DatabaseSchema": "",
// "RecipeName": "SaaS"
// },
// {
Expand All @@ -157,6 +165,7 @@
// "DatabaseProvider": "Sqlite",
// "DatabaseConnectionString": "",
// "DatabaseTablePrefix": "tenant",
// "DatabaseSchema": "",
// "RecipeName": "Agency",
// "RequestUrlHost": "",
// "RequestUrlPrefix": "tenant"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ public async Task<ShellSettings> CreateTenantSettingsAsync(TenantSetupOptions se

shellSettings["ConnectionString"] = setupOptions.DatabaseConnectionString;
shellSettings["TablePrefix"] = setupOptions.DatabaseTablePrefix;
shellSettings["Schema"] = setupOptions.DatabaseSchema;
shellSettings["DatabaseProvider"] = setupOptions.DatabaseProvider;
shellSettings["Secret"] = Guid.NewGuid().ToString();
shellSettings["RecipeName"] = setupOptions.RecipeName;
Expand Down Expand Up @@ -250,6 +251,7 @@ private static async Task<SetupContext> GetSetupContextAsync(TenantSetupOptions
setupContext.Properties[SetupConstants.DatabaseConnectionString] = options.DatabaseConnectionString;
setupContext.Properties[SetupConstants.DatabaseProvider] = options.DatabaseProvider;
setupContext.Properties[SetupConstants.DatabaseTablePrefix] = options.DatabaseTablePrefix;
setupContext.Properties[SetupConstants.DatabaseSchema] = options.DatabaseSchema;
setupContext.Properties[SetupConstants.SiteName] = options.SiteName;
setupContext.Properties[SetupConstants.SiteTimeZone] = options.SiteTimeZone;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ public class TenantSetupOptions
/// </summary>
public string DatabaseTablePrefix { get; set; }

/// <summary>
/// Gets or sets the database's schema.
/// </summary>
public string DatabaseSchema { get; set; }

/// <summary>
/// Gets or sets the recipe name.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\OrchardCore\OrchardCore.Abstractions\OrchardCore.Abstractions.csproj" />
<ProjectReference Include="..\..\OrchardCore\OrchardCore.Setup.Abstractions\OrchardCore.Setup.Abstractions.csproj" />
</ItemGroup>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public async Task<ActionResult> Index(string token)
DatabaseProviders = _databaseProviders,
Recipes = recipes,
RecipeName = defaultRecipe?.Name,
Secret = token
Secret = token,
MikeAlhayek marked this conversation as resolved.
Show resolved Hide resolved
};

CopyShellSettingsValues(model);
Expand All @@ -80,6 +80,12 @@ public async Task<ActionResult> Index(string token)
model.TablePrefix = _shellSettings["TablePrefix"];
}

if (!String.IsNullOrEmpty(_shellSettings["Schema"]))
{
model.DatabaseConfigurationPreset = true;
model.Schema = _shellSettings["Schema"];
}

return View(model);
}

Expand Down Expand Up @@ -157,12 +163,14 @@ public async Task<ActionResult> IndexPOST(SetupViewModel model)
setupContext.Properties[SetupConstants.DatabaseProvider] = _shellSettings["DatabaseProvider"];
setupContext.Properties[SetupConstants.DatabaseConnectionString] = _shellSettings["ConnectionString"];
setupContext.Properties[SetupConstants.DatabaseTablePrefix] = _shellSettings["TablePrefix"];
setupContext.Properties[SetupConstants.DatabaseSchema] = _shellSettings["Schema"];
}
else
{
setupContext.Properties[SetupConstants.DatabaseProvider] = model.DatabaseProvider;
setupContext.Properties[SetupConstants.DatabaseConnectionString] = model.ConnectionString;
setupContext.Properties[SetupConstants.DatabaseTablePrefix] = model.TablePrefix;
setupContext.Properties[SetupConstants.DatabaseSchema] = model.Schema;
}

var executionId = await _setupService.SetupAsync(setupContext);
Expand Down Expand Up @@ -204,11 +212,6 @@ private void CopyShellSettingsValues(SetupViewModel model)
{
model.DatabaseProvider = model.DatabaseProviders.FirstOrDefault(p => p.IsDefault)?.Value;
}

if (!String.IsNullOrEmpty(_shellSettings["Description"]))
{
model.Description = _shellSettings["Description"];
}
}

private async Task<bool> ShouldProceedWithTokenAsync(string token)
Expand All @@ -228,10 +231,9 @@ private async Task<bool> ShouldProceedWithTokenAsync(string token)

private async Task<bool> IsTokenValid(string token)
{
var result = false;
try
{
var result = false;

var shellScope = await _shellHost.GetScopeAsync(ShellHelper.DefaultShellName);

await shellScope.UsingAsync(scope =>
Expand All @@ -251,15 +253,13 @@ await shellScope.UsingAsync(scope =>

return Task.CompletedTask;
});

return result;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error in decrypting the token");
}

return false;
return result;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ public class SetupViewModel

public string TablePrefix { get; set; }

public string Schema { get; set; }

/// <summary>
/// True if the database configuration is preset and can't be changed or displayed on the Setup screen.
/// </summary>
Expand Down
19 changes: 14 additions & 5 deletions src/OrchardCore.Modules/OrchardCore.Setup/Views/Setup/Index.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@
<select asp-for="DatabaseProvider" class="form-select" required>
@foreach (var provider in Model.DatabaseProviders)
{
<option value="@provider.Value" data-connection-string="@provider.HasConnectionString" data-table-prefix="@provider.HasTablePrefix" data-connection-string-sample="@T["The connection string to your database instance. e.g., {0}", provider.SampleConnectionString]">@provider.Name</option>
<option value="@provider.Value" data-connection-string="@provider.HasConnectionString" data-table-prefix="@provider.HasTablePrefix" data-connection-string-sample="@T["The connection string to your database instance, e.g. {0}.", provider.SampleConnectionString]">@provider.Name</option>
}
</select>
<span asp-validation-for="DatabaseProvider" class="text-danger"></span>
Expand All @@ -194,6 +194,15 @@
<span id="connectionStringHint" class="text-muted form-text small"></span>
</div>
</div>

<div class="row row-cols-1 row-cols-md-2">
<div class="mb-3 col tablePrefix">
<label asp-for="Schema">@T["Table Schema"]</label>
<input asp-for="Schema" class="form-control" />
<span asp-validation-for="Schema" class="text-danger"></span>
<div class="text-muted form-text small">@T["When left blank, the default value on the server will be used."] @T["For example, '{0}' for SQL Server.", "dbo"]</div>
</div>
</div>
}
<fieldset>
<legend>@T["Super User"]</legend>
Expand Down Expand Up @@ -240,7 +249,7 @@
</form>
<script src="~/OrchardCore.Setup/Scripts/setup.min.js"></script>
<script>
$(function() {
$(function () {
$('#Password').strength({
minLength: @(options.Password.RequiredLength),
upperCase: @(options.Password.RequireUppercase ? "true" : "false"),
Expand All @@ -257,18 +266,18 @@

toggleConnectionString = document.querySelector('#toggleConnectionString');
if (toggleConnectionString) {
toggleConnectionString.addEventListener('click', function(e) {
toggleConnectionString.addEventListener('click', function (e) {
togglePasswordVisibility(document.querySelector('#ConnectionString'), document.querySelector('#toggleConnectionString'))
});
}

togglePassword = document.querySelector('#togglePassword');
togglePassword.addEventListener('click', function(e) {
togglePassword.addEventListener('click', function (e) {
togglePasswordVisibility(document.querySelector('#Password'), document.querySelector('#togglePassword'))
});

togglePasswordConfirmation = document.querySelector('#togglePasswordConfirmation');
togglePasswordConfirmation.addEventListener('click', function(e) {
togglePasswordConfirmation.addEventListener('click', function (e) {
togglePasswordVisibility(document.querySelector('#PasswordConfirmation'), document.querySelector('#togglePasswordConfirmation'))
});
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -281,28 +281,32 @@ public async Task<IActionResult> Create()
return Forbid();
}


var recipeCollections = await Task.WhenAll(_recipeHarvesters.Select(x => x.HarvestRecipesAsync()));
var recipes = recipeCollections.SelectMany(x => x).Where(x => x.IsSetupRecipe).OrderBy(r => r.DisplayName).ToArray();

// Creates a default shell settings based on the configuration.
var shellSettings = _shellSettingsManager.CreateDefaultSettings();

var currentFeatureProfile = shellSettings["FeatureProfile"];

var featureProfiles = await GetFeatureProfilesAsync(currentFeatureProfile);

var model = new EditTenantViewModel
{
Recipes = recipes,
RequestUrlHost = shellSettings.RequestUrlHost,
RequestUrlPrefix = shellSettings.RequestUrlPrefix,
TablePrefix = shellSettings["TablePrefix"],
RecipeName = shellSettings["RecipeName"],
DatabaseProvider = shellSettings["DatabaseProvider"],
ConnectionString = shellSettings["ConnectionString"],
TablePrefix = shellSettings["TablePrefix"],
Schema = shellSettings["Schema"],
FeatureProfile = currentFeatureProfile,
FeatureProfiles = featureProfiles
FeatureProfiles = featureProfiles,
MikeAlhayek marked this conversation as resolved.
Show resolved Hide resolved
};
SetConfigurationShellValues(model);

model.DatabaseConfigurationPreset =
!String.IsNullOrEmpty(model.ConnectionString) ||
!String.IsNullOrEmpty(model.DatabaseProvider);

model.Recipes = recipes;

Expand Down Expand Up @@ -337,11 +341,11 @@ public async Task<IActionResult> Create(EditTenantViewModel model)
shellSettings.RequestUrlPrefix = model.RequestUrlPrefix;
shellSettings.State = TenantState.Uninitialized;

SetConfigurationShellValues(model);
shellSettings["Category"] = model.Category;
shellSettings["Description"] = model.Description;
shellSettings["ConnectionString"] = model.ConnectionString;
shellSettings["TablePrefix"] = model.TablePrefix;
shellSettings["Schema"] = model.Schema;
shellSettings["DatabaseProvider"] = model.DatabaseProvider;
shellSettings["Secret"] = Guid.NewGuid().ToString();
shellSettings["RecipeName"] = model.RecipeName;
Expand Down Expand Up @@ -390,7 +394,7 @@ public async Task<IActionResult> Edit(string id)
RequestUrlHost = shellSettings.RequestUrlHost,
RequestUrlPrefix = shellSettings.RequestUrlPrefix,
FeatureProfile = currentFeatureProfile,
FeatureProfiles = featureProfiles
FeatureProfiles = featureProfiles,
MikeAlhayek marked this conversation as resolved.
Show resolved Hide resolved
};

// The user can change the 'preset' database information only if the
Expand All @@ -403,10 +407,10 @@ public async Task<IActionResult> Edit(string id)

model.DatabaseProvider = shellSettings["DatabaseProvider"];
model.TablePrefix = shellSettings["TablePrefix"];
model.Schema = shellSettings["Schema"];
model.ConnectionString = shellSettings["ConnectionString"];
model.RecipeName = shellSettings["RecipeName"];
model.CanEditDatabasePresets = true;
SetConfigurationShellValues(model);
}

return View(model);
Expand Down Expand Up @@ -447,9 +451,9 @@ public async Task<IActionResult> Edit(EditTenantViewModel model)
// tenant has not been initialized yet
if (shellSettings.State == TenantState.Uninitialized)
{
SetConfigurationShellValues(model);
shellSettings["DatabaseProvider"] = model.DatabaseProvider;
shellSettings["TablePrefix"] = model.TablePrefix;
shellSettings["Schema"] = model.Schema;
shellSettings["ConnectionString"] = model.ConnectionString;
shellSettings["RecipeName"] = model.RecipeName;
shellSettings["Secret"] = Guid.NewGuid().ToString();
Expand All @@ -460,24 +464,25 @@ public async Task<IActionResult> Edit(EditTenantViewModel model)
return RedirectToAction(nameof(Index));
}

// If we got this far, something failed. Reinitialize the model and re-display form.

// The user can change the 'preset' database information only if the
// tenant has not been initialized yet
if (shellSettings.State == TenantState.Uninitialized)
{
model.DatabaseProvider = shellSettings["DatabaseProvider"];
model.TablePrefix = shellSettings["TablePrefix"];
model.Schema = shellSettings["Schema"];
model.ConnectionString = shellSettings["ConnectionString"];
model.RecipeName = shellSettings["RecipeName"];
model.CanEditDatabasePresets = true;
SetConfigurationShellValues(model);
}

var recipeCollections = await Task.WhenAll(_recipeHarvesters.Select(x => x.HarvestRecipesAsync()));
var recipes = recipeCollections.SelectMany(x => x).Where(x => x.IsSetupRecipe).OrderBy(r => r.DisplayName).ToArray();
model.Recipes = recipes;
model.FeatureProfiles = await GetFeatureProfilesAsync(model.FeatureProfile);

// If we got this far, something failed, redisplay form
return View(model);
}

Expand Down Expand Up @@ -575,25 +580,6 @@ public async Task<IActionResult> Reload(string id)
return Redirect(redirectUrl);
}

private void SetConfigurationShellValues(EditTenantViewModel model)
{
var shellSettings = _shellSettingsManager.CreateDefaultSettings();
var configurationShellConnectionString = shellSettings["ConnectionString"];
var configurationDatabaseProvider = shellSettings["DatabaseProvider"];

model.DatabaseConfigurationPreset = !string.IsNullOrEmpty(configurationShellConnectionString) || !string.IsNullOrEmpty(configurationDatabaseProvider);

if (!string.IsNullOrEmpty(configurationShellConnectionString))
{
model.ConnectionString = configurationShellConnectionString;
}

if (!string.IsNullOrEmpty(configurationDatabaseProvider))
{
model.DatabaseProvider = configurationDatabaseProvider;
}
}

private async Task<List<SelectListItem>> GetFeatureProfilesAsync(string currentFeatureProfile)
{
var featureProfiles = (await _featureProfilesService.GetFeatureProfilesAsync())
Expand All @@ -608,9 +594,9 @@ private async Task<List<SelectListItem>> GetFeatureProfilesAsync(string currentF
return featureProfiles;
}

private async Task ValidateViewModelAsync(EditTenantViewModel model, bool newTenant)
private async Task ValidateViewModelAsync(EditTenantViewModel model, bool isNewTenant)
{
model.IsNewTenant = newTenant;
model.IsNewTenant = isNewTenant;

ModelState.AddModelErrors(await _tenantValidator.ValidateAsync(model));
}
Expand Down
Loading