diff --git a/workspaces/intelligent-assistant/.changeset/clear-owls-dance.md b/workspaces/intelligent-assistant/.changeset/clear-owls-dance.md new file mode 100644 index 00000000000..81bd9bea668 --- /dev/null +++ b/workspaces/intelligent-assistant/.changeset/clear-owls-dance.md @@ -0,0 +1,7 @@ +--- +'@red-hat-developer-hub/backstage-plugin-intelligent-assistant-common': major +'@red-hat-developer-hub/backstage-plugin-intelligent-assistant-backend': major +'@red-hat-developer-hub/backstage-plugin-intelligent-assistant': major +--- + +Consolidate Intelligent Assistant RBAC permissions into four feature-linked sets: `intelligent-assistant.chat`, `intelligent-assistant.notebooks`, `intelligent-assistant.mcp.tools`, and `intelligent-assistant.skills`. Update backend routes, frontend permission checks, example RBAC policies, and documentation to use the new permission names and exported constants. diff --git a/workspaces/intelligent-assistant/plugins/intelligent-assistant-backend/README.md b/workspaces/intelligent-assistant/plugins/intelligent-assistant-backend/README.md index 66e11e6199d..8e8d38f232d 100644 --- a/workspaces/intelligent-assistant/plugins/intelligent-assistant-backend/README.md +++ b/workspaces/intelligent-assistant/plugins/intelligent-assistant-backend/README.md @@ -81,16 +81,15 @@ All nested keys (`servicePort`, `systemPrompt`, `prompts`, `mcpServers`, `notebo Update permission names in your `rbac-policy.csv`: -| Before | After | -| -------------------------- | ---------------------------------------- | -| `lightspeed.chat.read` | `intelligent-assistant.chat.access` | -| `lightspeed.chat.create` | `intelligent-assistant.chat.use` | -| `lightspeed.chat.delete` | `intelligent-assistant.chat.manage` | -| `lightspeed.chat.update` | `intelligent-assistant.chat.manage` | -| `lightspeed.notebooks.use` | `intelligent-assistant.notebooks.use` | -| | `intelligent-assistant.notebooks.manage` | -| `lightspeed.mcp.read` | `mcp.tools.use` | -| `lightspeed.mcp.manage` | `mcp.tools.manage` | +| Before | After | +| -------------------------- | --------------------------------- | +| `lightspeed.chat.read` | `intelligent-assistant.chat` | +| `lightspeed.chat.create` | `intelligent-assistant.chat` | +| `lightspeed.chat.delete` | `intelligent-assistant.chat` | +| `lightspeed.chat.update` | `intelligent-assistant.chat` | +| `lightspeed.notebooks.use` | `intelligent-assistant.notebooks` | +| `lightspeed.mcp.read` | `intelligent-assistant.mcp.tools` | +| `lightspeed.mcp.manage` | `intelligent-assistant.mcp.tools` | #### 5. OFS dynamic plugin configuration @@ -333,17 +332,16 @@ The Intelligent Assistant Backend plugin has support for the permission framewor - When [RBAC permission](https://github.com/backstage/community-plugins/tree/main/workspaces/rbac/plugins/rbac-backend#installation) framework is enabled, for non-admin users to access intelligent-assistant backend API, the role associated with your user should have the following permission policies associated with it. Add the following in your permission policies configuration file named `rbac-policy.csv`: ```CSV -p, role:default/team_a, intelligent-assistant.chat.access, use, allow -p, role:default/team_a, intelligent-assistant.chat.use, use, allow -p, role:default/team_a, intelligent-assistant.chat.manage, use, allow +p, role:default/team_a, intelligent-assistant.chat, use, allow # Required for Notebooks feature (if enabled) -p, role:default/team_a, intelligent-assistant.notebooks.use, use, allow -p, role:default/team_a, intelligent-assistant.notebooks.manage, use, allow +p, role:default/team_a, intelligent-assistant.notebooks, use, allow # Required for MCP server management (if configured) -p, role:default/team_a, mcp.tools.use, use, allow -p, role:default/team_a, mcp.tools.manage, use, allow +p, role:default/team_a, intelligent-assistant.mcp.tools, use, allow + +# Required for Skills feature (if enabled) +p, role:default/team_a, intelligent-assistant.skills, use, allow g, user:default/, role:default/team_a @@ -456,9 +454,7 @@ When enabled, Notebooks exposes the following REST API endpoints: **Notes**: - All endpoints require authentication (user context is automatically provided by Backstage) -- All `/v1/*` endpoints require notebooks permissions: - - `intelligent-assistant.notebooks.use` for list/read/create session, upload document, and query endpoints - - `intelligent-assistant.notebooks.manage` for update/delete session and document endpoints +- All `/v1/*` endpoints require the `intelligent-assistant.notebooks` permission - Document endpoints verify session ownership before allowing operations - `documentId` in paths is the document title (URL-encoded for special characters) @@ -467,8 +463,7 @@ When enabled, Notebooks exposes the following REST API endpoints: When RBAC is enabled, users need the following permissions to use Notebooks: ```CSV -p, role:default/team_a, intelligent-assistant.notebooks.use, use, allow -p, role:default/team_a, intelligent-assistant.notebooks.manage, use, allow +p, role:default/team_a, intelligent-assistant.notebooks, use, allow g, user:default/, role:default/team_a ``` diff --git a/workspaces/intelligent-assistant/plugins/intelligent-assistant-backend/src/service/notebooks/notebooksRouters.ts b/workspaces/intelligent-assistant/plugins/intelligent-assistant-backend/src/service/notebooks/notebooksRouters.ts index fa1fff82276..f42f8003784 100644 --- a/workspaces/intelligent-assistant/plugins/intelligent-assistant-backend/src/service/notebooks/notebooksRouters.ts +++ b/workspaces/intelligent-assistant/plugins/intelligent-assistant-backend/src/service/notebooks/notebooksRouters.ts @@ -25,10 +25,7 @@ import type { BasicPermission } from '@backstage/plugin-permission-common'; import express, { Router } from 'express'; -import { - iaNotebooksManagePermission, - iaNotebooksUsePermission, -} from '@red-hat-developer-hub/backstage-plugin-intelligent-assistant-common'; +import { iaNotebooksPermission } from '@red-hat-developer-hub/backstage-plugin-intelligent-assistant-common'; import { Readable, Transform } from 'stream'; @@ -280,7 +277,7 @@ export async function createNotebooksRouter( notebooksRouter.post( '/v1/sessions', generalRateLimiter, - requirePermission(iaNotebooksUsePermission), + requirePermission(iaNotebooksPermission), withAuth(async (req, res, userId) => { const { name, description, metadata } = req.body; if (!name) { @@ -300,7 +297,7 @@ export async function createNotebooksRouter( notebooksRouter.get( '/v1/sessions', generalRateLimiter, - requirePermission(iaNotebooksUsePermission), + requirePermission(iaNotebooksPermission), withAuth(async (_req, res, userId) => { const sessions = await sessionService.listSessions(userId); res.json(createSessionListResponse(sessions)); @@ -310,7 +307,7 @@ export async function createNotebooksRouter( notebooksRouter.get( '/v1/sessions/:sessionId', generalRateLimiter, - requirePermission(iaNotebooksUsePermission), + requirePermission(iaNotebooksPermission), withAuth(async (req, res, userId) => { const { sessionId } = req.params; const session = await sessionService.readSession(sessionId, userId); @@ -323,7 +320,7 @@ export async function createNotebooksRouter( notebooksRouter.put( '/v1/sessions/:sessionId', generalRateLimiter, - requirePermission(iaNotebooksManagePermission), + requirePermission(iaNotebooksPermission), withAuth(async (req, res, userId) => { const { sessionId } = req.params; const { name, description, metadata } = req.body; @@ -341,7 +338,7 @@ export async function createNotebooksRouter( notebooksRouter.delete( '/v1/sessions/:sessionId', generalRateLimiter, - requirePermission(iaNotebooksManagePermission), + requirePermission(iaNotebooksPermission), withAuth(async (req, res, userId) => { const { sessionId } = req.params; await sessionService.deleteSession(sessionId, userId); @@ -357,7 +354,7 @@ export async function createNotebooksRouter( notebooksRouter.get( '/v1/sessions/:sessionId/documents', generalRateLimiter, - requirePermission(iaNotebooksUsePermission), + requirePermission(iaNotebooksPermission), requireSessionOwnership(), withAuth(async (req, res) => { const { sessionId } = req.params; @@ -373,7 +370,7 @@ export async function createNotebooksRouter( notebooksRouter.put( '/v1/sessions/:sessionId/documents', expensiveRateLimiter, - requirePermission(iaNotebooksUsePermission), + requirePermission(iaNotebooksPermission), upload.single('file') as any, withAuth(async (req, res, userId) => { const { sessionId } = req.params; @@ -432,7 +429,7 @@ export async function createNotebooksRouter( notebooksRouter.get( '/v1/sessions/:sessionId/documents/:documentId/status', generalRateLimiter, - requirePermission(iaNotebooksUsePermission), + requirePermission(iaNotebooksPermission), requireSessionOwnership(), withAuth(async (req, res) => { const { sessionId, documentId } = req.params; @@ -452,7 +449,7 @@ export async function createNotebooksRouter( notebooksRouter.patch( '/v1/sessions/:sessionId/documents/:documentId', generalRateLimiter, - requirePermission(iaNotebooksManagePermission), + requirePermission(iaNotebooksPermission), requireSessionOwnership(), withAuth(async (req, res) => { const { sessionId, documentId } = req.params; @@ -489,7 +486,7 @@ export async function createNotebooksRouter( notebooksRouter.delete( '/v1/sessions/:sessionId/documents/:documentId', generalRateLimiter, - requirePermission(iaNotebooksManagePermission), + requirePermission(iaNotebooksPermission), requireSessionOwnership(), withAuth(async (req, res) => { const { sessionId, documentId } = req.params; @@ -515,7 +512,7 @@ export async function createNotebooksRouter( notebooksRouter.post( '/v1/sessions/:sessionId/query', expensiveRateLimiter, - requirePermission(iaNotebooksUsePermission), + requirePermission(iaNotebooksPermission), express.json({ limit: EXPRESS_JSON_BODY_LIMIT }), withAuth(async (req, res, userId) => { const { sessionId } = req.params; diff --git a/workspaces/intelligent-assistant/plugins/intelligent-assistant-backend/src/service/router.ts b/workspaces/intelligent-assistant/plugins/intelligent-assistant-backend/src/service/router.ts index f593186aeb9..a404b15e3d7 100644 --- a/workspaces/intelligent-assistant/plugins/intelligent-assistant-backend/src/service/router.ts +++ b/workspaces/intelligent-assistant/plugins/intelligent-assistant-backend/src/service/router.ts @@ -28,14 +28,11 @@ import express, { Router } from 'express'; import { createProxyMiddleware } from 'http-proxy-middleware'; import { - iaChatAccessPermission, - iaChatManagePermission, - iaChatUsePermission, - iaMcpManagePermission, - iaMcpUsePermission, - iaNotebooksUsePermission, + iaChatPermission, + iaMcpToolsPermission, + iaNotebooksPermission, iaPermissions, - iaSkillsAccessPermission, + iaSkillsPermission, } from '@red-hat-developer-hub/backstage-plugin-intelligent-assistant-common'; import { Readable } from 'node:stream'; @@ -318,7 +315,7 @@ export async function createRouter( router.get( '/mcp-servers', generalRateLimiter, - requirePermission(iaMcpUsePermission), + requirePermission(iaMcpToolsPermission), async (req, res) => { try { const { userEntityRef } = getIdentity(req); @@ -359,7 +356,7 @@ export async function createRouter( router.post( '/mcp-servers/validate', generalRateLimiter, - requirePermission(iaMcpUsePermission), + requirePermission(iaMcpToolsPermission), async (req, res) => { try { const { url, token } = req.body; @@ -394,7 +391,7 @@ export async function createRouter( router.post( '/mcp-servers/:name/validate', generalRateLimiter, - requirePermission(iaMcpManagePermission), + requirePermission(iaMcpToolsPermission), async (req, res) => { try { const { userEntityRef, credentials } = getIdentity(req); @@ -479,7 +476,7 @@ export async function createRouter( router.patch( '/mcp-servers/:name', generalRateLimiter, - requirePermission(iaMcpManagePermission), + requirePermission(iaMcpToolsPermission), async (req, res) => { try { const { userEntityRef } = getIdentity(req); @@ -566,7 +563,7 @@ export async function createRouter( router.get( '/notebook-conversation-ids', generalRateLimiter, - requirePermission(iaNotebooksUsePermission), + requirePermission(iaNotebooksPermission), async (req, res) => { try { const { userEntityRef } = getIdentity(req); @@ -608,70 +605,70 @@ export async function createRouter( router.get( '/v1/models', generalRateLimiter, - requirePermission(iaChatAccessPermission), + requirePermission(iaChatPermission), apiProxy, ); router.get( '/v1/shields', generalRateLimiter, - requirePermission(iaChatAccessPermission), + requirePermission(iaChatPermission), apiProxy, ); router.get( '/v2/conversations', generalRateLimiter, - requirePermission(iaChatAccessPermission), + requirePermission(iaChatPermission), apiProxy, ); router.get( '/v2/conversations/:conversation_id', generalRateLimiter, - requirePermission(iaChatAccessPermission), + requirePermission(iaChatPermission), apiProxy, ); router.delete( '/v2/conversations/:conversation_id', generalRateLimiter, - requirePermission(iaChatManagePermission), + requirePermission(iaChatPermission), apiProxy, ); router.get( '/v1/feedback/status', generalRateLimiter, - requirePermission(iaChatAccessPermission), + requirePermission(iaChatPermission), apiProxy, ); router.get( '/v1/saved-prompts/config', generalRateLimiter, - requirePermission(iaChatUsePermission), + requirePermission(iaChatPermission), apiProxy, // SKIP_USER_ID_ENDPOINTS prevents user_id injection for this endpoint ); router.get( '/v1/saved-prompts', generalRateLimiter, - requirePermission(iaChatUsePermission), + requirePermission(iaChatPermission), apiProxy, ); router.delete( '/v1/saved-prompts/:prompt_id', generalRateLimiter, - requirePermission(iaChatUsePermission), + requirePermission(iaChatPermission), apiProxy, ); router.get( '/v1/skills', generalRateLimiter, - requirePermission(iaSkillsAccessPermission), + requirePermission(iaSkillsPermission), apiProxy, ); router.post( '/v1/feedback', generalRateLimiter, - requirePermission(iaChatUsePermission), + requirePermission(iaChatPermission), async (request, response) => { try { const { userEntityRef } = getIdentity(request); @@ -714,7 +711,7 @@ export async function createRouter( router.post( '/v1/saved-prompts', generalRateLimiter, - requirePermission(iaChatUsePermission), + requirePermission(iaChatPermission), async (request, response) => { try { const { userEntityRef } = getIdentity(request); @@ -759,7 +756,7 @@ export async function createRouter( router.post( '/v1/query/interrupt', generalRateLimiter, - requirePermission(iaChatUsePermission), + requirePermission(iaChatPermission), async (request, response) => { try { const { userEntityRef } = getIdentity(request); @@ -799,7 +796,7 @@ export async function createRouter( expensiveRateLimiter, validateCompletionsRequest, validateAttachmentsForModel, - requirePermission(iaChatUsePermission), + requirePermission(iaChatPermission), async (request, response) => { const { provider }: Pick = request.body; try { @@ -892,7 +889,7 @@ export async function createRouter( router.put( '/v2/conversations/:conversation_id', generalRateLimiter, - requirePermission(iaChatManagePermission), + requirePermission(iaChatPermission), async (request, response) => { try { const { userEntityRef } = getIdentity(request); @@ -933,7 +930,7 @@ export async function createRouter( router.post( '/v1/validate-model-vision', generalRateLimiter, - requirePermission(iaChatUsePermission), + requirePermission(iaChatPermission), async (request, response) => { const { model, provider } = request.body; diff --git a/workspaces/intelligent-assistant/plugins/intelligent-assistant-common/report.api.md b/workspaces/intelligent-assistant/plugins/intelligent-assistant-common/report.api.md index cbd035a534b..448c166e9e6 100644 --- a/workspaces/intelligent-assistant/plugins/intelligent-assistant-common/report.api.md +++ b/workspaces/intelligent-assistant/plugins/intelligent-assistant-common/report.api.md @@ -6,31 +6,19 @@ import { BasicPermission } from '@backstage/plugin-permission-common'; // @public -export const iaChatAccessPermission: BasicPermission; +export const iaChatPermission: BasicPermission; // @public -export const iaChatManagePermission: BasicPermission; +export const iaMcpToolsPermission: BasicPermission; // @public -export const iaChatUsePermission: BasicPermission; - -// @public -export const iaMcpManagePermission: BasicPermission; - -// @public -export const iaMcpUsePermission: BasicPermission; - -// @public -export const iaNotebooksManagePermission: BasicPermission; - -// @public -export const iaNotebooksUsePermission: BasicPermission; +export const iaNotebooksPermission: BasicPermission; // @public export const iaPermissions: BasicPermission[]; // @public -export const iaSkillsAccessPermission: BasicPermission; +export const iaSkillsPermission: BasicPermission; // @public export interface SavedPrompt { diff --git a/workspaces/intelligent-assistant/plugins/intelligent-assistant-common/src/permissions.ts b/workspaces/intelligent-assistant/plugins/intelligent-assistant-common/src/permissions.ts index a935d372964..9fb83d4bcfc 100644 --- a/workspaces/intelligent-assistant/plugins/intelligent-assistant-common/src/permissions.ts +++ b/workspaces/intelligent-assistant/plugins/intelligent-assistant-common/src/permissions.ts @@ -16,67 +16,35 @@ import { createPermission } from '@backstage/plugin-permission-common'; -/** This permission is used to access intelligent-assistant chats +/** Full permissions to use the intelligent-assistant chat feature * @public */ -export const iaChatAccessPermission = createPermission({ - name: 'intelligent-assistant.chat.access', +export const iaChatPermission = createPermission({ + name: 'intelligent-assistant.chat', attributes: {}, }); -/** This permission is used to create intelligent-assistant chats +/** Full permissions to use the intelligent-assistant notebooks feature * @public */ -export const iaChatUsePermission = createPermission({ - name: 'intelligent-assistant.chat.use', +export const iaNotebooksPermission = createPermission({ + name: 'intelligent-assistant.notebooks', attributes: {}, }); -/** This permission is used to update and delete intelligent-assistant chats +/** Full permissions to use the intelligent-assistant MCP actions tooling * @public */ -export const iaChatManagePermission = createPermission({ - name: 'intelligent-assistant.chat.manage', +export const iaMcpToolsPermission = createPermission({ + name: 'intelligent-assistant.mcp.tools', attributes: {}, }); -/** This permission is used to use MCP tooling +/** Full permissions to use the intelligent-assistant skills feature * @public */ -export const iaMcpUsePermission = createPermission({ - name: 'mcp.tools.use', - attributes: {}, -}); - -/** This permission is used to manage MCP tooling - * @public - */ -export const iaMcpManagePermission = createPermission({ - name: 'mcp.tools.manage', - attributes: {}, -}); - -/** This permission is used to access, create, and query intelligent-assistant notebooks - * @public - */ -export const iaNotebooksUsePermission = createPermission({ - name: 'intelligent-assistant.notebooks.use', - attributes: {}, -}); - -/** This permission is used to update and delete intelligent-assistant notebooks - * @public - */ -export const iaNotebooksManagePermission = createPermission({ - name: 'intelligent-assistant.notebooks.manage', - attributes: {}, -}); - -/** This permission is used to view the list of configured skills - * @public - */ -export const iaSkillsAccessPermission = createPermission({ - name: 'intelligent-assistant.skills.access', +export const iaSkillsPermission = createPermission({ + name: 'intelligent-assistant.skills', attributes: {}, }); @@ -86,12 +54,8 @@ export const iaSkillsAccessPermission = createPermission({ * @public */ export const iaPermissions = [ - iaChatAccessPermission, - iaChatManagePermission, - iaChatUsePermission, - iaMcpUsePermission, - iaMcpManagePermission, - iaNotebooksManagePermission, - iaNotebooksUsePermission, - iaSkillsAccessPermission, + iaChatPermission, + iaNotebooksPermission, + iaMcpToolsPermission, + iaSkillsPermission, ]; diff --git a/workspaces/intelligent-assistant/plugins/intelligent-assistant/README.md b/workspaces/intelligent-assistant/plugins/intelligent-assistant/README.md index c272a8105a2..b4dc5678d16 100644 --- a/workspaces/intelligent-assistant/plugins/intelligent-assistant/README.md +++ b/workspaces/intelligent-assistant/plugins/intelligent-assistant/README.md @@ -37,17 +37,16 @@ The Lightspeed plugin has support for the permission framework. - When [RBAC permission](https://github.com/backstage/community-plugins/tree/main/workspaces/rbac/plugins/rbac-backend#installation) framework is enabled, for non-admin users to access lightspeed UI, the role associated with your user should have the following permission policies associated with it. Add the following in your permission policies configuration file named `rbac-policy.csv`: ```CSV -p, role:default/team_a, intelligent-assistant.chat.access, use, allow -p, role:default/team_a, intelligent-assistant.chat.use, use, allow -p, role:default/team_a, intelligent-assistant.chat.manage, use, allow +p, role:default/team_a, intelligent-assistant.chat, use, allow # Required for Notebooks feature (if enabled) -p, role:default/team_a, intelligent-assistant.notebooks.use, use, allow -p, role:default/team_a, intelligent-assistant.notebooks.manage, use, allow +p, role:default/team_a, intelligent-assistant.notebooks, use, allow # Required for MCP server management (if configured) -p, role:default/team_a, mcp.tools.use, use, allow -p, role:default/team_a, mcp.tools.manage, use, allow +p, role:default/team_a, intelligent-assistant.mcp.tools, use, allow + +# Required for Skills feature (if enabled) +p, role:default/team_a, intelligent-assistant.skills, use, allow g, user:default/, role:default/team_a diff --git a/workspaces/intelligent-assistant/plugins/intelligent-assistant/src/components/LightSpeedChat.tsx b/workspaces/intelligent-assistant/plugins/intelligent-assistant/src/components/LightSpeedChat.tsx index 8df82e14905..b08378cfe86 100644 --- a/workspaces/intelligent-assistant/plugins/intelligent-assistant/src/components/LightSpeedChat.tsx +++ b/workspaces/intelligent-assistant/plugins/intelligent-assistant/src/components/LightSpeedChat.tsx @@ -738,7 +738,7 @@ export const LightspeedChat = ({ const { allowed: hasNotebooksAccess, loading: notebooksPermissionLoading, - iaNotebooksUsePermissionName, + iaNotebooksPermissionName, } = useLightspeedNotebooksPermission(); const notebooksPermissionResolved = !notebooksPermissionLoading && hasNotebooksAccess; @@ -2388,7 +2388,7 @@ export const LightspeedChat = ({ !hasNotebooksAccess && ( { const { allowed: hasViewAccess, loading, - iaChatAccessPermissionName, - iaChatUsePermissionName, + iaChatPermissionName, } = useLightspeedViewPermission(); const { value: profile, loading: profileLoading } = useAsync( @@ -172,7 +171,7 @@ const LightspeedChatContainerInner = () => { return ( ([]); const [sortColumn, setSortColumn] = useState('name'); const [sortAsc, setSortAsc] = useState(true); @@ -556,7 +556,7 @@ export const McpServersSettings = ({ className={classes.alert} /> )} - {!mcpManagePermission.loading && !canManageMcp && ( + {!mcpToolsPermission.loading && !canManageMcp && ( { describe('notebooks permission denied', () => { beforeEach(() => { mockUsePermission.mockImplementation((args: any) => { - if (args.permission.name === 'intelligent-assistant.notebooks.use') { + if (args.permission.name === 'intelligent-assistant.notebooks') { return { loading: false, allowed: false }; } return { loading: false, allowed: true }; diff --git a/workspaces/intelligent-assistant/plugins/intelligent-assistant/src/components/__tests__/Trans.test.tsx b/workspaces/intelligent-assistant/plugins/intelligent-assistant/src/components/__tests__/Trans.test.tsx index 9b31a6191ce..af105b7d003 100644 --- a/workspaces/intelligent-assistant/plugins/intelligent-assistant/src/components/__tests__/Trans.test.tsx +++ b/workspaces/intelligent-assistant/plugins/intelligent-assistant/src/components/__tests__/Trans.test.tsx @@ -18,8 +18,7 @@ import { render, screen } from '@testing-library/react'; import { Trans } from '../Trans'; -const iaAccessPermissionName = 'intelligent-assistant.chat.access'; -const iaUsePermissionName = 'intelligent-assistant.chat.use'; +const iaChatPermissionName = 'intelligent-assistant.chat'; // Mock the useTranslation hook jest.mock('../../hooks/useTranslation', () => ({ @@ -137,12 +136,9 @@ describe('Trans Component', () => { it('should handle permission description formatting', () => { render( ${iaAccessPermissionName} and ${iaUsePermissionName} permissions.`} + message={`To view intelligent assistant plugin, contact your administrator to give the ${iaChatPermissionName} permission.`} components={{ - [`${iaAccessPermissionName}`]: ( - {iaAccessPermissionName} - ), - [`${iaUsePermissionName}`]: {iaUsePermissionName}, + [`${iaChatPermissionName}`]: {iaChatPermissionName}, }} />, ); @@ -151,12 +147,10 @@ describe('Trans Component', () => { expect( screen.getByText(/To view intelligent assistant plugin/), ).toBeInTheDocument(); - expect(screen.getByText(iaAccessPermissionName)).toBeInTheDocument(); - expect(screen.getByText(iaUsePermissionName)).toBeInTheDocument(); + expect(screen.getByText(iaChatPermissionName)).toBeInTheDocument(); - // Check that permission names are bold - expect(screen.getByText(iaAccessPermissionName).tagName).toBe('B'); - expect(screen.getByText(iaUsePermissionName).tagName).toBe('B'); + // Check that permission name is bold + expect(screen.getByText(iaChatPermissionName).tagName).toBe('B'); }); }); diff --git a/workspaces/intelligent-assistant/plugins/intelligent-assistant/src/hooks/notebooks/useLightspeedNotebooksPermission.ts b/workspaces/intelligent-assistant/plugins/intelligent-assistant/src/hooks/notebooks/useLightspeedNotebooksPermission.ts index f3bcf307672..decc0666373 100644 --- a/workspaces/intelligent-assistant/plugins/intelligent-assistant/src/hooks/notebooks/useLightspeedNotebooksPermission.ts +++ b/workspaces/intelligent-assistant/plugins/intelligent-assistant/src/hooks/notebooks/useLightspeedNotebooksPermission.ts @@ -16,16 +16,16 @@ import { usePermission } from '@backstage/plugin-permission-react'; -import { iaNotebooksUsePermission } from '@red-hat-developer-hub/backstage-plugin-intelligent-assistant-common'; +import { iaNotebooksPermission } from '@red-hat-developer-hub/backstage-plugin-intelligent-assistant-common'; export const useLightspeedNotebooksPermission = () => { const result = usePermission({ - permission: iaNotebooksUsePermission, + permission: iaNotebooksPermission, }); return { loading: result.loading, allowed: result.allowed, - iaNotebooksUsePermissionName: iaNotebooksUsePermission.name, + iaNotebooksPermissionName: iaNotebooksPermission.name, }; }; diff --git a/workspaces/intelligent-assistant/plugins/intelligent-assistant/src/hooks/useLightspeedDeletePermission.ts b/workspaces/intelligent-assistant/plugins/intelligent-assistant/src/hooks/useLightspeedDeletePermission.ts index db3fe9a6a2a..d9504639706 100644 --- a/workspaces/intelligent-assistant/plugins/intelligent-assistant/src/hooks/useLightspeedDeletePermission.ts +++ b/workspaces/intelligent-assistant/plugins/intelligent-assistant/src/hooks/useLightspeedDeletePermission.ts @@ -16,11 +16,11 @@ import { usePermission } from '@backstage/plugin-permission-react'; -import { iaChatManagePermission } from '@red-hat-developer-hub/backstage-plugin-intelligent-assistant-common'; +import { iaChatPermission } from '@red-hat-developer-hub/backstage-plugin-intelligent-assistant-common'; export const useLightspeedDeletePermission = () => { const lightspeedDeletePermissionResult = usePermission({ - permission: iaChatManagePermission, + permission: iaChatPermission, }); return lightspeedDeletePermissionResult; diff --git a/workspaces/intelligent-assistant/plugins/intelligent-assistant/src/hooks/useLightspeedUpdatePermission.ts b/workspaces/intelligent-assistant/plugins/intelligent-assistant/src/hooks/useLightspeedUpdatePermission.ts index e2ad77fd0e8..a8c7b71c571 100644 --- a/workspaces/intelligent-assistant/plugins/intelligent-assistant/src/hooks/useLightspeedUpdatePermission.ts +++ b/workspaces/intelligent-assistant/plugins/intelligent-assistant/src/hooks/useLightspeedUpdatePermission.ts @@ -16,11 +16,11 @@ import { usePermission } from '@backstage/plugin-permission-react'; -import { iaChatManagePermission } from '@red-hat-developer-hub/backstage-plugin-intelligent-assistant-common'; +import { iaChatPermission } from '@red-hat-developer-hub/backstage-plugin-intelligent-assistant-common'; export const useLightspeedUpdatePermission = () => { const lightspeedUpdatePermissionResult = usePermission({ - permission: iaChatManagePermission, + permission: iaChatPermission, }); return lightspeedUpdatePermissionResult; diff --git a/workspaces/intelligent-assistant/plugins/intelligent-assistant/src/hooks/useLightspeedViewPermission.ts b/workspaces/intelligent-assistant/plugins/intelligent-assistant/src/hooks/useLightspeedViewPermission.ts index c3cbd1c7155..f310c843df6 100644 --- a/workspaces/intelligent-assistant/plugins/intelligent-assistant/src/hooks/useLightspeedViewPermission.ts +++ b/workspaces/intelligent-assistant/plugins/intelligent-assistant/src/hooks/useLightspeedViewPermission.ts @@ -16,24 +16,20 @@ import { usePermission } from '@backstage/plugin-permission-react'; -import { - iaChatAccessPermission, - iaChatUsePermission, -} from '@red-hat-developer-hub/backstage-plugin-intelligent-assistant-common'; +import { iaChatPermission } from '@red-hat-developer-hub/backstage-plugin-intelligent-assistant-common'; -export const useLightspeedViewPermission = () => { - const canReadChats = usePermission({ - permission: iaChatAccessPermission, - }); - - const canCreateChats = usePermission({ - permission: iaChatUsePermission, +export const useLightspeedViewPermission = (): { + loading: boolean; + allowed: boolean; + iaChatPermissionName: string; +} => { + const canUseChats = usePermission({ + permission: iaChatPermission, }); return { - loading: canReadChats.loading || canCreateChats.loading, - allowed: canReadChats.allowed && canCreateChats.allowed, - iaChatAccessPermissionName: iaChatAccessPermission.name, - iaChatUsePermissionName: iaChatUsePermission.name, + loading: canUseChats.loading, + allowed: canUseChats.allowed, + iaChatPermissionName: iaChatPermission.name, }; }; diff --git a/workspaces/intelligent-assistant/rbac-policy.csv b/workspaces/intelligent-assistant/rbac-policy.csv index a34fbf3b794..be97ee90ce7 100644 --- a/workspaces/intelligent-assistant/rbac-policy.csv +++ b/workspaces/intelligent-assistant/rbac-policy.csv @@ -6,14 +6,10 @@ # In production RHDH, policies are managed via ConfigMap. # --- Intelligent Assistant for RHDH permissions --- -p, role:default/intelligent-assistant-user, intelligent-assistant.chat.access, use, allow -p, role:default/intelligent-assistant-user, intelligent-assistant.chat.use, use, allow -p, role:default/intelligent-assistant-user, intelligent-assistant.chat.manage, use, allow -p, role:default/intelligent-assistant-user, mcp.tools.use, use, allow -p, role:default/intelligent-assistant-user, mcp.tools.manage, use, allow -p, role:default/intelligent-assistant-user, intelligent-assistant.notebooks.use, use, allow -p, role:default/intelligent-assistant-user, intelligent-assistant.notebooks.manage, use, allow -p, role:default/intelligent-assistant-user, intelligent-assistant.skills.access, use, allow +p, role:default/intelligent-assistant-user, intelligent-assistant.chat, use, allow +p, role:default/intelligent-assistant-user, intelligent-assistant.notebooks, use, allow +p, role:default/intelligent-assistant-user, intelligent-assistant.mcp.tools, use, allow +p, role:default/intelligent-assistant-user, intelligent-assistant.skills, use, allow # --- Catalog permissions (needed for MCP tools to query entities) --- p, role:default/intelligent-assistant-user, catalog.entity.read, read, allow