mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: migrate agents-access to org-scoped system role for proper chat RBAC (#24438)
The agents-access role previously granted chat permissions at user
scope, but chats are org-scoped objects. Rego skips user-level perms
when org_owner is set, making the grants invisible. Handler-level
band-aids used synthetic non-org-scoped objects as a workaround.
- Migrates agents-access from users.rbac_roles (site-level) to
organization_members.roles (org-scoped) via DB migration
- Redefines agents-access as a predefined org-scoped builtin role
alongside organization-admin, organization-auditor, etc., with
Member permissions granting chat create/read/update
- Excludes ResourceChat from OrgMemberPermissions so org membership
alone no longer grants chat access
- Fixes handler Authorize checks to use org-scoped objects with
semantically correct actions (ActionUpdate for message/tool operations)
- Grants org admins the ability to assign agents-access
Closes #24250
Fixes CODAGT-174
Note: this does not update the "Usage" endpoints. Tracked by CODAGT-161.
> 🤖
This commit is contained in:
@@ -1,6 +1,11 @@
|
||||
import type { Meta, StoryObj } from "@storybook/react-vite";
|
||||
import { userEvent, within } from "storybook/test";
|
||||
import {
|
||||
MockAgentsAccessRole,
|
||||
MockOrganizationAdminRole,
|
||||
MockOrganizationAuditorRole,
|
||||
MockOrganizationTemplateAdminRole,
|
||||
MockOrganizationUserAdminRole,
|
||||
MockOwnerRole,
|
||||
MockSiteRoles,
|
||||
MockUserAdminRole,
|
||||
@@ -64,3 +69,20 @@ export const AdvancedOpen: Story = {
|
||||
await userEvent.click(canvas.getByRole("button"));
|
||||
},
|
||||
};
|
||||
|
||||
export const OrgRoles: Story = {
|
||||
args: {
|
||||
selectedRoleNames: new Set([MockAgentsAccessRole.name]),
|
||||
roles: [
|
||||
MockOrganizationAdminRole,
|
||||
MockOrganizationUserAdminRole,
|
||||
MockOrganizationTemplateAdminRole,
|
||||
MockOrganizationAuditorRole,
|
||||
MockAgentsAccessRole,
|
||||
],
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const canvas = within(canvasElement);
|
||||
await userEvent.click(canvas.getByRole("button"));
|
||||
},
|
||||
};
|
||||
|
||||
@@ -29,7 +29,7 @@ const roleDescriptions: Record<string, string> = {
|
||||
"user-admin": "User admin can manage all users and groups.",
|
||||
"template-admin": "Template admin can manage all templates and workspaces.",
|
||||
auditor: "Auditor can access the audit logs.",
|
||||
"agents-access": "Coder Agents User allows creating and using Coder Agents.",
|
||||
"agents-access": "Grants access to Coder Agents chat.",
|
||||
member:
|
||||
"Everybody is a member. This is a shared and default role for all users.",
|
||||
};
|
||||
|
||||
@@ -374,6 +374,16 @@ export const MockOrganizationAuditorRole: TypesGen.AssignableRoles = {
|
||||
organization_member_permissions: [],
|
||||
};
|
||||
|
||||
export const MockAgentsAccessRole: TypesGen.Role = {
|
||||
name: "agents-access",
|
||||
display_name: "Coder Agents User",
|
||||
site_permissions: [],
|
||||
user_permissions: [],
|
||||
organization_id: MockOrganization.id,
|
||||
organization_permissions: [],
|
||||
organization_member_permissions: [],
|
||||
};
|
||||
|
||||
export const MockRoleWithOrgPermissions: TypesGen.AssignableRoles = {
|
||||
name: "my-role-1",
|
||||
display_name: "My Role 1",
|
||||
|
||||
Reference in New Issue
Block a user