Save all settings as json instead of having lots of keys

This commit is contained in:
Amelia 2025-07-01 13:50:59 +02:00
parent e8f74709f3
commit dc91696769
No known key found for this signature in database
GPG key ID: D6D0ECE365407EAA
7 changed files with 63 additions and 111 deletions

View file

@ -1,17 +1,25 @@
#nullable enable #nullable enable
using API.Entities.Enums;
namespace API.DTOs.Settings; namespace API.DTOs.Settings;
public record OidcConfigDto: OidcPublicConfigDto public record OidcConfigDto: OidcPublicConfigDto
{ {
/// <inheritdoc cref="ServerSettingKey.OidcProvisionAccounts"/> /// <summary>
/// If true, auto creates a new account when someone logs in via OpenID Connect
/// </summary>
public bool ProvisionAccounts { get; set; } public bool ProvisionAccounts { get; set; }
/// <inheritdoc cref="ServerSettingKey.OidcRequireVerifiedEmail"/> /// <summary>
public bool RequireVerifiedEmail { get; set; } /// Require emails to be verified by the OpenID Connect provider when creating accounts on login
/// <inheritdoc cref="ServerSettingKey.OidcProvisionUserSettings"/> /// </summary>
public bool RequireVerifiedEmail { get; set; } = true;
/// <summary>
/// Overwrite Kavita roles, libraries and age rating with OpenIDConnect provides roles on log in.
/// </summary>
public bool ProvisionUserSettings { get; set; } public bool ProvisionUserSettings { get; set; }
/// <inheritdoc cref="ServerSettingKey.OidcAutoLogin"/> /// <summary>
/// Requires roles to be configured in OIDC
/// </summary>
public bool RequireRoles { get; set; } = true;
/// <summary> /// <summary>
/// Returns true if the <see cref="OidcPublicConfigDto.Authority"/> has been set /// Returns true if the <see cref="OidcPublicConfigDto.Authority"/> has been set

View file

@ -9,10 +9,17 @@ public record OidcPublicConfigDto
public string? Authority { get; set; } public string? Authority { get; set; }
/// <inheritdoc cref="ServerSettingKey.OidcClientId"/> /// <inheritdoc cref="ServerSettingKey.OidcClientId"/>
public string? ClientId { get; set; } public string? ClientId { get; set; }
/// <inheritdoc cref="ServerSettingKey.OidcAutoLogin"/> /// <summary>
/// Optional OpenID Connect ClientSecret, required if authority is set
/// </summary>
public bool AutoLogin { get; set; } public bool AutoLogin { get; set; }
/// <inheritdoc cref="ServerSettingKey.DisablePasswordAuthentication"/> /// <summary>
/// Disables password authentication for non-admin users
/// </summary>
public bool DisablePasswordAuthentication { get; set; } public bool DisablePasswordAuthentication { get; set; }
/// <inheritdoc cref="ServerSettingKey.OidcProviderName"/> /// <summary>
public string ProviderName { get; set; } = string.Empty; /// Name of your provider, used to display on the login screen
/// </summary>
/// <remarks>Default to OpenID Connect</remarks>
public string ProviderName { get; set; } = "OpenID Connect";
} }

View file

@ -5,9 +5,11 @@ using System.Globalization;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Text.Json;
using System.Threading.Tasks; using System.Threading.Tasks;
using API.Constants; using API.Constants;
using API.Data.Repositories; using API.Data.Repositories;
using API.DTOs.Settings;
using API.Entities; using API.Entities;
using API.Entities.Enums; using API.Entities.Enums;
using API.Entities.Enums.Theme; using API.Entities.Enums.Theme;
@ -254,12 +256,7 @@ public static class Seed
}, // Not used from DB, but DB is sync with appSettings.json }, // Not used from DB, but DB is sync with appSettings.json
new() { Key = ServerSettingKey.OidcAuthority, Value = Configuration.OidcAuthority }, new() { Key = ServerSettingKey.OidcAuthority, Value = Configuration.OidcAuthority },
new() { Key = ServerSettingKey.OidcClientId, Value = Configuration.OidcClientId}, new() { Key = ServerSettingKey.OidcClientId, Value = Configuration.OidcClientId},
new() { Key = ServerSettingKey.OidcAutoLogin, Value = "false"}, new() { Key = ServerSettingKey.OidcConfiguration, Value = JsonSerializer.Serialize(new OidcConfigDto())},
new() { Key = ServerSettingKey.OidcProvisionAccounts, Value = "false"},
new() { Key = ServerSettingKey.OidcRequireVerifiedEmail, Value = "true"},
new() { Key = ServerSettingKey.OidcProvisionUserSettings, Value = "false"},
new() { Key = ServerSettingKey.DisablePasswordAuthentication, Value = "false"},
new() { Key = ServerSettingKey.OidcProviderName, Value = "OpenID Connect"},
new() {Key = ServerSettingKey.EmailHost, Value = string.Empty}, new() {Key = ServerSettingKey.EmailHost, Value = string.Empty},
new() {Key = ServerSettingKey.EmailPort, Value = string.Empty}, new() {Key = ServerSettingKey.EmailPort, Value = string.Empty},

