Skip to content

Feature/admin forth/1433/please normalize allowed e.g. #568

Open
SerVitasik wants to merge 7 commits intonextfrom
feature/AdminForth/1433/please-normalize-allowed-e.g.-
Open

Feature/admin forth/1433/please normalize allowed e.g. #568
SerVitasik wants to merge 7 commits intonextfrom
feature/AdminForth/1433/please-normalize-allowed-e.g.-

Conversation

@SerVitasik
Copy link
Copy Markdown
Collaborator

No description provided.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR updates AdminForth custom action metadata and permission handling by (1) normalizing allowed to support booleans/async checks and (2) aligning the frontend with a boolean “has bulk handler” flag exposed as bulkHandler.

Changes:

  • Extend AdminForthActionInput.allowed to support boolean and Promise<boolean>, and normalize boolean allowed values in config validation.
  • Update REST /get_resource to filter custom actions by allowed and to expose bulkHandler: true to the SPA instead of hasBulkHandler.
  • Update SPA components/utilities to use action.bulkHandler and tighten action typing in ThreeDotsMenu.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
adminforth/types/Common.ts Renames frontend bulk-handler indicator to bulkHandler?: boolean.
adminforth/types/Back.ts Expands allowed type to `boolean
adminforth/modules/restApi.ts Filters actions sent to frontend and adjusts runtime permission checks + frontend action shaping.
adminforth/modules/configValidator.ts Normalizes boolean allowed to a function during validation; improves return type.
adminforth/spa/src/utils/utils.ts Uses action.bulkHandler to decide whether to start custom bulk actions.
adminforth/spa/src/views/ListView.vue Uses action.bulkHandler for bulk success-message selection.
adminforth/spa/src/components/ThreeDotsMenu.vue Removes unused type import and uses AdminForthActionFront for click handling.
Comments suppressed due to low confidence (2)

adminforth/modules/restApi.ts:2117

  • The permission check only runs when allowed is a function; with the new allowed?: boolean | fn type, allowed: false will currently bypass the check and still allow action execution. Treat allowed === false as not allowed here (and optionally treat true/undefined as allowed).
        if (typeof action.allowed === 'function') {
          const execAllowed = await action.allowed({ adminUser, standardAllowedActions: allowedActions });
          if (!execAllowed) {
            return { error: await tr(`Action "{actionId}" not allowed`, 'errors', { actionId: action.name }) };
          }

adminforth/modules/restApi.ts:2170

  • Same as /start_custom_action: with allowed now supporting booleans, allowed: false will bypass this check because it isn't a function and the bulk handler will still execute. Handle boolean allowed values explicitly (deny on false).
        if (typeof action.allowed === 'function') {
          const execAllowed = await action.allowed({ adminUser, standardAllowedActions: allowedActions });
          if (!execAllowed) {
            return { error: await tr(`Action "{actionId}" not allowed`, 'errors', { actionId: action.name }) };
          }
        }

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +434 to +437
if (typeof action.allowed === 'boolean') {
const val = action.allowed;
action.allowed = () => val;
}
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

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

allowed boolean normalization is only applied during validateConfig(), but plugins can mutate resource.options.actions later during modifyResourceConfig() (after validation). That means boolean allowed values introduced by plugins won't be normalized here; consider normalizing again after plugin activation (or ensure runtime checks handle boolean allowed consistently).

Copilot uses AI. Check for mistakes.
Comment on lines +1086 to +1093
if (typeof action.allowed === 'function') {
const res = await action.allowed({ adminUser, standardAllowedActions: allowedActions });
if (res) {
allowedCustomActions.push(action);
}
} else {
allowedCustomActions.push(action);
}
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

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

action.allowed is now typed as boolean | (fn), but this filtering treats any non-function (including false) as allowed and exposes the action to the frontend. This can bypass action-level authorization for configs/plugins that set allowed: false (plugins run after validateConfig, so the boolean->fn normalization may not apply). Handle boolean explicitly (e.g., skip when allowed === false, include when allowed === true/undefined, and only await when it's a function).

Copilot uses AI. Check for mistakes.
Comment on lines +1082 to +1095
const allowedCustomActions = [];
if (resource.options.actions) {
await Promise.all(
resource.options.actions.map(async (action) => {
if (typeof action.allowed === 'function') {
const res = await action.allowed({ adminUser, standardAllowedActions: allowedActions });
if (res) {
allowedCustomActions.push(action);
}
} else {
allowedCustomActions.push(action);
}
})
);
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

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

Promise.all(...map(async ... allowedCustomActions.push(...) )) makes the returned actions order depend on async completion order rather than config order. If allowed checks have varying latency, the UI action ordering can become non-deterministic. Prefer building an array of results (e.g., map to boolean + filter by index) or for...of with await to preserve order.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants