mirror of
https://github.com/khoaliber/dockhand.git
synced 2026-03-03 05:29:05 +00:00
137 lines
4.2 KiB
TypeScript
137 lines
4.2 KiB
TypeScript
import { json } from '@sveltejs/kit';
|
|
import type { RequestHandler } from '@sveltejs/kit';
|
|
import {
|
|
getUsers,
|
|
createUser as dbCreateUser,
|
|
assignUserRole,
|
|
hasAdminUser,
|
|
getUserRoles,
|
|
userHasAdminRole,
|
|
getRoleByName
|
|
} from '$lib/server/db';
|
|
import { hashPassword, createUserSession } from '$lib/server/auth';
|
|
import { authorize } from '$lib/server/authorize';
|
|
|
|
// GET /api/users - List all users
|
|
// Free for all - local users are needed for basic auth
|
|
export const GET: RequestHandler = async ({ cookies }) => {
|
|
const auth = await authorize(cookies);
|
|
|
|
// When auth is enabled, require valid session (no specific permission needed to view users list)
|
|
if (auth.authEnabled && !auth.isAuthenticated) {
|
|
return json({ error: 'Authentication required' }, { status: 401 });
|
|
}
|
|
// Any authenticated user can view the users list
|
|
// Admin permissions are only needed for create/edit/delete operations
|
|
|
|
try {
|
|
const allUsers = await getUsers();
|
|
const users = await Promise.all(allUsers.map(async user => {
|
|
// Derive isAdmin from role assignment
|
|
const isAdmin = await userHasAdminRole(user.id);
|
|
const isSso = !user.passwordHash;
|
|
const userData: any = {
|
|
id: user.id,
|
|
username: user.username,
|
|
email: user.email,
|
|
displayName: user.displayName,
|
|
mfaEnabled: user.mfaEnabled,
|
|
isAdmin,
|
|
isActive: user.isActive,
|
|
isSso,
|
|
authProvider: user.authProvider || 'local',
|
|
lastLogin: user.lastLogin,
|
|
createdAt: user.createdAt
|
|
};
|
|
// Include roles for enterprise users
|
|
if (auth.isEnterprise) {
|
|
const userRoles = await getUserRoles(user.id);
|
|
userData.roles = userRoles.map(ur => ({
|
|
id: ur.roleId,
|
|
name: ur.role?.name,
|
|
environmentId: ur.environmentId
|
|
}));
|
|
}
|
|
return userData;
|
|
}));
|
|
return json(users);
|
|
} catch (error) {
|
|
console.error('Failed to get users:', error);
|
|
return json({ error: 'Failed to get users' }, { status: 500 });
|
|
}
|
|
};
|
|
|
|
// POST /api/users - Create a new user
|
|
// Free for all - local users are needed for basic auth
|
|
export const POST: RequestHandler = async ({ request, cookies }) => {
|
|
const auth = await authorize(cookies);
|
|
|
|
// When auth is enabled and user is logged in, check they can manage users
|
|
// (allow if no user logged in for initial setup when no users exist)
|
|
if (auth.authEnabled && auth.isAuthenticated && !await auth.canManageUsers()) {
|
|
return json({ error: 'Permission denied' }, { status: 403 });
|
|
}
|
|
|
|
try {
|
|
const { username, email, password, displayName } = await request.json();
|
|
|
|
if (!username || !password) {
|
|
return json({ error: 'Username and password are required' }, { status: 400 });
|
|
}
|
|
|
|
// Validate password strength
|
|
if (password.length < 8) {
|
|
return json({ error: 'Password must be at least 8 characters' }, { status: 400 });
|
|
}
|
|
|
|
// Hash password
|
|
const passwordHash = await hashPassword(password);
|
|
|
|
// Check if this is the first user
|
|
const isFirstUser = !(await hasAdminUser());
|
|
|
|
// Create user
|
|
const user = await dbCreateUser({
|
|
username,
|
|
email,
|
|
passwordHash,
|
|
displayName
|
|
});
|
|
|
|
// Role assignment logic:
|
|
// - Enterprise: Roles are managed via syncUserRoles() from the modal (no auto-assignment here)
|
|
// - Free edition: All users get Admin role (no RBAC)
|
|
// - First user: Always gets Admin role (regardless of edition)
|
|
if (!auth.isEnterprise || isFirstUser) {
|
|
const adminRole = await getRoleByName('Admin');
|
|
if (adminRole) {
|
|
await assignUserRole(user.id, adminRole.id, null);
|
|
}
|
|
}
|
|
|
|
// Auto-login if this is the first user being created (and auth is enabled)
|
|
let autoLoggedIn = false;
|
|
if (isFirstUser && auth.authEnabled) {
|
|
await createUserSession(user.id, 'local', cookies);
|
|
autoLoggedIn = true;
|
|
}
|
|
|
|
return json({
|
|
id: user.id,
|
|
username: user.username,
|
|
email: user.email,
|
|
displayName: user.displayName,
|
|
isAdmin: !auth.isEnterprise || isFirstUser,
|
|
isActive: user.isActive,
|
|
createdAt: user.createdAt,
|
|
autoLoggedIn: autoLoggedIn
|
|
}, { status: 201 });
|
|
} catch (error: any) {
|
|
console.error('Failed to create user:', error);
|
|
if (error.message?.includes('UNIQUE constraint failed')) {
|
|
return json({ error: 'Username already exists' }, { status: 409 });
|
|
}
|
|
return json({ error: 'Failed to create user' }, { status: 500 });
|
|
}
|
|
};
|