View file

@ -208,34 +208,9 @@ public enum ServerSettingKey
[Description("OpenIDConnectClientId")] [Description("OpenIDConnectClientId")]
OidcClientId = 41, OidcClientId = 41,
/// <summary> /// <summary>
/// Optional OpenID Connect ClientSecret, required if authority is set /// A Json object of type <see cref="API.DTOs.Settings.OidcConfigDto"/>
/// </summary> /// </summary>
[Description("OpenIdConnectAutoLogin")] [Description("OidcConfiguration")]
OidcAutoLogin = 42, OidcConfiguration = 42,
/// <summary>
/// If true, auto creates a new account when someone logs in via OpenID Connect
/// </summary>
[Description("OpenIDConnectCreateAccounts")]
OidcProvisionAccounts = 43,
/// <summary>
/// Require emails to be verified by the OpenID Connect provider when creating accounts on login
/// </summary>
[Description("OpenIDConnectVerifiedEmail")]
OidcRequireVerifiedEmail = 44,
/// <summary>
/// Overwrite Kavita roles, libraries and age rating with OpenIDConnect provides roles on log in.
/// </summary>
[Description("OpenIDConnectSyncUserSettings")]
OidcProvisionUserSettings = 45,
/// <summary>
/// Disables password authentication for non-admin users
/// </summary>
[Description("DisablePasswordAuthentication")]
DisablePasswordAuthentication = 46,
/// <summary>
/// Name of your provider, used to display on the login screen
/// </summary>
/// <remarks>Default to OpenID Connect</remarks>
[Description("OidcProviderName")]
OidcProviderName = 47,
} }

View file

@ -1,4 +1,7 @@
using System.Security.Claims; using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using API.Constants;
using Kavita.Common; using Kavita.Common;
using JwtRegisteredClaimNames = Microsoft.IdentityModel.JsonWebTokens.JwtRegisteredClaimNames; using JwtRegisteredClaimNames = Microsoft.IdentityModel.JsonWebTokens.JwtRegisteredClaimNames;
@ -41,4 +44,12 @@ public static class ClaimsPrincipalExtensions
return true; return true;
} }
public static List<string> GetAccessRoles(this ClaimsPrincipal claimsPrincipal)
{
return claimsPrincipal.FindAll(ClaimTypes.Role)
.Select(r => r.Value)
.Where(r => PolicyConstants.ValidRoles.Contains(r))
.ToList();
}
} }

View file

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.Text.Json;
using API.DTOs.Settings; using API.DTOs.Settings;
using API.Entities; using API.Entities;
using API.Entities.Enums; using API.Entities.Enums;
@ -137,29 +138,12 @@ public class ServerSettingConverter : ITypeConverter<IEnumerable<ServerSetting>,
destination.OidcConfig ??= new OidcConfigDto(); destination.OidcConfig ??= new OidcConfigDto();
destination.OidcConfig.ClientId = row.Value; destination.OidcConfig.ClientId = row.Value;
break; break;
case ServerSettingKey.OidcAutoLogin: case ServerSettingKey.OidcConfiguration:
destination.OidcConfig ??= new OidcConfigDto(); destination.OidcConfig ??= new OidcConfigDto();
destination.OidcConfig.AutoLogin = bool.Parse(row.Value); var configuration = JsonSerializer.Deserialize<OidcConfigDto>(row.Value)!;
break; configuration.Authority = destination.OidcConfig.Authority;
case ServerSettingKey.OidcProvisionAccounts: configuration.ClientId = destination.OidcConfig.ClientId;
destination.OidcConfig ??= new OidcConfigDto(); destination.OidcConfig = configuration;
destination.OidcConfig.ProvisionAccounts = bool.Parse(row.Value);
break;
case ServerSettingKey.OidcRequireVerifiedEmail:
destination.OidcConfig ??= new OidcConfigDto();
destination.OidcConfig.RequireVerifiedEmail = bool.Parse(row.Value);
break;
case ServerSettingKey.OidcProvisionUserSettings:
destination.OidcConfig ??= new OidcConfigDto();
destination.OidcConfig.ProvisionUserSettings = bool.Parse(row.Value);
break;
case ServerSettingKey.DisablePasswordAuthentication:
destination.OidcConfig ??= new OidcConfigDto();
destination.OidcConfig.DisablePasswordAuthentication = bool.Parse(row.Value);
break;
case ServerSettingKey.OidcProviderName:
destination.OidcConfig ??= new OidcConfigDto();
destination.OidcConfig.ProviderName = row.Value;
break; break;
case ServerSettingKey.LicenseKey: case ServerSettingKey.LicenseKey:
case ServerSettingKey.EnableAuthentication: case ServerSettingKey.EnableAuthentication:

