From 8bca6ed9e939e48ea1da0c6f3c1171daae3e7dbf Mon Sep 17 00:00:00 2001 From: Mathias Jakobsen Date: Thu, 3 Aug 2023 18:08:41 +0100 Subject: [PATCH] Merge pull request #14167 from overleaf/revert-14106-ab-ab-group-settings-admin-only Revert "[web] Restrict group settings page and managed users activation to group admin" GitOrigin-RevId: 01eea0696bae95a5c1c6b48486c08219445558a4 --- .../Subscription/SubscriptionController.js | 26 +++++----- .../UserMembershipAuthorization.js | 19 ++++--- .../UserMembershipEntityConfigs.js | 49 ++++++++++++++----- .../UserMembershipMiddleware.js | 14 +----- 4 files changed, 62 insertions(+), 46 deletions(-) diff --git a/services/web/app/src/Features/Subscription/SubscriptionController.js b/services/web/app/src/Features/Subscription/SubscriptionController.js index 44a8f13893..591c94f198 100644 --- a/services/web/app/src/Features/Subscription/SubscriptionController.js +++ b/services/web/app/src/Features/Subscription/SubscriptionController.js @@ -138,8 +138,8 @@ async function plansPage(req, res) { } /** - * @param {import('express').Request} req - * @param {import('express').Response} res + * @param {import("express").Request} req + * @param {import("express").Response} res * @returns {Promise} */ async function paymentPage(req, res) { @@ -208,8 +208,8 @@ function formatGroupPlansDataForDash() { } /** - * @param {import('express').Request} req - * @param {import('express').Response} res + * @param {import("express").Request} req + * @param {import("express").Response} res * @returns {Promise} */ async function userSubscriptionPage(req, res) { @@ -246,13 +246,9 @@ async function userSubscriptionPage(req, res) { const groupPlansDataForDash = formatGroupPlansDataForDash() - // display the Group Settings button only to admins of group subscriptions with the Managed Users feature available const groupSettingsEnabledFor = (managedGroupSubscriptions || []) - .filter( - subscription => - ManagedUsersManager.hasManagedUsersFeature(subscription) && - (subscription.admin_id._id || subscription.admin_id).toString() === - user._id.toString() + .filter(subscription => + ManagedUsersManager.hasManagedUsersFeature(subscription) ) .map(subscription => subscription._id.toString()) @@ -403,8 +399,8 @@ async function createSubscription(req, res) { } /** - * @param {import('express').Request} req - * @param {import('express').Response} res + * @param {import("express").Request} req + * @param {import("express").Response} res * @returns {Promise} */ async function successfulSubscription(req, res) { @@ -444,9 +440,9 @@ function cancelSubscription(req, res, next) { } /** - * @param {import('express').Request} req - * @param {import('express').Response} res - * @param {import('express').NextFunction} next + * @param {import("express").Request} req + * @param {import("express").Response} res + * @param {import("express").NextFunction} next * @returns {Promise} */ function canceledSubscription(req, res, next) { diff --git a/services/web/app/src/Features/UserMembership/UserMembershipAuthorization.js b/services/web/app/src/Features/UserMembership/UserMembershipAuthorization.js index a7f25c10a5..e3c29d32d6 100644 --- a/services/web/app/src/Features/UserMembership/UserMembershipAuthorization.js +++ b/services/web/app/src/Features/UserMembership/UserMembershipAuthorization.js @@ -17,12 +17,19 @@ const UserMembershipAuthorization = { if (!req.entity) { return false } - const fieldAccess = req.entity[req.entityConfig.fields.access] - const fieldAccessArray = Array.isArray(fieldAccess) - ? fieldAccess - : [fieldAccess.toString()] - return fieldAccessArray.some( - accessUserId => accessUserId.toString() === req.user._id.toString() + return req.entity[req.entityConfig.fields.access].some(accessUserId => + accessUserId.equals(req.user._id) + ) + } + }, + + isEntityMember() { + return req => { + if (!req.entity) { + return false + } + return req.entity[req.entityConfig.fields.membership].some(accessUserId => + accessUserId.equals(req.user._id) ) } }, diff --git a/services/web/app/src/Features/UserMembership/UserMembershipEntityConfigs.js b/services/web/app/src/Features/UserMembership/UserMembershipEntityConfigs.js index 781036db97..94bc01f7f2 100644 --- a/services/web/app/src/Features/UserMembership/UserMembershipEntityConfigs.js +++ b/services/web/app/src/Features/UserMembership/UserMembershipEntityConfigs.js @@ -14,6 +14,19 @@ module.exports = { baseQuery: { groupPlan: true, }, + translations: { + title: 'group_subscription', + subtitle: 'members_management', + remove: 'remove_from_group', + }, + pathsFor(id) { + return { + addMember: `/manage/groups/${id}/invites`, + removeMember: `/manage/groups/${id}/user`, + removeInvite: `/manage/groups/${id}/invites`, + exportMembers: `/manage/groups/${id}/members/export`, + } + }, }, team: { @@ -41,20 +54,16 @@ module.exports = { baseQuery: { groupPlan: true, }, - }, - - groupAdmin: { - modelName: 'Subscription', - fields: { - primaryKey: '_id', - read: ['admin_id'], - write: 'admin_id', - access: 'admin_id', - membership: 'admin_id', - name: 'teamName', + translations: { + title: 'group_subscription', + subtitle: 'managers_management', + remove: 'remove_manager', }, - baseQuery: { - groupPlan: true, + pathsFor(id) { + return { + addMember: `/manage/groups/${id}/managers`, + removeMember: `/manage/groups/${id}/managers`, + } }, }, @@ -68,9 +77,16 @@ module.exports = { membership: 'member_ids', name: 'name', }, + translations: { + title: 'institution_account', + subtitle: 'managers_management', + remove: 'remove_manager', + }, pathsFor(id) { return { index: `/manage/institutions/${id}/managers`, + addMember: `/manage/institutions/${id}/managers`, + removeMember: `/manage/institutions/${id}/managers`, } }, }, @@ -85,9 +101,16 @@ module.exports = { membership: 'member_ids', name: 'name', }, + translations: { + title: 'publisher_account', + subtitle: 'managers_management', + remove: 'remove_manager', + }, pathsFor(id) { return { index: `/manage/publishers/${id}/managers`, + addMember: `/manage/publishers/${id}/managers`, + removeMember: `/manage/publishers/${id}/managers`, } }, }, diff --git a/services/web/app/src/Features/UserMembership/UserMembershipMiddleware.js b/services/web/app/src/Features/UserMembership/UserMembershipMiddleware.js index 920bd9fbac..fc443cf67a 100644 --- a/services/web/app/src/Features/UserMembership/UserMembershipMiddleware.js +++ b/services/web/app/src/Features/UserMembership/UserMembershipMiddleware.js @@ -64,17 +64,6 @@ const UserMembershipMiddleware = { ]), ], - requireGroupAdminAccess: [ - AuthenticationController.requireLogin(), - fetchEntityConfig('groupAdmin'), - fetchEntity(), - requireEntity(), - allowAccessIfAny([ - UserMembershipAuthorization.hasEntityAccess(), - UserMembershipAuthorization.hasStaffAccess('groupManagement'), - ]), - ], - requireInstitutionMetricsAccess: [ AuthenticationController.requireLogin(), fetchEntityConfig('institution'), @@ -233,11 +222,12 @@ function fetchEntityConfig(entityName) { // fetch the entity with id and config, and set it in the request function fetchEntity() { return expressify(async (req, res, next) => { - req.entity = + const entity = await UserMembershipHandler.promises.getEntityWithoutAuthorizationCheck( req.params.id, req.entityConfig ) + req.entity = entity next() }) }