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) {