AI Catalog Maintainer Permission for Enable Button
TL;DR
- Investigated
is_user_maintainerarray from AI catalog projects maintainer query, which supports args like member/not-member, min_access_level, and duo_licensed_feature - Found a bug: using ‘array of projects where user is maintainer’ to enable private items is wrong because it doesn’t check the specific managing project
- Discovered the backend already has a ‘create AI catalog item consumer’ permission tied to maintainer role, defined in the policy and used in create.rb (line 45)
- Proposed solution: surface this permission via GraphQL on the project field in the AI catalog item fragment so the frontend can check it directly for the item’s managing project
- This would let the enable button be disabled correctly based on whether the item already has a consumer (private items can only have one) or whether the user is a maintainer of the specific managing project
Background: is_user_maintainer and the projects maintainer query
We have a field called is_user_maintainer, an array returned from the backend for a given user, part of the AI catalog projects maintainer query. This query fetches projects based on criteria for a specific user. Arguments include whether the user must be a member or not, a min_access_level (e.g. requiring maintainer role), and duo_licensed_feature to ensure returned projects are Duo-enabled with a valid license (e.g. duo_agent_platform). It essentially returns an array of project IDs. We hard-code maintainer and membership true, plus duo licensed, to get the list of projects where the user is a maintainer. This list is used on the frontend to block certain actions on AI catalog items (enable, disable, report, edit, duplicate), since users need maintainer permissions to enable an item. For public items, users can enable in any project where they’re a maintainer; for private items, they can only enable in the item’s managing project. It’s questionable whether private items should even be shown in the global catalog, since all catalog items should arguably be public, but that’s how it currently works.
The bug and the fix
The problem: we’ve been checking if the maintainer-projects array length is greater than one to decide whether to show the enable button, even for private items. This is wrong – I could be a maintainer of my own personal project but not the project associated with the private item I’m viewing (e.g., a developer’s project), and the enable button would incorrectly show as enabled. The fix: check permissions in the context of the specific item, not a generic array. I found the backend already has this covered – there’s a ‘create AI catalog item consumer’ permission already defined in the policy document under the maintainer role, used in the create mutation resolver (mutations AI catalog item consumer, create.rb line 45) to authorize users. My idea is to surface this same permission via GraphQL when fetching the AI catalog item, since we already have the project field (the managing project) in the AI catalog item fragment. By adding an ability/permission field there resolving to the maintainer policy, we get exactly what’s needed: (1) whether the item is already enabled/has a consumer (private items can only ever have one consumer), and (2) whether the current user is specifically a maintainer of that item’s managing project. If neither condition is met, the enable button must be disabled. This is a simple fix – just exposing the permission in the project query resolver’s permission types using the ability field, which uses Rails/Ruby magic to generate something like ‘grant maintainer role’ gating logic from the project policy.
ryer.io