Some checks failed
CI / Unit & Component Tests (pull_request) Failing after 1m16s
CI / OCR Service Tests (pull_request) Successful in 20s
CI / Backend Unit Tests (pull_request) Successful in 3m27s
CI / fail2ban Regex (pull_request) Successful in 45s
CI / Semgrep Security Scan (pull_request) Successful in 19s
CI / Compose Bucket Idempotency (pull_request) Successful in 59s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
70 lines
2.2 KiB
TypeScript
70 lines
2.2 KiB
TypeScript
import { error } from '@sveltejs/kit';
|
|
import { env } from '$env/dynamic/private';
|
|
import { createApiClient, extractErrorCode } from '$lib/shared/api.server';
|
|
import { getErrorMessage } from '$lib/shared/errors';
|
|
import type { components } from '$lib/generated/api';
|
|
|
|
type UserGroup = components['schemas']['UserGroup'];
|
|
|
|
function hasPerm(user: { groups?: UserGroup[] } | undefined, perm: string): boolean {
|
|
return user?.groups?.some((g) => g.permissions.includes(perm)) ?? false;
|
|
}
|
|
|
|
function hasAnyAdminPerm(user: { groups?: UserGroup[] } | undefined): boolean {
|
|
return (
|
|
hasPerm(user, 'ADMIN') ||
|
|
hasPerm(user, 'ADMIN_USER') ||
|
|
hasPerm(user, 'ADMIN_TAG') ||
|
|
hasPerm(user, 'ADMIN_PERMISSION')
|
|
);
|
|
}
|
|
|
|
export async function load({ fetch, locals }) {
|
|
const user = locals.user;
|
|
if (!hasAnyAdminPerm(user)) throw error(403, getErrorMessage('FORBIDDEN'));
|
|
|
|
const api = createApiClient(fetch);
|
|
const canManageUsers = hasPerm(user, 'ADMIN_USER');
|
|
|
|
// TODO(#453): replace with dedicated /api/admin/stats endpoint returning counts only
|
|
const [usersResult, groupsResult, tagsResult] = await Promise.all([
|
|
api.GET('/api/users'),
|
|
api.GET('/api/groups'),
|
|
api.GET('/api/tags')
|
|
]);
|
|
|
|
if (!usersResult.response.ok) {
|
|
throw error(usersResult.response.status, getErrorMessage(extractErrorCode(usersResult.error)));
|
|
}
|
|
if (!groupsResult.response.ok) {
|
|
throw error(
|
|
groupsResult.response.status,
|
|
getErrorMessage(extractErrorCode(groupsResult.error))
|
|
);
|
|
}
|
|
if (!tagsResult.response.ok) {
|
|
throw error(tagsResult.response.status, getErrorMessage(extractErrorCode(tagsResult.error)));
|
|
}
|
|
|
|
let inviteCount = 0;
|
|
if (canManageUsers) {
|
|
const apiUrl = env.API_INTERNAL_URL || 'http://localhost:8080';
|
|
const inviteRes = await fetch(`${apiUrl}/api/invites`);
|
|
if (inviteRes.ok) {
|
|
const invites = await inviteRes.json();
|
|
inviteCount = Array.isArray(invites) ? invites.length : 0;
|
|
}
|
|
}
|
|
|
|
return {
|
|
userCount: (usersResult.data ?? []).length,
|
|
groupCount: (groupsResult.data ?? []).length,
|
|
tagCount: (tagsResult.data ?? []).length,
|
|
inviteCount,
|
|
canManageUsers,
|
|
canManageTags: hasPerm(user, 'ADMIN_TAG'),
|
|
canManagePermissions: hasPerm(user, 'ADMIN_PERMISSION'),
|
|
canRunMaintenance: hasPerm(user, 'ADMIN')
|
|
};
|
|
}
|