diff --git a/src/main/frontend/components/administration/ConfigFormField.tsx b/src/main/frontend/components/administration/ConfigFormField.tsx index d9d44f5..7cce99d 100644 --- a/src/main/frontend/components/administration/ConfigFormField.tsx +++ b/src/main/frontend/components/administration/ConfigFormField.tsx @@ -2,9 +2,18 @@ import ConfigEntryDto from "Frontend/generated/de/grimsi/gameyfin/config/dto/Con import React from "react"; import Input from "Frontend/components/general/Input"; import CheckboxInput from "Frontend/components/general/CheckboxInput"; +import SelectInput from "Frontend/components/general/SelectInput"; export default function ConfigFormField({configElement, ...props}: any) { function inputElement(configElement: ConfigEntryDto) { + + if (configElement.allowedValues != null && configElement.allowedValues.length > 0) { + return ( + + ); + } + switch (configElement.type) { case "Boolean": return ( diff --git a/src/main/frontend/components/administration/SsoManagement.tsx b/src/main/frontend/components/administration/SsoManagement.tsx index 7d5935a..38c63e4 100644 --- a/src/main/frontend/components/administration/SsoManagement.tsx +++ b/src/main/frontend/components/administration/SsoManagement.tsx @@ -74,6 +74,38 @@ function SsoMangementLayout({getConfig, formik}: any) { ); } -const validationSchema = Yup.object({}); +const validationSchema = Yup.object({ + sso: Yup.object({ + oidc: Yup.object({ + enabled: Yup.boolean(), + "auto-register-new-users": Yup.boolean().required(), + "match-existing-users-by": Yup.string().required(), + "client-id": Yup.string().when("enabled", ([enabled], schema) => + enabled ? schema.required("Client ID is required") : schema + ), + "client-secret": Yup.string().when("enabled", ([enabled], schema) => + enabled ? schema.required("Client Secret is required") : schema + ), + "issuer-url": Yup.string().when("enabled", ([enabled], schema) => + enabled ? schema.required("Issuer URL is required") : schema + ), + "authorize-url": Yup.string().when("enabled", ([enabled], schema) => + enabled ? schema.required("Authorize URL is required") : schema + ), + "token-url": Yup.string().when("enabled", ([enabled], schema) => + enabled ? schema.required("Token URL is required") : schema + ), + "userinfo-url": Yup.string().when("enabled", ([enabled], schema) => + enabled ? schema.required("Userinfo URL is required") : schema + ), + "logout-url": Yup.string().when("enabled", ([enabled], schema) => + enabled ? schema.required("Logout URL is required") : schema + ), + "jwks-url": Yup.string().when("enabled", ([enabled], schema) => + enabled ? schema.required("JWKS URL is required") : schema + ) + }) + }) +}); export const SsoManagement = withConfigPage(SsoMangementLayout, "Single Sign-On", "sso", validationSchema); \ No newline at end of file diff --git a/src/main/frontend/components/general/SelectInput.tsx b/src/main/frontend/components/general/SelectInput.tsx new file mode 100644 index 0000000..f97a398 --- /dev/null +++ b/src/main/frontend/components/general/SelectInput.tsx @@ -0,0 +1,28 @@ +import {useField} from "formik"; +import {Select, SelectItem} from "@nextui-org/react"; + +// @ts-ignore +const SelectInput = ({label, values, ...props}) => { + // @ts-ignore + const [field] = useField(props); + + return ( +
+ +
+ ); +} + +export default SelectInput; \ No newline at end of file diff --git a/src/main/kotlin/de/grimsi/gameyfin/config/ConfigProperties.kt b/src/main/kotlin/de/grimsi/gameyfin/config/ConfigProperties.kt index 863dcc6..d32bbf3 100644 --- a/src/main/kotlin/de/grimsi/gameyfin/config/ConfigProperties.kt +++ b/src/main/kotlin/de/grimsi/gameyfin/config/ConfigProperties.kt @@ -7,7 +7,8 @@ sealed class ConfigProperties( val type: KClass, val key: String, val description: String, - val default: T? = null + val default: T? = null, + val allowedValues: List? = null ) { /** Libraries */ @@ -114,7 +115,8 @@ sealed class ConfigProperties( MatchUsersBy::class, "sso.oidc.match-existing-users-by", "Match existing users by", - MatchUsersBy.USERNAME + MatchUsersBy.USERNAME, + MatchUsersBy.entries ) data object SsoAutoRegisterNewUsers : ConfigProperties( diff --git a/src/main/kotlin/de/grimsi/gameyfin/config/ConfigService.kt b/src/main/kotlin/de/grimsi/gameyfin/config/ConfigService.kt index e3b3234..dbe6513 100644 --- a/src/main/kotlin/de/grimsi/gameyfin/config/ConfigService.kt +++ b/src/main/kotlin/de/grimsi/gameyfin/config/ConfigService.kt @@ -40,7 +40,8 @@ class ConfigService( value = appConfig?.value ?: configProperty.default?.toString(), defaultValue = configProperty.default?.toString(), type = configProperty.type.simpleName ?: "Unknown", - description = configProperty.description + description = configProperty.description, + allowedValues = configProperty.allowedValues?.map { it.toString() } ) } } @@ -172,9 +173,14 @@ class ConfigService( Boolean::class -> value.toBoolean() as T Int::class -> value.toFloat().toInt() as T Float::class -> value.toFloat() as T - Enum::class -> value as T else -> { - throw RuntimeException("Unknown config type ${configProperty.type}: '$value' for key ${configProperty.key}") + if (configProperty.type.java.isEnum) { + val enumConstants = configProperty.type.java.enumConstants + enumConstants.firstOrNull { it.toString() == value } + ?: throw IllegalArgumentException("Unknown enum value '$value' for key ${configProperty.key}") + } else { + throw IllegalArgumentException("Unknown config type ${configProperty.type}: '$value' for key ${configProperty.key}") + } } } } diff --git a/src/main/kotlin/de/grimsi/gameyfin/config/dto/ConfigEntryDto.kt b/src/main/kotlin/de/grimsi/gameyfin/config/dto/ConfigEntryDto.kt index fcb45b4..9bfe4da 100644 --- a/src/main/kotlin/de/grimsi/gameyfin/config/dto/ConfigEntryDto.kt +++ b/src/main/kotlin/de/grimsi/gameyfin/config/dto/ConfigEntryDto.kt @@ -9,5 +9,6 @@ data class ConfigEntryDto( val value: String?, val defaultValue: String?, @field:Nonnull val type: String, - @field:Nonnull val description: String + @field:Nonnull val description: String, + val allowedValues: List? ) \ No newline at end of file