Skip to content

Commit 4f99dc2

Browse files
docs: update release and usage documentation for routing hardening
Document centralized frontend URL/security guardrails and mobile UX guidance across changelogs, README, developer docs, and user manuals to keep implementation and operations aligned. Made-with: Cursor
1 parent 1580b25 commit 4f99dc2

7 files changed

Lines changed: 73 additions & 9 deletions

File tree

CHANGELOG.de.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,25 @@
44

55
- **Genehmigungs-Deadlock (App-Teams)**: Abwesenheiten und Zeiteintrags-Korrekturen behandeln „hat Kolleg:innen“ nicht mehr wie „hat eine:n Vorgesetzte:n“. Auto-Genehmigung, wenn **kein zuweisbarer Genehmiger** existiert, folgt `TeamResolverService::hasAssignableManagerForEmployee()` (explizite Team-Manager bei App-Teams; Legacy-Gruppenmodus weiterhin Kollegen-Proxy). Verhindert Anträge, die dauerhaft auf Managerfreigabe warten, obwohl niemand freigeben darf.
66
- **Zeiteintrags-Korrekturen**: Gleiche Zuweisbarkeitsregel wie bei Abwesenheiten (zuvor nur Kollegen-IDs).
7+
- **Admin-Users API auf `/index.php`-Instanzen**: Refresh/Edit/History/Update nutzen nun zuverlässig aufgelöste App-URLs; fehlerhafte Requests wie `search=[object PointerEvent]` treten nicht mehr auf.
8+
- **Admin-Teams und Settings auf Rewrite-losen Setups**: Zentrale URL-Auflösung enthält jetzt einen robusten `/index.php`-Fallback, wenn `OC.generateUrl()` im Seitenkontext fehlt oder unvollständig ist.
79

810
### Hinzugefügt
911

1012
- **Repair-Schritt** `ReleaseStuckPendingAbsences`: setzt nach Migration verbliebene `pending`-Abwesenheiten unter derselben Bedingung automatisch auf genehmigt (idempotent).
13+
- **Frontend-URL-Sicherheitsleitplanken**: Die gemeinsame AJAX-Schicht blockiert externe Cross-Origin-Calls standardmäßig (explizit `allowExternal: true` nötig); Unit-Tests decken URL-Normalisierung und External-Handling ab.
14+
- **Lint-Leitplanken**: ESLint-Regeln verhindern neue rohe `fetch('/apps/arbeitszeitcheck/...')`-Aufrufe und implizite externe `fetch(...)`-Nutzung außerhalb der vorgesehenen Abstraktionen.
1115

1216
### Geändert
1317

1418
- **UX**: Abwesenheiten zeigen einen Hinweis, wenn App-Teams aktiv sind und kein Genehmiger zugeordnet ist; in der Detailansicht erscheint bei veralteten hängenden Anträgen ein Warnhinweis (bis Repair/Admin die Teamkonfiguration korrigiert).
19+
- **Frontend-Architektur**: `ArbeitszeitCheckUtils` stellt nun zentral `getRequestToken()`, `resolveUrl()` und `isExternalUrl()` bereit; genutzt u. a. in `admin-users`, `reports`, `settings` und `validation`.
20+
- **Mobile UX Konsistenz (WCAG 2.1 AA)**: iPhone-Safe-Area-konforme Abstände, bessere Touch-Targets, klarere Abschnittsstruktur und visuelle Hierarchie für Nutzerseiten (`dashboard`, `time-entries`, `absences`) sowie Managerseiten (`manager-dashboard`, `manager-time-entries`, Mitarbeiter-Abwesenheiten).
1521

1622
### Dokumentation
1723

1824
- Nutzerhandbücher (EN/DE), `tests/WORKFLOW_ROLE_MATRIX.md` und Entwicklerdokumentation zur Semantik „zuweisbarer Manager“ und zum Repair-Schritt ergänzt.
25+
- README und Entwicklerdokumentation um zentrale Frontend-URL-Policy, striktes External-Call-Verhalten und Mobile/iOS-Layout-Hinweise ergänzt.
1926

2027
## 1.1.13 – 2026-04-13
2128

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1111

1212
- **Approver deadlock (app teams)**: Absence and time-entry correction workflows no longer treat “has colleagues” as “has a manager”. Auto-approval when **no assignable approver** exists now follows `TeamResolverService::hasAssignableManagerForEmployee()` (explicit team managers in app-teams mode; legacy group mode still uses colleagues as a proxy). Prevents requests stuck in “awaiting manager approval” when nobody can approve.
1313
- **Time entry corrections**: Same assignability rule as absences (previously used colleague IDs only).
14+
- **Admin users API requests on `/index.php` instances**: Refresh/edit/history/update actions now reliably resolve app URLs and no longer produce invalid requests like `search=[object PointerEvent]`.
15+
- **Admin teams and settings API reliability on rewrite-less setups**: Central URL resolution now includes a robust `/index.php` fallback when `OC.generateUrl()` is unavailable/incomplete in page context.
1416

