+ *
+ * @spec openspec/architecture/adr-023-action-authorization.md
+ */
+ public function getActions(): array
+ {
+ return array_keys($this->getMatrix());
+
+ }//end getActions()
+}//end class
diff --git a/lib/actions.seed.json b/lib/actions.seed.json
new file mode 100644
index 00000000..7da36a29
--- /dev/null
+++ b/lib/actions.seed.json
@@ -0,0 +1,79 @@
+{
+ "$comment": "ADR-023 action matrix seed for mydash. Default admin-only; broaden via Admin Settings > MyDash > Action authorization.",
+ "actions": {
+ "admin.get-my-role": ["admin"],
+ "admin-org-navigation.get-org-navigation": ["admin"],
+ "admin-org-navigation.get-position": ["admin"],
+ "analytics.top-dashboards": ["admin"],
+ "analytics.dashboard-detail": ["admin"],
+ "analytics.instance-summary": ["admin"],
+ "analytics.export-csv": ["admin"],
+ "dashboard.list": ["admin"],
+ "dashboard.visible": ["admin"],
+ "dashboard.get-active": ["admin"],
+ "dashboard.show": ["admin"],
+ "dashboard.update": ["admin"],
+ "dashboard.delete": ["admin"],
+ "dashboard.tree": ["admin"],
+ "dashboard.by-path": ["admin"],
+ "dashboard.compute-path": ["admin"],
+ "dashboard.activate": ["admin"],
+ "dashboard.list-group": ["admin"],
+ "dashboard.get-group": ["admin"],
+ "dashboard.set-active-dashboard": ["admin"],
+ "dashboard.set-default-dashboard": ["admin"],
+ "dashboard.get-default-dashboard": ["admin"],
+ "dashboard.publish": ["admin"],
+ "dashboard.unpublish": ["admin"],
+ "dashboard.schedule": ["admin"],
+ "dashboard.view-event": ["admin"],
+ "dashboard-comments.index": ["admin"],
+ "dashboard-comments.destroy": ["admin"],
+ "dashboard-lock.acquire": ["admin"],
+ "dashboard-lock.get": ["admin"],
+ "dashboard-metadata.get-metadata": ["admin"],
+ "dashboard-metadata.set-metadata": ["admin"],
+ "dashboard-reaction.get-reactions": ["admin"],
+ "dashboard-reaction.add-reaction": ["admin"],
+ "dashboard-reaction.remove-reaction": ["admin"],
+ "dashboard-reaction.get-reactors-by-emoji": ["admin"],
+ "dashboard-translation.list": ["admin"],
+ "dashboard-translation.create": ["admin"],
+ "dashboard-translation.update": ["admin"],
+ "dashboard-translation.destroy": ["admin"],
+ "dashboard-translation.set-primary": ["admin"],
+ "dashboard-translation.resolved": ["admin"],
+ "dashboard-version.list-versions": ["admin"],
+ "dashboard-version.fetch-version": ["admin"],
+ "dashboard-version.create-version": ["admin"],
+ "dashboard-version.restore-version": ["admin"],
+ "manifest.index": ["admin"],
+ "metadata-admin.list-fields": ["admin"],
+ "metadata-admin.create-field": ["admin"],
+ "metadata-admin.get-field": ["admin"],
+ "metadata-admin.update-field": ["admin"],
+ "metadata-admin.delete-field": ["admin"],
+ "people-widget.get-users": ["admin"],
+ "resource.get-resource": ["admin"],
+ "resource.list-resources": ["admin"],
+ "resource-serve.get-resource": ["admin"],
+ "resource-serve.list-resources": ["admin"],
+ "rule.get-rules": ["admin"],
+ "rule.add-rule": ["admin"],
+ "rule.update-rule": ["admin"],
+ "rule.delete-rule": ["admin"],
+ "template.gallery": ["admin"],
+ "tile.index": ["admin"],
+ "tile.create": ["admin"],
+ "tile.update": ["admin"],
+ "tile.destroy": ["admin"],
+ "widget.list-available": ["admin"],
+ "widget.get-items": ["admin"],
+ "widget.add-widget": ["admin"],
+ "widget.add-tile": ["admin"],
+ "widget.update-placement": ["admin"],
+ "widget.remove-placement": ["admin"],
+ "widget.news-items": ["admin"],
+ "widget.calendar-events": ["admin"]
+ }
+}
diff --git a/src/components/admin/ActionAuthMatrix.vue b/src/components/admin/ActionAuthMatrix.vue
new file mode 100644
index 00000000..5edbdff5
--- /dev/null
+++ b/src/components/admin/ActionAuthMatrix.vue
@@ -0,0 +1,250 @@
+
+
+
+
+
{{ t('mydash', 'Action authorization') }}
+
+ {{ t('mydash', 'Decide which Nextcloud groups may invoke each MyDash action (ADR-023). Admins always pass. Every action defaults to admin-only — tick a group to broaden it.') }}
+
+
+
+ {{ error }}
+
+
+
+ {{ t('mydash', 'Loading action matrix…') }}
+
+
+
+
+
+
+ |
+ {{ t('mydash', 'Action') }}
+ |
+
+ {{ group }}
+ |
+
+
+
+
+ |
+ {{ action }}
+ |
+
+
+ |
+
+
+
+
+
+
+
+ {{ saving ? t('mydash', 'Saving…') : t('mydash', 'Save action matrix') }}
+
+
+
+
+
+
+
+
diff --git a/src/components/admin/AdminSettings.vue b/src/components/admin/AdminSettings.vue
index e973cdba..400b0adc 100644
--- a/src/components/admin/AdminSettings.vue
+++ b/src/components/admin/AdminSettings.vue
@@ -231,6 +231,11 @@
+
+
+
{{ t('mydash', 'Setting as default app') }}
@@ -329,6 +334,7 @@ import AdminDemoData from './AdminDemoData.vue'
import SetupWizardModal from './SetupWizardModal.vue'
import { api } from '../../services/api.js'
import RolePermissionsSection from './RolePermissionsSection.vue'
+import ActionAuthMatrix from './ActionAuthMatrix.vue'
export default {
name: 'AdminSettings',
@@ -353,6 +359,7 @@ export default {
SetupWizardModal,
ViewDashboard,
RolePermissionsSection,
+ ActionAuthMatrix,
},
// REQ-INIT-004: read the initial-state snapshot the PHP admin form
diff --git a/src/services/api.js b/src/services/api.js
index 3ddf0d8b..e507dcef 100644
--- a/src/services/api.js
+++ b/src/services/api.js
@@ -423,6 +423,17 @@ export const api = {
return axios.post(`${baseUrl}/api/admin/groups`, { groups })
},
+ // ADR-023 action-authorization matrix. Both endpoints are admin-only
+ // on the server side via #[AuthorizedAdminSetting]; the UI gates the
+ // section behind the same admin check.
+ getActionMatrix() {
+ return axios.get(`${baseUrl}/api/admin/action-matrix`)
+ },
+
+ updateActionMatrix(matrix) {
+ return axios.put(`${baseUrl}/api/admin/action-matrix`, { matrix })
+ },
+
// Setup wizard endpoints (REQ-WIZ-008, REQ-WIZ-009, REQ-WIZ-003).
// All three are admin-only on the server side; the UI gates the
// banner + modal behind the same check via `getSetupWizardState`.