Overriding is working

This commit is contained in:
Owen
2026-06-01 20:54:37 -07:00
parent 6b3a0a2113
commit 8e0e32c2be
4 changed files with 32 additions and 57 deletions
+2 -1
View File
@@ -872,6 +872,7 @@
"resourcePolicyOtpEmpty": "No one time password", "resourcePolicyOtpEmpty": "No one time password",
"resourcePolicyReadOnly": "This policy is Read only", "resourcePolicyReadOnly": "This policy is Read only",
"resourcePolicyReadOnlyDescription": "This resource policy is shared accross multiple resources, you cannot edit it on this page.", "resourcePolicyReadOnlyDescription": "This resource policy is shared accross multiple resources, you cannot edit it on this page.",
"editSharedPolicy": "Edit Shared Policy",
"resourcePolicyTypeSave": "Save Resource type", "resourcePolicyTypeSave": "Save Resource type",
"resourcePolicySelect": "Select resource policy", "resourcePolicySelect": "Select resource policy",
"resourcePolicySelectError": "Select a resource policy", "resourcePolicySelectError": "Select a resource policy",
@@ -918,7 +919,7 @@
"resourcePolicyInline": "Inline Resource Policy", "resourcePolicyInline": "Inline Resource Policy",
"resourcePolicyInlineDescription": "Access Policy scoped to only this resource", "resourcePolicyInlineDescription": "Access Policy scoped to only this resource",
"resourcePolicyShared": "Shared Resource Policy", "resourcePolicyShared": "Shared Resource Policy",
"resourcePolicySharedDescription": "Access Policy shared accross multiple resources", "resourcePolicySharedDescription": "This resource uses a shared policy. Policy-level settings (auth methods, email whitelist) are locked. You can add resource-specific rules, roles, and users below.",
"resourceUsersRoles": "Access Controls", "resourceUsersRoles": "Access Controls",
"resourceUsersRolesDescription": "Configure which users and roles can visit this resource", "resourceUsersRolesDescription": "Configure which users and roles can visit this resource",
"resourceUsersRolesSubmit": "Save Access Controls", "resourceUsersRolesSubmit": "Save Access Controls",
@@ -315,13 +315,13 @@ export default function ResourceAuthenticationPage() {
key={policies.sharedPolicy.resourcePolicyId} key={policies.sharedPolicy.resourcePolicyId}
> >
<ActionBanner <ActionBanner
variant="warning" variant="info"
title={t("resourcePolicyReadOnly")} title={t("resourcePolicyShared")}
titleIcon={ titleIcon={
<ShieldAlertIcon className="w-5 h-5" /> <ShieldAlertIcon className="w-5 h-5" />
} }
description={t( description={t(
"resourcePolicyReadOnlyDescription" "resourcePolicySharedDescription"
)} )}
actions={ actions={
<Button <Button
@@ -332,14 +332,13 @@ export default function ResourceAuthenticationPage() {
<Link <Link
href={`/${org.org.orgId}/settings/policies/resource/${policies.sharedPolicy.niceId}`} href={`/${org.org.orgId}/settings/policies/resource/${policies.sharedPolicy.niceId}`}
> >
{t("edit")} {t("editSharedPolicy")}
<ArrowRightIcon className="size-4" /> <ArrowRightIcon className="size-4" />
</Link> </Link>
</Button> </Button>
} }
/> />
<EditPolicyForm <EditPolicyForm
readonly
resourceId={resource.resourceId} resourceId={resource.resourceId}
/> />
</ResourcePolicyProvider> </ResourcePolicyProvider>
@@ -44,6 +44,11 @@ export function EditPolicyForm({
const router = useRouter(); const router = useRouter();
// In overlay mode (resourceId provided), policy-level sections are locked.
// Rules and users/roles sections handle their own hybrid logic via resourceId.
const isOverlay = resourceId !== undefined;
const policyLevelReadonly = readonly || isOverlay;
const isMaxmindAvailable = !!( const isMaxmindAvailable = !!(
env.server.maxmind_db_path && env.server.maxmind_db_path.length > 0 env.server.maxmind_db_path && env.server.maxmind_db_path.length > 0
); );
@@ -79,7 +84,7 @@ export function EditPolicyForm({
return ( return (
<SettingsContainer> <SettingsContainer>
{!hidePolicyNameForm && ( {!hidePolicyNameForm && (
<EditPolicyNameSectionForm readonly={readonly} /> <EditPolicyNameSectionForm readonly={policyLevelReadonly} />
)} )}
<EditPolicyUsersRolesSectionForm <EditPolicyUsersRolesSectionForm
@@ -89,11 +94,11 @@ export function EditPolicyForm({
resourceId={resourceId} resourceId={resourceId}
/> />
<EditPolicyAuthMethodsSectionForm readonly={readonly} /> <EditPolicyAuthMethodsSectionForm readonly={policyLevelReadonly} />
<EditPolicyOtpEmailSectionForm <EditPolicyOtpEmailSectionForm
emailEnabled={env.email.emailEnabled} emailEnabled={env.email.emailEnabled}
readonly={readonly} readonly={policyLevelReadonly}
/> />
<EditPolicyRulesSectionForm <EditPolicyRulesSectionForm
@@ -268,59 +268,29 @@ export function EditPolicyUsersRolesSectionForm({
setIsSavingOverlay(true); setIsSavingOverlay(true);
try { try {
// Compute which roles/users are resource-specific (non-locked) // Compute which roles/users are resource-specific (non-locked)
const currentResourceRoleIds = new Set( const currentResourceRoleIds = combinedRoles
combinedRoles .filter((r) => !policyRoleLockedIds.has(r.id))
.filter((r) => !policyRoleLockedIds.has(r.id)) .map((r) => Number(r.id));
.map((r) => r.id) const currentResourceUserIds = combinedUsers
); .filter((u) => !policyUserLockedIds.has(u.id))
const currentResourceUserIds = new Set( .map((u) => u.id);
combinedUsers
.filter((u) => !policyUserLockedIds.has(u.id))
.map((u) => u.id)
);
const initialRoleIds = initialResourceRoleIdsRef.current;
const initialUserIds = initialResourceUserIdsRef.current;
const addedRoleIds = [...currentResourceRoleIds].filter(
(id) => !initialRoleIds.has(id)
);
const removedRoleIds = [...initialRoleIds].filter(
(id) => !currentResourceRoleIds.has(id)
);
const addedUserIds = [...currentResourceUserIds].filter(
(id) => !initialUserIds.has(id)
);
const removedUserIds = [...initialUserIds].filter(
(id) => !currentResourceUserIds.has(id)
);
// Use bulk-set endpoints (session-authenticated) which replace
// all resource-specific roles/users in one call
await Promise.all([ await Promise.all([
...addedRoleIds.map((id) => api.post(`/resource/${resourceId}/roles`, {
api.post(`/resource/${resourceId}/roles/add`, { roleIds: currentResourceRoleIds
roleId: Number(id) }),
}) api.post(`/resource/${resourceId}/users`, {
), userIds: currentResourceUserIds
...removedRoleIds.map((id) => })
api.post(`/resource/${resourceId}/roles/remove`, {
roleId: Number(id)
})
),
...addedUserIds.map((id) =>
api.post(`/resource/${resourceId}/users/add`, {
userId: id
})
),
...removedUserIds.map((id) =>
api.post(`/resource/${resourceId}/users/remove`, {
userId: id
})
)
]); ]);
// Update refs to reflect new state // Update refs to reflect new state
initialResourceRoleIdsRef.current = currentResourceRoleIds; initialResourceRoleIdsRef.current = new Set(
initialResourceUserIdsRef.current = currentResourceUserIds; currentResourceRoleIds.map(String)
);
initialResourceUserIdsRef.current = new Set(currentResourceUserIds);
toast({ toast({
title: t("success"), title: t("success"),