From aaea385422d24aee7224f9de4347a7e5533f2743 Mon Sep 17 00:00:00 2001 From: Umut Kantarci Date: Sun, 13 Sep 2026 20:51:55 +0200 Subject: [PATCH] Die Verwaltung kann umziehen: /admin ist frei waehlbar php bin/console cms:admin:path legt die Verwaltung auf eine andere Adresse. Geprueft wird, dass der Name frei ist und keine Seite verdeckt; der Wert steht in .env.local und fuellt einen Parameter, der als Praefix in jeder Verwaltungsroute steht, in der Firewall, in den Schutzkopfzeilen und in der Statistik. Die robots.txt nennt einen geaenderten Namen nicht - sie ist oeffentlich und waere sonst ein Wegweiser. Beim Standardnamen bleibt die Zeile, weil diese Adresse ohnehin jeder kennt. Die Auffangroute fuer Seiten steht jetzt zuletzt: sie kann einen frei gewaehlten Namen nicht per Regex ausschliessen, und die Reihenfolge ist ohnehin die richtige. Der Befehl raeumt den Zwischenspeicher auf, aber nicht den, in dem er selbst laeuft. Co-Authored-By: Claude Opus 5 --- .env | 3 + README.md | 2 + config/packages/security.yaml | 6 +- config/routes.yaml | 10 +- config/services.yaml | 23 ++++ docs/ARCHITECTURE.md | 18 +++ docs/LIVEGANG.md | 4 + docs/STATUS.md | 1 + src/Command/AdminPathCommand.php | 126 ++++++++++++++++++ src/Content/Statistics.php | 6 +- src/Controller/EditorController.php | 2 +- src/Controller/FormAdminController.php | 4 +- src/Controller/MediaController.php | 12 +- src/Controller/MenuController.php | 4 +- src/Controller/PartialController.php | 2 +- src/Controller/SecurityController.php | 4 +- src/Controller/SeoController.php | 11 +- src/Controller/SettingsController.php | 8 +- src/Controller/StatisticsController.php | 4 +- src/Controller/SystemController.php | 11 +- src/Controller/ThemeController.php | 6 +- src/Controller/UserController.php | 14 +- .../AdminHeadersSubscriber.php | 6 +- src/EventSubscriber/MaintenanceSubscriber.php | 4 +- templates/admin/system.html.twig | 9 ++ tests/CmsTest.php | 38 ++++++ 26 files changed, 293 insertions(+), 45 deletions(-) create mode 100644 src/Command/AdminPathCommand.php diff --git a/.env b/.env index 4b18a20..90a3775 100644 --- a/.env +++ b/.env @@ -4,3 +4,6 @@ DATABASE_URL="sqlite:///%kernel.project_dir%/var/cms.db" SITE_ORIGIN=http://127.0.0.1:8080 MEDIA_DIRECTORY="%kernel.project_dir%/var/media" MAILER_DSN=sendmail://default +# Die Adresse der Verwaltung. Aenderbar mit `php bin/console cms:admin:path `; +# der Befehl schreibt .env.local und prueft, dass die Adresse frei ist. +ADMIN_PATH=admin diff --git a/README.md b/README.md index 7d22785..997a227 100644 --- a/README.md +++ b/README.md @@ -88,6 +88,8 @@ npm.cmd run audit Unter Linux/macOS `npm` und `npx` ohne `.cmd`; in CI `npx playwright install --with-deps chromium`. `test:browser` und `audit` benötigen den laufenden lokalen Produktionsmodus auf Port 8080. Ein anderes Ziel lässt sich über `CMS_URL` konfigurieren. `test:editor` startet einen eigenen PHP-Prozess auf einem freien Port mit isolierter Datenbank und zufälligem Testkonto; es ändert keine echten Seiten oder Benutzer. `PHP_BINARY` kann dafür einen alternativen PHP-Pfad angeben. Testdaten bleiben unter `var/browser-tests`, Berichte/Screenshots unter `reports/`. Das Skript erneuert zuvor den Produktionscache. +Die Verwaltung liegt unter `/admin`. `php bin/console cms:admin:path meine-verwaltung` legt sie auf eine andere Adresse: der Wert landet in `.env.local`, gilt für Routen, Firewall und Schutzkopfzeilen, und wird in der `robots.txt` bewusst nicht genannt. Ohne Argument zeigt der Befehl die aktuelle Adresse. + `composer format` formatiert PHP. `composer build` wärmt den Symfony-Produktionscache; öffentliche CSS-Dateien sind direkt auslieferbar, es ist kein Frontend-Bundler nötig. Bei Änderungen an `public/assets/design-tokens.json` einmal `npm.cmd run build:design` ausführen und die erzeugte CSS-Datei mitliefern; Node ist auf dem Hosting nicht erforderlich. Nach Änderungen an Produktionskonfiguration/Templates `php bin/console cache:clear --env=prod --no-debug` ausführen. Falls lokale Tests alte Templates verwenden, vor PHPUnit auch `php bin/console cache:clear --env=test --no-debug` ausführen. `test:links` folgt der Sitemap, sammelt jeden internen Verweis samt Bildern, Stylesheets und Hintergrundbildern und meldet jede Antwort ab 400 – gebaut, nachdem im Nachbau von kant-it.de vier Verweise ins Leere zeigten, die kein Test finden konnte. diff --git a/config/packages/security.yaml b/config/packages/security.yaml index 48cc485..9896e11 100644 --- a/config/packages/security.yaml +++ b/config/packages/security.yaml @@ -9,7 +9,7 @@ security: ROLE_PUBLISHER: ROLE_EDITOR firewalls: admin: - pattern: ^/admin(?:/|$) + pattern: ^/%kant.admin_path%(?:/|$) lazy: true provider: cms_users form_login: @@ -25,5 +25,5 @@ security: target: admin_login enable_csrf: true access_control: - - { path: ^/admin/login$, roles: PUBLIC_ACCESS } - - { path: ^/admin, roles: ROLE_EDITOR } + - { path: ^/%kant.admin_path%/login$, roles: PUBLIC_ACCESS } + - { path: ^/%kant.admin_path%, roles: ROLE_EDITOR } diff --git a/config/routes.yaml b/config/routes.yaml index 9286e81..55d2f38 100644 --- a/config/routes.yaml +++ b/config/routes.yaml @@ -1,3 +1,11 @@ -controllers: +# Erst alle benannten Routen, dann die Auffangroute fuer oeffentliche Seiten. Ohne diese +# Reihenfolge wuerde `/verwaltung/partials` als Seitenadresse gelesen, sobald die Verwaltung nicht +# mehr `/admin` heisst - die Auffangroute schliesst nur den Standardnamen aus. +verwaltung: resource: ../src/Controller/ type: attribute + exclude: '../src/Controller/PageController.php' + +seiten: + resource: ../src/Controller/PageController.php + type: attribute diff --git a/config/services.yaml b/config/services.yaml index 248132c..c259f21 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -1,4 +1,10 @@ parameters: + # Die Adresse der Verwaltung. Standard bleibt /admin; wer sie aendert, nimmt Scannern und + # Anmeldeversuchen das Ziel - erraten laesst sie sich nicht mehr. Sie steht in der Umgebung und + # nicht in der Datenbank, weil die Routen beim Start feststehen muessen. Geaendert wird sie + # ueber `php bin/console cms:admin:path `; der Befehl prueft und raeumt den Cache auf. + kant.admin_path: '%env(string:default:kant.admin_path_default:ADMIN_PATH)%' + kant.admin_path_default: 'admin' # Wo Schriften und Stylesheets liegen. Im Normalfall im oeffentlichen Ordner; ueber # FONT_DIRECTORY und ASSET_DIRECTORY umstellbar - die Tests nutzen das, damit sie nicht in # das Projekt schreiben, und eine Installation mit schreibgeschuetztem public/ ebenfalls. @@ -24,6 +30,13 @@ services: $directory: '%env(resolve:MEDIA_DIRECTORY)%' # Die Schriften liegen im oeffentlichen Ordner: sie sollen vom Webserver direkt ausgeliefert # werden, ohne PHP dazwischen - das ist der Punkt der Uebung. + # Die Stellen, die wissen muessen, wie die Verwaltung heisst. + App\EventSubscriber\AdminHeadersSubscriber: + arguments: + $adminPath: '%kant.admin_path%' + App\Content\Statistics: + arguments: + $adminPath: '%kant.admin_path%' App\Content\FontLibrary: arguments: $directory: '%env(default:kant.fonts_dir:FONT_DIRECTORY)%' @@ -37,9 +50,18 @@ services: App\Controller\SeoController: arguments: $siteOrigin: '%env(SITE_ORIGIN)%' + $adminPath: '%kant.admin_path%' App\Command\HealthCommand: arguments: $projectDir: '%kernel.project_dir%' + App\Controller\SystemController: + arguments: + $adminPath: '%kant.admin_path%' + App\Command\AdminPathCommand: + arguments: + $projectDir: '%kernel.project_dir%' + $adminPath: '%kant.admin_path%' + $environment: '%kernel.environment%' App\Ops\Updater: arguments: $root: '%kernel.project_dir%' @@ -50,6 +72,7 @@ services: App\EventSubscriber\MaintenanceSubscriber: arguments: $projectDir: '%kernel.project_dir%' + $adminPath: '%kant.admin_path%' App\Ops\Installation: arguments: $root: '%kernel.project_dir%' diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 68c73ae..de8c40b 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -466,6 +466,24 @@ Drei Entscheidungen, die nicht offensichtlich sind: Der Preis steht in der Verwaltung: das Widget braucht JavaScript. Ohne Skript ist das Formular dann nicht absendbar – genau die Art von Verschlechterung, die dieses Projekt sonst vermeidet. Deshalb steht im Formular ein `