From 0cdeffde51115563cd05da2fa72b058bd6cfcd09 Mon Sep 17 00:00:00 2001
From: grimsi <9295182+grimsi@users.noreply.github.com>
Date: Tue, 17 Sep 2024 12:30:55 +0200
Subject: [PATCH] Implement Enum support for ConfigProperties in frontend and
backend
---
.../administration/ConfigFormField.tsx | 9 +++++
.../administration/SsoManagement.tsx | 34 ++++++++++++++++++-
.../components/general/SelectInput.tsx | 28 +++++++++++++++
.../gameyfin/config/ConfigProperties.kt | 6 ++--
.../grimsi/gameyfin/config/ConfigService.kt | 12 +++++--
.../gameyfin/config/dto/ConfigEntryDto.kt | 3 +-
6 files changed, 85 insertions(+), 7 deletions(-)
create mode 100644 src/main/frontend/components/general/SelectInput.tsx
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