bf4e5089ee
- Add OIDC/OAuth2 login via openid-client with PKCE flow - Auto-provision OAuth users with group mapping - Conditional login page (OAuth/local/both based on auth mode) - Admin OAuth test connection button - Install svelte-dnd-action for board editor DnD - Draggable sections and widgets with cross-section moves - Reorder APIs with atomic Prisma transactions - Visual drag handles and drop zone indicators
88 lines
2.5 KiB
TypeScript
88 lines
2.5 KiB
TypeScript
import type { Actions, PageServerLoad } from './$types.js';
|
|
import { superValidate, setError } from 'sveltekit-superforms';
|
|
import { zod } from '$lib/utils/zod-adapter.js';
|
|
import { fail, redirect } from '@sveltejs/kit';
|
|
import { loginSchema } from '$lib/utils/validators.js';
|
|
import * as userService from '$lib/server/services/userService.js';
|
|
import * as authService from '$lib/server/services/authService.js';
|
|
import { prisma } from '$lib/server/prisma.js';
|
|
import { DEFAULTS } from '$lib/utils/constants.js';
|
|
import type { AuthMode } from '$lib/utils/constants.js';
|
|
|
|
const COOKIE_BASE = {
|
|
httpOnly: true,
|
|
secure: process.env.NODE_ENV === 'production',
|
|
sameSite: 'lax' as const,
|
|
path: '/'
|
|
};
|
|
|
|
export const load: PageServerLoad = async ({ locals }) => {
|
|
// If already logged in, redirect to home
|
|
if (locals.user) {
|
|
throw redirect(302, '/');
|
|
}
|
|
|
|
// Load auth mode from SystemSettings
|
|
const settings = await prisma.systemSettings.findUnique({
|
|
where: { id: DEFAULTS.SYSTEM_SETTINGS_ID },
|
|
select: { authMode: true }
|
|
});
|
|
const authMode: AuthMode = (settings?.authMode as AuthMode) || 'local';
|
|
|
|
const form = await superValidate(zod(loginSchema));
|
|
return { form, authMode };
|
|
};
|
|
|
|
export const actions: Actions = {
|
|
default: async ({ request, cookies }) => {
|
|
const form = await superValidate(request, zod(loginSchema));
|
|
|
|
if (!form.valid) {
|
|
return fail(400, { form });
|
|
}
|
|
|
|
const { email, password } = form.data;
|
|
|
|
// Find user by email
|
|
const user = await userService.findByEmail(email);
|
|
if (!user) {
|
|
return setError(form, 'email', 'Invalid email or password');
|
|
}
|
|
|
|
// Verify password
|
|
if (!user.password) {
|
|
return setError(form, 'email', 'This account does not use password authentication');
|
|
}
|
|
|
|
const passwordValid = await authService.verifyPassword(password, user.password);
|
|
if (!passwordValid) {
|
|
return setError(form, 'email', 'Invalid email or password');
|
|
}
|
|
|
|
// Generate tokens
|
|
const accessToken = authService.signAccessToken({
|
|
userId: user.id,
|
|
email: user.email,
|
|
role: user.role
|
|
});
|
|
const refreshToken = authService.generateRefreshToken();
|
|
await authService.saveRefreshToken(user.id, refreshToken);
|
|
|
|
// Set cookies
|
|
cookies.set('access_token', accessToken, {
|
|
...COOKIE_BASE,
|
|
maxAge: 900 // 15 minutes
|
|
});
|
|
cookies.set('refresh_token', refreshToken, {
|
|
...COOKIE_BASE,
|
|
maxAge: 604800 // 7 days
|
|
});
|
|
cookies.set('refresh_user_id', user.id, {
|
|
...COOKIE_BASE,
|
|
maxAge: 604800 // 7 days
|
|
});
|
|
|
|
throw redirect(302, '/');
|
|
}
|
|
};
|