Files
optima/src/routes/admin/users/+page.server.ts
T
2026-02-22 19:12:13 -06:00

144 lines
4.1 KiB
TypeScript

import { optima } from "$lib";
import { handleApiError } from "$lib/optima-api/errorHandler";
import { checkPermissions } from "$lib/permissions";
import { fail } from "@sveltejs/kit";
import type { Actions, PageServerLoad } from "./$types";
import { AxiosError } from "axios";
export const load: PageServerLoad = async ({ locals }) => {
const accessToken = locals.session?.accessToken;
if (!accessToken) {
return { users: [], roles: [], permissions: {} };
}
try {
const [usersResult, rolesResult, permissions, permNodesResult] =
await Promise.all([
optima.users.fetchAll(accessToken),
optima.role.fetchMany(accessToken),
checkPermissions(accessToken, [
"admin.users.view",
"admin.users.edit",
"admin.users.delete",
"user.roles.other",
"user.permissions.other",
]),
optima.permission
.fetchCategorized(accessToken)
.catch(() => ({ data: {} })),
]);
const allUsers = usersResult?.data ?? [];
const allRoles = rolesResult?.data ?? [];
// Fetch roles for each user in parallel
const usersWithRoles = await Promise.all(
allUsers.map(async (user) => {
try {
const rolesResult = await optima.users.fetchRoles(
accessToken,
user.id,
);
return { ...user, roleDetails: rolesResult?.data ?? [] };
} catch {
return { ...user, roleDetails: [] };
}
}),
);
return {
users: usersWithRoles,
roles: allRoles,
permissions,
permissionNodes: permNodesResult?.data ?? {},
};
} catch (err) {
handleApiError(err);
}
};
export const actions: Actions = {
updateUser: async ({ locals, request }) => {
const accessToken = locals.session?.accessToken;
if (!accessToken) {
return fail(401, { message: "Not authenticated." });
}
const formData = await request.formData();
const id = (formData.get("id") as string)?.trim();
const name = (formData.get("name") as string)?.trim();
const image = (formData.get("image") as string)?.trim() || undefined;
const rolesJson = (formData.get("roles") as string)?.trim();
const permissionsJson = (formData.get("permissions") as string)?.trim();
if (!id || !name) {
return fail(400, { message: "User ID and name are required." });
}
const updates: {
name: string;
image?: string;
roles?: string[];
permissions?: string[];
} = { name, image };
if (rolesJson) {
try {
updates.roles = JSON.parse(rolesJson);
} catch {
return fail(400, { message: "Invalid roles data." });
}
}
if (permissionsJson) {
try {
updates.permissions = JSON.parse(permissionsJson);
} catch {
return fail(400, { message: "Invalid permissions data." });
}
}
try {
await optima.users.update(accessToken, id, updates);
return {};
} catch (err: unknown) {
const data = (err as AxiosError)?.response?.data as
| Record<string, unknown>
| undefined;
const message =
(data?.message as string) ??
(err instanceof Error ? err.message : "Failed to update user.");
const status = (data?.status as number) ?? 500;
return fail(status, { message });
}
},
deleteUser: async ({ locals, request }) => {
const accessToken = locals.session?.accessToken;
if (!accessToken) {
return fail(401, { message: "Not authenticated." });
}
const formData = await request.formData();
const id = (formData.get("id") as string)?.trim();
if (!id) {
return fail(400, { message: "User ID is required." });
}
try {
await optima.users.delete(accessToken, id);
return {};
} catch (err: unknown) {
const data = (err as AxiosError)?.response?.data as
| Record<string, unknown>
| undefined;
const message =
(data?.message as string) ??
(err instanceof Error ? err.message : "Failed to delete user.");
const status = (data?.status as number) ?? 500;
return fail(status, { message });
}
},
};