From d2936cd10bc29c11383e9982726549303b2fee10 Mon Sep 17 00:00:00 2001
From: Fred KISSIE
Date: Wed, 2 Sep 2026 19:19:03 +0200
Subject: [PATCH 1/4] =?UTF-8?q?=F0=9F=9A=A7=20server=20admin?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
messages/en-US.json | 9 ++
server/routers/external.ts | 6 +
server/routers/user/adminListUsers.ts | 4 +-
.../routers/user/adminPromoteServerAdmin.ts | 116 +++++++++++++++++
server/routers/user/index.ts | 1 +
src/app/admin/users/page.tsx | 3 +
src/components/AdminUsersTable.tsx | 122 +++++++++++++++++-
.../command-palette/CommandPalette.tsx | 4 +-
8 files changed, 259 insertions(+), 6 deletions(-)
create mode 100644 server/routers/user/adminPromoteServerAdmin.ts
diff --git a/messages/en-US.json b/messages/en-US.json
index 5199aee71..6c1f1fcf4 100644
--- a/messages/en-US.json
+++ b/messages/en-US.json
@@ -1424,6 +1424,15 @@
"logoutError": "Error logging out",
"signingAs": "Signed in as",
"serverAdmin": "Server Admin",
+ "promoteServerAdmin": "Promote to Server admin",
+ "promoteServerAdminTitle": "Promote to Server Admin",
+ "promoteServerAdminQuestion": "Are you sure you want to promote {selectedUser} to server admin?",
+ "promoteServerAdminMessage": "Server admins have full access to every organization, user, and setting on this instance.",
+ "promoteServerAdminWarning": "You cannot demote a server admin from this page.",
+ "promoteServerAdminConfirm": "Promote to server admin",
+ "promoteServerAdminSuccess": "User promoted",
+ "promoteServerAdminSuccessDescription": "{selectedUser} is now a server admin.",
+ "promoteServerAdminError": "Failed to promote user",
"managedSelfhosted": "Managed Self-Hosted",
"otpEnable": "Enable Two-factor",
"otpDisable": "Disable Two-factor",
diff --git a/server/routers/external.ts b/server/routers/external.ts
index d2935ff91..de0e68fe0 100644
--- a/server/routers/external.ts
+++ b/server/routers/external.ts
@@ -1378,6 +1378,12 @@ if (build !== "saas") {
user.adminGeneratePasswordResetCode
);
+ authenticated.post(
+ "/user/:userId/promote-server-admin",
+ verifyUserIsServerAdmin,
+ user.adminPromoteServerAdmin
+ );
+
authenticated.delete(
"/user/:userId",
verifyUserIsServerAdmin,
diff --git a/server/routers/user/adminListUsers.ts b/server/routers/user/adminListUsers.ts
index f3c08f25b..0a5bad705 100644
--- a/server/routers/user/adminListUsers.ts
+++ b/server/routers/user/adminListUsers.ts
@@ -4,7 +4,7 @@ import { db, idp, users } from "@server/db";
import response from "@server/lib/response";
import HttpCode from "@server/types/HttpCode";
import createHttpError from "http-errors";
-import { and, asc, desc, eq, like, or, sql } from "drizzle-orm";
+import { and, asc, desc, eq, like, or, sql, type SQL } from "drizzle-orm";
import logger from "@server/logger";
import { fromZodError } from "zod-validation-error";
import { OpenAPITags, registry } from "@server/openApi";
@@ -196,7 +196,7 @@ export async function adminListUsers(
}
}
- const conditions = [eq(users.serverAdmin, false)];
+ const conditions: Array | undefined> = [];
if (query) {
const q = "%" + query.toLowerCase() + "%";
diff --git a/server/routers/user/adminPromoteServerAdmin.ts b/server/routers/user/adminPromoteServerAdmin.ts
new file mode 100644
index 000000000..6c077fca6
--- /dev/null
+++ b/server/routers/user/adminPromoteServerAdmin.ts
@@ -0,0 +1,116 @@
+import { Request, Response, NextFunction } from "express";
+import { z } from "zod";
+import { db, users } from "@server/db";
+import { eq } from "drizzle-orm";
+import response from "@server/lib/response";
+import HttpCode from "@server/types/HttpCode";
+import createHttpError from "http-errors";
+import logger from "@server/logger";
+import { fromError } from "zod-validation-error";
+import { OpenAPITags, registry } from "@server/openApi";
+import { createApiResponseSchema } from "@server/lib/openapi/createApiResponseSchema";
+
+const promoteServerAdminParamsSchema = z.strictObject({
+ userId: z.string()
+});
+
+export type AdminPromoteServerAdminResponse = {
+ userId: string;
+ serverAdmin: boolean;
+};
+
+const AdminPromoteServerAdminResponseDataSchema = z.object({
+ userId: z.string(),
+ serverAdmin: z.boolean()
+});
+
+registry.registerPath({
+ method: "post",
+ path: "/user/{userId}/promote-server-admin",
+ description: "Promote a user to server admin (server admin).",
+ tags: [OpenAPITags.User],
+ request: {
+ params: promoteServerAdminParamsSchema
+ },
+ responses: {
+ 200: {
+ description: "Successful response",
+ content: {
+ "application/json": {
+ schema: createApiResponseSchema(
+ AdminPromoteServerAdminResponseDataSchema
+ )
+ }
+ }
+ }
+ }
+});
+
+export async function adminPromoteServerAdmin(
+ req: Request,
+ res: Response,
+ next: NextFunction
+): Promise {
+ try {
+ const parsedParams = promoteServerAdminParamsSchema.safeParse(
+ req.params
+ );
+ if (!parsedParams.success) {
+ return next(
+ createHttpError(
+ HttpCode.BAD_REQUEST,
+ fromError(parsedParams.error).toString()
+ )
+ );
+ }
+
+ const { userId } = parsedParams.data;
+
+ const [existingUser] = await db
+ .select({
+ userId: users.userId,
+ serverAdmin: users.serverAdmin
+ })
+ .from(users)
+ .where(eq(users.userId, userId))
+ .limit(1);
+
+ if (!existingUser) {
+ return next(createHttpError(HttpCode.NOT_FOUND, "User not found"));
+ }
+
+ if (existingUser.serverAdmin) {
+ return next(
+ createHttpError(
+ HttpCode.BAD_REQUEST,
+ "User is already a server admin"
+ )
+ );
+ }
+
+ logger.info(
+ `Promoting user ${userId} to server admin (by ${req.user?.userId})`
+ );
+
+ await db
+ .update(users)
+ .set({ serverAdmin: true })
+ .where(eq(users.userId, userId));
+
+ return response(res, {
+ data: {
+ userId: existingUser.userId,
+ serverAdmin: true
+ },
+ success: true,
+ error: false,
+ message: "User promoted to server admin successfully",
+ status: HttpCode.OK
+ });
+ } catch (error) {
+ logger.error(error);
+ return next(
+ createHttpError(HttpCode.INTERNAL_SERVER_ERROR, "An error occurred")
+ );
+ }
+}
diff --git a/server/routers/user/index.ts b/server/routers/user/index.ts
index 690a013f6..732794eaf 100644
--- a/server/routers/user/index.ts
+++ b/server/routers/user/index.ts
@@ -11,6 +11,7 @@ export * from "./adminListUsers";
export * from "./adminRemoveUser";
export * from "./adminGetUser";
export * from "./adminGeneratePasswordResetCode";
+export * from "./adminPromoteServerAdmin";
export * from "./listInvitations";
export * from "./removeInvitation";
export * from "./createOrgUser";
diff --git a/src/app/admin/users/page.tsx b/src/app/admin/users/page.tsx
index 0cfaaf3b0..cb06373ab 100644
--- a/src/app/admin/users/page.tsx
+++ b/src/app/admin/users/page.tsx
@@ -81,6 +81,9 @@ export default async function UsersPage(props: AdminUsersPageProps) {
};
});
+ console.log({
+ userRows
+ });
return (
<>
(null);
const [isGeneratingCode, setIsGeneratingCode] = useState(false);
+ const [isPromoteModalOpen, setIsPromoteModalOpen] = useState(false);
+ const [promoting, setPromoting] = useState(null);
+ const user = useUserContext();
const [isRefreshing, startTransition] = useTransition();
const {
@@ -184,6 +196,37 @@ export default function UsersTable({
}
};
+ const promoteToServerAdmin = async (user: GlobalUserRow) => {
+ try {
+ await api.post(`/user/${user.id}/promote-server-admin`);
+
+ toast({
+ title: t("promoteServerAdminSuccess"),
+ description: t("promoteServerAdminSuccessDescription", {
+ selectedUser: getUserDisplayName({
+ email: user.email,
+ name: user.name,
+ username: user.username
+ })
+ })
+ });
+
+ startTransition(() => {
+ router.refresh();
+ });
+ } catch (e) {
+ console.error(t("promoteServerAdminError"), e);
+ toast({
+ variant: "destructive",
+ title: t("promoteServerAdminError"),
+ description: formatAxiosError(e, t("promoteServerAdminError"))
+ });
+ } finally {
+ setIsPromoteModalOpen(false);
+ setPromoting(null);
+ }
+ };
+
function toggleSort(column: string) {
const newSearch = getNextSortOrder(column, searchParams);
filter({
@@ -235,7 +278,35 @@ export default function UsersTable({
);
- }
+ },
+ cell: ({ row }) => (
+
+ {row.original.username}{" "}
+ {row.original.id === user.user.userId && (
+ <>
+
+ ·
+ {" "}
+ you
+ >
+ )}
+ {row.original.serverAdmin && (
+ <>
+
+
+
+
+
+
+ {t("serverAdmin")}
+
+
+
+ {/* {t("serverAdmin")} */}
+ >
+ )}
+
+ )
},
{
accessorKey: "email",
@@ -369,11 +440,22 @@ export default function UsersTable({
{t("generatePasswordResetCode")}
)}
+ {!r.serverAdmin && (
+ {
+ setPromoting(r);
+ setIsPromoteModalOpen(true);
+ }}
+ >
+ {t("promoteServerAdmin")}
+
+ )}
{
setSelected(r);
setIsDeleteModalOpen(true);
}}
+ className="text-red-400"
>
{t("delete")}
@@ -435,6 +517,42 @@ export default function UsersTable({
/>
)}
+ {promoting && (
+ {
+ setIsPromoteModalOpen(val);
+ if (!val) {
+ setPromoting(null);
+ }
+ }}
+ dialog={
+
+
+ {t("promoteServerAdminQuestion", {
+ selectedUser: getUserDisplayName({
+ email: promoting.email,
+ name: promoting.name,
+ username: promoting.username
+ })
+ })}
+
+
+
{t("promoteServerAdminMessage")}
+
+ }
+ buttonText={t("promoteServerAdminConfirm")}
+ onConfirm={async () => promoteToServerAdmin(promoting)}
+ string={getUserDisplayName({
+ email: promoting.email,
+ name: promoting.name,
+ username: promoting.username
+ })}
+ warningText={t("promoteServerAdminWarning")}
+ title={t("promoteServerAdminTitle")}
+ />
+ )}
+
- {t("commandPaletteNoResults")}
-
+ {t("commandPaletteNoResults")}
+
{!isActionMode &&
navigationGroups.map((group, groupIndex) => (
From 1ad613f40302a8c86f9a15670d7c245a750e8936 Mon Sep 17 00:00:00 2001
From: Fred KISSIE
Date: Thu, 3 Sep 2026 22:40:36 +0200
Subject: [PATCH 2/4] =?UTF-8?q?=F0=9F=9A=A7=20toggle=20server=20admin?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
messages/en-US.json | 11 ++-
server/routers/external.ts | 4 +-
...eServerAdmin.ts => adminSetServerAdmin.ts} | 68 ++++++++++-----
server/routers/user/index.ts | 2 +-
src/components/AdminUsersTable.tsx | 87 ++++++++++++++++---
5 files changed, 136 insertions(+), 36 deletions(-)
rename server/routers/user/{adminPromoteServerAdmin.ts => adminSetServerAdmin.ts} (55%)
diff --git a/messages/en-US.json b/messages/en-US.json
index 6c1f1fcf4..d3496760b 100644
--- a/messages/en-US.json
+++ b/messages/en-US.json
@@ -1428,11 +1428,20 @@
"promoteServerAdminTitle": "Promote to Server Admin",
"promoteServerAdminQuestion": "Are you sure you want to promote {selectedUser} to server admin?",
"promoteServerAdminMessage": "Server admins have full access to every organization, user, and setting on this instance.",
- "promoteServerAdminWarning": "You cannot demote a server admin from this page.",
+ "promoteServerAdminWarning": "This can be undone at any time by demoting the user from this page.",
"promoteServerAdminConfirm": "Promote to server admin",
"promoteServerAdminSuccess": "User promoted",
"promoteServerAdminSuccessDescription": "{selectedUser} is now a server admin.",
"promoteServerAdminError": "Failed to promote user",
+ "demoteServerAdmin": "Demote from Server admin",
+ "demoteServerAdminTitle": "Demote from Server Admin",
+ "demoteServerAdminQuestion": "Are you sure you want to demote {selectedUser} from server admin?",
+ "demoteServerAdminMessage": "{selectedUser} will lose full access to every organization, user, and setting on this instance.",
+ "demoteServerAdminWarning": "This can be undone at any time by promoting the user from this page.",
+ "demoteServerAdminConfirm": "Demote from server admin",
+ "demoteServerAdminSuccess": "User demoted",
+ "demoteServerAdminSuccessDescription": "{selectedUser} is no longer a server admin.",
+ "demoteServerAdminError": "Failed to demote user",
"managedSelfhosted": "Managed Self-Hosted",
"otpEnable": "Enable Two-factor",
"otpDisable": "Disable Two-factor",
diff --git a/server/routers/external.ts b/server/routers/external.ts
index de0e68fe0..8e009bb0d 100644
--- a/server/routers/external.ts
+++ b/server/routers/external.ts
@@ -1379,9 +1379,9 @@ if (build !== "saas") {
);
authenticated.post(
- "/user/:userId/promote-server-admin",
+ "/user/:userId/server-admin",
verifyUserIsServerAdmin,
- user.adminPromoteServerAdmin
+ user.adminSetServerAdmin
);
authenticated.delete(
diff --git a/server/routers/user/adminPromoteServerAdmin.ts b/server/routers/user/adminSetServerAdmin.ts
similarity index 55%
rename from server/routers/user/adminPromoteServerAdmin.ts
rename to server/routers/user/adminSetServerAdmin.ts
index 6c077fca6..1cc90a084 100644
--- a/server/routers/user/adminPromoteServerAdmin.ts
+++ b/server/routers/user/adminSetServerAdmin.ts
@@ -10,27 +10,38 @@ import { fromError } from "zod-validation-error";
import { OpenAPITags, registry } from "@server/openApi";
import { createApiResponseSchema } from "@server/lib/openapi/createApiResponseSchema";
-const promoteServerAdminParamsSchema = z.strictObject({
+const setServerAdminParamsSchema = z.strictObject({
userId: z.string()
});
-export type AdminPromoteServerAdminResponse = {
+const setServerAdminBodySchema = z.strictObject({
+ serverAdmin: z.boolean()
+});
+
+export type AdminSetServerAdminResponse = {
userId: string;
serverAdmin: boolean;
};
-const AdminPromoteServerAdminResponseDataSchema = z.object({
+const AdminSetServerAdminResponseDataSchema = z.object({
userId: z.string(),
serverAdmin: z.boolean()
});
registry.registerPath({
method: "post",
- path: "/user/{userId}/promote-server-admin",
- description: "Promote a user to server admin (server admin).",
+ path: "/user/{userId}/server-admin",
+ description: "Promote or demote a user's server admin status (server admin).",
tags: [OpenAPITags.User],
request: {
- params: promoteServerAdminParamsSchema
+ params: setServerAdminParamsSchema,
+ body: {
+ content: {
+ "application/json": {
+ schema: setServerAdminBodySchema
+ }
+ }
+ }
},
responses: {
200: {
@@ -38,7 +49,7 @@ registry.registerPath({
content: {
"application/json": {
schema: createApiResponseSchema(
- AdminPromoteServerAdminResponseDataSchema
+ AdminSetServerAdminResponseDataSchema
)
}
}
@@ -46,13 +57,13 @@ registry.registerPath({
}
});
-export async function adminPromoteServerAdmin(
+export async function adminSetServerAdmin(
req: Request,
res: Response,
next: NextFunction
): Promise {
try {
- const parsedParams = promoteServerAdminParamsSchema.safeParse(
+ const parsedParams = setServerAdminParamsSchema.safeParse(
req.params
);
if (!parsedParams.success) {
@@ -64,7 +75,18 @@ export async function adminPromoteServerAdmin(
);
}
+ const parsedBody = setServerAdminBodySchema.safeParse(req.body);
+ if (!parsedBody.success) {
+ return next(
+ createHttpError(
+ HttpCode.BAD_REQUEST,
+ fromError(parsedBody.error).toString()
+ )
+ );
+ }
+
const { userId } = parsedParams.data;
+ const { serverAdmin } = parsedBody.data;
const [existingUser] = await db
.select({
@@ -79,32 +101,36 @@ export async function adminPromoteServerAdmin(
return next(createHttpError(HttpCode.NOT_FOUND, "User not found"));
}
- if (existingUser.serverAdmin) {
+ if (!serverAdmin && req.user?.userId === userId) {
return next(
createHttpError(
HttpCode.BAD_REQUEST,
- "User is already a server admin"
+ "You cannot remove your own server admin status"
)
);
}
- logger.info(
- `Promoting user ${userId} to server admin (by ${req.user?.userId})`
- );
+ if (existingUser.serverAdmin !== serverAdmin) {
+ logger.info(
+ `${serverAdmin ? "Promoting" : "Demoting"} user ${userId} ${serverAdmin ? "to" : "from"} server admin (by ${req.user?.userId})`
+ );
- await db
- .update(users)
- .set({ serverAdmin: true })
- .where(eq(users.userId, userId));
+ await db
+ .update(users)
+ .set({ serverAdmin })
+ .where(eq(users.userId, userId));
+ }
- return response(res, {
+ return response(res, {
data: {
userId: existingUser.userId,
- serverAdmin: true
+ serverAdmin
},
success: true,
error: false,
- message: "User promoted to server admin successfully",
+ message: serverAdmin
+ ? "User promoted to server admin successfully"
+ : "User demoted from server admin successfully",
status: HttpCode.OK
});
} catch (error) {
diff --git a/server/routers/user/index.ts b/server/routers/user/index.ts
index 732794eaf..50db85832 100644
--- a/server/routers/user/index.ts
+++ b/server/routers/user/index.ts
@@ -11,7 +11,7 @@ export * from "./adminListUsers";
export * from "./adminRemoveUser";
export * from "./adminGetUser";
export * from "./adminGeneratePasswordResetCode";
-export * from "./adminPromoteServerAdmin";
+export * from "./adminSetServerAdmin";
export * from "./listInvitations";
export * from "./removeInvitation";
export * from "./createOrgUser";
diff --git a/src/components/AdminUsersTable.tsx b/src/components/AdminUsersTable.tsx
index ce4cff8aa..fc1192212 100644
--- a/src/components/AdminUsersTable.tsx
+++ b/src/components/AdminUsersTable.tsx
@@ -101,6 +101,8 @@ export default function UsersTable({
const [isGeneratingCode, setIsGeneratingCode] = useState(false);
const [isPromoteModalOpen, setIsPromoteModalOpen] = useState(false);
const [promoting, setPromoting] = useState(null);
+ const [isDemoteModalOpen, setIsDemoteModalOpen] = useState(false);
+ const [demoting, setDemoting] = useState(null);
const user = useUserContext();
const [isRefreshing, startTransition] = useTransition();
@@ -196,17 +198,32 @@ export default function UsersTable({
}
};
- const promoteToServerAdmin = async (user: GlobalUserRow) => {
+ const setServerAdmin = async (
+ targetUser: GlobalUserRow,
+ serverAdmin: boolean
+ ) => {
+ const successTitleKey = serverAdmin
+ ? "promoteServerAdminSuccess"
+ : "demoteServerAdminSuccess";
+ const successDescriptionKey = serverAdmin
+ ? "promoteServerAdminSuccessDescription"
+ : "demoteServerAdminSuccessDescription";
+ const errorKey = serverAdmin
+ ? "promoteServerAdminError"
+ : "demoteServerAdminError";
+
try {
- await api.post(`/user/${user.id}/promote-server-admin`);
+ await api.post(`/user/${targetUser.id}/server-admin`, {
+ serverAdmin
+ });
toast({
- title: t("promoteServerAdminSuccess"),
- description: t("promoteServerAdminSuccessDescription", {
+ title: t(successTitleKey),
+ description: t(successDescriptionKey, {
selectedUser: getUserDisplayName({
- email: user.email,
- name: user.name,
- username: user.username
+ email: targetUser.email,
+ name: targetUser.name,
+ username: targetUser.username
})
})
});
@@ -215,15 +232,17 @@ export default function UsersTable({
router.refresh();
});
} catch (e) {
- console.error(t("promoteServerAdminError"), e);
+ console.error(t(errorKey), e);
toast({
variant: "destructive",
- title: t("promoteServerAdminError"),
- description: formatAxiosError(e, t("promoteServerAdminError"))
+ title: t(errorKey),
+ description: formatAxiosError(e, t(errorKey))
});
} finally {
setIsPromoteModalOpen(false);
setPromoting(null);
+ setIsDemoteModalOpen(false);
+ setDemoting(null);
}
};
@@ -450,6 +469,16 @@ export default function UsersTable({
{t("promoteServerAdmin")}
)}
+ {r.serverAdmin && r.id !== user.user.userId && (
+ {
+ setDemoting(r);
+ setIsDemoteModalOpen(true);
+ }}
+ >
+ {t("demoteServerAdmin")}
+
+ )}
{
setSelected(r);
@@ -542,7 +571,7 @@ export default function UsersTable({
}
buttonText={t("promoteServerAdminConfirm")}
- onConfirm={async () => promoteToServerAdmin(promoting)}
+ onConfirm={async () => setServerAdmin(promoting, true)}
string={getUserDisplayName({
email: promoting.email,
name: promoting.name,
@@ -553,6 +582,42 @@ export default function UsersTable({
/>
)}
+ {demoting && (
+ {
+ setIsDemoteModalOpen(val);
+ if (!val) {
+ setDemoting(null);
+ }
+ }}
+ dialog={
+
+
+ {t("demoteServerAdminQuestion", {
+ selectedUser: getUserDisplayName({
+ email: demoting.email,
+ name: demoting.name,
+ username: demoting.username
+ })
+ })}
+
+
+
{t("demoteServerAdminMessage")}
+
+ }
+ buttonText={t("demoteServerAdminConfirm")}
+ onConfirm={async () => setServerAdmin(demoting, false)}
+ string={getUserDisplayName({
+ email: demoting.email,
+ name: demoting.name,
+ username: demoting.username
+ })}
+ warningText={t("demoteServerAdminWarning")}
+ title={t("demoteServerAdminTitle")}
+ />
+ )}
+
Date: Fri, 4 Sep 2026 20:40:16 +0200
Subject: [PATCH 3/4] =?UTF-8?q?=F0=9F=92=AC=20update=20text?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/components/AdminUsersTable.tsx | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/src/components/AdminUsersTable.tsx b/src/components/AdminUsersTable.tsx
index fc1192212..8bb141487 100644
--- a/src/components/AdminUsersTable.tsx
+++ b/src/components/AdminUsersTable.tsx
@@ -603,7 +603,15 @@ export default function UsersTable({
})}
- {t("demoteServerAdminMessage")}
+
+ {t("demoteServerAdminMessage", {
+ selectedUser: getUserDisplayName({
+ email: demoting.email,
+ name: demoting.name,
+ username: demoting.username
+ })
+ })}
+
}
buttonText={t("demoteServerAdminConfirm")}
From 0be7628a002b35f721f7424f85af4ca8f66fa847 Mon Sep 17 00:00:00 2001
From: Fred KISSIE
Date: Fri, 4 Sep 2026 23:11:29 +0200
Subject: [PATCH 4/4] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20refactor?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/app/admin/users/page.tsx | 3 ---
1 file changed, 3 deletions(-)
diff --git a/src/app/admin/users/page.tsx b/src/app/admin/users/page.tsx
index cb06373ab..0cfaaf3b0 100644
--- a/src/app/admin/users/page.tsx
+++ b/src/app/admin/users/page.tsx
@@ -81,9 +81,6 @@ export default async function UsersPage(props: AdminUsersPageProps) {
};
});
- console.log({
- userRows
- });
return (
<>