Add passkey and magic link authentication
This commit is contained in:
@@ -7,12 +7,13 @@ import { randomUUID } from 'node:crypto';
|
||||
import type { Actions, PageServerLoad } from './$types';
|
||||
import { avatarUrl } from '$lib/avatar';
|
||||
import { deleteUploadedAvatar } from '$lib/server/avatars';
|
||||
import { canRemoveAuthenticationMethod, getAuthenticationMethods } from '$lib/server/auth/methods';
|
||||
|
||||
export const load: PageServerLoad = async ({ cookies, params }) => {
|
||||
const operator = await requirePermission(await getSessionUser(cookies), 'users.view');
|
||||
const database = await getDatabase();
|
||||
const [profile, roles, permissions, assignedRoles, directPermissions, logins, builds, comments] = await Promise.all([
|
||||
(await database.prepare(`SELECT users.id,users.username,COALESCE(user_profiles.display_name,users.username) AS display_name,
|
||||
const [profile, roles, permissions, assignedRoles, directPermissions, logins, builds, comments, authenticationMethods] = await Promise.all([
|
||||
(await database.prepare(`SELECT users.id,users.login_username AS username,COALESCE(user_profiles.display_name,users.username) AS display_name,
|
||||
users.role,users.discord_id,users.created_at,
|
||||
CASE WHEN users.password_hash IS NOT NULL THEN 1 ELSE 0 END AS has_password,
|
||||
discord_profiles.username AS discord_username,discord_profiles.display_name AS discord_display_name,
|
||||
@@ -33,6 +34,7 @@ export const load: PageServerLoad = async ({ cookies, params }) => {
|
||||
(await database.prepare('SELECT id,title,slug,visibility,updated_at FROM builds WHERE owner_id=? ORDER BY updated_at DESC LIMIT 50')).all(params.id),
|
||||
(await database.prepare(`SELECT comments.id,comments.body,comments.created_at,builds.title,builds.slug
|
||||
FROM comments JOIN builds ON builds.id=comments.build_id WHERE comments.user_id=? ORDER BY comments.created_at DESC LIMIT 50`)).all(params.id)
|
||||
,getAuthenticationMethods(database, params.id)
|
||||
]);
|
||||
if (!profile) error(404, 'User not found');
|
||||
return {
|
||||
@@ -45,6 +47,7 @@ export const load: PageServerLoad = async ({ cookies, params }) => {
|
||||
assignedRoleIds: assignedRoles.map((row) => String(row.role_id)),
|
||||
directPermissionIds: directPermissions.map((row) => String(row.permission_id)),
|
||||
logins, builds, comments,
|
||||
authenticationMethods,
|
||||
operatorPermissions: await getPermissions(operator),
|
||||
isSelf: operator.id === params.id
|
||||
};
|
||||
@@ -144,11 +147,11 @@ export const actions: Actions = {
|
||||
unlinkDiscord: async ({ cookies, params }) => {
|
||||
const operator = await requirePermission(await getSessionUser(cookies), 'users.identities');
|
||||
const database = await getDatabase();
|
||||
const target = await (await database.prepare('SELECT discord_id,password_hash FROM users WHERE id=?')).get(params.id);
|
||||
const target = await (await database.prepare('SELECT discord_id FROM users WHERE id=?')).get(params.id);
|
||||
if (!target) return fail(404, { identityError: 'User not found.' });
|
||||
if (!target.discord_id) return fail(409, { identityError: 'This user does not have a linked Discord account.' });
|
||||
if (typeof target.password_hash !== 'string') {
|
||||
return fail(400, { identityError: 'Discord is this user’s only sign-in method. They must set a password before it can be unlinked.' });
|
||||
if (!canRemoveAuthenticationMethod(await getAuthenticationMethods(database, params.id), 'discord')) {
|
||||
return fail(400, { identityError: 'Discord cannot be unlinked because it is this user’s only sign-in method.' });
|
||||
}
|
||||
const now = new Date().toISOString();
|
||||
await (await database.prepare('UPDATE users SET discord_id=NULL WHERE id=?')).run(params.id);
|
||||
|
||||
Reference in New Issue
Block a user