diff --git a/src/components/admin/admin-devices-table.tsx b/src/components/admin/admin-devices-table.tsx
index 9dcd564..963a923 100644
--- a/src/components/admin/admin-devices-table.tsx
+++ b/src/components/admin/admin-devices-table.tsx
@@ -11,7 +11,7 @@ import {
TableHeader,
TableRow,
} from "@/components/ui/table";
-import { userAtom } from "@/lib/auth-store";
+import { isAdminUser, userAtom } from "@/lib/auth-store";
import { cn } from "@/lib/utils";
import { getDevices } from "@/queries/devices";
import BlockDeviceDialog from "../block-device-dialog";
@@ -22,7 +22,7 @@ import Pagination from "../pagination";
export function AdminDevicesTable() {
const [searchParams] = useSearchParams();
const user = useAtomValue(userAtom);
- const isAdmin = user?.is_admin;
+ const isAdmin = isAdminUser(user);
const page = Number.parseInt(searchParams.get("page") as string) || 1;
const limit = 10;
diff --git a/src/components/devices-table.tsx b/src/components/devices-table.tsx
index b084ea0..a542fbf 100644
--- a/src/components/devices-table.tsx
+++ b/src/components/devices-table.tsx
@@ -10,7 +10,7 @@ import {
TableHeader,
TableRow,
} from "@/components/ui/table";
-import { userAtom } from "@/lib/auth-store";
+import { isAdminUser, userAtom } from "@/lib/auth-store";
import { getDevices } from "@/queries/devices";
import DevicesTableSkeleton from "./device-table-skeleton";
import ClickableRow from "./clickable-row";
@@ -27,7 +27,7 @@ export function DevicesTable({
}) {
const [searchParams] = useSearchParams();
const user = useAtomValue(userAtom);
- const isAdmin = user?.is_admin;
+ const isAdmin = isAdminUser(user);
const page = Number.parseInt(searchParams.get("page") as string) || 1;
const limit = 10;
diff --git a/src/components/ui/app-sidebar.tsx b/src/components/ui/app-sidebar.tsx
index 47e22aa..ad3df2b 100644
--- a/src/components/ui/app-sidebar.tsx
+++ b/src/components/ui/app-sidebar.tsx
@@ -29,7 +29,7 @@ import {
SidebarMenuItem,
SidebarRail,
} from "@/components/ui/sidebar";
-import { userAtom } from "@/lib/auth-store";
+import { isAdminUser, userAtom } from "@/lib/auth-store";
type Permission = {
id: number;
@@ -141,7 +141,7 @@ export function AppSidebar({
];
let CATEGORIES: Categories;
- if (user?.is_admin) {
+ if (isAdminUser(user)) {
CATEGORIES = categories;
} else {
// Filter out ADMIN CONTROL category for non-admin users
diff --git a/src/lib/auth-store.ts b/src/lib/auth-store.ts
index 08db710..63e83ca 100644
--- a/src/lib/auth-store.ts
+++ b/src/lib/auth-store.ts
@@ -42,6 +42,16 @@ export function getStoredUser(): AuthUser | null {
return store.get(userAtom);
}
+/**
+ * Single source of truth for "is this user an administrator?" on the client.
+ * Mirrors the backend `user_is_admin` helper: any of the app-specific
+ * `is_admin` flag, Django `is_staff`, or `is_superuser` grants admin access.
+ * Use this for every admin route/UI gate instead of checking `is_admin` alone.
+ */
+export function isAdminUser(user: AuthUser | null | undefined): boolean {
+ return Boolean(user && (user.is_admin || user.is_staff || user.is_superuser));
+}
+
/** Persist token + user on successful login. */
export function setAuth(token: string, user: AuthUser): void {
store.set(tokenAtom, token);
diff --git a/src/lib/types/user.ts b/src/lib/types/user.ts
index 2925bdc..0911c85 100644
--- a/src/lib/types/user.ts
+++ b/src/lib/types/user.ts
@@ -64,6 +64,7 @@ export interface AuthUser {
last_name: string;
email: string;
is_admin: boolean;
+ is_staff: boolean;
is_superuser: boolean;
last_login: string;
date_joined: string;
diff --git a/src/pages/admin/UserAgreement.tsx b/src/pages/admin/UserAgreement.tsx
index 2ab0db5..cf1ac3b 100644
--- a/src/pages/admin/UserAgreement.tsx
+++ b/src/pages/admin/UserAgreement.tsx
@@ -4,7 +4,7 @@ import { Navigate, useParams } from "react-router-dom";
import ClientErrorMessage from "@/components/client-error-message";
import FullPageLoader from "@/components/full-page-loader";
import UserAgreementForm from "@/components/user/user-agreement-form";
-import { userAtom } from "@/lib/auth-store";
+import { isAdminUser, userAtom } from "@/lib/auth-store";
import { getProfileById } from "@/queries/users";
export default function UserAgreement() {
@@ -17,7 +17,7 @@ export default function UserAgreement() {
enabled: !!userId,
});
- if (!authUser?.is_admin) return