1517
### Added
1618

1719
- **Repair step** `ReleaseStuckPendingAbsences`: post-migration repair auto-approves legacy `pending` absences that still match the “no assignable approver” condition (idempotent).
20+
- **Frontend URL security guardrails**: Shared AJAX layer now blocks external cross-origin calls by default (explicit `allowExternal: true` required), with unit tests covering URL normalization and external URL handling.
21+
- **Lint guardrails**: ESLint rules now prevent introducing raw `fetch('/apps/arbeitszeitcheck/...')` and implicit external `fetch(...)` patterns outside approved abstractions.
1822

1923
### Changed
2024

2125
- **UX**: Absences UI shows an informational callout when app teams are enabled and no approver is assigned; detail view shows a defensive warning if an old `pending` row is still stuck (until repair/admin fixes team setup).
26+
- **Frontend architecture**: `ArbeitszeitCheckUtils` now provides centralized `getRequestToken()`, `resolveUrl()`, and `isExternalUrl()` primitives used by page scripts (`admin-users`, `reports`, `settings`, `validation`).
27+
- **Mobile UX consistency (WCAG 2.1 AA focused)**: iPhone-safe-area-aware spacing, improved touch targets, clearer section rhythm, and better visual hierarchy for normal user pages (`dashboard`, `time-entries`, `absences`) and manager pages (`manager-dashboard`, `manager-time-entries`, employee absences view).
2228

2329
### Documentation
2430

2531
- User manuals (EN/DE), `tests/WORKFLOW_ROLE_MATRIX.md`, and developer documentation updated for assignable-manager semantics and repair step.
32+
- README and developer documentation updated with centralized frontend URL policy, strict external-call behavior, and mobile/iOS layout guidance.
2633

2734
## 1.1.13 - 2026-04-13
2835

README.md

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Die App läuft vollständig innerhalb Ihrer selbst gehosteten Nextcloud‑Instan
1616
- **Team‑ und Manager‑Ansicht**: Genehmigungen, Team‑Übersichten, Compliance‑Status
1717
- **Berichte & Exporte**: Tages/Wochen/Monats‑Reports, Overtime‑Reports, Absenzberichte, DATEV‑Export
1818
- **Audit‑Logs**: Lückenlose Nachvollziehbarkeit von Änderungen an Zeiten, Abwesenheiten und Einstellungen
19+
- **Revisionssichere Monatsfinalisierung** (optional, Admin‑Schalter): Kalendermonat mit Snapshot, Hash und PDF‑Nachweis abschließen; finalisierte Monate bleiben gesperrt, bis eine Administratorin/ein Administrator mit Begründung wieder öffnet
1920
- **DSGVO‑Support**: Exporte, Löschkonzepte (unter Beachtung der gesetzlichen Aufbewahrung), DPIA‑/Verarbeitungsverzeichnis‑Vorlagen
2021

2122
> **Rechtlicher Hinweis (DE):**
@@ -100,12 +101,23 @@ Diese Dateien werden vom Nextcloud App Store für Listung, Detailseite und Revie
100101

101102
### Entwicklung & Tests
102103

