Skip to content

ABAC: share TableEditor/CELEditor with plugins via window.Components - #37510

Merged
nickmisasi merged 5 commits into
masterfrom
cursor/agents-abac-editor-share-229e
Jul 24, 2026
Merged

ABAC: share TableEditor/CELEditor with plugins via window.Components#37510
nickmisasi merged 5 commits into
masterfrom
cursor/agents-abac-editor-share-229e

Conversation

@nickmisasi

@nickmisasi nickmisasi commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Summary

Makes the ABAC policy editors reusable by plugins (first consumer: the Agents plugin, for agent/service/MCP resource policies) without changing any existing admin-console or channel-settings behavior.

  • CELEditor gains an optional actions prop (checkExpression, searchUsers). When provided, the editor makes zero direct Client4/redux calls — validation and the test-results modal go through the injected callbacks. When omitted, behavior is exactly as today (all 6 existing caller sites verified unchanged).
  • TableEditor's existing actions prop gains an optional searchUsers with the same fallback discipline; TestResultsModal and child components needed no changes (injected callbacks are wrapped in a pass-through thunk).
  • New plugins/access_control_editors.ts exports both editors as React.lazy components on window.Components (AccessControlTableEditor, AccessControlCELEditor). Lazy export keeps Monaco out of the main bundle — verified via production webpack stats (zero Monaco modules in initial chunks); consuming plugins render inside their own Suspense and never bundle Monaco.
  • Tests: injected-vs-fallback paths for both editors (asserting Client4/redux are not hit on the injected path), export presence assertions, and a lazy-export smoke test.

Ticket: https://mattermost.atlassian.net/browse/MM-69921

Screenshot of the shared editors rendering inside the Agents plugin (simple/table mode with attribute autocomplete, backed entirely by injected callbacks):
image
image

Release Note

NONE

To show artifacts inline, enable in settings.

Open in Web Open in Cursor 

Change Impact: 🟡 Medium

Regression Risk: Changes span shared editor components and public plugin exports in authorization-related flows, though injected and fallback paths are covered by automated tests.
QA Recommendation: Manual QA can be skipped; automated coverage is sufficient.

Generated by CodeRabbitAI

cursoragent and others added 3 commits July 14, 2026 20:52
Co-authored-by: nick.misasi <nick.misasi@mattermost.com>
Co-authored-by: nick.misasi <nick.misasi@mattermost.com>
…Event clicks

Co-authored-by: nick.misasi <nick.misasi@mattermost.com>
Co-authored-by: nick.misasi <nick.misasi@mattermost.com>
@nickmisasi
nickmisasi marked this pull request as ready for review July 21, 2026 01:09
@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Adds injectable validation and user-search actions to ABAC editors, exposes the editors through lazy-loaded plugin components, and adds tests for fallback behavior, schema handling, rendering, and window.Components registration.

Changes

ABAC editor integration

Layer / File(s) Summary
Injectable editor actions
webapp/channels/src/components/admin_console/access_control/editors/cel_editor/editor.tsx, webapp/channels/src/components/admin_console/access_control/editors/table_editor/table_editor.tsx
CEL and table editors accept optional validation and user-search callbacks while retaining existing fallbacks; CEL schema construction includes attributes without an explicit object type as user attributes.
Action override coverage
webapp/channels/src/components/admin_console/access_control/editors/{cel_editor/editor.test.tsx,table_editor/table_editor_channel_admin.test.tsx}
Tests cover injected and fallback action routing, context parameters, validation errors, schema handling, and rendered test results.

Lazy plugin editor exports

