From 39a1a3695ee19c7d25cf0a521f6a59f153ee5e8e Mon Sep 17 00:00:00 2001 From: ajnart Date: Mon, 6 Jul 2026 06:31:42 +0200 Subject: [PATCH] fix: address coderabbit review on #6214 - Remove invalid null return from session callback (must return session object) - Prevent admin from disabling their own account (guard with isSelf check) - Hide disable UI when viewing own profile - Add user existence check to changeDisabled endpoint - Add OpenAPI metadata to changeDisabled mutation --- .../_components/_disable-user-button.tsx | 8 +++++-- .../manage/users/[userId]/general/page.tsx | 12 +++++----- packages/api/src/router/user.ts | 22 +++++++++++++++++++ packages/auth/callbacks.ts | 5 ----- 4 files changed, 35 insertions(+), 12 deletions(-) diff --git a/apps/nextjs/src/app/[locale]/manage/users/[userId]/general/_components/_disable-user-button.tsx b/apps/nextjs/src/app/[locale]/manage/users/[userId]/general/_components/_disable-user-button.tsx index 21662f08d..72f0a757c 100644 --- a/apps/nextjs/src/app/[locale]/manage/users/[userId]/general/_components/_disable-user-button.tsx +++ b/apps/nextjs/src/app/[locale]/manage/users/[userId]/general/_components/_disable-user-button.tsx @@ -10,9 +10,10 @@ import { useI18n } from "@homarr/translation/client"; interface DisableUserButtonProps { user: RouterOutputs["user"]["getById"]; + isSelf?: boolean; } -export const DisableUserButton = ({ user }: DisableUserButtonProps) => { +export const DisableUserButton = ({ user, isSelf = false }: DisableUserButtonProps) => { const t = useI18n(); const [isPending, startTransition] = useTransition(); const changeDisabledMutation = clientApi.user.changeDisabled.useMutation(); @@ -32,6 +33,8 @@ export const DisableUserButton = ({ user }: DisableUserButtonProps) => { }; const handleToggle = () => { + if (isSelf) return; + startTransition(async () => { try { await changeDisabledMutation.mutateAsync({ @@ -65,12 +68,13 @@ export const DisableUserButton = ({ user }: DisableUserButtonProps) => { const getButtonColor = () => (isDisabled ? "green" : "yellow"); return ( - + diff --git a/apps/nextjs/src/app/[locale]/manage/users/[userId]/general/page.tsx b/apps/nextjs/src/app/[locale]/manage/users/[userId]/general/page.tsx index 620b02a33..5074181ef 100644 --- a/apps/nextjs/src/app/[locale]/manage/users/[userId]/general/page.tsx +++ b/apps/nextjs/src/app/[locale]/manage/users/[userId]/general/page.tsx @@ -110,11 +110,13 @@ export default async function EditUserPage(props: Props) { )} - } - /> + {!isSelf && ( + } + /> + )} { + const dbUser = await ctx.db.query.users.findFirst({ + columns: { + id: true, + }, + where: eq(users.id, input.userId), + }); + + if (!dbUser) { + throw new TRPCError({ + code: "NOT_FOUND", + message: "User not found", + }); + } + await ctx.db .update(users) .set({ diff --git a/packages/auth/callbacks.ts b/packages/auth/callbacks.ts index dd11786c1..51c9c83e5 100644 --- a/packages/auth/callbacks.ts +++ b/packages/auth/callbacks.ts @@ -47,14 +47,9 @@ export const createSessionCallback = (db: Database): NextAuthCallbackOf<"session where: eq(users.id, user.id), columns: { colorScheme: true, - disabled: true, }, }); - if (additionalProperties?.disabled) { - return null; - } - return { ...session, user: {