diff --git a/.changes/v3.2.3.md b/.changes/v3.2.3.md new file mode 100644 index 000000000..b7064350a --- /dev/null +++ b/.changes/v3.2.3.md @@ -0,0 +1,4 @@ +## v3.2.3 - 2024-11-05 +### Fixed +* ([#315](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/315)) Fix display of accompanying period work referrers. Only current referrers should be displayed. +Fix color of Chill footer diff --git a/.changes/v3.2.4.md b/.changes/v3.2.4.md new file mode 100644 index 000000000..f89cf37eb --- /dev/null +++ b/.changes/v3.2.4.md @@ -0,0 +1,3 @@ +## v3.2.4 - 2024-11-06 +### Fixed +* Fix compilation of chill assets diff --git a/.changes/v3.3.0.md b/.changes/v3.3.0.md new file mode 100644 index 000000000..bb56973b7 --- /dev/null +++ b/.changes/v3.3.0.md @@ -0,0 +1,13 @@ +## v3.3.0 - 2024-11-20 +### Feature +* Electronic signature + +Implementation of the electronic signature for documents within chill. +* ([#286](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/286)) The behavoir of the voters for stored objects is adjusted so as to limit edit and delete possibilities to users related to the activity, social action or workflow entity. +* ([#288](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/288)) Metadata form added for person signatures +* Add a signature step in workflow, which allow to apply an electronic signature on documents +* Keep an history of each version of a stored object. +* Add a "send external" step in workflow, which allow to send stored objects and other elements to remote people, by sending them a public url +### Fixed +* Adjust household list export to include households even if their address is NULL +* Remove validation of date string on deathDate diff --git a/.changes/v3.4.0.md b/.changes/v3.4.0.md new file mode 100644 index 000000000..3fc4dd5d6 --- /dev/null +++ b/.changes/v3.4.0.md @@ -0,0 +1,4 @@ +## v3.4.0 - 2024-11-20 +### Feature +* ([#314](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/314)) Admin: improve document type admin form with a select field for related class. +Admin: Allow administrator to assign multiple group centers in one go to a user. diff --git a/.changes/v3.4.1.md b/.changes/v3.4.1.md new file mode 100644 index 000000000..261023d15 --- /dev/null +++ b/.changes/v3.4.1.md @@ -0,0 +1,3 @@ +## v3.4.1 - 2024-11-22 +### Fixed +* Set the workflow's title to notification content and subject diff --git a/.changes/v3.4.2.md b/.changes/v3.4.2.md new file mode 100644 index 000000000..18b0759e0 --- /dev/null +++ b/.changes/v3.4.2.md @@ -0,0 +1,6 @@ +## v3.4.2 - 2024-12-05 +### Fixed +* ([#329](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/329)) Fix the serialization of gender for the generation of documents +* ([#337](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/337)) Enforce unique contraint on activity storedobject +### DX +* ([#310](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/310)) Clean migrations, to reduce the number of bloated migration when running diff on schema diff --git a/.changes/v3.4.3.md b/.changes/v3.4.3.md new file mode 100644 index 000000000..00acd4577 --- /dev/null +++ b/.changes/v3.4.3.md @@ -0,0 +1,4 @@ +## v3.4.3 - 2024-12-05 +### Fixed +* Remove the "not null" constraint on person supplementary phones +* Remove doctrine annotation that prevent from adding documents to activities diff --git a/.changes/v3.5.0.md b/.changes/v3.5.0.md new file mode 100644 index 000000000..566b883a0 --- /dev/null +++ b/.changes/v3.5.0.md @@ -0,0 +1,6 @@ +## v3.5.0 - 2024-12-09 +### Feature +* ([#318](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/318)) Show all the pages of the documents in the signature app +### Fixed +* Wrap the signature's change state into a transaction, to avoid race conditions +* Fix display of gender label diff --git a/.env b/.env index 1714966d4..4c6ee4ca6 100644 --- a/.env +++ b/.env @@ -11,19 +11,13 @@ # Run "composer dump-env prod" to compile .env files for production use (requires symfony/flex >=1.2). # https://symfony.com/doc/current/best_practices.html#use-environment-variables-for-infrastructure-configuration -## Locale -LOCALE=fr - ###> symfony/framework-bundle ### -# this should be set in docker-compose.yml file APP_ENV=prod -APP_SECRET=ChangeItf2b58287ef7f9976409d3f6c72529e99ChangeIt -TRUSTED_PROXIES=127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 -TRUSTED_HOSTS='^(localhost|example\.com|nginx)$' +APP_SECRET=!ChangeMeInAppEnv! ###< symfony/framework-bundle ### ## Wopi server for editing documents online -WOPI_SERVER=http://collabora:9980 +EDITOR_SERVER=http://collabora:9980 # must be manually set in .env.local # ADMIN_PASSWORD= @@ -32,52 +26,14 @@ WOPI_SERVER=http://collabora:9980 # MAILER_DSN=null://null ###< symfony/mailer ### -## Notifications -NOTIFICATION_HOST=localhost:8001 -NOTIFICATION_FROM_EMAIL=admin@chill.social -NOTIFICATION_FROM_NAME="Chill " - -## Pgadmin credential -PGADMIN_DEFAULT_EMAIL= -PGADMIN_DEFAULT_PASSWORD= - -## OVH OpenStack Storage Container -ASYNC_UPLOAD_TEMP_URL_KEY= -ASYNC_UPLOAD_TEMP_URL_BASE_PATH= -ASYNC_UPLOAD_TEMP_URL_CONTAINER= - -## Redis Cache -REDIS_HOST=redis -REDIS_PORT=6379 -REDIS_URL=redis://${REDIS_HOST}:${REDIS_PORT} - -## Twilio -TWILIO_SID=~ -TWILIO_SECRET=~ -DEFAULT_CARRIER_CODE=BE - -ADD_ADDRESS_DEFAULT_COUNTRY=BE - -ADD_ADDRESS_MAP_CENTER_X=50.8443 -ADD_ADDRESS_MAP_CENTER_Y=4.3523 -ADD_ADDRESS_MAP_CENTER_Z=15 - -SHORT_MESSAGE_DSN=null://null - -## DOCKER IMAGES REGISTRY -#IMAGE_PHP= -#IMAGE_NGINX= - -## DOCKER IMAGES TAG -#VERSION=test -#VERSION=prod ###> symfony/messenger ### # Choose one of the transports below # MESSENGER_TRANSPORT_DSN=amqp://guest:guest@localhost:5672/%2f/messages # MESSENGER_TRANSPORT_DSN=redis://localhost:6379/messages -MESSENGER_TRANSPORT_DSN=sync:// -MESSENGER_TRANSPORT_DSN=doctrine://default?auto_setup=0 +# MESSENGER_TRANSPORT_DSN=sync:// +# MESSENGER_TRANSPORT_DSN=doctrine://default?auto_setup=0 +MESSENGER_TRANSPORT_DSN=${RABBITMQ_URL}/%2f ###< symfony/messenger ### ###> doctrine/doctrine-bundle ### @@ -92,3 +48,43 @@ JWT_SECRET_KEY=%kernel.project_dir%/config/jwt/private.pem JWT_PUBLIC_KEY=%kernel.project_dir%/config/jwt/public.pem JWT_PASSPHRASE=2a30f6ba26521a2613821da35f28386e ###< lexik/jwt-authentication-bundle ### + +###> chill-project/chill-bundles ### +# Generate a password using `symfony console security:hash-password --empty-salt 'Symfony\Component\Security\Core\User\User'` and paste it into .env.local file +# ADMIN_PASSWORD= +# Add a configuration for sending SMS (before calendar appointments, aka "Rendez-vous"). See https://symfony.com/doc/current/notifier.html#sms-channel +# Configuration for using ovh custom notifier +# SHORT_MESSAGE_DSN="ovh://user:password@ovh-eu?consumer_key=123456&sender=%2B32475123456&service_name=sms-xx123456-1" +SHORT_MESSAGE_DSN=null://null +# Default locale for the project +LOCALE=fr +# Those keys are required to configure the access to store documents +ASYNC_UPLOAD_TEMP_URL_KEY= +ASYNC_UPLOAD_TEMP_URL_BASE_PATH= +ASYNC_UPLOAD_TEMP_URL_CONTAINER= +# Twilio configuration, to check for the existence of phonenumber in a directory (may be deprecated in a near future) +TWILIO_SID= +TWILIO_SECRET= +# Default carrier code will replace all leading zero by an international code. Set here the country as two letters +DEFAULT_CARRIER_CODE=FR +# Configuration for the notification emails +NOTIFICATION_FROM_EMAIL=chill@instance.com +NOTIFICATION_FROM_NAME=Chill +# Will set the default host when sending email from command or services (see https://symfony.com/doc/5.x/routing.html#generating-urls-in-commands) +NOTIFICATION_HOST=my.chill.social +# Variables for relatorio host, which generates documents +RELATORIO_HOST= +RELATORIO_PORT= +# Address for your collabora server +#EDITOR_SERVER=https://code.example.com +EDITOR_SERVER=https://collabora.champs-libres.be +# center address widget when empty +ADD_ADDRESS_DEFAULT_COUNTRY=BE +ADD_ADDRESS_MAP_CENTER_X=50.8443 +ADD_ADDRESS_MAP_CENTER_Y=4.3523 +ADD_ADDRESS_MAP_CENTER_Z=15 +## Redis Cache & redis database +REDIS_HOST=redis +REDIS_PORT=6379 +REDIS_URL=redis://${REDIS_HOST}:${REDIS_PORT} +###< chill-project/chill-bundles ### diff --git a/.env.test b/.env.test index f84920e54..9cd2ae81b 100644 --- a/.env.test +++ b/.env.test @@ -4,15 +4,8 @@ KERNEL_CLASS='App\Kernel' APP_SECRET='$ecretf0rt3st' -TRUSTED_HOSTS= - ADMIN_PASSWORD=password -LOCALE=fr -REDIS_URL=redis -REDIS_PORT=6379 -REDIS_URL=redis://${REDIS_HOST}:${REDIS_PORT} - JWT_SECRET_KEY=%kernel.project_dir%/config/jwt/private.pem JWT_PUBLIC_KEY=%kernel.project_dir%/config/jwt/public.pem JWT_PASSPHRASE=2a30f6ba26521a2613821da35f28386e @@ -22,22 +15,25 @@ TWILIO_SECRET=~ DEFAULT_CARRIER_CODE=BE ADD_ADDRESS_DEFAULT_COUNTRY=BE - ADD_ADDRESS_MAP_CENTER_X=50.8443 ADD_ADDRESS_MAP_CENTER_Y=4.3523 ADD_ADDRESS_MAP_CENTER_Z=15 SHORT_MESSAGE_DSN=null://null MESSENGER_TRANSPORT_DSN=sync:// -###< symfony/messenger ### ###> doctrine/doctrine-bundle ### # Format described at https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url # IMPORTANT: You MUST configure your server version, either here or in config/packages/doctrine.yaml # -DATABASE_URL="postgresql://postgres:postgres@db:5432/test?serverVersion=14&charset=utf8" +DATABASE_URL="postgresql://app:!ChangeMe!@127.0.0.1:5454/test?serverVersion=14&charset=utf8" ###< doctrine/doctrine-bundle ### ASYNC_UPLOAD_TEMP_URL_KEY= ASYNC_UPLOAD_TEMP_URL_BASE_PATH= ASYNC_UPLOAD_TEMP_URL_CONTAINER= + +MAILER_DSN=null://null + +REDIS_HOST=127.0.0.1 +REDIS_PORT=6363 diff --git a/.gitignore b/.gitignore index 26802dca0..41e33aa1b 100644 --- a/.gitignore +++ b/.gitignore @@ -3,10 +3,18 @@ composer composer.phar composer.lock docs/build/ -node_modules/* .php_cs.cache .cache/* +docker/db/data +docker/rabbitmq/data + +# in this development bundle, we want to ignore directories related to a real app +assets/* +migrations/* +templates/* +translations/* + ###> symfony/framework-bundle ### /.env.local /.env.local.php @@ -15,7 +23,6 @@ node_modules/* /public/bundles/ /var/ /vendor/ -/bin/ ###< symfony/framework-bundle ### ###> phpunit/phpunit ### @@ -27,4 +34,20 @@ node_modules/* /.idea/ /.psalm/ -node_modules/* +###> phpstan/phpstan ### +phpstan.neon +###< phpstan/phpstan ### + +###> lexik/jwt-authentication-bundle ### +/config/jwt/*.pem +###< lexik/jwt-authentication-bundle ### + +###> symfony/phpunit-bridge ### +###< symfony/phpunit-bridge ### + +###> symfony/webpack-encore-bundle ### +/node_modules/ +/public/build/ +npm-debug.log +yarn-error.log +###< symfony/webpack-encore-bundle ### diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 2e4915f63..a632f8f18 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -10,7 +10,7 @@ cache: # Bring in any services we need http://docs.gitlab.com/ee/ci/docker/using_docker_images.html#what-is-a-service # See http://docs.gitlab.com/ee/ci/services/README.html for examples. services: - - name: postgis/postgis:14-3.3-alpine + - name: postgis/postgis:17-3.5-alpine alias: db command: - postgres @@ -27,7 +27,7 @@ variables: POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres # configure database access - DATABASE_URL: postgresql://postgres:postgres@db:5432/postgres?serverVersion=14&charset=utf8 + DATABASE_URL: postgresql://postgres:postgres@db:5432/postgres?serverVersion=17&charset=utf8 # fetch the chill-app using git submodules # GIT_SUBMODULE_STRATEGY: recursive REDIS_HOST: redis @@ -57,7 +57,6 @@ build: artifacts: expire_in: 1 day paths: - - bin - vendor/ code_style: @@ -71,36 +70,38 @@ code_style: artifacts: expire_in: 1 day paths: - - bin - vendor/ phpstan_tests: stage: Tests image: gitea.champs-libres.be/chill-project/chill-skeleton-basic/base-image:php82 + variables: + COMPOSER_MEMORY_LIMIT: 3G + before_script: + - bin/console cache:clear --env=dev script: - - bin/phpstan analyze --memory-limit=2G + - composer exec phpstan -- analyze --memory-limit=3G cache: paths: - .cache/ artifacts: expire_in: 1 day paths: - - bin - vendor/ rector_tests: stage: Tests image: gitea.champs-libres.be/chill-project/chill-skeleton-basic/base-image:php82 + before_script: + - bin/console cache:clear --env=dev script: - - tests/console cache:clear - - bin/rector process --dry-run + - composer exec rector -- process --dry-run cache: paths: - .cache/ artifacts: expire_in: 1 day paths: - - bin - vendor/ lint: @@ -132,16 +133,19 @@ lint: unit_tests: stage: Tests image: gitea.champs-libres.be/chill-project/chill-skeleton-basic/base-image:php82 + variables: + COMPOSER_MEMORY_LIMIT: 3G + before_script: + - php bin/console doctrine:database:create -n --env=test + - php bin/console doctrine:migrations:migrate -n --env=test + - php bin/console chill:db:sync-views --env=test + - php bin/console cache:clear --env=test + - php bin/console doctrine:fixtures:load -n --env=test script: - - php tests/console doctrine:migrations:migrate -n --env=test - - php tests/console chill:db:sync-views --env=test - - php -d memory_limit=2G tests/console cache:clear --env=test - - php -d memory_limit=3G tests/console doctrine:fixtures:load -n --env=test - - php -d memory_limit=4G bin/phpunit --colors=never --exclude-group dbIntensive + - composer exec phpunit -- --colors=never --exclude-group dbIntensive,openstack-integration artifacts: expire_in: 1 day paths: - - bin - vendor/ release: diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 000000000..2edeafb09 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +20 \ No newline at end of file diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index 4a70e81e7..49b6f1a07 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -120,6 +120,6 @@ $rules = array_merge( $untilFullSwitchToPhp8, ); -$rules['header_comment']['header'] = trim(file_get_contents(__DIR__.'/resource/header.txt')); +$rules['header_comment']['header'] = trim(file_get_contents(__DIR__.'/resources/header.txt')); return $config->setRules($rules); diff --git a/.symfony.local.yaml b/.symfony.local.yaml new file mode 100644 index 000000000..fad7fc396 --- /dev/null +++ b/.symfony.local.yaml @@ -0,0 +1,2 @@ +workers: + docker_compose: ~ diff --git a/CHANGELOG.md b/CHANGELOG.md index fabe545d6..e82ce62bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,57 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html), and is generated by [Changie](https://github.com/miniscruff/changie). +## v3.5.0 - 2024-12-09 +### Feature +* ([#318](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/318)) Show all the pages of the documents in the signature app +### Fixed +* Wrap the signature's change state into a transaction, to avoid race conditions +* Fix display of gender label + +## v3.4.3 - 2024-12-05 +### Fixed +* Remove the "not null" constraint on person supplementary phones +* Remove doctrine annotation that prevent from adding documents to activities + +## v3.4.2 - 2024-12-05 +### Fixed +* ([#329](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/329)) Fix the serialization of gender for the generation of documents +* ([#337](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/337)) Enforce unique contraint on activity storedobject +### DX +* ([#310](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/310)) Clean migrations, to reduce the number of bloated migration when running diff on schema + +## v3.4.1 - 2024-11-22 +### Fixed +* Set the workflow's title to notification content and subject + +## v3.4.0 - 2024-11-20 +### Feature +* ([#314](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/314)) Admin: improve document type admin form with a select field for related class. +Admin: Allow administrator to assign multiple group centers in one go to a user. + +## v3.3.0 - 2024-11-20 +### Feature +* Electronic signature + +Implementation of the electronic signature for documents within chill. +* ([#286](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/286)) The behavoir of the voters for stored objects is adjusted so as to limit edit and delete possibilities to users related to the activity, social action or workflow entity. +* ([#288](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/288)) Metadata form added for person signatures +* Add a signature step in workflow, which allow to apply an electronic signature on documents +* Keep an history of each version of a stored object. +* Add a "send external" step in workflow, which allow to send stored objects and other elements to remote people, by sending them a public url +### Fixed +* Adjust household list export to include households even if their address is NULL +* Remove validation of date string on deathDate + +## v3.2.4 - 2024-11-06 +### Fixed +* Fix compilation of chill assets + +## v3.2.3 - 2024-11-05 +### Fixed +* ([#315](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/315)) Fix display of accompanying period work referrers. Only current referrers should be displayed. +Fix color of Chill footer + ## v3.2.2 - 2024-10-31 ### Fixed * Fix gender translation for unknown diff --git a/README.md b/README.md index bf3e28f41..6a5c7d603 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,15 @@ -# Chill framework +# Main Chill Bundles and Chill framework -Documentation of the Chill software. +Chill is a software for social workers. It allows them to keep track of the social work they do. -The online documentation can be found at http://docs.chill.social +See our website for more information https://www.chill.social -See the [`docs`][1] directory for more. +## Installation -[1]: docs/README.md +Chill-bundles is a set of bundles that should be used within a Symfony application. + +A symfony application will help you to customize all the configuration options, change the behaviour of some parts of the usual-way that chill works, … without to have to fork this repository ! + +See [the instructions in the docs](./docs/source/installation/index.rst). + +Those instructions are also built [online](https://docs.chill.social). diff --git a/tests/console b/bin/console similarity index 78% rename from tests/console rename to bin/console index c933dc535..d8d530e2c 100755 --- a/tests/console +++ b/bin/console @@ -4,6 +4,10 @@ use App\Kernel; use Symfony\Bundle\FrameworkBundle\Console\Application; +if (!is_dir(dirname(__DIR__).'/vendor')) { + throw new LogicException('Dependencies are missing. Try running "composer install".'); +} + if (!is_file(dirname(__DIR__).'/vendor/autoload_runtime.php')) { throw new LogicException('Symfony Runtime is missing. Try running "composer require symfony/runtime".'); } diff --git a/compose.override.yaml b/compose.override.yaml new file mode 100644 index 000000000..01169fbf0 --- /dev/null +++ b/compose.override.yaml @@ -0,0 +1,34 @@ +services: + ###> doctrine/doctrine-bundle ### + database: + ports: + - "127.0.0.1:5454:5432" + ###< doctrine/doctrine-bundle ### + + ###> symfony/mailer ### + mailer: + image: axllent/mailpit + ports: + - "1025" + - "8025" + environment: + MP_SMTP_AUTH_ACCEPT_ANY: 1 + MP_SMTP_AUTH_ALLOW_INSECURE: 1 + ###< symfony/mailer ### + + + redis: + ports: + - 127.0.0.1:6363:6379 + relatorio: + ports: + - 8888 + + rabbitmq: + ports: + - 127.0.0.1:5689:5672 + - 127.0.0.1:15689:15672 + # required to make data persistent + hostname: my-rabbit + volumes: + - ./docker/rabbitmq/data:/var/lib/rabbitmq diff --git a/compose.yaml b/compose.yaml new file mode 100644 index 000000000..920f2e1b9 --- /dev/null +++ b/compose.yaml @@ -0,0 +1,56 @@ +services: + ###> doctrine/doctrine-bundle ### + database: + image: postgis/postgis:${POSTGRES_VERSION:-16}-3.4-alpine + environment: + POSTGRES_DB: ${POSTGRES_DB:-app} + # You should definitely change the password in production + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-!ChangeMe!} + POSTGRES_USER: ${POSTGRES_USER:-app} + volumes: + # - database_data:/var/lib/postgresql/data:rw + # You may use a bind-mounted host directory instead, so that it is harder to accidentally remove the volume and lose all your data! + - ./docker/db/data:/var/lib/postgresql/data:rw + ###< doctrine/doctrine-bundle ### + + redis: + image: redis + relatorio: + image: registry.gitlab.com/champs-libres/public/relatorio-tornado/app:latest + + sign-worker: + image: h3m6q87t.gra7.container-registry.ovh.net/sign-pdf-worker/worker:latest + environment: + AMQP_URL: amqp://guest:guest@rabbitmq:5672/%2f/to_python_sign + LOG_LEVEL: INFO + PKCS12_PATH: /etc/sign-pdf/dummy.p12 + TIMESTAMP_URL: http://freetsa.org/tsr + QUEUE_IN: to_python_sign + EXCHANGE_OUT: signed_docs + OUT_ROUTING_KEY: signed_doc + TSA_CERT_CHAIN: /etc/sign-pdf/tsa/tsa-chain.pem + TSA_CONFIG_PATH: /etc/sign-pdf/rootca.conf + TSA_KEY_PASSWORD: "5678" + volumes: + - "./resources/dev-certificate/dummy.p12:/etc/sign-pdf/dummy.p12:ro" + - "./resources/dev-certificate/rootca.conf:/etc/sign-pdf/rootca.conf:ro" + - "./resources/dev-certificate/tsa:/etc/sign-pdf/tsa:ro" + - "./resources/dev-certificate/tsa_serial:/var/lib/tsa/tsa_serial:rw" + links: + - rabbitmq + depends_on: + rabbitmq: + condition: service_healthy + + rabbitmq: + image: rabbitmq:3-management-alpine + healthcheck: + test: rabbitmq-diagnostics -q ping + interval: 30s + timeout: 30s + retries: 3 + +volumes: + ###> doctrine/doctrine-bundle ### + database_data: +###< doctrine/doctrine-bundle ### diff --git a/composer.json b/composer.json index 9ec23e857..cba8969cd 100644 --- a/composer.json +++ b/composer.json @@ -31,6 +31,7 @@ "phpoffice/phpspreadsheet": "^1.16", "ramsey/uuid-doctrine": "^1.7", "sensio/framework-extra-bundle": "^5.5", + "smalot/pdfparser": "^2.10", "spomky-labs/base64url": "^2.0", "symfony/asset": "^5.4", "symfony/browser-kit": "^5.4", @@ -94,13 +95,16 @@ "phpstan/phpstan-strict-rules": "^1.0", "phpunit/phpunit": "^10.5.24", "rector/rector": "^1.1.0", + "symfony/amqp-messenger": "^5.4.45", "symfony/debug-bundle": "^5.4", "symfony/dotenv": "^5.4", + "symfony/flex": "^2.4", "symfony/maker-bundle": "^1.20", "symfony/phpunit-bridge": "^7.1", "symfony/runtime": "^5.4", "symfony/stopwatch": "^5.4", - "symfony/var-dumper": "^5.4" + "symfony/var-dumper": "^5.4", + "symfony/web-profiler-bundle": "^5.4" }, "conflict": { "symfony/symfony": "*" @@ -128,7 +132,7 @@ }, "autoload-dev": { "psr-4": { - "App\\": "tests/", + "App\\": "src/app", "Chill\\DocGeneratorBundle\\Tests\\": "src/Bundle/ChillDocGeneratorBundle/tests", "Chill\\WopiBundle\\Tests\\": "src/Bundle/ChillDocGeneratorBundle/tests", "Chill\\Utils\\Rector\\Tests\\": "utils/rector/tests" @@ -142,16 +146,22 @@ "phpro/grumphp": true, "phpstan/extension-installer": true, "roave/you-are-using-it-wrong": true, - "symfony/runtime": true + "symfony/runtime": true, + "symfony/flex": true }, - "bin-dir": "bin", "optimize-autoloader": true, "sort-packages": true }, "scripts": { "auto-scripts": { - "cache:clear": "symfony-cmd" + "cache:clear": "symfony-cmd", + "assets:install %PUBLIC_DIR%": "symfony-cmd" }, "php-cs-fixer": "php-cs-fixer fix --config=./.php-cs-fixer.dist.php --show-progress=none" + }, + "extra": { + "symfony": { + "docker": true + } } } diff --git a/tests/app/config/bundles.php b/config/bundles.php similarity index 81% rename from tests/app/config/bundles.php rename to config/bundles.php index 39549e2f0..815c3e62d 100644 --- a/tests/app/config/bundles.php +++ b/config/bundles.php @@ -1,15 +1,26 @@ ['all' => true], + loophp\PsrHttpMessageBridgeBundle\PsrHttpMessageBridgeBundle::class => ['all' => true], + ChampsLibres\WopiBundle\WopiBundle::class => ['all' => true], + Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true], + Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle::class => ['dev' => true, 'test' => true], + Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true], + Knp\Bundle\MenuBundle\KnpMenuBundle::class => ['all' => true], + Knp\Bundle\TimeBundle\KnpTimeBundle::class => ['all' => true], + KnpU\OAuth2ClientBundle\KnpUOAuth2ClientBundle::class => ['all' => true], + Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true], + Lexik\Bundle\JWTAuthenticationBundle\LexikJWTAuthenticationBundle::class => ['all' => true], + Nelmio\Alice\Bridge\Symfony\NelmioAliceBundle::class => ['dev' => true, 'test' => true], + Misd\PhoneNumberBundle\MisdPhoneNumberBundle::class => ['all' => true], + Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle::class => ['all' => true], + Symfony\Bundle\DebugBundle\DebugBundle::class => ['dev' => true], + Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true], + Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true], + Symfony\WebpackEncoreBundle\WebpackEncoreBundle::class => ['all' => true], + Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true], + Twig\Extra\TwigExtraBundle\TwigExtraBundle::class => ['all' => true], Chill\ActivityBundle\ChillActivityBundle::class => ['all' => true], Chill\AsideActivityBundle\ChillAsideActivityBundle::class => ['all' => true], Chill\CalendarBundle\ChillCalendarBundle::class => ['all' => true], @@ -23,24 +34,6 @@ return [ Chill\TaskBundle\ChillTaskBundle::class => ['all' => true], Chill\ThirdPartyBundle\ChillThirdPartyBundle::class => ['all' => true], Chill\BudgetBundle\ChillBudgetBundle::class => ['all' => true], - Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true], - Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle::class => ['dev' => true, 'test' => true], - Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true], - Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle::class => ['all' => true], - Symfony\Bundle\DebugBundle\DebugBundle::class => ['dev' => true, 'test' => true], - Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true], - Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true], - Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true], - Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true], - Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true], - //Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true], - Symfony\WebpackEncoreBundle\WebpackEncoreBundle::class => ['all' => true], - Knp\Bundle\MenuBundle\KnpMenuBundle::class => ['all' => true], - Knp\Bundle\TimeBundle\KnpTimeBundle::class => ['all' => true], - Twig\Extra\TwigExtraBundle\TwigExtraBundle::class => ['all' => true], - loophp\PsrHttpMessageBridgeBundle\PsrHttpMessageBridgeBundle::class => ['all' => true], - \Misd\PhoneNumberBundle\MisdPhoneNumberBundle::class => ['all' => true], - ChampsLibres\WopiBundle\WopiBundle::class => ['all' => true], Chill\WopiBundle\ChillWopiBundle::class => ['all' => true], - \Lexik\Bundle\JWTAuthenticationBundle\LexikJWTAuthenticationBundle::class => ['all' => true], + Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true], ]; diff --git a/tests/app/config/packages/cache.yaml b/config/packages/cache.yaml similarity index 61% rename from tests/app/config/packages/cache.yaml rename to config/packages/cache.yaml index c7a5f169d..6899b7200 100644 --- a/tests/app/config/packages/cache.yaml +++ b/config/packages/cache.yaml @@ -17,17 +17,3 @@ framework: # Namespaced pools use the above "app" backend by default #pools: #my.dedicated.cache: null - - default_redis_provider: '%env(resolve:REDIS_URL)%' - - pools: - cache.user_data: - adapter: cache.adapter.redis - public: true - default_lifetime: 300 # 5 minutes - - # will be used in chill_main.tag_aware_cache service - cache.tags: - adapter: cache.adapter.redis - public: false - default_lifetime: 300 diff --git a/config/packages/cache_chill.yaml b/config/packages/cache_chill.yaml new file mode 100644 index 000000000..71877b6dd --- /dev/null +++ b/config/packages/cache_chill.yaml @@ -0,0 +1,14 @@ +framework: + cache: + default_redis_provider: '%env(resolve:REDIS_URL)%' + pools: + cache.user_data: + adapter: cache.adapter.redis + public: true + default_lifetime: 300 # 5 minutes + + # will be used in chill_main.tag_aware_cache service + cache.tags: + adapter: cache.adapter.redis + public: false + default_lifetime: 300 diff --git a/config/packages/chill.yaml b/config/packages/chill.yaml new file mode 100644 index 000000000..76578a2c7 --- /dev/null +++ b/config/packages/chill.yaml @@ -0,0 +1,121 @@ +chill_main: + available_languages: [ '%env(resolve:LOCALE)%', 'en' ] + available_countries: ['BE', 'FR'] + notifications: + from_email: '%env(resolve:NOTIFICATION_FROM_EMAIL)%' + from_name: '%env(resolve:NOTIFICATION_FROM_NAME)%' + host: '%env(resolve:NOTIFICATION_HOST)%' + redis: + host: '%env(resolve:REDIS_HOST)%' + port: '%env(resolve:REDIS_PORT)%' + phone_helper: + twilio_sid: '%env(resolve:TWILIO_SID)%' + twilio_secret: '%env(resolve:TWILIO_SECRET)%' + default_carrier_code: '%env(resolve:DEFAULT_CARRIER_CODE)%' + short_messages: + dsn: '%env(string:SHORT_MESSAGE_DSN)%' + acl: + form_show_scopes: true + form_show_centers: true + access_global_history: false + access_user_change_password: true + access_permissions_group_list: true + add_address: + default_country: '%env(string:ADD_ADDRESS_DEFAULT_COUNTRY)%' + map_center: + x: '%env(float:ADD_ADDRESS_MAP_CENTER_X)%' + y: '%env(float:ADD_ADDRESS_MAP_CENTER_Y)%' + z: '%env(float:ADD_ADDRESS_MAP_CENTER_Z)%' + +when@test: + chill_main: + available_languages: + - 'fr' + - 'en' + +chill_custom_fields: + show_empty_values_in_views: false + +chill_person: + create_person_allowed: false + create_parcours_allowed: false + allow_multiple_simultaneous_accompanying_periods: true + accompanying_periods_fields: + user: visible + # createdBy, step, origin, intensity, scopes, requestor, anonymous, emergency, confidential : visible(default) | hidden + person_fields: + acceptEmail: hidden + alt_names: + - key: jeune_fille + labels: + lang: fr + label: Nom de naissance + marital_status: visible + civility: visible + deathdate: visible + validation: + center_required: true + +chill_activity: + form: + time_duration: + - + label: '5 minutes' + seconds: 300 + - + label: '10 minutes' + seconds: 600 + - + label: '15 minutes' + seconds: 900 + - + label: '20 minutes' + seconds: 1200 + - + label: '25 minutes' + seconds: 1500 + - + label: '30 minutes' + seconds: 1800 + - + label: '45 minutes' + seconds: 2700 + - + label: '1 hour' + seconds: 3600 + - + label: '1 hour 15' + seconds: 4500 + - + label: '1 hour 30' + seconds: 5400 + - + label: '1 hour 45' + seconds: 6300 + - + label: '2 hours' + seconds: 7200 + - + label: '2 hours 15' + seconds: 8100 + - + label: '2 hours 30' + seconds: 9000 + - + label: '2 hours 45' + seconds: 9900 + - + label: '3 hours' + seconds: 10800 + - + label: '3 hours 30' + seconds: 12600 + - + label: '4 hours' + seconds: 14400 + - + label: '4 hours 30' + seconds: 16200 + - + label: '5 hours' + seconds: 18000 diff --git a/config/packages/chill_budget.yaml b/config/packages/chill_budget.yaml new file mode 100644 index 000000000..853dc197b --- /dev/null +++ b/config/packages/chill_budget.yaml @@ -0,0 +1,85 @@ +chill_budget: + resources: + - { key: fixed_contract, labels: [{ lang: fr, label: "Salarié en CDI" }]} + - { key: temporary_contract, labels: [{ lang: fr, label: "Salarié en CDD"}]} + - { key: interim, labels: [{ lang: fr, label: "Salarié en intérim"}]} + - { key: other_revenues, labels: [{ lang: fr, label: "Revenus non salariés, commerçant, artisan,..."}]} + - { key: agricultural_activity, labels: [{ lang: fr, label: "Exploitant agricole"}]} + - { key: chomage_ass, labels: [{ lang: fr, label: "Allocations chômage ASS"}]} + - { key: chomage_are, labels: [{ lang: fr, label: "Allocations chômage ARE"}]} + - { key: remuneration_stage, labels: [{ lang: fr, label: "Rémunération de stage, d’apprentissage,..."}]} + - { key: daily_allowences, labels: [{ lang: fr, label: "Indemnités journalières"}]} + - { key: others, labels: [{ lang: fr, label: "Autres"}]} + - { key: pension, labels: [{ lang: fr, label: "Pension de retraite"}]} + - { key: invalidity, labels: [{ lang: fr, label: "Pension d'invalidité"}]} + - { key: reversion, labels: [{ lang: fr, label: "Pension de réversion"}]} + - { key: widowhood, labels: [{ lang: fr, label: "Pension de veuvage"}]} + - { key: military, labels: [{ lang: fr, label: "Pension militaire"}]} + - { key: food, labels: [{ lang: fr, label: "Pension alimentaire"}]} + - { key: compensation, labels: [{ lang: fr, label: "Pension de prestation compensatoire"}]} + - { key: allocation_handicap_adult, labels: [{ lang: fr, label: "Allocation aux adultes handicapés"}]} + - { key: rsa, labels: [{ lang: fr, label: "RSA"}]} + - { key: annuity_accident, labels: [{ lang: fr, label: "Rente accident"}]} + - { key: premium_al_pl, labels: [{ lang: fr, label: "Prime d’activité AL/APL au bénéficiaire"}]} + - { key: premium_thirdparty, labels: [{ lang: fr, label: "Prime d’activité versé au tiers"}]} + - { key: other_income, labels: [{ lang: fr, label: "Autres ressources (ARS, ...)"}]} + - { key: allocation_family, labels: [{ lang: fr, label: "Allocations familiales"}]} + - { key: allocation_basic, labels: [{ lang: fr, label: "Allocation de base"}]} + - { key: free_choice_saving, labels: [{ lang: fr, label: "Complément de libre choix du mode de garde"}]} + - { key: shared_benefits_child, labels: [{ lang: fr, label: "Prestation partagée éducation de l’enfant"}]} + - { key: complimentary_family, labels: [{ lang: fr, label: "Complément familial"}]} + - { key: allocation_family_support, labels: [{ lang: fr, label: "Allocation de soutien familial"}]} + - { key: allocation_education_child_handicap, labels: [{ lang: fr, label: "Allocation d’éducation de l’enfant handicapé"}]} + + charges: + - { key: rent, labels: [{ lang: fr, label: "Loyer" }]} + - { key: home_ownership, labels: [{ lang: fr, label: "Accession à la propriété" }]} + - { key: costs_accomodation, labels: [{ lang: fr, label: "Frais d’hébergement" }]} + - { key: home_insurance, labels: [{ lang: fr, label: "Assurance habitation" }]} + - { key: taxes, labels: [{ lang: fr, label: "Impôts (taxe habitation, taxe foncière, ordures ménagères, redevances incitatives)" }]} + - { key: impots, labels: [{lang: fr, label: "Impôts"}]} + - { key: electricity, labels: [{ lang: fr, label: "Electricité" }]} + - { key: gas, labels: [{ lang: fr, label: "Gaz en bouteille" }]} + - { key: heating, labels: [{ lang: fr, label: "Autre moyen de chauffage" }]} + - { key: water, labels: [{ lang: fr, label: "Eau" }]} + - { key: school_fees, labels: [ { lang: fr, label: "Frais de scolarité"}]} + - { key: alimony, labels: [ { lang: fr, label: "Pension alimentaire à reverser"}]} + - { key: child_care, labels: [ { lang: fr, label: "Frais de garde (en totalité)"}]} + - { key: telecom, labels: [ { lang: fr, label: "Frais de communication fixe"}]} + - { key: mobilephone, labels: [ { lang: fr, label: "Frais de communication mobile"}]} + - { key: internet, labels: [ { lang: fr, label: "Frais de communication internet"}]} + - { key: insurance, labels: [{ lang: fr, label: "Assurances"}]} + - { key: debt_commission, labels: [{ lang: fr, label: "Saisine de la commission surendettement"}]} + - { key: recovery_plan, labels: [{ lang: fr, label: "Plan de redressement"}]} + - { key: rpr, labels: [{ lang: fr, label: "PRP"}]} + - { key: moratoire, labels: [{lang: fr, label: "Moratoire"}]} + - { key: mutuelle, labels: [{lang: fr, label: "Mutuelle"}]} + - { key: transport, labels: [{lang: fr, label: "Frais de transport"}]} + - { key: decouvbank, labels: [{lang: fr, label: "Découvert bancaire utilisé"}]} + - { key: procsaisie, labels: [{lang: fr, label: "Procédure de saisie"}]} + - { key: indus, labels: [{lang: fr, label: "Indus"}]} + - { key: apurement, labels: [{lang: fr, label: "Plan d'apurement"}]} + - { key: debt_rent, labels: [{lang: fr, label: "Dette de loyer (hors APL)"}]} + - { key: debt_property, labels: [{lang: fr, label: "Dette d'accession à la propriété"}]} + - { key: debt_lodging, labels: [{lang: fr, label: "Dette de frais d’hébergement"}]} + - { key: debt_electricity, labels: [{lang: fr, label: "Dette d'électricité"}]} + - { key: debt_water, labels: [{lang: fr, label: "Dette d'eau"}]} + - { key: debt_heating, labels: [{lang: fr, label: "Dette d'autre moyen de chauffage"}]} + - { key: debt_gas, labels: [{lang: fr, label: "Dette de gaz en bouteille"}]} + - { key: debt_house_insurance, labels: [{lang: fr, label: "Dette d'assurance habitation"}]} + - { key: debt_housing_taxes, labels: [{lang: fr, label: "Dette d'impôts liées au logement"}]} + - { key: debt_taxes, labels: [{lang: fr, label: "Dette d'impôts autres"}]} + - { key: debt_school, labels: [{lang: fr, label: "Dette de frais de scolarité (cantine, transport, frais de scolarité, frais de garde)"}]} + - { key: debt_alimentation, labels: [{lang: fr, label: "Dette de pension alimentaire à reverser"}]} + - { key: debt_childcare, labels: [{lang: fr, label: "Dette de frais de garde (en totalité)"}]} + - { key: debt_phone, labels: [{lang: fr, label: "Dette de communication fixe"}]} + - { key: debt_mobile, labels: [{lang: fr, label: "Dette de communication portable"}]} + - { key: debt_internet, labels: [{lang: fr, label: "Dette de communication internet"}]} + - { key: debt_car_insurance, labels: [{lang: fr, label: "Dette d'assurance auto"}]} + - { key: debt_mutual, labels: [{lang: fr, label: "Dette de mutuelle"}]} + - { key: debt_transport, labels: [{lang: fr, label: "Dette de frais de transport"}]} + - { key: debt_bank, labels: [{lang: fr, label: "Dette de découvert bancaire utilisé"}]} + - { key: debt_garbage, labels: [{lang: fr, label: "Dette de taxe d’ordures ménagère"}]} + - { key: debt_other, labels: [{lang: fr, label: "Dette autre"}]} + - { key: autre, labels: [{lang: fr, label: "Autre"}]} + diff --git a/config/packages/chill_calendar.yaml b/config/packages/chill_calendar.yaml new file mode 100644 index 000000000..f7eedf748 --- /dev/null +++ b/config/packages/chill_calendar.yaml @@ -0,0 +1,3 @@ +chill_calendar: + remote_calendars_sync: + enabled: false diff --git a/config/packages/chill_doc_generator.yaml b/config/packages/chill_doc_generator.yaml new file mode 100644 index 000000000..1e5bf8686 --- /dev/null +++ b/config/packages/chill_doc_generator.yaml @@ -0,0 +1,5 @@ +chill_doc_generator: + driver: + type: relatorio + relatorio: + url: 'http://%env(RELATORIO_HOST)%:%env(RELATORIO_PORT)%/' \ No newline at end of file diff --git a/tests/app/config/packages/chill_doc_store.yaml b/config/packages/chill_doc_store.yaml similarity index 100% rename from tests/app/config/packages/chill_doc_store.yaml rename to config/packages/chill_doc_store.yaml diff --git a/config/packages/chill_workflow_signature_documents.yaml b/config/packages/chill_workflow_signature_documents.yaml new file mode 100644 index 000000000..5784f55e7 --- /dev/null +++ b/config/packages/chill_workflow_signature_documents.yaml @@ -0,0 +1,11 @@ +chill_main: + workflow_signature: + base_signer: + document_kinds: + - { key: id_card, labels: [ { lang: fr, label: "Carte d'identité" } ] } + - { key: passport, labels: [ { lang: fr, label: "Passeport" } ] } + - { key: drivers_license, labels: [ { lang: fr, label: "Permis de conduire" } ] } + - { key: visa_long_stay, labels: [ { lang: fr, label: "Visa de long séjour" } ] } + - { key: resident_permit, labels: [ { lang: fr, label: "Carte de séjour" } ] } + - { key: residency_card, labels: [ { lang: fr, label: "Carte de résident" } ] } + - { key: provisionary_residency_permit, labels: [ { lang: fr, label: "Autorisation provisoire de séjour" } ] } diff --git a/config/packages/debug.yaml b/config/packages/debug.yaml new file mode 100644 index 000000000..ad874afdd --- /dev/null +++ b/config/packages/debug.yaml @@ -0,0 +1,5 @@ +when@dev: + debug: + # Forwards VarDumper Data clones to a centralized server allowing to inspect dumps on CLI or in your browser. + # See the "server:dump" command to start a new server. + dump_destination: "tcp://%env(VAR_DUMPER_SERVER)%" diff --git a/config/packages/doctrine.yaml b/config/packages/doctrine.yaml new file mode 100644 index 000000000..d421158a0 --- /dev/null +++ b/config/packages/doctrine.yaml @@ -0,0 +1,38 @@ +doctrine: + dbal: + url: '%env(resolve:DATABASE_URL)%' + + # IMPORTANT: You MUST configure your server version, + # either here or in the DATABASE_URL env var (see .env file) + #server_version: '16' + use_savepoints: true + orm: + auto_generate_proxy_classes: true + naming_strategy: doctrine.orm.naming_strategy.default + auto_mapping: true + +when@test: + doctrine: + dbal: + # "TEST_TOKEN" is typically set by ParaTest + dbname_suffix: '_test%env(default::TEST_TOKEN)%' + +when@prod: + doctrine: + orm: + auto_generate_proxy_classes: false + proxy_dir: '%kernel.build_dir%/doctrine/orm/Proxies' + query_cache_driver: + type: pool + pool: doctrine.system_cache_pool + result_cache_driver: + type: pool + pool: doctrine.result_cache_pool + + framework: + cache: + pools: + doctrine.result_cache_pool: + adapter: cache.app + doctrine.system_cache_pool: + adapter: cache.system diff --git a/config/packages/doctrine_migrations.yaml b/config/packages/doctrine_migrations.yaml new file mode 100644 index 000000000..6eac03d9f --- /dev/null +++ b/config/packages/doctrine_migrations.yaml @@ -0,0 +1,2 @@ +doctrine_migrations: + enable_profiler: false diff --git a/tests/app/config/packages/doctrine_migrations.yaml b/config/packages/doctrine_migrations_chill.yaml similarity index 80% rename from tests/app/config/packages/doctrine_migrations.yaml rename to config/packages/doctrine_migrations_chill.yaml index a559780d3..8b8bf539b 100644 --- a/tests/app/config/packages/doctrine_migrations.yaml +++ b/config/packages/doctrine_migrations_chill.yaml @@ -7,24 +7,15 @@ doctrine_migrations: 'Chill\Migrations\CustomFields': '@ChillCustomFieldsBundle/migrations' 'Chill\Migrations\Event': '@ChillEventBundle/migrations' 'Chill\Migrations\Person': '@ChillPersonBundle/migrations' - 'Chill\Migrations\Report': '@ChillReportBundle/migrations' 'Chill\Migrations\Task': '@ChillTaskBundle/migrations' 'Chill\Migrations\ThirdParty': '@ChillThirdPartyBundle/migrations' - 'Chill\Migrations\AsideActivity': '@ChillAsideActivityBundle/migrations' 'Chill\Migrations\DocGenerator': '@ChillDocGeneratorBundle/migrations' + 'Chill\Migrations\AsideActivity': '@ChillAsideActivityBundle/migrations' 'Chill\Migrations\Calendar': '@ChillCalendarBundle/migrations' 'Chill\Migrations\Budget': '@ChillBudgetBundle/migrations' - + 'Chill\Migrations\Report': '@ChillReportBundle/migrations' all_or_nothing: true services: 'Doctrine\Migrations\Version\Comparator': 'Chill\MainBundle\Doctrine\Migrations\VersionComparator' - - storage: - table_storage: - table_name: 'migration_versions' - version_column_name: 'version' - version_column_length: 1024 - executed_at_column_name: 'executed_at' - execution_time_column_name: 'execution_time' diff --git a/tests/app/config/packages/framework.yaml b/config/packages/framework.yaml similarity index 65% rename from tests/app/config/packages/framework.yaml rename to config/packages/framework.yaml index a5ec738f2..33a27cd5c 100644 --- a/tests/app/config/packages/framework.yaml +++ b/config/packages/framework.yaml @@ -1,16 +1,6 @@ # see https://symfony.com/doc/current/reference/configuration/framework.html framework: secret: '%env(APP_SECRET)%' - - http_client: - default_options: - verify_peer: false - verify_host: false - - trusted_hosts: - - '^(localhost|127.0.0.1|web)$' - - '%env(resolve:TRUSTED_HOSTS)%' - #csrf_protection: true http_method_override: false @@ -27,12 +17,6 @@ framework: php_errors: log: true - #error_controller: App\Controller\ErrorController::show - - ## sf4 check: ou à déplacer dans un chill.yaml - assets: - json_manifest_path: '%kernel.project_dir%/public/build/manifest.json' - when@test: framework: test: true diff --git a/tests/app/config/packages/assets.yaml b/config/packages/framework_chill.yaml similarity index 55% rename from tests/app/config/packages/assets.yaml rename to config/packages/framework_chill.yaml index 051d36dce..d67a9d570 100644 --- a/tests/app/config/packages/assets.yaml +++ b/config/packages/framework_chill.yaml @@ -1,3 +1,8 @@ framework: assets: json_manifest_path: '%kernel.project_dir%/public/build/manifest.json' + +when@test: + framework: + assets: + json_manifest_path: null diff --git a/config/packages/knpu_oauth2_client.yaml b/config/packages/knpu_oauth2_client.yaml new file mode 100644 index 000000000..05e853399 --- /dev/null +++ b/config/packages/knpu_oauth2_client.yaml @@ -0,0 +1,3 @@ +knpu_oauth2_client: + clients: + # configure your clients as described here: https://github.com/knpuniversity/oauth2-client-bundle#configuration diff --git a/config/packages/lexik_jwt_authentication.yaml b/config/packages/lexik_jwt_authentication.yaml new file mode 100644 index 000000000..edfb69dc8 --- /dev/null +++ b/config/packages/lexik_jwt_authentication.yaml @@ -0,0 +1,4 @@ +lexik_jwt_authentication: + secret_key: '%env(resolve:JWT_SECRET_KEY)%' + public_key: '%env(resolve:JWT_PUBLIC_KEY)%' + pass_phrase: '%env(JWT_PASSPHRASE)%' diff --git a/config/packages/lexik_jwt_authentication_chill.yaml b/config/packages/lexik_jwt_authentication_chill.yaml new file mode 100644 index 000000000..0f1f9c130 --- /dev/null +++ b/config/packages/lexik_jwt_authentication_chill.yaml @@ -0,0 +1,9 @@ +lexik_jwt_authentication: + # required for wopi - recommended duration + token_ttl: 36000 + + # required for wopi - token in parameter access_token + token_extractors: + query_parameter: + enabled: true + name: access_token \ No newline at end of file diff --git a/tests/app/config/packages/loophp_psr17.yaml b/config/packages/loophp_psr17.yaml similarity index 100% rename from tests/app/config/packages/loophp_psr17.yaml rename to config/packages/loophp_psr17.yaml diff --git a/config/packages/mailer.yaml b/config/packages/mailer.yaml new file mode 100644 index 000000000..56a650d89 --- /dev/null +++ b/config/packages/mailer.yaml @@ -0,0 +1,3 @@ +framework: + mailer: + dsn: '%env(MAILER_DSN)%' diff --git a/config/packages/mailer_chill.yaml b/config/packages/mailer_chill.yaml new file mode 100644 index 000000000..041ea7978 --- /dev/null +++ b/config/packages/mailer_chill.yaml @@ -0,0 +1,4 @@ +framework: + mailer: + envelope: + sender: '%env(NOTIFICATION_FROM_EMAIL)%' diff --git a/config/packages/messenger.yaml b/config/packages/messenger.yaml new file mode 100644 index 000000000..b460fd60c --- /dev/null +++ b/config/packages/messenger.yaml @@ -0,0 +1,75 @@ +framework: + messenger: + # reset services after consuming messages + reset_on_message: true + + # Uncomment this (and the failed transport below) to send failed messages to this transport for later handling. + failure_transport: failed + + transports: + # those transports are added by chill-bundles recipes + sync: sync:// + async: + dsn: '%env(MESSENGER_TRANSPORT_DSN)%/async' + options: + exchange: + name: async + type: fanout + queues: + async: ~ + auto_setup: true + + priority: '%env(MESSENGER_TRANSPORT_DSN)%/priority' + # end of transports added by chill-bundles recipes + # https://symfony.com/doc/current/messenger.html#transport-configuration + failed: 'doctrine://default?queue_name=failed' + to_sign_worker: + dsn: '%env(MESSENGER_TRANSPORT_DSN)%/to_python_sign' + serializer: Chill\DocStoreBundle\Service\Signature\Driver\BaseSigner\RequestPdfSignMessageSerializer + options: + exchange: + name: to_python_sign + type: direct + queues: + to_python_sign: ~ + signed_docs: + dsn: '%env(MESSENGER_TRANSPORT_DSN)%/signed_docs' + serializer: Chill\DocStoreBundle\Service\Signature\Driver\BaseSigner\PdfSignedMessageSerializer + options: + exchange: + name: signed_docs + type: direct + queues: + signed_docs: + binding_keys: [signed_doc] + + auto_setup: false + + routing: + # routes added by chill-bundles recipes + 'Chill\CalendarBundle\Messenger\Message\CalendarRangeMessage': async + 'Chill\CalendarBundle\Messenger\Message\CalendarRangeRemovedMessage': async + 'Chill\CalendarBundle\Messenger\Message\CalendarRemovedMessage': async + 'Chill\CalendarBundle\Messenger\Message\CalendarMessage': async + 'Chill\CalendarBundle\Messenger\Message\InviteUpdateMessage': async + 'Chill\CalendarBundle\Messenger\Message\MSGraphChangeNotificationMessage': async + 'Chill\MainBundle\Service\ShortMessage\ShortMessage': async + 'Chill\DocGeneratorBundle\Service\Messenger\RequestGenerationMessage': priority + 'Chill\PersonBundle\AccompanyingPeriod\Lifecycle\AccompanyingPeriodStepChangeRequestMessage': async + 'Chill\DocStoreBundle\Service\Signature\Driver\BaseSigner\RequestPdfSignMessage': to_sign_worker + 'Chill\DocStoreBundle\Service\StoredObjectCleaner\RemoveOldVersionMessage': async + 'Chill\MainBundle\Workflow\Messenger\PostSignatureStateChangeMessage': priority + 'Chill\MainBundle\Workflow\Messenger\PostPublicViewMessage': async + 'Chill\MainBundle\Service\Workflow\CancelStaleWorkflowMessage': async + # end of routes added by chill-bundles recipes + # Route your messages to the transports + # 'App\Message\YourMessage': async + # 'Symfony\Component\Mailer\Messenger\SendEmailMessage': async + +when@test: + framework: + messenger: + transports: + async: 'in-memory://' + priority: 'in-memory://' + signed_docs: 'in-memory://' diff --git a/config/packages/misd_phone_number.yaml b/config/packages/misd_phone_number.yaml new file mode 100644 index 000000000..20e0144ae --- /dev/null +++ b/config/packages/misd_phone_number.yaml @@ -0,0 +1,13 @@ +# To persist libphonenumber\PhoneNumber objects, add the Misd\PhoneNumberBundle\Doctrine\DBAL\Types\PhoneNumberType mapping to your application's config. +# This requires: doctrine/doctrine-bundle +#doctrine: +# dbal: +# types: +# phone_number: Misd\PhoneNumberBundle\Doctrine\DBAL\Types\PhoneNumberType + +#misd_phone_number: +# twig: false +# form: false +# serializer: false +# validator: +# default_region: GB diff --git a/config/packages/monolog.yaml b/config/packages/monolog.yaml new file mode 100644 index 000000000..9db7d8a7f --- /dev/null +++ b/config/packages/monolog.yaml @@ -0,0 +1,62 @@ +monolog: + channels: + - deprecation # Deprecations are logged in the dedicated "deprecation" channel when it exists + +when@dev: + monolog: + handlers: + main: + type: stream + path: "%kernel.logs_dir%/%kernel.environment%.log" + level: debug + channels: ["!event"] + # 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 diff --git a/config/packages/nelmio_alice.yaml b/config/packages/nelmio_alice.yaml new file mode 100644 index 000000000..e82c32982 --- /dev/null +++ b/config/packages/nelmio_alice.yaml @@ -0,0 +1,12 @@ +when@dev: &dev + nelmio_alice: + functions_blacklist: + - 'current' + - 'shuffle' + - 'date' + - 'time' + - 'file' + - 'md5' + - 'sha1' + +when@test: *dev diff --git a/tests/app/config/packages/nyholm_psr7.yaml b/config/packages/nyholm_psr7.yaml similarity index 56% rename from tests/app/config/packages/nyholm_psr7.yaml rename to config/packages/nyholm_psr7.yaml index f1357233b..ade831249 100644 --- a/tests/app/config/packages/nyholm_psr7.yaml +++ b/config/packages/nyholm_psr7.yaml @@ -7,15 +7,5 @@ services: Psr\Http\Message\UploadedFileFactoryInterface: '@nyholm.psr7.psr17_factory' Psr\Http\Message\UriFactoryInterface: '@nyholm.psr7.psr17_factory' - # Register nyholm/psr7 services for autowiring with HTTPlug factories - Http\Message\MessageFactory: '@nyholm.psr7.httplug_factory' - Http\Message\RequestFactory: '@nyholm.psr7.httplug_factory' - Http\Message\ResponseFactory: '@nyholm.psr7.httplug_factory' - Http\Message\StreamFactory: '@nyholm.psr7.httplug_factory' - Http\Message\UriFactory: '@nyholm.psr7.httplug_factory' - nyholm.psr7.psr17_factory: class: Nyholm\Psr7\Factory\Psr17Factory - - nyholm.psr7.httplug_factory: - class: Nyholm\Psr7\Factory\HttplugFactory diff --git a/tests/app/config/packages/ramsey_uuid_doctrine.yaml b/config/packages/ramsey_uuid_doctrine.yaml similarity index 100% rename from tests/app/config/packages/ramsey_uuid_doctrine.yaml rename to config/packages/ramsey_uuid_doctrine.yaml diff --git a/tests/app/config/packages/routing.yaml b/config/packages/routing.yaml similarity index 75% rename from tests/app/config/packages/routing.yaml rename to config/packages/routing.yaml index b45c1cec7..4b766ce57 100644 --- a/tests/app/config/packages/routing.yaml +++ b/config/packages/routing.yaml @@ -5,3 +5,8 @@ framework: # Configure how to generate URLs in non-HTTP contexts, such as CLI commands. # See https://symfony.com/doc/current/routing.html#generating-urls-in-commands #default_uri: http://localhost + +when@prod: + framework: + router: + strict_requirements: null diff --git a/config/packages/routing_chill.yaml b/config/packages/routing_chill.yaml new file mode 100644 index 000000000..ca2bc8d8d --- /dev/null +++ b/config/packages/routing_chill.yaml @@ -0,0 +1,8 @@ +parameters: + composed_uri: 'https://%env(resolve:NOTIFICATION_HOST)%' + +framework: + router: + # Configure how to generate URLs in non-HTTP contexts, such as CLI commands. + # See https://symfony.com/doc/current/routing.html#generating-urls-in-commands + default_uri: '%composed_uri%' \ No newline at end of file diff --git a/tests/app/config/packages/security.yaml b/config/packages/security.yaml similarity index 65% rename from tests/app/config/packages/security.yaml rename to config/packages/security.yaml index a1a257736..af2385ba9 100644 --- a/tests/app/config/packages/security.yaml +++ b/config/packages/security.yaml @@ -1,68 +1,68 @@ security: - - access_decision_manager: - strategy: unanimous - allow_if_all_abstain: false - enable_authenticator_manager: true # https://symfony.com/doc/current/security.html#registering-the-user-hashing-passwords password_hashers: Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto' # https://symfony.com/doc/current/security.html#loading-the-user-the-user-provider providers: - - chain_provider: - chain : - providers: [in_memory, users] - in_memory: + # providers added by chill-bundles recipes\n + # those providers are required to make chill working + chill_chain_provider: + chain: + providers: [chill_in_memory, chill_users] + chill_in_memory: memory: users: admin: { password: '%env(resolve:ADMIN_PASSWORD)%', roles: ['ROLE_ADMIN', 'ROLE_ALLOWED_TO_SWITCH', 'ROLE_USER'] } - users: + chill_users: id: chill.main.user_provider - - encoders: - Chill\MainBundle\Entity\User: - algorithm: bcrypt - Symfony\Component\Security\Core\User\User: plaintext - + # end of providers added by chill-bundles recipes\n + # all other providers might be removed, unless you have specific needs\n firewalls: - dev: pattern: ^/(_(profiler|wdt)|css|images|js)/ security: false - + # those lines are added by chill-bundles recipe, and are requires to make chill-bundles working + # this firewall is in use for wopi endpoint, which requires wopi: pattern: ^/wopi - provider: chain_provider + provider: chill_chain_provider stateless: true guard: authenticators: - lexik_jwt_authentication.jwt_token_authenticator - - main: - # remove during upgrade from symfony 4 to symfony 5 TODO check this - #anonymous: ~ - provider: chain_provider + dav: + pattern: ^/dav + provider: chill_chain_provider + stateless: true + guard: + authenticators: + - Chill\DocStoreBundle\Security\Guard\JWTOnDavUrlAuthenticator + # this firewall is the main firewall for chill. It should be the last one in the stack, + # unless you have specific needs + chill_main: + provider: chill_chain_provider + entry_point: form_login form_login: csrf_parameter: _csrf_token csrf_token_id: authenticate #csrf_provider: security.csrf.token_manager - # remove during upgrade from symfony 4 to symfony 5 TODO check this - # logout_on_user_change: true logout: path: /logout - # uncomment to enable impersonate mode in Chill # https://symfony.com/doc/current/security/impersonating_user.html switch_user: true - + # end of lines added by chill-bundles recipe # activate different ways to authenticate - # https://symfony.com/doc/current/security.html#firewalls-authentication + # https://symfony.com/doc/current/security.html#the-firewall + + # https://symfony.com/doc/current/security/impersonating_user.html + # switch_user: true # Easy way to control access for large sections of your site # Note: Only the *first* access control that matches will be used access_control: + # those lines are added by chill-bundles recipes, and are requires to make chill-bundles working - { path: ^/(login|logout), roles: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/public, roles: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/wopi, roles: IS_AUTHENTICATED_FULLY } @@ -75,6 +75,7 @@ security: - { path: ^/([a-z]+/)?admin, roles: ROLE_ADMIN } # other pages, only for regular user (no admin) - { path: ^/, roles: ROLE_USER } + # this is the end of line added by chill-project/chill-bundles recipes when@test: security: diff --git a/config/packages/security_chill.yaml b/config/packages/security_chill.yaml new file mode 100644 index 000000000..1de2a5ff6 --- /dev/null +++ b/config/packages/security_chill.yaml @@ -0,0 +1,9 @@ +security: + access_decision_manager: + strategy: unanimous + allow_if_all_abstain: false + +when@test: + security: + role_hierarchy: + CHILL_MASTER_ROLE: [ CHILL_INHERITED_ROLE_1 ] diff --git a/tests/app/config/packages/sensio_framework_extra.yaml b/config/packages/sensio_framework_extra.yaml similarity index 100% rename from tests/app/config/packages/sensio_framework_extra.yaml rename to config/packages/sensio_framework_extra.yaml diff --git a/config/packages/translation.yaml b/config/packages/translation.yaml new file mode 100644 index 000000000..b3f8f9cfe --- /dev/null +++ b/config/packages/translation.yaml @@ -0,0 +1,7 @@ +framework: + default_locale: en + translator: + default_path: '%kernel.project_dir%/translations' + fallbacks: + - en + providers: diff --git a/config/packages/translation_chill.yaml b/config/packages/translation_chill.yaml new file mode 100644 index 000000000..a0371ff10 --- /dev/null +++ b/config/packages/translation_chill.yaml @@ -0,0 +1,4 @@ +framework: + default_locale: '%env(resolve:LOCALE)%' + translator: + fallbacks: [ '%env(resolve:LOCALE)%' ] \ No newline at end of file diff --git a/config/packages/twig.yaml b/config/packages/twig.yaml new file mode 100644 index 000000000..f9f4cc539 --- /dev/null +++ b/config/packages/twig.yaml @@ -0,0 +1,6 @@ +twig: + default_path: '%kernel.project_dir%/templates' + +when@test: + twig: + strict_variables: true diff --git a/tests/app/config/packages/twig.yaml b/config/packages/twig_chill.yaml similarity index 72% rename from tests/app/config/packages/twig.yaml rename to config/packages/twig_chill.yaml index 02d862922..15a3066fd 100644 --- a/tests/app/config/packages/twig.yaml +++ b/config/packages/twig_chill.yaml @@ -1,9 +1,4 @@ twig: - default_path: '%kernel.project_dir%/templates' - debug: '%kernel.debug%' - strict_variables: '%kernel.debug%' - exception_controller: null - ## In Symfony 5, bootstrap_5 theme is supported. But not yet in sf4 !! # see sf5 https://symfony.com/doc/current/form/form_themes.html # see sf4 https://symfony.com/doc/4.4/form/form_themes.html @@ -14,4 +9,8 @@ twig: # and adapt it lightly. # form_themes: ['@ChillMain/Form/bootstrap5/bootstrap_5_horizontal_layout.html.twig'] - #form_themes: ['bootstrap_5_horizontal_layout.html.twig'] + +when@dev: + twig: + globals: + responsive_debug: false diff --git a/tests/app/config/packages/validator.yaml b/config/packages/validator.yaml similarity index 74% rename from tests/app/config/packages/validator.yaml rename to config/packages/validator.yaml index 350786a13..0201281d3 100644 --- a/tests/app/config/packages/validator.yaml +++ b/config/packages/validator.yaml @@ -6,3 +6,8 @@ framework: # For instance, basic validation constraints will be inferred from Doctrine's metadata. #auto_mapping: # App\Entity\: [] + +when@test: + framework: + validation: + not_compromised_password: false diff --git a/config/packages/web_profiler.yaml b/config/packages/web_profiler.yaml new file mode 100644 index 000000000..17893da18 --- /dev/null +++ b/config/packages/web_profiler.yaml @@ -0,0 +1,15 @@ +when@dev: + web_profiler: + toolbar: true + intercept_redirects: false + + framework: + profiler: { only_exceptions: false } + +when@test: + web_profiler: + toolbar: false + intercept_redirects: false + + framework: + profiler: { collect: false } diff --git a/tests/app/config/packages/webpack_encore.yaml b/config/packages/webpack_encore.yaml similarity index 63% rename from tests/app/config/packages/webpack_encore.yaml rename to config/packages/webpack_encore.yaml index 709531205..476246aec 100644 --- a/tests/app/config/packages/webpack_encore.yaml +++ b/config/packages/webpack_encore.yaml @@ -1,16 +1,18 @@ ---- webpack_encore: # The path where Encore is building the assets - i.e. Encore.setOutputPath() output_path: '%kernel.project_dir%/public/build' - # If multiple builds are defined (as shown below), you can disable the default build: # output_path: false # Set attributes that will be rendered on all script and link tags script_attributes: defer: true + # Uncomment (also under link_attributes) if using Turbo Drive + # https://turbo.hotwired.dev/handbook/drive#reloading-when-assets-change + # 'data-turbo-track': reload # link_attributes: - # + # Uncomment if using Turbo Drive + # 'data-turbo-track': reload # If using Encore.enableIntegrityHashes() and need the crossorigin attribute (default: false, or use 'anonymous' or 'use-credentials') # crossorigin: 'anonymous' @@ -23,11 +25,17 @@ webpack_encore: # If you have multiple builds: # builds: - # pass "frontend" as the 3rg arg to the Twig functions - # {{ encore_entry_script_tags('entry1', null, 'frontend') }} - # frontend: '%kernel.project_dir%/public/frontend/build' - # Cache the entrypoints.json (rebuild Symfony's cache when entrypoints.json changes) - # Put in config/packages/prod/webpack_encore.yaml - # cache: true + # pass the build name as the 3rd argument to the Twig functions + # {{ encore_entry_script_tags('entry1', null, 'frontend') }} + +#when@prod: +# webpack_encore: +# # Cache the entrypoints.json (rebuild Symfony's cache when entrypoints.json changes) +# # Available in version 1.2 +# cache: true + +when@test: + webpack_encore: + strict_mode: false diff --git a/config/packages/wopi.yaml b/config/packages/wopi.yaml new file mode 100644 index 000000000..fc93a858e --- /dev/null +++ b/config/packages/wopi.yaml @@ -0,0 +1,2 @@ +wopi: + server: "%env(resolve:EDITOR_SERVER)%" \ No newline at end of file diff --git a/tests/app/config/packages/workflow.yaml b/config/packages/workflow.yaml similarity index 100% rename from tests/app/config/packages/workflow.yaml rename to config/packages/workflow.yaml diff --git a/config/packages/workflow_chill.yaml b/config/packages/workflow_chill.yaml new file mode 100644 index 000000000..434625410 --- /dev/null +++ b/config/packages/workflow_chill.yaml @@ -0,0 +1,346 @@ +framework: + workflows: + vendee_internal: + type: state_machine + metadata: + related_entity: + - Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluationDocument + - Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork + - Chill\DocStoreBundle\Entity\AccompanyingCourseDocument + label: + fr: 'Suivi' + support_strategy: Chill\MainBundle\Workflow\RelatedEntityWorkflowSupportsStrategy + marking_store: + service: Chill\MainBundle\Workflow\EntityWorkflowMarkingStore + initial_marking: 'initial' + places: + initial: + metadata: + label: + fr: Étape initiale + attenteModification: + metadata: + label: + fr: En attente de modification du document + validationFilterInputLabels: + forward: {fr: Modification effectuée} + backward: {fr: Pas de modification effectuée} + neutral: {fr: Autre} + attenteMiseEnForme: + metadata: + label: + fr: En attente de mise en forme + validationFilterInputLabels: + forward: {fr: Mise en forme terminée} + backward: {fr: Pas de mise en forme effectuée} + neutral: {fr: Autre} + attenteVisa: + metadata: + label: + fr: En attente de visa + validationFilterInputLabels: + forward: {fr: Visa accordé} + backward: {fr: Visa refusé} + neutral: {fr: Autre} + attenteSignature: + metadata: + isSignature: ['user', 'person'] + onSignatureCompleted: + transitionName: signatureApplied + label: + fr: En attente de signature + validationFilterInputLabels: + forward: {fr: Signature accordée} + backward: {fr: Signature refusée} + neutral: {fr: Autre} + postSignature: + metadata: + label: + fr: Signatures traitées + validationFilterInputLabels: + forward: {fr: Poursuite du traitement} + backward: {fr: Annulation ou refus de signature} + neutral: {fr: Autre} + attenteTraitement: + metadata: + label: + fr: En attente de traitement + validationFilterInputLabels: + forward: {fr: Traitement terminé favorablement} + backward: {fr: Traitement terminé défavorablement} + neutral: {fr: Autre} + attenteEnvoi: + metadata: + label: + fr: En attente d'envoi + validationFilterInputLabels: + forward: {fr: Document envoyé} + backward: {fr: Document non envoyé} + neutral: {fr: Autre} + attenteValidationMiseEnForme: + metadata: + label: + fr: En attente de validation de la mise en forme + validationFilterInputLabels: + forward: {fr: Validation de la mise en forme} + backward: {fr: Refus de validation de la mise en forme} + neutral: {fr: Autre} + attenteReceptionExternal: + metadata: + isSentExternal: true + onExternalView: clotureApresLectureEnvoiExterne + label: + fr: En attente d'ouverture par un destinataire externe + validationFilterInputLabels: + forward: {fr: Document reçu par un destinataire externe} + backward: {fr: Document non reçu par un destinataire externe} + neutral: {fr: Autre} + annule: + metadata: + isFinal: true + isFinalPositive: false + label: + fr: Annulé + final: + metadata: + isFinal: true + isFinalPositive: true + label: + fr: Finalisé + transitions: + # transition qui avancent + demandeModificationDocument: + from: + - initial + to: attenteModification + metadata: + label: + fr: Demande de modification du document + isForward: true + demandeMiseEnForme: + from: + - initial + - attenteModification + to: attenteMiseEnForme + metadata: + label: + fr: Demande de mise en forme + isForward: true + demandeValidationMiseEnForme: + from: + - attenteMiseEnForme + to: attenteValidationMiseEnForme + metadata: + label: + fr: Demande de validation de la mise en forme + isForward: true + demandeVisa: + from: + - initial + - attenteModification + - attenteMiseEnForme + - attenteValidationMiseEnForme + - postSignature + - attenteTraitement + to: attenteVisa + metadata: + label: + fr: Demande de visa + isForward: true + demandeSignature: + from: + - initial + - attenteModification + - attenteMiseEnForme + - attenteValidationMiseEnForme + - attenteVisa + - attenteTraitement + to: attenteSignature + metadata: + label: {fr: Demande de signature} + isForward: true + signatureApplied: + from: + - attenteSignature + to: postSignature + metadata: + label: {fr: Signatures appliquées} + isForward: true + transitionGuard: 'system' # can be 'system+only-dest' or 'only-dest' (only-dest is default) + demandeTraitement: + from: + - initial + - attenteModification + - attenteMiseEnForme + - attenteValidationMiseEnForme + - attenteVisa + - postSignature + to: attenteTraitement + metadata: + label: {fr: Demande de traitement} + isForward: true + demandeEnvoi: + from: + - initial + - attenteModification + - attenteMiseEnForme + - attenteValidationMiseEnForme + - attenteVisa + - postSignature + - attenteTraitement + to: attenteEnvoi + metadata: + label: {fr: Demande d'envoi} + isForward: true + demandeEnvoiExterne: + from: + - initial + - attenteModification + - attenteMiseEnForme + - attenteValidationMiseEnForme + - attenteVisa + - postSignature + - attenteTraitement + to: attenteReceptionExternal + metadata: + label: {fr: Envoi sécurisé par courrier électronique} + isForward: true + clotureApresLectureEnvoiExterne: + from: + - attenteReceptionExternal + to: + - final + metadata: + transitionGuard: system + isForward: true + label: {fr: Consultation de l'envoi sécurisé} + annulation: + from: + - initial + - attenteModification + - attenteMiseEnForme + - attenteValidationMiseEnForme + - attenteVisa + - postSignature + - attenteTraitement + - attenteEnvoi + to: annule + metadata: + label: {fr: Annulation} + isForward: false + transitionGuard: 'system+only-dest' # can be 'system+only-dest' or 'only-dest' (only-dest is default) + # transitions qui répètent l'étape + demandeMiseEnFormeSupplementaire: + from: + - attenteMiseEnForme + - attenteValidationMiseEnForme + to: attenteMiseEnForme + metadata: + label: {fr: Demande de mise en forme supplémentaire} + demandeVisaSupplementaire: + from: + - attenteVisa + to: attenteVisa + metadata: + label: {fr: Demande de visa supplémentaire} + isForward: true + demandeSignatureSupplementaire: + from: + - postSignature + to: attenteSignature + metadata: + label: {fr: Demande de signature supplémentaire} + isForward: true + demandeTraitementSupplementaire: + from: + - attenteTraitement + to: attenteTraitement + metadata: + label: {fr: Demande de traitement supplémentaire} + # transitions qui renvoient vers une étape précédente + refusEtModificationDocument: + from: + - attenteVisa + - postSignature + - attenteTraitement + - attenteEnvoi + to: attenteModification + metadata: + label: + fr: Refus et demande de modification du document + isForward: false + refusEtDemandeMiseEnForme: + from: + - attenteVisa + - attenteTraitement + - attenteEnvoi + to: attenteMiseEnForme + metadata: + label: {fr: Refus et demande de mise en forme} + isForward: false + refusEtDemandeVisa: + from: + - postSignature + - attenteEnvoi + to: attenteVisa + metadata: + label: {fr: Refus et demande de visa} + isForward: false + refusEtDemandeSignature: + from: + - attenteEnvoi + to: attenteSignature + metadata: + label: {fr: Refus et demande de signature} + isForward: false + refusEtDemandeTraitement: + from: + - attenteEnvoi + to: attenteTraitement + metadata: + label: {fr: Refus et demande de traitement} + isForward: false + # transition vers final + initialToFinal: + from: + - initial + to: final + metadata: + label: {fr: Clotûre immédiate et cloture positive} + isForward: true + attenteMiseEnFormeToFinal: + from: + - attenteMiseEnForme + - attenteValidationMiseEnForme + to: final + metadata: + label: {fr: Mise en forme terminée et cloture positive} + isForward: true + attenteVisaToFinal: + from: + - attenteVisa + to: final + metadata: + label: {fr: Accorde le visa et cloture positive} + isForward: true + postSignatureToFinal: + from: + - postSignature + to: final + metadata: + label: {fr: Cloture positive} + isForward: true + attenteTraitementToFinal: + from: + - attenteTraitement + to: final + metadata: + label: {fr: Traitement terminé et cloture positive} + isForward: true + attenteEnvoiToFinal: + from: + - attenteEnvoi + to: final + metadata: + label: {fr: Envoyé et cloture positive} + isForward: true diff --git a/config/preload.php b/config/preload.php new file mode 100644 index 000000000..5ebcdb215 --- /dev/null +++ b/config/preload.php @@ -0,0 +1,5 @@ +`_ + +We also encourage you to use tools like `phpstan `_ and `rector `_. + +For running php-cs-fixer: + +.. code-block:: bash + + symfony composer php-cs-fixer + +Execute tests +============= + +.. code-block:: bash + + symfony composer exec phpunit -- /path/to_your_test.php + +Note that IDE like PhpStorm should be able to run tests, even KernelTestcase or WebTestCase, `from within their interfaces `_. + +Execute rector +============== + +.. code-block:: bash + + symfony composer exec rector -- process + diff --git a/docs/source/installation/enable-collabora-for-dev.rst b/docs/source/installation/enable-collabora-for-dev.rst new file mode 100644 index 000000000..17a9ae1cc --- /dev/null +++ b/docs/source/installation/enable-collabora-for-dev.rst @@ -0,0 +1,125 @@ + +Enable CODE for development +=========================== + +For editing a document, there must be a way to communicate between the collabora server and the symfony server, in +both direction. The domain name should also be the same for collabora server and for the browser which access to the +online editor. + +Using ngrok (or other http tunnel) +---------------------------------- + +One can configure a tunnel server to expose your local install to the web, and access to your local server using the +tunnel url. + +Start ngrok +^^^^^^^^^^^ + +This can be achieve using `ngrok `_. + +.. note:: + + The configuration of ngrok is outside of the scope of this document. Refers to the ngrok's documentation. + +.. code-block:: bash + + # ensuring that your server is running through http and port 8000 + ngrok http 8000 + # then open the link given by the ngrok utility and you should reach your app + +At this step, ensure that you can reach your local app using the ngrok url. + +Configure Collabora +^^^^^^^^^^^^^^^^^^^ + +The collabora server must be executed online and configure to access to your ngrok installation. Ensure that the aliasgroup +exists for your ngrok application (`See the CODE documentation: `_). + +Configure your app +^^^^^^^^^^^^^^^^^^ + +Set the :code:`EDITOR_SERVER` variable to point to your collabora server, this should be done in your :code:`.env.local` file. + +At this point, everything must be fine. In case of errors, watch the log from your collabora server, use the `profiler `_ +to debug the requests. + +.. note:: + + In case of error while validating proof (you'll see those message in the collabora's logs), you can temporarily disable + the proof validation adding this code snippet in `config/services.yaml`: + + .. code-block:: yaml + + when@dev: + # add only in dev environment, to avoid security problems + services: + ChampsLibres\WopiLib\Contract\Service\ProofValidatorInterface: + # this class will always validate proof + alias: Chill\WopiBundle\Service\Wopi\NullProofValidator + +With a local CODE image +----------------------- + +.. warning:: + + This configuration is not sure, and must be refined. The documentation does not seems to be entirely valid. + +Use a local domain name and https for your app +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Use the proxy feature from embedded symfony server to run your app. `See the dedicated doc ` + +Configure also the `https certificate `_ + +In this example, your local domain name will be :code:`my-domain` and the url will be :code:`https://my-domain.wip`. + +Ensure that the proxy is running. + +Create a certificate database for collabora +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Collabora must validate your certificate generated by symfony console. For that, you need `to create a NSS database ` +and configure collabora to use it. + +At first, export the certificate for symfony development. Use the graphical interface from your browser to get the +certificate as a PEM file. + +.. code-block:: bash + + # create your database in a custom directory + mkdir /path/to/your/directory + certutil -N -d /path/to/your/directory + cat /path/to/your/ca.crt | certutil -d . -A symfony -t -t C,P,C,u,w -a + +Launch CODE properly configured + +.. code-block:: yaml + + collabora: + image: collabora/code:latest + environment: + - SLEEPFORDEBUGGER=0 + - DONT_GEN_SSL_CERT="True" + # add path to the database + - extra_params=--o:ssl.enable=false --o:ssl.termination=false --o:logging.level=7 -o:certificates.database_path=/etc/custom-certificates/nss-database + - username=admin + - password=admin + - dictionaries=en_US + - aliasgroup1=https://my-domain.wip + ports: + - "127.0.0.1:9980:9980" + volumes: + - "/path/to/your/directory/nss-database:/etc/custom-certificates/nss-database" + extra_hosts: + - "my-domain.wip:host-gateway" + +Configure your app +^^^^^^^^^^^^^^^^^^ + +Into your :code:`.env.local` file: + +.. code-block:: env + + EDITOR_SERVER=http://${COLLABORA_HOST}:${COLLABORA_PORT} + +At this step, you should be able to edit a document through collabora. diff --git a/docs/source/installation/index.rst b/docs/source/installation/index.rst index a9a4ea0c6..fb4cb3cac 100644 --- a/docs/source/installation/index.rst +++ b/docs/source/installation/index.rst @@ -17,6 +17,27 @@ Installation & Usage You will learn here how to install a new symfony project with chill, and configure it. +Which can of installation do I need ? +===================================== + +I want to run chill in production +--------------------------------- + +See the :ref:`instructions about installing Chill for production `. + +I want to add features to the main chill bundles +------------------------------------------------ + +If you want to add features to chill bundles itself, **and** you want those features to be merged into the chill bundles, +you can use the "development" installation mode. + +See the :ref:`instruction for installation for development `. + +I want to add features to Chill, but keep those features for my instance +------------------------------------------------------------------------- + +Follow the same instruction than for production, until the end. + Requirements ============ @@ -36,341 +57,11 @@ Chill needs a redis server and a postgresql database, and a few other things lik generate documents from templates. **All these things are available through docker using the plugin compose**. We do not provide information on how to run this without docker compose. - -Install a new project -===================== - -Initialize project and dependencies -*********************************** - -.. code-block:: bash - - symfony new --version=5.4 my_chill_project - cd my_chill_project - -We strongly encourage you to initialize a git repository at this step, to track further changes. - -.. code-block:: bash - - # add the flex endpoints required for custom recipes - cat <<< "$(jq '.extra.symfony += {"endpoint": ["flex://defaults", "https://gitlab.com/api/v4/projects/57371968/repository/files/index.json/raw?ref=main"]}' composer.json)" > composer.json - # install chill and some dependencies - # TODO fix the suffix "alpha1" and replace by ^3.0.0 when version 3.0.0 will be released - symfony composer require chill-project/chill-bundles v3.0.0-RC3 champs-libres/wopi-lib dev-master@dev champs-libres/wopi-bundle dev-master@dev - -We encourage you to accept the inclusion of the "Docker configuration from recipes": this is the documented way to run the database. -You must also accept to configure recipes from the contrib repository, unless you want to configure the bundles manually). - -.. code-block:: bash - - # fix some configuration - ./post-install-chill.sh - # install node dependencies - yarn install - # and compile assets - yarn run encore production - -.. note:: - - If you encounter this error during assets compilation (:code:`yarn run encore production`) (repeated multiple times): - - .. code-block:: txt - - [tsl] ERROR in /tmp/chill/v1/public/bundles/chillcalendar/types.ts(2,65) - TS2307: Cannot find module '../../../ChillMainBundle/Resources/public/types' or its corresponding type declarations. - - run: - - .. code-block:: bash - - rm -rf public/bundles/* - - Then restart the compilation of assets (:code:```yarn run encore production```) - -Configure your project -********************** - -You should read the configuration files in :code:`chill/config/packages` carefully, especially if you have -custom developments. But most of the time, this should be fine. - -You have to configure some local variables, which are described in the :code:`.env` file. The secrets should not be stored -in this :code:`.env` file, but instead using the `secrets management tool `_ -or in the :code:`.env.local` file, which should not be committed to the git repository. - -You do not need to set variables for the smtp server, redis server and relatorio server, as they are generated automatically -by the symfony server, from the docker compose services. - -The only required variable is the :code:`ADMIN_PASSWORD`. You can generate a hashed and salted admin password using the command -:code:`symfony console security:hash-password 'Symfony\Component\Security\Core\User\User'`. Then, -you can either: - -- add this password to the :code:`.env.local` file, you must escape the character :code:`$`: if the generated password - is :code:`$2y$13$iyvJLuT4YEa6iWXyQV4/N.hNHpNG8kXlYDkkt5MkYy4FXcSwYAwmm`, your :code:`.env.local` file will be: - - .. code-block:: env - - ADMIN_PASSWORD=\$2y\$13\$iyvJLuT4YEa6iWXyQV4/N.hNHpNG8kXlYDkkt5MkYy4FXcSwYAwmm - # note: if you copy-paste the line above, the password will be "admin". - -- add the generated password to the secrets manager (**note**: you must add the generated hashed password to the secrets env, - not the password in clear text). - -- set up the jwt authentication bundle - -Some environment variables are available for the JWT authentication bundle in the :code:`.env` file. - -Prepare migrations and other tools -********************************** - -To continue the installation process, you will have to run migrations: - -.. code-block:: bash - - # start databases and other services - docker compose up -d - # the first start, it may last some seconds, you can check with docker compose ps - # run migrations - symfony console doctrine:migrations:migrate - # setup messenger - symfony console messenger:setup-transports - # prepare some views - symfony console chill:db:sync-views - # generate jwt token, required for some api features (webdav access, ...) - symfony console lexik:jwt:generate-keypair - -.. warning:: - - If you encounter an error while running :code:`symfony console messenger:setup-transports`, you can set up the messenger - transport to redis, by adding this in the :code:`.env.local` or :code:`.env` file: - - .. code-block:: env - - MESSENGER_TRANSPORT_DSN=redis://${REDIS_HOST}:${REDIS_PORT}/messages - -Start your web server locally -***************************** - -At this step, Chill will be ready to be served locally, but without any configuration. You can run the project -locally using the `local symfony server `_: - -.. code-block:: bash - - # see the whole possibilities at https://symfony.com/doc/current/setup/symfony_server.html - symfony server:start -d - - -If you need to test the instance with accounts and some basic configuration, please install the fixtures (see below). - - -Add capabilities for dev -======================== - -If you need to add custom bundles, you can develop them in the `src/` directory, like for any other symfony project. You -can rely on the whole chill framework, meaning there is no need to add them to the original `chill-bundles`. - -You will require some bundles to have the following development tools: - -- add fixtures -- add profiler and debug bundle - -Install fixtures -**************** - -.. code-block:: bash - - # generate fixtures for chill - symfony composer require --dev doctrine/doctrine-fixtures-bundle nelmio/alice - # now, you can generate fixtures (this will reset your database) - symfony console doctrine:fixtures:load - -This will generate user accounts, centers, and some basic configuration. - -The accounts created are: :code:`center a_social`, :code:`center b_social`, :code:`center a_direction`, ... The full list is -visible in the "users" table: :code:`docker compose exec database psql -U app -c "SELECT username FROM users"`. - -The password is always :code:`password`. - -.. warning:: - - The fixtures are not fully functional. See the `corresponding issue `_. - -Add web profiler and debugger -***************************** - -.. code-block:: bash - - symfony composer require --dev symfony/web-profiler-bundle symfony/debug-bundle - -Working on chill bundles -************************ - -If you plan to improve the chill-bundles repository, that's great! - -You will have to download chill-bundles as a git repository (and not as an archive, which is barely editable). - -In your :code:`composer.json` file, add these lines: - -.. code-block:: diff - - { - "config": { - + "preferred-install": { - + "chill-project/chill-bundles": "source", - "*": "dist" - + } - } - -Then, run :code:`symfony composer reinstall chill-project/chill-bundles` to re-install the package from source. - -Code style, code quality and other tools -**************************************** - -For development, you will also have to install: - -- `php-cs-fixer `_ - -We also encourage you to use tools like `phpstan `_ and `rector `_. - -Commit and share your project -============================= - -If multiple developers work on a project, you can commit your symfony project and share it with other people. - -When another developer clones your project, they will have to: - -- run :code:`symfony composer install` and :code:`yarn install` to install the same dependencies as the initial developer; -- run :code:`yarn run encore production` to compile assets; -- copy any possible variables from the :code:`.env.local` files; -- start the docker compose stack, using :code:`docker compose`, and run migrations, set up transports, and prepare chill db views - (see the corresponding command above) - -Update -====== - -In order to update your app, you must update dependencies: - -- for chill-bundles, you can `set the last version `_ manually - in the :code:`composer.json` file, or set the version to `^3.0.0` and run :code:`symfony composer update` regularly -- run :code:`composer update` and :code:`yarn update` to maintain your dependencies up-to-date. - -After each update, you must update your database schema: - -.. code-block:: bash - - symfony console doctrine:migrations:migrate - symfony console chill:db:sync-views - -Operations -========== - -Build assets -************ - -run those commands: - -.. code-block:: bash - - # for production (or in dev, when you don't need to work on your assets and need some speed) - yarn run encore production - # in dev, when you wan't to reload the assets on each changes - yarn run encore dev --watch - -How to execute the console ? -**************************** - -.. code-block:: bash - - # start the console with all required variables - symfony console - # you can add your command after that: - symfony console list - -How to generate documents -************************* - -Documents are generated asynchronously by `"consuming messages" `_. - -You must generate them using a dedicated process: - -.. code-block:: bash - - symfony console messenger:consume async priority - -To avoid memory issues, we encourage you to also use the :code:`--limit` parameter of the command. - -How to read emails sent by the program ? -******************************************* - -In development, there is a built-in "mail catcher". Open it with :code:`symfony open:local:webmail` - -How to run cron-jobs ? -********************** - -Some commands must be executed in :ref:`cron jobs `. To execute them: - -.. code-block:: bash - - symfony console chill:cron-job:execute - -What about materialized views ? -******************************* - -There are some materialized views in chill, to speed up some complex computations in the database. - -In order to refresh them, run a cron job or refresh them manually in your database. - -How to run tests for chill-bundles -********************************** - -Tests reside inside the installed bundles. You must `cd` into that directory, download the required packages, and execute them from this place. - -**Note**: some bundles require the fixtures to be executed. See the dedicated _how-tos_. - -Example, for running a unit test inside `main` bundle: - -.. code-block:: bash - - # cd into main directory - cd vendor/chill-project/chill-bundles - composer install - # run tests - bin/phpunit src/Bundle/path/to/your/test - -Or for running tests to check code style and php conventions with csfixer and phpstan: - -Troubleshooting -=============== - -Error `An exception has been thrown during the rendering of a template ("Asset manifest file "/var/www/app/web/build/manifest.json" does not exist.").` on first run -******************************************************************************************************************************************************************** - -Build assets, see above. - -Running in production -===================== - -Currently, to run this software in production, the *state of the art* is the following : - -1. Run the software locally and tweak the configuration to your needs ; -2. Build the image and store it in a private container registry. - -.. warning:: - - In production, you **must** set these variables: - - * ``APP_ENV`` to ``prod`` - * ``APP_DEBUG`` to ``false`` - - There are security issues if you keep the same variables as for production. - - -Going further -============= +Instructions +============ .. toctree:: :maxdepth: 2 - prod.rst - load-addresses.rst - prod-calendar-sms-sending.rst - msgraph-configure.rst + installation-development.rst + installation-production.rst diff --git a/docs/source/installation/installation-development.rst b/docs/source/installation/installation-development.rst new file mode 100644 index 000000000..5977747c6 --- /dev/null +++ b/docs/source/installation/installation-development.rst @@ -0,0 +1,101 @@ +.. _installation-for-dev: + +Installation for development or testing purpose only +==================================================== + +⚠️ Use this method for development only. ⚠️ + +You will need: + +- `Composer `__; +- `Symfony-cli tool `__; +- `docker `__ and + `docker-compose `__ +- node > 20 and yarn 1.22 + +First initialization +-------------------- + +1. clone the repository and move to the cloned directory: + +.. code:: bash + + git clone https://gitlab.com/Chill-Projet/chill-bundles.git + cd chill-bundles + +2. install dependencies using composer + +.. code:: bash + + composer install + +3. Install and compile assets: + +.. code:: bash + + yarn install + yarn run encore production + +**note** double check that you have the node version > 20 using the +``node --version`` command. + +4. configure your project: create a ``.env.local`` file at the root, and + add the admin password: + +.. code:: dotenv + + # for this installation mode, the environment should always be "dev" + APP_ENV=dev + ADMIN_PASSWORD=\$2y\$13\$iyvJLuT4YEa6iWXyQV4/N.hNHpNG8kXlYDkkt5MkYy4FXcSwYAwmm + # note: if you copy-paste the line above, the password will be "admin". + +5. start the stack using ``docker compose up -d``, check the status of + the start with ``docker compose ps`` + +6. configure all the needed third-party tools + + .. code:: bash + + # the first start, it may last some seconds, you can check with docker compose ps + # run migrations + symfony console doctrine:migrations:migrate + # setup messenger + symfony console messenger:setup-transports + # prepare some views + symfony console chill:db:sync-views + # generate jwt token, required for some api features (webdav access, ...) + symfony console lexik:jwt:generate-keypair + +7. add some fixtures + +This will truncate all the existing data of the database. But remember, +we are in dev mode ! + +.. code:: bash + + symfony console doctrine:fixtures:load + +8. launch symfony dev-server + +.. code:: bash + + symfony server:start -d + +And visit the web page it suggest. You can login with user +``center a_social`` and password ``password``, or login ``admin`` with +the password you set. + +Stopping the server +------------------- + +.. code:: bash + + symfony server:stop + +Restart the webserver for subsequent start +------------------------------------------ + +.. code:: bash + + symfony server:start -d + # this will automatically starts the full docker compose services diff --git a/docs/source/installation/installation-production.rst b/docs/source/installation/installation-production.rst new file mode 100644 index 000000000..c02390b5a --- /dev/null +++ b/docs/source/installation/installation-production.rst @@ -0,0 +1,328 @@ +.. _installation-production: + +Install Chill for production with or without adding personal features +##################################################################### + +Chill is a set of "bundles" for a symfony app. + +To run Chill in production or add new features to it (without merging those features to the chill core), you must create +a symfony app, and eventually add those features into your app. + +Once you are happy with the configuration, `you should follow the dedicated instructions of how to go into production for +Symfony apps `_. + +Install a new app +================= + +Initialize project and dependencies +----------------------------------- + +.. code-block:: bash + + symfony new --version=5.4 my_chill_project + cd my_chill_project + +We strongly encourage you to initialize a git repository at this step, to track further changes. + +.. code-block:: bash + + # add the flex endpoints required for custom recipes + cat <<< "$(jq '.extra.symfony += {"endpoint": ["flex://defaults", "https://gitlab.com/api/v4/projects/57371968/repository/files/index.json/raw?ref=main"]}' composer.json)" > composer.json + # install chill and some dependencies + # TODO fix the suffix "alpha1" and replace by ^3.0.0 when version 3.0.0 will be released + symfony composer require chill-project/chill-bundles v3.0.0-RC3 champs-libres/wopi-lib dev-master@dev champs-libres/wopi-bundle dev-master@dev + +We encourage you to accept the inclusion of the "Docker configuration from recipes": this is the documented way to run the database. +You must also accept to configure recipes from the contrib repository, unless you want to configure the bundles manually). + +.. code-block:: bash + + # fix some configuration + ./post-install-chill.sh + # install node dependencies + yarn install + # and compile assets + yarn run encore production + +.. note:: + + If you encounter this error during assets compilation (:code:`yarn run encore production`) (repeated multiple times): + + .. code-block:: txt + + [tsl] ERROR in /tmp/chill/v1/public/bundles/chillcalendar/types.ts(2,65) + TS2307: Cannot find module '../../../ChillMainBundle/Resources/public/types' or its corresponding type declarations. + + run: + + .. code-block:: bash + + rm -rf public/bundles/* + + Then restart the compilation of assets (:code:```yarn run encore production```) + +Configure your project +---------------------- + +You should read the configuration files in :code:`chill/config/packages` carefully, especially if you have +custom developments. But most of the time, this should be fine. + +You have to configure some local variables, which are described in the :code:`.env` file. The secrets should not be stored +in this :code:`.env` file, but instead using the `secrets management tool `_ +or in the :code:`.env.local` file, which should not be committed to the git repository. + +You do not need to set variables for the smtp server, redis server and relatorio server, as they are generated automatically +by the symfony server, from the docker compose services. + +The only required variable is the :code:`ADMIN_PASSWORD`. You can generate a hashed and salted admin password using the command +:code:`symfony console security:hash-password 'Symfony\Component\Security\Core\User\User'`. Then, +you can either: + +- add this password to the :code:`.env.local` file, you must escape the character :code:`$`: if the generated password + is :code:`$2y$13$iyvJLuT4YEa6iWXyQV4/N.hNHpNG8kXlYDkkt5MkYy4FXcSwYAwmm`, your :code:`.env.local` file will be: + + .. code-block:: env + + ADMIN_PASSWORD=\$2y\$13\$iyvJLuT4YEa6iWXyQV4/N.hNHpNG8kXlYDkkt5MkYy4FXcSwYAwmm + # note: if you copy-paste the line above, the password will be "admin". + +- add the generated password to the secrets manager (**note**: you must add the generated hashed password to the secrets env, + not the password in clear text). + +- set up the jwt authentication bundle + +Some environment variables are available for the JWT authentication bundle in the :code:`.env` file. + +Prepare migrations and other tools +---------------------------------- + +To continue the installation process, you will have to run migrations: + +.. code-block:: bash + + # start databases and other services + docker compose up -d + # the first start, it may last some seconds, you can check with docker compose ps + # run migrations + symfony console doctrine:migrations:migrate + # setup messenger + symfony console messenger:setup-transports + # prepare some views + symfony console chill:db:sync-views + # generate jwt token, required for some api features (webdav access, ...) + symfony console lexik:jwt:generate-keypair + +.. warning:: + + If you encounter an error while running :code:`symfony console messenger:setup-transports`, you can set up the messenger + transport to redis, by adding this in the :code:`.env.local` or :code:`.env` file: + + .. code-block:: env + + MESSENGER_TRANSPORT_DSN=redis://${REDIS_HOST}:${REDIS_PORT}/messages + +Start your web server locally +----------------------------- + +At this step, Chill will be ready to be served locally, but without any configuration. You can run the project +locally using the `local symfony server `_: + +.. code-block:: bash + + # see the whole possibilities at https://symfony.com/doc/current/setup/symfony_server.html + symfony server:start -d + + +If you need to test the instance with accounts and some basic configuration, please install the fixtures (see below). + + +Add capabilities for dev +======================== + +If you need to add custom bundles, you can develop them in the `src/` directory, like for any other symfony project. You +can rely on the whole chill framework, meaning there is no need to add them to the original `chill-bundles`. + +You will require some bundles to have the following development tools: + +- add fixtures +- add profiler and debug bundle + +Install fixtures +---------------- + +.. code-block:: bash + + # generate fixtures for chill + symfony composer require --dev doctrine/doctrine-fixtures-bundle nelmio/alice + # now, you can generate fixtures (this will reset your database) + symfony console doctrine:fixtures:load + +This will generate user accounts, centers, and some basic configuration. + +The accounts created are: :code:`center a_social`, :code:`center b_social`, :code:`center a_direction`, ... The full list is +visible in the "users" table: :code:`docker compose exec database psql -U app -c "SELECT username FROM users"`. + +The password is always :code:`password`. + +.. warning:: + + The fixtures are not fully functional. See the `corresponding issue `_. + +Add web profiler and debugger +----------------------------- + +.. code-block:: bash + + symfony composer require --dev symfony/web-profiler-bundle symfony/debug-bundle + +Working on chill bundles +------------------------ + +If you plan to improve the chill-bundles repository, that's great! + +It would be better :ref:`to follow the instruction about development `. But if those features are +deeply linked to some dev you made in the app, it can be easier to develop within the :code:`vendor/` directory. + +You will have to download chill-bundles as a git repository (and not as an archive, which is barely editable). + +In your :code:`composer.json` file, add these lines: + +.. code-block:: diff + + { + "config": { + + "preferred-install": { + + "chill-project/chill-bundles": "source", + "*": "dist" + + } + } + +Then, run :code:`symfony composer reinstall chill-project/chill-bundles` to re-install the package from source. + + +Update +====== + +In order to update your app, you must update dependencies: + +- for chill-bundles, you can `set the last version `_ manually + in the :code:`composer.json` file, or set the version to `^3.0.0` and run :code:`symfony composer update` regularly +- run :code:`composer update` and :code:`yarn update` to maintain your dependencies up-to-date. + +After each update, you must update your database schema: + +.. code-block:: bash + + symfony console doctrine:migrations:migrate + symfony console chill:db:sync-views + + +Commit and share your project +============================= + +If multiple developers work on a project, you can commit your symfony project and share it with other people. + +When another developer clones your project, they will have to: + +- run :code:`symfony composer install` and :code:`yarn install` to install the same dependencies as the initial developer; +- run :code:`yarn run encore production` to compile assets; +- copy any possible variables from the :code:`.env.local` files; +- start the docker compose stack, using :code:`docker compose`, and run migrations, set up transports, and prepare chill db views + (see the corresponding command above) + +Operations +========== + +Build assets +------------ + +run those commands: + +.. code-block:: bash + + # for production (or in dev, when you don't need to work on your assets and need some speed) + yarn run encore production + # in dev, when you wan't to reload the assets on each changes + yarn run encore dev --watch + +How to execute the console ? +---------------------------- + +.. code-block:: bash + + # start the console with all required variables + symfony console + # you can add your command after that: + symfony console list + +How to generate documents +------------------------- + +Documents are generated asynchronously by `"consuming messages" `_. + +You must generate them using a dedicated process: + +.. code-block:: bash + + symfony console messenger:consume async priority + +To avoid memory issues, we encourage you to also use the :code:`--limit` parameter of the command. + +How to read emails sent by the program ? +------------------------------------------- + +In development, there is a built-in "mail catcher". Open it with :code:`symfony open:local:webmail` + +How to run cron-jobs ? +---------------------- + +Some commands must be executed in :ref:`cron jobs `. To execute them: + +.. code-block:: bash + + symfony console chill:cron-job:execute + +What about materialized views ? +------------------------------- + +There are some materialized views in chill, to speed up some complex computations in the database. + +In order to refresh them, run a cron job or refresh them manually in your database. + + +Troubleshooting +=============== + +Error `An exception has been thrown during the rendering of a template ("Asset manifest file "/var/www/app/web/build/manifest.json" does not exist.").` on first run +-------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +Build assets, see above. + +Go to production +================ + +Currently, to run this software in production, the *state of the art* is the following : + +1. Run the software locally and tweak the configuration to your needs ; +2. Build the image and store it in a private container registry. + +.. warning:: + + In production, you **must** set these variables: + + * ``APP_ENV`` to ``prod`` + * ``APP_DEBUG`` to ``false`` + + There are security issues if you keep the same variables as for production. + + +Going further +============= + +.. toctree:: + :maxdepth: 2 + + prod.rst + load-addresses.rst + prod-calendar-sms-sending.rst + msgraph-configure.rst diff --git a/package.json b/package.json index d86004981..f0dbfa3b3 100644 --- a/package.json +++ b/package.json @@ -64,9 +64,9 @@ "marked": "^12.0.2", "masonry-layout": "^4.2.2", "mime": "^4.0.0", - "swagger-ui": "^4.15.5", + "pdfjs-dist": "^4.3.136", "vis-network": "^9.1.0", - "vue": "^3.2.37", + "vue": "^3.5.6", "vue-i18n": "^9.1.6", "vue-multiselect": "3.0.0-alpha.2", "vue-toast-notification": "^3.1.2", diff --git a/phpstan.neon.dist b/phpstan.dist.neon similarity index 100% rename from phpstan.neon.dist rename to phpstan.dist.neon diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 336877a0c..cdc7468ec 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,12 +1,21 @@ - + + - + + + -