Layer / File(s) Summary
Lazy plugin editor exports
webapp/channels/src/plugins/access_control_editors.ts, webapp/channels/src/plugins/export.ts, webapp/channels/src/plugins/*test.tsx
Table and CEL editors are lazy-loaded, registered on window.Components, and tested for lazy behavior, Suspense rendering, and global availability.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CELEditor
  participant ValidationAction
  participant TestResultsModal
  participant SearchAction
  CELEditor->>ValidationAction: validate CEL expression
  ValidationAction-->>CELEditor: return validation errors
  CELEditor->>TestResultsModal: open access rule test
  TestResultsModal->>SearchAction: search matching users
  SearchAction-->>TestResultsModal: return access test results
Loading

Suggested labels: 2: Dev Review, 3: QA Review, 3: Security Review, Changelog/Not Needed

Suggested reviewers: isacikgoz

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: exposing TableEditor and CELEditor to plugins through window.Components.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch cursor/agents-abac-editor-share-229e

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
webapp/channels/src/components/admin_console/access_control/editors/cel_editor/editor.tsx (1)

482-493: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Extract the duplicated searchUsers thunk-wrapping into a shared helper. Both editors implement the identical "use injected searchUsers wrapped as a zero-arg thunk, else return the searchUsersForExpression thunk" logic; a future signature change to this pattern would need to be updated in both places consistently.

  • webapp/channels/src/components/admin_console/access_control/editors/cel_editor/editor.tsx#L482-L493: extract this branch (using editorState.expression) into a shared helper, e.g. wrapSearchUsersAction(injected, fallback).
  • webapp/channels/src/components/admin_console/access_control/editors/table_editor/table_editor.tsx#L679-L692: extract this branch (using value) into the same shared helper.
♻️ Proposed shared helper
// e.g. in a shared module such as editors/search_users_action.ts
import {searchUsersForExpression} from 'mattermost-redux/actions/access_control';
import type {AccessControlTestResult} from '`@mattermost/types/access_control`';
import type {ActionResult} from 'mattermost-redux/types/actions';

export function wrapSearchUsersAction(
    injected: ((expression: string, term: string, after: string, limit: number) => Promise<ActionResult<AccessControlTestResult>>) | undefined,
    expression: string,
    channelId?: string,
    teamId?: string,
) {
    return (term: string, after: string, limit: number) => {
        if (injected) {
            return () => injected(expression, term, after, limit);
        }
        return searchUsersForExpression(expression, term, after, limit, channelId, teamId);
    };
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@webapp/channels/src/components/admin_console/access_control/editors/cel_editor/editor.tsx`
around lines 482 - 493, The duplicated searchUsers thunk-wrapping logic should
be centralized in a shared wrapSearchUsersAction helper. Update
webapp/channels/src/components/admin_console/access_control/editors/cel_editor/editor.tsx
lines 482-493 to call it with editorState.expression, and update
webapp/channels/src/components/admin_console/access_control/editors/table_editor/table_editor.tsx
lines 679-692 to call it with value; the helper must preserve the injected
zero-argument thunk behavior and searchUsersForExpression fallback, including
channelId and teamId.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In
`@webapp/channels/src/components/admin_console/access_control/editors/cel_editor/editor.tsx`:
- Around line 482-493: The duplicated searchUsers thunk-wrapping logic should be
centralized in a shared wrapSearchUsersAction helper. Update
webapp/channels/src/components/admin_console/access_control/editors/cel_editor/editor.tsx
lines 482-493 to call it with editorState.expression, and update
webapp/channels/src/components/admin_console/access_control/editors/table_editor/table_editor.tsx
lines 679-692 to call it with value; the helper must preserve the injected
zero-argument thunk behavior and searchUsersForExpression fallback, including
channelId and teamId.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: cae552c4-81b1-4e29-b50c-49e790a192e7

📥 Commits

Reviewing files that changed from the base of the PR and between 922276c and 34a9bf2.

📒 Files selected for processing (8)
  • webapp/channels/src/components/admin_console/access_control/editors/cel_editor/editor.test.tsx
  • webapp/channels/src/components/admin_console/access_control/editors/cel_editor/editor.tsx
  • webapp/channels/src/components/admin_console/access_control/editors/table_editor/table_editor.tsx
  • webapp/channels/src/components/admin_console/access_control/editors/table_editor/table_editor_channel_admin.test.tsx
  • webapp/channels/src/plugins/access_control_editors.test.tsx
  • webapp/channels/src/plugins/access_control_editors.ts
  • webapp/channels/src/plugins/export.test.ts
  • webapp/channels/src/plugins/export.ts

Co-authored-by: nick.misasi <nick.misasi@mattermost.com>
@nickmisasi
nickmisasi requested a review from pvev July 21, 2026 02:33
@nickmisasi nickmisasi added the 2: Dev Review Requires review by a developer label Jul 21, 2026
@nickmisasi

Copy link
Copy Markdown
Contributor Author

@pvev this lays the groundwork for the upcoming ABAC in agents as a whole. We need to have it so that the CEL funnels through the Agents backend so it knows the rules exist for the resources, and the easiest way was to add props that we can override on the window.

The Agents side is still in draft here: mattermost/mattermost-plugin-agents#886

import {lazy} from 'react';

// Lazy-wrapped so monaco-editor stays out of the main channels bundle; consumers render inside <Suspense>.
export const AccessControlTableEditor = lazy(() => import(/* webpackChunkName: 'access-control-editors' */ 'components/admin_console/access_control/editors/table_editor/table_editor'));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: is the lazy call directly here intentional? I asked because I checked how other published components do and they provide their own suspense, like published_modals.ts for example.

@nickmisasi nickmisasi Jul 24, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, intentional. Same code-splitting pattern as published_modals/published_editor so Monaco stays out of the main channels bundle. Difference is we leave the Suspense boundary to the plugin consumer rather than wrapping it here (those helpers add one because ModalController doesn’t).

@pvev pvev left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎉

@nickmisasi
nickmisasi merged commit 7bc3bbf into master Jul 24, 2026
115 checks passed
@nickmisasi
nickmisasi deleted the cursor/agents-abac-editor-share-229e branch July 24, 2026 16:28
@amyblais amyblais added the Changelog/Not Needed Does not require a changelog entry label Jul 27, 2026 — with Claude
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

2: Dev Review Requires review by a developer Changelog/Not Needed Does not require a changelog entry release-note-none Denotes a PR that doesn't merit a release note.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants