Compare commits
4
Commits
d9489f2558
...
37462e4646
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
37462e4646 | ||
|
|
fbee23c022 | ||
|
|
facd5bc9c0 | ||
|
|
1bf738be1c |
@@ -89,10 +89,16 @@ docker network create somniarooms-network
|
|||||||
Go to the app address (`https://localhost`) and it will show Symfony welcome page (or a error when running on prod).
|
Go to the app address (`https://localhost`) and it will show Symfony welcome page (or a error when running on prod).
|
||||||
|
|
||||||
Go to addres `https://localhost/setup` to inicialize app users and data.
|
Go to addres `https://localhost/setup` to inicialize app users and data.
|
||||||
|
|
||||||
|
During setup you must configure the admin account.
|
||||||
|
If you check "Add example data" you will be redirected to example data setup.
|
||||||
|
Example data can be added anytime at `https://localhost/debug/exampleData`. There is needed to use a Superadmin account.
|
||||||
|
|
||||||
Then, you the admin panel is at `https://localhost/admin`
|
Then, you the admin panel is at `https://localhost/admin`
|
||||||
|
|
||||||
You may login using default admin user:
|
## Logs.
|
||||||
```
|
|
||||||
user: admin
|
By default logs are saved to `/app/var/log` on an unamed container volume.
|
||||||
pass: admin
|
For development, `/app/var/log` directory is mounted to `./var/log` on the local filesystem.
|
||||||
```
|
|
||||||
|
This config can be overriden setting a different mount for `/app/var/log` when creating the containers.
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ services:
|
|||||||
# If you develop on Mac or Windows you can remove the vendor/ directory
|
# If you develop on Mac or Windows you can remove the vendor/ directory
|
||||||
# from the bind-mount for better performance by enabling the next line:
|
# from the bind-mount for better performance by enabling the next line:
|
||||||
- /app/vendor
|
- /app/vendor
|
||||||
|
# On dev mount var to localfiles.
|
||||||
|
- ./var/log:/app/var/log
|
||||||
environment:
|
environment:
|
||||||
MERCURE_EXTRA_DIRECTIVES: demo
|
MERCURE_EXTRA_DIRECTIVES: demo
|
||||||
# See https://xdebug.org/docs/all_settings#mode
|
# See https://xdebug.org/docs/all_settings#mode
|
||||||
|
|||||||
@@ -27,12 +27,14 @@
|
|||||||
"symfony/form": "7.0.*",
|
"symfony/form": "7.0.*",
|
||||||
"symfony/framework-bundle": "7.0.*",
|
"symfony/framework-bundle": "7.0.*",
|
||||||
"symfony/mime": "7.0.*",
|
"symfony/mime": "7.0.*",
|
||||||
|
"symfony/monolog-bundle": "^3.10",
|
||||||
"symfony/property-access": "7.0.*",
|
"symfony/property-access": "7.0.*",
|
||||||
"symfony/property-info": "7.0.*",
|
"symfony/property-info": "7.0.*",
|
||||||
"symfony/runtime": "7.0.*",
|
"symfony/runtime": "7.0.*",
|
||||||
"symfony/security-bundle": "7.0.*",
|
"symfony/security-bundle": "7.0.*",
|
||||||
"symfony/serializer": "7.0.*",
|
"symfony/serializer": "7.0.*",
|
||||||
"symfony/twig-bundle": "7.0.*",
|
"symfony/twig-bundle": "7.0.*",
|
||||||
|
"symfony/validator": "7.0.*",
|
||||||
"symfony/var-exporter": "7.0.4",
|
"symfony/var-exporter": "7.0.4",
|
||||||
"symfony/yaml": "7.0.*",
|
"symfony/yaml": "7.0.*",
|
||||||
"twig/extra-bundle": "^2.12|^3.0",
|
"twig/extra-bundle": "^2.12|^3.0",
|
||||||
|
|||||||
Generated
+269
-8
@@ -4,7 +4,7 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "20c33276e1944c7bb2e51459e4f90463",
|
"content-hash": "974cb22b15d6dc64bd6dac49da5d671d",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "composer/semver",
|
"name": "composer/semver",
|
||||||
@@ -1401,6 +1401,107 @@
|
|||||||
],
|
],
|
||||||
"time": "2024-04-19T18:13:15+00:00"
|
"time": "2024-04-19T18:13:15+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "monolog/monolog",
|
||||||
|
"version": "3.7.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/Seldaek/monolog.git",
|
||||||
|
"reference": "f4393b648b78a5408747de94fca38beb5f7e9ef8"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/Seldaek/monolog/zipball/f4393b648b78a5408747de94fca38beb5f7e9ef8",
|
||||||
|
"reference": "f4393b648b78a5408747de94fca38beb5f7e9ef8",
|
||||||
|
"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",
|
||||||
|
"php-amqplib/php-amqplib": "~2.4 || ^3",
|
||||||
|
"phpstan/phpstan": "^1.9",
|
||||||
|
"phpstan/phpstan-deprecation-rules": "^1.0",
|
||||||
|
"phpstan/phpstan-strict-rules": "^1.4",
|
||||||
|
"phpunit/phpunit": "^10.5.17",
|
||||||
|
"predis/predis": "^1.1 || ^2",
|
||||||
|
"ruflin/elastica": "^7",
|
||||||
|
"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": "[email protected]",
|
||||||
|
"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.7.0"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://github.com/Seldaek",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/monolog/monolog",
|
||||||
|
"type": "tidelift"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2024-06-28T09:40:51+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "nelmio/api-doc-bundle",
|
"name": "nelmio/api-doc-bundle",
|
||||||
"version": "v4.30.0",
|
"version": "v4.30.0",
|
||||||
@@ -4187,6 +4288,165 @@
|
|||||||
],
|
],
|
||||||
"time": "2024-06-28T09:58:46+00:00"
|
"time": "2024-06-28T09:58:46+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "symfony/monolog-bridge",
|
||||||
|
"version": "v7.0.8",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/symfony/monolog-bridge.git",
|
||||||
|
"reference": "d80b7aeabc539538c6ae8962259ac422632d7796"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/symfony/monolog-bridge/zipball/d80b7aeabc539538c6ae8962259ac422632d7796",
|
||||||
|
"reference": "d80b7aeabc539538c6ae8962259ac422632d7796",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"monolog/monolog": "^3",
|
||||||
|
"php": ">=8.2",
|
||||||
|
"symfony/http-kernel": "^6.4|^7.0",
|
||||||
|
"symfony/service-contracts": "^2.5|^3"
|
||||||
|
},
|
||||||
|
"conflict": {
|
||||||
|
"symfony/console": "<6.4",
|
||||||
|
"symfony/http-foundation": "<6.4",
|
||||||
|
"symfony/security-core": "<6.4"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"symfony/console": "^6.4|^7.0",
|
||||||
|
"symfony/http-client": "^6.4|^7.0",
|
||||||
|
"symfony/mailer": "^6.4|^7.0",
|
||||||
|
"symfony/messenger": "^6.4|^7.0",
|
||||||
|
"symfony/mime": "^6.4|^7.0",
|
||||||
|
"symfony/security-core": "^6.4|^7.0",
|
||||||
|
"symfony/var-dumper": "^6.4|^7.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": "[email protected]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"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/v7.0.8"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://symfony.com/sponsor",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/fabpot",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||||
|
"type": "tidelift"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2024-05-31T14:55:39+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "symfony/monolog-bundle",
|
||||||
|
"version": "v3.10.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/symfony/monolog-bundle.git",
|
||||||
|
"reference": "414f951743f4aa1fd0f5bf6a0e9c16af3fe7f181"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/symfony/monolog-bundle/zipball/414f951743f4aa1fd0f5bf6a0e9c16af3fe7f181",
|
||||||
|
"reference": "414f951743f4aa1fd0f5bf6a0e9c16af3fe7f181",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"monolog/monolog": "^1.25.1 || ^2.0 || ^3.0",
|
||||||
|
"php": ">=7.2.5",
|
||||||
|
"symfony/config": "^5.4 || ^6.0 || ^7.0",
|
||||||
|
"symfony/dependency-injection": "^5.4 || ^6.0 || ^7.0",
|
||||||
|
"symfony/http-kernel": "^5.4 || ^6.0 || ^7.0",
|
||||||
|
"symfony/monolog-bridge": "^5.4 || ^6.0 || ^7.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"symfony/console": "^5.4 || ^6.0 || ^7.0",
|
||||||
|
"symfony/phpunit-bridge": "^6.3 || ^7.0",
|
||||||
|
"symfony/yaml": "^5.4 || ^6.0 || ^7.0"
|
||||||
|
},
|
||||||
|
"type": "symfony-bundle",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "3.x-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Symfony\\Bundle\\MonologBundle\\": ""
|
||||||
|
},
|
||||||
|
"exclude-from-classmap": [
|
||||||
|
"/Tests/"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Fabien Potencier",
|
||||||
|
"email": "[email protected]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"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/v3.10.0"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://symfony.com/sponsor",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/fabpot",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||||
|
"type": "tidelift"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2023-11-06T17:08:13+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/options-resolver",
|
"name": "symfony/options-resolver",
|
||||||
"version": "v7.0.0",
|
"version": "v7.0.0",
|
||||||
@@ -6322,16 +6582,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/validator",
|
"name": "symfony/validator",
|
||||||
"version": "v7.0.6",
|
"version": "v7.0.10",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/validator.git",
|
"url": "https://github.com/symfony/validator.git",
|
||||||
"reference": "a2df2c63b7944a162dee86ab8065f2f91b7d6e36"
|
"reference": "b3e4d838cdae9f2882402c2ad8018a27d469c075"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/validator/zipball/a2df2c63b7944a162dee86ab8065f2f91b7d6e36",
|
"url": "https://api.github.com/repos/symfony/validator/zipball/b3e4d838cdae9f2882402c2ad8018a27d469c075",
|
||||||
"reference": "a2df2c63b7944a162dee86ab8065f2f91b7d6e36",
|
"reference": "b3e4d838cdae9f2882402c2ad8018a27d469c075",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -6376,7 +6636,8 @@
|
|||||||
"Symfony\\Component\\Validator\\": ""
|
"Symfony\\Component\\Validator\\": ""
|
||||||
},
|
},
|
||||||
"exclude-from-classmap": [
|
"exclude-from-classmap": [
|
||||||
"/Tests/"
|
"/Tests/",
|
||||||
|
"/Resources/bin/"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
@@ -6396,7 +6657,7 @@
|
|||||||
"description": "Provides tools to validate values",
|
"description": "Provides tools to validate values",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/validator/tree/v7.0.6"
|
"source": "https://github.com/symfony/validator/tree/v7.0.10"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -6412,7 +6673,7 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2024-03-28T09:20:36+00:00"
|
"time": "2024-07-26T12:31:22+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/var-dumper",
|
"name": "symfony/var-dumper",
|
||||||
|
|||||||
@@ -12,4 +12,5 @@ return [
|
|||||||
Nelmio\CorsBundle\NelmioCorsBundle::class => ['all' => true],
|
Nelmio\CorsBundle\NelmioCorsBundle::class => ['all' => true],
|
||||||
Twig\Extra\TwigExtraBundle\TwigExtraBundle::class => ['all' => true],
|
Twig\Extra\TwigExtraBundle\TwigExtraBundle::class => ['all' => true],
|
||||||
Nelmio\ApiDocBundle\NelmioApiDocBundle::class => ['all' => true],
|
Nelmio\ApiDocBundle\NelmioApiDocBundle::class => ['all' => true],
|
||||||
|
Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true],
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -0,0 +1,75 @@
|
|||||||
|
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
|
||||||
|
channels: ["!event", "!doctrine"]
|
||||||
|
max_files: 0
|
||||||
|
doctrine:
|
||||||
|
type: rotating_file
|
||||||
|
path: "%kernel.logs_dir%/db_%kernel.environment%.log"
|
||||||
|
level: debug
|
||||||
|
channels: ["doctrine", "request"]
|
||||||
|
max_files: 10
|
||||||
|
# uncomment to get logging in your browser
|
||||||
|
# you may have to allow bigger header sizes in your Web server configuration
|
||||||
|
#firephp:
|
||||||
|
# type: firephp
|
||||||
|
# level: info
|
||||||
|
#chromephp:
|
||||||
|
# type: chromephp
|
||||||
|
# level: info
|
||||||
|
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]
|
||||||
|
buffer_size: 50 # How many messages should be saved? Prevent memory leaks
|
||||||
|
nested:
|
||||||
|
type: stream
|
||||||
|
path: php://stderr
|
||||||
|
level: debug
|
||||||
|
formatter: monolog.formatter.json
|
||||||
|
console:
|
||||||
|
type: console
|
||||||
|
process_psr_3_messages: false
|
||||||
|
channels: ["!event", "!doctrine"]
|
||||||
|
deprecation:
|
||||||
|
type: stream
|
||||||
|
channels: [deprecation]
|
||||||
|
path: php://stderr
|
||||||
|
formatter: monolog.formatter.json
|
||||||
|
logfile:
|
||||||
|
type: rotating_file
|
||||||
|
path: "%kernel.logs_dir%/%kernel.environment%.log"
|
||||||
|
level: info
|
||||||
|
channels: ["!event"]
|
||||||
|
max_files: 60
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App;
|
||||||
|
|
||||||
|
use App\DTO\ApiErrorMessage;
|
||||||
|
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||||
|
|
||||||
|
class ApiErrorException extends HttpException
|
||||||
|
{
|
||||||
|
|
||||||
|
private ApiErrorMessage $apiErrorMsg;
|
||||||
|
|
||||||
|
public function __construct(ApiErrorMessage $apiErrorMsg, $detailsData = null, \Exception $previous = null, array $headers = array(), $code = 0)
|
||||||
|
{
|
||||||
|
$this->apiErrorMsg = $apiErrorMsg;
|
||||||
|
|
||||||
|
if (isset($detailsData)) {
|
||||||
|
$this->apiErrorMsg->setDetails($detailsData);
|
||||||
|
}
|
||||||
|
|
||||||
|
$statusCode = $apiErrorMsg->getStatusCode();
|
||||||
|
$message = $apiErrorMsg->getTitle();
|
||||||
|
|
||||||
|
parent::__construct($statusCode, $message, $previous, $headers, $code);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getApiErrorMsg(): ApiErrorMessage
|
||||||
|
{
|
||||||
|
return $this->apiErrorMsg;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,6 +11,8 @@ use App\Repository\RoomCategoryRepository;
|
|||||||
use App\Service\AppSetupService;
|
use App\Service\AppSetupService;
|
||||||
use App\Service\ExampleDataService;
|
use App\Service\ExampleDataService;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
use Monolog\Logger;
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
@@ -20,6 +22,7 @@ class AppSetupController extends AbstractController
|
|||||||
{
|
{
|
||||||
#[Route(path: '/setup', name: 'app_setup_setup')]
|
#[Route(path: '/setup', name: 'app_setup_setup')]
|
||||||
public function addAdmin(
|
public function addAdmin(
|
||||||
|
LoggerInterface $logger,
|
||||||
AppSetupService $setupService,
|
AppSetupService $setupService,
|
||||||
Request $request,
|
Request $request,
|
||||||
EntityManagerInterface $entityManager
|
EntityManagerInterface $entityManager
|
||||||
@@ -29,6 +32,8 @@ class AppSetupController extends AbstractController
|
|||||||
$setupStatus = $configRepo->findBy(["key" => "SETUP_STATUS"]);
|
$setupStatus = $configRepo->findBy(["key" => "SETUP_STATUS"]);
|
||||||
|
|
||||||
if ($setupStatus != null && $setupStatus[0] != null && $setupStatus[0]->getValue() == 1) {
|
if ($setupStatus != null && $setupStatus[0] != null && $setupStatus[0]->getValue() == 1) {
|
||||||
|
$logger->warning("SomniaRooms was already setup");
|
||||||
|
|
||||||
return $this->GoToResultPage(
|
return $this->GoToResultPage(
|
||||||
isError: false,
|
isError: false,
|
||||||
message: "SomniaRooms already setup.",
|
message: "SomniaRooms already setup.",
|
||||||
|
|||||||
@@ -2,8 +2,9 @@
|
|||||||
|
|
||||||
namespace App\Controller;
|
namespace App\Controller;
|
||||||
|
|
||||||
|
use App\ApiErrorException;
|
||||||
|
use App\DTO\ApiErrorMessage;
|
||||||
use App\Entity\Booking;
|
use App\Entity\Booking;
|
||||||
use App\Entity\BookingCustomer;
|
|
||||||
use App\Entity\BookingRoom;
|
use App\Entity\BookingRoom;
|
||||||
use App\Repository\BookingRepository;
|
use App\Repository\BookingRepository;
|
||||||
use App\Repository\RoomCategoryRepository;
|
use App\Repository\RoomCategoryRepository;
|
||||||
@@ -16,11 +17,10 @@ use Doctrine\ORM\EntityManagerInterface;
|
|||||||
use Nelmio\ApiDocBundle\Annotation\Model;
|
use Nelmio\ApiDocBundle\Annotation\Model;
|
||||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
|
||||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
|
||||||
use Symfony\Component\Routing\Attribute\Route;
|
use Symfony\Component\Routing\Attribute\Route;
|
||||||
use OpenApi\Attributes as OA;
|
use OpenApi\Attributes as OA;
|
||||||
use Symfony\Component\HttpKernel\Attribute\MapRequestPayload;
|
use Symfony\Component\HttpKernel\Attribute\MapRequestPayload;
|
||||||
|
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||||
|
|
||||||
class BookingController extends AbstractController
|
class BookingController extends AbstractController
|
||||||
{
|
{
|
||||||
@@ -48,21 +48,16 @@ class BookingController extends AbstractController
|
|||||||
#[MapRequestPayload()] BookingDetailsRequest $detailsRequest
|
#[MapRequestPayload()] BookingDetailsRequest $detailsRequest
|
||||||
): JsonResponse {
|
): JsonResponse {
|
||||||
|
|
||||||
if (\is_null($detailsRequest)) {
|
$selectedBooking = $repoBooking->findOneBy(["refNumber" => $detailsRequest->refNumber]);
|
||||||
throw new \Exception('Invalid Payload', 400);
|
if (\is_null($selectedBooking)) {
|
||||||
|
throw new NotFoundHttpException('Booking not found');
|
||||||
}
|
}
|
||||||
|
|
||||||
$bookingList = $repoBooking->findBy(["refNumber" => $detailsRequest->refNumber]);
|
if ($selectedBooking->getBookingCustomer()->getEmail() != $detailsRequest->email) {
|
||||||
if (\is_null($bookingList) || \count($bookingList) == 0) {
|
throw new NotFoundHttpException('Booking not found');
|
||||||
throw new HttpException(404, 'Invalid Booking');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$customerBooking = $bookingList[0];
|
return $this->json($selectedBooking);
|
||||||
if ($customerBooking->getBookingCustomer()->getEmail() != $detailsRequest->email) {
|
|
||||||
throw new HttpException(404, 'Invalid Booking');
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->json($customerBooking);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -85,26 +80,25 @@ class BookingController extends AbstractController
|
|||||||
)
|
)
|
||||||
)]
|
)]
|
||||||
public function newBooking(
|
public function newBooking(
|
||||||
Request $request,
|
|
||||||
EntityManagerInterface $entityManager,
|
EntityManagerInterface $entityManager,
|
||||||
RoomCategoryRepository $repoCat,
|
RoomCategoryRepository $repoCat,
|
||||||
RoomAvailabilityRepository $repoAvailability,
|
RoomAvailabilityRepository $repoAvailability,
|
||||||
PricesService $priceSrv,
|
PricesService $priceSrv,
|
||||||
#[MapRequestPayload()] BookingCreateRequest $createRequest
|
#[MapRequestPayload()] BookingCreateRequest $createRequest
|
||||||
): JsonResponse {
|
): JsonResponse {
|
||||||
if (\is_null($createRequest)) {
|
|
||||||
throw new HttpException('Invalid Payload', 400);
|
|
||||||
}
|
|
||||||
|
|
||||||
$booking = new Booking();
|
$booking = new Booking();
|
||||||
try {
|
try {
|
||||||
if ($createRequest->arrivalDate >= $createRequest->departureDate) {
|
if ($createRequest->arrivalDate >= $createRequest->departureDate) {
|
||||||
throw new HttpException(400, "Arrival cant be before departure");
|
throw new ApiErrorException(
|
||||||
|
new ApiErrorMessage(422, ApiErrorMessage::TYPE_INVALID_DATE),
|
||||||
|
'Arrival cant be before departure',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$entityManager->beginTransaction();
|
$entityManager->beginTransaction();
|
||||||
|
|
||||||
$currentTime = new \DateTime();
|
$currentTime = new \DateTime("now");
|
||||||
|
|
||||||
// Create booking from request data.
|
// Create booking from request data.
|
||||||
$booking->setBookingTime($currentTime);
|
$booking->setBookingTime($currentTime);
|
||||||
@@ -124,7 +118,10 @@ class BookingController extends AbstractController
|
|||||||
$entityManager->persist($booking);
|
$entityManager->persist($booking);
|
||||||
|
|
||||||
if (\count($createRequest->rooms) == 0) {
|
if (\count($createRequest->rooms) == 0) {
|
||||||
throw new HttpException(400, "Se debe indicar al menos una habitación");
|
throw new ApiErrorException(
|
||||||
|
new ApiErrorMessage(422, ApiErrorMessage::TYPE_VALIDATION_ERROR),
|
||||||
|
'Booking must contain rooms',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create each room.
|
// Create each room.
|
||||||
@@ -135,7 +132,10 @@ class BookingController extends AbstractController
|
|||||||
//Get Room category.
|
//Get Room category.
|
||||||
$roomCategory = $repoCat->find($roomItem->roomCategory);
|
$roomCategory = $repoCat->find($roomItem->roomCategory);
|
||||||
if ($roomCategory == null) {
|
if ($roomCategory == null) {
|
||||||
throw new HttpException(400, "La RoomCategory no es válida.");
|
throw new ApiErrorException(
|
||||||
|
new ApiErrorMessage(422, ApiErrorMessage::TYPE_VALIDATION_ERROR),
|
||||||
|
'Invalid RoomCategory: ' . $roomItem->roomCategory,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Check room availability.
|
//Check room availability.
|
||||||
@@ -144,7 +144,10 @@ class BookingController extends AbstractController
|
|||||||
$selectedGuestAmount = $roomItem->guestNumber;
|
$selectedGuestAmount = $roomItem->guestNumber;
|
||||||
|
|
||||||
if ($amountAvailable == null || $selectedAmount > $amountAvailable) {
|
if ($amountAvailable == null || $selectedAmount > $amountAvailable) {
|
||||||
throw new HttpException(400, "No se pueden reservar más habitaciones de las disponibles.");
|
throw new ApiErrorException(
|
||||||
|
new ApiErrorMessage(400, ApiErrorMessage::TYPE_LOGICAL_ERROR),
|
||||||
|
'Not enought rooms available for category: ' . $roomItem->roomCategory,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$room->setRoomCategory($roomCategory);
|
$room->setRoomCategory($roomCategory);
|
||||||
@@ -163,9 +166,9 @@ class BookingController extends AbstractController
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!$priceFound) {
|
if (!$priceFound) {
|
||||||
throw new HttpException(
|
throw new ApiErrorException(
|
||||||
500,
|
new ApiErrorMessage(422, ApiErrorMessage::TYPE_LOGICAL_ERROR),
|
||||||
"No se puedo obtener el precio para la categoría: " . $roomCategory->getId() . " , guests: " . $selectedGuestAmount
|
'Price not found for category: ' . $roomCategory->getId() . ', guests: ' . $selectedGuestAmount,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
namespace App\Controller;
|
namespace App\Controller;
|
||||||
|
|
||||||
|
use App\ApiErrorException;
|
||||||
|
use App\DTO\ApiErrorMessage;
|
||||||
use App\Entity\ConfigVariable;
|
use App\Entity\ConfigVariable;
|
||||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
@@ -91,7 +93,9 @@ class ConfigVariableController extends AbstractController
|
|||||||
public function getVariablesBySection(ConfigVariableRepository $repo, string $section): Response
|
public function getVariablesBySection(ConfigVariableRepository $repo, string $section): Response
|
||||||
{
|
{
|
||||||
if(\is_null($section) || $section == '') {
|
if(\is_null($section) || $section == '') {
|
||||||
return new Response("Invalid section value", 404);
|
throw new ApiErrorException(
|
||||||
|
new ApiErrorMessage(400, ApiErrorMessage::TYPE_INVALID_REQUEST_BODY_FORMAT)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$varList = $repo->findAllBySection($section);
|
$varList = $repo->findAllBySection($section);
|
||||||
|
|||||||
@@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
namespace App\Controller;
|
namespace App\Controller;
|
||||||
|
|
||||||
use App\Repository\FareTableRepository;
|
use App\ApiErrorException;
|
||||||
|
use App\DTO\ApiErrorMessage;
|
||||||
use App\Repository\RoomAvailabilityRepository;
|
use App\Repository\RoomAvailabilityRepository;
|
||||||
use App\Repository\RoomCategoryRepository;
|
use App\Repository\RoomCategoryRepository;
|
||||||
use App\Request\SearchAvailabilityPeriodRequest;
|
use App\Request\SearchAvailabilityPeriodRequest;
|
||||||
@@ -12,12 +13,10 @@ use App\Response\SearchPricesForCategoryResponse;
|
|||||||
use App\Service\PricesService;
|
use App\Service\PricesService;
|
||||||
use Nelmio\ApiDocBundle\Annotation\Model;
|
use Nelmio\ApiDocBundle\Annotation\Model;
|
||||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
|
||||||
use Symfony\Component\Routing\Attribute\Route;
|
use Symfony\Component\Routing\Attribute\Route;
|
||||||
use OpenApi\Attributes as OA;
|
use OpenApi\Attributes as OA;
|
||||||
|
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||||
use Symfony\Component\HttpKernel\Attribute\MapRequestPayload;
|
use Symfony\Component\HttpKernel\Attribute\MapRequestPayload;
|
||||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
|
||||||
|
|
||||||
class SearchRoomsController extends AbstractController
|
class SearchRoomsController extends AbstractController
|
||||||
{
|
{
|
||||||
@@ -48,16 +47,15 @@ class SearchRoomsController extends AbstractController
|
|||||||
)
|
)
|
||||||
)]
|
)]
|
||||||
public function getAvailabilityForPeriod(
|
public function getAvailabilityForPeriod(
|
||||||
Request $request,
|
|
||||||
RoomAvailabilityRepository $repoAvailability,
|
RoomAvailabilityRepository $repoAvailability,
|
||||||
#[MapRequestPayload()] SearchAvailabilityPeriodRequest $searchRequest
|
#[MapRequestPayload()] SearchAvailabilityPeriodRequest $searchRequest
|
||||||
): Response {
|
): JsonResponse {
|
||||||
if (\is_null($searchRequest)) {
|
|
||||||
throw new HttpException('Invalid Payload', 400);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($searchRequest->startDate >= $searchRequest->endDate) {
|
if ($searchRequest->startDate >= $searchRequest->endDate) {
|
||||||
throw new HttpException(400, "startDate cant be before endDate");
|
throw new ApiErrorException(
|
||||||
|
new ApiErrorMessage(422, ApiErrorMessage::TYPE_INVALID_DATE),
|
||||||
|
'startDate cant be before endDate',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
$rs = $repoAvailability->getAvailabilityForPeriod($searchRequest->startDate, $searchRequest->endDate);
|
$rs = $repoAvailability->getAvailabilityForPeriod($searchRequest->startDate, $searchRequest->endDate);
|
||||||
|
|
||||||
@@ -71,13 +69,9 @@ class SearchRoomsController extends AbstractController
|
|||||||
#[Route('/api/search/availabilityDetails', name: 'app_search_availabilityDetails', methods: ["POST"], format: "json")]
|
#[Route('/api/search/availabilityDetails', name: 'app_search_availabilityDetails', methods: ["POST"], format: "json")]
|
||||||
#[OA\Tag(name: "Searchs")]
|
#[OA\Tag(name: "Searchs")]
|
||||||
public function getAvailabilityForPeriodDetails(
|
public function getAvailabilityForPeriodDetails(
|
||||||
Request $request,
|
|
||||||
RoomAvailabilityRepository $repoAvailability,
|
RoomAvailabilityRepository $repoAvailability,
|
||||||
#[MapRequestPayload()] SearchAvailabilityPeriodRequest $searchRequest
|
#[MapRequestPayload()] SearchAvailabilityPeriodRequest $searchRequest
|
||||||
): Response {
|
): JsonResponse {
|
||||||
if (\is_null($searchRequest)) {
|
|
||||||
throw new \Exception('Invalid Payload', 400);
|
|
||||||
}
|
|
||||||
|
|
||||||
$rs = $repoAvailability->getAvailabilityForPeriodDetails($searchRequest->startDate, $searchRequest->endDate);
|
$rs = $repoAvailability->getAvailabilityForPeriodDetails($searchRequest->startDate, $searchRequest->endDate);
|
||||||
|
|
||||||
@@ -112,22 +106,24 @@ class SearchRoomsController extends AbstractController
|
|||||||
)
|
)
|
||||||
)]
|
)]
|
||||||
public function getPricesForCategoryOnPeriod(
|
public function getPricesForCategoryOnPeriod(
|
||||||
Request $request,
|
|
||||||
RoomCategoryRepository $repoCat,
|
RoomCategoryRepository $repoCat,
|
||||||
PricesService $priceService,
|
PricesService $priceService,
|
||||||
#[MapRequestPayload()] SearchPricesForCategoryRequest $searchRequest
|
#[MapRequestPayload()] SearchPricesForCategoryRequest $searchRequest
|
||||||
): Response {
|
): JsonResponse {
|
||||||
if (\is_null($searchRequest)) {
|
|
||||||
throw new \Exception('Invalid Payload', 400);
|
|
||||||
}
|
|
||||||
|
|
||||||
$roomCategory = $repoCat->find($searchRequest->roomCategory);
|
$roomCategory = $repoCat->find($searchRequest->roomCategory);
|
||||||
if ($roomCategory === null) {
|
if ($roomCategory === null) {
|
||||||
throw new \Exception('Invalid Category', 400);
|
throw new ApiErrorException(
|
||||||
|
new ApiErrorMessage(422, ApiErrorMessage::TYPE_VALIDATION_ERROR),
|
||||||
|
'Invalid RoomCategory: ' . $searchRequest->roomCategory,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($searchRequest->startDate >= $searchRequest->endDate) {
|
if ($searchRequest->startDate >= $searchRequest->endDate) {
|
||||||
throw new \Exception('Invalid time interval', 400);
|
throw new ApiErrorException(
|
||||||
|
new ApiErrorMessage(422, ApiErrorMessage::TYPE_INVALID_DATE),
|
||||||
|
'startDate cant be before endDate',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$fareList = $priceService->getFinalPricesForSearch($roomCategory, $searchRequest->startDate, $searchRequest->endDate);
|
$fareList = $priceService->getFinalPricesForSearch($roomCategory, $searchRequest->startDate, $searchRequest->endDate);
|
||||||
@@ -138,19 +134,4 @@ class SearchRoomsController extends AbstractController
|
|||||||
|
|
||||||
return $this->json(["results" => $rs]);
|
return $this->json(["results" => $rs]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Route('/debug/search', name: 'app_search_faresDebug')]
|
|
||||||
public function faresDebug(Request $request, PricesService $priceService, FareTableRepository $repoFareTable, RoomCategoryRepository $repoCat): Response
|
|
||||||
{
|
|
||||||
$fareTable[] = $repoFareTable->find(1);
|
|
||||||
$fareTable[] = $repoFareTable->find(2);
|
|
||||||
$cat = $repoCat->find(4);
|
|
||||||
|
|
||||||
$startDate = new \DateTime("2024-04-27");
|
|
||||||
$endDate = new \DateTime("2024-05-02");
|
|
||||||
|
|
||||||
$rs = $priceService->getFinalPricesForSearch($cat, $startDate, $endDate);
|
|
||||||
|
|
||||||
return $this->json($rs);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,80 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\DTO;
|
||||||
|
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
|
class ApiErrorMessage
|
||||||
|
{
|
||||||
|
const TYPE_VALIDATION_ERROR = 'validation_error';
|
||||||
|
const TYPE_INVALID_REQUEST_BODY_FORMAT = 'invalid_body_format';
|
||||||
|
const TYPE_LOGICAL_ERROR = 'logical_error';
|
||||||
|
const TYPE_SERVER_ERROR = 'server_error';
|
||||||
|
const TYPE_INVALID_DATE = 'invalid_date';
|
||||||
|
|
||||||
|
private static $titles = array(
|
||||||
|
self::TYPE_VALIDATION_ERROR => 'There was a validation error',
|
||||||
|
self::TYPE_INVALID_REQUEST_BODY_FORMAT => 'Invalid JSON format sent',
|
||||||
|
self::TYPE_LOGICAL_ERROR => 'Invalid request due to a logic error',
|
||||||
|
self::TYPE_SERVER_ERROR => 'Error on server side',
|
||||||
|
self::TYPE_INVALID_DATE => 'Invalid date on request',
|
||||||
|
);
|
||||||
|
|
||||||
|
private int $statusCode;
|
||||||
|
private string $type;
|
||||||
|
private string $title;
|
||||||
|
private array $extraData = array();
|
||||||
|
|
||||||
|
public function __construct($statusCode, $type = null)
|
||||||
|
{
|
||||||
|
if ($type === null) {
|
||||||
|
// no type? The default is about:blank and the title should
|
||||||
|
// be the standard status code message
|
||||||
|
$type = 'about:blank';
|
||||||
|
$title = isset(Response::$statusTexts[$statusCode]) ?
|
||||||
|
Response::$statusTexts[$statusCode] : 'Unknown status code :(';
|
||||||
|
} else {
|
||||||
|
if (!isset(self::$titles[$type])) {
|
||||||
|
throw new \InvalidArgumentException('No title for type ' . $type);
|
||||||
|
}
|
||||||
|
$title = self::$titles[$type];
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->statusCode = $statusCode;
|
||||||
|
$this->type = $type;
|
||||||
|
$this->title = $title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getStatusCode(): int
|
||||||
|
{
|
||||||
|
return $this->statusCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTitle(): string
|
||||||
|
{
|
||||||
|
return $this->title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setExtraData($name, $value)
|
||||||
|
{
|
||||||
|
$this->extraData[$name] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setDetails($value)
|
||||||
|
{
|
||||||
|
$this->extraData['details'] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function toArray(): array
|
||||||
|
{
|
||||||
|
return array_merge(
|
||||||
|
$this->extraData,
|
||||||
|
array(
|
||||||
|
'status' => $this->statusCode,
|
||||||
|
'type' => $this->type,
|
||||||
|
'title' => $this->title,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@ namespace App\Entity;
|
|||||||
use App\Repository\BookingCustomerRepository;
|
use App\Repository\BookingCustomerRepository;
|
||||||
use Doctrine\ORM\Mapping as ORM;
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
use Symfony\Component\Serializer\Annotation\Ignore;
|
use Symfony\Component\Serializer\Annotation\Ignore;
|
||||||
|
use Symfony\Component\Validator\Constraints as Assert;
|
||||||
|
|
||||||
#[ORM\Entity(repositoryClass: BookingCustomerRepository::class)]
|
#[ORM\Entity(repositoryClass: BookingCustomerRepository::class)]
|
||||||
class BookingCustomer
|
class BookingCustomer
|
||||||
@@ -21,15 +22,20 @@ class BookingCustomer
|
|||||||
private ?Booking $booking = null;
|
private ?Booking $booking = null;
|
||||||
|
|
||||||
#[ORM\Column(length: 64)]
|
#[ORM\Column(length: 64)]
|
||||||
|
#[Assert\NotBlank]
|
||||||
private ?string $name = null;
|
private ?string $name = null;
|
||||||
|
|
||||||
#[ORM\Column(length: 255)]
|
#[ORM\Column(length: 255)]
|
||||||
|
#[Assert\NotBlank]
|
||||||
private ?string $surname = null;
|
private ?string $surname = null;
|
||||||
|
|
||||||
#[ORM\Column(length: 255)]
|
#[ORM\Column(length: 255)]
|
||||||
|
#[Assert\NotBlank]
|
||||||
|
#[Assert\Email]
|
||||||
private ?string $email = null;
|
private ?string $email = null;
|
||||||
|
|
||||||
#[ORM\Column(length: 255)]
|
#[ORM\Column(length: 255)]
|
||||||
|
#[Assert\NotBlank]
|
||||||
private ?string $phoneNumber = null;
|
private ?string $phoneNumber = null;
|
||||||
|
|
||||||
public function getId(): ?int
|
public function getId(): ?int
|
||||||
|
|||||||
@@ -0,0 +1,86 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\EventSubscriber;
|
||||||
|
|
||||||
|
use App\ApiErrorException;
|
||||||
|
use App\DTO\ApiErrorMessage;
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
|
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||||
|
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
|
||||||
|
use Symfony\Component\HttpKernel\KernelEvents;
|
||||||
|
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||||
|
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
|
||||||
|
use Symfony\Component\Validator\Exception\ValidationFailedException;
|
||||||
|
|
||||||
|
class ApiExceptionSubscriber implements EventSubscriberInterface
|
||||||
|
{
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
private LoggerInterface $logger,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public function onKernelException(ExceptionEvent $event): void
|
||||||
|
{
|
||||||
|
$e = $event->getThrowable();
|
||||||
|
if ($e instanceof ApiErrorException) {
|
||||||
|
$apiErrorMsg = $e->getApiErrorMsg();
|
||||||
|
} else {
|
||||||
|
$statusCode = $e instanceof HttpExceptionInterface ? $e->getStatusCode() : 500;
|
||||||
|
$apiErrorMsg = new ApiErrorMessage($statusCode);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If it's an HttpException message (e.g. for 404, 403),
|
||||||
|
* we'll say as a rule that the exception message is safe
|
||||||
|
* for the client. Otherwise, it could be some sensitive
|
||||||
|
* low-level exception, which should *not* be exposed
|
||||||
|
*/
|
||||||
|
if ($e instanceof HttpExceptionInterface) {
|
||||||
|
//Check if it's a Validation error.
|
||||||
|
// When using MapRequestPayload() ValidationErrors throw HttpExceptions.
|
||||||
|
$prev = $e->getPrevious();
|
||||||
|
if ($prev instanceof ValidationFailedException) {
|
||||||
|
//Get validation error details.
|
||||||
|
$errorList = [];
|
||||||
|
$violationList = $prev->getViolations();
|
||||||
|
foreach ($violationList as $violation) {
|
||||||
|
$errorList[] = [
|
||||||
|
'field' => $violation->getPropertyPath(),
|
||||||
|
'message' => $violation->getMessage(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
$apiErrorMsg->setExtraData('detail', "Validation Error. See errorList for details");
|
||||||
|
$apiErrorMsg->setExtraData('errorList', $errorList);
|
||||||
|
} else {
|
||||||
|
//Get exception error message.
|
||||||
|
$apiErrorMsg->setExtraData('detail', $e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Send error to logs.
|
||||||
|
$exceptionError = [
|
||||||
|
'message' => $e->getMessage(),
|
||||||
|
'file' => $e->getFile(),
|
||||||
|
'line' => $e->getLine(),
|
||||||
|
'trace' => $e->getTrace()
|
||||||
|
];
|
||||||
|
$errorContext = array_merge($apiErrorMsg->toArray(), $exceptionError);
|
||||||
|
$this->logger->error("API ERROR Exception:", $errorContext);
|
||||||
|
|
||||||
|
//Send error to client.
|
||||||
|
$response = new JsonResponse(
|
||||||
|
$apiErrorMsg->toArray(),
|
||||||
|
$apiErrorMsg->getStatusCode()
|
||||||
|
);
|
||||||
|
$response->headers->set('Content-Type', 'application/problem+json');
|
||||||
|
|
||||||
|
$event->setResponse($response);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getSubscribedEvents(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
KernelEvents::EXCEPTION => 'onKernelException',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,19 +3,26 @@
|
|||||||
namespace App\Request;
|
namespace App\Request;
|
||||||
|
|
||||||
use App\Entity\BookingCustomer;
|
use App\Entity\BookingCustomer;
|
||||||
|
use DateTimeInterface;
|
||||||
use OpenApi\Attributes as OA;
|
use OpenApi\Attributes as OA;
|
||||||
|
use Symfony\Component\Validator\Constraints as Assert;
|
||||||
|
|
||||||
class BookingCreateRequest
|
class BookingCreateRequest
|
||||||
{
|
{
|
||||||
#[OA\Property(description: 'Booking Arrival date')]
|
#[OA\Property(description: 'Booking Arrival date')]
|
||||||
public \DateTime $arrivalDate;
|
#[Assert\NotBlank]
|
||||||
|
#[Assert\GreaterThanOrEqual(value: 'today')]
|
||||||
|
public DateTimeInterface $arrivalDate;
|
||||||
|
|
||||||
#[OA\Property(description: 'Booking departure date')]
|
#[OA\Property(description: 'Booking departure date')]
|
||||||
public \DateTime $departureDate;
|
#[Assert\NotBlank]
|
||||||
|
public DateTimeInterface $departureDate;
|
||||||
|
|
||||||
#[OA\Property(
|
#[OA\Property(
|
||||||
description: 'Booking customer details',
|
description: 'Booking customer details',
|
||||||
)]
|
)]
|
||||||
|
#[Assert\NotBlank]
|
||||||
|
#[Assert\Valid]
|
||||||
public BookingCustomer $customerDetails;
|
public BookingCustomer $customerDetails;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -24,5 +31,7 @@ class BookingCreateRequest
|
|||||||
#[OA\Property(
|
#[OA\Property(
|
||||||
description: 'Rooms to book',
|
description: 'Rooms to book',
|
||||||
)]
|
)]
|
||||||
|
#[Assert\NotBlank]
|
||||||
|
#[Assert\Valid]
|
||||||
public array $rooms;
|
public array $rooms;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,15 +3,21 @@
|
|||||||
namespace App\Request;
|
namespace App\Request;
|
||||||
|
|
||||||
use OpenApi\Attributes as OA;
|
use OpenApi\Attributes as OA;
|
||||||
|
use Symfony\Component\Validator\Constraints as Assert;
|
||||||
|
|
||||||
class BookingCreateRoomItem
|
class BookingCreateRoomItem
|
||||||
{
|
{
|
||||||
#[OA\Property(description: 'Room category ID')]
|
#[OA\Property(description: 'Room category ID')]
|
||||||
|
#[Assert\NotBlank]
|
||||||
public int $roomCategory;
|
public int $roomCategory;
|
||||||
|
|
||||||
#[OA\Property(description: 'Guest number for the room')]
|
#[OA\Property(description: 'Guest number for the room')]
|
||||||
|
#[Assert\NotBlank]
|
||||||
|
#[Assert\GreaterThan(value: 0)]
|
||||||
public int $guestNumber;
|
public int $guestNumber;
|
||||||
|
|
||||||
#[OA\Property(description: 'Room amount')]
|
#[OA\Property(description: 'Room amount')]
|
||||||
|
#[Assert\NotBlank]
|
||||||
|
#[Assert\GreaterThan(value: 0)]
|
||||||
public int $amount;
|
public int $amount;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,12 +3,16 @@
|
|||||||
namespace App\Request;
|
namespace App\Request;
|
||||||
|
|
||||||
use OpenApi\Attributes as OA;
|
use OpenApi\Attributes as OA;
|
||||||
|
use Symfony\Component\Validator\Constraints as Assert;
|
||||||
|
|
||||||
class BookingDetailsRequest
|
class BookingDetailsRequest
|
||||||
{
|
{
|
||||||
#[OA\Property(description: 'Booking reference number')]
|
#[OA\Property(description: 'Booking reference number')]
|
||||||
|
#[Assert\NotBlank]
|
||||||
public string $refNumber;
|
public string $refNumber;
|
||||||
|
|
||||||
#[OA\Property(maxLength: 255, description: 'Email associated to the booking')]
|
#[OA\Property(maxLength: 255, description: 'Email associated to the booking')]
|
||||||
|
#[Assert\NotBlank]
|
||||||
|
#[Assert\Email]
|
||||||
public string $email;
|
public string $email;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,13 +2,17 @@
|
|||||||
|
|
||||||
namespace App\Request;
|
namespace App\Request;
|
||||||
|
|
||||||
|
use DateTimeInterface;
|
||||||
use OpenApi\Attributes as OA;
|
use OpenApi\Attributes as OA;
|
||||||
|
use Symfony\Component\Validator\Constraints as Assert;
|
||||||
|
|
||||||
class SearchAvailabilityPeriodRequest
|
class SearchAvailabilityPeriodRequest
|
||||||
{
|
{
|
||||||
#[OA\Property(description: 'Period start date')]
|
#[OA\Property(description: 'Period start date')]
|
||||||
public \DateTime $startDate;
|
#[Assert\NotBlank]
|
||||||
|
public DateTimeInterface $startDate;
|
||||||
|
|
||||||
#[OA\Property(description: 'Period end date')]
|
#[OA\Property(description: 'Period end date')]
|
||||||
public \DateTime $endDate;
|
#[Assert\NotBlank]
|
||||||
|
public DateTimeInterface $endDate;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,16 +2,21 @@
|
|||||||
|
|
||||||
namespace App\Request;
|
namespace App\Request;
|
||||||
|
|
||||||
|
use DateTimeInterface;
|
||||||
use OpenApi\Attributes as OA;
|
use OpenApi\Attributes as OA;
|
||||||
|
use Symfony\Component\Validator\Constraints as Assert;
|
||||||
|
|
||||||
class SearchPricesForCategoryRequest
|
class SearchPricesForCategoryRequest
|
||||||
{
|
{
|
||||||
#[OA\Property(description: 'Room category ID')]
|
#[OA\Property(description: 'Room category ID')]
|
||||||
|
#[Assert\NotBlank]
|
||||||
public int $roomCategory;
|
public int $roomCategory;
|
||||||
|
|
||||||
#[OA\Property(description: 'Period start date')]
|
#[OA\Property(description: 'Period start date')]
|
||||||
public \DateTime $startDate;
|
#[Assert\NotBlank]
|
||||||
|
public DateTimeInterface $startDate;
|
||||||
|
|
||||||
#[OA\Property(description: 'Period end date')]
|
#[OA\Property(description: 'Period end date')]
|
||||||
public \DateTime $endDate;
|
#[Assert\NotBlank]
|
||||||
|
public DateTimeInterface $endDate;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -127,6 +127,18 @@
|
|||||||
"ref": "fadbfe33303a76e25cb63401050439aa9b1a9c7f"
|
"ref": "fadbfe33303a76e25cb63401050439aa9b1a9c7f"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"symfony/monolog-bundle": {
|
||||||
|
"version": "3.10",
|
||||||
|
"recipe": {
|
||||||
|
"repo": "github.com/symfony/recipes",
|
||||||
|
"branch": "main",
|
||||||
|
"version": "3.7",
|
||||||
|
"ref": "aff23899c4440dd995907613c1dd709b6f59503f"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"./config/packages/monolog.yaml"
|
||||||
|
]
|
||||||
|
},
|
||||||
"symfony/routing": {
|
"symfony/routing": {
|
||||||
"version": "7.0",
|
"version": "7.0",
|
||||||
"recipe": {
|
"recipe": {
|
||||||
|
|||||||
Reference in New Issue
Block a user