Files
nadir-webui/src/lib/auth/server.ts
T

118 lines
3.1 KiB
TypeScript

import { getRequestEvent } from '$app/server';
import { m } from '$lib/paraglide/messages';
import { getConfig } from '$lib/server/config';
import { db } from '$lib/server/db';
import * as schema from '$lib/server/db/schema';
import { emailer } from '$lib/server/emails';
import { drizzleAdapter } from 'better-auth/adapters/drizzle';
import { betterAuth } from 'better-auth/minimal';
import { admin, twoFactor, username } from 'better-auth/plugins';
import { genericOAuth, type GenericOAuthConfig } from 'better-auth/plugins/generic-oauth';
import { sveltekitCookies } from 'better-auth/svelte-kit';
import path from 'node:path';
import { cwd } from 'node:process';
export const oauthConfig = (await Bun.file(
path.join(cwd(), 'config/oauth.json')
).json()) as GenericOAuthConfig[];
function build() {
const cfg = getConfig();
return betterAuth({
basePath: '/api/auth',
baseURL: cfg.ORIGIN,
database: drizzleAdapter(db, {
provider: 'sqlite',
schema
}),
emailAndPassword: {
autoSignIn: false,
customSyntheticUser: ({ additionalFields, coreFields, id }) => ({
...coreFields,
banExpires: null,
banned: false,
banReason: null,
displayUsername: null,
role: 'user',
twoFactorEnabled: false,
username: null,
...additionalFields,
id
}),
disableSignUp: cfg.DISABLE_SIGNUP || false,
enabled: cfg.ENABLE_EMAIL_AND_PASSWORD || true,
requireEmailVerification: true,
sendResetPassword: async ({ token, url, user }) => {
if (url.endsWith('reset-password')) await emailer.sendResetPassword({ token, url, user });
if (url.endsWith('complete-registration'))
await emailer.sendCompleteRegistration({ token, url, user });
}
},
emailVerification: {
autoSignInAfterVerification: true,
sendOnSignIn: true,
sendOnSignUp: true,
sendVerificationEmail: async ({ url, user }) => {
await emailer.sendVerificationEmail({ url, user });
}
},
plugins: [
admin(),
genericOAuth({ config: oauthConfig }),
twoFactor({
issuer: m.appname(),
otpOptions: {
sendOTP: async ({ otp, user }) => {
await emailer.sendOtp({ otp, user });
}
},
totpOptions: {
period: 30
}
}),
username(),
sveltekitCookies(getRequestEvent)
],
rateLimit: { enabled: true },
socialProviders: {
facebook:
(cfg.FACEBOOK_CLIENT_ID && {
clientId: cfg.FACEBOOK_CLIENT_ID,
clientSecret: cfg.FACEBOOK_CLIENT_SECRET ?? ''
}) ||
undefined,
github:
(cfg.GITHUB_CLIENT_ID && {
clientId: cfg.GITHUB_CLIENT_ID,
clientSecret: cfg.GITHUB_CLIENT_SECRET ?? ''
}) ||
undefined,
google:
(cfg.GOOGLE_CLIENT_ID && {
clientId: cfg.GOOGLE_CLIENT_ID,
clientSecret: cfg.GOOGLE_CLIENT_SECRET ?? ''
}) ||
undefined
},
telemetry: { enabled: false },
user: {
deleteUser: {
enabled: true
}
}
});
}
let cached: null | ReturnType<typeof build> = null;
export type Auth = ReturnType<typeof build>;
export function getAuth(): ReturnType<typeof build> {
return (cached ??= build());
}
export function invalidateAuth(): void {
cached = null;
}