forked from mirror/crumbs-original
feat(api): admin user management endpoints
- GET/POST /api/admin/users — list and create users (admin only) - PATCH/DELETE /api/admin/users/[id] — update role/reset password, delete user - PUT /api/auth/password — change own password All admin routes guarded by requireAdmin(). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
committed by
Fred Cabassut
co-authored by
Claude Opus 4.6
parent
133690994b
commit
33864d9355
@@ -0,0 +1,25 @@
|
||||
import { json, error } from '@sveltejs/kit';
|
||||
import type { RequestHandler } from './$types.js';
|
||||
import { requireAdmin } from '$lib/server/api-utils.js';
|
||||
import { listUsers, createUser } from '$lib/server/auth.js';
|
||||
|
||||
export const GET: RequestHandler = async (event) => {
|
||||
requireAdmin(event);
|
||||
return json(listUsers());
|
||||
};
|
||||
|
||||
export const POST: RequestHandler = async ({ request, ...event }) => {
|
||||
requireAdmin(event);
|
||||
const { email, displayName, password, role } = await request.json();
|
||||
|
||||
if (!email || !password) {
|
||||
throw error(400, 'Email and password are required');
|
||||
}
|
||||
|
||||
if (password.length < 8) {
|
||||
throw error(400, 'Password must be at least 8 characters');
|
||||
}
|
||||
|
||||
const user = await createUser(email, displayName || email.split('@')[0], password, role || 'user');
|
||||
return json(user, { status: 201 });
|
||||
};
|
||||
@@ -0,0 +1,46 @@
|
||||
import { json, error } from '@sveltejs/kit';
|
||||
import type { RequestHandler } from './$types.js';
|
||||
import { requireAdmin } from '$lib/server/api-utils.js';
|
||||
import { getUser, deleteUser, updateUserRole, resetPassword } from '$lib/server/auth.js';
|
||||
|
||||
export const PATCH: RequestHandler = async ({ params, request, ...event }) => {
|
||||
const admin = requireAdmin(event);
|
||||
const userId = parseInt(params.id, 10);
|
||||
const body = await request.json();
|
||||
|
||||
const user = getUser(userId);
|
||||
if (!user) throw error(404, 'User not found');
|
||||
|
||||
if (body.role !== undefined) {
|
||||
// Prevent admin from demoting themselves
|
||||
if (userId === admin.id && body.role !== 'admin') {
|
||||
throw error(400, 'Cannot change your own role');
|
||||
}
|
||||
updateUserRole(userId, body.role);
|
||||
}
|
||||
|
||||
if (body.newPassword !== undefined) {
|
||||
if (body.newPassword.length < 8) {
|
||||
throw error(400, 'Password must be at least 8 characters');
|
||||
}
|
||||
await resetPassword(userId, body.newPassword);
|
||||
}
|
||||
|
||||
const updated = getUser(userId);
|
||||
return json(updated);
|
||||
};
|
||||
|
||||
export const DELETE: RequestHandler = async ({ params, ...event }) => {
|
||||
const admin = requireAdmin(event);
|
||||
const userId = parseInt(params.id, 10);
|
||||
|
||||
if (userId === admin.id) {
|
||||
throw error(400, 'Cannot delete your own account');
|
||||
}
|
||||
|
||||
const user = getUser(userId);
|
||||
if (!user) throw error(404, 'User not found');
|
||||
|
||||
await deleteUser(userId);
|
||||
return json({ success: true });
|
||||
};
|
||||
@@ -0,0 +1,24 @@
|
||||
import { json, error } from '@sveltejs/kit';
|
||||
import type { RequestHandler } from './$types.js';
|
||||
import { getUserId } from '$lib/server/api-utils.js';
|
||||
import { changePassword } from '$lib/server/auth.js';
|
||||
|
||||
export const PUT: RequestHandler = async ({ request, ...event }) => {
|
||||
const userId = getUserId(event);
|
||||
const { currentPassword, newPassword } = await request.json();
|
||||
|
||||
if (!currentPassword || !newPassword) {
|
||||
throw error(400, 'Current password and new password are required');
|
||||
}
|
||||
|
||||
if (newPassword.length < 8) {
|
||||
throw error(400, 'New password must be at least 8 characters');
|
||||
}
|
||||
|
||||
const success = await changePassword(userId, currentPassword, newPassword);
|
||||
if (!success) {
|
||||
throw error(401, 'Current password is incorrect');
|
||||
}
|
||||
|
||||
return json({ success: true });
|
||||
};
|
||||
Reference in New Issue
Block a user