From 0f90278e9fda59c8952e170862199c7ddc3646d9 Mon Sep 17 00:00:00 2001
From: grimsi <9295182+grimsi@users.noreply.github.com>
Date: Sun, 11 May 2025 22:28:34 +0200
Subject: [PATCH] Add CORS management to admin frontend
---
.../administration/SystemManagement.tsx | 19 +++++++++++++++++--
.../gameyfin/config/ConfigProperties.kt | 12 ++++++++++++
.../gameyfin/core/security/SecurityConfig.kt | 11 +++++++++++
3 files changed, 40 insertions(+), 2 deletions(-)
diff --git a/gameyfin/src/main/frontend/components/administration/SystemManagement.tsx b/gameyfin/src/main/frontend/components/administration/SystemManagement.tsx
index 5f20de6..07ebc50 100644
--- a/gameyfin/src/main/frontend/components/administration/SystemManagement.tsx
+++ b/gameyfin/src/main/frontend/components/administration/SystemManagement.tsx
@@ -1,11 +1,26 @@
-import React from "react";
+import React, {useEffect} from "react";
import {SystemEndpoint} from "Frontend/generated/endpoints";
import withConfigPage from "Frontend/components/administration/withConfigPage";
import {Button} from "@heroui/react";
+import ConfigFormField from "Frontend/components/administration/ConfigFormField";
+import Section from "Frontend/components/general/Section";
+
+function SystemManagementLayout({getConfig, formik, setSaveMessage}: any) {
+
+ useEffect(() => {
+ if (formik.dirty && (formik.initialValues.system.cors["allowed-origins"] !== formik.values.system.cors["allowed-origins"])) {
+ setSaveMessage("Gameyfin must be restarted for the changes to take effect");
+ } else {
+ setSaveMessage(null);
+ }
+ }, [formik.dirty]);
-function SystemManagementLayout() {
return (
+
+
+
+
);
diff --git a/gameyfin/src/main/kotlin/de/grimsi/gameyfin/config/ConfigProperties.kt b/gameyfin/src/main/kotlin/de/grimsi/gameyfin/config/ConfigProperties.kt
index 79c33cb..62e3c2d 100644
--- a/gameyfin/src/main/kotlin/de/grimsi/gameyfin/config/ConfigProperties.kt
+++ b/gameyfin/src/main/kotlin/de/grimsi/gameyfin/config/ConfigProperties.kt
@@ -242,6 +242,18 @@ sealed class ConfigProperties(
)
}
}
+
+ /** System */
+ sealed class System {
+ sealed class Cors {
+ data object AllowedOrigins : ConfigProperties>(
+ Array::class,
+ "system.cors.allowed-origins",
+ "List of allowed CORS origins",
+ emptyArray()
+ )
+ }
+ }
}
enum class MatchUsersBy {
diff --git a/gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/security/SecurityConfig.kt b/gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/security/SecurityConfig.kt
index 9cc497b..5db5821 100644
--- a/gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/security/SecurityConfig.kt
+++ b/gameyfin/src/main/kotlin/de/grimsi/gameyfin/core/security/SecurityConfig.kt
@@ -19,6 +19,8 @@ import org.springframework.security.oauth2.client.registration.ClientRegistratio
import org.springframework.security.oauth2.client.registration.InMemoryClientRegistrationRepository
import org.springframework.security.oauth2.core.AuthorizationGrantType
import org.springframework.security.web.authentication.logout.HttpStatusReturningLogoutSuccessHandler
+import org.springframework.web.cors.CorsConfiguration
+
@Configuration
@EnableWebSecurity
@@ -33,6 +35,7 @@ class SecurityConfig(
@Throws(Exception::class)
override fun configure(http: HttpSecurity) {
+
// Configure your static resources with public access before calling super.configure(HttpSecurity) as it adds final anyRequest matcher
http.authorizeHttpRequests { auth: AuthorizeHttpRequestsConfigurer.AuthorizationManagerRequestMatcherRegistry ->
auth.requestMatchers("/setup").permitAll()
@@ -49,6 +52,14 @@ class SecurityConfig(
.sessionRegistry(sessionRegistry)
}
+ http.cors { cors ->
+ cors.configurationSource { request ->
+ val configuration = CorsConfiguration()
+ configuration.allowedOrigins = config.get(ConfigProperties.System.Cors.AllowedOrigins)?.toList()
+ configuration
+ }
+ }
+
super.configure(http)
if (config.get(ConfigProperties.SSO.OIDC.Enabled) == true) {