259 lines
11 KiB
Plaintext
259 lines
11 KiB
Plaintext
@page "/appsettings/json"
|
|
@using Indotalent.Infrastructure.Authentication.Firebase
|
|
@using Indotalent.Infrastructure.Authentication.Keycloak
|
|
@using Microsoft.AspNetCore.Authorization
|
|
@using Indotalent.Infrastructure.Authorization.Identity
|
|
@attribute [Authorize(Roles = ApplicationRoles.Admin)]
|
|
@using Indotalent.Infrastructure.Authentication.Identity
|
|
@using Indotalent.Infrastructure.Database
|
|
@using Indotalent.Infrastructure.BackgroundJob
|
|
@using Indotalent.Infrastructure.Email
|
|
@using Indotalent.Infrastructure.File
|
|
@using Indotalent.Infrastructure.Logging
|
|
@using Indotalent.Infrastructure.Authentication
|
|
@using MudBlazor
|
|
@using System.Reflection
|
|
@inject IdentityService IdentitySvc
|
|
@inject DatabaseService DbSvc
|
|
@inject BackgroundJobService JobSvc
|
|
@inject EmailService EmailSvc
|
|
@inject FileStorageService StorageSvc
|
|
@inject LoggingService LogSvc
|
|
@inject FirebaseService FirebaseSvc
|
|
@inject KeycloakService KeycloakSvc
|
|
|
|
<style>
|
|
.clean-white-tabs .mud-tabs-toolbar {
|
|
background-color: white !important;
|
|
border-bottom: 2px solid #DCEBFA;
|
|
border-radius: 0px !important;
|
|
}
|
|
|
|
.clean-white-tabs .mud-tab {
|
|
color: #94a3b8 !important;
|
|
text-transform: none;
|
|
font-weight: 500;
|
|
min-width: 140px;
|
|
border-radius: 0px !important;
|
|
}
|
|
|
|
.clean-white-tabs .mud-tab-active {
|
|
color: var(--mud-palette-primary) !important;
|
|
font-weight: 800;
|
|
}
|
|
|
|
.clean-white-tabs .mud-tabs-slider {
|
|
background-color: var(--mud-palette-primary) !important;
|
|
height: 3px !important;
|
|
bottom: 0;
|
|
}
|
|
|
|
.soltemp-info-card {
|
|
border: 1px solid #DCEBFA !important;
|
|
border-radius: 0px !important;
|
|
background-color: #ffffff;
|
|
margin-bottom: 24px;
|
|
}
|
|
|
|
.soltemp-info-header {
|
|
padding: 12px 16px !important;
|
|
background-color: #F0F7FF;
|
|
border-bottom: 1px solid #DCEBFA;
|
|
}
|
|
|
|
.soltemp-row-compact {
|
|
display: flex;
|
|
padding: 10px 16px;
|
|
align-items: center;
|
|
border-bottom: 1px solid #F0F7FF;
|
|
}
|
|
|
|
.soltemp-label-text {
|
|
width: 30%;
|
|
font-weight: 800;
|
|
color: #1a1a1a;
|
|
font-size: 0.75rem;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.5px;
|
|
}
|
|
|
|
.soltemp-value-text {
|
|
width: 70%;
|
|
color: #4A5D75;
|
|
font-size: 0.85rem;
|
|
font-weight: 500;
|
|
font-family: 'Consolas', monospace;
|
|
word-break: break-all;
|
|
}
|
|
|
|
.status-chip {
|
|
font-weight: 900;
|
|
font-size: 10px;
|
|
border-radius: 0px !important;
|
|
}
|
|
</style>
|
|
|
|
<MudContainer MaxWidth="MaxWidth.ExtraLarge" Class="mt-2 mb-8">
|
|
<div class="clean-white-tabs">
|
|
<MudTabs Elevation="0" TabPanelsClass="pt-4" Rounded="false" ApplyEffectsToContainer="true">
|
|
|
|
<MudTabPanel Text="Identity" Icon="@Icons.Material.Outlined.AdminPanelSettings">
|
|
@RenderIdentityProperties(IdentitySvc.GetConfiguration(), "Security & Identity")
|
|
</MudTabPanel>
|
|
|
|
<MudTabPanel Text="Database" Icon="@Icons.Material.Outlined.Storage">
|
|
@RenderObjectProperties(DbSvc.GetConfiguration(), "Database Engine")
|
|
</MudTabPanel>
|
|
|
|
<MudTabPanel Text="Jobs" Icon="@Icons.Material.Outlined.Schedule">
|
|
@RenderObjectProperties(JobSvc.GetConfiguration(), "Background Job Services")
|
|
</MudTabPanel>
|
|
|
|
<MudTabPanel Text="Email" Icon="@Icons.Material.Outlined.Email">
|
|
@RenderObjectProperties(EmailSvc.GetConfiguration(), "Email Providers")
|
|
</MudTabPanel>
|
|
|
|
<MudTabPanel Text="Storage" Icon="@Icons.Material.Outlined.CloudUpload">
|
|
@RenderObjectProperties(StorageSvc.GetConfiguration(), "File Storage Systems")
|
|
</MudTabPanel>
|
|
|
|
<MudTabPanel Text="Logging" Icon="@Icons.Material.Outlined.ListAlt">
|
|
@RenderObjectProperties(LogSvc.GetConfiguration(), "Diagnostic Logging")
|
|
</MudTabPanel>
|
|
|
|
</MudTabs>
|
|
</div>
|
|
</MudContainer>
|
|
|
|
@code {
|
|
private RenderFragment RenderIdentityProperties(IdentitySettingsModel settings, string sectionTitle)
|
|
{
|
|
return __builder =>
|
|
{
|
|
<MudPaper Elevation="0" Class="pa-6 mb-6 d-flex align-center justify-space-between" Style="border: 1px solid #DCEBFA;">
|
|
<div>
|
|
<MudText Typo="Typo.h5" Style="font-weight: 900; color: #1a1a1a;">@sectionTitle</MudText>
|
|
<MudText Typo="Typo.body2" Style="color: #64748b;">Security Policy & Default Credentials</MudText>
|
|
</div>
|
|
<div class="d-flex align-center gap-2">
|
|
<MudIcon Icon="@Icons.Material.Filled.Home" Size="Size.Small" Color="Color.Default" />
|
|
<MudText Typo="Typo.caption" Style="color: #94a3b8;">/</MudText>
|
|
<MudText Typo="Typo.caption" Style="color: #94a3b8;">System</MudText>
|
|
<MudText Typo="Typo.caption" Style="color: #94a3b8;">/</MudText>
|
|
<MudText Typo="Typo.caption" Style="font-weight: 600; color: #1a1a1a;">@sectionTitle</MudText>
|
|
</div>
|
|
</MudPaper>
|
|
|
|
if (settings != null)
|
|
{
|
|
@RenderSectionCard("Password Policy", settings.Password)
|
|
@RenderSectionCard("Cookie Settings", settings.Cookies)
|
|
@RenderSectionCard("Default Admin", settings.DefaultAdmin)
|
|
@RenderSectionCard("SignIn Policy", settings.SignIn)
|
|
@RenderSectionCard("SSO Firebase", settings.SsoFirebase)
|
|
@RenderSectionCard("SSO Keycloak", settings.SsoKeycloak)
|
|
}
|
|
};
|
|
}
|
|
|
|
private RenderFragment RenderSectionCard(string title, object sectionValue)
|
|
{
|
|
return __builder =>
|
|
{
|
|
if (sectionValue == null) return;
|
|
|
|
<MudCard Elevation="0" Class="soltemp-info-card">
|
|
<div class="soltemp-info-header d-flex align-center justify-space-between">
|
|
<MudText Typo="Typo.body1" Style="font-weight: 900; color: #1a1a1a;">@title</MudText>
|
|
<MudChip T="string" Color="Color.Primary" Size="Size.Small" Variant="Variant.Filled" Class="status-chip">CONFIGURED</MudChip>
|
|
</div>
|
|
<MudCardContent Style="padding: 0;">
|
|
@{
|
|
var props = sectionValue.GetType().GetProperties();
|
|
int i = 0;
|
|
}
|
|
@foreach (var p in props)
|
|
{
|
|
var val = p.GetValue(sectionValue);
|
|
<div class="soltemp-row-compact" style="background-color: @(i++ % 2 == 0 ? "#ffffff" : "#F9FCFF");">
|
|
<div class="soltemp-label-text">@p.Name</div>
|
|
<div class="soltemp-value-text">
|
|
@(MaskIfSensitive(p.Name, val?.ToString()))
|
|
</div>
|
|
</div>
|
|
}
|
|
</MudCardContent>
|
|
</MudCard>
|
|
};
|
|
}
|
|
|
|
private RenderFragment RenderObjectProperties(object settingsObj, string sectionTitle)
|
|
{
|
|
return __builder =>
|
|
{
|
|
<MudPaper Elevation="0" Class="pa-6 mb-6 d-flex align-center justify-space-between" Style="border: 1px solid #DCEBFA;">
|
|
<div>
|
|
<MudText Typo="Typo.h5" Style="font-weight: 900; color: #1a1a1a;">@sectionTitle</MudText>
|
|
<MudText Typo="Typo.body2" Style="color: #64748b;">Configuration discovery (Full Inspection Mode)</MudText>
|
|
</div>
|
|
<div class="d-flex align-center gap-2">
|
|
<MudIcon Icon="@Icons.Material.Filled.Home" Size="Size.Small" Color="Color.Default" />
|
|
<MudText Typo="Typo.caption" Style="color: #94a3b8;">/</MudText>
|
|
<MudText Typo="Typo.caption" Style="color: #94a3b8;">System</MudText>
|
|
<MudText Typo="Typo.caption" Style="color: #94a3b8;">/</MudText>
|
|
<MudText Typo="Typo.caption" Style="font-weight: 600; color: #1a1a1a;">@sectionTitle</MudText>
|
|
</div>
|
|
</MudPaper>
|
|
|
|
if (settingsObj != null)
|
|
{
|
|
var providers = settingsObj.GetType().GetProperties();
|
|
foreach (var provider in providers)
|
|
{
|
|
var providerValue = provider.GetValue(settingsObj);
|
|
if (providerValue == null) continue;
|
|
|
|
<MudCard Elevation="0" Class="soltemp-info-card">
|
|
<div class="soltemp-info-header d-flex align-center justify-space-between">
|
|
<MudText Typo="Typo.body1" Style="font-weight: 900; color: #1a1a1a;">@provider.Name</MudText>
|
|
@{
|
|
var isUsedProp = providerValue.GetType().GetProperty("IsUsed");
|
|
bool isUsed = (bool)(isUsedProp?.GetValue(providerValue) ?? false);
|
|
}
|
|
<MudChip T="string" Color="@(isUsed? Color.Success: Color.Default)" Size="Size.Small" Variant="Variant.Filled" Class="status-chip">
|
|
@(isUsed ? "ACTIVE" : "DISABLED")
|
|
</MudChip>
|
|
</div>
|
|
<MudCardContent Style="padding: 0;">
|
|
@{
|
|
var props = providerValue.GetType().GetProperties();
|
|
int i = 0;
|
|
}
|
|
@foreach (var p in props)
|
|
{
|
|
if (p.Name == "IsUsed") continue;
|
|
<div class="soltemp-row-compact" style="background-color: @(i++ % 2 == 0 ? "#ffffff" : "#F9FCFF");">
|
|
<div class="soltemp-label-text">@p.Name</div>
|
|
<div class="soltemp-value-text">
|
|
@(MaskIfSensitive(p.Name, p.GetValue(providerValue)?.ToString()))
|
|
</div>
|
|
</div>
|
|
}
|
|
</MudCardContent>
|
|
</MudCard>
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
private string MaskIfSensitive(string propertyName, string value)
|
|
{
|
|
if (string.IsNullOrEmpty(value)) return "-";
|
|
var sensitiveKeys = new[] { "Password", "Secret", "Key", "Token", "ApiKey" };
|
|
if (sensitiveKeys.Any(k => propertyName.Contains(k, StringComparison.OrdinalIgnoreCase)))
|
|
{
|
|
return "•••••••••••••••• (Encrypted)";
|
|
}
|
|
return value;
|
|
}
|
|
} |