Sfoglia il codice sorgente

Merge pull request #30916 from overleaf/ar-allow-read-only-institution-access-for-admins-with-no-modify-capability

[web] Add view-only version of institution managers page

GitOrigin-RevId: 65d19e42220932fe268d595ea13d0ba0b18c4398
Andrew Rumble 6 mesi fa
parent
commit
2dfcfd1804

+ 13 - 1
services/web/app/src/Features/UserMembership/UserMembershipMiddleware.mjs

@@ -95,7 +95,19 @@ const UserMembershipMiddleware = {
     ]),
   ],
 
-  requireInstitutionManagementAccess: [
+  requireInstitutionManagerAccess: [
+    AuthenticationController.requireLogin(),
+    fetchEntityConfig('institution'),
+    fetchEntity(),
+    requireEntityOrCreate(),
+    useAdminCapabilities,
+    allowAccessIfAny([
+      UserMembershipAuthorization.hasEntityAccess(),
+      UserMembershipAuthorization.hasAdminAccess,
+    ]),
+  ],
+
+  requireInstitutionManagerManagement: [
     AuthenticationController.requireLogin(),
     fetchEntityConfig('institution'),
     fetchEntity(),

+ 3 - 3
services/web/app/src/Features/UserMembership/UserMembershipRouter.mjs

@@ -82,17 +82,17 @@ export default {
     // institution members routes
     webRouter.get(
       '/manage/institutions/:id/managers',
-      UserMembershipMiddleware.requireInstitutionManagementAccess,
+      UserMembershipMiddleware.requireInstitutionManagerAccess,
       UserMembershipController.manageInstitutionManagers
     )
     webRouter.post(
       '/manage/institutions/:id/managers',
-      UserMembershipMiddleware.requireInstitutionManagementAccess,
+      UserMembershipMiddleware.requireInstitutionManagerManagement,
       UserMembershipController.add
     )
     webRouter.delete(
       '/manage/institutions/:id/managers/:userId',
-      UserMembershipMiddleware.requireInstitutionManagementAccess,
+      UserMembershipMiddleware.requireInstitutionManagerManagement,
       UserMembershipController.remove
     )
 

+ 2 - 1
services/web/app/views/user_membership/institution-managers-react.pug

@@ -4,11 +4,12 @@ block entrypointVar
 	- entrypoint = 'pages/user/subscription/group-management/institution-managers'
 
 block append meta
+	- const hasWriteAccess = entityAccess || (hasAdminAccess() && hasAdminCapability('modify-institution-manager'))
 	meta(name='ol-user' data-type='json' content=user)
 	meta(name='ol-users' data-type='json' content=users)
 	meta(name='ol-groupId' data-type='string' content=groupId)
 	meta(name='ol-groupName' data-type='string' content=name)
-	meta(name='ol-hasWriteAccess' data-type='boolean' content)
+	meta(name='ol-hasWriteAccess' data-type='boolean' content=hasWriteAccess)
 
 block content
 	main#subscription-manage-group-root.content.content-alt

+ 64 - 1
services/web/test/acceptance/src/UserMembershipAuthorizationTests.mjs

@@ -90,7 +90,7 @@ describe('UserMembershipAuthorization', function () {
     })
 
     describe('users management', function () {
-      it('should allow managers only', function (done) {
+      it('should allow managers', function (done) {
         const url = `/manage/institutions/${this.institution.v1Id}/managers`
         async.series(
           [
@@ -102,6 +102,54 @@ describe('UserMembershipAuthorization', function () {
           done
         )
       })
+
+      it('should allow admin users', function (done) {
+        const url = `/manage/institutions/${this.institution.v1Id}/managers`
+        async.series(
+          [
+            this.user.login.bind(this.user),
+            expectAccess(this.user, url, 403),
+            cb => this.user.ensureAdmin(cb),
+            cb => this.user.ensureAdminRole('sales', cb),
+            this.user.login.bind(this.user),
+            expectAccess(this.user, url, 200),
+          ],
+          done
+        )
+      })
+
+      it('should not allow "sales" admin to add managers', function (done) {
+        const url = `/manage/institutions/${this.institution.v1Id}/managers`
+        async.series(
+          [
+            this.user.login.bind(this.user),
+            expectPost(this.user, url, { email: this.user.email }, 403),
+            cb => this.user.ensureAdmin(cb),
+            cb => this.user.ensureAdminRole('sales', cb),
+            this.user.login.bind(this.user),
+            expectPost(this.user, url, { email: this.user.email }, 403),
+          ],
+          done
+        )
+      })
+
+      it('should allow "engineering" admin to add managers', function (done) {
+        const user = new User()
+        const url = `/manage/institutions/${this.institution.v1Id}/managers`
+        async.series(
+          [
+            user.ensureUserExists.bind(user),
+            this.user.login.bind(this.user),
+            expectPost(this.user, url, { email: user.email }, 403),
+            cb => this.user.ensureAdmin(cb),
+            cb => this.user.ensureAdminRole('engineering', cb),
+            this.user.login.bind(this.user),
+            expectPost(this.user, url, { email: user.email }, 200),
+            cb => this.institution.setManagerIds([], cb),
+          ],
+          done
+        )
+      })
     })
 
     describe('creation', function () {
@@ -195,3 +243,18 @@ function expectAccess(user, url, status, pattern) {
     })
   }
 }
+
+function expectPost(user, url, body, status, pattern) {
+  return callback => {
+    user.request.post({ url, json: body }, (error, response, body) => {
+      if (error) {
+        return callback(error)
+      }
+      expect(response.statusCode).to.equal(status)
+      if (pattern) {
+        expect(body).to.match(pattern)
+      }
+      callback()
+    })
+  }
+}