diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/users/[userId]/page-client.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/users/[userId]/page-client.tsx
index 4a241ea48..e45f7e871 100644
--- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/users/[userId]/page-client.tsx
+++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/users/[userId]/page-client.tsx
@@ -46,7 +46,7 @@ import { KnownErrors } from "@stackframe/stack-shared";
import { AppId } from "@stackframe/stack-shared/dist/apps/apps-config";
import { normalizeCountryCode } from "@stackframe/stack-shared/dist/schema-fields";
import { fromNow } from "@stackframe/stack-shared/dist/utils/dates";
-import { captureError, StackAssertionError, throwErr } from '@stackframe/stack-shared/dist/utils/errors';
+import { StackAssertionError, throwErr } from '@stackframe/stack-shared/dist/utils/errors';
import { runAsynchronouslyWithAlert } from "@stackframe/stack-shared/dist/utils/promises";
import { deindent } from "@stackframe/stack-shared/dist/utils/strings";
import { Suspense, useCallback, useMemo, useState, type ReactNode } from "react";
@@ -145,7 +145,7 @@ function UserHeader({ user }: UserHeaderProps) {
}] satisfies DesignMenuActionItem[] : [],
{
id: "restriction",
- label: "User restriction",
+ label: getRestrictionActionLabel(user),
onClick: () => { setRestrictionDialogOpen(true); },
},
{
@@ -185,6 +185,26 @@ function getRestrictionReasonText(user: ServerUser): string {
}
}
+function getRestrictionActionLabel(user: ServerUser): string {
+ if (user.restrictedByAdmin) {
+ return "Edit or remove manual restriction";
+ }
+ if (user.isRestricted) {
+ return "Add manual restriction";
+ }
+ return "Restrict user";
+}
+
+function getManualRestrictionStatusText(user: ServerUser): string {
+ if (user.restrictedByAdmin) {
+ return "Restricted by admin";
+ }
+ if (user.isRestricted) {
+ return `Not manually restricted (${getRestrictionReasonText(user)})`;
+ }
+ return "Not restricted";
+}
+
// Restriction dialog for editing restriction details
function RestrictionDialog({
user,
@@ -195,35 +215,31 @@ function RestrictionDialog({
open: boolean,
onOpenChange: (open: boolean) => void,
}) {
- const restrictedByAdmin = (user as any).restrictedByAdmin ?? false;
- const restrictedByAdminReason = (user as any).restrictedByAdminReason ?? null;
- const restrictedByAdminPrivateDetails = (user as any).restrictedByAdminPrivateDetails ?? null;
-
- const [publicReason, setPublicReason] = useState(restrictedByAdminReason ?? '');
- const [privateDetails, setPrivateDetails] = useState(restrictedByAdminPrivateDetails ?? '');
+ const [publicReason, setPublicReason] = useState(user.restrictedByAdminReason ?? '');
+ const [privateDetails, setPrivateDetails] = useState(user.restrictedByAdminPrivateDetails ?? '');
const [isSaving, setIsSaving] = useState(false);
// Reset form when dialog opens
const handleOpenChange = (newOpen: boolean) => {
if (newOpen) {
- setPublicReason(restrictedByAdminReason ?? '');
- setPrivateDetails(restrictedByAdminPrivateDetails ?? '');
+ setPublicReason(user.restrictedByAdminReason ?? '');
+ setPrivateDetails(user.restrictedByAdminPrivateDetails ?? '');
}
onOpenChange(newOpen);
};
const handleSaveAndRestrict = async () => {
- if (!privateDetails.trim()) {
- alert('Please enter the private details for the restriction.');
- return;
- }
+ const trimmedPublicReason = publicReason.trim();
+ const trimmedPrivateDetails = privateDetails.trim();
setIsSaving(true);
try {
- await user.update({ restrictedByAdmin: true, restrictedByAdminReason: publicReason.trim() || null, restrictedByAdminPrivateDetails: privateDetails.trim() || null } as any);
+ await user.update({
+ restrictedByAdmin: true,
+ restrictedByAdminReason: trimmedPublicReason.length > 0 ? trimmedPublicReason : null,
+ restrictedByAdminPrivateDetails: trimmedPrivateDetails.length > 0 ? trimmedPrivateDetails : null,
+ });
onOpenChange(false);
- } catch (error) {
- captureError(`user-restriction-save-and-restrict-error`, new StackAssertionError(`Failed to save and restrict user ${user.id}`, { cause: error }));
} finally {
setIsSaving(false);
}
@@ -236,7 +252,7 @@ function RestrictionDialog({
restrictedByAdmin: false,
restrictedByAdminReason: null,
restrictedByAdminPrivateDetails: null,
- } as any);
+ });
onOpenChange(false);
} finally {
setIsSaving(false);
@@ -249,7 +265,9 @@ function RestrictionDialog({