Bladeren bron

Merge pull request #29803 from overleaf/acf-admin-privileges-matrix

Admin privileges matrix

GitOrigin-RevId: 926c8053ab00292ee6fc0f04e0e429f307081f5e
Anna Claire Fields 10 maanden geleden
bovenliggende
commit
9d2f5b3cde

+ 17 - 9
services/web/app/src/Features/ServerAdmin/AdminController.mjs

@@ -6,6 +6,7 @@ import TpdsUpdateSender from '../ThirdPartyDataStore/TpdsUpdateSender.mjs'
 import TpdsProjectFlusher from '../ThirdPartyDataStore/TpdsProjectFlusher.mjs'
 import TpdsProjectFlusher from '../ThirdPartyDataStore/TpdsProjectFlusher.mjs'
 import EditorRealTimeController from '../Editor/EditorRealTimeController.mjs'
 import EditorRealTimeController from '../Editor/EditorRealTimeController.mjs'
 import SystemMessageManager from '../SystemMessages/SystemMessageManager.mjs'
 import SystemMessageManager from '../SystemMessages/SystemMessageManager.mjs'
+import Modules from '../../infrastructure/Modules.js'
 
 
 const AdminController = {
 const AdminController = {
   _sendDisconnectAllUsersMessage: delay => {
   _sendDisconnectAllUsersMessage: delay => {
@@ -30,16 +31,23 @@ const AdminController = {
       )
       )
     }
     }
 
 
-    SystemMessageManager.getMessagesFromDB(function (error, systemMessages) {
-      if (error) {
-        return next(error)
+    SystemMessageManager.getMessagesFromDB(
+      async function (error, systemMessages) {
+        if (error) {
+          return next(error)
+        }
+        const privilegesMatrixResults = await Modules.promises.hooks.fire(
+          'getPrivilegesMatrix'
+        )
+        const privilegesMatrix = privilegesMatrixResults[0] || null
+        res.render('admin/index', {
+          title: 'System Admin',
+          openSockets,
+          systemMessages,
+          privilegesMatrix,
+        })
       }
       }
-      res.render('admin/index', {
-        title: 'System Admin',
-        openSockets,
-        systemMessages,
-      })
-    })
+    )
   },
   },
 
 
   disconnectAllUsers: (req, res) => {
   disconnectAllUsers: (req, res) => {

+ 36 - 0
services/web/app/views/admin/index.pug

@@ -16,6 +16,7 @@ block content
 										+bookmarkable-tabset-header('system-messages', 'System Messages', true)
 										+bookmarkable-tabset-header('system-messages', 'System Messages', true)
 										+bookmarkable-tabset-header('open-sockets', 'Open Sockets')
 										+bookmarkable-tabset-header('open-sockets', 'Open Sockets')
 										+bookmarkable-tabset-header('open-close-editor', 'Open/Close Editor')
 										+bookmarkable-tabset-header('open-close-editor', 'Open/Close Editor')
+										+bookmarkable-tabset-header('privileges-matrix', 'Privileges Matrix')
 										if hasFeature('saas')
 										if hasFeature('saas')
 											+bookmarkable-tabset-header('tpds', 'TPDS/Dropbox Management')
 											+bookmarkable-tabset-header('tpds', 'TPDS/Dropbox Management')
 
 
@@ -71,6 +72,41 @@ block content
 													button.btn.btn-danger(type='submit') Reopen Editor
 													button.btn.btn-danger(type='submit') Reopen Editor
 												p.small Will reopen the editor after closing.
 												p.small Will reopen the editor after closing.
 
 
+									.tab-pane(role='tabpanel' id='privileges-matrix')
+										p This matrix shows the access levels for different admin roles across various user management privileges. The matrix is automatically generated from the code-defined roles and capabilities.
+										if hasFeature('saas') && privilegesMatrix
+											.privileges-matrix-container
+												table.table.table-bordered.table-striped.privileges-matrix-table
+													thead
+														tr
+															th Webpage and privilege
+															th(colspan=privilegesMatrix.roles.length) Access Level Needed For Team
+														tr
+															th
+															each role in privilegesMatrix.roles
+																th= role.displayName
+													tbody
+														- let currentSection = null
+														each row in privilegesMatrix.privileges
+															- const privilege = row.privilege
+															- if (currentSection !== privilege.section)
+																- currentSection = privilege.section
+																tr.section-header
+																	td(colspan=privilegesMatrix.roles.length + 1)
+																		strong= privilege.section
+															tr
+																td.privilege-label= privilege.label
+																each role in privilegesMatrix.roles
+																	- const accessLevel = row.access[role.id]
+																	td.access-cell(class=`access-${accessLevel}`)
+																		span.access-badge(class=`badge-${accessLevel}`)
+																			if accessLevel === 'yes'
+																				| Yes
+																			else
+																				| No
+										else
+											p The privileges matrix is not available in this environment.
+
 									if hasFeature('saas')
 									if hasFeature('saas')
 										.tab-pane(role='tabpanel' id='tpds')
 										.tab-pane(role='tabpanel' id='tpds')
 											h3 Flush project to TPDS
 											h3 Flush project to TPDS

+ 73 - 0
services/web/frontend/stylesheets/pages/admin/admin.scss

@@ -100,3 +100,76 @@
 .expiration-label {
 .expiration-label {
   vertical-align: super;
   vertical-align: super;
 }
 }
+
+.privileges-matrix-container {
+  overflow-x: auto;
+  margin-top: var(--spacing-04);
+}
+
+.privileges-matrix-table {
+  width: 100%;
+  min-width: 800px;
+
+  thead {
+    background-color: var(--bg-accent-01);
+    position: sticky;
+    top: 0;
+    z-index: 10;
+
+    th {
+      text-align: center;
+      font-weight: 600;
+      padding: var(--spacing-03);
+      border: 1px solid var(--border-color);
+    }
+
+    th:first-child {
+      text-align: left;
+    }
+  }
+
+  tbody {
+    .section-header {
+      background-color: var(--bg-accent-02);
+      font-weight: 600;
+
+      td {
+        padding: var(--spacing-03);
+        border: 1px solid var(--border-color);
+      }
+    }
+
+    .privilege-label {
+      padding: var(--spacing-03);
+      border: 1px solid var(--border-color);
+      text-align: left;
+    }
+
+    .access-cell {
+      text-align: center;
+      padding: var(--spacing-03);
+      border: 1px solid var(--border-color);
+      vertical-align: middle;
+    }
+
+    .access-badge {
+      display: inline-block;
+      padding: var(--spacing-01) var(--spacing-02);
+      border-radius: var(--border-radius-large);
+      font-weight: 500;
+      font-size: 0.875rem;
+      min-width: 40px;
+      text-align: center;
+    }
+
+    .badge-yes {
+      background-color: #28a745;
+      color: white;
+    }
+
+    .badge-no {
+      background-color: #8b4513;
+      color: white;
+    }
+  }
+}