From 32a2fdf34757c84832d75992efe09ce292cb5460 Mon Sep 17 00:00:00 2001 From: cstns Date: Fri, 9 Oct 2026 13:20:42 +0300 Subject: [PATCH 1/3] Let application Owners create instances from the team pages The Add Instance button on team Home and the Create Instance buttons on team Hosted Instances only checked the team role, so a team Member with Owner access on an application saw them disabled. They now allow it when the team role or any application role permits it. The create form already only lists applications the user can create in. --- frontend/src/composables/Permissions.js | 28 +++++++++++++++ frontend/src/pages/team/Home/index.vue | 9 ++--- frontend/src/pages/team/Instances.vue | 12 +++---- .../frontend/composables/Permissions.spec.js | 34 +++++++++++++++++++ 4 files changed, 73 insertions(+), 10 deletions(-) create mode 100644 test/unit/frontend/composables/Permissions.spec.js diff --git a/frontend/src/composables/Permissions.js b/frontend/src/composables/Permissions.js index 704c6f722e..d0b4d1af62 100644 --- a/frontend/src/composables/Permissions.js +++ b/frontend/src/composables/Permissions.js @@ -52,6 +52,25 @@ export const hasPermission = (scope, teamMembership, context) => { return true } +/** + * Checks if a user has the required permission either at the team level or in at least + * one application where they have an application-level role. + * + * Used for team-wide actions that end up in an application of the user's choosing, + * e.g. creating an instance from the team pages. + * + * @param {string} scope - The specific scope for which the permission check is being made. + * @param {Object|null} teamMembership - The user's team membership information. + * @returns {boolean} Returns true if the user has the permission in the team or in any of their applications. + */ +export const hasPermissionInAnyApplication = (scope, teamMembership) => { + if (hasPermission(scope, teamMembership)) { + return true + } + const applications = Object.keys(teamMembership?.permissions?.applications || {}) + return applications.some(applicationId => hasPermission(scope, teamMembership, { applicationId })) +} + /** * Check if the user has the minimum required role. * @param {Role} role - The role to check against. @@ -110,6 +129,14 @@ export default function usePermissions () { */ const _hasPermission = (scope, context) => hasPermission(scope, teamMembership.value, context) + /** + * Checks if a user has the required permission in the team or in at least one of their applications. + * + * @param {string} scope - The specific scope for which the permission check is being made. + * @returns {boolean} Returns true if the user has the permission in the team or in any of their applications. + */ + const _hasPermissionInAnyApplication = (scope) => hasPermissionInAnyApplication(scope, teamMembership.value) + /** * Check if the user has the minimum required role. * @param {Role} role - The role to check against. @@ -133,6 +160,7 @@ export default function usePermissions () { return { isVisitingAdmin: _isVisitingAdmin, hasPermission: _hasPermission, + hasPermissionInAnyApplication: _hasPermissionInAnyApplication, hasAMinimumTeamRoleOf: _hasAMinimumTeamRoleOf, hasALowerOrEqualTeamRoleThan: _hasALowerOrEqualTeamRoleThan } diff --git a/frontend/src/pages/team/Home/index.vue b/frontend/src/pages/team/Home/index.vue index 275024d6cc..50367ab74d 100644 --- a/frontend/src/pages/team/Home/index.vue +++ b/frontend/src/pages/team/Home/index.vue @@ -38,11 +38,11 @@