From e5eaaca5a01f84ccbf21f855249bd721bd8de84c Mon Sep 17 00:00:00 2001 From: diced Date: Fri, 6 Jun 2025 20:33:41 -0700 Subject: [PATCH] feat: discord oauth whitelist --- .gitignore | 1 + .../migration.sql | 2 ++ prisma/schema.prisma | 1 + .../parts/ServerSettingsOauth.tsx | 21 ++++++++++++++++++- src/lib/config/read.ts | 1 + src/lib/config/validate.ts | 2 ++ src/server/routes/api/auth/oauth/discord.ts | 10 +++++++++ src/server/routes/api/server/settings.ts | 10 +++++++++ 8 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 prisma/migrations/20250607030453_discord_whitelist/migration.sql diff --git a/.gitignore b/.gitignore index 74154c00..2f3b58c0 100755 --- a/.gitignore +++ b/.gitignore @@ -23,6 +23,7 @@ # misc .DS_Store *.pem +.idea # debug npm-debug.log* diff --git a/prisma/migrations/20250607030453_discord_whitelist/migration.sql b/prisma/migrations/20250607030453_discord_whitelist/migration.sql new file mode 100644 index 00000000..155f2a6d --- /dev/null +++ b/prisma/migrations/20250607030453_discord_whitelist/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "Zipline" ADD COLUMN "oauthDiscordWhitelistIds" TEXT[] DEFAULT ARRAY[]::TEXT[]; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 7390fd6c..4dd6baa6 100755 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -82,6 +82,7 @@ model Zipline { oauthDiscordClientId String? oauthDiscordClientSecret String? oauthDiscordRedirectUri String? + oauthDiscordWhitelistIds String[] @default([]) oauthGoogleClientId String? oauthGoogleClientSecret String? diff --git a/src/components/pages/serverSettings/parts/ServerSettingsOauth.tsx b/src/components/pages/serverSettings/parts/ServerSettingsOauth.tsx index bffd4f3c..54ceb6f2 100644 --- a/src/components/pages/serverSettings/parts/ServerSettingsOauth.tsx +++ b/src/components/pages/serverSettings/parts/ServerSettingsOauth.tsx @@ -30,6 +30,7 @@ export default function ServerSettingsOauth({ oauthDiscordClientId: '', oauthDiscordClientSecret: '', oauthDiscordRedirectUri: '', + oauthDiscordWhitelistIds: '', oauthGoogleClientId: '', oauthGoogleClientSecret: '', @@ -50,7 +51,7 @@ export default function ServerSettingsOauth({ const onSubmit = async (values: typeof form.values) => { for (const key in values) { - if (!['oauthBypassLocalLogin', 'oauthLoginOnly'].includes(key)) { + if (!['oauthBypassLocalLogin', 'oauthLoginOnly', 'oauthDiscordWhitelistIds'].includes(key)) { if ((values[key as keyof typeof form.values] as string)?.trim() === '') { // @ts-ignore values[key as keyof typeof form.values] = null; @@ -61,6 +62,16 @@ export default function ServerSettingsOauth({ )?.trim(); } } + + if (key === 'oauthDiscordWhitelistIds') { + if (Array.isArray(values['oauthDiscordWhitelistIds'])) continue; + + // @ts-ignore + values['oauthDiscordWhitelistIds'] = (values['oauthDiscordWhitelistIds'] as string) + .split(',') + .map((id) => id.trim()) + .filter((id) => id !== ''); + } } return settingsOnSubmit(router, form)(values); @@ -76,6 +87,9 @@ export default function ServerSettingsOauth({ oauthDiscordClientId: data?.oauthDiscordClientId ?? '', oauthDiscordClientSecret: data?.oauthDiscordClientSecret ?? '', oauthDiscordRedirectUri: data?.oauthDiscordRedirectUri ?? '', + oauthDiscordWhitelistIds: data?.oauthDiscordWhitelistIds + ? data?.oauthDiscordWhitelistIds.join(', ') + : '', oauthGoogleClientId: data?.oauthGoogleClientId ?? '', oauthGoogleClientSecret: data?.oauthGoogleClientSecret ?? '', @@ -129,6 +143,11 @@ export default function ServerSettingsOauth({ + /^\d+$/.test(s), 'Discord ID must be a number')), + z + .string() + .refine((s) => s === '' || /^\d+(,\d+)*$/.test(s), 'Discord IDs must be comma-separated'), + ]) + .transform((value) => + typeof value === 'string' ? value.split(',').map((id) => id.trim()) : value, + ), oauthGoogleClientId: z.string().nullable(), oauthGoogleClientSecret: z.string().nullable(),