Add team roles and content management updates
This commit is contained in:
@@ -16,10 +16,22 @@ public static class AdminSiteSettingsEndpoints
|
||||
|
||||
public static RouteGroupBuilder MapAdminSiteSettingsEndpoints(this RouteGroupBuilder group)
|
||||
{
|
||||
group.MapGet("/site-settings", GetSiteSettings).WithName("GetAdminSiteSettings").WithOpenApi();
|
||||
group.MapPut("/site-settings", UpdateSiteSettings).WithName("UpdateAdminSiteSettings").WithOpenApi();
|
||||
group.MapGet("/operational-settings", GetOperationalSettings).WithName("GetAdminOperationalSettings").WithOpenApi();
|
||||
group.MapPut("/operational-settings", UpdateOperationalSettings).WithName("UpdateAdminOperationalSettings").WithOpenApi();
|
||||
group.MapGet("/site-settings", GetSiteSettings)
|
||||
.AddEndpointFilter((context, next) => AdminEndpointConventions.RequirePermission(context, next, AdminPermissionCatalog.Content))
|
||||
.WithName("GetAdminSiteSettings")
|
||||
.WithOpenApi();
|
||||
group.MapPut("/site-settings", UpdateSiteSettings)
|
||||
.AddEndpointFilter((context, next) => AdminEndpointConventions.RequireWritePermission(context, next, AdminPermissionCatalog.Content))
|
||||
.WithName("UpdateAdminSiteSettings")
|
||||
.WithOpenApi();
|
||||
group.MapGet("/operational-settings", GetOperationalSettings)
|
||||
.AddEndpointFilter((context, next) => AdminEndpointConventions.RequirePermission(context, next, AdminPermissionCatalog.Settings))
|
||||
.WithName("GetAdminOperationalSettings")
|
||||
.WithOpenApi();
|
||||
group.MapPut("/operational-settings", UpdateOperationalSettings)
|
||||
.AddEndpointFilter((context, next) => AdminEndpointConventions.RequireWritePermission(context, next, AdminPermissionCatalog.Settings))
|
||||
.WithName("UpdateAdminOperationalSettings")
|
||||
.WithOpenApi();
|
||||
return group;
|
||||
}
|
||||
|
||||
@@ -40,8 +52,11 @@ public static class AdminSiteSettingsEndpoints
|
||||
settings.PrivacyPolicyUpdatedBy,
|
||||
settings.PrivacyPolicyUpdatedAt,
|
||||
settings.ImprintUrl,
|
||||
settings.ImprintContent,
|
||||
settings.ContactUrl,
|
||||
settings.ContactContent,
|
||||
settings.SponsorsUrl,
|
||||
settings.SponsorsContent,
|
||||
SeasonMappings.ReadSocialLinks(settings),
|
||||
SeasonMappings.ReadFaqItems(settings)));
|
||||
}
|
||||
@@ -53,10 +68,6 @@ public static class AdminSiteSettingsEndpoints
|
||||
IAdminAuditService adminAuditService)
|
||||
{
|
||||
var session = AdminEndpointConventions.CurrentSession(context);
|
||||
if (!AdminRoles.CanManageContent(session.Role))
|
||||
{
|
||||
return Results.Json(new { message = "Landingpage content requires a content admin, admin or owner role." }, statusCode: StatusCodes.Status403Forbidden);
|
||||
}
|
||||
|
||||
var settings = await db.SiteSettings.FirstOrDefaultAsync(item => item.Id == 1);
|
||||
if (settings is null)
|
||||
@@ -78,8 +89,11 @@ public static class AdminSiteSettingsEndpoints
|
||||
}
|
||||
|
||||
settings.ImprintUrl = request.ImprintUrl.Trim();
|
||||
settings.ImprintContent = request.ImprintContent.Trim();
|
||||
settings.ContactUrl = request.ContactUrl.Trim();
|
||||
settings.ContactContent = request.ContactContent.Trim();
|
||||
settings.SponsorsUrl = request.SponsorsUrl.Trim();
|
||||
settings.SponsorsContent = request.SponsorsContent.Trim();
|
||||
settings.SocialLinksJson = JsonSerializer.Serialize(request.SocialLinks ?? []);
|
||||
settings.FaqJson = JsonSerializer.Serialize(request.Faq ?? []);
|
||||
|
||||
@@ -111,6 +125,7 @@ public static class AdminSiteSettingsEndpoints
|
||||
}
|
||||
|
||||
var usesDatabaseDemo = settings.DemoLoginManagedByDatabase || HasDatabaseDemoCredentials(settings);
|
||||
var twitchSettings = ReadEffectiveTwitchSettings(settings, configuration);
|
||||
return Results.Ok(new AdminOperationalSettingsResponse(
|
||||
usesDatabaseDemo,
|
||||
usesDatabaseDemo ? settings.DemoLoginEnabled : IsDemoLoginEnabled(configuration),
|
||||
@@ -118,6 +133,12 @@ public static class AdminSiteSettingsEndpoints
|
||||
usesDatabaseDemo ? HasDatabaseDemoCredentials(settings) : !string.IsNullOrWhiteSpace(ReadDemoSetting(configuration, "Password", "VTSA_DEMO_ADMIN_PASSWORD")),
|
||||
usesDatabaseDemo ? settings.DemoLoginTwitchUserId : ReadDemoSetting(configuration, "TwitchUserId", "VTSA_DEMO_ADMIN_TWITCH_ID"),
|
||||
usesDatabaseDemo ? settings.DemoLoginDisplayName : ReadDemoSetting(configuration, "DisplayName", "VTSA_DEMO_ADMIN_DISPLAY_NAME"),
|
||||
settings.TwitchAuthManagedByDatabase,
|
||||
twitchSettings.Configured,
|
||||
twitchSettings.ClientId,
|
||||
twitchSettings.ClientSecretSet,
|
||||
twitchSettings.RedirectUri,
|
||||
twitchSettings.Scope,
|
||||
settings.MaintenanceModeEnabled,
|
||||
string.IsNullOrWhiteSpace(settings.MaintenanceTitle) ? FallbackMaintenanceTitle : settings.MaintenanceTitle,
|
||||
string.IsNullOrWhiteSpace(settings.MaintenanceMessage)
|
||||
@@ -144,12 +165,18 @@ public static class AdminSiteSettingsEndpoints
|
||||
return Results.NotFound();
|
||||
}
|
||||
|
||||
var before = CreateOperationalSettingsSnapshot(settings);
|
||||
var before = CreateOperationalSettingsSnapshot(settings, configuration);
|
||||
var loginIdentifier = request.DemoLoginEmail.Trim();
|
||||
var twitchUserId = request.DemoLoginTwitchUserId.Trim();
|
||||
var displayName = request.DemoLoginDisplayName.Trim();
|
||||
var newPassword = request.DemoLoginPassword?.Trim() ?? string.Empty;
|
||||
var fallbackPassword = ReadDemoSetting(configuration, "Password", "VTSA_DEMO_ADMIN_PASSWORD");
|
||||
var twitchClientId = request.TwitchClientId.Trim();
|
||||
var twitchClientSecret = request.TwitchClientSecret?.Trim() ?? string.Empty;
|
||||
var twitchRedirectUri = request.TwitchRedirectUri.Trim();
|
||||
var twitchScope = request.TwitchScope.Trim();
|
||||
var existingTwitchSecretAvailable = !string.IsNullOrWhiteSpace(settings.TwitchClientSecret)
|
||||
|| !string.IsNullOrWhiteSpace(ReadTwitchSetting(configuration, "ClientSecret", "VTSA_TWITCH_CLIENT_SECRET"));
|
||||
|
||||
if (request.DemoLoginEnabled)
|
||||
{
|
||||
@@ -168,9 +195,22 @@ public static class AdminSiteSettingsEndpoints
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(newPassword) && newPassword.Length < 12)
|
||||
if (!string.IsNullOrWhiteSpace(newPassword) && newPassword.Length < 10)
|
||||
{
|
||||
return Results.BadRequest(new { message = "Das Demo-Passwort muss mindestens 12 Zeichen lang sein." });
|
||||
return Results.BadRequest(new { message = "Das Demo-Passwort muss mindestens 10 Zeichen lang sein." });
|
||||
}
|
||||
|
||||
if (HasAnyTwitchAuthSetting(twitchClientId, twitchClientSecret, twitchRedirectUri, twitchScope)
|
||||
&& string.IsNullOrWhiteSpace(twitchClientId))
|
||||
{
|
||||
return Results.BadRequest(new { message = "Twitch OAuth braucht eine Client-ID." });
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(twitchClientId)
|
||||
&& string.IsNullOrWhiteSpace(twitchClientSecret)
|
||||
&& !existingTwitchSecretAvailable)
|
||||
{
|
||||
return Results.BadRequest(new { message = "Twitch OAuth braucht beim ersten Speichern ein Client Secret." });
|
||||
}
|
||||
|
||||
settings.DemoLoginManagedByDatabase = true;
|
||||
@@ -178,6 +218,22 @@ public static class AdminSiteSettingsEndpoints
|
||||
settings.DemoLoginEmail = loginIdentifier;
|
||||
settings.DemoLoginTwitchUserId = string.IsNullOrWhiteSpace(twitchUserId) ? "jayuhime_admin" : twitchUserId;
|
||||
settings.DemoLoginDisplayName = string.IsNullOrWhiteSpace(displayName) ? "Jayuhime Admin" : displayName;
|
||||
settings.TwitchClientId = twitchClientId;
|
||||
settings.TwitchRedirectUri = twitchRedirectUri;
|
||||
settings.TwitchScope = twitchScope;
|
||||
if (!string.IsNullOrWhiteSpace(twitchClientSecret))
|
||||
{
|
||||
settings.TwitchClientSecret = twitchClientSecret;
|
||||
}
|
||||
else if (string.IsNullOrWhiteSpace(twitchClientId) && string.IsNullOrWhiteSpace(twitchRedirectUri) && string.IsNullOrWhiteSpace(twitchScope))
|
||||
{
|
||||
settings.TwitchClientSecret = string.Empty;
|
||||
}
|
||||
settings.TwitchAuthManagedByDatabase = HasAnyTwitchAuthSetting(
|
||||
settings.TwitchClientId,
|
||||
settings.TwitchClientSecret,
|
||||
settings.TwitchRedirectUri,
|
||||
settings.TwitchScope);
|
||||
|
||||
var passwordToPersist = !string.IsNullOrWhiteSpace(newPassword)
|
||||
? newPassword
|
||||
@@ -201,8 +257,9 @@ public static class AdminSiteSettingsEndpoints
|
||||
|
||||
var changes = BuildOperationalSettingChanges(
|
||||
before,
|
||||
CreateOperationalSettingsSnapshot(settings),
|
||||
!string.IsNullOrWhiteSpace(passwordToPersist));
|
||||
CreateOperationalSettingsSnapshot(settings, configuration),
|
||||
!string.IsNullOrWhiteSpace(passwordToPersist),
|
||||
!string.IsNullOrWhiteSpace(twitchClientSecret));
|
||||
|
||||
adminAuditService.AddEntry(
|
||||
session.TwitchUserId,
|
||||
@@ -225,6 +282,7 @@ public static class AdminSiteSettingsEndpoints
|
||||
{
|
||||
saved = true,
|
||||
demoLoginPasswordSet = HasDatabaseDemoCredentials(settings),
|
||||
twitchClientSecretSet = HasEffectiveTwitchClientSecret(settings, configuration),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -250,6 +308,9 @@ public static class AdminSiteSettingsEndpoints
|
||||
private static string ReadDemoSetting(IConfiguration configuration, string key, string environmentKey) =>
|
||||
configuration[environmentKey] ?? configuration[$"DemoAdmin:{key}"] ?? string.Empty;
|
||||
|
||||
private static string ReadTwitchSetting(IConfiguration configuration, string key, string environmentKey) =>
|
||||
configuration[environmentKey] ?? configuration[$"TwitchAuth:{key}"] ?? string.Empty;
|
||||
|
||||
private static string ReadDemoLoginIdentifier(IConfiguration configuration)
|
||||
{
|
||||
var configuredLogin = ReadDemoSetting(configuration, "Login", "VTSA_DEMO_ADMIN_LOGIN");
|
||||
@@ -263,7 +324,35 @@ public static class AdminSiteSettingsEndpoints
|
||||
&& !string.IsNullOrWhiteSpace(settings.DemoLoginPasswordHash)
|
||||
&& !string.IsNullOrWhiteSpace(settings.DemoLoginPasswordSalt);
|
||||
|
||||
private static OperationalSettingsSnapshot CreateOperationalSettingsSnapshot(SiteSettings settings) =>
|
||||
private static bool HasAnyTwitchAuthSetting(params string[] values) =>
|
||||
values.Any(value => !string.IsNullOrWhiteSpace(value));
|
||||
|
||||
private static bool HasEffectiveTwitchClientSecret(SiteSettings settings, IConfiguration configuration) =>
|
||||
!string.IsNullOrWhiteSpace(settings.TwitchClientSecret)
|
||||
|| !string.IsNullOrWhiteSpace(ReadTwitchSetting(configuration, "ClientSecret", "VTSA_TWITCH_CLIENT_SECRET"));
|
||||
|
||||
private static TwitchSettingsSnapshot ReadEffectiveTwitchSettings(SiteSettings settings, IConfiguration configuration)
|
||||
{
|
||||
var clientId = !string.IsNullOrWhiteSpace(settings.TwitchClientId)
|
||||
? settings.TwitchClientId
|
||||
: ReadTwitchSetting(configuration, "ClientId", "VTSA_TWITCH_CLIENT_ID");
|
||||
var redirectUri = !string.IsNullOrWhiteSpace(settings.TwitchRedirectUri)
|
||||
? settings.TwitchRedirectUri
|
||||
: ReadTwitchSetting(configuration, "RedirectUri", "VTSA_TWITCH_REDIRECT_URI");
|
||||
var scope = !string.IsNullOrWhiteSpace(settings.TwitchScope)
|
||||
? settings.TwitchScope
|
||||
: ReadTwitchSetting(configuration, "Scope", "VTSA_TWITCH_SCOPE");
|
||||
var secretSet = HasEffectiveTwitchClientSecret(settings, configuration);
|
||||
|
||||
return new(
|
||||
clientId,
|
||||
secretSet,
|
||||
redirectUri,
|
||||
scope,
|
||||
!string.IsNullOrWhiteSpace(clientId) && secretSet);
|
||||
}
|
||||
|
||||
private static OperationalSettingsSnapshot CreateOperationalSettingsSnapshot(SiteSettings settings, IConfiguration configuration) =>
|
||||
new(
|
||||
settings.DemoLoginManagedByDatabase,
|
||||
settings.DemoLoginEnabled,
|
||||
@@ -271,6 +360,11 @@ public static class AdminSiteSettingsEndpoints
|
||||
HasDatabaseDemoCredentials(settings),
|
||||
settings.DemoLoginTwitchUserId,
|
||||
settings.DemoLoginDisplayName,
|
||||
settings.TwitchAuthManagedByDatabase,
|
||||
settings.TwitchClientId,
|
||||
HasEffectiveTwitchClientSecret(settings, configuration),
|
||||
settings.TwitchRedirectUri,
|
||||
settings.TwitchScope,
|
||||
settings.MaintenanceModeEnabled,
|
||||
string.IsNullOrWhiteSpace(settings.MaintenanceTitle) ? FallbackMaintenanceTitle : settings.MaintenanceTitle,
|
||||
string.IsNullOrWhiteSpace(settings.MaintenanceMessage) ? FallbackMaintenanceMessage : settings.MaintenanceMessage);
|
||||
@@ -278,7 +372,8 @@ public static class AdminSiteSettingsEndpoints
|
||||
private static object[] BuildOperationalSettingChanges(
|
||||
OperationalSettingsSnapshot before,
|
||||
OperationalSettingsSnapshot after,
|
||||
bool passwordChanged)
|
||||
bool passwordChanged,
|
||||
bool twitchClientSecretChanged)
|
||||
{
|
||||
var changes = new List<object>();
|
||||
|
||||
@@ -287,6 +382,22 @@ public static class AdminSiteSettingsEndpoints
|
||||
AddOperationalChange(changes, "demoLoginEmail", "Demo Login", before.DemoLoginEmail, after.DemoLoginEmail);
|
||||
AddOperationalChange(changes, "demoLoginTwitchUserId", "Demo Twitch-ID", before.DemoLoginTwitchUserId, after.DemoLoginTwitchUserId);
|
||||
AddOperationalChange(changes, "demoLoginDisplayName", "Demo Anzeigename", before.DemoLoginDisplayName, after.DemoLoginDisplayName);
|
||||
AddOperationalChange(changes, "twitchAuthManagedByDatabase", "Twitch OAuth Quelle", before.TwitchAuthManagedByDatabase, after.TwitchAuthManagedByDatabase);
|
||||
AddOperationalChange(changes, "twitchClientId", "Twitch Client-ID", before.TwitchClientId, after.TwitchClientId);
|
||||
AddOperationalChange(changes, "twitchRedirectUri", "Twitch Redirect URI", before.TwitchRedirectUri, after.TwitchRedirectUri);
|
||||
AddOperationalChange(changes, "twitchScope", "Twitch Scope", before.TwitchScope, after.TwitchScope);
|
||||
|
||||
if (before.TwitchClientSecretSet != after.TwitchClientSecretSet || twitchClientSecretChanged)
|
||||
{
|
||||
changes.Add(new
|
||||
{
|
||||
field = "twitchClientSecret",
|
||||
label = "Twitch Client Secret",
|
||||
@from = before.TwitchClientSecretSet ? "gesetzt" : "nicht gesetzt",
|
||||
to = twitchClientSecretChanged ? "neu gesetzt" : after.TwitchClientSecretSet ? "gesetzt" : "nicht gesetzt",
|
||||
sensitive = true,
|
||||
});
|
||||
}
|
||||
|
||||
if (passwordChanged)
|
||||
{
|
||||
@@ -347,7 +458,19 @@ public static class AdminSiteSettingsEndpoints
|
||||
bool DemoLoginPasswordSet,
|
||||
string DemoLoginTwitchUserId,
|
||||
string DemoLoginDisplayName,
|
||||
bool TwitchAuthManagedByDatabase,
|
||||
string TwitchClientId,
|
||||
bool TwitchClientSecretSet,
|
||||
string TwitchRedirectUri,
|
||||
string TwitchScope,
|
||||
bool MaintenanceModeEnabled,
|
||||
string MaintenanceTitle,
|
||||
string MaintenanceMessage);
|
||||
|
||||
private sealed record TwitchSettingsSnapshot(
|
||||
string ClientId,
|
||||
bool ClientSecretSet,
|
||||
string RedirectUri,
|
||||
string Scope,
|
||||
bool Configured);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user