diff --git a/.env b/.env index c07a872..24cea0d 100644 --- a/.env +++ b/.env @@ -67,3 +67,7 @@ GOOGLE_APPLICATION_CREDENTIALS=%kernel.project_dir%/google.json SENTRY_DSN="" ###< sentry/sentry-symfony ### DEFAULT_URI=https://esyweb.local +KEYCLOAK_AUTH_SERVER_URL=https://auth.esy-web.dev +KEYCLOAK_REALM=master +KEYCLOAK_CLIENT_ID=ludikevent +KEYCLOAK_CLIENT_SECRET=FA7ue4h6rKL0bFZSEXxoZ4uh5LIohsyd diff --git a/.gitea/workflows/install-deps.yml b/.gitea/workflows/install-deps.yml new file mode 100644 index 0000000..2f91076 --- /dev/null +++ b/.gitea/workflows/install-deps.yml @@ -0,0 +1,34 @@ +# Nom du workflow +name: Symfony CI - Install, Test, Build, Attest & Deploy + +# Déclencheurs du workflow +on: + push: + branches: + - master # Ou 'main' + pull_request: + types: [opened, synchronize, reopened] + branches: + - master # Ou 'main' + +# Permissions nécessaires pour les actions utilisées +permissions: + contents: read + pull-requests: write + id-token: write + attestations: write + security-events: write # Requis pour Snyk pour poster les résultats + +jobs: + deploy: + name: 🚀 Deploy to Production + steps: + - name: Deploy with SSH & Ansible + uses: appleboy/ssh-action@v1.0.0 + with: + host: ${{ secrets.SSH_HOST }} + username: ${{ secrets.SSH_USER }} + key: ${{ secrets.SSH_PRIVATE_KEY }} + port: 22 + script: | + cd /var/www/ludikevent-intranet && git pull && nohup sh ./update.sh diff --git a/ansible/hosts.ini b/ansible/hosts.ini new file mode 100644 index 0000000..73b3127 --- /dev/null +++ b/ansible/hosts.ini @@ -0,0 +1,2 @@ +[webservers] +127.0.0.1 ansible_connection=local ansible_python_interpreter=/usr/bin/python3 path=/var/www/ludikevent-intranet diff --git a/ansible/playbook.yml b/ansible/playbook.yml new file mode 100644 index 0000000..96eabc9 --- /dev/null +++ b/ansible/playbook.yml @@ -0,0 +1,220 @@ +# Fichier: install_php_83_symfony_pgsql.yml + +- name: Deploy application + hosts: webservers + become: true + gather_facts: true + + vars: + db_name: "ludikevent" + db_user: "ludikevent" + db_password: "ludikevent" + redis_password: "ludikevent" + redis_port: "20110" + # Assurez-vous que 'path' est définie dans votre inventaire ou comme extra-var + # Exemple: path: /var/www/mainframe/app + + tasks: + - name: Exécuter 'composer install' dans le répertoire de l'application + ansible.builtin.command: composer install --no-dev --optimize-autoloader + become: false # Run as the connection user (e.g., 'bot') + args: + chdir: "{{ path }}" + when: ansible_os_family == "Debian" + - name: Send a message to the Discord channel + community.general.discord: + webhook_id: "1419573620602044518" + webhook_token: "ikAdxWxsrrTqMTb5Gh_8ylcoJHlOnq7aJZvR5udoS_fCK56Jk3qpEnJHVKdD8fwuNJF3" + content: "Mise à jour du intranet ludikevent" + + - name: Installer le support ACL pour corriger les permissions de 'become_user' + ansible.builtin.apt: + name: acl + state: present + update_cache: true + when: ansible_os_family == "Debian" + + - name: Installation des dépendances pour le module Ansible PostgreSQL + ansible.builtin.apt: + name: python3-psycopg2 + state: present + update_cache: true + when: ansible_os_family == "Debian" + + - name: Installation de PHP 8.3 et PHP 8.3-FPM avec les dépendances + ansible.builtin.apt: + name: + - php8.3 + - php8.3-fpm + - php8.3-cli + - php8.3-common + - php8.3-mysql + - php8.3-pgsql + - php8.3-xml + - php8.3-mbstring + - php8.3-zip + - php8.3-intl + - php8.3-gd + - php8.3-curl + - php8.3-pdo + - php8.3-opcache + - php8.3-bcmath + - php8.3-redis + - php8.3-imagick + - ffmpeg + state: present + when: ansible_os_family == "Debian" + + - name: Démarrage et activation du service PHP 8.3 FPM + ansible.builtin.systemd: + name: php8.3-fpm + state: started + enabled: yes + when: ansible_os_family == "Debian" + + - name: Créer le fichier .env.local avec les secrets de production + ansible.builtin.copy: + content: | + APP_ENV=prod + VITE_LOAD=1 + DATABASE_URL="postgresql://{{ db_user }}:{{ db_password }}@127.0.0.1:5432/{{ db_name }}?serverVersion=16&charset=utf8" + REDIS_DSN="redis://{{ redis_password }}@127.0.0.1:{{ redis_port }}" + REDIS_URL="redis://{{ redis_password }}@127.0.0.1:{{ redis_port }}" + MESSENGER_TRANSPORT_DSN="redis://{{ redis_password }}@127.0.0.1:{{ redis_port }}/messages" + APP_SECRET=939bbc67038c2e2d1232d86fc605bf2f + REAL_MAIL=1 + VAULT_ADDR=http://127.0.0.1:8200 + VAULT_TOKEN=hvs.QLpUdiptXtSPo5Qf7i2nn2Xz + MAILER_DSN=ses+smtp://AKIAWTT2T22CWBRBBDYN:BBdgb6KxRQ8mNcpWFJsZCJxbSGNdgLhKFiITMErfBlQP@default?region=eu-west-3 + + dest: "{{ path }}/.env.local" + when: ansible_os_family == "Debian" + + # --- Initial creation of essential directories with correct ownership --- + # These directories should exist before composer runs, but composer might create subdirs. + - name: Ensure app/var and public/media directories exist with correct owner/group + ansible.builtin.file: + path: "{{ item }}" + owner: bot # Assuming 'bot' is your deployment user + group: www-data + mode: '0775' # Allow 'bot' and 'www-data' to read/write/execute + state: directory + recurse: yes # Important to ensure subdirectories created by previous deploys also get permissions + loop: + - "{{ path }}/var" + - "{{ path }}/var/log" # Specific for log, though var/log might be created by composer later + - "{{ path }}/public/media" # For uploads + - "{{ path }}/public/storage" # For uploads + - "{{ path }}/public/tmp-sign" # For uploads + + # --- POST-COMPOSER PERMISSION FIXES --- + # This is crucial because composer creates var/cache as the `become: false` user + - name: Set correct permissions for Symfony cache and logs directories + ansible.builtin.file: + path: "{{ item }}" + owner: bot + group: www-data + mode: '0775' # rwx for owner and group, rx for others + state: directory + recurse: yes # Apply to all contents + loop: + - "{{ path }}/var/cache" + - "{{ path }}/var/log" + # For web-writable directories created by the app itself (e.g., uploads), you might set ACLs + # or chown to www-data and then your user gets access via group membership. + + # Alternative for cache/log permissions using ACLs (more robust for mixed ownership) + # This requires 'acl' package installed (which you already do). + # Use this if 'bot' needs to own, but www-data needs to write. + - name: Set ACLs for Symfony cache and logs (recommended for web-writable dirs) + ansible.builtin.acl: + path: "{{ item }}" + entity: www-data + etype: group + permissions: rwx + state: present + recursive: yes + default: yes # Apply default ACLs for new files/dirs within + loop: + - "{{ path }}/var/cache" + - "{{ path }}/var/log" + when: ansible_os_family == "Debian" # ACLs are Linux-specific + + - name: Exécuter bun install dans le répertoire de l application + ansible.builtin.command: bun install + become: false + args: + chdir: "{{ path }}" + when: ansible_os_family == "Debian" + + - name: Exécuter bun build dans le répertoire de l application + ansible.builtin.command: bun run build + become: false + args: + chdir: "{{ path }}" + when: ansible_os_family == "Debian" + + - name: Supervisor config + ansible.builtin.template: + src: supervisor.j2 + dest: "/etc/supervisor/conf.d/mainframe.conf" + mode: '0644' + + - name: Reread Supervisor configuration + ansible.builtin.command: supervisorctl reread + changed_when: true # Always mark as changed, as output is not always useful for idempotency + + - name: Update Supervisor (add/remove updated programs) + ansible.builtin.command: supervisorctl update + changed_when: true + + - name: Purger la base de données Redis + ansible.builtin.command: "redis-cli -p {{ redis_port }} -a {{ redis_password }} FLUSHALL" + when: ansible_os_family == "Debian" + + - name: Generate Caddy site configuration + ansible.builtin.template: + src: caddy.j2 + dest: "/etc/caddy/sites/mainframe.conf" + mode: '0644' + + - name: Reload Caddy to apply new configuration + ansible.builtin.systemd: + name: caddy + state: reloaded + enabled: yes + - name: Exécuter doctrine:migration:migrate dans le répertoire de l application + ansible.builtin.command: php bin/console doctrine:migrations:migrate --no-interaction + become: false + args: + chdir: "{{ path }}" + when: ansible_os_family == "Debian" + - name: Exécuter cache:clear dans le répertoire de l application + ansible.builtin.command: php bin/console cache:clear + become: false + args: + chdir: "{{ path }}" + when: ansible_os_family == "Debian" + + - name: Exécuter liip:imagine:cache:remove dans le répertoire de l application + ansible.builtin.command: php bin/console liip:imagine:cache:remove + become: false + args: + chdir: "{{ path }}" + when: ansible_os_family == "Debian" # Added a when condition here, often missed + + - name: Set correct permissions for Symfony cache and logs directories + ansible.builtin.file: + path: "{{ item }}" + owner: bot + group: www-data + mode: '0777' # rwx for owner and group, rx for others + state: directory + recurse: yes # Apply to all contents + loop: + - "{{ path }}/var/cache" + - "{{ path }}/var/log" + - "{{ path }}/public/media" + - "{{ path }}/public/storage" # For uploads + - "{{ path }}/public/tmp-sign" # For uploads + diff --git a/ansible/templates/caddy.j2 b/ansible/templates/caddy.j2 new file mode 100644 index 0000000..aa1d776 --- /dev/null +++ b/ansible/templates/caddy.j2 @@ -0,0 +1,21 @@ +intranet.ludikevent.fr{ + tls { + dns cloudflare KL6pZ-Z_12_zbnM2TtFDIsKM8A-HLPhU5GJJbKTW + } + root * {{ path }}/public + + file_server + request_body { + max_size 100MB + } + header { + Permissions-Policy "accelerometer=(), autoplay=(), camera=(), clipboard-write=(), encrypted-media=(), fullscreen=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), midi=(), payment=(), picture-in-picture=(), publickey-credentials-get=(), usb=(), vr=(), screen-wake-lock=(), xr-spatial-tracking=(), bluetooth=(), ambient-light-sensor=(), battery=(), gamepad=(), notifications=(), push=()" + } + + php_fastcgi unix//run/php/php8.3-fpm.sock { + read_timeout 300s + write_timeout 300s + dial_timeout 100s + env HTTP_PROXY "" + } +} diff --git a/ansible/templates/supervisor.j2 b/ansible/templates/supervisor.j2 new file mode 100644 index 0000000..1c44fcb --- /dev/null +++ b/ansible/templates/supervisor.j2 @@ -0,0 +1,17 @@ +[program:redis_ludikevent_intranet] +command=redis-server --port {{ redis_port }} --requirepass {{ redis_password }} +autostart=true +autorestart=true +user=root +stdout_logfile=/var/www/ludikevent-intranet/var/log/redis_stdout.log +stderr_logfile=/var/www/ludikevent-intranet/var/log/redis_stderr.log + +[program:messenger_redis_ludikevent_intranet] +command=php {{path}}/bin/console messenger:consume async --time-limit=3600 +autostart=true +autorestart=true +user=root +startsecs=0 +startretries=10 +stdout_logfile=/var/www/ludikevent-intranet/var/log/messenger_stderr.log +stderr_logfile=/var/www/ludikevent-intranet/var/log/messenger_stdout.log diff --git a/composer.json b/composer.json index 5c8f742..d59e937 100644 --- a/composer.json +++ b/composer.json @@ -11,40 +11,42 @@ "ext-libxml": "*", "ext-zip": "*", "chillerlan/php-qrcode": ">=5.0.5", - "cocur/slugify": ">=4.6", - "doctrine/dbal": "^3.10.3", - "doctrine/doctrine-bundle": "^2.18.1", + "cocur/slugify": ">=4.7.1", + "doctrine/dbal": "^3.10.4", + "doctrine/doctrine-bundle": "^2.18.2", "doctrine/doctrine-migrations-bundle": "^3.7.0", - "doctrine/orm": "^3.5.7", + "doctrine/orm": "^3.6.1", "docusealco/docuseal-php": "^1.0.5", "endroid/qr-code": ">=6.0.9", "exbil/mailcow-php-api": ">=0.15.0", - "fpdf/fpdf": ">=1.86", - "google/apiclient": "^2.18.4", + "fpdf/fpdf": ">=1.86.1", + "google/apiclient": "^2.19.0", "google/cloud": "^0.296.0", "healey/robots": "^1.0.1", - "imagine/imagine": "^1.5", + "imagine/imagine": "^1.5.2", "io-developer/php-whois": ">=4.1.10", - "knplabs/knp-paginator-bundle": "^6.9.1", + "knplabs/knp-paginator-bundle": "^6.10.0", + "knpuniversity/oauth2-client-bundle": "^2.20", "lasserafn/php-initial-avatar-generator": "^4.5", "league/flysystem-aws-s3-v3": "^3.30.1", - "league/flysystem-bundle": "^3.6", + "league/flysystem-bundle": "^3.6.1", "liip/imagine-bundle": "^2.15", "lufiipe/insee-sierene": ">=1", - "minishlink/web-push": "^9.0.3", + "minishlink/web-push": "^9.0.4", "mittwald/vault-php": "^3.0.2", - "mobiledetect/mobiledetectlib": "^4.8.09", - "nelmio/cors-bundle": "^2.6", + "mobiledetect/mobiledetectlib": "^4.8.10", + "nelmio/cors-bundle": "^2.6.1", "ovh/ovh": ">=3.5", "pear/net_dns2": ">=2.0.7", - "phpdocumentor/reflection-docblock": "^5.6.4", - "phpoffice/phpspreadsheet": ">=5.3", - "phpstan/phpdoc-parser": "^2.3", + "phpdocumentor/reflection-docblock": "^5.6.6", + "phpoffice/phpspreadsheet": ">=5.4", + "phpstan/phpdoc-parser": "^2.3.1", "presta/sitemap-bundle": "^4.2", - "sentry/sentry-symfony": "^5.6", + "sentry/sentry-symfony": "^5.8.3", "setasign/fpdi": "^2.6.4", "spatie/mjml-php": "^1.2.5", "stancer/stancer": ">=2.0.1", + "stevenmaguire/oauth2-keycloak": "^5.1", "symfony/amazon-mailer": "7.3.*", "symfony/asset": "7.3.*", "symfony/asset-mapper": "7.3.*", @@ -59,7 +61,7 @@ "symfony/intl": "7.3.*", "symfony/mailer": "7.3.*", "symfony/mime": "7.3.*", - "symfony/monolog-bundle": "^3.10", + "symfony/monolog-bundle": "^3.11.1", "symfony/notifier": "7.3.*", "symfony/process": "7.3.*", "symfony/property-access": "7.3.*", @@ -76,11 +78,11 @@ "symfony/web-link": "7.3.*", "symfony/yaml": "7.3.*", "tecnickcom/tcpdf": "^6.10.1", - "twig/extra-bundle": "^3.22.1", + "twig/extra-bundle": "^3.22.2", "twig/intl-extra": "^3.22.1", - "twig/twig": "^3.22", - "vich/uploader-bundle": "^2.8.1", - "web-auth/webauthn-lib": ">=5.2.2" + "twig/twig": "^3.22.2", + "vich/uploader-bundle": "^2.9.1", + "web-auth/webauthn-lib": ">=5.2.3" }, "config": { "allow-plugins": { @@ -135,12 +137,12 @@ }, "require-dev": { "fakerphp/faker": "^1.24.1", - "phpunit/phpunit": "^12.4.4", - "rector/rector": "^2.2.8", + "phpunit/phpunit": "^12.5.5", + "rector/rector": "^2.3.1", "symfony/browser-kit": "7.3.*", "symfony/css-selector": "7.3.*", "symfony/debug-bundle": "7.3.*", - "symfony/maker-bundle": "^1.65", + "symfony/maker-bundle": "^1.65.1", "symfony/stopwatch": "7.3.*", "symfony/web-profiler-bundle": "7.3.*" } diff --git a/composer.lock b/composer.lock index 2b72345..f609957 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": "4ab8febdfe6b7b880d54cd11845803da", + "content-hash": "bd9ebbc9c455efb1ac19197eaf03b368", "packages": [ { "name": "async-aws/core", @@ -187,16 +187,16 @@ }, { "name": "aws/aws-sdk-php", - "version": "3.366.3", + "version": "3.369.13", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "11d27829df69c67506d15e6b057ed928b88c4f05" + "reference": "bedc36250c92b8287be855a2d25427fb0e065483" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/11d27829df69c67506d15e6b057ed928b88c4f05", - "reference": "11d27829df69c67506d15e6b057ed928b88c4f05", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/bedc36250c92b8287be855a2d25427fb0e065483", + "reference": "bedc36250c92b8287be855a2d25427fb0e065483", "shasum": "" }, "require": { @@ -210,7 +210,7 @@ "mtdowling/jmespath.php": "^2.8.0", "php": ">=8.1", "psr/http-message": "^1.0 || ^2.0", - "symfony/filesystem": "^v6.4.3 || ^v7.1.0 || ^v8.0.0" + "symfony/filesystem": "^v5.4.45 || ^v6.4.3 || ^v7.1.0 || ^v8.0.0" }, "require-dev": { "andrewsville/php-token-reflection": "^1.4", @@ -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.366.3" + "source": "https://github.com/aws/aws-sdk-php/tree/3.369.13" }, - "time": "2025-12-08T19:11:08+00:00" + "time": "2026-01-14T19:13:46+00:00" }, { "name": "bacon/bacon-qr-code", @@ -339,25 +339,25 @@ }, { "name": "brick/math", - "version": "0.13.1", + "version": "0.14.1", "source": { "type": "git", "url": "https://github.com/brick/math.git", - "reference": "fc7ed316430118cc7836bf45faff18d5dfc8de04" + "reference": "f05858549e5f9d7bb45875a75583240a38a281d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/brick/math/zipball/fc7ed316430118cc7836bf45faff18d5dfc8de04", - "reference": "fc7ed316430118cc7836bf45faff18d5dfc8de04", + "url": "https://api.github.com/repos/brick/math/zipball/f05858549e5f9d7bb45875a75583240a38a281d0", + "reference": "f05858549e5f9d7bb45875a75583240a38a281d0", "shasum": "" }, "require": { - "php": "^8.1" + "php": "^8.2" }, "require-dev": { "php-coveralls/php-coveralls": "^2.2", - "phpunit/phpunit": "^10.1", - "vimeo/psalm": "6.8.8" + "phpstan/phpstan": "2.1.22", + "phpunit/phpunit": "^11.5" }, "type": "library", "autoload": { @@ -387,7 +387,7 @@ ], "support": { "issues": "https://github.com/brick/math/issues", - "source": "https://github.com/brick/math/tree/0.13.1" + "source": "https://github.com/brick/math/tree/0.14.1" }, "funding": [ { @@ -395,7 +395,7 @@ "type": "github" } ], - "time": "2025-03-29T13:50:30+00:00" + "time": "2025-11-24T14:40:29+00:00" }, { "name": "carbonphp/carbon-doctrine-types", @@ -907,16 +907,16 @@ }, { "name": "doctrine/collections", - "version": "2.4.0", + "version": "2.5.1", "source": { "type": "git", "url": "https://github.com/doctrine/collections.git", - "reference": "9acfeea2e8666536edff3d77c531261c63680160" + "reference": "171e68db4b9aca9dc1f5d49925762f3d53d248c5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/collections/zipball/9acfeea2e8666536edff3d77c531261c63680160", - "reference": "9acfeea2e8666536edff3d77c531261c63680160", + "url": "https://api.github.com/repos/doctrine/collections/zipball/171e68db4b9aca9dc1f5d49925762f3d53d248c5", + "reference": "171e68db4b9aca9dc1f5d49925762f3d53d248c5", "shasum": "" }, "require": { @@ -973,7 +973,7 @@ ], "support": { "issues": "https://github.com/doctrine/collections/issues", - "source": "https://github.com/doctrine/collections/tree/2.4.0" + "source": "https://github.com/doctrine/collections/tree/2.5.1" }, "funding": [ { @@ -989,7 +989,7 @@ "type": "tidelift" } ], - "time": "2025-10-25T09:18:13+00:00" + "time": "2026-01-12T20:53:55+00:00" }, { "name": "doctrine/dbal", @@ -1155,16 +1155,16 @@ }, { "name": "doctrine/doctrine-bundle", - "version": "2.18.1", + "version": "2.18.2", "source": { "type": "git", "url": "https://github.com/doctrine/DoctrineBundle.git", - "reference": "b769877014de053da0e5cbbb63d0ea2f3b2fea76" + "reference": "0ff098b29b8b3c68307c8987dcaed7fd829c6546" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/DoctrineBundle/zipball/b769877014de053da0e5cbbb63d0ea2f3b2fea76", - "reference": "b769877014de053da0e5cbbb63d0ea2f3b2fea76", + "url": "https://api.github.com/repos/doctrine/DoctrineBundle/zipball/0ff098b29b8b3c68307c8987dcaed7fd829c6546", + "reference": "0ff098b29b8b3c68307c8987dcaed7fd829c6546", "shasum": "" }, "require": { @@ -1256,7 +1256,7 @@ ], "support": { "issues": "https://github.com/doctrine/DoctrineBundle/issues", - "source": "https://github.com/doctrine/DoctrineBundle/tree/2.18.1" + "source": "https://github.com/doctrine/DoctrineBundle/tree/2.18.2" }, "funding": [ { @@ -1272,7 +1272,7 @@ "type": "tidelift" } ], - "time": "2025-11-05T14:42:10+00:00" + "time": "2025-12-20T21:35:32+00:00" }, { "name": "doctrine/doctrine-migrations-bundle", @@ -1792,16 +1792,16 @@ }, { "name": "doctrine/orm", - "version": "3.5.8", + "version": "3.6.1", "source": { "type": "git", "url": "https://github.com/doctrine/orm.git", - "reference": "78dd074266e8b47a83bcf60ab5fe06c91a639168" + "reference": "2148940290e4c44b9101095707e71fb590832fa5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/orm/zipball/78dd074266e8b47a83bcf60ab5fe06c91a639168", - "reference": "78dd074266e8b47a83bcf60ab5fe06c91a639168", + "url": "https://api.github.com/repos/doctrine/orm/zipball/2148940290e4c44b9101095707e71fb590832fa5", + "reference": "2148940290e4c44b9101095707e71fb590832fa5", "shasum": "" }, "require": { @@ -1874,9 +1874,9 @@ ], "support": { "issues": "https://github.com/doctrine/orm/issues", - "source": "https://github.com/doctrine/orm/tree/3.5.8" + "source": "https://github.com/doctrine/orm/tree/3.6.1" }, - "time": "2025-11-29T23:11:02+00:00" + "time": "2026-01-09T05:28:15+00:00" }, { "name": "doctrine/persistence", @@ -2393,20 +2393,20 @@ }, { "name": "google/apiclient", - "version": "v2.18.4", + "version": "v2.19.0", "source": { "type": "git", "url": "https://github.com/googleapis/google-api-php-client.git", - "reference": "5b51fdb2cbd2a96088e3dfc6f565bdf6fb0af94b" + "reference": "b18fa8aed7b2b2dd4bcce74e2c7d267e16007ea9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/googleapis/google-api-php-client/zipball/5b51fdb2cbd2a96088e3dfc6f565bdf6fb0af94b", - "reference": "5b51fdb2cbd2a96088e3dfc6f565bdf6fb0af94b", + "url": "https://api.github.com/repos/googleapis/google-api-php-client/zipball/b18fa8aed7b2b2dd4bcce74e2c7d267e16007ea9", + "reference": "b18fa8aed7b2b2dd4bcce74e2c7d267e16007ea9", "shasum": "" }, "require": { - "firebase/php-jwt": "^6.0", + "firebase/php-jwt": "^6.0||^7.0", "google/apiclient-services": "~0.350", "google/auth": "^1.37", "guzzlehttp/guzzle": "^7.4.5", @@ -2456,22 +2456,22 @@ ], "support": { "issues": "https://github.com/googleapis/google-api-php-client/issues", - "source": "https://github.com/googleapis/google-api-php-client/tree/v2.18.4" + "source": "https://github.com/googleapis/google-api-php-client/tree/v2.19.0" }, - "time": "2025-09-30T04:23:07+00:00" + "time": "2026-01-09T19:59:47+00:00" }, { "name": "google/apiclient-services", - "version": "v0.423.0", + "version": "v0.428.0", "source": { "type": "git", "url": "https://github.com/googleapis/google-api-php-client-services.git", - "reference": "c8f2e8a92e2848987db421175eaaf7602ef30c33" + "reference": "94a3c50a80a36cafb76e32fb76b8007e9f572deb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/googleapis/google-api-php-client-services/zipball/c8f2e8a92e2848987db421175eaaf7602ef30c33", - "reference": "c8f2e8a92e2848987db421175eaaf7602ef30c33", + "url": "https://api.github.com/repos/googleapis/google-api-php-client-services/zipball/94a3c50a80a36cafb76e32fb76b8007e9f572deb", + "reference": "94a3c50a80a36cafb76e32fb76b8007e9f572deb", "shasum": "" }, "require": { @@ -2500,26 +2500,26 @@ ], "support": { "issues": "https://github.com/googleapis/google-api-php-client-services/issues", - "source": "https://github.com/googleapis/google-api-php-client-services/tree/v0.423.0" + "source": "https://github.com/googleapis/google-api-php-client-services/tree/v0.428.0" }, - "time": "2025-12-08T01:10:26+00:00" + "time": "2026-01-12T00:58:26+00:00" }, { "name": "google/auth", - "version": "v1.49.0", + "version": "v1.50.0", "source": { "type": "git", "url": "https://github.com/googleapis/google-auth-library-php.git", - "reference": "68e3d88cb59a49f713e3db25d4f6bb3cc0b70764" + "reference": "e1c26a718198e16d8a3c69b1cae136b73f959b0f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/googleapis/google-auth-library-php/zipball/68e3d88cb59a49f713e3db25d4f6bb3cc0b70764", - "reference": "68e3d88cb59a49f713e3db25d4f6bb3cc0b70764", + "url": "https://api.github.com/repos/googleapis/google-auth-library-php/zipball/e1c26a718198e16d8a3c69b1cae136b73f959b0f", + "reference": "e1c26a718198e16d8a3c69b1cae136b73f959b0f", "shasum": "" }, "require": { - "firebase/php-jwt": "^6.0", + "firebase/php-jwt": "^6.0||^7.0", "guzzlehttp/guzzle": "^7.4.5", "guzzlehttp/psr7": "^2.4.5", "php": "^8.1", @@ -2529,7 +2529,7 @@ }, "require-dev": { "guzzlehttp/promises": "^2.0", - "kelvinmo/simplejwt": "0.7.1", + "kelvinmo/simplejwt": "^1.1.0", "phpseclib/phpseclib": "^3.0.35", "phpspec/prophecy-phpunit": "^2.1", "phpunit/phpunit": "^9.6", @@ -2537,7 +2537,7 @@ "squizlabs/php_codesniffer": "^4.0", "symfony/filesystem": "^6.3||^7.3", "symfony/process": "^6.0||^7.0", - "webmozart/assert": "^1.11" + "webmozart/assert": "^1.11||^2.0" }, "suggest": { "phpseclib/phpseclib": "May be used in place of OpenSSL for signing strings or for token management. Please require version ^2." @@ -2562,9 +2562,9 @@ "support": { "docs": "https://cloud.google.com/php/docs/reference/auth/latest", "issues": "https://github.com/googleapis/google-auth-library-php/issues", - "source": "https://github.com/googleapis/google-auth-library-php/tree/v1.49.0" + "source": "https://github.com/googleapis/google-auth-library-php/tree/v1.50.0" }, - "time": "2025-11-06T21:27:55+00:00" + "time": "2026-01-08T21:33:57+00:00" }, { "name": "google/cloud", @@ -3426,16 +3426,16 @@ }, { "name": "google/protobuf", - "version": "v4.33.2", + "version": "v4.33.4", "source": { "type": "git", "url": "https://github.com/protocolbuffers/protobuf-php.git", - "reference": "fbd96b7bf1343f4b0d8fb358526c7ba4d72f1318" + "reference": "22d28025cda0d223a2e48c2e16c5284ecc9f5402" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/protocolbuffers/protobuf-php/zipball/fbd96b7bf1343f4b0d8fb358526c7ba4d72f1318", - "reference": "fbd96b7bf1343f4b0d8fb358526c7ba4d72f1318", + "url": "https://api.github.com/repos/protocolbuffers/protobuf-php/zipball/22d28025cda0d223a2e48c2e16c5284ecc9f5402", + "reference": "22d28025cda0d223a2e48c2e16c5284ecc9f5402", "shasum": "" }, "require": { @@ -3464,9 +3464,9 @@ "proto" ], "support": { - "source": "https://github.com/protocolbuffers/protobuf-php/tree/v4.33.2" + "source": "https://github.com/protocolbuffers/protobuf-php/tree/v4.33.4" }, - "time": "2025-12-05T22:12:22+00:00" + "time": "2026-01-12T17:58:43+00:00" }, { "name": "grpc/grpc", @@ -3877,16 +3877,16 @@ }, { "name": "illuminate/collections", - "version": "v12.42.0", + "version": "v12.47.0", "source": { "type": "git", "url": "https://github.com/illuminate/collections.git", - "reference": "16657effa6a5a4e728f9aeb3e38fb4fa9ba70e7d" + "reference": "d3f104a32fdfbf416cd1a839dad0e2c670a03f4e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/collections/zipball/16657effa6a5a4e728f9aeb3e38fb4fa9ba70e7d", - "reference": "16657effa6a5a4e728f9aeb3e38fb4fa9ba70e7d", + "url": "https://api.github.com/repos/illuminate/collections/zipball/d3f104a32fdfbf416cd1a839dad0e2c670a03f4e", + "reference": "d3f104a32fdfbf416cd1a839dad0e2c670a03f4e", "shasum": "" }, "require": { @@ -3894,6 +3894,7 @@ "illuminate/contracts": "^12.0", "illuminate/macroable": "^12.0", "php": "^8.2", + "symfony/polyfill-php83": "^1.33", "symfony/polyfill-php84": "^1.33", "symfony/polyfill-php85": "^1.33" }, @@ -3932,11 +3933,11 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2025-12-06T18:08:25+00:00" + "time": "2026-01-07T21:26:29+00:00" }, { "name": "illuminate/conditionable", - "version": "v12.42.0", + "version": "v12.47.0", "source": { "type": "git", "url": "https://github.com/illuminate/conditionable.git", @@ -3982,16 +3983,16 @@ }, { "name": "illuminate/contracts", - "version": "v12.42.0", + "version": "v12.47.0", "source": { "type": "git", "url": "https://github.com/illuminate/contracts.git", - "reference": "19e8938edb73047017cfbd443b96844b86da4a59" + "reference": "2c0015e16b40f32c41e49810b6a0acf61204ea3d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/contracts/zipball/19e8938edb73047017cfbd443b96844b86da4a59", - "reference": "19e8938edb73047017cfbd443b96844b86da4a59", + "url": "https://api.github.com/repos/illuminate/contracts/zipball/2c0015e16b40f32c41e49810b6a0acf61204ea3d", + "reference": "2c0015e16b40f32c41e49810b6a0acf61204ea3d", "shasum": "" }, "require": { @@ -4026,11 +4027,11 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2025-11-26T21:36:01+00:00" + "time": "2026-01-07T14:57:06+00:00" }, { "name": "illuminate/macroable", - "version": "v12.42.0", + "version": "v12.47.0", "source": { "type": "git", "url": "https://github.com/illuminate/macroable.git", @@ -4076,7 +4077,7 @@ }, { "name": "illuminate/reflection", - "version": "v12.42.0", + "version": "v12.47.0", "source": { "type": "git", "url": "https://github.com/illuminate/reflection.git", @@ -4127,16 +4128,16 @@ }, { "name": "illuminate/support", - "version": "v12.42.0", + "version": "v12.47.0", "source": { "type": "git", "url": "https://github.com/illuminate/support.git", - "reference": "d35411be5657e0b5560a5885f3c9140e4cbe0be5" + "reference": "1757ae693f552f82179ebcdb0a4983a56e645f27" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/support/zipball/d35411be5657e0b5560a5885f3c9140e4cbe0be5", - "reference": "d35411be5657e0b5560a5885f3c9140e4cbe0be5", + "url": "https://api.github.com/repos/illuminate/support/zipball/1757ae693f552f82179ebcdb0a4983a56e645f27", + "reference": "1757ae693f552f82179ebcdb0a4983a56e645f27", "shasum": "" }, "require": { @@ -4203,20 +4204,20 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2025-12-09T15:26:52+00:00" + "time": "2026-01-13T14:50:24+00:00" }, { "name": "imagine/imagine", - "version": "1.5.1", + "version": "1.5.2", "source": { "type": "git", "url": "https://github.com/php-imagine/Imagine.git", - "reference": "8b130cd281efdea67e52d5f0f998572eb62d2f04" + "reference": "f9ed796eefb77c2f0f2167e1d4e36bc2b5ed6b0c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-imagine/Imagine/zipball/8b130cd281efdea67e52d5f0f998572eb62d2f04", - "reference": "8b130cd281efdea67e52d5f0f998572eb62d2f04", + "url": "https://api.github.com/repos/php-imagine/Imagine/zipball/f9ed796eefb77c2f0f2167e1d4e36bc2b5ed6b0c", + "reference": "f9ed796eefb77c2f0f2167e1d4e36bc2b5ed6b0c", "shasum": "" }, "require": { @@ -4263,9 +4264,9 @@ ], "support": { "issues": "https://github.com/php-imagine/Imagine/issues", - "source": "https://github.com/php-imagine/Imagine/tree/1.5.1" + "source": "https://github.com/php-imagine/Imagine/tree/1.5.2" }, - "time": "2025-12-09T15:27:47+00:00" + "time": "2026-01-09T10:45:12+00:00" }, { "name": "intervention/image", @@ -4701,6 +4702,66 @@ }, "time": "2025-11-29T09:14:09+00:00" }, + { + "name": "knpuniversity/oauth2-client-bundle", + "version": "v2.20.1", + "source": { + "type": "git", + "url": "https://github.com/knpuniversity/oauth2-client-bundle.git", + "reference": "d59e4dc61484e777b6f19df2efcf8b1bcc03828a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/knpuniversity/oauth2-client-bundle/zipball/d59e4dc61484e777b6f19df2efcf8b1bcc03828a", + "reference": "d59e4dc61484e777b6f19df2efcf8b1bcc03828a", + "shasum": "" + }, + "require": { + "league/oauth2-client": "^2.0", + "php": ">=8.1", + "symfony/dependency-injection": "^6.4|^7.3|^8.0", + "symfony/framework-bundle": "^6.4|^7.3|^8.0", + "symfony/http-foundation": "^6.4|^7.3|^8.0", + "symfony/routing": "^6.4|^7.3|^8.0", + "symfony/security-core": "^6.4|^7.3|^8.0", + "symfony/security-http": "^6.4|^7.3|^8.0" + }, + "require-dev": { + "league/oauth2-facebook": "^1.1|^2.0", + "symfony/phpunit-bridge": "^7.3", + "symfony/yaml": "^6.4|^7.3|^8.0" + }, + "suggest": { + "symfony/security-guard": "For integration with Symfony's Guard Security layer" + }, + "type": "symfony-bundle", + "autoload": { + "psr-4": { + "KnpU\\OAuth2ClientBundle\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ryan Weaver", + "email": "ryan@symfonycasts.com" + } + ], + "description": "Integration with league/oauth2-client to provide services", + "homepage": "https://symfonycasts.com", + "keywords": [ + "oauth", + "oauth2" + ], + "support": { + "issues": "https://github.com/knpuniversity/oauth2-client-bundle/issues", + "source": "https://github.com/knpuniversity/oauth2-client-bundle/tree/v2.20.1" + }, + "time": "2025-12-04T15:46:43+00:00" + }, { "name": "lasserafn/php-initial-avatar-generator", "version": "4.5", @@ -5002,16 +5063,16 @@ }, { "name": "league/flysystem-bundle", - "version": "3.6.0", + "version": "3.6.1", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem-bundle.git", - "reference": "88376670b35f11846bed7dca2efb82d993be22d0" + "reference": "61e7f989f14080abb14d5ade80629303691555cf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem-bundle/zipball/88376670b35f11846bed7dca2efb82d993be22d0", - "reference": "88376670b35f11846bed7dca2efb82d993be22d0", + "url": "https://api.github.com/repos/thephpleague/flysystem-bundle/zipball/61e7f989f14080abb14d5ade80629303691555cf", + "reference": "61e7f989f14080abb14d5ade80629303691555cf", "shasum": "" }, "require": { @@ -5066,9 +5127,9 @@ ], "support": { "issues": "https://github.com/thephpleague/flysystem-bundle/issues", - "source": "https://github.com/thephpleague/flysystem-bundle/tree/3.6.0" + "source": "https://github.com/thephpleague/flysystem-bundle/tree/3.6.1" }, - "time": "2025-08-21T17:25:13+00:00" + "time": "2025-12-11T15:40:58+00:00" }, { "name": "league/flysystem-local", @@ -5452,16 +5513,16 @@ }, { "name": "maennchen/zipstream-php", - "version": "3.2.0", + "version": "3.2.1", "source": { "type": "git", "url": "https://github.com/maennchen/ZipStream-PHP.git", - "reference": "9712d8fa4cdf9240380b01eb4be55ad8dcf71416" + "reference": "682f1098a8fddbaf43edac2306a691c7ad508ec5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/9712d8fa4cdf9240380b01eb4be55ad8dcf71416", - "reference": "9712d8fa4cdf9240380b01eb4be55ad8dcf71416", + "url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/682f1098a8fddbaf43edac2306a691c7ad508ec5", + "reference": "682f1098a8fddbaf43edac2306a691c7ad508ec5", "shasum": "" }, "require": { @@ -5472,7 +5533,7 @@ "require-dev": { "brianium/paratest": "^7.7", "ext-zip": "*", - "friendsofphp/php-cs-fixer": "^3.16", + "friendsofphp/php-cs-fixer": "^3.86", "guzzlehttp/guzzle": "^7.5", "mikey179/vfsstream": "^1.6", "php-coveralls/php-coveralls": "^2.5", @@ -5518,7 +5579,7 @@ ], "support": { "issues": "https://github.com/maennchen/ZipStream-PHP/issues", - "source": "https://github.com/maennchen/ZipStream-PHP/tree/3.2.0" + "source": "https://github.com/maennchen/ZipStream-PHP/tree/3.2.1" }, "funding": [ { @@ -5526,7 +5587,7 @@ "type": "github" } ], - "time": "2025-07-17T11:15:13+00:00" + "time": "2025-12-10T09:58:31+00:00" }, { "name": "markbaker/complex", @@ -5687,16 +5748,16 @@ }, { "name": "minishlink/web-push", - "version": "v9.0.3", + "version": "v9.0.4", "source": { "type": "git", "url": "https://github.com/web-push-libs/web-push-php.git", - "reference": "5c185f78ee41f271e2ea7314c80760040465b713" + "reference": "f979f40b0017d2f86d82b9f21edbc515d031cc23" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/web-push-libs/web-push-php/zipball/5c185f78ee41f271e2ea7314c80760040465b713", - "reference": "5c185f78ee41f271e2ea7314c80760040465b713", + "url": "https://api.github.com/repos/web-push-libs/web-push-php/zipball/f979f40b0017d2f86d82b9f21edbc515d031cc23", + "reference": "f979f40b0017d2f86d82b9f21edbc515d031cc23", "shasum": "" }, "require": { @@ -5704,15 +5765,17 @@ "ext-json": "*", "ext-mbstring": "*", "ext-openssl": "*", - "guzzlehttp/guzzle": "^7.4.5", + "guzzlehttp/guzzle": "^7.9.2", "php": ">=8.1", "spomky-labs/base64url": "^2.0.4", + "symfony/polyfill-php82": "^v1.31.0", "web-token/jwt-library": "^3.3.0|^4.0.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^v3.68.5", + "friendsofphp/php-cs-fixer": "^v3.91.3", "phpstan/phpstan": "^2.1.2", - "phpunit/phpunit": "^10.5.44|^11.5.6" + "phpunit/phpunit": "^10.5.44|^11.5.6", + "symfony/polyfill-iconv": "^1.33" }, "suggest": { "ext-bcmath": "Optional for performance.", @@ -5746,9 +5809,9 @@ ], "support": { "issues": "https://github.com/web-push-libs/web-push-php/issues", - "source": "https://github.com/web-push-libs/web-push-php/tree/v9.0.3" + "source": "https://github.com/web-push-libs/web-push-php/tree/v9.0.4" }, - "time": "2025-11-13T17:14:30+00:00" + "time": "2025-12-10T14:00:12+00:00" }, { "name": "mittwald/vault-php", @@ -5804,29 +5867,28 @@ }, { "name": "mobiledetect/mobiledetectlib", - "version": "4.8.09", + "version": "4.8.10", "source": { "type": "git", "url": "https://github.com/serbanghita/Mobile-Detect.git", - "reference": "a06fe2e546a06bb8c2639d6823d5250b2efb3209" + "reference": "96b1e1fa9a968de7660a031106ab529f659d0192" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/serbanghita/Mobile-Detect/zipball/a06fe2e546a06bb8c2639d6823d5250b2efb3209", - "reference": "a06fe2e546a06bb8c2639d6823d5250b2efb3209", + "url": "https://api.github.com/repos/serbanghita/Mobile-Detect/zipball/96b1e1fa9a968de7660a031106ab529f659d0192", + "reference": "96b1e1fa9a968de7660a031106ab529f659d0192", "shasum": "" }, "require": { "php": ">=8.0", - "psr/cache": "^3.0", "psr/simple-cache": "^3" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^v3.65.0", + "friendsofphp/php-cs-fixer": "^v3.75.0", "phpbench/phpbench": "^1.2", - "phpstan/phpstan": "^1.12.x-dev", - "phpunit/phpunit": "^9.6.18", - "squizlabs/php_codesniffer": "^3.11.1" + "phpstan/phpstan": "^2.1.11", + "phpunit/phpunit": "^9.6.22", + "squizlabs/php_codesniffer": "^3.12.1" }, "type": "library", "autoload": { @@ -5857,7 +5919,7 @@ ], "support": { "issues": "https://github.com/serbanghita/Mobile-Detect/issues", - "source": "https://github.com/serbanghita/Mobile-Detect/tree/4.8.09" + "source": "https://github.com/serbanghita/Mobile-Detect/tree/4.8.10" }, "funding": [ { @@ -5865,20 +5927,20 @@ "type": "github" } ], - "time": "2024-12-10T15:32:06+00:00" + "time": "2026-01-09T16:21:59+00:00" }, { "name": "monolog/monolog", - "version": "3.9.0", + "version": "3.10.0", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "10d85740180ecba7896c87e06a166e0c95a0e3b6" + "reference": "b321dd6749f0bf7189444158a3ce785cc16d69b0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/10d85740180ecba7896c87e06a166e0c95a0e3b6", - "reference": "10d85740180ecba7896c87e06a166e0c95a0e3b6", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/b321dd6749f0bf7189444158a3ce785cc16d69b0", + "reference": "b321dd6749f0bf7189444158a3ce785cc16d69b0", "shasum": "" }, "require": { @@ -5896,7 +5958,7 @@ "graylog2/gelf-php": "^1.4.2 || ^2.0", "guzzlehttp/guzzle": "^7.4.5", "guzzlehttp/psr7": "^2.2", - "mongodb/mongodb": "^1.8", + "mongodb/mongodb": "^1.8 || ^2.0", "php-amqplib/php-amqplib": "~2.4 || ^3", "php-console/php-console": "^3.1.8", "phpstan/phpstan": "^2", @@ -5956,7 +6018,7 @@ ], "support": { "issues": "https://github.com/Seldaek/monolog/issues", - "source": "https://github.com/Seldaek/monolog/tree/3.9.0" + "source": "https://github.com/Seldaek/monolog/tree/3.10.0" }, "funding": [ { @@ -5968,7 +6030,7 @@ "type": "tidelift" } ], - "time": "2025-03-24T10:02:05+00:00" + "time": "2026-01-02T08:56:05+00:00" }, { "name": "mtdowling/jmespath.php", @@ -6038,16 +6100,16 @@ }, { "name": "nelmio/cors-bundle", - "version": "2.6.0", + "version": "2.6.1", "source": { "type": "git", "url": "https://github.com/nelmio/NelmioCorsBundle.git", - "reference": "530217472204881cacd3671909f634b960c7b948" + "reference": "3d80dbcd5d1eb5f8b20ed5199e1778d44c2e4d1c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nelmio/NelmioCorsBundle/zipball/530217472204881cacd3671909f634b960c7b948", - "reference": "530217472204881cacd3671909f634b960c7b948", + "url": "https://api.github.com/repos/nelmio/NelmioCorsBundle/zipball/3d80dbcd5d1eb5f8b20ed5199e1778d44c2e4d1c", + "reference": "3d80dbcd5d1eb5f8b20ed5199e1778d44c2e4d1c", "shasum": "" }, "require": { @@ -6097,9 +6159,9 @@ ], "support": { "issues": "https://github.com/nelmio/NelmioCorsBundle/issues", - "source": "https://github.com/nelmio/NelmioCorsBundle/tree/2.6.0" + "source": "https://github.com/nelmio/NelmioCorsBundle/tree/2.6.1" }, - "time": "2025-10-23T06:57:22+00:00" + "time": "2026-01-12T15:59:08+00:00" }, { "name": "nesbot/carbon", @@ -6567,16 +6629,16 @@ }, { "name": "phpdocumentor/reflection-docblock", - "version": "5.6.5", + "version": "5.6.6", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "90614c73d3800e187615e2dd236ad0e2a01bf761" + "reference": "5cee1d3dfc2d2aa6599834520911d246f656bcb8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/90614c73d3800e187615e2dd236ad0e2a01bf761", - "reference": "90614c73d3800e187615e2dd236ad0e2a01bf761", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/5cee1d3dfc2d2aa6599834520911d246f656bcb8", + "reference": "5cee1d3dfc2d2aa6599834520911d246f656bcb8", "shasum": "" }, "require": { @@ -6586,7 +6648,7 @@ "phpdocumentor/reflection-common": "^2.2", "phpdocumentor/type-resolver": "^1.7", "phpstan/phpdoc-parser": "^1.7|^2.0", - "webmozart/assert": "^1.9.1" + "webmozart/assert": "^1.9.1 || ^2" }, "require-dev": { "mockery/mockery": "~1.3.5 || ~1.6.0", @@ -6625,9 +6687,9 @@ "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", "support": { "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", - "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.6.5" + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.6.6" }, - "time": "2025-11-27T19:50:05+00:00" + "time": "2025-12-22T21:13:58+00:00" }, { "name": "phpdocumentor/type-resolver", @@ -6689,16 +6751,16 @@ }, { "name": "phpoffice/phpspreadsheet", - "version": "5.3.0", + "version": "5.4.0", "source": { "type": "git", "url": "https://github.com/PHPOffice/PhpSpreadsheet.git", - "reference": "4d597c1aacdde1805a33c525b9758113ea0d90df" + "reference": "48f2fe37d64c2dece0ef71fb2ac55497566782af" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/4d597c1aacdde1805a33c525b9758113ea0d90df", - "reference": "4d597c1aacdde1805a33c525b9758113ea0d90df", + "url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/48f2fe37d64c2dece0ef71fb2ac55497566782af", + "reference": "48f2fe37d64c2dece0ef71fb2ac55497566782af", "shasum": "" }, "require": { @@ -6706,6 +6768,7 @@ "ext-ctype": "*", "ext-dom": "*", "ext-fileinfo": "*", + "ext-filter": "*", "ext-gd": "*", "ext-iconv": "*", "ext-libxml": "*", @@ -6720,13 +6783,12 @@ "markbaker/complex": "^3.0", "markbaker/matrix": "^3.0", "php": "^8.1", - "psr/http-client": "^1.0", - "psr/http-factory": "^1.0", "psr/simple-cache": "^1.0 || ^2.0 || ^3.0" }, "require-dev": { "dealerdirect/phpcodesniffer-composer-installer": "dev-main", "dompdf/dompdf": "^2.0 || ^3.0", + "ext-intl": "*", "friendsofphp/php-cs-fixer": "^3.2", "mitoteam/jpgraph": "^10.5", "mpdf/mpdf": "^8.1.1", @@ -6740,7 +6802,7 @@ }, "suggest": { "dompdf/dompdf": "Option for rendering PDF with PDF Writer", - "ext-intl": "PHP Internationalization Functions, required for NumberFormat Wizard", + "ext-intl": "PHP Internationalization Functions, required for NumberFormat Wizard and StringHelper::setLocale()", "mitoteam/jpgraph": "Option for rendering charts, or including charts with PDF or HTML Writers", "mpdf/mpdf": "Option for rendering PDF with PDF Writer", "tecnickcom/tcpdf": "Option for rendering PDF with PDF Writer" @@ -6773,6 +6835,9 @@ }, { "name": "Adrien Crivelli" + }, + { + "name": "Owen Leibman" } ], "description": "PHPSpreadsheet - Read, Create and Write Spreadsheet documents in PHP - Spreadsheet engine", @@ -6789,22 +6854,22 @@ ], "support": { "issues": "https://github.com/PHPOffice/PhpSpreadsheet/issues", - "source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/5.3.0" + "source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/5.4.0" }, - "time": "2025-11-24T15:47:10+00:00" + "time": "2026-01-11T04:52:00+00:00" }, { "name": "phpseclib/phpseclib", - "version": "3.0.47", + "version": "3.0.48", "source": { "type": "git", "url": "https://github.com/phpseclib/phpseclib.git", - "reference": "9d6ca36a6c2dd434765b1071b2644a1c683b385d" + "reference": "64065a5679c50acb886e82c07aa139b0f757bb89" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/9d6ca36a6c2dd434765b1071b2644a1c683b385d", - "reference": "9d6ca36a6c2dd434765b1071b2644a1c683b385d", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/64065a5679c50acb886e82c07aa139b0f757bb89", + "reference": "64065a5679c50acb886e82c07aa139b0f757bb89", "shasum": "" }, "require": { @@ -6885,7 +6950,7 @@ ], "support": { "issues": "https://github.com/phpseclib/phpseclib/issues", - "source": "https://github.com/phpseclib/phpseclib/tree/3.0.47" + "source": "https://github.com/phpseclib/phpseclib/tree/3.0.48" }, "funding": [ { @@ -6901,20 +6966,20 @@ "type": "tidelift" } ], - "time": "2025-10-06T01:07:24+00:00" + "time": "2025-12-15T11:51:42+00:00" }, { "name": "phpstan/phpdoc-parser", - "version": "2.3.0", + "version": "2.3.1", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "1e0cd5370df5dd2e556a36b9c62f62e555870495" + "reference": "16dbf9937da8d4528ceb2145c9c7c0bd29e26374" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/1e0cd5370df5dd2e556a36b9c62f62e555870495", - "reference": "1e0cd5370df5dd2e556a36b9c62f62e555870495", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/16dbf9937da8d4528ceb2145c9c7c0bd29e26374", + "reference": "16dbf9937da8d4528ceb2145c9c7c0bd29e26374", "shasum": "" }, "require": { @@ -6946,9 +7011,9 @@ "description": "PHPDoc parser with support for nullable, intersection and generic types", "support": { "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/2.3.0" + "source": "https://github.com/phpstan/phpdoc-parser/tree/2.3.1" }, - "time": "2025-08-30T15:50:23+00:00" + "time": "2026-01-12T11:33:04+00:00" }, { "name": "presta/sitemap-bundle", @@ -7657,20 +7722,20 @@ }, { "name": "ramsey/uuid", - "version": "4.9.1", + "version": "4.9.2", "source": { "type": "git", "url": "https://github.com/ramsey/uuid.git", - "reference": "81f941f6f729b1e3ceea61d9d014f8b6c6800440" + "reference": "8429c78ca35a09f27565311b98101e2826affde0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ramsey/uuid/zipball/81f941f6f729b1e3ceea61d9d014f8b6c6800440", - "reference": "81f941f6f729b1e3ceea61d9d014f8b6c6800440", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/8429c78ca35a09f27565311b98101e2826affde0", + "reference": "8429c78ca35a09f27565311b98101e2826affde0", "shasum": "" }, "require": { - "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12 || ^0.13 || ^0.14", + "brick/math": "^0.8.16 || ^0.9 || ^0.10 || ^0.11 || ^0.12 || ^0.13 || ^0.14", "php": "^8.0", "ramsey/collection": "^1.2 || ^2.0" }, @@ -7729,9 +7794,9 @@ ], "support": { "issues": "https://github.com/ramsey/uuid/issues", - "source": "https://github.com/ramsey/uuid/tree/4.9.1" + "source": "https://github.com/ramsey/uuid/tree/4.9.2" }, - "time": "2025-09-04T20:59:21+00:00" + "time": "2025-12-14T04:43:48+00:00" }, { "name": "rize/uri-template", @@ -7887,16 +7952,16 @@ }, { "name": "sentry/sentry-symfony", - "version": "5.8.2", + "version": "5.8.3", "source": { "type": "git", "url": "https://github.com/getsentry/sentry-symfony.git", - "reference": "fb03d506c575cd1cb5274774d0dd968938150982" + "reference": "e82559a078b26c8f8592289e98a25b203527a9c6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/getsentry/sentry-symfony/zipball/fb03d506c575cd1cb5274774d0dd968938150982", - "reference": "fb03d506c575cd1cb5274774d0dd968938150982", + "url": "https://api.github.com/repos/getsentry/sentry-symfony/zipball/e82559a078b26c8f8592289e98a25b203527a9c6", + "reference": "e82559a078b26c8f8592289e98a25b203527a9c6", "shasum": "" }, "require": { @@ -7973,7 +8038,7 @@ ], "support": { "issues": "https://github.com/getsentry/sentry-symfony/issues", - "source": "https://github.com/getsentry/sentry-symfony/tree/5.8.2" + "source": "https://github.com/getsentry/sentry-symfony/tree/5.8.3" }, "funding": [ { @@ -7985,7 +8050,7 @@ "type": "custom" } ], - "time": "2025-12-04T12:34:17+00:00" + "time": "2025-12-18T09:26:49+00:00" }, { "name": "setasign/fpdi", @@ -8258,16 +8323,16 @@ }, { "name": "spomky-labs/pki-framework", - "version": "1.4.0", + "version": "1.4.1", "source": { "type": "git", "url": "https://github.com/Spomky-Labs/pki-framework.git", - "reference": "bf6f55a9d9eb25b7781640221cb54f5c727850d7" + "reference": "f0e9a548df4e3942886adc9b7830581a46334631" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Spomky-Labs/pki-framework/zipball/bf6f55a9d9eb25b7781640221cb54f5c727850d7", - "reference": "bf6f55a9d9eb25b7781640221cb54f5c727850d7", + "url": "https://api.github.com/repos/Spomky-Labs/pki-framework/zipball/f0e9a548df4e3942886adc9b7830581a46334631", + "reference": "f0e9a548df4e3942886adc9b7830581a46334631", "shasum": "" }, "require": { @@ -8351,7 +8416,7 @@ ], "support": { "issues": "https://github.com/Spomky-Labs/pki-framework/issues", - "source": "https://github.com/Spomky-Labs/pki-framework/tree/1.4.0" + "source": "https://github.com/Spomky-Labs/pki-framework/tree/1.4.1" }, "funding": [ { @@ -8363,7 +8428,7 @@ "type": "patreon" } ], - "time": "2025-10-22T08:24:34+00:00" + "time": "2025-12-20T12:57:40+00:00" }, { "name": "stancer/stancer", @@ -8429,6 +8494,67 @@ }, "time": "2024-11-15T17:47:59+00:00" }, + { + "name": "stevenmaguire/oauth2-keycloak", + "version": "5.1.0", + "source": { + "type": "git", + "url": "https://github.com/stevenmaguire/oauth2-keycloak.git", + "reference": "1b690b7377dfe7a23e1590373f37e12cf40a6d75" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/stevenmaguire/oauth2-keycloak/zipball/1b690b7377dfe7a23e1590373f37e12cf40a6d75", + "reference": "1b690b7377dfe7a23e1590373f37e12cf40a6d75", + "shasum": "" + }, + "require": { + "firebase/php-jwt": "^6.0", + "league/oauth2-client": "^2.0", + "php": "~7.2 || ~8.0" + }, + "require-dev": { + "mockery/mockery": "~1.5.0", + "phpunit/phpunit": "~9.6.4", + "squizlabs/php_codesniffer": "~3.7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Stevenmaguire\\OAuth2\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Steven Maguire", + "email": "stevenmaguire@gmail.com", + "homepage": "https://github.com/stevenmaguire" + } + ], + "description": "Keycloak OAuth 2.0 Client Provider for The PHP League OAuth2-Client", + "keywords": [ + "authorisation", + "authorization", + "client", + "keycloak", + "oauth", + "oauth2" + ], + "support": { + "issues": "https://github.com/stevenmaguire/oauth2-keycloak/issues", + "source": "https://github.com/stevenmaguire/oauth2-keycloak/tree/5.1.0" + }, + "time": "2023-10-24T06:10:44+00:00" + }, { "name": "symfony/amazon-mailer", "version": "v7.3.0", @@ -8566,16 +8692,16 @@ }, { "name": "symfony/asset-mapper", - "version": "v7.3.8", + "version": "v7.3.9", "source": { "type": "git", "url": "https://github.com/symfony/asset-mapper.git", - "reference": "d66dba9dbc1b75289ed3dc45664794891ae881cb" + "reference": "781da831b7e4eaa39c904958f9446c829fa21a6d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/asset-mapper/zipball/d66dba9dbc1b75289ed3dc45664794891ae881cb", - "reference": "d66dba9dbc1b75289ed3dc45664794891ae881cb", + "url": "https://api.github.com/repos/symfony/asset-mapper/zipball/781da831b7e4eaa39c904958f9446c829fa21a6d", + "reference": "781da831b7e4eaa39c904958f9446c829fa21a6d", "shasum": "" }, "require": { @@ -8626,7 +8752,7 @@ "description": "Maps directories of assets & makes them available in a public directory with versioned filenames.", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/asset-mapper/tree/v7.3.8" + "source": "https://github.com/symfony/asset-mapper/tree/v7.3.9" }, "funding": [ { @@ -8646,20 +8772,20 @@ "type": "tidelift" } ], - "time": "2025-11-21T13:14:48+00:00" + "time": "2025-12-19T08:58:15+00:00" }, { "name": "symfony/cache", - "version": "v7.3.8", + "version": "v7.3.9", "source": { "type": "git", "url": "https://github.com/symfony/cache.git", - "reference": "288ea9853bbf6b395ee09bde9ac6da415fffbc8c" + "reference": "fae016390a2e6b451abc0f4805cbfe0bf70f437f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/288ea9853bbf6b395ee09bde9ac6da415fffbc8c", - "reference": "288ea9853bbf6b395ee09bde9ac6da415fffbc8c", + "url": "https://api.github.com/repos/symfony/cache/zipball/fae016390a2e6b451abc0f4805cbfe0bf70f437f", + "reference": "fae016390a2e6b451abc0f4805cbfe0bf70f437f", "shasum": "" }, "require": { @@ -8728,7 +8854,7 @@ "psr6" ], "support": { - "source": "https://github.com/symfony/cache/tree/v7.3.8" + "source": "https://github.com/symfony/cache/tree/v7.3.9" }, "funding": [ { @@ -8748,7 +8874,7 @@ "type": "tidelift" } ], - "time": "2025-12-04T18:07:52+00:00" + "time": "2025-12-28T10:45:15+00:00" }, { "name": "symfony/cache-contracts", @@ -8985,16 +9111,16 @@ }, { "name": "symfony/console", - "version": "v7.3.8", + "version": "v7.3.9", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "6d0d25cc1138bb7bab0685fbe4184e6289914406" + "reference": "3fe62811ba48799ae958208b55674abbc8796b71" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/6d0d25cc1138bb7bab0685fbe4184e6289914406", - "reference": "6d0d25cc1138bb7bab0685fbe4184e6289914406", + "url": "https://api.github.com/repos/symfony/console/zipball/3fe62811ba48799ae958208b55674abbc8796b71", + "reference": "3fe62811ba48799ae958208b55674abbc8796b71", "shasum": "" }, "require": { @@ -9059,7 +9185,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.3.8" + "source": "https://github.com/symfony/console/tree/v7.3.9" }, "funding": [ { @@ -9079,20 +9205,20 @@ "type": "tidelift" } ], - "time": "2025-12-05T13:52:21+00:00" + "time": "2025-12-23T14:45:27+00:00" }, { "name": "symfony/dependency-injection", - "version": "v7.3.8", + "version": "v7.3.9", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "6d83d997230971a350bfb0b9bfc43e8dead5ff9a" + "reference": "53a1c925df19dc3a67eb124fc5dc980a09f5d971" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/6d83d997230971a350bfb0b9bfc43e8dead5ff9a", - "reference": "6d83d997230971a350bfb0b9bfc43e8dead5ff9a", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/53a1c925df19dc3a67eb124fc5dc980a09f5d971", + "reference": "53a1c925df19dc3a67eb124fc5dc980a09f5d971", "shasum": "" }, "require": { @@ -9143,7 +9269,7 @@ "description": "Allows you to standardize and centralize the way objects are constructed in your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/dependency-injection/tree/v7.3.8" + "source": "https://github.com/symfony/dependency-injection/tree/v7.3.9" }, "funding": [ { @@ -9163,7 +9289,7 @@ "type": "tidelift" } ], - "time": "2025-12-07T09:35:41+00:00" + "time": "2025-12-28T10:53:28+00:00" }, { "name": "symfony/deprecation-contracts", @@ -9347,16 +9473,16 @@ }, { "name": "symfony/doctrine-messenger", - "version": "v7.3.8", + "version": "v7.3.9", "source": { "type": "git", "url": "https://github.com/symfony/doctrine-messenger.git", - "reference": "f5d6c8ea82b9378221186393e8dff9c32ea09d10" + "reference": "ed215e61df79c1e504b2790ebdf68a6110a5e526" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/doctrine-messenger/zipball/f5d6c8ea82b9378221186393e8dff9c32ea09d10", - "reference": "f5d6c8ea82b9378221186393e8dff9c32ea09d10", + "url": "https://api.github.com/repos/symfony/doctrine-messenger/zipball/ed215e61df79c1e504b2790ebdf68a6110a5e526", + "reference": "ed215e61df79c1e504b2790ebdf68a6110a5e526", "shasum": "" }, "require": { @@ -9399,7 +9525,7 @@ "description": "Symfony Doctrine Messenger Bridge", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/doctrine-messenger/tree/v7.3.8" + "source": "https://github.com/symfony/doctrine-messenger/tree/v7.3.9" }, "funding": [ { @@ -9419,7 +9545,7 @@ "type": "tidelift" } ], - "time": "2025-12-05T13:52:21+00:00" + "time": "2025-12-16T07:50:38+00:00" }, { "name": "symfony/dotenv", @@ -9880,16 +10006,16 @@ }, { "name": "symfony/finder", - "version": "v7.3.5", + "version": "v7.3.9", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "9f696d2f1e340484b4683f7853b273abff94421f" + "reference": "197abc62f8d8537dd9f75d1bfd307ec24551d994" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/9f696d2f1e340484b4683f7853b273abff94421f", - "reference": "9f696d2f1e340484b4683f7853b273abff94421f", + "url": "https://api.github.com/repos/symfony/finder/zipball/197abc62f8d8537dd9f75d1bfd307ec24551d994", + "reference": "197abc62f8d8537dd9f75d1bfd307ec24551d994", "shasum": "" }, "require": { @@ -9924,7 +10050,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v7.3.5" + "source": "https://github.com/symfony/finder/tree/v7.3.9" }, "funding": [ { @@ -9944,7 +10070,7 @@ "type": "tidelift" } ], - "time": "2025-10-15T18:45:57+00:00" + "time": "2025-12-23T14:45:27+00:00" }, { "name": "symfony/flex", @@ -10021,16 +10147,16 @@ }, { "name": "symfony/form", - "version": "v7.3.8", + "version": "v7.3.9", "source": { "type": "git", "url": "https://github.com/symfony/form.git", - "reference": "008a7b331d7f42ac68f8f979566000f1aa0fbe0c" + "reference": "3e3299150a8a9ba080c93dc3af62e1a38fcb77b7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/form/zipball/008a7b331d7f42ac68f8f979566000f1aa0fbe0c", - "reference": "008a7b331d7f42ac68f8f979566000f1aa0fbe0c", + "url": "https://api.github.com/repos/symfony/form/zipball/3e3299150a8a9ba080c93dc3af62e1a38fcb77b7", + "reference": "3e3299150a8a9ba080c93dc3af62e1a38fcb77b7", "shasum": "" }, "require": { @@ -10098,7 +10224,7 @@ "description": "Allows to easily create, process and reuse HTML forms", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/form/tree/v7.3.8" + "source": "https://github.com/symfony/form/tree/v7.3.9" }, "funding": [ { @@ -10118,20 +10244,20 @@ "type": "tidelift" } ], - "time": "2025-12-05T13:52:21+00:00" + "time": "2025-12-23T14:45:27+00:00" }, { "name": "symfony/framework-bundle", - "version": "v7.3.8", + "version": "v7.3.9", "source": { "type": "git", "url": "https://github.com/symfony/framework-bundle.git", - "reference": "5d2e60f301dbafba1408e62b9838fdb58920c2ca" + "reference": "aeae70599abfc530a787b2ef091f3ab89d7a2a80" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/5d2e60f301dbafba1408e62b9838fdb58920c2ca", - "reference": "5d2e60f301dbafba1408e62b9838fdb58920c2ca", + "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/aeae70599abfc530a787b2ef091f3ab89d7a2a80", + "reference": "aeae70599abfc530a787b2ef091f3ab89d7a2a80", "shasum": "" }, "require": { @@ -10256,7 +10382,7 @@ "description": "Provides a tight integration between Symfony components and the Symfony full-stack framework", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/framework-bundle/tree/v7.3.8" + "source": "https://github.com/symfony/framework-bundle/tree/v7.3.9" }, "funding": [ { @@ -10276,20 +10402,20 @@ "type": "tidelift" } ], - "time": "2025-12-05T13:52:40+00:00" + "time": "2025-12-23T14:45:27+00:00" }, { "name": "symfony/http-client", - "version": "v7.3.8", + "version": "v7.3.9", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "3d125854b2f254303d7dfd1d3af15954ac65703b" + "reference": "7978f8fcbd86fca55d02f9cd1428a9f8b8cf5d06" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/3d125854b2f254303d7dfd1d3af15954ac65703b", - "reference": "3d125854b2f254303d7dfd1d3af15954ac65703b", + "url": "https://api.github.com/repos/symfony/http-client/zipball/7978f8fcbd86fca55d02f9cd1428a9f8b8cf5d06", + "reference": "7978f8fcbd86fca55d02f9cd1428a9f8b8cf5d06", "shasum": "" }, "require": { @@ -10356,7 +10482,7 @@ "http" ], "support": { - "source": "https://github.com/symfony/http-client/tree/v7.3.8" + "source": "https://github.com/symfony/http-client/tree/v7.3.9" }, "funding": [ { @@ -10376,7 +10502,7 @@ "type": "tidelift" } ], - "time": "2025-12-04T18:07:52+00:00" + "time": "2025-12-23T14:45:27+00:00" }, { "name": "symfony/http-client-contracts", @@ -10458,16 +10584,16 @@ }, { "name": "symfony/http-foundation", - "version": "v7.3.8", + "version": "v7.3.9", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "8cdae4e108673e0d3e4f18ef2ee79ff5023beeac" + "reference": "6dc98931a559065ff8f968ae0e461e600a321291" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/8cdae4e108673e0d3e4f18ef2ee79ff5023beeac", - "reference": "8cdae4e108673e0d3e4f18ef2ee79ff5023beeac", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/6dc98931a559065ff8f968ae0e461e600a321291", + "reference": "6dc98931a559065ff8f968ae0e461e600a321291", "shasum": "" }, "require": { @@ -10517,7 +10643,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v7.3.8" + "source": "https://github.com/symfony/http-foundation/tree/v7.3.9" }, "funding": [ { @@ -10537,20 +10663,20 @@ "type": "tidelift" } ], - "time": "2025-12-04T18:07:52+00:00" + "time": "2025-12-19T08:58:15+00:00" }, { "name": "symfony/http-kernel", - "version": "v7.3.8", + "version": "v7.3.9", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "b4bfe6980782b89a2f9c78e4a0f00f0582c8043e" + "reference": "b319fe1248b4df79adb7b2b1f0954fdecf08f0b2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/b4bfe6980782b89a2f9c78e4a0f00f0582c8043e", - "reference": "b4bfe6980782b89a2f9c78e4a0f00f0582c8043e", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/b319fe1248b4df79adb7b2b1f0954fdecf08f0b2", + "reference": "b319fe1248b4df79adb7b2b1f0954fdecf08f0b2", "shasum": "" }, "require": { @@ -10635,7 +10761,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v7.3.8" + "source": "https://github.com/symfony/http-kernel/tree/v7.3.9" }, "funding": [ { @@ -10655,7 +10781,7 @@ "type": "tidelift" } ], - "time": "2025-12-07T16:03:07+00:00" + "time": "2025-12-31T08:34:55+00:00" }, { "name": "symfony/intl", @@ -10749,16 +10875,16 @@ }, { "name": "symfony/mailer", - "version": "v7.3.5", + "version": "v7.3.9", "source": { "type": "git", "url": "https://github.com/symfony/mailer.git", - "reference": "fd497c45ba9c10c37864e19466b090dcb60a50ba" + "reference": "efd8b9875358612a5d80a02bab4d63c312d8efe4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mailer/zipball/fd497c45ba9c10c37864e19466b090dcb60a50ba", - "reference": "fd497c45ba9c10c37864e19466b090dcb60a50ba", + "url": "https://api.github.com/repos/symfony/mailer/zipball/efd8b9875358612a5d80a02bab4d63c312d8efe4", + "reference": "efd8b9875358612a5d80a02bab4d63c312d8efe4", "shasum": "" }, "require": { @@ -10809,7 +10935,7 @@ "description": "Helps sending emails", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/mailer/tree/v7.3.5" + "source": "https://github.com/symfony/mailer/tree/v7.3.9" }, "funding": [ { @@ -10829,20 +10955,20 @@ "type": "tidelift" } ], - "time": "2025-10-24T14:27:20+00:00" + "time": "2025-12-16T07:50:38+00:00" }, { "name": "symfony/messenger", - "version": "v7.3.6", + "version": "v7.3.9", "source": { "type": "git", "url": "https://github.com/symfony/messenger.git", - "reference": "58a7efa3bebadbe4cdd8f7577c5856f0e3ea3978" + "reference": "43cf1fcc37adfee14f5ef8eb0ca1440554e98ec5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/messenger/zipball/58a7efa3bebadbe4cdd8f7577c5856f0e3ea3978", - "reference": "58a7efa3bebadbe4cdd8f7577c5856f0e3ea3978", + "url": "https://api.github.com/repos/symfony/messenger/zipball/43cf1fcc37adfee14f5ef8eb0ca1440554e98ec5", + "reference": "43cf1fcc37adfee14f5ef8eb0ca1440554e98ec5", "shasum": "" }, "require": { @@ -10902,7 +11028,7 @@ "description": "Helps applications send and receive messages to/from other applications or via message queues", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/messenger/tree/v7.3.6" + "source": "https://github.com/symfony/messenger/tree/v7.3.9" }, "funding": [ { @@ -10922,7 +11048,7 @@ "type": "tidelift" } ], - "time": "2025-11-06T11:17:34+00:00" + "time": "2025-12-18T08:25:32+00:00" }, { "name": "symfony/mime", @@ -12151,16 +12277,16 @@ }, { "name": "symfony/process", - "version": "v7.3.4", + "version": "v7.3.9", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "f24f8f316367b30810810d4eb30c543d7003ff3b" + "reference": "cbfa8595e86911b7c9dcd6e80e2205e82be86180" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/f24f8f316367b30810810d4eb30c543d7003ff3b", - "reference": "f24f8f316367b30810810d4eb30c543d7003ff3b", + "url": "https://api.github.com/repos/symfony/process/zipball/cbfa8595e86911b7c9dcd6e80e2205e82be86180", + "reference": "cbfa8595e86911b7c9dcd6e80e2205e82be86180", "shasum": "" }, "require": { @@ -12192,7 +12318,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v7.3.4" + "source": "https://github.com/symfony/process/tree/v7.3.9" }, "funding": [ { @@ -12212,25 +12338,25 @@ "type": "tidelift" } ], - "time": "2025-09-11T10:12:26+00:00" + "time": "2025-12-19T08:58:15+00:00" }, { "name": "symfony/property-access", - "version": "v7.3.3", + "version": "v7.3.9", "source": { "type": "git", "url": "https://github.com/symfony/property-access.git", - "reference": "4a4389e5c8bd1d0320d80a23caa6a1ac71cb81a7" + "reference": "fa254c8f0be6423281822cefa6a81ef59c10b8ec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/property-access/zipball/4a4389e5c8bd1d0320d80a23caa6a1ac71cb81a7", - "reference": "4a4389e5c8bd1d0320d80a23caa6a1ac71cb81a7", + "url": "https://api.github.com/repos/symfony/property-access/zipball/fa254c8f0be6423281822cefa6a81ef59c10b8ec", + "reference": "fa254c8f0be6423281822cefa6a81ef59c10b8ec", "shasum": "" }, "require": { "php": ">=8.2", - "symfony/property-info": "^6.4|^7.0" + "symfony/property-info": "^6.4.31|~7.3.9|^7.4.2" }, "require-dev": { "symfony/cache": "^6.4|^7.0" @@ -12272,7 +12398,7 @@ "reflection" ], "support": { - "source": "https://github.com/symfony/property-access/tree/v7.3.3" + "source": "https://github.com/symfony/property-access/tree/v7.3.9" }, "funding": [ { @@ -12292,20 +12418,20 @@ "type": "tidelift" } ], - "time": "2025-08-04T15:15:28+00:00" + "time": "2025-12-18T10:35:05+00:00" }, { "name": "symfony/property-info", - "version": "v7.3.8", + "version": "v7.3.9", "source": { "type": "git", "url": "https://github.com/symfony/property-info.git", - "reference": "3a0f08e10916364a02780181eb9c2269be114044" + "reference": "243a05bc1d8cc73df8ed19d29d76aeec7b930677" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/property-info/zipball/3a0f08e10916364a02780181eb9c2269be114044", - "reference": "3a0f08e10916364a02780181eb9c2269be114044", + "url": "https://api.github.com/repos/symfony/property-info/zipball/243a05bc1d8cc73df8ed19d29d76aeec7b930677", + "reference": "243a05bc1d8cc73df8ed19d29d76aeec7b930677", "shasum": "" }, "require": { @@ -12362,7 +12488,7 @@ "validator" ], "support": { - "source": "https://github.com/symfony/property-info/tree/v7.3.8" + "source": "https://github.com/symfony/property-info/tree/v7.3.9" }, "funding": [ { @@ -12382,7 +12508,7 @@ "type": "tidelift" } ], - "time": "2025-12-05T13:52:40+00:00" + "time": "2025-12-18T08:25:32+00:00" }, { "name": "symfony/psr-http-message-bridge", @@ -12544,16 +12670,16 @@ }, { "name": "symfony/routing", - "version": "v7.3.8", + "version": "v7.3.9", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "7350aebf3d01e41c0a13245dd6008ace8780b3bb" + "reference": "de7849b54c6a6f2a5fe1c761639e549eb81a5089" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/7350aebf3d01e41c0a13245dd6008ace8780b3bb", - "reference": "7350aebf3d01e41c0a13245dd6008ace8780b3bb", + "url": "https://api.github.com/repos/symfony/routing/zipball/de7849b54c6a6f2a5fe1c761639e549eb81a5089", + "reference": "de7849b54c6a6f2a5fe1c761639e549eb81a5089", "shasum": "" }, "require": { @@ -12605,7 +12731,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v7.3.8" + "source": "https://github.com/symfony/routing/tree/v7.3.9" }, "funding": [ { @@ -12625,7 +12751,7 @@ "type": "tidelift" } ], - "time": "2025-11-26T15:55:45+00:00" + "time": "2025-12-16T20:27:23+00:00" }, { "name": "symfony/runtime", @@ -12822,16 +12948,16 @@ }, { "name": "symfony/security-core", - "version": "v7.3.5", + "version": "v7.3.9", "source": { "type": "git", "url": "https://github.com/symfony/security-core.git", - "reference": "772a7c1eddd8bf8a977a67e6e8adc59650c604eb" + "reference": "dcd462202eb3ced09edf610926eb469b9180c33f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-core/zipball/772a7c1eddd8bf8a977a67e6e8adc59650c604eb", - "reference": "772a7c1eddd8bf8a977a67e6e8adc59650c604eb", + "url": "https://api.github.com/repos/symfony/security-core/zipball/dcd462202eb3ced09edf610926eb469b9180c33f", + "reference": "dcd462202eb3ced09edf610926eb469b9180c33f", "shasum": "" }, "require": { @@ -12889,7 +13015,7 @@ "description": "Symfony Security Component - Core Library", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/security-core/tree/v7.3.5" + "source": "https://github.com/symfony/security-core/tree/v7.3.9" }, "funding": [ { @@ -12909,20 +13035,20 @@ "type": "tidelift" } ], - "time": "2025-10-24T14:27:20+00:00" + "time": "2025-12-19T11:33:01+00:00" }, { "name": "symfony/security-csrf", - "version": "v7.3.0", + "version": "v7.3.9", "source": { "type": "git", "url": "https://github.com/symfony/security-csrf.git", - "reference": "2b4b0c46c901729e4e90719eacd980381f53e0a3" + "reference": "ce032a98fd6cdef964e932cc9d7f38cb2b2b9035" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-csrf/zipball/2b4b0c46c901729e4e90719eacd980381f53e0a3", - "reference": "2b4b0c46c901729e4e90719eacd980381f53e0a3", + "url": "https://api.github.com/repos/symfony/security-csrf/zipball/ce032a98fd6cdef964e932cc9d7f38cb2b2b9035", + "reference": "ce032a98fd6cdef964e932cc9d7f38cb2b2b9035", "shasum": "" }, "require": { @@ -12963,7 +13089,7 @@ "description": "Symfony Security Component - CSRF Library", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/security-csrf/tree/v7.3.0" + "source": "https://github.com/symfony/security-csrf/tree/v7.3.9" }, "funding": [ { @@ -12974,25 +13100,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-01-02T18:42:10+00:00" + "time": "2025-12-23T15:22:52+00:00" }, { "name": "symfony/security-http", - "version": "v7.3.8", + "version": "v7.3.9", "source": { "type": "git", "url": "https://github.com/symfony/security-http.git", - "reference": "64b65f2e35d5443a750ac7729652f4b6676a941b" + "reference": "61efc01cf3dad84a436b17d95b44027a8b7c6c41" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-http/zipball/64b65f2e35d5443a750ac7729652f4b6676a941b", - "reference": "64b65f2e35d5443a750ac7729652f4b6676a941b", + "url": "https://api.github.com/repos/symfony/security-http/zipball/61efc01cf3dad84a436b17d95b44027a8b7c6c41", + "reference": "61efc01cf3dad84a436b17d95b44027a8b7c6c41", "shasum": "" }, "require": { @@ -13051,7 +13181,7 @@ "description": "Symfony Security Component - HTTP Integration", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/security-http/tree/v7.3.8" + "source": "https://github.com/symfony/security-http/tree/v7.3.9" }, "funding": [ { @@ -13071,20 +13201,20 @@ "type": "tidelift" } ], - "time": "2025-11-23T02:26:15+00:00" + "time": "2025-12-19T11:33:01+00:00" }, { "name": "symfony/serializer", - "version": "v7.3.8", + "version": "v7.3.9", "source": { "type": "git", "url": "https://github.com/symfony/serializer.git", - "reference": "e9f668bb3e69cc43571ddd9c2578fe442b6bc632" + "reference": "e6769b126ea7f9668beea94f68fbaf4ed88772f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/serializer/zipball/e9f668bb3e69cc43571ddd9c2578fe442b6bc632", - "reference": "e9f668bb3e69cc43571ddd9c2578fe442b6bc632", + "url": "https://api.github.com/repos/symfony/serializer/zipball/e6769b126ea7f9668beea94f68fbaf4ed88772f6", + "reference": "e6769b126ea7f9668beea94f68fbaf4ed88772f6", "shasum": "" }, "require": { @@ -13154,7 +13284,7 @@ "description": "Handles serializing and deserializing data structures, including object graphs, into array structures or other formats like XML and JSON.", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/serializer/tree/v7.3.8" + "source": "https://github.com/symfony/serializer/tree/v7.3.9" }, "funding": [ { @@ -13174,7 +13304,7 @@ "type": "tidelift" } ], - "time": "2025-11-12T15:21:00+00:00" + "time": "2025-12-23T14:45:27+00:00" }, { "name": "symfony/service-contracts", @@ -13417,16 +13547,16 @@ }, { "name": "symfony/translation", - "version": "v7.3.8", + "version": "v7.3.9", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "c586b151e8e06987d905679a11f1dd5cc5bc562b" + "reference": "b9bcef6c99cc63f67c2dd0603e7f55db72c7ed3a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/c586b151e8e06987d905679a11f1dd5cc5bc562b", - "reference": "c586b151e8e06987d905679a11f1dd5cc5bc562b", + "url": "https://api.github.com/repos/symfony/translation/zipball/b9bcef6c99cc63f67c2dd0603e7f55db72c7ed3a", + "reference": "b9bcef6c99cc63f67c2dd0603e7f55db72c7ed3a", "shasum": "" }, "require": { @@ -13493,7 +13623,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v7.3.8" + "source": "https://github.com/symfony/translation/tree/v7.3.9" }, "funding": [ { @@ -13513,7 +13643,7 @@ "type": "tidelift" } ], - "time": "2025-11-26T15:55:45+00:00" + "time": "2025-12-19T11:33:01+00:00" }, { "name": "symfony/translation-contracts", @@ -13599,16 +13729,16 @@ }, { "name": "symfony/twig-bridge", - "version": "v7.3.8", + "version": "v7.3.9", "source": { "type": "git", "url": "https://github.com/symfony/twig-bridge.git", - "reference": "2e9f47a405989f8a543f94160c0d530379b51510" + "reference": "accabb095e9d546ee045f4ff8f013bd7d78ff540" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/2e9f47a405989f8a543f94160c0d530379b51510", - "reference": "2e9f47a405989f8a543f94160c0d530379b51510", + "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/accabb095e9d546ee045f4ff8f013bd7d78ff540", + "reference": "accabb095e9d546ee045f4ff8f013bd7d78ff540", "shasum": "" }, "require": { @@ -13690,7 +13820,7 @@ "description": "Provides integration for Twig with various Symfony components", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/twig-bridge/tree/v7.3.8" + "source": "https://github.com/symfony/twig-bridge/tree/v7.3.9" }, "funding": [ { @@ -13710,20 +13840,20 @@ "type": "tidelift" } ], - "time": "2025-12-05T13:52:21+00:00" + "time": "2025-12-16T07:50:38+00:00" }, { "name": "symfony/twig-bundle", - "version": "v7.3.4", + "version": "v7.3.9", "source": { "type": "git", "url": "https://github.com/symfony/twig-bundle.git", - "reference": "da5c778a8416fcce5318737c4d944f6fa2bb3f81" + "reference": "67ce9929f47bd5875ff04317ac8f5b097b0a2990" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bundle/zipball/da5c778a8416fcce5318737c4d944f6fa2bb3f81", - "reference": "da5c778a8416fcce5318737c4d944f6fa2bb3f81", + "url": "https://api.github.com/repos/symfony/twig-bundle/zipball/67ce9929f47bd5875ff04317ac8f5b097b0a2990", + "reference": "67ce9929f47bd5875ff04317ac8f5b097b0a2990", "shasum": "" }, "require": { @@ -13778,7 +13908,7 @@ "description": "Provides a tight integration of Twig into the Symfony full-stack framework", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/twig-bundle/tree/v7.3.4" + "source": "https://github.com/symfony/twig-bundle/tree/v7.3.9" }, "funding": [ { @@ -13798,7 +13928,7 @@ "type": "tidelift" } ], - "time": "2025-09-10T12:00:31+00:00" + "time": "2025-12-19T08:58:15+00:00" }, { "name": "symfony/type-info", @@ -13959,16 +14089,16 @@ }, { "name": "symfony/validator", - "version": "v7.3.8", + "version": "v7.3.9", "source": { "type": "git", "url": "https://github.com/symfony/validator.git", - "reference": "f30a6aba4a09d5b5042e06d183ef248e14482313" + "reference": "344efc1f9af111e2a3aaca8990118fd231fb1412" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/validator/zipball/f30a6aba4a09d5b5042e06d183ef248e14482313", - "reference": "f30a6aba4a09d5b5042e06d183ef248e14482313", + "url": "https://api.github.com/repos/symfony/validator/zipball/344efc1f9af111e2a3aaca8990118fd231fb1412", + "reference": "344efc1f9af111e2a3aaca8990118fd231fb1412", "shasum": "" }, "require": { @@ -14037,7 +14167,7 @@ "description": "Provides tools to validate values", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/validator/tree/v7.3.8" + "source": "https://github.com/symfony/validator/tree/v7.3.9" }, "funding": [ { @@ -14057,7 +14187,7 @@ "type": "tidelift" } ], - "time": "2025-12-05T13:52:21+00:00" + "time": "2025-12-27T17:05:10+00:00" }, { "name": "symfony/var-dumper", @@ -14459,16 +14589,16 @@ }, { "name": "twig/extra-bundle", - "version": "v3.22.1", + "version": "v3.22.2", "source": { "type": "git", "url": "https://github.com/twigphp/twig-extra-bundle.git", - "reference": "b6534bc925bec930004facca92fccebd0c809247" + "reference": "09de9be7f6c0d19ede7b5a1dbfcfb2e9d1e0ea9e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/twig-extra-bundle/zipball/b6534bc925bec930004facca92fccebd0c809247", - "reference": "b6534bc925bec930004facca92fccebd0c809247", + "url": "https://api.github.com/repos/twigphp/twig-extra-bundle/zipball/09de9be7f6c0d19ede7b5a1dbfcfb2e9d1e0ea9e", + "reference": "09de9be7f6c0d19ede7b5a1dbfcfb2e9d1e0ea9e", "shasum": "" }, "require": { @@ -14517,7 +14647,7 @@ "twig" ], "support": { - "source": "https://github.com/twigphp/twig-extra-bundle/tree/v3.22.1" + "source": "https://github.com/twigphp/twig-extra-bundle/tree/v3.22.2" }, "funding": [ { @@ -14529,7 +14659,7 @@ "type": "tidelift" } ], - "time": "2025-11-02T11:00:49+00:00" + "time": "2025-12-05T08:51:53+00:00" }, { "name": "twig/intl-extra", @@ -14597,16 +14727,16 @@ }, { "name": "twig/twig", - "version": "v3.22.1", + "version": "v3.22.2", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "1de2ec1fc43ab58a4b7e80b214b96bfc895750f3" + "reference": "946ddeafa3c9f4ce279d1f34051af041db0e16f2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/1de2ec1fc43ab58a4b7e80b214b96bfc895750f3", - "reference": "1de2ec1fc43ab58a4b7e80b214b96bfc895750f3", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/946ddeafa3c9f4ce279d1f34051af041db0e16f2", + "reference": "946ddeafa3c9f4ce279d1f34051af041db0e16f2", "shasum": "" }, "require": { @@ -14660,7 +14790,7 @@ ], "support": { "issues": "https://github.com/twigphp/Twig/issues", - "source": "https://github.com/twigphp/Twig/tree/v3.22.1" + "source": "https://github.com/twigphp/Twig/tree/v3.22.2" }, "funding": [ { @@ -14672,20 +14802,20 @@ "type": "tidelift" } ], - "time": "2025-11-16T16:01:12+00:00" + "time": "2025-12-14T11:28:47+00:00" }, { "name": "vich/uploader-bundle", - "version": "v2.9.0", + "version": "v2.9.1", "source": { "type": "git", "url": "https://github.com/dustin10/VichUploaderBundle.git", - "reference": "deb1d70a46f3d4250801e8fa40bd52ffa3494d70" + "reference": "945939a04a33c0b78c5fbb7ead31533d85112df5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dustin10/VichUploaderBundle/zipball/deb1d70a46f3d4250801e8fa40bd52ffa3494d70", - "reference": "deb1d70a46f3d4250801e8fa40bd52ffa3494d70", + "url": "https://api.github.com/repos/dustin10/VichUploaderBundle/zipball/945939a04a33c0b78c5fbb7ead31533d85112df5", + "reference": "945939a04a33c0b78c5fbb7ead31533d85112df5", "shasum": "" }, "require": { @@ -14778,9 +14908,9 @@ ], "support": { "issues": "https://github.com/dustin10/VichUploaderBundle/issues", - "source": "https://github.com/dustin10/VichUploaderBundle/tree/v2.9.0" + "source": "https://github.com/dustin10/VichUploaderBundle/tree/v2.9.1" }, - "time": "2025-12-07T13:46:23+00:00" + "time": "2025-12-10T08:23:38+00:00" }, { "name": "voku/portable-ascii", @@ -14858,43 +14988,32 @@ }, { "name": "web-auth/cose-lib", - "version": "4.4.2", + "version": "4.5.0", "source": { "type": "git", "url": "https://github.com/web-auth/cose-lib.git", - "reference": "a93b61c48fb587855f64a9ec11ad7b60e867cb15" + "reference": "5adac6fe126994a3ee17ed9950efb4947ab132a9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/web-auth/cose-lib/zipball/a93b61c48fb587855f64a9ec11ad7b60e867cb15", - "reference": "a93b61c48fb587855f64a9ec11ad7b60e867cb15", + "url": "https://api.github.com/repos/web-auth/cose-lib/zipball/5adac6fe126994a3ee17ed9950efb4947ab132a9", + "reference": "5adac6fe126994a3ee17ed9950efb4947ab132a9", "shasum": "" }, "require": { - "brick/math": "^0.9|^0.10|^0.11|^0.12|^0.13", + "brick/math": "^0.9|^0.10|^0.11|^0.12|^0.13|^0.14", "ext-json": "*", "ext-openssl": "*", "php": ">=8.1", "spomky-labs/pki-framework": "^1.0" }, "require-dev": { - "deptrac/deptrac": "^3.0", - "ekino/phpstan-banned-code": "^1.0|^2.0|^3.0", - "infection/infection": "^0.29", - "php-parallel-lint/php-parallel-lint": "^1.3", - "phpstan/extension-installer": "^1.3", - "phpstan/phpstan": "^1.7|^2.0", - "phpstan/phpstan-deprecation-rules": "^1.0|^2.0", - "phpstan/phpstan-phpunit": "^1.1|^2.0", - "phpstan/phpstan-strict-rules": "^1.0|^2.0", - "phpunit/phpunit": "^10.1|^11.0|^12.0", - "rector/rector": "^2.0", - "symfony/phpunit-bridge": "^6.4|^7.0", - "symplify/easy-coding-standard": "^12.0" + "spomky-labs/cbor-php": "^3.2.2" }, "suggest": { "ext-bcmath": "For better performance, please install either GMP (recommended) or BCMath extension", - "ext-gmp": "For better performance, please install either GMP (recommended) or BCMath extension" + "ext-gmp": "For better performance, please install either GMP (recommended) or BCMath extension", + "spomky-labs/cbor-php": "For COSE Signature support" }, "type": "library", "autoload": { @@ -14924,7 +15043,7 @@ ], "support": { "issues": "https://github.com/web-auth/cose-lib/issues", - "source": "https://github.com/web-auth/cose-lib/tree/4.4.2" + "source": "https://github.com/web-auth/cose-lib/tree/4.5.0" }, "funding": [ { @@ -14936,20 +15055,20 @@ "type": "patreon" } ], - "time": "2025-08-14T20:33:29+00:00" + "time": "2026-01-03T14:43:18+00:00" }, { "name": "web-auth/webauthn-lib", - "version": "5.2.2", + "version": "5.2.3", "source": { "type": "git", "url": "https://github.com/web-auth/webauthn-lib.git", - "reference": "8937c397c8ae91b5af422ca8aa915c756062da74" + "reference": "8782f575032fedc36e2eb27c39c736054e2b6867" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/web-auth/webauthn-lib/zipball/8937c397c8ae91b5af422ca8aa915c756062da74", - "reference": "8937c397c8ae91b5af422ca8aa915c756062da74", + "url": "https://api.github.com/repos/web-auth/webauthn-lib/zipball/8782f575032fedc36e2eb27c39c736054e2b6867", + "reference": "8782f575032fedc36e2eb27c39c736054e2b6867", "shasum": "" }, "require": { @@ -15010,7 +15129,7 @@ "webauthn" ], "support": { - "source": "https://github.com/web-auth/webauthn-lib/tree/5.2.2" + "source": "https://github.com/web-auth/webauthn-lib/tree/5.2.3" }, "funding": [ { @@ -15022,20 +15141,20 @@ "type": "patreon" } ], - "time": "2025-03-16T14:38:43+00:00" + "time": "2025-12-20T10:54:02+00:00" }, { "name": "web-token/jwt-library", - "version": "4.1.2", + "version": "4.1.3", "source": { "type": "git", "url": "https://github.com/web-token/jwt-library.git", - "reference": "621ff3ec618c6a34f63d47e467cefe8788871d6f" + "reference": "690d4dd47b78f423cb90457f858e4106e1deb728" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/web-token/jwt-library/zipball/621ff3ec618c6a34f63d47e467cefe8788871d6f", - "reference": "621ff3ec618c6a34f63d47e467cefe8788871d6f", + "url": "https://api.github.com/repos/web-token/jwt-library/zipball/690d4dd47b78f423cb90457f858e4106e1deb728", + "reference": "690d4dd47b78f423cb90457f858e4106e1deb728", "shasum": "" }, "require": { @@ -15099,7 +15218,7 @@ ], "support": { "issues": "https://github.com/web-token/jwt-library/issues", - "source": "https://github.com/web-token/jwt-library/tree/4.1.2" + "source": "https://github.com/web-token/jwt-library/tree/4.1.3" }, "funding": [ { @@ -15111,27 +15230,27 @@ "type": "patreon" } ], - "time": "2025-11-17T21:14:49+00:00" + "time": "2025-12-18T14:27:35+00:00" }, { "name": "webmozart/assert", - "version": "1.12.1", + "version": "2.1.2", "source": { "type": "git", "url": "https://github.com/webmozarts/assert.git", - "reference": "9be6926d8b485f55b9229203f962b51ed377ba68" + "reference": "ce6a2f100c404b2d32a1dd1270f9b59ad4f57649" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozarts/assert/zipball/9be6926d8b485f55b9229203f962b51ed377ba68", - "reference": "9be6926d8b485f55b9229203f962b51ed377ba68", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/ce6a2f100c404b2d32a1dd1270f9b59ad4f57649", + "reference": "ce6a2f100c404b2d32a1dd1270f9b59ad4f57649", "shasum": "" }, "require": { "ext-ctype": "*", "ext-date": "*", "ext-filter": "*", - "php": "^7.2 || ^8.0" + "php": "^8.2" }, "suggest": { "ext-intl": "", @@ -15141,7 +15260,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.10-dev" + "dev-feature/2-0": "2.0-dev" } }, "autoload": { @@ -15157,6 +15276,10 @@ { "name": "Bernhard Schussek", "email": "bschussek@gmail.com" + }, + { + "name": "Woody Gilk", + "email": "woody.gilk@gmail.com" } ], "description": "Assertions to validate method input/output with nice error messages.", @@ -15167,9 +15290,9 @@ ], "support": { "issues": "https://github.com/webmozarts/assert/issues", - "source": "https://github.com/webmozarts/assert/tree/1.12.1" + "source": "https://github.com/webmozarts/assert/tree/2.1.2" }, - "time": "2025-10-29T15:56:20+00:00" + "time": "2026-01-13T14:02:24+00:00" } ], "packages-dev": [ @@ -15594,16 +15717,16 @@ }, { "name": "phpunit/php-code-coverage", - "version": "12.5.1", + "version": "12.5.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "c467c59a4f6e04b942be422844e7a6352fa01b57" + "reference": "4a9739b51cbcb355f6e95659612f92e282a7077b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/c467c59a4f6e04b942be422844e7a6352fa01b57", - "reference": "c467c59a4f6e04b942be422844e7a6352fa01b57", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/4a9739b51cbcb355f6e95659612f92e282a7077b", + "reference": "4a9739b51cbcb355f6e95659612f92e282a7077b", "shasum": "" }, "require": { @@ -15618,7 +15741,7 @@ "sebastian/environment": "^8.0.3", "sebastian/lines-of-code": "^4.0", "sebastian/version": "^6.0", - "theseer/tokenizer": "^2.0" + "theseer/tokenizer": "^2.0.1" }, "require-dev": { "phpunit/phpunit": "^12.5.1" @@ -15659,7 +15782,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/12.5.1" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/12.5.2" }, "funding": [ { @@ -15679,7 +15802,7 @@ "type": "tidelift" } ], - "time": "2025-12-08T07:17:58+00:00" + "time": "2025-12-24T07:03:04+00:00" }, { "name": "phpunit/php-file-iterator", @@ -15928,16 +16051,16 @@ }, { "name": "phpunit/phpunit", - "version": "12.5.2", + "version": "12.5.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "06713c2633d6d832f2fe98a70511ecaa7cb92c1a" + "reference": "ba2d126905713bcf802c7f1e0d7507092ce9bf9a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/06713c2633d6d832f2fe98a70511ecaa7cb92c1a", - "reference": "06713c2633d6d832f2fe98a70511ecaa7cb92c1a", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/ba2d126905713bcf802c7f1e0d7507092ce9bf9a", + "reference": "ba2d126905713bcf802c7f1e0d7507092ce9bf9a", "shasum": "" }, "require": { @@ -15951,7 +16074,7 @@ "phar-io/manifest": "^2.0.4", "phar-io/version": "^3.2.1", "php": ">=8.3", - "phpunit/php-code-coverage": "^12.5.1", + "phpunit/php-code-coverage": "^12.5.2", "phpunit/php-file-iterator": "^6.0.0", "phpunit/php-invoker": "^6.0.0", "phpunit/php-text-template": "^5.0.0", @@ -16005,7 +16128,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/12.5.2" + "source": "https://github.com/sebastianbergmann/phpunit/tree/12.5.5" }, "funding": [ { @@ -16029,20 +16152,20 @@ "type": "tidelift" } ], - "time": "2025-12-08T07:22:32+00:00" + "time": "2026-01-15T12:03:46+00:00" }, { "name": "rector/rector", - "version": "2.2.14", + "version": "2.3.1", "source": { "type": "git", "url": "https://github.com/rectorphp/rector.git", - "reference": "6d56bb0e94d4df4f57a78610550ac76ab403657d" + "reference": "9afc1bb43571b25629f353c61a9315b5ef31383a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/rectorphp/rector/zipball/6d56bb0e94d4df4f57a78610550ac76ab403657d", - "reference": "6d56bb0e94d4df4f57a78610550ac76ab403657d", + "url": "https://api.github.com/repos/rectorphp/rector/zipball/9afc1bb43571b25629f353c61a9315b5ef31383a", + "reference": "9afc1bb43571b25629f353c61a9315b5ef31383a", "shasum": "" }, "require": { @@ -16081,7 +16204,7 @@ ], "support": { "issues": "https://github.com/rectorphp/rector/issues", - "source": "https://github.com/rectorphp/rector/tree/2.2.14" + "source": "https://github.com/rectorphp/rector/tree/2.3.1" }, "funding": [ { @@ -16089,7 +16212,7 @@ "type": "github" } ], - "time": "2025-12-09T10:57:55+00:00" + "time": "2026-01-13T15:13:58+00:00" }, { "name": "sebastian/cli-parser", @@ -17042,16 +17165,16 @@ }, { "name": "symfony/browser-kit", - "version": "v7.3.6", + "version": "v7.3.9", "source": { "type": "git", "url": "https://github.com/symfony/browser-kit.git", - "reference": "e9a9fd604296b17bf90939c3647069f1f16ef04e" + "reference": "9403aa24cacd754493c988e0bde22cadb509be5e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/browser-kit/zipball/e9a9fd604296b17bf90939c3647069f1f16ef04e", - "reference": "e9a9fd604296b17bf90939c3647069f1f16ef04e", + "url": "https://api.github.com/repos/symfony/browser-kit/zipball/9403aa24cacd754493c988e0bde22cadb509be5e", + "reference": "9403aa24cacd754493c988e0bde22cadb509be5e", "shasum": "" }, "require": { @@ -17090,7 +17213,7 @@ "description": "Simulates the behavior of a web browser, allowing you to make requests, click on links and submit forms programmatically", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/browser-kit/tree/v7.3.6" + "source": "https://github.com/symfony/browser-kit/tree/v7.3.9" }, "funding": [ { @@ -17110,7 +17233,7 @@ "type": "tidelift" } ], - "time": "2025-11-05T07:57:47+00:00" + "time": "2025-12-14T08:06:00+00:00" }, { "name": "symfony/css-selector", @@ -17427,16 +17550,16 @@ }, { "name": "symfony/web-profiler-bundle", - "version": "v7.3.5", + "version": "v7.3.9", "source": { "type": "git", "url": "https://github.com/symfony/web-profiler-bundle.git", - "reference": "c2ed11cc0e9093fe0425ad52498d26a458842e0c" + "reference": "42c439f0d9a62b845700e037e8f4997cfa7119d7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/c2ed11cc0e9093fe0425ad52498d26a458842e0c", - "reference": "c2ed11cc0e9093fe0425ad52498d26a458842e0c", + "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/42c439f0d9a62b845700e037e8f4997cfa7119d7", + "reference": "42c439f0d9a62b845700e037e8f4997cfa7119d7", "shasum": "" }, "require": { @@ -17492,7 +17615,7 @@ "dev" ], "support": { - "source": "https://github.com/symfony/web-profiler-bundle/tree/v7.3.5" + "source": "https://github.com/symfony/web-profiler-bundle/tree/v7.3.9" }, "funding": [ { @@ -17512,7 +17635,7 @@ "type": "tidelift" } ], - "time": "2025-10-06T13:36:11+00:00" + "time": "2025-12-26T06:49:41+00:00" }, { "name": "theseer/tokenizer", diff --git a/config/bundles.php b/config/bundles.php index 8781dbc..77def6c 100644 --- a/config/bundles.php +++ b/config/bundles.php @@ -18,4 +18,5 @@ return [ Presta\SitemapBundle\PrestaSitemapBundle::class => ['all' => true], Sentry\SentryBundle\SentryBundle::class => ['prod' => true], Vich\UploaderBundle\VichUploaderBundle::class => ['all' => true], + KnpU\OAuth2ClientBundle\KnpUOAuth2ClientBundle::class => ['all' => true], ]; diff --git a/config/packages/knpu_oauth2_client.yaml b/config/packages/knpu_oauth2_client.yaml new file mode 100644 index 0000000..95e20b7 --- /dev/null +++ b/config/packages/knpu_oauth2_client.yaml @@ -0,0 +1,13 @@ +knpu_oauth2_client: + clients: + # This key 'keycloak' is what you'll use in your code + keycloak: + type: keycloak + # All these should be stored in your .env file + auth_server_url: '%env(KEYCLOAK_AUTH_SERVER_URL)%' + realm: '%env(KEYCLOAK_REALM)%' + client_id: '%env(KEYCLOAK_CLIENT_ID)%' + client_secret: '%env(KEYCLOAK_CLIENT_SECRET)%' + # The route name where Keycloak will redirect the user back to + redirect_route: connect_keycloak_check + redirect_params: {} diff --git a/config/packages/security.yaml b/config/packages/security.yaml index 9db2dc1..98fd2e3 100644 --- a/config/packages/security.yaml +++ b/config/packages/security.yaml @@ -27,6 +27,7 @@ security: entry_point: App\Security\AuthenticationEntryPoint custom_authenticator: - App\Security\LoginFormAuthenticator + - App\Security\KeycloakAuthenticator logout: target: app_logout @@ -40,9 +41,8 @@ security: # algorithm: bcrypt role_hierarchy: - ROLE_ROOT: [ROLE_ADMIN] # ROLE_ROOT inclut ROLE_ADMIN, qui à son tour inclut ROLE_ARTEMIS + ROLE_ROOT: [ROLE_ADMIN] # access_control: - { path: ^/admin, roles: [ROLE_ADMIN] } - - { path: ^/console, roles: [ROLE_COSPLAY] } - { path: ^/, roles: PUBLIC_ACCESS } # Toutes les autres pages nécessitent une authentification complète diff --git a/docker-compose.yml b/docker-compose.yml index 3678339..ca5b374 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -111,65 +111,16 @@ services: # --- Service de Test d'Emails (MailHog) --- # Intercepte tous les emails envoyés en développement mailhog: - image: mailhog/mailhog:latest - container_name: crm_mailhog + image: axllent/mailpit:latest ports: - # Port 1025 pour le serveur SMTP factice - - "1025:1025" - # Port 8025 pour l'interface web de MailHog - - "8025:8025" + - "1025:1025" + - "8025:8025" networks: - - crm_network # Assignation au réseau commun - - # --- Service de Stockage Fichiers (MinIO) --- - # Fournit une API compatible S3 pour le stockage de fichiers - minio: - image: minio/minio:RELEASE.2025-02-03T21-03-04Z - container_name: crm_minio - ports: - # Port 9000 pour l'API S3 - - "9000:9000" - # Port 9001 pour la console web de MinIO - - "9001:9001" - environment: - MINIO_ROOT_USER: minio_user - MINIO_ROOT_PASSWORD: ChangeMeInProd! - volumes: - # Volume nommé pour la persistance des fichiers - - minio_data:/data - # Commande pour démarrer MinIO et lancer la console sur le bon port - command: server /data --console-address ":9001" - networks: - - crm_network # Assignation au réseau commun - - # --- Service de Gestion des Secrets (HashiCorp Vault) --- - vault: - image: hashicorp/vault:latest - container_name: crm_vault - ports: - - "8210:8200" # Mappe le port 8210 de l'hôte au port 8200 du conteneur Vault - - "8211:8201" # Mappe le port 8210 de l'hôte au port 8200 du conteneur Vault - - "8212:8202" # Mappe le port 8212 de l'hôte au port 8200 du conteneur Vault - volumes: - # Volume pour la persistance des données - - vault_data:/vault - # Volume pour monter notre fichier de configuration - environment: - VAULT_DEV_ROOT_TOKEN_ID: myroot - VAULT_DEV_LISTEN_ADDRESS: 0.0.0.0:8201 - VAULT_LOCAL_CONFIG: '{"storage": {"file": {"path": "/vault/file"}}, "listener": [{"tcp": { "address": "0.0.0.0:8200", "tls_disable": true}}], "default_lease_ttl": "168h", "max_lease_ttl": "720h", "ui": true,"disable_mlock": false}' - # Lance Vault en mode serveur avec notre fichier de configuration - cap_add: - - IPC_LOCK - command: "server -dev" - networks: - - crm_network # Assignation au réseau commun + - crm_network # Assignation au réseau commun # Définition des volumes pour la persistance des données volumes: db_data: # Pour la base de données principale de Symfony - minio_data: # Pour le stockage de fichiers MinIO - vault_data: # Pour les données de HashiCorp Vault # Définition des réseaux networks: diff --git a/makefile b/makefile index 5129eb6..548c602 100644 --- a/makefile +++ b/makefile @@ -48,7 +48,8 @@ migrate: ## Applique les migrations composer-install: ## Installe les dépendances Composer @$(PHP_EXEC) composer install deps: composer-install ## Alias pour composer-install - +db_remove: ## Crée la base de données + @$(CONSOLE) doctrine:database:drop --force dbtest_add: ## Crée la base de données @$(CONSOLE) doctrine:database:create --env=test dbtest_migrate: ## Crée la base de données diff --git a/migrations/Version20251209163956.php b/migrations/Version20251211203538.php similarity index 98% rename from migrations/Version20251209163956.php rename to migrations/Version20251211203538.php index 1e99171..3415081 100644 --- a/migrations/Version20251209163956.php +++ b/migrations/Version20251211203538.php @@ -10,7 +10,7 @@ use Doctrine\Migrations\AbstractMigration; /** * Auto-generated Migration: Please modify to your needs! */ -final class Version20251209163956 extends AbstractMigration +final class Version20251211203538 extends AbstractMigration { public function getDescription(): string { diff --git a/migrations/Version20260115165200.php b/migrations/Version20260115165200.php new file mode 100644 index 0000000..db2a964 --- /dev/null +++ b/migrations/Version20260115165200.php @@ -0,0 +1,44 @@ +addSql('ALTER TABLE account ADD keycloak_id VARCHAR(255) DEFAULT NULL'); + $this->addSql('ALTER TABLE account ADD first_name VARCHAR(255) DEFAULT NULL'); + $this->addSql('ALTER TABLE account ADD name VARCHAR(255) DEFAULT NULL'); + $this->addSql('DROP INDEX idx_75ea56e016ba31db'); + $this->addSql('DROP INDEX idx_75ea56e0e3bd61ce'); + $this->addSql('DROP INDEX idx_75ea56e0fb7336f0'); + $this->addSql('CREATE INDEX IDX_75EA56E0FB7336F0E3BD61CE16BA31DBBF396750 ON messenger_messages (queue_name, available_at, delivered_at, id)'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('CREATE SCHEMA public'); + $this->addSql('ALTER TABLE "account" DROP keycloak_id'); + $this->addSql('ALTER TABLE "account" DROP first_name'); + $this->addSql('ALTER TABLE "account" DROP name'); + $this->addSql('DROP INDEX IDX_75EA56E0FB7336F0E3BD61CE16BA31DBBF396750'); + $this->addSql('CREATE INDEX idx_75ea56e016ba31db ON messenger_messages (delivered_at)'); + $this->addSql('CREATE INDEX idx_75ea56e0e3bd61ce ON messenger_messages (available_at)'); + $this->addSql('CREATE INDEX idx_75ea56e0fb7336f0 ON messenger_messages (queue_name)'); + } +} diff --git a/migrations/Version20260115165808.php b/migrations/Version20260115165808.php new file mode 100644 index 0000000..2bbc80e --- /dev/null +++ b/migrations/Version20260115165808.php @@ -0,0 +1,32 @@ +addSql('ALTER TABLE account ALTER password DROP NOT NULL'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('CREATE SCHEMA public'); + $this->addSql('ALTER TABLE "account" ALTER password SET NOT NULL'); + } +} diff --git a/public/assets/images/logo.png b/public/assets/images/logo.png new file mode 100644 index 0000000..30aad0a Binary files /dev/null and b/public/assets/images/logo.png differ diff --git a/src/Command/AccountCommand.php b/src/Command/AccountCommand.php deleted file mode 100644 index a157dd9..0000000 --- a/src/Command/AccountCommand.php +++ /dev/null @@ -1,66 +0,0 @@ -title("Création d'un utilisateur administrateur"); - - - - $existingUser = $this->entityManager->getRepository(Account::class)->findOneBy(['email' => "jovann@siteconseil.fr"]); - if (!$existingUser instanceof Account) { - $password = TempPasswordGenerator::generate(); - $newUser = new Account(); - $newUser->setRoles(['ROLE_ROOT']); - $newUser->setUuid(Uuid::v4()); - $newUser->setIsActif(true); - $newUser->setIsFirstLogin(true); - $newUser->setEmail("jovann@siteconseil.fr"); - $newUser->setUsername("Jovann"); - - - - $hashedPassword = $this->userPasswordHasher->hashPassword($newUser, $password); - $newUser->setPassword($hashedPassword); - $this->eventDispatcher->dispatch(new CreatedAdminEvent($newUser,$password)); - - $this->entityManager->persist($newUser); - $this->entityManager->flush(); - - - $io->success("Utilisateur administrateur créé avec succès."); - } else { - $io->warning("Un utilisateur avec l'email existe déjà."); - } - - return Command::SUCCESS; - } -} diff --git a/src/Controller/Dashboard/HomeController.php b/src/Controller/Dashboard/HomeController.php new file mode 100644 index 0000000..0127c25 --- /dev/null +++ b/src/Controller/Dashboard/HomeController.php @@ -0,0 +1,40 @@ + false], methods: ['GET','POST'])] + public function crm(): Response + { + return $this->render('dashboard/home.twig'); + } + + + #[Route(path: '/crm/administrateur', name: 'app_crm_administrateur', options: ['sitemap' => false], methods: ['GET','POST'])] + public function administrateur(AccountRepository $accountRepository): Response + { + return $this->render('dashboard/administrateur.twig',[ + 'admins' => $accountRepository->findAll(), + ]); + } +} diff --git a/src/Controller/HomeController.php b/src/Controller/HomeController.php index 9f9ec44..fd41b9b 100644 --- a/src/Controller/HomeController.php +++ b/src/Controller/HomeController.php @@ -8,6 +8,7 @@ use App\Form\RequestPasswordConfirmType; use App\Form\RequestPasswordRequestType; use App\Service\ResetPassword\Event\ResetPasswordConfirmEvent; use App\Service\ResetPassword\Event\ResetPasswordEvent; +use KnpU\OAuth2ClientBundle\Client\ClientRegistry; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\HttpFoundation\JsonResponse; @@ -21,9 +22,27 @@ use Symfony\Contracts\HttpClient\HttpClientInterface; class HomeController extends AbstractController { - #[Route(path: '/', name: 'app_home', options: ['sitemap' => false], methods: ['GET'])] + + #[Route('/connect/keycloak', name: 'connect_keycloak_start')] + public function connect(ClientRegistry $clientRegistry) + { + // Redirects to Keycloak + return $clientRegistry + ->getClient('keycloak') + ->redirect(['email', 'profile','openid'], []); + } + + #[Route('/oauth/sso', name: 'connect_keycloak_check')] + public function connectCheck(Request $request) + { + // This method stays empty; the authenticator will intercept it! + } + #[Route(path: '/', name: 'app_home', options: ['sitemap' => false], methods: ['GET','POST'])] public function index(AuthenticationUtils $authenticationUtils): Response { + if($this->getUser()){ + return $this->redirectToRoute('app_crm'); + } return $this->render('home.twig',[ 'last_username' => $authenticationUtils->getLastUsername(), 'error' => $authenticationUtils->getLastAuthenticationError(), diff --git a/src/Entity/Account.php b/src/Entity/Account.php index 9c93382..46d3dd2 100644 --- a/src/Entity/Account.php +++ b/src/Entity/Account.php @@ -34,7 +34,7 @@ class Account implements UserInterface, PasswordAuthenticatedUserInterface, \Ser #[ORM\Column] private array $roles = []; - #[ORM\Column] + #[ORM\Column(nullable: true)] private ?string $password = null; #[ORM\Column(length: 255)] @@ -57,6 +57,15 @@ class Account implements UserInterface, PasswordAuthenticatedUserInterface, \Ser #[ORM\Column(nullable: true)] private ?bool $isActif = null; + #[ORM\Column(length: 255, nullable: true)] + private ?string $keycloakId = null; + + #[ORM\Column(length: 255, nullable: true)] + private ?string $firstName = null; + + #[ORM\Column(length: 255, nullable: true)] + private ?string $name = null; + public function __construct() { @@ -190,7 +199,6 @@ class Account implements UserInterface, PasswordAuthenticatedUserInterface, \Ser $this->id, $this->email, $this->username, - $this->avatarFileName, )); } @@ -200,7 +208,6 @@ class Account implements UserInterface, PasswordAuthenticatedUserInterface, \Ser $this->id, $this->email, $this->username, - $this->avatarFileName, ) = unserialize($data); } @@ -245,4 +252,40 @@ class Account implements UserInterface, PasswordAuthenticatedUserInterface, \Ser return $this; } + + public function getKeycloakId(): ?string + { + return $this->keycloakId; + } + + public function setKeycloakId(?string $keycloakId): static + { + $this->keycloakId = $keycloakId; + + return $this; + } + + public function getFirstName(): ?string + { + return $this->firstName; + } + + public function setFirstName(?string $firstName): static + { + $this->firstName = $firstName; + + return $this; + } + + public function getName(): ?string + { + return $this->name; + } + + public function setName(?string $name): static + { + $this->name = $name; + + return $this; + } } diff --git a/src/Security/KeycloakAuthenticator.php b/src/Security/KeycloakAuthenticator.php new file mode 100644 index 0000000..4c75487 --- /dev/null +++ b/src/Security/KeycloakAuthenticator.php @@ -0,0 +1,101 @@ +clientRegistry = $clientRegistry; + $this->entityManager = $entityManager; + $this->router = $router; + } + + public function supports(Request $request): ?bool + { + // match the route name from the controller + return $request->attributes->get('_route') === 'connect_keycloak_check'; + } + + public function authenticate(Request $request): Passport + { + $client = $this->clientRegistry->getClient('keycloak'); + $accessToken = $this->fetchAccessToken($client); + + return new SelfValidatingPassport( + new UserBadge($accessToken->getToken(), function() use ($accessToken, $client) { + /** @var \Stevenmaguire\OAuth2\Client\Provider\KeycloakResourceOwner $keycloakUser */ + $keycloakUser = $client->fetchUserFromToken($accessToken); + + + $email = $keycloakUser->getEmail(); + + $existingUser = $this->entityManager->getRepository(Account::class)->findOneBy(['keycloakId' => $keycloakUser->getId()]); + + if ($existingUser) { + return $existingUser; + } + + // 2) Optional: Find by email if ID doesn't match (syncing) + $user = $this->entityManager->getRepository(Account::class)->findOneBy(['email' => $email]); + + if (!$user) { + // 3) Create a new user if they don't exist + $user = new Account(); + $user->setUuid(Uuid::v4()); + $user->setRoles(['ROLE_ROOT']); + $user->setIsActif(true); + $user->setIsFirstLogin(false); + $user->setUsername($keycloakUser->getUsername()); + $user->setFirstName($keycloakUser->toArray()['given_name']); + $user->setName($keycloakUser->toArray()['family_name']); + $user->setEmail($email); + } + + $user->setKeycloakId($keycloakUser->getId()); + $this->entityManager->persist($user); + $this->entityManager->flush(); + + return $user; + }) + ); + } + + public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response + { + // Redirect to your homepage or dashboard after login + return new RedirectResponse($this->router->generate('app_home')); + } + + public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response + { + $message = strtr($exception->getMessageKey(), $exception->getMessageData()); + return new Response($message, Response::HTTP_FORBIDDEN); + } + + public function start(Request $request, AuthenticationException $authException = null): Response + { + return new RedirectResponse($this->router->generate('connect_keycloak_start')); + } +} diff --git a/src/Service/Mailer/MailerSubscriber.php b/src/Service/Mailer/MailerSubscriber.php index d4df803..4172a4e 100644 --- a/src/Service/Mailer/MailerSubscriber.php +++ b/src/Service/Mailer/MailerSubscriber.php @@ -23,7 +23,7 @@ class MailerSubscriber $this->mailer->send( $account->getEmail(), $account->getUsername(), - "[CRM] - Création d'un compte administrateur", + "[LudikEvent] - Création d'un compte administrateur", "mails/new_admin.twig", [ 'username' => $account->getUsername(), diff --git a/symfony.lock b/symfony.lock index f79524d..5a428db 100644 --- a/symfony.lock +++ b/symfony.lock @@ -50,6 +50,18 @@ "knplabs/knp-paginator-bundle": { "version": "v6.10.0" }, + "knpuniversity/oauth2-client-bundle": { + "version": "2.20", + "recipe": { + "repo": "github.com/symfony/recipes-contrib", + "branch": "main", + "version": "1.20", + "ref": "1ff300d8c030f55c99219cc55050b97a695af3f6" + }, + "files": [ + "config/packages/knpu_oauth2_client.yaml" + ] + }, "league/flysystem-bundle": { "version": "3.6", "recipe": { diff --git a/templates/base.twig b/templates/base.twig index 2f18aa5..d36f37a 100644 --- a/templates/base.twig +++ b/templates/base.twig @@ -4,7 +4,7 @@ -