View file

@ -1,6 +1,7 @@
using System; using System;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Text.Json;
using System.Threading.Tasks; using System.Threading.Tasks;
using API.Data; using API.Data;
using API.DTOs.KavitaPlus.Metadata; using API.DTOs.KavitaPlus.Metadata;
@ -413,66 +414,35 @@ public class SettingsService : ISettingsService
private async Task UpdateOidcSettings(ServerSetting setting, ServerSettingDto updateSettingsDto) private async Task UpdateOidcSettings(ServerSetting setting, ServerSettingDto updateSettingsDto)
{ {
if (setting.Key == ServerSettingKey.OidcAuthority && if (setting.Key == ServerSettingKey.OidcAuthority && setting.Value != updateSettingsDto.OidcConfig.Authority)
updateSettingsDto.OidcConfig.Authority + string.Empty != setting.Value)
{ {
if (!await IsValidAuthority(updateSettingsDto.OidcConfig.Authority + string.Empty)) if (!await IsValidAuthority(updateSettingsDto.OidcConfig.Authority + string.Empty))
{ {
throw new KavitaException("oidc-invalid-authority"); throw new KavitaException("oidc-invalid-authority");
} }
setting.Value = updateSettingsDto.OidcConfig.Authority;
setting.Value = updateSettingsDto.OidcConfig.Authority + string.Empty;
Configuration.OidcAuthority = setting.Value;
_unitOfWork.SettingsRepository.Update(setting); _unitOfWork.SettingsRepository.Update(setting);
_logger.LogWarning("OIDC Authority is changing, clearing all external ids");
await _oidcService.ClearOidcIds(); await _oidcService.ClearOidcIds();
return;
} }
if (setting.Key == ServerSettingKey.OidcClientId && if (setting.Key == ServerSettingKey.OidcClientId && setting.Value != updateSettingsDto.OidcConfig.ClientId)
updateSettingsDto.OidcConfig.ClientId + string.Empty != setting.Value)
{ {
setting.Value = updateSettingsDto.OidcConfig.ClientId + string.Empty; setting.Value = updateSettingsDto.OidcConfig.ClientId;
Configuration.OidcClientId = setting.Value;
_unitOfWork.SettingsRepository.Update(setting); _unitOfWork.SettingsRepository.Update(setting);
return;
} }
if (setting.Key == ServerSettingKey.OidcAutoLogin && if (setting.Key != ServerSettingKey.OidcConfiguration) return;
updateSettingsDto.OidcConfig.AutoLogin + string.Empty != setting.Value)
{
setting.Value = updateSettingsDto.OidcConfig.AutoLogin + string.Empty;
_unitOfWork.SettingsRepository.Update(setting);
}
if (setting.Key == ServerSettingKey.OidcProvisionAccounts && var newValue = JsonSerializer.Serialize(updateSettingsDto.OidcConfig);
updateSettingsDto.OidcConfig.ProvisionAccounts + string.Empty != setting.Value) if (setting.Value == newValue) return;
{
setting.Value = updateSettingsDto.OidcConfig.ProvisionAccounts + string.Empty;
_unitOfWork.SettingsRepository.Update(setting);
}
if (setting.Key == ServerSettingKey.OidcProvisionUserSettings && setting.Value = JsonSerializer.Serialize(updateSettingsDto.OidcConfig);
updateSettingsDto.OidcConfig.ProvisionUserSettings + string.Empty != setting.Value)
{
setting.Value = updateSettingsDto.OidcConfig.ProvisionUserSettings + string.Empty;
_unitOfWork.SettingsRepository.Update(setting); _unitOfWork.SettingsRepository.Update(setting);
} }
if (setting.Key == ServerSettingKey.DisablePasswordAuthentication &&
updateSettingsDto.OidcConfig.DisablePasswordAuthentication + string.Empty != setting.Value)
{
setting.Value = updateSettingsDto.OidcConfig.DisablePasswordAuthentication + string.Empty;
_unitOfWork.SettingsRepository.Update(setting);
}
if (setting.Key == ServerSettingKey.OidcProviderName &&
updateSettingsDto.OidcConfig.ProviderName + string.Empty != setting.Value)
{
setting.Value = updateSettingsDto.OidcConfig.ProviderName + string.Empty;
_unitOfWork.SettingsRepository.Update(setting);
}
}
private void UpdateEmailSettings(ServerSetting setting, ServerSettingDto updateSettingsDto) private void UpdateEmailSettings(ServerSetting setting, ServerSettingDto updateSettingsDto)
{ {
if (setting.Key == ServerSettingKey.EmailHost && if (setting.Key == ServerSettingKey.EmailHost &&