🌐 US-Proxy
class="logged-out env-production page-responsive" style="word-wrap: break-word;" >
Skip to content

Commit 350070e

Browse files
fix(site): backport admin settings dropdown visibility fix to release/2.34 (#27851)
Backport of #27481 to `release/2.34`. ## Problem `canViewAnyOrganization` included `viewAnyMembers`, a permission every user now has because of workspace sharing. This meant the Admin settings dropdown (and the Organizations entry within it) showed up for every user, not just admins. ## Fix - Removed `permissions.viewAnyMembers` from `canViewAnyOrganization` in `site/src/modules/permissions/index.ts`. - Updated `site/e2e/tests/roles.spec.ts` to match, including a new regression test for org members with no roles. ## Note on scope Upstream #27481 also refactored `DeploymentDropdown`/`MobileMenu` into a shared `AdminSettings.tsx` component driven by a single permissions object. That refactor doesn't apply to `release/2.34`: this branch's `DeploymentDropdown` and `MobileMenu` already gate the Admin settings menu with equivalent per-permission checks, so only the actual permission fix and its test coverage are backported here. ## Validation - `pnpm exec biome check` on the two changed files: clean. - Confirmed pre-existing `tsc` errors in this branch are unrelated environment/dependency issues (reproduced identically on a clean `release/2.34` checkout). > 🤖 This PR was created with the help of Coder Agents, and needs a human review. 🧑💻 --------- Co-authored-by: Jeremy Ruppel <jeremy.ruppel@gmail.com>
1 parent b080be4 commit 350070e

4 files changed

Lines changed: 36 additions & 19 deletions

File tree

site/e2e/tests/roles.spec.ts

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -61,25 +61,21 @@ test.describe("roles admin settings access", () => {
6161
await login(page, users.templateAdmin);
6262
await page.goto("/", { waitUntil: "domcontentloaded" });
6363

64-
await hasAccessToAdminSettings(page, ["Deployment", "Organizations"]);
64+
await hasAccessToAdminSettings(page, ["Deployment"]);
6565
});
6666

6767
test("user admin can see admin settings", async ({ page }) => {
6868
await login(page, users.userAdmin);
6969
await page.goto("/", { waitUntil: "domcontentloaded" });
7070

71-
await hasAccessToAdminSettings(page, ["Deployment", "Organizations"]);
71+
await hasAccessToAdminSettings(page, ["Deployment"]);
7272
});
7373

7474
test("auditor can see admin settings", async ({ page }) => {
7575
await login(page, users.auditor);
7676
await page.goto("/", { waitUntil: "domcontentloaded" });
7777

78-
await hasAccessToAdminSettings(page, [
79-
"Deployment",
80-
"Organizations",
81-
"Audit Logs",
82-
]);
78+
await hasAccessToAdminSettings(page, ["Deployment", "Audit Logs"]);
8379
});
8480

8581
test("owner can see admin settings", async ({ page }) => {
@@ -88,7 +84,6 @@ test.describe("roles admin settings access", () => {
8884

8985
await hasAccessToAdminSettings(page, [
9086
"Deployment",
91-
"Organizations",
9287
"Healthcheck",
9388
"Audit Logs",
9489
]);
@@ -103,6 +98,23 @@ test.describe("org-scoped roles admin settings access", () => {
10398
await setupApiCalls(page);
10499
});
105100

101+
test("member cannot see admin settings", async ({ page }) => {
102+
// The unlicensed member test above cannot catch all regressions here.
103+
// Many admin settings are locked behind a license and wouldn't be shown.
104+
const org = await createOrganization();
105+
const member = await createOrganizationMember({
106+
orgRoles: {
107+
[org.id]: [],
108+
},
109+
});
110+
111+
await login(page, member);
112+
await page.goto("/", { waitUntil: "domcontentloaded" });
113+
114+
// None, "Admin settings" button should not be visible
115+
await hasAccessToAdminSettings(page, []);
116+
});
117+
106118
test("org template admin can see admin settings", async ({ page }) => {
107119
const org = await createOrganization();
108120
const orgTemplateAdmin = await createOrganizationMember({

site/src/modules/dashboard/Navbar/DeploymentDropdown.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ export const DeploymentDropdown: FC<DeploymentDropdownProps> = ({
6767

6868
const DeploymentDropdownContent: FC<DeploymentDropdownProps> = ({
6969
canViewDeployment,
70+
canViewOrganizations,
7071
canViewAuditLog,
7172
canViewConnectionLog,
7273
canViewAIBridge,
@@ -80,9 +81,11 @@ const DeploymentDropdownContent: FC<DeploymentDropdownProps> = ({
8081
<Link to="/deployment">Deployment</Link>
8182
</DropdownMenuItem>
8283
)}
83-
<DropdownMenuItem asChild>
84-
<Link to="/organizations">Organizations</Link>
85-
</DropdownMenuItem>
84+
{canViewOrganizations && (
85+
<DropdownMenuItem asChild>
86+
<Link to="/organizations">Organizations</Link>
87+
</DropdownMenuItem>
88+
)}
8689
{canViewAISettings && (
8790
<DropdownMenuItem asChild>
8891
<Link to="/ai/settings">AI</Link>

site/src/modules/dashboard/Navbar/MobileMenu.tsx

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ const ProxySettingsSub: FC<ProxySettingsSubProps> = ({ proxyContextValue }) => {
208208

209209
const AdminSettingsSub: FC<MobileMenuPermissions> = ({
210210
canViewDeployment,
211+
canViewOrganizations,
211212
canViewAuditLog,
212213
canViewConnectionLog,
213214
canViewHealth,
@@ -239,12 +240,14 @@ const AdminSettingsSub: FC<MobileMenuPermissions> = ({
239240
<Link to="/deployment">Deployment</Link>
240241
</DropdownMenuItem>
241242
)}
242-
<DropdownMenuItem
243-
asChild
244-
className={cn(itemStyles.default, itemStyles.sub)}
245-
>
246-
<Link to="/organizations">Organizations</Link>
247-
</DropdownMenuItem>
243+
{canViewOrganizations && (
244+
<DropdownMenuItem
245+
asChild
246+
className={cn(itemStyles.default, itemStyles.sub)}
247+
>
248+
<Link to="/organizations">Organizations</Link>
249+
</DropdownMenuItem>
250+
)}
248251
{canViewAuditLog && (
249252
<DropdownMenuItem
250253
asChild

site/src/modules/permissions/index.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,7 @@ export const canViewAnyOrganization = (
3939
): permissions is Permissions => {
4040
return (
4141
permissions !== undefined &&
42-
(permissions.viewAnyMembers ||
43-
permissions.editAnyGroups ||
42+
(permissions.editAnyGroups ||
4443
permissions.assignAnyRoles ||
4544
permissions.viewAnyIdpSyncSettings ||
4645
permissions.editAnySettings)

0 commit comments

Comments
 (0)