/** * Roles Management Page — Admin view for role-based permissions * Ball Studios */ import React, { useEffect, useState } from 'react'; import http from '@/api/http'; import { ServerContext } from '@/state/server'; import PageContentBlock from '@/components/elements/PageContentBlock'; import tw from 'twin.macro'; interface Role { id: number; name: string; color: string; description: string; permissions: string[]; created_at: string; } interface UserRole { role: Role; override: string | null; source: string; } export default function RolesPage() { const uuid = ServerContext.useStoreState((s) => s.server.data!.uuid); const [userRoles, setUserRoles] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(''); useEffect(() => { http.get(`/api/client/servers/${uuid}/addons/permissions/effective/me`) .then(({ data }: any) => setUserRoles(data.data ?? [])) .catch(() => setError('Failed to load role data.')) .finally(() => setLoading(false)); }, [uuid]); return (

🛡 Role Permissions

Your effective permissions for this server, managed by the Ball Studios Advanced Admin addon.

{loading && (
Loading permissions…
)} {error && (
{error}
)} {!loading && !error && userRoles.length === 0 && (
No roles assigned. Contact an administrator.
)}
{userRoles.map((ur, i) => (
{ur.role?.name ?? 'Unknown Role'} {ur.source && ( via {ur.source} )}
{ur.role?.description && (

{ur.role.description}

)} {ur.role?.permissions?.length > 0 && (
{ur.role.permissions.map((perm: string) => ( {perm} ))}
)}
))}
); }