Add a deny option for the proxy default role (#24145)

* backend

* frontend

* docs

* fix none default role casing and name reserved roles in the error

* reserve every casing of none as a role name
This commit is contained in:
Josh Hawkins
2026-09-12 07:30:04 -06:00
committed by Nicolas Mowen
parent 41bc1a5844
commit e2da7aae99
9 changed files with 194 additions and 18 deletions
+1 -1
View File
@@ -212,7 +212,7 @@
},
"default_role": {
"label": "Default role",
"description": "Default role assigned to proxy-authenticated users when no role mapping applies."
"description": "Default role assigned to proxy-authenticated users when no role mapping applies. Set to 'none' to deny access to unmapped users."
},
"separator": {
"label": "Separator character",
+2 -1
View File
@@ -1738,7 +1738,8 @@
},
"defaultRole": {
"admin": "Admin",
"viewer": "Viewer"
"viewer": "Viewer",
"none": "None (deny access)"
}
},
"globalConfig": {
@@ -12,6 +12,7 @@ import type { ConfigFormContext } from "@/types/configForm";
import { getSizedFieldClassName } from "../utils";
const BUILT_IN_ROLES = ["admin", "viewer"];
const NONE_ROLE = "none";
export function DefaultRoleWidget(props: WidgetProps) {
const { id, value, disabled, readonly, onChange, schema, options, registry } =
@@ -25,13 +26,15 @@ export function DefaultRoleWidget(props: WidgetProps) {
const configured = Object.keys(formContext?.fullConfig?.auth?.roles ?? {});
// Keep admin/viewer first, then any custom roles in config order.
const custom = configured.filter((r) => !BUILT_IN_ROLES.includes(r));
return [...BUILT_IN_ROLES, ...custom];
return [...BUILT_IN_ROLES, ...custom, NONE_ROLE];
}, [formContext]);
const selectedValue = typeof value === "string" && value ? value : "viewer";
const getLabel = (role: string) =>
BUILT_IN_ROLES.includes(role) ? t(`configForm.defaultRole.${role}`) : role;
BUILT_IN_ROLES.includes(role) || role === NONE_ROLE
? t(`configForm.defaultRole.${role}`)
: role;
return (
<Select