mirror of
https://github.com/diced/zipline.git
synced 2025-12-12 15:50:11 -08:00
feat: allow/denylist discord oauth
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
Warnings:
|
||||
|
||||
- You are about to drop the column `oauthDiscordWhitelistIds` on the `Zipline` table. All the data in the column will be lost.
|
||||
|
||||
*/
|
||||
-- AlterTable
|
||||
ALTER TABLE "Zipline" DROP COLUMN "oauthDiscordWhitelistIds",
|
||||
ADD COLUMN "oauthDiscordAllowedIds" TEXT[] DEFAULT ARRAY[]::TEXT[],
|
||||
ADD COLUMN "oauthDiscordDeniedIds" TEXT[] DEFAULT ARRAY[]::TEXT[];
|
||||
@@ -82,7 +82,8 @@ model Zipline {
|
||||
oauthDiscordClientId String?
|
||||
oauthDiscordClientSecret String?
|
||||
oauthDiscordRedirectUri String?
|
||||
oauthDiscordWhitelistIds String[] @default([])
|
||||
oauthDiscordAllowedIds String[] @default([])
|
||||
oauthDiscordDeniedIds String[] @default([])
|
||||
|
||||
oauthGoogleClientId String?
|
||||
oauthGoogleClientSecret String?
|
||||
|
||||
@@ -30,7 +30,8 @@ export default function Oauth({
|
||||
oauthDiscordClientId: '',
|
||||
oauthDiscordClientSecret: '',
|
||||
oauthDiscordRedirectUri: '',
|
||||
oauthDiscordWhitelistIds: '',
|
||||
oauthDiscordAllowedIds: '',
|
||||
oauthDiscordDeniedIds: '',
|
||||
|
||||
oauthGoogleClientId: '',
|
||||
oauthGoogleClientSecret: '',
|
||||
@@ -54,7 +55,14 @@ export default function Oauth({
|
||||
|
||||
const onSubmit = async (values: typeof form.values) => {
|
||||
for (const key in values) {
|
||||
if (!['oauthBypassLocalLogin', 'oauthLoginOnly', 'oauthDiscordWhitelistIds'].includes(key)) {
|
||||
if (
|
||||
![
|
||||
'oauthBypassLocalLogin',
|
||||
'oauthLoginOnly',
|
||||
'oauthDiscordAllowedIds',
|
||||
'oauthDiscordDeniedIds',
|
||||
].includes(key)
|
||||
) {
|
||||
if ((values[key as keyof typeof form.values] as string)?.trim() === '') {
|
||||
// @ts-ignore
|
||||
values[key as keyof typeof form.values] = null;
|
||||
@@ -66,11 +74,11 @@ export default function Oauth({
|
||||
}
|
||||
}
|
||||
|
||||
if (key === 'oauthDiscordWhitelistIds') {
|
||||
if (Array.isArray(values['oauthDiscordWhitelistIds'])) continue;
|
||||
if (key === 'oauthDiscordAllowedIds' || key === 'oauthDiscordDeniedIds') {
|
||||
if (Array.isArray(values[key])) continue;
|
||||
|
||||
// @ts-ignore
|
||||
values['oauthDiscordWhitelistIds'] = (values['oauthDiscordWhitelistIds'] as string)
|
||||
values[key] = (values[key] as string)
|
||||
.split(',')
|
||||
.map((id) => id.trim())
|
||||
.filter((id) => id !== '');
|
||||
@@ -90,8 +98,11 @@ export default function Oauth({
|
||||
oauthDiscordClientId: data.settings.oauthDiscordClientId ?? '',
|
||||
oauthDiscordClientSecret: data.settings.oauthDiscordClientSecret ?? '',
|
||||
oauthDiscordRedirectUri: data.settings.oauthDiscordRedirectUri ?? '',
|
||||
oauthDiscordWhitelistIds: data.settings.oauthDiscordWhitelistIds
|
||||
? data.settings.oauthDiscordWhitelistIds.join(', ')
|
||||
oauthDiscordAllowedIds: data.settings.oauthDiscordAllowedIds
|
||||
? data.settings.oauthDiscordAllowedIds.join(', ')
|
||||
: '',
|
||||
oauthDiscordDeniedIds: data.settings.oauthDiscordDeniedIds
|
||||
? data.settings.oauthDiscordDeniedIds.join(', ')
|
||||
: '',
|
||||
|
||||
oauthGoogleClientId: data.settings.oauthGoogleClientId ?? '',
|
||||
@@ -147,9 +158,14 @@ export default function Oauth({
|
||||
<TextInput label='Discord Client ID' {...form.getInputProps('oauthDiscordClientId')} />
|
||||
<TextInput label='Discord Client Secret' {...form.getInputProps('oauthDiscordClientSecret')} />
|
||||
<TextInput
|
||||
label='Discord Whitelist IDs'
|
||||
description='A comma-separated list of Discord user IDs that are allowed to log in. Leave empty to allow all users.'
|
||||
{...form.getInputProps('oauthDiscordWhitelistIds')}
|
||||
label='Discord Allowed IDs'
|
||||
description='A comma-separated list of Discord user IDs that are allowed to log in. Leave empty to disable allow list.'
|
||||
{...form.getInputProps('oauthDiscordAllowedIds')}
|
||||
/>
|
||||
<TextInput
|
||||
label='Discord Denied IDs'
|
||||
description='A comma-separated list of Discord user IDs that are denied from logging in. Leave empty to disable deny list.'
|
||||
{...form.getInputProps('oauthDiscordDeniedIds')}
|
||||
/>
|
||||
<TextInput
|
||||
label='Discord Redirect URL'
|
||||
|
||||
@@ -70,7 +70,8 @@ export const DATABASE_TO_PROP = {
|
||||
oauthDiscordClientId: 'oauth.discord.clientId',
|
||||
oauthDiscordClientSecret: 'oauth.discord.clientSecret',
|
||||
oauthDiscordRedirectUri: 'oauth.discord.redirectUri',
|
||||
oauthDiscordWhitelistIds: 'oauth.discord.whitelistIds',
|
||||
oauthDiscordAllowedIds: 'oauth.discord.allowedIds',
|
||||
oauthDiscordDeniedIds: 'oauth.discord.deniedIds',
|
||||
|
||||
oauthGoogleClientId: 'oauth.google.clientId',
|
||||
oauthGoogleClientSecret: 'oauth.google.clientSecret',
|
||||
|
||||
@@ -95,7 +95,8 @@ export const ENVS = [
|
||||
env('oauth.discord.clientId', 'OAUTH_DISCORD_CLIENT_ID', 'string', true),
|
||||
env('oauth.discord.clientSecret', 'OAUTH_DISCORD_CLIENT_SECRET', 'string', true),
|
||||
env('oauth.discord.redirectUri', 'OAUTH_DISCORD_REDIRECT_URI', 'string', true),
|
||||
env('oauth.discord.whitelistIds', 'OAUTH_DISCORD_WHITELIST_IDS', 'string[]', true),
|
||||
env('oauth.discord.allowedIds', 'OAUTH_DISCORD_ALLOWED_IDS', 'string[]', true),
|
||||
env('oauth.discord.deniedIds', 'OAUTH_DISCORD_DENIED_IDS', 'string[]', true),
|
||||
|
||||
env('oauth.google.clientId', 'OAUTH_GOOGLE_CLIENT_ID', 'string', true),
|
||||
env('oauth.google.clientSecret', 'OAUTH_GOOGLE_CLIENT_SECRET', 'string', true),
|
||||
|
||||
@@ -222,14 +222,16 @@ export const schema = z.object({
|
||||
clientId: z.string(),
|
||||
clientSecret: z.string(),
|
||||
redirectUri: z.string().url().nullable().default(null),
|
||||
whitelistIds: z.array(z.string()).default([]),
|
||||
allowedIds: z.array(z.string()).default([]),
|
||||
deniedIds: z.array(z.string()).default([]),
|
||||
})
|
||||
.or(
|
||||
z.object({
|
||||
clientId: z.undefined(),
|
||||
clientSecret: z.undefined(),
|
||||
redirectUri: z.undefined(),
|
||||
whitelistIds: z.undefined().or(z.array(z.string()).default([])),
|
||||
allowedIds: z.undefined().or(z.array(z.string()).default([])),
|
||||
deniedIds: z.undefined().or(z.array(z.string()).default([])),
|
||||
}),
|
||||
),
|
||||
github: z
|
||||
|
||||
@@ -80,14 +80,12 @@ async function discordOauth({ code, host, state }: OAuthQuery, logger: Logger):
|
||||
|
||||
logger.debug('user', { '@me': userJson });
|
||||
|
||||
if (config.oauth.discord.whitelistIds?.length) {
|
||||
if (!config.oauth.discord.whitelistIds.includes(userJson.id)) {
|
||||
logger.warn('Discord user not whitelisted', { userId: userJson.id });
|
||||
return {
|
||||
error: 'You are not whitelisted to use Discord OAuth',
|
||||
error_code: 403,
|
||||
};
|
||||
}
|
||||
// handle config.oauth.discord.allowedIds and config.oauth.discord.deniedIds
|
||||
if (config.oauth.discord.allowedIds && !config.oauth.discord.allowedIds.includes(userJson.id)) {
|
||||
return { error: 'You are not allowed to log in with Discord.' };
|
||||
}
|
||||
if (config.oauth.discord.deniedIds && config.oauth.discord.deniedIds.includes(userJson.id)) {
|
||||
return { error: 'You are not allowed to log in with Discord.' };
|
||||
}
|
||||
|
||||
const avatar = userJson.avatar
|
||||
|
||||
@@ -222,7 +222,17 @@ export default fastifyPlugin(
|
||||
oauthDiscordClientId: z.string().nullable(),
|
||||
oauthDiscordClientSecret: z.string().nullable(),
|
||||
oauthDiscordRedirectUri: z.string().url().endsWith('/api/auth/oauth/discord').nullable(),
|
||||
oauthDiscordWhitelistIds: z
|
||||
oauthDiscordAllowedIds: z
|
||||
.union([
|
||||
z.array(z.string().refine((s) => /^\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,
|
||||
),
|
||||
oauthDiscordDeniedIds: z
|
||||
.union([
|
||||
z.array(z.string().refine((s) => /^\d+$/.test(s), 'Discord ID must be a number')),
|
||||
z
|
||||
|
||||
Reference in New Issue
Block a user