151 lines
5.0 KiB
Plaintext
151 lines
5.0 KiB
Plaintext
@page "/admin/config"
|
|
@attribute [Authorize]
|
|
|
|
@using Microsoft.Extensions.Options
|
|
@using Rms.Risk.Mango.Services.Context
|
|
|
|
@* ReSharper disable once CSharpWarnings::CS8669 *@
|
|
@inject IDatabaseConfigurationStorage? Storage
|
|
@inject IUserService UserService
|
|
@inject IConfiguration Config
|
|
@inject IOptions<DbMangoSettings> Settings
|
|
@inject IUserSession UserSession
|
|
|
|
@*
|
|
* dbMango
|
|
*
|
|
* Copyright 2025 Deutsche Bank AG
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*@
|
|
|
|
<h3>Configuration</h3>
|
|
|
|
<AuthorizedOnly Policy="AdminAccess" Resource="@Settings.Value.Initial">
|
|
|
|
@if (Settings.Value.EnableDatabaseOverrides && Storage != null )
|
|
{
|
|
<NameValueControl Value="@_data" PossibleNames="@_possibleNames">
|
|
<FormButton Name="Save" Icon="icon-save-outline-sm" OnClick="Save" />
|
|
</NameValueControl>
|
|
}
|
|
else
|
|
{
|
|
<div class="alert-warning">
|
|
Database is not enabled as a source for configuration parameters overrides in app configuration.<br/>
|
|
Set <code>DbMangoSettings:EnableDatabaseOverrides</code> to <code>true</code>.
|
|
</div>
|
|
}
|
|
|
|
</AuthorizedOnly>
|
|
|
|
@code {
|
|
[CascadingParameter] public IModalService Modal { get; set; } = null!;
|
|
|
|
private List<NameValueControl.NameValuePair> _data = [];
|
|
private List<string> _possibleNames = [];
|
|
|
|
|
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
|
{
|
|
if (!firstRender || Storage == null)
|
|
return;
|
|
|
|
var cts = new CancellationTokenSource(DatabaseConfigurationService.DefaultTimeout);
|
|
var overrides = await Storage.GetConfiguration(UserService.GetEmail(), cts.Token);
|
|
_data = overrides.Select(o => new NameValueControl.NameValuePair
|
|
{
|
|
Name = o.Key,
|
|
Value = o.Value
|
|
}).ToList();
|
|
|
|
_possibleNames = GetConfigSections(Config);
|
|
StateHasChanged(); // Refresh the UI after loading new configuration
|
|
}
|
|
|
|
private List<string> GetConfigSections(IConfiguration config, string parentKey = "")
|
|
{
|
|
var sections = new List<string>();
|
|
foreach (var section in config.GetChildren())
|
|
{
|
|
var fullKey = string.IsNullOrEmpty(parentKey) ? section.Key : $"{parentKey}:{section.Key}";
|
|
sections.Add(fullKey);
|
|
sections.AddRange(GetConfigSections(section, fullKey));
|
|
}
|
|
return sections;
|
|
}
|
|
|
|
private Task<string?> CanExecuteCommand()
|
|
=> Shell.CanExecuteCommand(UserSession, InvokeAsync, Modal);
|
|
|
|
private async Task Save()
|
|
{
|
|
if ( Storage == null )
|
|
return;
|
|
|
|
var ticket = await CanExecuteCommand();
|
|
if (string.IsNullOrWhiteSpace(ticket))
|
|
return;
|
|
|
|
|
|
try
|
|
{
|
|
// it's safer to build it this way as there can be duplicate names in the user input
|
|
var dict = new Dictionary<string, string>();
|
|
foreach (var pair in _data)
|
|
{
|
|
dict[pair.Name] = pair.Value;
|
|
}
|
|
var cts = new CancellationTokenSource(DatabaseConfigurationService.DefaultTimeout);
|
|
await Storage.UpdateConfiguration(dict, UserService.GetEmail(), cts.Token);
|
|
|
|
await ModalDialogUtils.ShowInfoDialog(Modal, "Success", "The configuration has been successfully saved.");
|
|
|
|
// exception in Audit() call can lead to 2 dialogs shown in total: Success in config change + error recording audit
|
|
try
|
|
{
|
|
await Audit(ticket);
|
|
}
|
|
catch (Exception ex2)
|
|
{
|
|
await ModalDialogUtils.ShowExceptionDialog(Modal, "Error", ex2);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
try
|
|
{
|
|
await Audit(ticket, ex);
|
|
}
|
|
catch (Exception ex2)
|
|
{
|
|
await ModalDialogUtils.ShowExceptionDialog(Modal, "Error", ex2);
|
|
}
|
|
await ModalDialogUtils.ShowExceptionDialog(Modal, "Error", ex);
|
|
}
|
|
}
|
|
|
|
private async Task Audit(string ticket, Exception? exception = null)
|
|
{
|
|
var doc = new BsonDocument
|
|
{
|
|
["dbMangoConfigUpdate"] = exception?.Message ?? "Configuration updated"
|
|
};
|
|
|
|
var auditRecord = new AuditRecord(UserSession.Database, DateTime.UtcNow, UserService.GetEmail(), ticket, exception == null, doc, exception?.Message);
|
|
await UserSession.Audit.Record(auditRecord);
|
|
}
|
|
|
|
}
|