diff --git a/.gitignore b/.gitignore index b7282f4..0ee7cd1 100644 --- a/.gitignore +++ b/.gitignore @@ -38,3 +38,13 @@ bun.lockd public/tmp-sign/*.pdf backup/*.zip backup/*.sql + +###> spomky-labs/pwa-bundle ### +/public/idb +/public/pwa +/public/workbox +/public/favicon.ico +/public/site.webmanifest +/public/site.*.webmanifest +/public/sw.js +###< spomky-labs/pwa-bundle ### diff --git a/ansible/playbook.yml b/ansible/playbook.yml index 9c43b1d..4fd3acc 100644 --- a/ansible/playbook.yml +++ b/ansible/playbook.yml @@ -202,7 +202,11 @@ args: chdir: "{{ path }}" when: ansible_os_family == "Debian" # Added a when condition here, often missed - + - name: Exécuter pwa:compile dans le répertoire de l application + ansible.builtin.command: php -d memory_limit=-1 bin/console pwa:compile + become: false + args: + chdir: "{{ path }}" - name: Set correct permissions for Symfony cache and logs directories ansible.builtin.file: path: "{{ item }}" diff --git a/composer.json b/composer.json index 230749f..66e5bbb 100644 --- a/composer.json +++ b/composer.json @@ -26,7 +26,7 @@ "imagine/imagine": "^1.5.2", "io-developer/php-whois": ">=4.1.10", "knplabs/knp-paginator-bundle": "^6.10", - "knpuniversity/oauth2-client-bundle": "^2.20", + "knpuniversity/oauth2-client-bundle": "^2.20.1", "lasserafn/php-initial-avatar-generator": "^4.5", "league/flysystem-aws-s3-v3": "^3.30.1", "league/flysystem-bundle": "^3.6.1", @@ -43,11 +43,13 @@ "phpoffice/phpspreadsheet": "^5.4", "phpstan/phpdoc-parser": "^2.3.1", "presta/sitemap-bundle": "^4.2", - "scheb/2fa-bundle": "^7.13", - "scheb/2fa-google-authenticator": "^7.13", - "sentry/sentry-symfony": "^5.8", + "scheb/2fa-bundle": "^7.13.1", + "scheb/2fa-google-authenticator": "^7.13.1", + "sentry/sentry-symfony": "^5.8.3", "setasign/fpdi": "^2.6.4", "spatie/mjml-php": "^1.2.5", + "spomky-labs/pwa-bundle": "1.3.5", + "spomky-labs/web-push-bundle": "^3.1", "stancer/stancer": ">=2.0.1", "stevenmaguire/oauth2-keycloak": "^5.1", "symfony/amazon-mailer": "7.3.*", @@ -85,7 +87,8 @@ "twig/intl-extra": "^3.22.1", "twig/twig": "^3.22.2", "vich/uploader-bundle": "^2.9.1", - "web-auth/webauthn-lib": ">=5.2.3" + "web-auth/webauthn-lib": ">=5.2.3", + "web-token/jwt-library": "^4.1" }, "config": { "allow-plugins": { diff --git a/composer.lock b/composer.lock index 06fdc03..1cb9597 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "4ce617f198e010903ec5351925259b10", + "content-hash": "9c1f1c501a3764fad79d4fb69f99c1eb", "packages": [ { "name": "async-aws/core", @@ -187,16 +187,16 @@ }, { "name": "aws/aws-sdk-php", - "version": "3.369.13", + "version": "3.369.14", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "bedc36250c92b8287be855a2d25427fb0e065483" + "reference": "b40eb1177d2e621c18cd797ca6cc9efb5a0e99d9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/bedc36250c92b8287be855a2d25427fb0e065483", - "reference": "bedc36250c92b8287be855a2d25427fb0e065483", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/b40eb1177d2e621c18cd797ca6cc9efb5a0e99d9", + "reference": "b40eb1177d2e621c18cd797ca6cc9efb5a0e99d9", "shasum": "" }, "require": { @@ -278,9 +278,9 @@ "support": { "forum": "https://github.com/aws/aws-sdk-php/discussions", "issues": "https://github.com/aws/aws-sdk-php/issues", - "source": "https://github.com/aws/aws-sdk-php/tree/3.369.13" + "source": "https://github.com/aws/aws-sdk-php/tree/3.369.14" }, - "time": "2026-01-14T19:13:46+00:00" + "time": "2026-01-15T19:10:54+00:00" }, { "name": "bacon/bacon-qr-code", @@ -979,16 +979,16 @@ }, { "name": "doctrine/collections", - "version": "2.5.1", + "version": "2.6.0", "source": { "type": "git", "url": "https://github.com/doctrine/collections.git", - "reference": "171e68db4b9aca9dc1f5d49925762f3d53d248c5" + "reference": "7713da39d8e237f28411d6a616a3dce5e20d5de2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/collections/zipball/171e68db4b9aca9dc1f5d49925762f3d53d248c5", - "reference": "171e68db4b9aca9dc1f5d49925762f3d53d248c5", + "url": "https://api.github.com/repos/doctrine/collections/zipball/7713da39d8e237f28411d6a616a3dce5e20d5de2", + "reference": "7713da39d8e237f28411d6a616a3dce5e20d5de2", "shasum": "" }, "require": { @@ -1045,7 +1045,7 @@ ], "support": { "issues": "https://github.com/doctrine/collections/issues", - "source": "https://github.com/doctrine/collections/tree/2.5.1" + "source": "https://github.com/doctrine/collections/tree/2.6.0" }, "funding": [ { @@ -1061,7 +1061,7 @@ "type": "tidelift" } ], - "time": "2026-01-12T20:53:55+00:00" + "time": "2026-01-15T10:01:58+00:00" }, { "name": "doctrine/dbal", @@ -8767,6 +8767,247 @@ ], "time": "2025-12-20T12:57:40+00:00" }, + { + "name": "spomky-labs/pwa-bundle", + "version": "1.3.5", + "source": { + "type": "git", + "url": "https://github.com/Spomky-Labs/pwa-bundle.git", + "reference": "3530dc2c02544e7f7518d4dfab28b1615630ae27" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Spomky-Labs/pwa-bundle/zipball/3530dc2c02544e7f7518d4dfab28b1615630ae27", + "reference": "3530dc2c02544e7f7518d4dfab28b1615630ae27", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "phpdocumentor/reflection-docblock": "^5.3", + "psr/log": "^1.1|^2.0|^3.0", + "symfony/asset": "^6.4|^7.0", + "symfony/asset-mapper": "^6.4|^7.0", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/deprecation-contracts": "^3.5", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/property-access": "^6.4|^7.0", + "symfony/property-info": "^6.4|^7.0", + "symfony/routing": "^6.4|^7.0", + "symfony/serializer": "^6.4|^7.0", + "symfony/service-contracts": "^3.0", + "twig/twig": "^3.8" + }, + "require-dev": { + "matthiasnoback/symfony-config-test": "^5.1|^6.0", + "nelmio/security-bundle": "^3.0", + "symfony/console": "^7.2", + "symfony/filesystem": "^7.1", + "symfony/framework-bundle": "^6.4|^7.0", + "symfony/mime": "^6.4|^7.0", + "symfony/monolog-bundle": "^3.10", + "symfony/translation": "^7.0", + "symfony/ux-icons": "^2.29", + "symfony/yaml": "^6.4|^7.0" + }, + "suggest": { + "ext-gd": "Required to generate icons (or Imagick).", + "ext-imagick": "Required to generate icons (or GD).", + "symfony/filesystem": "For generating and manipulating icons or screenshots", + "symfony/mime": "For generating and manipulating icons or screenshots", + "symfony/ux-icons": "For using SVG icons (e.g. for shortcuts)" + }, + "type": "symfony-bundle", + "extra": { + "thanks": { + "url": "https://github.com/spomky-labs/pwa-bundle", + "name": "spomky-labs/pwa-bundle" + } + }, + "autoload": { + "psr-4": { + "SpomkyLabs\\PwaBundle\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Florent Morselli", + "homepage": "https://github.com/Spomky" + }, + { + "name": "All contributors", + "homepage": "https://github.com/spomky-labs/pwa-bundle/contributors" + } + ], + "description": "Progressive Web App Manifest Generator Bundle for Symfony.", + "homepage": "https://github.com/spomky-labs", + "keywords": [ + "bundle", + "pwa", + "symfony", + "symfony-ux" + ], + "support": { + "issues": "https://github.com/Spomky-Labs/pwa-bundle/issues", + "source": "https://github.com/Spomky-Labs/pwa-bundle/tree/1.3.5" + }, + "funding": [ + { + "url": "https://www.buymeacoffee.com/FlorentMorselli", + "type": "custom" + }, + { + "url": "https://github.com/Spomky", + "type": "github" + }, + { + "url": "https://www.patreon.com/FlorentMorselli", + "type": "patreon" + } + ], + "time": "2025-10-26T00:12:45+00:00" + }, + { + "name": "spomky-labs/web-push-bundle", + "version": "3.1.2", + "source": { + "type": "git", + "url": "https://github.com/Spomky-Labs/web-push-bundle.git", + "reference": "fb7f93f0d16ca11af296b16a5b5ddad38aed18e6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Spomky-Labs/web-push-bundle/zipball/fb7f93f0d16ca11af296b16a5b5ddad38aed18e6", + "reference": "fb7f93f0d16ca11af296b16a5b5ddad38aed18e6", + "shasum": "" + }, + "require": { + "spomky-labs/web-push-lib": "^3.0", + "symfony/config": "^6.2|^7.0", + "symfony/dependency-injection": "^6.2|^7.0", + "symfony/framework-bundle": "^6.2|^7.0" + }, + "type": "symfony-bundle", + "autoload": { + "psr-4": { + "WebPush\\Bundle\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Spomky-Labs", + "homepage": "https://github.com/Spomky-Labs" + }, + { + "name": "All contributors", + "homepage": "https://github.com/Spomky-Labs/web-push-bundle/contributors" + } + ], + "description": "Web-Push bundle for Symfony", + "homepage": "https://github.com/Spomky-Labs/web-push", + "keywords": [ + "Push API", + "WebPush", + "notifications", + "push", + "web" + ], + "support": { + "source": "https://github.com/Spomky-Labs/web-push-bundle/tree/3.1.2" + }, + "funding": [ + { + "url": "https://github.com/Spomky", + "type": "github" + }, + { + "url": "https://www.patreon.com/FlorentMorselli", + "type": "patreon" + } + ], + "time": "2024-04-11T06:25:37+00:00" + }, + { + "name": "spomky-labs/web-push-lib", + "version": "3.1.2", + "source": { + "type": "git", + "url": "https://github.com/Spomky-Labs/web-push-lib.git", + "reference": "01a88115f4089620988e21f6e49c38f2104ced3f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Spomky-Labs/web-push-lib/zipball/01a88115f4089620988e21f6e49c38f2104ced3f", + "reference": "01a88115f4089620988e21f6e49c38f2104ced3f", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": ">=8.2", + "psr/cache": "^1.0|^2.0|^3.0", + "psr/clock": "^1.0", + "psr/log": "^1.1|^2.0|^3.0", + "symfony/http-kernel": "^6.2|^7.0" + }, + "suggest": { + "ext-mbstring": "Mandatory when using Payload or VAPID extensions", + "ext-openssl": "Mandatory when using Payload or VAPID extensions", + "lcobucci/jwt": "Mandatory if you want to use VAPID using lcobucci/jwt", + "psr/log-implementation": "Recommended to receive logs from the library", + "web-token/jwt-library": "Mandatory if you want to use VAPID using web-token/jwt-framework" + }, + "type": "library", + "autoload": { + "psr-4": { + "WebPush\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Spomky-Labs", + "homepage": "https://github.com/Spomky-Labs" + }, + { + "name": "All contributors", + "homepage": "https://github.com/Spomky-Labs/web-push-lib/contributors" + } + ], + "description": "Web-Push library for PHP", + "homepage": "https://github.com/spomky-labs/web-push", + "keywords": [ + "Push API", + "WebPush", + "notifications", + "push", + "web" + ], + "support": { + "source": "https://github.com/Spomky-Labs/web-push-lib/tree/3.1.2" + }, + "funding": [ + { + "url": "https://github.com/Spomky", + "type": "github" + }, + { + "url": "https://www.patreon.com/FlorentMorselli", + "type": "patreon" + } + ], + "time": "2024-04-11T06:36:56+00:00" + }, { "name": "stancer/stancer", "version": "v2.0.1", diff --git a/config/bundles.php b/config/bundles.php index e55dc6f..23a56ed 100644 --- a/config/bundles.php +++ b/config/bundles.php @@ -21,4 +21,6 @@ return [ KnpU\OAuth2ClientBundle\KnpUOAuth2ClientBundle::class => ['all' => true], Scheb\TwoFactorBundle\SchebTwoFactorBundle::class => ['all' => true], Nelmio\SecurityBundle\NelmioSecurityBundle::class => ['all' => true], + SpomkyLabs\PwaBundle\SpomkyLabsPwaBundle::class => ['all' => true], + WebPush\Bundle\WebPushBundle::class => ['all' => true], ]; diff --git a/config/packages/nelmio_security.yaml b/config/packages/nelmio_security.yaml index 2f32d34..5a3082c 100644 --- a/config/packages/nelmio_security.yaml +++ b/config/packages/nelmio_security.yaml @@ -15,17 +15,20 @@ nelmio_security: # Si tu veux bloquer une fonction pour tout le monde : usb: [] csp: + hash: + algorithm: 'sha256' enforce: default-src: ["'self'"] + worker-src: ["'self'"] script-src: - "'self'" - "nonce" + - "'strict-dynamic'" - "https://sentry.esy-web.dev" - "https://chat.esy-web.dev" - "https://auth.esy-web.dev" - "https://static.cloudflareinsights.com" - "https://challenges.cloudflare.com" - - "'strict-dynamic'" connect-src: - "'self'" - "https://sentry.esy-web.dev" @@ -52,3 +55,4 @@ nelmio_security: frame-ancestors: ["'none'"] # Optionnel : forcer le passage en HTTPS upgrade-insecure-requests: false + diff --git a/config/packages/pwa.yaml b/config/packages/pwa.yaml new file mode 100644 index 0000000..8a2067a --- /dev/null +++ b/config/packages/pwa.yaml @@ -0,0 +1,47 @@ +pwa: + image_processor: 'pwa.image_processor.gd' + favicons: + enabled: true + src: '%kernel.project_dir%/public/provider/images/favicon.png' + + serviceworker: + enabled: true + workbox: + cache_manifest: true + resource_caches: + - match_callback: 'startsWith: /provider/' + cache_name: 'static-pages' + strategy: 'CacheFirst' + + image_cache: + enabled: true + max_age: 3600 + max_entries: 200 + regex: '/\.(png|jpe?g|svg|webp)$/' + font_cache: + enabled: true + max_entries: 10 + max_age: 3600 + google_fonts: + enabled: true + cache_prefix: 'goolge-fonts' + max_entries: 20 + max_age: 3600 + manifest: + enabled: true + name: "Intranet Lukikevent" + short_name: "Intranet" + start_url: "app_home" + display: "standalone" + background_color: "#ffffff" + theme_color: "#f4c842" + scope: "/" + id: "/" + dir: "ltr" + lang: "fr" + orientation: "portrait" + description: "Application Intranet Ludikevent" + categories: ['shopping'] + icons: + - src: '%kernel.project_dir%/public/provider/images/favicon.png' + sizes: [ 192 ] diff --git a/config/packages/webpush.yaml b/config/packages/webpush.yaml new file mode 100644 index 0000000..e5d9192 --- /dev/null +++ b/config/packages/webpush.yaml @@ -0,0 +1,17 @@ +webpush: + payload: + aesgcm: + cache: Psr\Cache\CacheItemPoolInterface + cache_lifetime: '+1 hour' #Default: now +30min + aes128gcm: + cache: Psr\Cache\CacheItemPoolInterface + cache_lifetime: '+1 hour' #Default: now +30min + logger: Psr\Log\LoggerInterface + vapid: + enabled: true # Enable the feature + subject: '%env(DEFAULT_URI)%' + token_lifetime: 'now +2 hours' + web_token: + enabled: true # We use web-token in this example + public_key: 'BGMEBoSFbdvggeiTJ4eX64iNDhrxKj3B5RzJ1CYG6IpMazmlgwFxgKE8SKhsDz4pzhrP9qDhWj-o84NPoqaijyg' + private_key: 'wKuTIzpONJ46kvuwaRLIjd7qKWCAiEKqbxSxU' diff --git a/importmap.php b/importmap.php index b73b323..0e268a0 100644 --- a/importmap.php +++ b/importmap.php @@ -25,4 +25,13 @@ return [ '@hotwired/turbo' => [ 'version' => '7.3.0', ], + 'idb' => [ + 'version' => '8.0.3', + ], + 'idb-keyval' => [ + 'version' => '6.2.2', + ], + '@spomky-labs/pwa/helpers' => [ + 'path' => './vendor/spomky-labs/pwa-bundle/assets/src/helpers.js', + ], ]; diff --git a/public/apple-touch-icon.png b/public/apple-touch-icon.png deleted file mode 100644 index 37f7e6f..0000000 Binary files a/public/apple-touch-icon.png and /dev/null differ diff --git a/public/assets/images/logo (2).png:Zone.Identifier b/public/assets/images/logo (2).png:Zone.Identifier deleted file mode 100644 index d6c1ec6..0000000 Binary files a/public/assets/images/logo (2).png:Zone.Identifier and /dev/null differ diff --git a/public/favicon-96x96.png b/public/favicon-96x96.png deleted file mode 100644 index aa79987..0000000 Binary files a/public/favicon-96x96.png and /dev/null differ diff --git a/public/favicon.ico b/public/favicon.ico deleted file mode 100644 index d80381a..0000000 Binary files a/public/favicon.ico and /dev/null differ diff --git a/public/favicon.svg b/public/favicon.svg deleted file mode 100644 index 4fa314f..0000000 --- a/public/favicon.svg +++ /dev/null @@ -1,3 +0,0 @@ - \ No newline at end of file diff --git a/public/provider/images/favicon.png b/public/provider/images/favicon.png new file mode 100644 index 0000000..039481e Binary files /dev/null and b/public/provider/images/favicon.png differ diff --git a/public/assets/images/logo.png b/public/provider/images/logo.png similarity index 100% rename from public/assets/images/logo.png rename to public/provider/images/logo.png diff --git a/public/site.webmanifest b/public/site.webmanifest deleted file mode 100644 index dbb772b..0000000 --- a/public/site.webmanifest +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "Intranet ", - "short_name": "Intranet ", - "icons": [ - { - "src": "/web-app-manifest-192x192.png", - "sizes": "192x192", - "type": "image/png", - "purpose": "maskable" - }, - { - "src": "/web-app-manifest-512x512.png", - "sizes": "512x512", - "type": "image/png", - "purpose": "maskable" - } - ], - "theme_color": "#505458", - "background_color": "#505458", - "display": "standalone" -} \ No newline at end of file diff --git a/public/web-app-manifest-192x192.png b/public/web-app-manifest-192x192.png deleted file mode 100644 index 81a0726..0000000 Binary files a/public/web-app-manifest-192x192.png and /dev/null differ diff --git a/public/web-app-manifest-512x512.png b/public/web-app-manifest-512x512.png deleted file mode 100644 index 38b5de6..0000000 Binary files a/public/web-app-manifest-512x512.png and /dev/null differ diff --git a/symfony.lock b/symfony.lock index 6022a4f..f833676 100644 --- a/symfony.lock +++ b/symfony.lock @@ -167,6 +167,21 @@ "config/packages/sentry.yaml" ] }, + "spomky-labs/pwa-bundle": { + "version": "1.4", + "recipe": { + "repo": "github.com/symfony/recipes-contrib", + "branch": "main", + "version": "1.3", + "ref": "ac33d9498ab25856f16d1d7df9ad4b9b0cad066d" + }, + "files": [ + "config/packages/pwa.yaml" + ] + }, + "spomky-labs/web-push-bundle": { + "version": "3.1.2" + }, "symfony/amazon-mailer": { "version": "7.3", "recipe": { diff --git a/templates/base.twig b/templates/base.twig index e926400..7189371 100644 --- a/templates/base.twig +++ b/templates/base.twig @@ -9,12 +9,9 @@ {{ vite_asset('app.js', []) }} - - - - - - + + {{ pwa() }} + {# Le corps aura un fond gris clair pour correspondre au fond du logo #} diff --git a/templates/dashboard/base.twig b/templates/dashboard/base.twig index c82ee03..dac23b6 100644 --- a/templates/dashboard/base.twig +++ b/templates/dashboard/base.twig @@ -5,12 +5,7 @@ {% block title %}Administration{% endblock %} — Intranet Ludikevent {{ vite_asset('admin.js', {}) }} - - - - - - + {{ pwa(swAttributes={ 'nonce': csp_nonce('script') }) }}