Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c88333b052 | ||
| 8f5cd98b82 | |||
| 48f7e4c6ac | |||
| c46769a67d | |||
|
|
28394ce1b4 | ||
|
|
8cfcb41a39 | ||
|
|
980a7c310e | ||
|
|
00f18d1c7d |
@@ -7,6 +7,13 @@
|
||||
"X-Profile-Id": "admin-default-profile",
|
||||
"X-Profile-Password": "A123"
|
||||
}
|
||||
},
|
||||
"lesstime": {
|
||||
"type": "http",
|
||||
"url": "http://project.malio-dev.fr/_mcp",
|
||||
"headers": {
|
||||
"Authorization": "Bearer b355c6cbf27d2a86d7eba1c3132c99bb3133f94cfd9e9243ffcc3c5ae1dc82c8"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
"symfony/framework-bundle": "8.0.*",
|
||||
"symfony/mcp-bundle": "^0.6.0",
|
||||
"symfony/mime": "8.0.*",
|
||||
"symfony/monolog-bundle": "^4.0.2",
|
||||
"symfony/property-access": "8.0.*",
|
||||
"symfony/property-info": "8.0.*",
|
||||
"symfony/rate-limiter": "8.0.*",
|
||||
|
||||
261
composer.lock
generated
261
composer.lock
generated
@@ -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": "f94dc3c05e9ba6be99c510aad3d17182",
|
||||
"content-hash": "5c54b1589d9e815f4c9b7e5e1d2d69c7",
|
||||
"packages": [
|
||||
{
|
||||
"name": "api-platform/doctrine-common",
|
||||
@@ -2437,6 +2437,109 @@
|
||||
},
|
||||
"time": "2026-02-23T21:42:54+00:00"
|
||||
},
|
||||
{
|
||||
"name": "monolog/monolog",
|
||||
"version": "3.10.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Seldaek/monolog.git",
|
||||
"reference": "b321dd6749f0bf7189444158a3ce785cc16d69b0"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Seldaek/monolog/zipball/b321dd6749f0bf7189444158a3ce785cc16d69b0",
|
||||
"reference": "b321dd6749f0bf7189444158a3ce785cc16d69b0",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.1",
|
||||
"psr/log": "^2.0 || ^3.0"
|
||||
},
|
||||
"provide": {
|
||||
"psr/log-implementation": "3.0.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"aws/aws-sdk-php": "^3.0",
|
||||
"doctrine/couchdb": "~1.0@dev",
|
||||
"elasticsearch/elasticsearch": "^7 || ^8",
|
||||
"ext-json": "*",
|
||||
"graylog2/gelf-php": "^1.4.2 || ^2.0",
|
||||
"guzzlehttp/guzzle": "^7.4.5",
|
||||
"guzzlehttp/psr7": "^2.2",
|
||||
"mongodb/mongodb": "^1.8 || ^2.0",
|
||||
"php-amqplib/php-amqplib": "~2.4 || ^3",
|
||||
"php-console/php-console": "^3.1.8",
|
||||
"phpstan/phpstan": "^2",
|
||||
"phpstan/phpstan-deprecation-rules": "^2",
|
||||
"phpstan/phpstan-strict-rules": "^2",
|
||||
"phpunit/phpunit": "^10.5.17 || ^11.0.7",
|
||||
"predis/predis": "^1.1 || ^2",
|
||||
"rollbar/rollbar": "^4.0",
|
||||
"ruflin/elastica": "^7 || ^8",
|
||||
"symfony/mailer": "^5.4 || ^6",
|
||||
"symfony/mime": "^5.4 || ^6"
|
||||
},
|
||||
"suggest": {
|
||||
"aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB",
|
||||
"doctrine/couchdb": "Allow sending log messages to a CouchDB server",
|
||||
"elasticsearch/elasticsearch": "Allow sending log messages to an Elasticsearch server via official client",
|
||||
"ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)",
|
||||
"ext-curl": "Required to send log messages using the IFTTTHandler, the LogglyHandler, the SendGridHandler, the SlackWebhookHandler or the TelegramBotHandler",
|
||||
"ext-mbstring": "Allow to work properly with unicode symbols",
|
||||
"ext-mongodb": "Allow sending log messages to a MongoDB server (via driver)",
|
||||
"ext-openssl": "Required to send log messages using SSL",
|
||||
"ext-sockets": "Allow sending log messages to a Syslog server (via UDP driver)",
|
||||
"graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server",
|
||||
"mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)",
|
||||
"php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib",
|
||||
"rollbar/rollbar": "Allow sending log messages to Rollbar",
|
||||
"ruflin/elastica": "Allow sending log messages to an Elastic Search server"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "3.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Monolog\\": "src/Monolog"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Jordi Boggiano",
|
||||
"email": "j.boggiano@seld.be",
|
||||
"homepage": "https://seld.be"
|
||||
}
|
||||
],
|
||||
"description": "Sends your logs to files, sockets, inboxes, databases and various web services",
|
||||
"homepage": "https://github.com/Seldaek/monolog",
|
||||
"keywords": [
|
||||
"log",
|
||||
"logging",
|
||||
"psr-3"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/Seldaek/monolog/issues",
|
||||
"source": "https://github.com/Seldaek/monolog/tree/3.10.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/Seldaek",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/monolog/monolog",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-01-02T08:56:05+00:00"
|
||||
},
|
||||
{
|
||||
"name": "nelmio/cors-bundle",
|
||||
"version": "2.6.0",
|
||||
@@ -5427,6 +5530,162 @@
|
||||
],
|
||||
"time": "2026-03-30T15:14:47+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/monolog-bridge",
|
||||
"version": "v8.0.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/monolog-bridge.git",
|
||||
"reference": "c6efdcbd5cc17cf7618fb4447053b792df6ae724"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/monolog-bridge/zipball/c6efdcbd5cc17cf7618fb4447053b792df6ae724",
|
||||
"reference": "c6efdcbd5cc17cf7618fb4447053b792df6ae724",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"monolog/monolog": "^3",
|
||||
"php": ">=8.4",
|
||||
"symfony/http-kernel": "^7.4|^8.0",
|
||||
"symfony/service-contracts": "^2.5|^3"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/console": "^7.4|^8.0",
|
||||
"symfony/http-client": "^7.4|^8.0",
|
||||
"symfony/mailer": "^7.4|^8.0",
|
||||
"symfony/messenger": "^7.4|^8.0",
|
||||
"symfony/mime": "^7.4|^8.0",
|
||||
"symfony/security-core": "^7.4|^8.0",
|
||||
"symfony/var-dumper": "^7.4|^8.0"
|
||||
},
|
||||
"type": "symfony-bridge",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Bridge\\Monolog\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Provides integration for Monolog with various Symfony components",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/monolog-bridge/tree/v8.0.8"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"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": "2026-03-30T15:14:47+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/monolog-bundle",
|
||||
"version": "v4.0.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/monolog-bundle.git",
|
||||
"reference": "c012c6aba13129eb02aa7dd61e66e720911d8598"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/monolog-bundle/zipball/c012c6aba13129eb02aa7dd61e66e720911d8598",
|
||||
"reference": "c012c6aba13129eb02aa7dd61e66e720911d8598",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"composer-runtime-api": "^2.0",
|
||||
"monolog/monolog": "^3.5",
|
||||
"php": ">=8.2",
|
||||
"symfony/config": "^7.3 || ^8.0",
|
||||
"symfony/dependency-injection": "^7.3 || ^8.0",
|
||||
"symfony/http-kernel": "^7.3 || ^8.0",
|
||||
"symfony/monolog-bridge": "^7.3 || ^8.0",
|
||||
"symfony/polyfill-php84": "^1.30"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^11.5.41 || ^12.3",
|
||||
"symfony/console": "^7.3 || ^8.0",
|
||||
"symfony/yaml": "^7.3 || ^8.0"
|
||||
},
|
||||
"type": "symfony-bundle",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Bundle\\MonologBundle\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony MonologBundle",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"log",
|
||||
"logging"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/symfony/monolog-bundle/issues",
|
||||
"source": "https://github.com/symfony/monolog-bundle/tree/v4.0.2"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"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": "2026-04-02T18:27:21+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/options-resolver",
|
||||
"version": "v8.0.0",
|
||||
|
||||
@@ -9,6 +9,7 @@ use Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle;
|
||||
use Nelmio\CorsBundle\NelmioCorsBundle;
|
||||
use Symfony\AI\McpBundle\McpBundle;
|
||||
use Symfony\Bundle\FrameworkBundle\FrameworkBundle;
|
||||
use Symfony\Bundle\MonologBundle\MonologBundle;
|
||||
use Symfony\Bundle\SecurityBundle\SecurityBundle;
|
||||
use Symfony\Bundle\TwigBundle\TwigBundle;
|
||||
|
||||
@@ -22,4 +23,5 @@ return [
|
||||
ApiPlatformBundle::class => ['all' => true],
|
||||
DAMADoctrineTestBundle::class => ['test' => true],
|
||||
McpBundle::class => ['all' => true],
|
||||
MonologBundle::class => ['all' => true],
|
||||
];
|
||||
|
||||
56
config/packages/monolog.yaml
Normal file
56
config/packages/monolog.yaml
Normal file
@@ -0,0 +1,56 @@
|
||||
monolog:
|
||||
channels:
|
||||
- deprecation # Deprecations are logged in the dedicated "deprecation" channel when it exists
|
||||
|
||||
when@dev:
|
||||
monolog:
|
||||
handlers:
|
||||
main:
|
||||
type: rotating_file
|
||||
path: "%kernel.logs_dir%/%kernel.environment%.log"
|
||||
level: debug
|
||||
max_files: 7
|
||||
channels: ["!event"]
|
||||
console:
|
||||
type: console
|
||||
process_psr_3_messages: false
|
||||
channels: ["!event", "!doctrine", "!console"]
|
||||
|
||||
when@test:
|
||||
monolog:
|
||||
handlers:
|
||||
main:
|
||||
type: fingers_crossed
|
||||
action_level: error
|
||||
handler: nested
|
||||
excluded_http_codes: [404, 405]
|
||||
channels: ["!event"]
|
||||
nested:
|
||||
type: stream
|
||||
path: "%kernel.logs_dir%/%kernel.environment%.log"
|
||||
level: debug
|
||||
|
||||
when@prod:
|
||||
monolog:
|
||||
handlers:
|
||||
main:
|
||||
type: fingers_crossed
|
||||
action_level: error
|
||||
handler: nested
|
||||
excluded_http_codes: [404, 405]
|
||||
channels: ["!deprecation"]
|
||||
buffer_size: 50
|
||||
nested:
|
||||
type: rotating_file
|
||||
path: "%kernel.logs_dir%/%kernel.environment%.log"
|
||||
level: debug
|
||||
max_files: 30
|
||||
console:
|
||||
type: console
|
||||
process_psr_3_messages: false
|
||||
channels: ["!event", "!doctrine"]
|
||||
deprecation:
|
||||
type: rotating_file
|
||||
channels: [deprecation]
|
||||
path: "%kernel.logs_dir%/deprecations.log"
|
||||
max_files: 7
|
||||
@@ -1,2 +1,2 @@
|
||||
parameters:
|
||||
app.version: '1.9.26'
|
||||
app.version: '1.9.29'
|
||||
|
||||
19
frontend/package-lock.json
generated
19
frontend/package-lock.json
generated
@@ -98,6 +98,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.4.tgz",
|
||||
"integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "^7.27.1",
|
||||
"@babel/generator": "^7.28.3",
|
||||
@@ -2092,6 +2093,7 @@
|
||||
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.17.tgz",
|
||||
"integrity": "sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@alloc/quick-lru": "^5.2.0",
|
||||
"arg": "^5.0.2",
|
||||
@@ -4112,6 +4114,7 @@
|
||||
"integrity": "sha512-CPrnr8voK8vC6eEtyRzvMpgp3VyVRhgclonE7qYi6P9sXwYb59ucfrnmFBTaP0yUi8Gk4yZg/LlTJULGxvTNsg==",
|
||||
"devOptional": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"undici-types": "~7.16.0"
|
||||
}
|
||||
@@ -4181,6 +4184,7 @@
|
||||
"integrity": "sha512-EHrrEsyhOhxYt8MTg4zTF+DJMuNBzWwgvvOYNj/zm1vnaD/IC5zCXFehZv94Piqa2cRFfXrTFxIvO95L7Qc/cw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/scope-manager": "8.44.1",
|
||||
"@typescript-eslint/types": "8.44.1",
|
||||
@@ -4977,6 +4981,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.22.tgz",
|
||||
"integrity": "sha512-tbTR1zKGce4Lj+JLzFXDq36K4vcSZbJ1RBu8FxcDv1IGRz//Dh2EBqksyGVypz3kXpshIfWKGOCcqpSbyGWRJQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/parser": "^7.28.4",
|
||||
"@vue/compiler-core": "3.5.22",
|
||||
@@ -5207,6 +5212,7 @@
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
|
||||
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
},
|
||||
@@ -5637,6 +5643,7 @@
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"baseline-browser-mapping": "^2.8.3",
|
||||
"caniuse-lite": "^1.0.30001741",
|
||||
@@ -7069,6 +7076,7 @@
|
||||
"integrity": "sha512-hB4FIzXovouYzwzECDcUkJ4OcfOEkXTv2zRY6B9bkwjx/cprAq0uvm1nl7zvQ0/TsUk0zQiN4uPfJpB9m+rPMQ==",
|
||||
"devOptional": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.8.0",
|
||||
"@eslint-community/regexpp": "^4.12.1",
|
||||
@@ -10490,6 +10498,7 @@
|
||||
"integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
|
||||
"devOptional": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"deep-is": "^0.1.3",
|
||||
"fast-levenshtein": "^2.0.6",
|
||||
@@ -10536,6 +10545,7 @@
|
||||
"resolved": "https://registry.npmjs.org/oxc-parser/-/oxc-parser-0.87.0.tgz",
|
||||
"integrity": "sha512-uc47XrtHwkBoES4HFgwgfH9sqwAtJXgAIBq4fFBMZ4hWmgVZoExyn+L4g4VuaecVKXkz1bvlaHcfwHAJPQb5Gw==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@oxc-project/types": "^0.87.0"
|
||||
},
|
||||
@@ -10937,6 +10947,7 @@
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"nanoid": "^3.3.11",
|
||||
"picocolors": "^1.1.1",
|
||||
@@ -11376,6 +11387,7 @@
|
||||
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz",
|
||||
"integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"cssesc": "^3.0.0",
|
||||
"util-deprecate": "^1.0.2"
|
||||
@@ -12118,6 +12130,7 @@
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.52.2.tgz",
|
||||
"integrity": "sha512-I25/2QgoROE1vYV+NQ1En9T9UFB9Cmfm2CJ83zZOlaDpvz29wGQSZXWKw7MiNXau7wYgB/T9fVIdIuEQ+KbiiA==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@types/estree": "1.0.8"
|
||||
},
|
||||
@@ -13180,6 +13193,7 @@
|
||||
"integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==",
|
||||
"devOptional": true,
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
@@ -13537,6 +13551,7 @@
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"napi-postinstall": "^0.3.0"
|
||||
},
|
||||
@@ -13783,6 +13798,7 @@
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-7.1.7.tgz",
|
||||
"integrity": "sha512-VbA8ScMvAISJNJVbRDTJdCwqQoAareR/wutevKanhR2/1EkoXVZVkkORaYm/tNVCjP/UDTKtcw3bAkwOUdedmA==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"esbuild": "^0.25.0",
|
||||
"fdir": "^6.5.0",
|
||||
@@ -14186,6 +14202,7 @@
|
||||
"resolved": "https://registry.npmjs.org/vue/-/vue-3.5.22.tgz",
|
||||
"integrity": "sha512-toaZjQ3a/G/mYaLSbV+QsQhIdMo9x5rrqIpYRObsJ6T/J+RyCSFwN2LHNVH9v8uIcljDNa3QzPVdv3Y6b9hAJQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@vue/compiler-dom": "3.5.22",
|
||||
"@vue/compiler-sfc": "3.5.22",
|
||||
@@ -14230,6 +14247,7 @@
|
||||
"integrity": "sha512-CydUvFOQKD928UzZhTp4pr2vWz1L+H99t7Pkln2QSPdvmURT0MoC4wUccfCnuEaihNsu9aYYyk+bep8rlfkUXw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"debug": "^4.4.0",
|
||||
"eslint-scope": "^8.2.0",
|
||||
@@ -14253,6 +14271,7 @@
|
||||
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.5.1.tgz",
|
||||
"integrity": "sha512-ogAF3P97NPm8fJsE4by9dwSYtDwXIY1nFY9T6DyQnGHd1E2Da94w9JIolpe42LJGIl0DwOHBi8TcRPlPGwbTtw==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@vue/devtools-api": "^6.6.4"
|
||||
},
|
||||
|
||||
@@ -7,6 +7,10 @@ services:
|
||||
- "8082:80"
|
||||
volumes:
|
||||
- ./storage:/var/www/html/var/storage/documents
|
||||
- inventory_logs:/var/www/html/var/log
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway"
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
inventory_logs:
|
||||
|
||||
320
src/Command/ConvertMoteurPieceToComponentCommand.php
Normal file
320
src/Command/ConvertMoteurPieceToComponentCommand.php
Normal file
@@ -0,0 +1,320 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Command;
|
||||
|
||||
use DateTimeImmutable;
|
||||
use Doctrine\DBAL\Connection;
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
use Throwable;
|
||||
|
||||
#[AsCommand(
|
||||
name: 'app:convert-moteur-piece-to-component',
|
||||
description: 'Convertit la catégorie "Moteur" (PIECE) en COMPONENT et migre toutes les pièces liées en composants.',
|
||||
)]
|
||||
class ConvertMoteurPieceToComponentCommand extends Command
|
||||
{
|
||||
private const MODEL_TYPE_ID = 'cmgytewe0002447ffup09bscr';
|
||||
|
||||
public function __construct(
|
||||
private readonly Connection $connection,
|
||||
) {
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
protected function configure(): void
|
||||
{
|
||||
$this->addOption('dry-run', null, InputOption::VALUE_NONE, 'Affiche les actions sans les exécuter');
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
$dryRun = $input->getOption('dry-run');
|
||||
|
||||
$io->title('Conversion catégorie "Moteur" : PIECE → COMPONENT');
|
||||
|
||||
// ── 1. Vérifications ──────────────────────────────────────────────
|
||||
|
||||
$modelType = $this->connection->fetchAssociative(
|
||||
'SELECT id, name, code, category FROM model_types WHERE id = :id',
|
||||
['id' => self::MODEL_TYPE_ID],
|
||||
);
|
||||
|
||||
if (!$modelType) {
|
||||
$io->error('ModelType "Moteur" introuvable (id: '.self::MODEL_TYPE_ID.')');
|
||||
|
||||
return Command::FAILURE;
|
||||
}
|
||||
|
||||
if ('PIECE' !== $modelType['category']) {
|
||||
$io->error(sprintf('Le ModelType "Moteur" est déjà de catégorie %s — rien à faire.', $modelType['category']));
|
||||
|
||||
return Command::FAILURE;
|
||||
}
|
||||
|
||||
$pieces = $this->connection->fetchAllAssociative(
|
||||
'SELECT id, name, reference FROM pieces WHERE typepieceid = :id ORDER BY name',
|
||||
['id' => self::MODEL_TYPE_ID],
|
||||
);
|
||||
|
||||
$pieceCount = count($pieces);
|
||||
$io->info(sprintf('Pièces à convertir : %d', $pieceCount));
|
||||
|
||||
if ($pieceCount > 0) {
|
||||
$io->table(
|
||||
['ID', 'Nom', 'Référence'],
|
||||
array_map(fn (array $p) => [$p['id'], $p['name'], $p['reference'] ?? '—'], $pieces),
|
||||
);
|
||||
}
|
||||
|
||||
// Check blockers
|
||||
$blockers = [];
|
||||
|
||||
$machineLinked = (int) $this->connection->fetchOne(
|
||||
'SELECT COUNT(*) FROM machine_piece_links mpl
|
||||
JOIN pieces p ON mpl.pieceid = p.id
|
||||
WHERE p.typepieceid = :id',
|
||||
['id' => self::MODEL_TYPE_ID],
|
||||
);
|
||||
|
||||
if ($machineLinked > 0) {
|
||||
$blockers[] = sprintf('%d pièce(s) liée(s) à des machines — conversion impossible.', $machineLinked);
|
||||
}
|
||||
|
||||
$nameCollisions = $this->connection->fetchFirstColumn(
|
||||
'SELECT p.name FROM pieces p
|
||||
WHERE p.typepieceid = :id
|
||||
AND p.name IN (SELECT c.name FROM composants c)',
|
||||
['id' => self::MODEL_TYPE_ID],
|
||||
);
|
||||
|
||||
if ([] !== $nameCollisions) {
|
||||
$blockers[] = sprintf('Collision de noms avec des composants existants : %s', implode(', ', $nameCollisions));
|
||||
}
|
||||
|
||||
$categoryCollision = (int) $this->connection->fetchOne(
|
||||
"SELECT COUNT(*) FROM model_types WHERE category = 'COMPONENT' AND name = :name AND id != :id",
|
||||
['name' => $modelType['name'], 'id' => self::MODEL_TYPE_ID],
|
||||
);
|
||||
|
||||
if ($categoryCollision > 0) {
|
||||
$blockers[] = sprintf('Un ModelType composant « %s » existe déjà.', $modelType['name']);
|
||||
}
|
||||
|
||||
if ([] !== $blockers) {
|
||||
$io->error($blockers);
|
||||
|
||||
return Command::FAILURE;
|
||||
}
|
||||
|
||||
// Summary of related data
|
||||
$relatedCounts = $this->countRelatedData();
|
||||
$io->section('Données liées à migrer');
|
||||
$io->table(
|
||||
['Table', 'Nombre'],
|
||||
array_map(fn (string $k, int $v) => [$k, $v], array_keys($relatedCounts), array_values($relatedCounts)),
|
||||
);
|
||||
|
||||
if ($dryRun) {
|
||||
$io->warning('Mode dry-run : aucune modification effectuée.');
|
||||
|
||||
return Command::SUCCESS;
|
||||
}
|
||||
|
||||
// ── 2. Exécution ──────────────────────────────────────────────────
|
||||
|
||||
$this->connection->beginTransaction();
|
||||
|
||||
try {
|
||||
$now = new DateTimeImmutable()->format('Y-m-d H:i:s');
|
||||
|
||||
// 2a. Copier les pièces dans composants
|
||||
$converted = $this->connection->executeStatement(
|
||||
'INSERT INTO composants (id, name, reference, referenceauto, description, prix, typecomposantid, productid, version, createdat, updatedat)
|
||||
SELECT id, name, reference, referenceauto, description, prix, typepieceid, productid, version, createdat, :now
|
||||
FROM pieces
|
||||
WHERE typepieceid = :id',
|
||||
['id' => self::MODEL_TYPE_ID, 'now' => $now],
|
||||
);
|
||||
$io->text(sprintf('✓ %d pièce(s) copiée(s) dans composants', $converted));
|
||||
|
||||
// 2b. Transférer les documents
|
||||
$docs = $this->connection->executeStatement(
|
||||
'UPDATE documents SET composantid = pieceid, pieceid = NULL
|
||||
WHERE pieceid IN (SELECT id FROM pieces WHERE typepieceid = :id)',
|
||||
['id' => self::MODEL_TYPE_ID],
|
||||
);
|
||||
$io->text(sprintf('✓ %d document(s) transféré(s)', $docs));
|
||||
|
||||
// 2c. Transférer les custom_field_values
|
||||
$cfv = $this->connection->executeStatement(
|
||||
'UPDATE custom_field_values SET composantid = pieceid, pieceid = NULL
|
||||
WHERE pieceid IN (SELECT id FROM pieces WHERE typepieceid = :id)',
|
||||
['id' => self::MODEL_TYPE_ID],
|
||||
);
|
||||
$io->text(sprintf('✓ %d valeur(s) de champs perso transférée(s)', $cfv));
|
||||
|
||||
// 2d. Transférer les custom_fields (définitions)
|
||||
$cf = $this->connection->executeStatement(
|
||||
'UPDATE custom_fields SET typecomposantid = typepieceid, typepieceid = NULL
|
||||
WHERE typepieceid = :id',
|
||||
['id' => self::MODEL_TYPE_ID],
|
||||
);
|
||||
$io->text(sprintf('✓ %d définition(s) de champs perso transférée(s)', $cf));
|
||||
|
||||
// 2e. Transférer les constructeur links
|
||||
$ctorLinks = $this->connection->executeStatement(
|
||||
"INSERT INTO composant_constructeur_links (id, composantid, constructeurid, supplierreference, createdat, updatedat)
|
||||
SELECT 'cl' || substring(md5(random()::text || clock_timestamp()::text), 1, 24),
|
||||
pcl.pieceid, pcl.constructeurid, pcl.supplierreference, pcl.createdat, :now
|
||||
FROM piece_constructeur_links pcl
|
||||
WHERE pcl.pieceid IN (SELECT id FROM pieces WHERE typepieceid = :id)",
|
||||
['id' => self::MODEL_TYPE_ID, 'now' => $now],
|
||||
);
|
||||
|
||||
if ($ctorLinks > 0) {
|
||||
$this->connection->executeStatement(
|
||||
'DELETE FROM piece_constructeur_links
|
||||
WHERE pieceid IN (SELECT id FROM pieces WHERE typepieceid = :id)',
|
||||
['id' => self::MODEL_TYPE_ID],
|
||||
);
|
||||
}
|
||||
$io->text(sprintf('✓ %d lien(s) constructeur transféré(s)', $ctorLinks));
|
||||
|
||||
// 2f. Convertir composant_piece_slots → composant_subcomponent_slots
|
||||
$slots = $this->connection->executeStatement(
|
||||
"INSERT INTO composant_subcomponent_slots (id, composantid, alias, familycode, typecomposantid, selectedcomposantid, position, createdat, updatedat)
|
||||
SELECT 'cl' || substring(md5(random()::text || clock_timestamp()::text), 1, 24),
|
||||
cps.composantid,
|
||||
COALESCE(sp.name, 'Moteur'),
|
||||
'moteur',
|
||||
cps.typepieceid,
|
||||
cps.selectedpieceid,
|
||||
cps.position,
|
||||
cps.createdat,
|
||||
:now
|
||||
FROM composant_piece_slots cps
|
||||
LEFT JOIN pieces sp ON sp.id = cps.selectedpieceid
|
||||
WHERE cps.typepieceid = :id",
|
||||
['id' => self::MODEL_TYPE_ID, 'now' => $now],
|
||||
);
|
||||
|
||||
$this->connection->executeStatement(
|
||||
'DELETE FROM composant_piece_slots WHERE typepieceid = :id',
|
||||
['id' => self::MODEL_TYPE_ID],
|
||||
);
|
||||
$io->text(sprintf('✓ %d slot(s) pièce convertis en slots sous-composant', $slots));
|
||||
|
||||
// 2g. Convertir skeleton_piece_requirements → skeleton_subcomponent_requirements
|
||||
$skelReqs = $this->connection->executeStatement(
|
||||
"INSERT INTO skeleton_subcomponent_requirements (id, modeltypeid, alias, familycode, typecomposantid, position, createdat, updatedat)
|
||||
SELECT 'cl' || substring(md5(random()::text || clock_timestamp()::text), 1, 24),
|
||||
spr.modeltypeid,
|
||||
'Moteur',
|
||||
'moteur',
|
||||
spr.typepieceid,
|
||||
spr.position,
|
||||
spr.createdat,
|
||||
:now
|
||||
FROM skeleton_piece_requirements spr
|
||||
WHERE spr.typepieceid = :id",
|
||||
['id' => self::MODEL_TYPE_ID, 'now' => $now],
|
||||
);
|
||||
|
||||
$this->connection->executeStatement(
|
||||
'DELETE FROM skeleton_piece_requirements WHERE typepieceid = :id',
|
||||
['id' => self::MODEL_TYPE_ID],
|
||||
);
|
||||
$io->text(sprintf('✓ %d skeleton requirement(s) convertis', $skelReqs));
|
||||
|
||||
// 2h. Mettre à jour audit_logs entity_type
|
||||
$auditUpdated = $this->connection->executeStatement(
|
||||
"UPDATE audit_logs SET entitytype = 'composant'
|
||||
WHERE entitytype = 'piece'
|
||||
AND entityid IN (SELECT id FROM pieces WHERE typepieceid = :id)",
|
||||
['id' => self::MODEL_TYPE_ID],
|
||||
);
|
||||
$io->text(sprintf('✓ %d audit log(s) mis à jour', $auditUpdated));
|
||||
|
||||
// 2i. Mettre à jour comments entity_type
|
||||
$commentsUpdated = $this->connection->executeStatement(
|
||||
"UPDATE comments SET entity_type = 'composant'
|
||||
WHERE entity_type = 'piece'
|
||||
AND entity_id IN (SELECT id FROM pieces WHERE typepieceid = :id)",
|
||||
['id' => self::MODEL_TYPE_ID],
|
||||
);
|
||||
$io->text(sprintf('✓ %d commentaire(s) mis à jour', $commentsUpdated));
|
||||
|
||||
// 2j. Supprimer les pièces originales
|
||||
$deleted = $this->connection->executeStatement(
|
||||
'DELETE FROM pieces WHERE typepieceid = :id',
|
||||
['id' => self::MODEL_TYPE_ID],
|
||||
);
|
||||
$io->text(sprintf('✓ %d pièce(s) supprimée(s)', $deleted));
|
||||
|
||||
// 2k. Changer la catégorie du ModelType
|
||||
$this->connection->executeStatement(
|
||||
"UPDATE model_types SET category = 'COMPONENT', updatedat = :now WHERE id = :id",
|
||||
['id' => self::MODEL_TYPE_ID, 'now' => $now],
|
||||
);
|
||||
$io->text('✓ ModelType "Moteur" passé en COMPONENT');
|
||||
|
||||
$this->connection->commit();
|
||||
|
||||
$io->success(sprintf('Conversion terminée : %d pièces → composants.', $converted));
|
||||
|
||||
return Command::SUCCESS;
|
||||
} catch (Throwable $e) {
|
||||
$this->connection->rollBack();
|
||||
$io->error('Erreur — rollback effectué : '.$e->getMessage());
|
||||
|
||||
return Command::FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, int>
|
||||
*/
|
||||
private function countRelatedData(): array
|
||||
{
|
||||
$id = self::MODEL_TYPE_ID;
|
||||
|
||||
return [
|
||||
'pieces' => (int) $this->connection->fetchOne(
|
||||
'SELECT COUNT(*) FROM pieces WHERE typepieceid = :id',
|
||||
['id' => $id],
|
||||
),
|
||||
'documents' => (int) $this->connection->fetchOne(
|
||||
'SELECT COUNT(*) FROM documents WHERE pieceid IN (SELECT id FROM pieces WHERE typepieceid = :id)',
|
||||
['id' => $id],
|
||||
),
|
||||
'custom_field_values' => (int) $this->connection->fetchOne(
|
||||
'SELECT COUNT(*) FROM custom_field_values WHERE pieceid IN (SELECT id FROM pieces WHERE typepieceid = :id)',
|
||||
['id' => $id],
|
||||
),
|
||||
'custom_fields' => (int) $this->connection->fetchOne(
|
||||
'SELECT COUNT(*) FROM custom_fields WHERE typepieceid = :id',
|
||||
['id' => $id],
|
||||
),
|
||||
'piece_constructeur_links' => (int) $this->connection->fetchOne(
|
||||
'SELECT COUNT(*) FROM piece_constructeur_links WHERE pieceid IN (SELECT id FROM pieces WHERE typepieceid = :id)',
|
||||
['id' => $id],
|
||||
),
|
||||
'composant_piece_slots (→ subcomponent_slots)' => (int) $this->connection->fetchOne(
|
||||
'SELECT COUNT(*) FROM composant_piece_slots WHERE typepieceid = :id',
|
||||
['id' => $id],
|
||||
),
|
||||
'skeleton_piece_requirements (→ subcomponent_reqs)' => (int) $this->connection->fetchOne(
|
||||
'SELECT COUNT(*) FROM skeleton_piece_requirements WHERE typepieceid = :id',
|
||||
['id' => $id],
|
||||
),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -337,6 +337,7 @@ class MachineStructureController extends AbstractController
|
||||
$newValue->setMachineComponentLink($newLink);
|
||||
$newValue->setComposant($newLink->getComposant());
|
||||
$this->entityManager->persist($newValue);
|
||||
$newLink->getContextFieldValues()->add($newValue);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -352,6 +353,7 @@ class MachineStructureController extends AbstractController
|
||||
$newValue->setMachinePieceLink($newLink);
|
||||
$newValue->setPiece($newLink->getPiece());
|
||||
$this->entityManager->persist($newValue);
|
||||
$newLink->getContextFieldValues()->add($newValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
57
src/EventSubscriber/ModelTypeReferenceCleanupSubscriber.php
Normal file
57
src/EventSubscriber/ModelTypeReferenceCleanupSubscriber.php
Normal file
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\EventSubscriber;
|
||||
|
||||
use App\Entity\ModelType;
|
||||
use Doctrine\Bundle\DoctrineBundle\Attribute\AsDoctrineListener;
|
||||
use Doctrine\ORM\Event\PreRemoveEventArgs;
|
||||
use Doctrine\ORM\Events;
|
||||
|
||||
use function sprintf;
|
||||
|
||||
/**
|
||||
* Belt-and-suspenders cleanup of weak references to a ModelType before deletion:
|
||||
* runs the equivalent of every "ON DELETE SET NULL" cascade applicatively, in case
|
||||
* the database FK fails to fire (observed on prod in 2026-04 — the deletion of
|
||||
* ModelType "Paliers" left an orphan in skeleton_subcomponent_requirements).
|
||||
*/
|
||||
#[AsDoctrineListener(event: Events::preRemove)]
|
||||
final class ModelTypeReferenceCleanupSubscriber
|
||||
{
|
||||
/** @var list<array{0: string, 1: string}> */
|
||||
private const NULLABLE_REFERENCES = [
|
||||
['skeleton_subcomponent_requirements', 'typecomposantid'],
|
||||
['skeleton_piece_requirements', 'typepieceid'],
|
||||
['skeleton_product_requirements', 'typeproductid'],
|
||||
['composant_piece_slots', 'typepieceid'],
|
||||
['composant_product_slots', 'typeproductid'],
|
||||
['composant_subcomponent_slots', 'typecomposantid'],
|
||||
['piece_product_slots', 'typeproductid'],
|
||||
['machine_component_links', 'modeltypeid'],
|
||||
['machine_piece_links', 'modeltypeid'],
|
||||
['machine_product_links', 'modeltypeid'],
|
||||
];
|
||||
|
||||
public function preRemove(PreRemoveEventArgs $args): void
|
||||
{
|
||||
$entity = $args->getObject();
|
||||
if (!$entity instanceof ModelType) {
|
||||
return;
|
||||
}
|
||||
|
||||
$id = $entity->getId();
|
||||
if (!$id) {
|
||||
return;
|
||||
}
|
||||
|
||||
$conn = $args->getObjectManager()->getConnection();
|
||||
foreach (self::NULLABLE_REFERENCES as [$table, $column]) {
|
||||
$conn->executeStatement(
|
||||
sprintf('UPDATE %s SET %s = NULL WHERE %s = ?', $table, $column, $column),
|
||||
[$id],
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
12
symfony.lock
12
symfony.lock
@@ -157,6 +157,18 @@
|
||||
"symfony/mcp-bundle": {
|
||||
"version": "v0.6.0"
|
||||
},
|
||||
"symfony/monolog-bundle": {
|
||||
"version": "4.0",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "3.7",
|
||||
"ref": "1b9efb10c54cb51c713a9391c9300ff8bceda459"
|
||||
},
|
||||
"files": [
|
||||
"config/packages/monolog.yaml"
|
||||
]
|
||||
},
|
||||
"symfony/property-info": {
|
||||
"version": "8.0",
|
||||
"recipe": {
|
||||
|
||||
@@ -7,10 +7,10 @@ namespace App\Tests;
|
||||
use ApiPlatform\Symfony\Bundle\Test\ApiTestCase;
|
||||
use ApiPlatform\Symfony\Bundle\Test\Client;
|
||||
use App\Entity\Composant;
|
||||
use App\Entity\ComposantConstructeurLink;
|
||||
use App\Entity\ComposantPieceSlot;
|
||||
use App\Entity\ComposantProductSlot;
|
||||
use App\Entity\ComposantSubcomponentSlot;
|
||||
use App\Entity\ComposantConstructeurLink;
|
||||
use App\Entity\Constructeur;
|
||||
use App\Entity\CustomField;
|
||||
use App\Entity\CustomFieldValue;
|
||||
@@ -467,6 +467,14 @@ abstract class AbstractApiTestCase extends ApiTestCase
|
||||
$em->persist($cfv);
|
||||
$em->flush();
|
||||
|
||||
// Keep inverse-side collections in sync so identity-mapped entities reflect the new CFV.
|
||||
if (null !== $machineComponentLink && !$machineComponentLink->getContextFieldValues()->contains($cfv)) {
|
||||
$machineComponentLink->getContextFieldValues()->add($cfv);
|
||||
}
|
||||
if (null !== $machinePieceLink && !$machinePieceLink->getContextFieldValues()->contains($cfv)) {
|
||||
$machinePieceLink->getContextFieldValues()->add($cfv);
|
||||
}
|
||||
|
||||
return $cfv;
|
||||
}
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ class SessionProfileTest extends AbstractApiTestCase
|
||||
]);
|
||||
|
||||
$this->assertResponseStatusCodeSame(401);
|
||||
$this->assertJsonContains(['message' => 'Mot de passe incorrect.']);
|
||||
$this->assertJsonContains(['message' => 'Identifiants invalides.']);
|
||||
}
|
||||
|
||||
public function testLoginMissingPassword(): void
|
||||
@@ -103,7 +103,7 @@ class SessionProfileTest extends AbstractApiTestCase
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertResponseStatusCodeSame(403);
|
||||
$this->assertResponseStatusCodeSame(401);
|
||||
}
|
||||
|
||||
public function testGetActiveProfileAuthenticated(): void
|
||||
|
||||
Reference in New Issue
Block a user