const API_BASE = process.env.NEXT_PUBLIC_CORE_API_BASE ?? ""; export class ApiError extends Error {} async function req(path: string, init?: RequestInit): Promise { const res = await fetch(`${API_BASE}${path}`, { credentials: "include", headers: init?.body ? { "Content-Type": "application/json" } : undefined, ...init, }); const data = await res.json().catch(() => ({})); if (!res.ok) { throw new ApiError(data.error ?? data.message ?? "Unbekannter Fehler"); } return data as T; } export type Role = "user" | "tenant_admin"; export interface RoleInfo { role: Role; permissions: string[]; } export function fetchRoles(): Promise { return req("/rbac/roles"); } export interface Assignment { UserID: string; Role: Role; GrantedBy: string; } export function assignRole(userId: string, role: Role): Promise { return req("/rbac/users/role", { method: "POST", body: JSON.stringify({ user_id: userId, role }) }); } export function fetchRoleHistory(userId: string): Promise { return req(`/rbac/users/${userId}/history`); } export interface Group { ID: string; Name: string; Role: Role | ""; members: string[]; } export function fetchGroups(): Promise { return req("/rbac/groups"); } export function createGroup(name: string): Promise { return req("/rbac/groups", { method: "POST", body: JSON.stringify({ name }) }); } export function setGroupRole(groupId: string, role: Role): Promise { return req("/rbac/groups/role", { method: "POST", body: JSON.stringify({ group_id: groupId, role }) }); } export function addGroupMember(groupId: string, userId: string): Promise { return req("/rbac/groups/members", { method: "POST", body: JSON.stringify({ group_id: groupId, user_id: userId }) }); } export function removeGroupMember(groupId: string, userId: string): Promise { return req("/rbac/groups/members/remove", { method: "POST", body: JSON.stringify({ group_id: groupId, user_id: userId }) }); }