From 5565f60d6d62ca24bedea337e21effc13e5853a5 Mon Sep 17 00:00:00 2001 From: Elias Schneider Date: Fri, 25 Oct 2024 21:33:54 +0200 Subject: [PATCH] feat: add `email_verified` claim --- .../controller/well_known_controller.go | 2 +- backend/internal/dto/app_config_dto.go | 1 + backend/internal/model/app_config.go | 1 + .../internal/service/app_config_service.go | 5 ++++ backend/internal/service/oidc_service.go | 1 + .../src/lib/services/app-config-service.ts | 21 ++++++++++++-- .../lib/types/application-configuration.ts | 16 ++++++----- frontend/src/lib/utils/debounce-util.ts | 4 +-- .../forms/app-config-email-form.svelte | 14 +++++----- .../forms/app-config-general-form.svelte | 28 ++++++++++++------- 10 files changed, 64 insertions(+), 29 deletions(-) diff --git a/backend/internal/controller/well_known_controller.go b/backend/internal/controller/well_known_controller.go index c2b5e2c..32104cd 100644 --- a/backend/internal/controller/well_known_controller.go +++ b/backend/internal/controller/well_known_controller.go @@ -37,7 +37,7 @@ func (wkc *WellKnownController) openIDConfigurationHandler(c *gin.Context) { "userinfo_endpoint": appUrl + "/api/oidc/userinfo", "jwks_uri": appUrl + "/.well-known/jwks.json", "scopes_supported": []string{"openid", "profile", "email"}, - "claims_supported": []string{"sub", "given_name", "family_name", "name", "email", "preferred_username"}, + "claims_supported": []string{"sub", "given_name", "family_name", "name", "email", "email_verified", "preferred_username"}, "response_types_supported": []string{"code", "id_token"}, "subject_types_supported": []string{"public"}, "id_token_signing_alg_values_supported": []string{"RS256"}, diff --git a/backend/internal/dto/app_config_dto.go b/backend/internal/dto/app_config_dto.go index b061cd6..90c5611 100644 --- a/backend/internal/dto/app_config_dto.go +++ b/backend/internal/dto/app_config_dto.go @@ -14,6 +14,7 @@ type AppConfigVariableDto struct { type AppConfigUpdateDto struct { AppName string `json:"appName" binding:"required,min=1,max=30"` SessionDuration string `json:"sessionDuration" binding:"required"` + EmailsVerified string `json:"emailsVerified" binding:"required"` EmailEnabled string `json:"emailEnabled" binding:"required"` SmtHost string `json:"smtpHost"` SmtpPort string `json:"smtpPort"` diff --git a/backend/internal/model/app_config.go b/backend/internal/model/app_config.go index 9486520..fae0fd7 100644 --- a/backend/internal/model/app_config.go +++ b/backend/internal/model/app_config.go @@ -14,6 +14,7 @@ type AppConfig struct { LogoLightImageType AppConfigVariable LogoDarkImageType AppConfigVariable SessionDuration AppConfigVariable + EmailsVerified AppConfigVariable EmailEnabled AppConfigVariable SmtpHost AppConfigVariable diff --git a/backend/internal/service/app_config_service.go b/backend/internal/service/app_config_service.go index b28e951..8181752 100644 --- a/backend/internal/service/app_config_service.go +++ b/backend/internal/service/app_config_service.go @@ -41,6 +41,11 @@ var defaultDbConfig = model.AppConfig{ Type: "number", Value: "60", }, + EmailsVerified: model.AppConfigVariable{ + Key: "emailsVerified", + Type: "bool", + Value: "false", + }, BackgroundImageType: model.AppConfigVariable{ Key: "backgroundImageType", Type: "string", diff --git a/backend/internal/service/oidc_service.go b/backend/internal/service/oidc_service.go index 64fbb5b..9d24bcd 100644 --- a/backend/internal/service/oidc_service.go +++ b/backend/internal/service/oidc_service.go @@ -315,6 +315,7 @@ func (s *OidcService) GetUserClaimsForClient(userID string, clientID string) (ma if strings.Contains(scope, "email") { claims["email"] = user.Email + claims["email_verified"] = s.appConfigService.DbConfig.EmailsVerified.Value == "true" } if strings.Contains(scope, "groups") { diff --git a/frontend/src/lib/services/app-config-service.ts b/frontend/src/lib/services/app-config-service.ts index 9e3c27d..e9d4703 100644 --- a/frontend/src/lib/services/app-config-service.ts +++ b/frontend/src/lib/services/app-config-service.ts @@ -14,14 +14,19 @@ export default class AppConfigService extends APIService { const appConfig: Partial = {}; data.forEach(({ key, value }) => { - (appConfig as any)[key] = value; + (appConfig as any)[key] = this.parseValue(value); }); return appConfig as AllAppConfig; } async update(appConfig: AllAppConfig) { - const res = await this.api.put('/application-configuration', appConfig); + // Convert all values to string + const appConfigConvertedToString = {}; + for (const key in appConfig) { + (appConfigConvertedToString as any)[key] = (appConfig as any)[key].toString(); + } + const res = await this.api.put('/application-configuration', appConfigConvertedToString); return res.data as AllAppConfig; } @@ -62,4 +67,16 @@ export default class AppConfigService extends APIService { currentVersion }; } + + private parseValue(value: string) { + if (value === 'true') { + return true; + } else if (value === 'false') { + return false; + } else if (!isNaN(Number(value))) { + return Number(value); + } else { + return value; + } + } } diff --git a/frontend/src/lib/types/application-configuration.ts b/frontend/src/lib/types/application-configuration.ts index af5e59e..b4d9796 100644 --- a/frontend/src/lib/types/application-configuration.ts +++ b/frontend/src/lib/types/application-configuration.ts @@ -1,16 +1,18 @@ -export type AllAppConfig = { +export type AppConfig = { appName: string; - sessionDuration: string; - emailEnabled: string; +}; + +export type AllAppConfig = AppConfig & { + sessionDuration: number; + emailsVerified: boolean; + emailEnabled: boolean; smtpHost: string; - smtpPort: string; + smtpPort: number; smtpFrom: string; smtpUser: string; smtpPassword: string; }; -export type AppConfig = AllAppConfig; - export type AppConfigRawResponse = { key: string; type: string; @@ -21,4 +23,4 @@ export type AppVersionInformation = { isUpToDate: boolean; newestVersion: string; currentVersion: string; -}; \ No newline at end of file +}; diff --git a/frontend/src/lib/utils/debounce-util.ts b/frontend/src/lib/utils/debounce-util.ts index 5c55cfa..340fd9a 100644 --- a/frontend/src/lib/utils/debounce-util.ts +++ b/frontend/src/lib/utils/debounce-util.ts @@ -1,5 +1,5 @@ export function debounced void>(func: T, delay: number) { - let debounceTimeout: number | undefined; + let debounceTimeout: ReturnType; return (...args: Parameters) => { if (debounceTimeout !== undefined) { @@ -10,4 +10,4 @@ export function debounced void>(func: T, delay: nu func(...args); }, delay); }; -} \ No newline at end of file +} diff --git a/frontend/src/routes/settings/admin/application-configuration/forms/app-config-email-form.svelte b/frontend/src/routes/settings/admin/application-configuration/forms/app-config-email-form.svelte index a6c8ab1..94d8223 100644 --- a/frontend/src/routes/settings/admin/application-configuration/forms/app-config-email-form.svelte +++ b/frontend/src/routes/settings/admin/application-configuration/forms/app-config-email-form.svelte @@ -15,10 +15,10 @@ } = $props(); let isLoading = $state(false); - let emailEnabled = $state(appConfig.emailEnabled == 'true'); + let emailEnabled = $state(appConfig.emailEnabled); const updatedAppConfig = { - emailEnabled: emailEnabled.toString(), + emailEnabled: appConfig.emailEnabled, smtpHost: appConfig.smtpHost, smtpPort: appConfig.smtpPort, smtpUser: appConfig.smtpUser, @@ -28,13 +28,13 @@ const formSchema = z.object({ smtpHost: z.string().min(1), - smtpPort: z.string().min(1), + smtpPort: z.number().min(1), smtpUser: z.string().min(1), smtpPassword: z.string().min(1), smtpFrom: z.string().email() }); - const { inputs, ...form } = createForm< typeof formSchema>(formSchema, updatedAppConfig); + const { inputs, ...form } = createForm(formSchema, updatedAppConfig); async function onSubmit() { const data = form.validate(); @@ -42,15 +42,15 @@ isLoading = true; await callback({ ...data, - emailEnabled: 'true' + emailEnabled: true }).finally(() => (isLoading = false)); toast.success('Email configuration updated successfully'); return true; } async function onDisable() { - await callback({ emailEnabled: 'false' }); emailEnabled = false; + await callback({ emailEnabled }); toast.success('Email disabled successfully'); } @@ -64,7 +64,7 @@
- + diff --git a/frontend/src/routes/settings/admin/application-configuration/forms/app-config-general-form.svelte b/frontend/src/routes/settings/admin/application-configuration/forms/app-config-general-form.svelte index a551f30..ab96658 100644 --- a/frontend/src/routes/settings/admin/application-configuration/forms/app-config-general-form.svelte +++ b/frontend/src/routes/settings/admin/application-configuration/forms/app-config-general-form.svelte @@ -1,6 +1,8 @@