103-
- PHPUnit‑Tests: `composer test` (bzw. `phpunit` mit bereitgestellter `phpunit.xml`)
104-
- JS‑Build: `npm run build`, Dev‑Watch: `npm run watch`
105-
- Test‑Abdeckung:
106-
- Controller‑Tests (`tests/Unit/Controller/*Test.php`)
107-
- Service‑Tests (z. B. `ComplianceServiceTest`, `TimeTrackingServiceTest`, `OvertimeServiceTest`)
108-
- Integrationstests für zentrale API‑Flows (`tests/Integration/`, falls vorhanden)
104+
**Voraussetzungen:** Node.js **20 oder 22** und npm **10+** (siehe `package.json``engines`), Composer, PHPUnit über `composer.json`.
105+
106+
- **PHP:** `composer test` (alle Suites), `composer test:unit`, `composer test:integration` (Integration unter `tests/Integration/`), optional `composer test:coverage`
107+
- **PHP im Docker‑Stack dieses Monorepos:** vom Nextcloud‑Server‑Root `./docker/run-app-phpunit.sh arbeitszeitcheck` oder in der App `composer test:docker` bzw. `npm run test:php:docker`
108+
- **JavaScript (Vitest):** `npm test`, bei Bedarf `npm run test:watch`
109+
- **Lint:** `npm run lint`, `npm run stylelint` (sowie `composer lint` für PHP‑Syntaxcheck unter `lib/`)
110+
- **E2E (Playwright):** `npm run e2e` — erfordert laufende Nextcloud‑Instanz und Umgebungsvariablen (`NC_BASE_URL`, Testnutzer); siehe `docs/Developer-Documentation.en.md`
111+
- **Alle Tests im Container (Hilfsskript):** `scripts/run-tests-docker.sh` vom App‑ bzw. Repo‑Kontext
112+
113+
Hinweis: `npm run build` ist ein Platzhalter (**kein** Bundler‑Build; Frontend ist Vanilla‑JS mit PHP‑Templates).
114+
115+
### Frontend Runtime & UX Guardrails
116+
117+
- **One URL resolution path:** Frontend requests should use `ArbeitszeitCheckUtils.ajax(...)` (or `ArbeitszeitCheckUtils.resolveUrl(...)` when using `fetch` explicitly) to normalize app URLs reliably on both pretty-URL and `/index.php` installations.
118+
- **Strict external-call policy:** `ArbeitszeitCheckUtils.ajax(...)` blocks cross-origin URLs by default. External calls require explicit opt-in via `allowExternal: true`.
119+
- **Lint enforcement:** ESLint rejects raw `fetch('/apps/arbeitszeitcheck/...')` and implicit external `fetch(...)` patterns outside approved abstractions.
120+
- **Mobile/iPhone consistency:** Shared layout styles in `css/common/` include safe-area-aware spacing and touch-target improvements (WCAG 2.1 AA focus) for user and manager pages.
109121

110122
Weitere Details zur Architektur und zu Beitrag‑Richtlinien finden sich in `docs/Developer-Documentation.en.md`.
111123

docs/Developer-Documentation.en.md

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Developer Documentation – ArbeitszeitCheck
22

3-
**Version:** 1.1.12
4-
**Last Updated:** 2026-04-13
3+
**Version:** 1.1.13
4+
**Last Updated:** 2026-04-14
55

66
This guide is for developers who want to contribute to ArbeitszeitCheck or integrate with it.
77