- Déposez un document ou cliquez ici pour remplacer le document - existant -

-

- Déposez un document ou cliquez ici pour ouvrir le navigateur de - fichier -

+

Déposez un document ou cliquez ici pour remplacer le document existant

+

Déposez un document ou cliquez ici pour ouvrir le navigateur de fichier

@@ -198,8 +140,7 @@ const handleFile = async (file: File): Promise => { font-weight: 200; } - & > .area, - & > .waiting { + & > .area, & > .waiting { width: 100%; height: 10rem; @@ -207,6 +148,11 @@ const handleFile = async (file: File): Promise => { flex-direction: column; justify-content: center; align-items: center; + + p { + // require for display in DropFileModal + text-align: center; + } } & > .area { @@ -217,4 +163,5 @@ const handleFile = async (file: File): Promise => { } } } + diff --git a/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/DropFileWidget/DropFileModal.vue b/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/DropFileWidget/DropFileModal.vue new file mode 100644 index 000000000..db868131a --- /dev/null +++ b/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/DropFileWidget/DropFileModal.vue @@ -0,0 +1,69 @@ + + + + + diff --git a/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/DropFileWidget/DropFileWidget.vue b/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/DropFileWidget/DropFileWidget.vue index 6d9d6e210..dd37a56fd 100644 --- a/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/DropFileWidget/DropFileWidget.vue +++ b/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/DropFileWidget/DropFileWidget.vue @@ -1,12 +1,13 @@ - + diff --git a/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/FileIcon.vue b/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/FileIcon.vue new file mode 100644 index 000000000..437d6bdc8 --- /dev/null +++ b/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/FileIcon.vue @@ -0,0 +1,25 @@ + + + + + diff --git a/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/StoredObjectButton/ConvertButton.vue b/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/StoredObjectButton/ConvertButton.vue index 8b83d3269..397837688 100644 --- a/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/StoredObjectButton/ConvertButton.vue +++ b/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/StoredObjectButton/ConvertButton.vue @@ -1,64 +1,60 @@ - diff --git a/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/StoredObjectButton/DownloadButton.vue b/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/StoredObjectButton/DownloadButton.vue index ae0135320..f3fd3b4b5 100644 --- a/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/StoredObjectButton/DownloadButton.vue +++ b/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/StoredObjectButton/DownloadButton.vue @@ -1,124 +1,117 @@ - diff --git a/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/StoredObjectButton/HistoryButton.vue b/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/StoredObjectButton/HistoryButton.vue new file mode 100644 index 000000000..547416879 --- /dev/null +++ b/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/StoredObjectButton/HistoryButton.vue @@ -0,0 +1,57 @@ + + + + + diff --git a/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/StoredObjectButton/HistoryButton/HistoryButtonList.vue b/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/StoredObjectButton/HistoryButton/HistoryButtonList.vue new file mode 100644 index 000000000..893d85a77 --- /dev/null +++ b/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/StoredObjectButton/HistoryButton/HistoryButtonList.vue @@ -0,0 +1,67 @@ + + + + + diff --git a/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/StoredObjectButton/HistoryButton/HistoryButtonListItem.vue b/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/StoredObjectButton/HistoryButton/HistoryButtonListItem.vue new file mode 100644 index 000000000..13ad2b547 --- /dev/null +++ b/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/StoredObjectButton/HistoryButton/HistoryButtonListItem.vue @@ -0,0 +1,115 @@ + + + + + diff --git a/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/StoredObjectButton/HistoryButton/HistoryButtonModal.vue b/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/StoredObjectButton/HistoryButton/HistoryButtonModal.vue new file mode 100644 index 000000000..3ba108cec --- /dev/null +++ b/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/StoredObjectButton/HistoryButton/HistoryButtonModal.vue @@ -0,0 +1,47 @@ + + + + diff --git a/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/StoredObjectButton/HistoryButton/RestoreVersionButton.vue b/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/StoredObjectButton/HistoryButton/RestoreVersionButton.vue new file mode 100644 index 000000000..0c2ba2996 --- /dev/null +++ b/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/StoredObjectButton/HistoryButton/RestoreVersionButton.vue @@ -0,0 +1,32 @@ + + + + + diff --git a/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/StoredObjectButton/HistoryButton/api.ts b/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/StoredObjectButton/HistoryButton/api.ts new file mode 100644 index 000000000..b2865bc48 --- /dev/null +++ b/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/StoredObjectButton/HistoryButton/api.ts @@ -0,0 +1,12 @@ +import {StoredObject, StoredObjectVersionPersisted, StoredObjectVersionWithPointInTime} from "../../../types"; +import {fetchResults, makeFetch} from "../../../../../../ChillMainBundle/Resources/public/lib/api/apiMethods"; + +export const get_versions = async (storedObject: StoredObject): Promise => { + const versions = await fetchResults(`/api/1.0/doc-store/stored-object/${storedObject.uuid}/versions`); + + return versions.sort((a: StoredObjectVersionWithPointInTime, b: StoredObjectVersionWithPointInTime) => b.version - a.version); +} + +export const restore_version = async (version: StoredObjectVersionPersisted): Promise => { + return await makeFetch("POST", `/api/1.0/doc-store/stored-object/restore-from-version/${version.id}`); +} diff --git a/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/StoredObjectButton/WopiEditButton.vue b/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/StoredObjectButton/WopiEditButton.vue index fa1fc698f..135392c1e 100644 --- a/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/StoredObjectButton/WopiEditButton.vue +++ b/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/StoredObjectButton/WopiEditButton.vue @@ -1,30 +1,20 @@ - + diff --git a/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/StoredObjectButton/helpers.ts b/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/StoredObjectButton/helpers.ts index 707170c93..2fb55f71c 100644 --- a/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/StoredObjectButton/helpers.ts +++ b/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/StoredObjectButton/helpers.ts @@ -1,228 +1,247 @@ -import { - StoredObject, - StoredObjectStatus, - StoredObjectStatusChange, -} from "../../types"; +import {StoredObject, StoredObjectStatus, StoredObjectStatusChange, StoredObjectVersion} from "../../types"; +import {makeFetch} from "../../../../../ChillMainBundle/Resources/public/lib/api/apiMethods"; const MIMES_EDIT = new Set([ - "application/vnd.ms-powerpoint", - "application/vnd.ms-excel", - "application/vnd.oasis.opendocument.text", - "application/vnd.oasis.opendocument.text-flat-xml", - "application/vnd.oasis.opendocument.spreadsheet", - "application/vnd.oasis.opendocument.spreadsheet-flat-xml", - "application/vnd.oasis.opendocument.presentation", - "application/vnd.oasis.opendocument.presentation-flat-xml", - "application/vnd.oasis.opendocument.graphics", - "application/vnd.oasis.opendocument.graphics-flat-xml", - "application/vnd.oasis.opendocument.chart", - "application/msword", - "application/vnd.ms-excel", - "application/vnd.ms-powerpoint", - "application/vnd.openxmlformats-officedocument.wordprocessingml.document", - "application/vnd.ms-word.document.macroEnabled.12", - "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", - "application/vnd.ms-excel.sheet.binary.macroEnabled.12", - "application/vnd.ms-excel.sheet.macroEnabled.12", - "application/vnd.openxmlformats-officedocument.presentationml.presentation", - "application/vnd.ms-powerpoint.presentation.macroEnabled.12", - "application/x-dif-document", - "text/spreadsheet", - "text/csv", - "application/x-dbase", - "text/rtf", - "text/plain", - "application/vnd.openxmlformats-officedocument.presentationml.slideshow", + 'application/vnd.ms-powerpoint', + 'application/vnd.ms-excel', + 'application/vnd.oasis.opendocument.text', + 'application/vnd.oasis.opendocument.text-flat-xml', + 'application/vnd.oasis.opendocument.spreadsheet', + 'application/vnd.oasis.opendocument.spreadsheet-flat-xml', + 'application/vnd.oasis.opendocument.presentation', + 'application/vnd.oasis.opendocument.presentation-flat-xml', + 'application/vnd.oasis.opendocument.graphics', + 'application/vnd.oasis.opendocument.graphics-flat-xml', + 'application/vnd.oasis.opendocument.chart', + 'application/msword', + 'application/vnd.ms-excel', + 'application/vnd.ms-powerpoint', + 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + 'application/vnd.ms-word.document.macroEnabled.12', + 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + 'application/vnd.ms-excel.sheet.binary.macroEnabled.12', + 'application/vnd.ms-excel.sheet.macroEnabled.12', + 'application/vnd.openxmlformats-officedocument.presentationml.presentation', + 'application/vnd.ms-powerpoint.presentation.macroEnabled.12', + 'application/x-dif-document', + 'text/spreadsheet', + 'text/csv', + 'application/x-dbase', + 'text/rtf', + 'text/plain', + 'application/vnd.openxmlformats-officedocument.presentationml.slideshow', ]); + + const MIMES_VIEW = new Set([ - ...MIMES_EDIT, - [ - "image/svg+xml", - "application/vnd.sun.xml.writer", - "application/vnd.sun.xml.calc", - "application/vnd.sun.xml.impress", - "application/vnd.sun.xml.draw", - "application/vnd.sun.xml.writer.global", - "application/vnd.sun.xml.writer.template", - "application/vnd.sun.xml.calc.template", - "application/vnd.sun.xml.impress.template", - "application/vnd.sun.xml.draw.template", - "application/vnd.oasis.opendocument.text-master", - "application/vnd.oasis.opendocument.text-template", - "application/vnd.oasis.opendocument.text-master-template", - "application/vnd.oasis.opendocument.spreadsheet-template", - "application/vnd.oasis.opendocument.presentation-template", - "application/vnd.oasis.opendocument.graphics-template", - "application/vnd.ms-word.template.macroEnabled.12", - "application/vnd.openxmlformats-officedocument.spreadsheetml.template", - "application/vnd.ms-excel.template.macroEnabled.12", - "application/vnd.openxmlformats-officedocument.presentationml.template", - "application/vnd.ms-powerpoint.template.macroEnabled.12", - "application/vnd.wordperfect", - "application/x-aportisdoc", - "application/x-hwp", - "application/vnd.ms-works", - "application/x-mswrite", - "application/vnd.lotus-1-2-3", - "image/cgm", - "image/vnd.dxf", - "image/x-emf", - "image/x-wmf", - "application/coreldraw", - "application/vnd.visio2013", - "application/vnd.visio", - "application/vnd.ms-visio.drawing", - "application/x-mspublisher", - "application/x-sony-bbeb", - "application/x-gnumeric", - "application/macwriteii", - "application/x-iwork-numbers-sffnumbers", - "application/vnd.oasis.opendocument.text-web", - "application/x-pagemaker", - "application/x-fictionbook+xml", - "application/clarisworks", - "image/x-wpg", - "application/x-iwork-pages-sffpages", - "application/x-iwork-keynote-sffkey", - "application/x-abiword", - "image/x-freehand", - "application/vnd.sun.xml.chart", - "application/x-t602", - "image/bmp", - "image/png", - "image/gif", - "image/tiff", - "image/jpg", - "image/jpeg", - "application/pdf", - ], -]); + ...MIMES_EDIT, + [ + 'image/svg+xml', + 'application/vnd.sun.xml.writer', + 'application/vnd.sun.xml.calc', + 'application/vnd.sun.xml.impress', + 'application/vnd.sun.xml.draw', + 'application/vnd.sun.xml.writer.global', + 'application/vnd.sun.xml.writer.template', + 'application/vnd.sun.xml.calc.template', + 'application/vnd.sun.xml.impress.template', + 'application/vnd.sun.xml.draw.template', + 'application/vnd.oasis.opendocument.text-master', + 'application/vnd.oasis.opendocument.text-template', + 'application/vnd.oasis.opendocument.text-master-template', + 'application/vnd.oasis.opendocument.spreadsheet-template', + 'application/vnd.oasis.opendocument.presentation-template', + 'application/vnd.oasis.opendocument.graphics-template', + 'application/vnd.ms-word.template.macroEnabled.12', + 'application/vnd.openxmlformats-officedocument.spreadsheetml.template', + 'application/vnd.ms-excel.template.macroEnabled.12', + 'application/vnd.openxmlformats-officedocument.presentationml.template', + 'application/vnd.ms-powerpoint.template.macroEnabled.12', + 'application/vnd.wordperfect', + 'application/x-aportisdoc', + 'application/x-hwp', + 'application/vnd.ms-works', + 'application/x-mswrite', + 'application/vnd.lotus-1-2-3', + 'image/cgm', + 'image/vnd.dxf', + 'image/x-emf', + 'image/x-wmf', + 'application/coreldraw', + 'application/vnd.visio2013', + 'application/vnd.visio', + 'application/vnd.ms-visio.drawing', + 'application/x-mspublisher', + 'application/x-sony-bbeb', + 'application/x-gnumeric', + 'application/macwriteii', + 'application/x-iwork-numbers-sffnumbers', + 'application/vnd.oasis.opendocument.text-web', + 'application/x-pagemaker', + 'application/x-fictionbook+xml', + 'application/clarisworks', + 'image/x-wpg', + 'application/x-iwork-pages-sffpages', + 'application/x-iwork-keynote-sffkey', + 'application/x-abiword', + 'image/x-freehand', + 'application/vnd.sun.xml.chart', + 'application/x-t602', + 'image/bmp', + 'image/png', + 'image/gif', + 'image/tiff', + 'image/jpg', + 'image/jpeg', + 'application/pdf', + ] +]) + +export interface SignedUrlGet { + method: 'GET'|'HEAD', + url: string, + expires: number, + object_name: string, +} function is_extension_editable(mimeType: string): boolean { - return MIMES_EDIT.has(mimeType); + return MIMES_EDIT.has(mimeType); } function is_extension_viewable(mimeType: string): boolean { - return MIMES_VIEW.has(mimeType); + return MIMES_VIEW.has(mimeType); } function build_convert_link(uuid: string) { - return `/chill/wopi/convert/${uuid}`; + return `/chill/wopi/convert/${uuid}`; } -function build_download_info_link(object_name: string) { - return `/asyncupload/temp_url/generate/GET?object_name=${object_name}`; +function build_download_info_link(storedObject: StoredObject, atVersion: null|StoredObjectVersion): string { + const url = `/api/1.0/doc-store/async-upload/temp_url/${storedObject.uuid}/generate/get`; + + if (null !== atVersion) { + const params = new URLSearchParams({version: atVersion.filename}); + + return url + '?' + params.toString(); + } + + return url; +} + +async function download_info_link(storedObject: StoredObject, atVersion: null|StoredObjectVersion): Promise { + return makeFetch('GET', build_download_info_link(storedObject, atVersion)); } function build_wopi_editor_link(uuid: string, returnPath?: string) { - if (returnPath === undefined) { - returnPath = - window.location.pathname + - window.location.search + - window.location.hash; - } + if (returnPath === undefined) { + returnPath = window.location.pathname + window.location.search + window.location.hash; + } - return ( - `/chill/wopi/edit/${uuid}?returnPath=` + encodeURIComponent(returnPath) - ); + return `/chill/wopi/edit/${uuid}?returnPath=` + encodeURIComponent(returnPath); } function download_doc(url: string): Promise { - return window.fetch(url).then((r) => { - if (r.ok) { - return r.blob(); - } + return window.fetch(url).then(r => { + if (r.ok) { + return r.blob() + } - throw new Error("Could not download document"); - }); + throw new Error('Could not download document'); + }); } -async function download_and_decrypt_doc( - urlGenerator: string, - keyData: JsonWebKey, - iv: Uint8Array, -): Promise { - const algo = "AES-CBC"; - // get an url to download the object - const downloadInfoResponse = await window.fetch(urlGenerator); +async function download_and_decrypt_doc(storedObject: StoredObject, atVersion: null|StoredObjectVersion): Promise +{ + const algo = 'AES-CBC'; - if (!downloadInfoResponse.ok) { - throw new Error( - "error while downloading url " + - downloadInfoResponse.status + - " " + - downloadInfoResponse.statusText, - ); + const atVersionToDownload = atVersion ?? storedObject.currentVersion; + + if (null === atVersionToDownload) { + throw new Error("no version associated to stored object"); + } + + // sometimes, the downloadInfo may be embedded into the storedObject + console.log('storedObject', storedObject); + let downloadInfo; + if (typeof storedObject._links !== 'undefined' && typeof storedObject._links.downloadLink !== 'undefined') { + downloadInfo = storedObject._links.downloadLink; + } else { + downloadInfo = await download_info_link(storedObject, atVersionToDownload); } - const downloadInfo = (await downloadInfoResponse.json()) as { url: string }; - const rawResponse = await window.fetch(downloadInfo.url); + const rawResponse = await window.fetch(downloadInfo.url); - if (!rawResponse.ok) { - throw new Error( - "error while downloading raw file " + - rawResponse.status + - " " + - rawResponse.statusText, - ); - } + if (!rawResponse.ok) { + throw new Error("error while downloading raw file " + rawResponse.status + " " + rawResponse.statusText); + } - if (iv.length === 0) { - console.log("returning document immediatly"); - return rawResponse.blob(); - } + if (atVersionToDownload.iv.length === 0) { + return rawResponse.blob(); + } - console.log("start decrypting doc"); + const rawBuffer = await rawResponse.arrayBuffer(); + try { + const key = await window.crypto.subtle + .importKey('jwk', atVersionToDownload.keyInfos, { name: algo }, false, ['decrypt']); + const iv = Uint8Array.from(atVersionToDownload.iv); + const decrypted = await window.crypto.subtle + .decrypt({ name: algo, iv: iv }, key, rawBuffer); - const rawBuffer = await rawResponse.arrayBuffer(); + return Promise.resolve(new Blob([decrypted])); + } catch (e) { + console.error('encounter error while keys and decrypt operations'); + console.error(e); - try { - const key = await window.crypto.subtle.importKey( - "jwk", - keyData, - { name: algo }, - false, - ["decrypt"], - ); - console.log("key created"); - const decrypted = await window.crypto.subtle.decrypt( - { name: algo, iv: iv }, - key, - rawBuffer, - ); - console.log("doc decrypted"); - - return Promise.resolve(new Blob([decrypted])); - } catch (e) { - console.error("get error while keys and decrypt operations"); - console.error(e); - - throw e; - } + throw e; + } } -async function is_object_ready( - storedObject: StoredObject, -): Promise { - const new_status_response = await window.fetch( - `/api/1.0/doc-store/stored-object/${storedObject.uuid}/is-ready`, - ); +/** + * Fetch the stored object as a pdf. + * + * If the document is already in a pdf on the server side, the document is retrieved "as is" from the usual + * storage. + */ +async function download_doc_as_pdf(storedObject: StoredObject): Promise +{ + if (null === storedObject.currentVersion) { + throw new Error("the stored object does not count any version"); + } + + if (storedObject.currentVersion?.type === 'application/pdf') { + return download_and_decrypt_doc(storedObject, storedObject.currentVersion); + } + + const convertLink = build_convert_link(storedObject.uuid); + const response = await fetch(convertLink); + + if (!response.ok) { + throw new Error("Could not convert the document: " + response.status); + } + + return response.blob(); +} + +async function is_object_ready(storedObject: StoredObject): Promise +{ + const new_status_response = await window + .fetch( `/api/1.0/doc-store/stored-object/${storedObject.uuid}/is-ready`); if (!new_status_response.ok) { - throw new Error("could not fetch the new status"); + throw new Error("could not fetch the new status"); } return await new_status_response.json(); } export { - build_convert_link, - build_download_info_link, - build_wopi_editor_link, - download_and_decrypt_doc, - download_doc, - is_extension_editable, - is_extension_viewable, - is_object_ready, + build_convert_link, + build_wopi_editor_link, + download_and_decrypt_doc, + download_doc, + download_doc_as_pdf, + is_extension_editable, + is_extension_viewable, + is_object_ready, }; diff --git a/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/_components/AddAsyncUpload.vue b/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/_components/AddAsyncUpload.vue deleted file mode 100644 index a55a203d3..000000000 --- a/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/_components/AddAsyncUpload.vue +++ /dev/null @@ -1,195 +0,0 @@ - - - diff --git a/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/_components/AddAsyncUploadDownloader.vue b/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/_components/AddAsyncUploadDownloader.vue deleted file mode 100644 index 42bc37ddc..000000000 --- a/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/_components/AddAsyncUploadDownloader.vue +++ /dev/null @@ -1,42 +0,0 @@ - - - diff --git a/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/_components/helper.ts b/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/_components/helper.ts deleted file mode 100644 index 1fffcfbf0..000000000 --- a/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/_components/helper.ts +++ /dev/null @@ -1,73 +0,0 @@ -import { makeFetch } from "../../../../../ChillMainBundle/Resources/public/lib/api/apiMethods"; -import { PostStoreObjectSignature } from "../../types"; - -const algo = "AES-CBC"; - -const URL_POST = "/asyncupload/temp_url/generate/post"; - -const keyDefinition = { - name: algo, - length: 256, -}; - -const createFilename = (): string => { - let text = ""; - const possible = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; - - for (let i = 0; i < 7; i++) { - text += possible.charAt(Math.floor(Math.random() * possible.length)); - } - - return text; -}; - -export const uploadFile = async (uploadFile: ArrayBuffer): Promise => { - const params = new URLSearchParams(); - params.append("expires_delay", "180"); - params.append("submit_delay", "180"); - const asyncData: PostStoreObjectSignature = await makeFetch( - "GET", - URL_POST + "?" + params.toString(), - ); - const suffix = createFilename(); - const filename = asyncData.prefix + suffix; - const formData = new FormData(); - formData.append("redirect", asyncData.redirect); - formData.append("max_file_size", asyncData.max_file_size.toString()); - formData.append("max_file_count", asyncData.max_file_count.toString()); - formData.append("expires", asyncData.expires.toString()); - formData.append("signature", asyncData.signature); - formData.append(filename, new Blob([uploadFile]), suffix); - - const response = await window.fetch(asyncData.url, { - method: "POST", - body: formData, - }); - - if (!response.ok) { - console.error("Error while sending file to store", response); - throw new Error(response.statusText); - } - - return Promise.resolve(filename); -}; - -export const encryptFile = async ( - originalFile: ArrayBuffer, -): Promise<[ArrayBuffer, Uint8Array, JsonWebKey]> => { - console.log("encrypt", originalFile); - const iv = crypto.getRandomValues(new Uint8Array(16)); - const key = await window.crypto.subtle.generateKey(keyDefinition, true, [ - "encrypt", - "decrypt", - ]); - const exportedKey = await window.crypto.subtle.exportKey("jwk", key); - const encrypted = await window.crypto.subtle.encrypt( - { name: algo, iv: iv }, - key, - originalFile, - ); - - return Promise.resolve([encrypted, iv, exportedKey]); -}; diff --git a/src/Bundle/ChillDocStoreBundle/Resources/views/AccompanyingCourseDocument/_workflow.html.twig b/src/Bundle/ChillDocStoreBundle/Resources/views/AccompanyingCourseDocument/_workflow.html.twig index 58d4903b4..b1850ff82 100644 --- a/src/Bundle/ChillDocStoreBundle/Resources/views/AccompanyingCourseDocument/_workflow.html.twig +++ b/src/Bundle/ChillDocStoreBundle/Resources/views/AccompanyingCourseDocument/_workflow.html.twig @@ -38,6 +38,11 @@ {% if display_action is defined and display_action == true %}