d48e2b7d9d
Major features: - Full backup & restore system (JSON snapshots of all 20 tables + settings) - Web UI, REST API, OCC CLI commands, scheduled background job - Self-update from Gitea releases with Ed25519 signature verification - Configurable column visibility on all data tables (persisted via localStorage) Fixes: - NC admin group fallback for PermissionService (IGroupManager) - Bundle import inline error correction (editable error rows) New files: BackupService, BackupSettingsService, BackupController, BackupJob, SelfUpdateService, 4 OCC commands, ColumnPicker component, Backup.vue, Ed25519 signing scripts, signature verification tests (18 tests) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
183 lines
16 KiB
PHP
183 lines
16 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
return [
|
|
'routes' => [
|
|
// ── Page routes ──────────────────────────────────────────────
|
|
['name' => 'page#index', 'url' => '/', 'verb' => 'GET'],
|
|
|
|
// ── Member search ───────────────────────────────────────────
|
|
['name' => 'member#search', 'url' => '/api/v1/members/search', 'verb' => 'GET'],
|
|
|
|
// ── Member archive (soft-deleted, admin-only) ───────────────
|
|
['name' => 'member#archive', 'url' => '/api/v1/members/archive', 'verb' => 'GET'],
|
|
|
|
// ── Member CRUD ──────────────────────────────────────────────
|
|
['name' => 'member#index', 'url' => '/api/v1/members', 'verb' => 'GET'],
|
|
['name' => 'member#show', 'url' => '/api/v1/members/{id}', 'verb' => 'GET'],
|
|
['name' => 'member#create', 'url' => '/api/v1/members', 'verb' => 'POST'],
|
|
['name' => 'member#update', 'url' => '/api/v1/members/{id}', 'verb' => 'PUT'],
|
|
['name' => 'member#destroy', 'url' => '/api/v1/members/{id}', 'verb' => 'DELETE'],
|
|
|
|
// ── DSGVO actions (admin-only) ───────────────────────────────
|
|
['name' => 'dsgvo#export', 'url' => '/api/v1/members/{id}/dsgvo-export', 'verb' => 'POST'],
|
|
['name' => 'dsgvo#hardDelete', 'url' => '/api/v1/members/{id}/dsgvo-delete', 'verb' => 'DELETE'],
|
|
|
|
// ── Member addresses ─────────────────────────────────────────
|
|
['name' => 'member#createAddress', 'url' => '/api/v1/members/{memberId}/addresses', 'verb' => 'POST'],
|
|
['name' => 'member#updateAddress', 'url' => '/api/v1/members/{memberId}/addresses/{addrId}', 'verb' => 'PUT'],
|
|
['name' => 'member#destroyAddress', 'url' => '/api/v1/members/{memberId}/addresses/{addrId}', 'verb' => 'DELETE'],
|
|
|
|
// ── Member phones ────────────────────────────────────────────
|
|
['name' => 'member#createPhone', 'url' => '/api/v1/members/{memberId}/phones', 'verb' => 'POST'],
|
|
['name' => 'member#updatePhone', 'url' => '/api/v1/members/{memberId}/phones/{phoneId}', 'verb' => 'PUT'],
|
|
['name' => 'member#destroyPhone', 'url' => '/api/v1/members/{memberId}/phones/{phoneId}', 'verb' => 'DELETE'],
|
|
|
|
// ── Member emails ────────────────────────────────────────────
|
|
['name' => 'member#createEmail', 'url' => '/api/v1/members/{memberId}/emails', 'verb' => 'POST'],
|
|
['name' => 'member#updateEmail', 'url' => '/api/v1/members/{memberId}/emails/{emailId}', 'verb' => 'PUT'],
|
|
['name' => 'member#destroyEmail', 'url' => '/api/v1/members/{memberId}/emails/{emailId}', 'verb' => 'DELETE'],
|
|
|
|
// ── Family CRUD ──────────────────────────────────────────────
|
|
['name' => 'family#index', 'url' => '/api/v1/families', 'verb' => 'GET'],
|
|
['name' => 'family#show', 'url' => '/api/v1/families/{id}', 'verb' => 'GET'],
|
|
['name' => 'family#create', 'url' => '/api/v1/families', 'verb' => 'POST'],
|
|
['name' => 'family#update', 'url' => '/api/v1/families/{id}', 'verb' => 'PUT'],
|
|
['name' => 'family#destroy', 'url' => '/api/v1/families/{id}', 'verb' => 'DELETE'],
|
|
|
|
// ── Family member linking ────────────────────────────────────
|
|
['name' => 'family#linkMember', 'url' => '/api/v1/families/{id}/members/{memberId}', 'verb' => 'POST'],
|
|
['name' => 'family#unlinkMember', 'url' => '/api/v1/families/{id}/members/{memberId}', 'verb' => 'DELETE'],
|
|
|
|
// ── Stufen CRUD ──────────────────────────────────────────────
|
|
['name' => 'stufe#index', 'url' => '/api/v1/stufen', 'verb' => 'GET'],
|
|
['name' => 'stufe#create', 'url' => '/api/v1/stufen', 'verb' => 'POST'],
|
|
['name' => 'stufe#update', 'url' => '/api/v1/stufen/{id}', 'verb' => 'PUT'],
|
|
['name' => 'stufe#destroy', 'url' => '/api/v1/stufen/{id}', 'verb' => 'DELETE'],
|
|
|
|
// ── Stufe suggestions + history ──────────────────────────────
|
|
['name' => 'stufe#suggestions', 'url' => '/api/v1/stufen/suggestions', 'verb' => 'GET'],
|
|
['name' => 'stufe#memberHistory', 'url' => '/api/v1/members/{memberId}/stufe-history', 'verb' => 'GET'],
|
|
|
|
// ── Fee rules ───────────────────────────────────────────────
|
|
['name' => 'fee#listRules', 'url' => '/api/v1/fees/rules', 'verb' => 'GET'],
|
|
['name' => 'fee#createRule', 'url' => '/api/v1/fees/rules', 'verb' => 'POST'],
|
|
['name' => 'fee#updateRule', 'url' => '/api/v1/fees/rules/{ruleId}', 'verb' => 'PUT'],
|
|
|
|
// ── Fee records ─────────────────────────────────────────────
|
|
['name' => 'fee#listRecords', 'url' => '/api/v1/fees/records', 'verb' => 'GET'],
|
|
['name' => 'fee#memberRecords', 'url' => '/api/v1/fees/members/{memberId}/records', 'verb' => 'GET'],
|
|
['name' => 'fee#batchCalculate', 'url' => '/api/v1/fees/batch-calculate', 'verb' => 'POST'],
|
|
['name' => 'fee#markPaid', 'url' => '/api/v1/fees/records/{recordId}/paid', 'verb' => 'PUT'],
|
|
['name' => 'fee#manualOverride', 'url' => '/api/v1/fees/records/{recordId}/override', 'verb' => 'PUT'],
|
|
|
|
// ── Permissions ─────────────────────────────────────────────
|
|
['name' => 'permission#index', 'url' => '/api/v1/permissions', 'verb' => 'GET'],
|
|
['name' => 'permission#listUsers', 'url' => '/api/v1/permissions/users', 'verb' => 'GET'],
|
|
['name' => 'permission#setPermission', 'url' => '/api/v1/permissions/{ncUserId}', 'verb' => 'PUT'],
|
|
['name' => 'permission#removePermission', 'url' => '/api/v1/permissions/{ncUserId}', 'verb' => 'DELETE'],
|
|
|
|
// ── CSV Export (plain) ──────────────────────────────────────
|
|
['name' => 'export#members', 'url' => '/api/v1/export/members', 'verb' => 'GET'],
|
|
['name' => 'export#fees', 'url' => '/api/v1/export/fees', 'verb' => 'GET'],
|
|
['name' => 'export#birthdays', 'url' => '/api/v1/export/birthdays', 'verb' => 'GET'],
|
|
|
|
// ── Full bundle export (Issue #149) ────────────────────────
|
|
['name' => 'export#bundle', 'url' => '/api/v1/export/bundle', 'verb' => 'GET'],
|
|
['name' => 'export#bundleSensitive', 'url' => '/api/v1/export/bundle/sensitive', 'verb' => 'POST'],
|
|
|
|
// ── Per-entity export (Issue #148) ─────────────────────────
|
|
['name' => 'export#entityTypes', 'url' => '/api/v1/export/entity-types', 'verb' => 'GET'],
|
|
['name' => 'export#entity', 'url' => '/api/v1/export/entity/{type}', 'verb' => 'GET'],
|
|
|
|
// ── Encrypted Export (password-protected ZIP) ───────────────
|
|
['name' => 'export#membersEncrypted', 'url' => '/api/v1/export/members/encrypted', 'verb' => 'POST'],
|
|
['name' => 'export#feesEncrypted', 'url' => '/api/v1/export/fees/encrypted', 'verb' => 'POST'],
|
|
['name' => 'export#birthdaysEncrypted', 'url' => '/api/v1/export/birthdays/encrypted', 'verb' => 'POST'],
|
|
['name' => 'export#bankingEncrypted', 'url' => '/api/v1/export/banking/encrypted', 'verb' => 'POST'],
|
|
|
|
// ── Lager (camps) CRUD ──────────────────────────────────────
|
|
['name' => 'lager#index', 'url' => '/api/v1/lager', 'verb' => 'GET'],
|
|
['name' => 'lager#show', 'url' => '/api/v1/lager/{id}', 'verb' => 'GET'],
|
|
['name' => 'lager#create', 'url' => '/api/v1/lager', 'verb' => 'POST'],
|
|
['name' => 'lager#update', 'url' => '/api/v1/lager/{id}', 'verb' => 'PUT'],
|
|
['name' => 'lager#destroy', 'url' => '/api/v1/lager/{id}', 'verb' => 'DELETE'],
|
|
['name' => 'lager#addTeilnehmer', 'url' => '/api/v1/lager/{id}/teilnehmer', 'verb' => 'POST'],
|
|
['name' => 'lager#removeTeilnehmer', 'url' => '/api/v1/lager/{id}/teilnehmer/{memberId}', 'verb' => 'DELETE'],
|
|
['name' => 'lager#addFile', 'url' => '/api/v1/lager/{id}/files', 'verb' => 'POST'],
|
|
['name' => 'lager#removeFile', 'url' => '/api/v1/lager/{id}/files/{fileId}', 'verb' => 'DELETE'],
|
|
['name' => 'lager#memberHistory', 'url' => '/api/v1/members/{memberId}/lager-history', 'verb' => 'GET'],
|
|
|
|
// ── Reports (preview + PDF + encrypted) ────────────────────
|
|
['name' => 'report#index', 'url' => '/api/v1/reports', 'verb' => 'GET'],
|
|
['name' => 'report#preview', 'url' => '/api/v1/reports/{type}/preview', 'verb' => 'GET'],
|
|
['name' => 'report#pdf', 'url' => '/api/v1/reports/{type}/pdf', 'verb' => 'GET'],
|
|
['name' => 'report#encrypted', 'url' => '/api/v1/reports/{type}/encrypted', 'verb' => 'POST'],
|
|
|
|
// ── Milestones (Jubilaeen) ──────────────────────────────────
|
|
['name' => 'milestone#index', 'url' => '/api/v1/milestones', 'verb' => 'GET'],
|
|
['name' => 'milestone#getSettings', 'url' => '/api/v1/milestones/settings', 'verb' => 'GET'],
|
|
['name' => 'milestone#updateSettings', 'url' => '/api/v1/milestones/settings', 'verb' => 'PUT'],
|
|
|
|
// ── Injury tracking ────────────────────────────────────────
|
|
['name' => 'injury#index', 'url' => '/api/v1/injuries', 'verb' => 'GET'],
|
|
['name' => 'injury#show', 'url' => '/api/v1/injuries/{id}', 'verb' => 'GET'],
|
|
['name' => 'injury#create', 'url' => '/api/v1/injuries', 'verb' => 'POST'],
|
|
['name' => 'injury#update', 'url' => '/api/v1/injuries/{id}', 'verb' => 'PUT'],
|
|
['name' => 'injury#destroy', 'url' => '/api/v1/injuries/{id}', 'verb' => 'DELETE'],
|
|
['name' => 'injury#addInvolved', 'url' => '/api/v1/injuries/{id}/involved', 'verb' => 'POST'],
|
|
['name' => 'injury#removeInvolved', 'url' => '/api/v1/injuries/{id}/involved/{memberId}', 'verb' => 'DELETE'],
|
|
|
|
// ── Audit log ───────────────────────────────────────────────
|
|
['name' => 'audit#index', 'url' => '/api/v1/audit-log', 'verb' => 'GET'],
|
|
|
|
// ── Import wizard (admin-only) ─────────────────────────────
|
|
['name' => 'import#upload', 'url' => '/api/v1/import/upload', 'verb' => 'POST'],
|
|
['name' => 'import#preview', 'url' => '/api/v1/import/preview', 'verb' => 'POST'],
|
|
['name' => 'import#execute', 'url' => '/api/v1/import/execute', 'verb' => 'POST'],
|
|
|
|
// ── Per-entity import (Issue #150) ────────────────────────
|
|
['name' => 'import#entityUpload', 'url' => '/api/v1/import/entity/upload', 'verb' => 'POST'],
|
|
['name' => 'import#entitySchema', 'url' => '/api/v1/import/entity/schema/{type}', 'verb' => 'GET'],
|
|
['name' => 'import#entityPreview', 'url' => '/api/v1/import/entity/preview', 'verb' => 'POST'],
|
|
['name' => 'import#entityExecute', 'url' => '/api/v1/import/entity/execute', 'verb' => 'POST'],
|
|
['name' => 'import#entityMerge', 'url' => '/api/v1/import/entity/merge', 'verb' => 'POST'],
|
|
|
|
// ── ZIP bundle import (Issue #151) ────────────────────────
|
|
['name' => 'import#bundleUpload', 'url' => '/api/v1/import/bundle/upload', 'verb' => 'POST'],
|
|
['name' => 'import#bundlePreview', 'url' => '/api/v1/import/bundle/preview', 'verb' => 'POST'],
|
|
['name' => 'import#bundleExecute', 'url' => '/api/v1/import/bundle/execute', 'verb' => 'POST'],
|
|
|
|
// ── Saved queries + query execution ────────────────────────
|
|
['name' => 'query#fields', 'url' => '/api/v1/queries/fields', 'verb' => 'GET'],
|
|
['name' => 'query#executeAdHoc', 'url' => '/api/v1/queries/execute', 'verb' => 'POST'],
|
|
['name' => 'query#index', 'url' => '/api/v1/queries', 'verb' => 'GET'],
|
|
['name' => 'query#create', 'url' => '/api/v1/queries', 'verb' => 'POST'],
|
|
['name' => 'query#update', 'url' => '/api/v1/queries/{id}', 'verb' => 'PUT'],
|
|
['name' => 'query#destroy', 'url' => '/api/v1/queries/{id}', 'verb' => 'DELETE'],
|
|
['name' => 'query#executeSaved', 'url' => '/api/v1/queries/{id}/execute', 'verb' => 'POST'],
|
|
|
|
// ── Backup & Restore (admin-only) ─────────────────────────
|
|
['name' => 'backup#getSettings', 'url' => '/api/v1/backups/settings', 'verb' => 'GET'],
|
|
['name' => 'backup#updateSettings', 'url' => '/api/v1/backups/settings', 'verb' => 'PUT'],
|
|
['name' => 'backup#index', 'url' => '/api/v1/backups', 'verb' => 'GET'],
|
|
['name' => 'backup#create', 'url' => '/api/v1/backups', 'verb' => 'POST'],
|
|
['name' => 'backup#show', 'url' => '/api/v1/backups/{filename}', 'verb' => 'GET'],
|
|
['name' => 'backup#download', 'url' => '/api/v1/backups/{filename}/download', 'verb' => 'GET'],
|
|
['name' => 'backup#restore', 'url' => '/api/v1/backups/{filename}/restore', 'verb' => 'POST'],
|
|
['name' => 'backup#destroy', 'url' => '/api/v1/backups/{filename}', 'verb' => 'DELETE'],
|
|
|
|
// ── Self-update (admin-only) ───────────────────────────────
|
|
['name' => 'backup#checkUpdate', 'url' => '/api/v1/update/check', 'verb' => 'GET'],
|
|
['name' => 'backup#installUpdate', 'url' => '/api/v1/update/install', 'verb' => 'POST'],
|
|
|
|
// ── Files integration (NC Files browser) ────────────────────
|
|
['name' => 'file#getSettings', 'url' => '/api/v1/files/settings', 'verb' => 'GET'],
|
|
['name' => 'file#updateSettings', 'url' => '/api/v1/files/settings', 'verb' => 'PUT'],
|
|
['name' => 'file#memberFiles', 'url' => '/api/v1/members/{memberId}/files', 'verb' => 'GET'],
|
|
['name' => 'file#ensureFolder', 'url' => '/api/v1/members/{memberId}/files/ensure-folder', 'verb' => 'POST'],
|
|
['name' => 'file#lagerFiles', 'url' => '/api/v1/lager/{lagerId}/files/browse', 'verb' => 'GET'],
|
|
],
|
|
];
|