From 42864ebcf42f16117af44d4a7dd6edf88b7113f5 Mon Sep 17 00:00:00 2001 From: tchapi Date: Wed, 30 Sep 2026 22:29:47 +0200 Subject: [PATCH 1/3] chore --- config/packages/framework.yaml | 5 ++ docker/configurations/Caddyfile | 5 ++ docker/configurations/nginx.conf | 15 ++++ migrations/Version20260930120000.php | 43 ++++++++++++ public/.htaccess | 8 +++ src/Entity/AddressBook.php | 3 +- src/Entity/CalendarInstance.php | 5 +- src/Entity/Card.php | 2 +- templates/_partials/navigation.html.twig | 2 +- templates/base.html.twig | 10 +-- templates/index.html.twig | 14 ++-- .../Controllers/AddressBookControllerTest.php | 28 ++++++++ .../Controllers/CalendarControllerTest.php | 70 +++++++++++++++++++ .../Functional/Controllers/DashboardTest.php | 25 +++++++ 14 files changed, 218 insertions(+), 17 deletions(-) create mode 100644 migrations/Version20260930120000.php diff --git a/config/packages/framework.yaml b/config/packages/framework.yaml index f5e13706..3ac1a695 100644 --- a/config/packages/framework.yaml +++ b/config/packages/framework.yaml @@ -14,6 +14,11 @@ framework: name: 'DAVIS_SESSION' storage_factory_id: session.storage.factory.native + # The CSS and JS only ever change with a release, so the version is the release. It also makes + # `asset()` prepend the base path, which a hard-coded `/css/…` does not on a sub-directory install. + assets: + version: !php/const App\Version::VERSION + property_info: with_constructor_extractor: false diff --git a/docker/configurations/Caddyfile b/docker/configurations/Caddyfile index eb109e92..7702552f 100644 --- a/docker/configurations/Caddyfile +++ b/docker/configurations/Caddyfile @@ -37,4 +37,9 @@ Permissions-Policy "camera=(), microphone=(), geolocation=()" } + # Every URL Davis emits for these carries a `?` that changes with the release, so a + # stale copy can never be served: a new release is a new URL + @static path *.css *.js *.png *.jpg *.jpeg *.gif *.svg *.ico *.woff *.woff2 + header @static Cache-Control "public, max-age=31536000, immutable" + } diff --git a/docker/configurations/nginx.conf b/docker/configurations/nginx.conf index 89291f8f..6de54a32 100644 --- a/docker/configurations/nginx.conf +++ b/docker/configurations/nginx.conf @@ -28,6 +28,21 @@ server { return 404; } + # Every URL Davis emits for these carries a `?` that changes with the release, so a + # stale copy can never be served: a new release is a new URL + location ~* \.(css|js|png|jpe?g|gif|svg|ico|woff2?)$ { + add_header Cache-Control "public, max-age=31536000, immutable" always; + + # An `add_header` here replaces the whole inherited set, so the server-level headers above + # have to be repeated or static files would be served without them + add_header X-Content-Type-Options nosniff always; + add_header X-Frame-Options DENY always; + add_header Referrer-Policy strict-origin-when-cross-origin always; + add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always; + + try_files $uri =404; + } + location / { try_files $uri $uri/ /index.php$is_args$args; } diff --git a/migrations/Version20260930120000.php b/migrations/Version20260930120000.php new file mode 100644 index 00000000..38795dbf --- /dev/null +++ b/migrations/Version20260930120000.php @@ -0,0 +1,43 @@ +connection->getDatabasePlatform() instanceof SqlitePlatform) { + return; + } + + if ($this->connection->getDatabasePlatform() instanceof AbstractMySQLPlatform) { + $this->addSql('ALTER TABLE cards CHANGE lastmodified lastmodified BIGINT DEFAULT NULL'); + } + + if ($this->connection->getDatabasePlatform() instanceof PostgreSQLPlatform) { + $this->addSql('ALTER TABLE cards ALTER COLUMN lastmodified TYPE BIGINT'); + } + } + + public function down(Schema $schema): void + { + // Narrowing back to INT would truncate post-2038 timestamps, like Version20250409193948 + } +} diff --git a/public/.htaccess b/public/.htaccess index 2776637c..11b2a20b 100644 --- a/public/.htaccess +++ b/public/.htaccess @@ -5,6 +5,14 @@ # to each configured DirectoryIndex file (e.g. index.php, index.html, index.pl). DirectoryIndex index.php +# Every URL Davis emits for a static file carries a `?` that changes with the release, so +# a stale copy can never be served: a new release is a new URL. + + + Header set Cache-Control "public, max-age=31536000, immutable" + + + # By default, Apache does not evaluate symbolic links if you did not enable this # feature in your server configuration. Uncomment the following line if you # install assets as symlinks or if you experience problems related to symlinks diff --git a/src/Entity/AddressBook.php b/src/Entity/AddressBook.php index dc208aa7..e631e3eb 100644 --- a/src/Entity/AddressBook.php +++ b/src/Entity/AddressBook.php @@ -27,7 +27,8 @@ class AddressBook private $displayName; #[ORM\Column(type: 'string', length: 255)] - #[Assert\Regex("/[0-9a-z\-]+/")] + #[Assert\NotBlank] + #[Assert\Regex("/^[0-9a-zA-Z_\-]+$/")] #[Assert\Length(max: 255)] private $uri; diff --git a/src/Entity/CalendarInstance.php b/src/Entity/CalendarInstance.php index f53620ad..6df4de64 100644 --- a/src/Entity/CalendarInstance.php +++ b/src/Entity/CalendarInstance.php @@ -41,7 +41,8 @@ public static function getOwnerAccesses(): array private $displayName; #[ORM\Column(type: 'string', length: 255, nullable: true)] - #[Assert\Regex("/[0-9a-z\-]+/")] + #[Assert\NotBlank] + #[Assert\Regex("/^[0-9a-zA-Z_\-]+$/")] #[Assert\Length(max: 255)] private $uri; @@ -52,7 +53,7 @@ public static function getOwnerAccesses(): array private $calendarOrder; #[ORM\Column(name: 'calendarcolor', type: 'string', length: 10, nullable: true)] - #[Assert\Regex("/\#[0-9A-F]{6}/")] + #[Assert\Regex('/^#([0-9A-Fa-f]{3,4}|[0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})$/')] #[Assert\Length(max: 10)] private $calendarColor; diff --git a/src/Entity/Card.php b/src/Entity/Card.php index 20a96de0..8b031d8c 100644 --- a/src/Entity/Card.php +++ b/src/Entity/Card.php @@ -26,7 +26,7 @@ class Card #[ORM\Column(type: 'string', length: 255, nullable: true)] private $uri; - #[ORM\Column(name: 'lastmodified', type: 'integer', nullable: true)] + #[ORM\Column(name: 'lastmodified', type: 'bigint', nullable: true)] private $lastModified; #[ORM\Column(type: 'string', length: 32, nullable: true)] diff --git a/templates/_partials/navigation.html.twig b/templates/_partials/navigation.html.twig index 24dee276..f8264386 100644 --- a/templates/_partials/navigation.html.twig +++ b/templates/_partials/navigation.html.twig @@ -1,7 +1,7 @@