@@ -594,6 +594,35 @@ ArbeitszeitCheckMessaging.showError('Operation failed');
594594
ArbeitszeitCheckComponents.openModal('my-modal-id');
595595
```
596596

597+
### Frontend URL and request policy (important)
598+
599+
For reliability and security, all frontend network calls should follow one path:
600+
601+
1. **Prefer** `ArbeitszeitCheckUtils.ajax(...)` for app API calls.
602+
2. If a raw `fetch(...)` is unavoidable, resolve URLs with `ArbeitszeitCheckUtils.resolveUrl(...)` and read CSRF token via `ArbeitszeitCheckUtils.getRequestToken()`.
603+
3. Do not hardcode raw app URLs in fetch calls (e.g. `fetch('/apps/arbeitszeitcheck/...')`) — lint rules reject this.
604+
605+
Behavior implemented in `js/common/utils.js`:
606+
607+
- `resolveUrl(...)` normalizes app URLs for both pretty-URL and `/index.php` deployments.
608+
- `ajax(...)` injects `requesttoken` and `credentials: 'same-origin'`.
609+
- External cross-origin URLs are blocked by default in `ajax(...)`; explicit opt-in is required with `allowExternal: true`.
610+
611+
### Mobile/iPhone layout guidance
612+
613+
Shared layout behavior is centralized in:
614+
615+
- `css/common/app-layout.css`
616+
- `css/common/responsive.css`
617+
- `css/navigation.css`
618+
619+
Key rules:
620+
621+
- Use safe-area aware spacing (`env(safe-area-inset-*)`) for iPhone notch/home-indicator devices.
622+
- Keep interactive controls at least ~44px height (WCAG touch-target guidance).
623+
- Preserve clear section hierarchy: one strong heading, concise helper text, and consistent card/action spacing.
624+
- Keep mobile behavior in shared CSS first; page CSS should only add local adjustments.
625+
597626
### CSS Organization
598627

599628
**Use BEM naming:**
@@ -868,6 +897,13 @@ public function getEntry(int $id): JSONResponse
868897
- `AppAdminMiddleware` is registered in `Application::register()` and gates `AdminController` methods centrally.
869898
- Unauthorized access to admin pages throws `NotAppAdminException` and resolves to a 403 response.
870899

900+
### Frontend request security model
901+
902+
- Central request guardrails are implemented in `ArbeitszeitCheckUtils.ajax(...)`.
903+
- Cross-origin URLs are denied by default; callers must explicitly set `allowExternal: true`.
904+
- URL normalization and token handling are centralized to avoid route drift and accidental insecure request patterns.
905+
- ESLint guardrails in `.eslintrc.cjs` enforce this policy for `fetch(...)` usage.
906+
871907
### SQL Injection Prevention
872908

873909
Always use parameterized queries:

docs/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ This folder contains the documentation included with ArbeitszeitCheck for admini
1111
| [GDPR-Compliance-Guide.en.md](GDPR-Compliance-Guide.en.md) | How to operate ArbeitszeitCheck in a GDPR-compliant way (legal basis, data minimization, employee rights, retention) |
1212
| [Compliance-Implementation.en.md](Compliance-Implementation.en.md) | Technical implementation of ArbZG compliance checks (breaks, rest periods, real-time vs batch) |
1313
| [Compliance-Implementation.de.md](Compliance-Implementation.de.md) | Same content in German |
14-
| [Developer-Documentation.en.md](Developer-Documentation.en.md) | Architecture, development setup, contribution guidelines, and technical notes (including vacation carryover / Resturlaub, assignable-manager / auto-approval semantics) |
14+
| [Developer-Documentation.en.md](Developer-Documentation.en.md) | Architecture, development setup, contribution guidelines, and technical notes (including vacation carryover / Resturlaub, assignable-manager / auto-approval semantics, centralized frontend URL/security guardrails, and mobile/iPhone UX implementation notes) |
1515

1616
## Legal Notice
1717

docs/User-Manual.de.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ Im Auswahldialog erscheinen nur Konten aus der Nextcloud-`admin`-Gruppe.
5757
- **App-Teams (empfohlene Einrichtung):** Wenn Ihre Organisation **App-Teams** nutzt und in der App **kein:e Vorgesetzte:r** für Ihr Team hinterlegt ist, werden Anträge **ohne** Vertretung beim Absenden **automatisch genehmigt**—es gäbe sonst niemanden mit Managerfreigabe. Mit **Vertretung** läuft zuerst der Vertretungs-Schritt. Die Oberfläche kann dazu einen kurzen Hinweis anzeigen.
5858
- **Älteres Gruppenmodell:** Verhalten folgt dem früheren „gleiche Gruppe“-Modell; die Administration sollte sicherstellen, dass Genehmigungen für Ihre Organisation weiterhin sinnvoll möglich sind.
5959
- **Manager-Dashboard** (als Führungskraft): Unter **Ausstehende Genehmigungen** erscheint der **Abwesenheitstyp in Ihrer Sprache** (z. B. Urlaub, Krankheit), nicht technische Kurzbezeichnungen. Wo freigeschaltet, bietet **Abwesenheiten der Mitarbeitenden** eine eigene Listen-/Filteransicht.
60+
- **Mobile Nutzung (Smartphone/Tablet):** Die Oberfläche ist responsiv optimiert (klarere Abschnittsabstände, größere Touch-Ziele, iPhone-Safe-Area-Berücksichtigung). Auf sehr kleinen Displays funktionieren Formulare meist am besten im Hochformat, breite Tabellen/Berichte im Querformat.
6061
- **Berichte** für Zeiträume erstellen und erlaubte Exporte nutzen (CSV, DATEV, …).
6162
- **Compliance-Hinweise** (z. B. fehlende Pausen) nach Vorgabe des Arbeitgebers bearbeiten.
6263

docs/User-Manual.en.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ Only users in Nextcloud's `admin` group are eligible in this picker.
5757
- **App teams (recommended setup):** If your organization uses **app-managed teams** and **no manager is assigned** to your team in the app, requests you submit **without** a substitute are **approved automatically** when you send them—there is nobody who could approve them in the manager workflow. If you **do** pick a substitute, the substitute step still runs first. The UI may show a short explanation when this applies.
5858
- **Legacy group-based setup:** Behavior follows the older “same group” model; your admin should ensure approvals remain workable for your organization.
5959
- **Manager dashboard** (if you are a team lead): Under **Pending approvals**, absence requests list each person with the **absence type in your language** (e.g. vacation vs sick leave), not raw internal codes. Where enabled, **Employee absences** provides a dedicated list/filter view of team absences.
60+
- **Mobile use (phones/tablets):** The UI is optimized for responsive use with clearer section spacing, larger touch targets, and iPhone safe-area aware layout. If you use a very small screen, prefer portrait mode for forms and landscape for wide tables/reports.
6061
- **Reports**: Generate period reports or exports your admin allows (CSV, DATEV, etc.).
6162
- **Compliance**: The app may flag violations (e.g. missing breaks); your employer defines how those are handled.
6263

0 commit comments

Comments
 (0)