From d0c51af6a81e41f4813cd66e669d6c270fa12e24 Mon Sep 17 00:00:00 2001 From: Mikkel Ricky Date: Tue, 30 Jan 2024 21:50:37 +0100 Subject: [PATCH 1/2] Updated stuff and mocks --- .docker/data/.gitignore | 5 + .docker/data/README.md | 26 +++ .docker/nginx.conf | 36 ++++ .docker/templates/default.conf.template | 40 +++++ .docker/vhost.conf | 29 ---- .env | 8 +- README.md | 107 ++++++++---- config/packages/doctrine.yaml | 56 +++--- config/packages/easy_admin.yaml | 58 +++---- config/services.local.yaml.dist | 161 ++++++++++++++++++ config/services.yaml | 6 +- docker-compose.dev.yml | 25 +-- docker-compose.override.yml | 6 + docker-compose.redirect.yml | 5 +- docker-compose.server.yml | 17 +- docker-compose.yml | 32 ++-- src/Controller/Api/Admin/AdminController.php | 10 +- src/Mock/Controller/SmsGatewayController.php | 5 +- src/Mock/Entity/ActionLogEntry.php | 6 +- src/Mock/Entity/AeosActionLogEntry.php | 4 +- src/Mock/Entity/SmsGatewayActionLogEntry.php | 4 +- .../Repository/ActionLogEntryRepository.php | 29 ++++ src/Mock/Service/ActionLogManager.php | 22 ++- 23 files changed, 520 insertions(+), 177 deletions(-) create mode 100644 .docker/data/.gitignore create mode 100644 .docker/data/README.md create mode 100644 .docker/nginx.conf create mode 100644 .docker/templates/default.conf.template delete mode 100644 .docker/vhost.conf create mode 100644 config/services.local.yaml.dist create mode 100644 docker-compose.override.yml create mode 100644 src/Mock/Repository/ActionLogEntryRepository.php diff --git a/.docker/data/.gitignore b/.docker/data/.gitignore new file mode 100644 index 00000000..80a9dc93 --- /dev/null +++ b/.docker/data/.gitignore @@ -0,0 +1,5 @@ +# Ignore everything in this directory +* +# Except this file +!.gitignore +!Readme.md diff --git a/.docker/data/README.md b/.docker/data/README.md new file mode 100644 index 00000000..8895d7b1 --- /dev/null +++ b/.docker/data/README.md @@ -0,0 +1,26 @@ +# .docker/data + +Please map persistent volumes to this directory on the servers. + +If a container needs to persist data between restarts you can map the relevant files in the container to ``docker/data/`. + +## RabbitMQ example +If you are using RabbitMQ running in a container as a message broker you need to configure a persistent volume for RabbitMQs data directory to avoid losing message on container restarts. + +```yaml +# docker-compose.server.override.yml + +services: + rabbit: + image: rabbitmq:3.9-management-alpine + hostname: "${COMPOSE_PROJECT_NAME}" + networks: + - app + - frontend + environment: + - "RABBITMQ_DEFAULT_USER=${RABBITMQ_USER}" + - "RABBITMQ_DEFAULT_PASS=${RABBITMQ_PASSWORD}" + - "RABBITMQ_ERLANG_COOKIE=${RABBITMQ_ERLANG_COOKIE}" + volumes: + - ".docker/data/rabbitmq:/var/lib/rabbitmq/mnesia/" +``` diff --git a/.docker/nginx.conf b/.docker/nginx.conf new file mode 100644 index 00000000..0335e534 --- /dev/null +++ b/.docker/nginx.conf @@ -0,0 +1,36 @@ +worker_processes auto; + +error_log /dev/stderr notice; +pid /tmp/nginx.pid; + +events { + worker_connections 1024; +} + +http { + proxy_temp_path /tmp/proxy_temp; + client_body_temp_path /tmp/client_temp; + fastcgi_temp_path /tmp/fastcgi_temp; + uwsgi_temp_path /tmp/uwsgi_temp; + scgi_temp_path /tmp/scgi_temp; + + include /etc/nginx/mime.types; + default_type application/octet-stream; + + set_real_ip_from 172.16.0.0/8; + real_ip_recursive on; + real_ip_header X-Forwarded-For; + + log_format main '$http_x_real_ip - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + access_log /dev/stdout main; + + sendfile on; + keepalive_timeout 65; + + gzip on; + + include /etc/nginx/conf.d/*.conf; +} diff --git a/.docker/templates/default.conf.template b/.docker/templates/default.conf.template new file mode 100644 index 00000000..df4744c3 --- /dev/null +++ b/.docker/templates/default.conf.template @@ -0,0 +1,40 @@ +server { + listen ${NGINX_PORT}; + server_name localhost; + + root ${NGINX_WEB_ROOT}; + + location / { + # try to serve file directly, fallback to index.php + try_files $uri /index.php$is_args$args; + } + + # Protect files and directories from prying eyes. + location ~* \.(engine|inc|install|make|module|profile|po|sh|.*sql|.tar|.gz|.bz2|theme|twig|tpl(\.php)?|xtmpl|yml)(~|\.sw[op]|\.bak|\.orig|\.save)?$|^(\.(?!well-known).*|Entries.*|Repository|Root|Tag|Template|composer\.(json|lock)|web\.config)$|^#.*#$|\.php(~|\.sw[op]|\.bak|\.orig|\.save)$ { + deny all; + return 404; + } + + location ~ ^/index\.php(/|$) { + fastcgi_buffers 16 32k; + fastcgi_buffer_size 64k; + fastcgi_busy_buffers_size 64k; + + fastcgi_pass ${NGINX_FPM_SERVICE}; + fastcgi_split_path_info ^(.+\.php)(/.*)$; + include fastcgi_params; + + fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; + fastcgi_param DOCUMENT_ROOT $realpath_root; + + internal; + } + + location ~ \.php$ { + return 404; + } + + # Send log message to files symlinked to stdout/stderr. + error_log /dev/stderr; + access_log /dev/stdout main; +} diff --git a/.docker/vhost.conf b/.docker/vhost.conf deleted file mode 100644 index 7220debe..00000000 --- a/.docker/vhost.conf +++ /dev/null @@ -1,29 +0,0 @@ -server { - listen 8080; - server_name localhost; - root /app/public; - - location / { - # try to serve file directly, fallback to index.php - try_files $uri /index.php$is_args$args; - } - - location ~ ^/index\.php(/|$) { - fastcgi_pass phpfpm:9000; - fastcgi_split_path_info ^(.+\.php)(/.*)$; - include fastcgi_params; - - fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; - fastcgi_param DOCUMENT_ROOT $realpath_root; - - internal; - } - - location ~ \.php$ { - return 404; - } - - # Send log message to files symlinked to stdout/stderr. - error_log /dev/stderr; - access_log /dev/stdout; -} diff --git a/.env b/.env index 85b9b7a5..7e701879 100644 --- a/.env +++ b/.env @@ -13,8 +13,8 @@ # 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 -COMPOSE_PROJECT_NAME=dokk1gh -COMPOSE_DOMAIN=dokk1gh.local.itkdev.dk +COMPOSE_PROJECT_NAME=dokk1gh-legacy +COMPOSE_DOMAIN=dokk1gh-legacy.local.itkdev.dk ###> symfony/framework-bundle ### APP_ENV=prod @@ -32,7 +32,7 @@ DATABASE_URL=mysql://db:db@mariadb:3306/db?serverVersion=mariadb-10.3.24 ###< doctrine/doctrine-bundle ### ###> symfony/mailer ### -MAILER_DSN=smtp://mailhog:1025 +MAILER_DSN=smtp://mail:1025 ###< symfony/mailer ### SITE_URL=http://dokk1gh-4.4.local.itkdev.dk @@ -40,3 +40,5 @@ SITE_NAME='Gæstehåndtering' MAILER_FROM_EMAIL='gh@dokk1.gh.vm' MAILER_FROM_NAME='GH' + +MOCK_DATABASE_URL="sqlite:///%kernel.project_dir%/var/mocks.sqlite" diff --git a/README.md b/README.md index f1544d25..d9695cf1 100644 --- a/README.md +++ b/README.md @@ -2,23 +2,32 @@ ## Installation -```sh -docker compose up -d +```shell +docker compose pull +docker compose up --detach ``` -```sh +```shell docker compose exec phpfpm composer install ``` +Define default local settings: + +``` shell +cp config/services.local.yaml.dist config/services.local.yaml +``` + +Edit `config/services.local.yaml` as needed (cf. [Mocks](#mocks)). + Set up database: -```sh +```shell docker compose exec phpfpm bin/console doctrine:migrations:migrate --no-interaction ``` Create super administrator: -```sh +```shell docker compose exec phpfpm bin/console user:create super-admin@example.com docker compose exec phpfpm bin/console user:promote super-admin@example.com ROLE_SUPER_ADMIN docker compose exec phpfpm bin/console user:set-password super-admin@example.com @@ -26,36 +35,36 @@ docker compose exec phpfpm bin/console user:set-password super-admin@example.com Create administrator: -```sh +```shell docker compose exec phpfpm bin/console user:create admin@example.com ``` -```sh +```shell docker compose exec phpfpm bin/console user:promote admin@example.com ROLE_ADMIN ``` Create user: -```sh +```shell docker compose exec phpfpm bin/console user:create user user@example.com ``` Open the site: -```sh +```shell open "http://$(docker compose port nginx 8080)" ``` ## Build assets -```sh +```shell docker compose run --rm node yarn install docker compose run --rm node yarn build ``` During development, use -```sh +```shell docker-compose run node yarn watch ``` @@ -65,13 +74,13 @@ to watch for changes. The `app:aeos:code-cleanup` console command can be used to delete expires codes: -```sh +```shell bin/console app:aeos:code-cleanup --help ``` A couple of commands can clean up guest and apps -```sh +```shell bin/console app:expire-guests bin/console app:expire-inactive-apps --app-sent-before='-24 hours' ``` @@ -79,7 +88,7 @@ bin/console app:expire-inactive-apps --app-sent-before='-24 hours' Set up a `cron` job to have expired codes deleted daily at 02:00 (adjust paths to match your actual setup): -```sh +```shell 0 2 * * * /usr/bin/php /home/www/dokk1gh/htdocs/bin/console --env=prod app:aeos:code-cleanup ``` @@ -87,31 +96,31 @@ Set up a `cron` job to have expired codes deleted daily at 02:00 API documentation: -```sh +```shell open "http://$(docker compose port nginx 8080)/api/doc" ``` Using an `apikey`, users can get a list of available templates: -```sh +```shell curl "http://$(docker compose port nginx 8080)/api/templates?apikey=apikey" ``` Get list of codes created by user: -```sh +```shell curl "http://$(docker compose port nginx 8080)/api/codes?apikey=apikey" ``` An administrator can get all codes by adding `all=1`: -```sh +```shell curl "http://$(docker compose port nginx 8080)/api/codes?apikey=apikey&all=1" ``` Create a code: -```sh +```shell curl --silent "http://$(docker compose port nginx 8080)/api/codes?apikey=apikey" --header "content-type: application/json" --data @- <<'JSON' { "template": 1, @@ -142,45 +151,69 @@ On success the result will look like this: Debug email sent to user when created: -```sh +```shell bin/console app:debug notify-user-created [user email] ``` e.g. -```sh +```shell bin/console app:debug notify-user-created user@example.com ``` +Open test mail UI: + +``` shell +open "http://$(docker compose port mail 8025)" +``` + ### Mocks -```sh -bin/console doctrine:schema:update --em=mocks --force +```shell +docker compose exec phpfpm bin/console doctrine:schema:update --em=mock --force --complete ``` #### Mock AEOS web service -`parameters.yml`: +Use this during local testing and development. ```yaml -aoes_location: 'http://nginx/mock/aeosws' -aoes_username: null -aoes_password: null +# config/services.local.yaml +parameters: + aoes_location: 'http://nginx:8080/mock/aeosws' + aoes_username: null + aoes_password: null ``` +* List mock AEOS templates to use when editing templates: + + ```shell + open "http://$(docker compose port nginx 8080)/api/admin/templates"` + ``` + +* List mock AEOS users to use when editing users: + + ```shell + open "http://$(docker compose port nginx 8080)/api/admin/people" + ``` + #### Mock SMS gateway +Use this during local testing and development. + ```yaml -sms_gateway_location: 'http://nginx/mock/sms -sms_gateway_username: null -sms_gateway_password: null +# config/services.local.yaml +parameters: + sms_gateway_location: 'http://nginx:8080/mock/sms + sms_gateway_username: null + sms_gateway_password: null ``` ## Acceptance tests Clear out the acceptance test cache and set up the database: -```sh +```shell SYMFONY_ENV=acceptance bin/console cache:clear --no-warmup SYMFONY_ENV=acceptance bin/console cache:warmup SYMFONY_ENV=acceptance bin/console doctrine:database:create @@ -188,7 +221,7 @@ SYMFONY_ENV=acceptance bin/console doctrine:database:create Run API tests: -```sh +```shell ./vendor/bin/behat ``` @@ -198,25 +231,25 @@ Run API tests: Check code: -```sh +```shell docker compose exec phpfpm composer coding-standards-check ``` Apply coding standards: -```sh +```shell docker compose exec phpfpm composer coding-standards-apply ``` ### Twig (experimental) -```sh +```shell docker compose exec phpfpm composer coding-standards-check/twigcs ``` ### Markdown -```sh +```shell docker compose run --rm node yarn coding-standards-check ``` @@ -224,7 +257,7 @@ docker compose run --rm node yarn coding-standards-check Run -```sh +```shell docker compose exec phpfpm composer install-git-hooks ``` diff --git a/config/packages/doctrine.yaml b/config/packages/doctrine.yaml index d6ef5d11..ada22224 100644 --- a/config/packages/doctrine.yaml +++ b/config/packages/doctrine.yaml @@ -1,33 +1,47 @@ doctrine: dbal: - url: '%env(resolve:DATABASE_URL)%' + connections: + default: + url: '%env(resolve:DATABASE_URL)%' + schema_filter: ~^(?!craue_config_setting|mock_)~ + mock: + url: '%env(resolve:MOCK_DATABASE_URL)%' + default_connection: default # IMPORTANT: You MUST configure your server version, # either here or in the DATABASE_URL env var (see .env file) #server_version: '5.7' - schema_filter: ~^(?!craue_config_setting|mock_)~ orm: auto_generate_proxy_classes: true - naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware - auto_mapping: true - mappings: - App: - is_bundle: false - type: annotation - dir: '%kernel.project_dir%/src/Entity' - prefix: 'App\Entity' - alias: App + default_entity_manager: default + entity_managers: + default: + connection: default + naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware + # auto_mapping: true + mappings: + App: + is_bundle: false + type: annotation + dir: '%kernel.project_dir%/src/Entity' + prefix: 'App\Entity' + alias: App - App\Mock: - is_bundle: false - type: annotation - dir: '%kernel.project_dir%/src/Mock/Entity' - prefix: 'App\Mock\Entity' - alias: Mock + filters: + softdeleteable: + class: Gedmo\SoftDeleteable\Filter\SoftDeleteableFilter + enabled: true - filters: - softdeleteable: - class: Gedmo\SoftDeleteable\Filter\SoftDeleteableFilter - enabled: true + mock: + connection: mock + naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware + # auto_mapping: true + mappings: + App\Mock: + is_bundle: false + type: annotation + dir: '%kernel.project_dir%/src/Mock/Entity' + prefix: 'App\Mock\Entity' + alias: Mock diff --git a/config/packages/easy_admin.yaml b/config/packages/easy_admin.yaml index 972bae54..f7547c52 100644 --- a/config/packages/easy_admin.yaml +++ b/config/packages/easy_admin.yaml @@ -28,9 +28,9 @@ easy_admin: roles: [ROLE_USER_ADMIN] - entity: Template roles: [ROLE_TEMPLATE_ADMIN] - - entity: Setting - label: Settings - roles: [ROLE_CONFIG_ADMIN] + # - entity: Setting + # label: Settings + # roles: [ROLE_CONFIG_ADMIN] formats: datetime: '%format_datetime%' @@ -252,30 +252,30 @@ easy_admin: type_options: required: false - Setting: - roles: [ROLE_CONFIG_ADMIN] - controller: ItkDev\ConfigBundle\Controller\SettingController - class: ItkDev\ConfigBundle\Entity\Setting - disabled_actions: [new, delete] - list: - title: Settings - fields: - - property: name - template: admin/translate.html.twig - - property: value - label: Value - template: '@ItkDevConfig/easy_admin/Setting/display_value.html.twig' + # Setting: + # roles: [ROLE_CONFIG_ADMIN] + # controller: ItkDev\ConfigBundle\Controller\SettingController + # class: ItkDev\ConfigBundle\Entity\Setting + # disabled_actions: [new, delete] + # list: + # title: Settings + # fields: + # - property: name + # template: admin/translate.html.twig + # - property: value + # label: Value + # template: '@ItkDevConfig/easy_admin/Setting/display_value.html.twig' - edit: - fields: - - property: name - type_options: - disabled: true - - property: value - type_options: - required: false - - property: description - type_options: - disabled: true - # attr: - # raw: true + # edit: + # fields: + # - property: name + # type_options: + # disabled: true + # - property: value + # type_options: + # required: false + # - property: description + # type_options: + # disabled: true + # # attr: + # # raw: true diff --git a/config/services.local.yaml.dist b/config/services.local.yaml.dist new file mode 100644 index 00000000..0add14ed --- /dev/null +++ b/config/services.local.yaml.dist @@ -0,0 +1,161 @@ +parameters: + aeos_location: 'http://nginx:8080/mock/aeosws' + aeos_username: null + aeos_password: null + + sms_gateway_url: 'http://nginx:8080/mock/sms/send' + sms_gateway_username: test + sms_gateway_password: test + + app_name: Gæstehåndtering + site_name: '%env(SITE_NAME)%' + site_url: '%env(SITE_URL)%' + router.request_context.scheme: http + router.request_context.host: dokk1gh.local.itkdev.dk + mailer_name: '%env(MAILER_FROM_NAME)%' + mailer_email: '%env(MAILER_FROM_EMAIL)%' + administrator_email: admin@dokk1.gh.vm + error_mail_sender: error@dokk1gh.vm + error_mail_recipient: + - error@dokk1gh.vm + + aeos_timezone: Europe/Copenhagen + aeos_context: + ssl: + verify_peer: false + verify_peer_name: false + allow_self_signed: true + aeos_identifier_type: 16509 + aeos_identifier_length: 8 + aeos_vistor_name_template: 'Code {{ code.id|default(''–'') }}; {{ ''now''|date(''Y-m-d H:i'') }}; {{ code.createdBy.email|default(user.email)|default('''') }}' + aeos_block_reason: 2 + header_image_url: /images/logo.png + locale: da + format_datetime: 'd/m/Y H:i' + format_date: d/m/Y + format_time: 'H:i' + view_timezone: Europe/Copenhagen + form_format_date: d/m/Y + form_format_date_js: dd/mm/yyyy + api_title: 'Gæstehåndtering – API' + api_description: 'The API' + user_created_user_subject: '{{ site_name }} – brugeroprettelse' + user_created_user_header: 'Bruger oprettet på {{ site_name }}' + user_created_user_body: "

Du er blevet oprettet som bruger på {{ site_name }} med e-mailadressen {{ user.email }}.

\n

For at komme i gang skal du angive en adgangskode.

\n

Du kan efterfølgende logge ind med din e-mailadresse ({{ user.email }}) og den valgte adgangskode.

" + user_created_user_button_text: 'Angiv adgangskode' + user_created_user_footer: '

Venlig hilsen
{{ sender.name }}

' + password_resetting_subject: '{{ site_name }} – nulstilling af adgangskode' + password_resetting_header: 'Nulstilling af adgangskode på {{ site_name }}' + password_resetting_body: '

Du kan skifte adgangskoden for {{ user.email }} ved at gå til {{ confirmationUrl }} og vælge en ny adgangskode.

' + password_resetting_button_text: 'Skift adgangskode' + password_resetting_footer: '

Venlig hilsen
{{ sender.name }}

' + code_generate_email.subject: 'Adgangskode til Dokk1' + code_generate_email.body: "Her er din adgangskode til Dokk1: {{ code.identifier }}\n\nKoden indtastes på tal-panelet ved siden af døren eller inde i elevatoren. OBS: Når du taster koden skal du huske at afslutte med E, dvs. du skal taste “{{ code.identifier }}E”.\n\nKoden giver adgang til “{{ code.template.name }}” i tidsrummet {% if (code.startTime | date('Y-m-d')) == (code.endTime | date('Y-m-d')) -%}\n{{ code.startTime | date(format_date, view_timezone) }} {{ code.startTime | date(format_time, view_timezone) }}-{{ code.endTime | date(format_time, view_timezone) }}\n{%- else -%}\n{{ code.startTime | date(format_datetime, view_timezone) }}-{{ code.endTime | date(format_datetime, view_timezone) }}\n{%- endif -%}.\n\nBemærk at der kan gå op til 30 minutter før koden er aktiv.\n\nVenlig hilsen\n{{ site_name }}" + code_generate_sms.body: "Her er din adgangskode til Dokk1: {{ code.identifier }}\n\nKoden indtastes på tal-panelet ved siden af døren eller inde i elevatoren. OBS: Når du taster koden skal du huske at afslutte med E, dvs. du skal taste “{{ code.identifier }}E”.\n\nKoden giver adgang til “{{ code.template.name }}” i tidsrummet {% if (code.startTime | date('Y-m-d')) == (code.endTime | date('Y-m-d')) -%}\n{{ code.startTime | date(format_date, view_timezone) }} {{ code.startTime | date(format_time, view_timezone) }}-{{ code.endTime | date(format_time, view_timezone) }}\n{%- else -%}\n{{ code.startTime | date(format_datetime, view_timezone) }}-{{ code.endTime | date(format_datetime, view_timezone) }}\n{%- endif -%}.\n\nBemærk at der kan gå op til 30 minutter før koden er aktiv.\n\nVenlig hilsen\n{{ site_name }}" + code_valid_time_period: "{% if (code.startTime | date('Y-m-d')) == (code.endTime | date('Y-m-d')) -%}\n{{ code.startTime | date(format_date, view_timezone) }} {{ code.startTime | date(format_time, view_timezone) }}–{{ code.endTime | date(format_time, view_timezone) }}\n{%- else -%}\n{{ code.startTime | date(format_datetime, view_timezone) }}–{{ code.endTime | date(format_datetime, view_timezone) }}\n{%- endif -%}" + code.config: + startTime: + hours: + min: 8 + max: 21 + minutes: + - 0 + - 30 + endTime: + hours: + min: 9 + max: 22 + minutes: + - 0 + - 30 + daysEnabled: + - 0 + - 1 + - 2 + - 3 + - 4 + - 5 + - 6 + code.defaults.startTime: 'today +7 hours' + code.defaults.endTime: 'today +14 hours' + user.cannot_create_codes.subject: 'Bruger {{ app.user.email }} kan ikke oprette koder på {{ site_name }}' + user.cannot_create_codes.body: 'Bruger {{ app.user.email }} kan ikke oprette koder på {{ site_name }} ({{ site_url }}).' + guest_code_duration: null + guest_code_name_template: '{{ ''now'' | date(format_datetime) }}: {{ guest.name }}; {{ guest.company }}; {{ guest.phone }}; {{ guest.email }}' + guest_code_sms_template: '%code_generate_sms.body%' + pwa_app_short_name: Code2Dokk1 + pwa_app_name: 'Code2Dokk1 - Generer dørkoder' + + guest_timeRanges_min: '06:00' + guest_timeRanges_max: '22:00' + guest_timeRanges_step: 30M + guest_default_phone_country_code: '45' + guest_default_startTime: today + guest_default_endTime: 'today + 7 days' + guest_default_timeRanges: + 1: + - '06:00' + - '15:00' + 2: + - '06:00' + - '15:00' + 3: + - '06:00' + - '15:00' + 4: + - '06:00' + - '15:00' + 5: + - '06:00' + - '14:00' + 6: null + 7: null + guest_app_email_sender_email: '%mailer_email%' + guest_app_email_sender_name: '%mailer_name%' + guest_app_email_subject_template: 'Gæstehåndtering – App''en' + guest_app_email_body_template: "

\nDu kan åbne din helt personlige app på: {{ app_url }}.\n

\n\n

\nVenlig hilsen
\n{{ site_name }}\n

" + guest_app_sms_body_template: "Du kan åbne din helt personlige app på: {{ app_url }}.\n\nVenlig hilsen\n{{ site_name }}" + app_icons: + 20x20: images/code2dokk1_launcher_ic_20.png + 29x29: images/code2dokk1_launcher_ic_29.png + 40x40: images/code2dokk1_launcher_ic_40.png + 48x48: images/code2dokk1_launcher_ic_48.png + 58x58: images/code2dokk1_launcher_ic_58.png + 60x60: images/code2dokk1_launcher_ic_60.png + 72x72: images/code2dokk1_launcher_ic_72.png + 76x76: images/code2dokk1_launcher_ic_76.png + 80x80: images/code2dokk1_launcher_ic_80.png + 87x87: images/code2dokk1_launcher_ic_87.png + 96x96: images/code2dokk1_launcher_ic_96.png + 120x120: images/code2dokk1_launcher_ic_120.png + 144x144: images/code2dokk1_launcher_ic_144.png + 152x152: images/code2dokk1_launcher_ic_152.png + 167x167: images/code2dokk1_launcher_ic_167.png + 180x180: images/code2dokk1_launcher_ic_180.png + 192x192: images/code2dokk1_launcher_ic_192.png + 512x512: images/code2dokk1_launcher_ic_512.png + 1024x1024: images/code2dokk1_launcher_ic_1024.png + + + # aeos_visitor_name_template: 'Code {{ code.id|default(''–'') }}; {{ ''now''|date(''Y-m-d H:i'') }}; {{ code.createdBy.email|default(user.email)|default('''') }}' + # code_generate_email: + # subject: 'Adgangskode til Dokk1' + # body: | + # Her er din adgangskode til Dokk1: {{ code.identifier }} + + # Koden indtastes på tal-panelet ved siden af døren eller inde i + # elevatoren. OBS: Når du taster koden skal du huske at afslutte med + # E, dvs. du skal taste “{{ code.identifier }}E”. + + # Koden giver adgang til “{{ code.template.name }}” i tidsrummet + # {% if (code.startTime | date('Y-m-d')) == (code.endTime | date('Y-m-d')) -%} + # {{ code.startTime | date(format_date, view_timezone) }} {{ code.startTime | date(format_time, view_timezone) }}–{{ code.endTime | date(format_time, view_timezone) }} + # {%- else -%} + # {{ code.startTime | date(format_datetime, view_timezone) }}–{{ code.endTime | date(format_datetime, view_timezone) }} + # {%- endif -%}. + + # Venlig hilsen + # {{ site_name }} + + + # guest_timeRanges_min: '06:00' diff --git a/config/services.yaml b/config/services.yaml index 143c5e38..479fb74b 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -18,9 +18,9 @@ services: bind: $aeosConfiguration: client: - location: '%aoes_location%' - username: '%aoes_username%' - password: '%aoes_password%' + location: '%aeos_location%' + username: '%aeos_username%' + password: '%aeos_password%' context: '%aeos_context%' debug: '%kernel.debug%' aeos: diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index 2cc5cada..c4a8594c 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -1,28 +1,29 @@ -# itk-version: 2.2.0 -version: "3" +# itk-version: 3.2.0 +version: "3.8" services: phpfpm: environment: - - PHP_SENDMAIL_PATH='/usr/local/bin/mhsendmail --smtp-addr="mailhog:1025"' + - PHP_SENDMAIL_PATH=/usr/sbin/sendmail -S mail:1025 nginx: labels: - "traefik.http.routers.${COMPOSE_PROJECT_NAME}.middlewares=ITKBasicAuth@file" - mailhog: - image: itkdev/mailhog + mail: + image: axllent/mailpit + restart: unless-stopped networks: - app - frontend labels: - "traefik.enable=true" - "traefik.docker.network=frontend" - - "traefik.http.routers.mailhog_${COMPOSE_PROJECT_NAME}-http.rule=Host(`mailhog.${COMPOSE_SERVER_DOMAIN}`)" - - "traefik.http.routers.mailhog_${COMPOSE_PROJECT_NAME}-http.entrypoints=web" - - "traefik.http.routers.mailhog_${COMPOSE_PROJECT_NAME}-http.middlewares=redirect-to-https" + - "traefik.http.routers.mail_${COMPOSE_PROJECT_NAME}-http.rule=Host(`mail.${COMPOSE_SERVER_DOMAIN}`)" + - "traefik.http.routers.mail_${COMPOSE_PROJECT_NAME}-http.entrypoints=web" + - "traefik.http.routers.mail_${COMPOSE_PROJECT_NAME}-http.middlewares=redirect-to-https" - "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https" - - "traefik.http.routers.mailhog_${COMPOSE_PROJECT_NAME}.rule=Host(`mailhog.${COMPOSE_SERVER_DOMAIN}`)" - - "traefik.http.routers.mailhog_${COMPOSE_PROJECT_NAME}.entrypoints=websecure" - - "traefik.http.services.mailhog_${COMPOSE_PROJECT_NAME}.loadbalancer.server.port=8025" - - "traefik.http.routers.mailhog_${COMPOSE_PROJECT_NAME}.middlewares=ITKMailhogAuth@file" + - "traefik.http.routers.mail_${COMPOSE_PROJECT_NAME}.rule=Host(`mail.${COMPOSE_SERVER_DOMAIN}`)" + - "traefik.http.routers.mail_${COMPOSE_PROJECT_NAME}.entrypoints=websecure" + - "traefik.http.services.mail_${COMPOSE_PROJECT_NAME}.loadbalancer.server.port=8025" + - "traefik.http.routers.mail_${COMPOSE_PROJECT_NAME}.middlewares=ITKMailhogAuth@file" diff --git a/docker-compose.override.yml b/docker-compose.override.yml new file mode 100644 index 00000000..16ab1dfb --- /dev/null +++ b/docker-compose.override.yml @@ -0,0 +1,6 @@ +services: + node: + image: node:14 + volumes: + - .:/app + working_dir: /app diff --git a/docker-compose.redirect.yml b/docker-compose.redirect.yml index ee6568c3..2769a7d1 100644 --- a/docker-compose.redirect.yml +++ b/docker-compose.redirect.yml @@ -1,6 +1,5 @@ -# itk-version: 2.1.0 -version: "3" - +# itk-version: 3.2.0 +version: "3.8" services: nginx: labels: diff --git a/docker-compose.server.yml b/docker-compose.server.yml index de648b3c..df30dc1a 100644 --- a/docker-compose.server.yml +++ b/docker-compose.server.yml @@ -1,5 +1,5 @@ -# itk-version: 2.0.1 -version: "3" +# itk-version: 3.2.0 +version: "3.8" networks: frontend: @@ -21,7 +21,7 @@ services: - PHP_MEMORY_LIMIT=128M - COMPOSER_VERSION=2 volumes: - - .:/app:delegated + - .:/app nginx: image: nginxinc/nginx-unprivileged:alpine @@ -31,11 +31,14 @@ services: - frontend depends_on: - phpfpm - ports: - - '8080' volumes: - - ${PWD}/.docker/vhost.conf:/etc/nginx/conf.d/default.conf:ro - - ./:/app:rw + - ./.docker/templates:/etc/nginx/templates:ro + - ./.docker/nginx.conf:/etc/nginx/nginx.conf:ro + - .:/app + environment: + NGINX_FPM_SERVICE: ${COMPOSE_PROJECT_NAME}-phpfpm-1:9000 + NGINX_WEB_ROOT: /app/public + NGINX_PORT: 8080 labels: - "traefik.enable=true" - "traefik.docker.network=frontend" diff --git a/docker-compose.yml b/docker-compose.yml index b02b1825..6575df17 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,5 +1,5 @@ -# itk-version: 2.0.2 -version: "3" +# itk-version: 3.2.0 +version: "3.8" networks: frontend: @@ -29,12 +29,14 @@ services: image: itkdev/php7.4-fpm:latest networks: - app + extra_hosts: + - "host.docker.internal:host-gateway" environment: - - XDEBUG_MODE=${XDEBUG_MODE:-off} - - XDEBUG_SESSION=${XDEBUG_SESSION:-0} + - PHP_XDEBUG_MODE=${PHP_XDEBUG_MODE:-off} - PHP_MAX_EXECUTION_TIME=30 - PHP_MEMORY_LIMIT=256M - # - PHP_MAIL=1 # Uncomment to enable mailhog. + # Depending on the setup, you may have to remove --read-envelope-from from msmtp (cf. https://marlam.de/msmtp/msmtp.html) or use SMTP to send mail + - PHP_SENDMAIL_PATH=/usr/bin/msmtp --host=mail --port=1025 --read-recipients --read-envelope-from - DOCKER_HOST_DOMAIN=${COMPOSE_DOMAIN} - COMPOSER_VERSION=2 - PHP_IDE_CONFIG=serverName=localhost @@ -53,8 +55,12 @@ services: ports: - '8080' volumes: - - ./.docker/vhost.conf:/etc/nginx/conf.d/default.conf:ro + - ./.docker/templates:/etc/nginx/templates:ro - .:/app + environment: + NGINX_FPM_SERVICE: ${COMPOSE_PROJECT_NAME}-phpfpm-1:9000 + NGINX_WEB_ROOT: /app/public + NGINX_PORT: 8080 labels: - "traefik.enable=true" - "traefik.docker.network=frontend" @@ -63,8 +69,8 @@ services: # - "traefik.http.routers.${COMPOSE_PROJECT_NAME}.middlewares=redirect-to-https" # - "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https" - mailhog: - image: itkdev/mailhog + mail: + image: axllent/mailpit networks: - app - frontend @@ -74,11 +80,5 @@ services: labels: - "traefik.enable=true" - "traefik.docker.network=frontend" - - "traefik.http.routers.${COMPOSE_PROJECT_NAME}Mailhog.rule=Host(`mailhog-${COMPOSE_DOMAIN}`)" - - "traefik.http.services.${COMPOSE_PROJECT_NAME}Mailhog.loadbalancer.server.port=8025" - - node: - image: node:14 - volumes: - - .:/app - working_dir: /app + - "traefik.http.routers.${COMPOSE_PROJECT_NAME}mail.rule=Host(`mail-${COMPOSE_DOMAIN}`)" + - "traefik.http.services.${COMPOSE_PROJECT_NAME}mail.loadbalancer.server.port=8025" diff --git a/src/Controller/Api/Admin/AdminController.php b/src/Controller/Api/Admin/AdminController.php index f461615e..e7b221d6 100644 --- a/src/Controller/Api/Admin/AdminController.php +++ b/src/Controller/Api/Admin/AdminController.php @@ -97,7 +97,7 @@ public function getPeopleSearchAction(Request $request) { $data = $this->searchAction($request, 'getPersons', ['Id', 'PersonnelNo', 'LastName', 'FirstName'], User::class); - $data = array_map(static fn ($item) => (array) $item, $data); + $data = array_map(static fn ($item) => (array) $item, $data ?? []); return $data; } @@ -143,9 +143,11 @@ public function getPersonAction($id) */ public function getTemplatesAction(Request $request) { - $result = $this->aeosService->getTemplates($request->query->all()); + $data = $this->aeosService->getTemplates($request->query->all()); - return $result; + $data = array_map(static fn ($item) => (array) $item, $data ?? []); + + return $data; } /** @@ -166,7 +168,7 @@ public function getTemplatesSearchAction(Request $request) { $data = $this->searchAction($request, 'getTemplates', ['Id', 'Name'], Template::class); - $data = array_map(static fn ($item) => (array) $item, $data); + $data = array_map(static fn ($item) => (array) $item, $data ?? []); return $data; } diff --git a/src/Mock/Controller/SmsGatewayController.php b/src/Mock/Controller/SmsGatewayController.php index b4e8b7fc..d6552be5 100644 --- a/src/Mock/Controller/SmsGatewayController.php +++ b/src/Mock/Controller/SmsGatewayController.php @@ -12,6 +12,7 @@ use App\Mock\Entity\SmsGatewayActionLogEntry; use App\Mock\Service\ActionLogManager; +use Doctrine\Persistence\ManagerRegistry; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -41,7 +42,7 @@ public function indexAction() /** * @Route("/log", name="sms_log") */ - public function logAction() + public function logAction(ManagerRegistry $registry) { $items = $this->manager->findAll(SmsGatewayActionLogEntry::class); @@ -55,7 +56,7 @@ public function logAction() */ public function logLastestAction() { - $items = [$this->manager->findOne(SmsGatewayActionLogEntry::class)]; + $items = array_filter([$this->manager->findOne(SmsGatewayActionLogEntry::class)]); return $this->render('@Mock/smsgateway/index.html.twig', [ 'items' => $items, diff --git a/src/Mock/Entity/ActionLogEntry.php b/src/Mock/Entity/ActionLogEntry.php index 9dd0088a..849f84da 100644 --- a/src/Mock/Entity/ActionLogEntry.php +++ b/src/Mock/Entity/ActionLogEntry.php @@ -10,13 +10,14 @@ namespace App\Mock\Entity; +use App\Mock\Repository\ActionLogEntryRepository; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Validator\Constraints as Assert; /** * Class AeosEntity. * - * @ORM\Entity() + * @ORM\Entity(repositoryClass=ActionLogEntryRepository::class) * @ORM\Table(name="mock_action_log_entry") * @ORM\InheritanceType("SINGLE_TABLE") * @ORM\DiscriminatorColumn(name="discr", type="string") @@ -36,9 +37,10 @@ abstract class ActionLogEntry * @var array * * @Assert\NotBlank() - * @ORM\Column(type="json_array") + * @ORM\Column(type="json") */ protected $data; + /** * @var int * diff --git a/src/Mock/Entity/AeosActionLogEntry.php b/src/Mock/Entity/AeosActionLogEntry.php index 75decdcf..fec9eac7 100644 --- a/src/Mock/Entity/AeosActionLogEntry.php +++ b/src/Mock/Entity/AeosActionLogEntry.php @@ -10,13 +10,13 @@ namespace App\Mock\Entity; +use App\Mock\Repository\ActionLogEntryRepository; use Doctrine\ORM\Mapping as ORM; /** * Class AeosActionLogEntry. * - * @ORM\Entity() - * @ ORM\Table() + * @ORM\Entity(repositoryClass=ActionLogEntryRepository::class) */ class AeosActionLogEntry extends ActionLogEntry { diff --git a/src/Mock/Entity/SmsGatewayActionLogEntry.php b/src/Mock/Entity/SmsGatewayActionLogEntry.php index 0d76988a..892e108c 100644 --- a/src/Mock/Entity/SmsGatewayActionLogEntry.php +++ b/src/Mock/Entity/SmsGatewayActionLogEntry.php @@ -10,13 +10,13 @@ namespace App\Mock\Entity; +use App\Mock\Repository\ActionLogEntryRepository; use Doctrine\ORM\Mapping as ORM; /** * Class SmsGatewayActionLogEntry. * - * @ORM\Entity() - * @ ORM\Table() + * @ORM\Entity(repositoryClass=ActionLogEntryRepository::class) */ class SmsGatewayActionLogEntry extends ActionLogEntry { diff --git a/src/Mock/Repository/ActionLogEntryRepository.php b/src/Mock/Repository/ActionLogEntryRepository.php new file mode 100644 index 00000000..cb6b7439 --- /dev/null +++ b/src/Mock/Repository/ActionLogEntryRepository.php @@ -0,0 +1,29 @@ +getEntityManager()->persist($entity); + if ($flush) { + $this->getEntityManager()->flush(); + } + } +} diff --git a/src/Mock/Service/ActionLogManager.php b/src/Mock/Service/ActionLogManager.php index 2467e430..6885f8b2 100644 --- a/src/Mock/Service/ActionLogManager.php +++ b/src/Mock/Service/ActionLogManager.php @@ -11,32 +11,44 @@ namespace App\Mock\Service; use App\Mock\Entity\ActionLogEntry; +use App\Mock\Repository\ActionLogEntryRepository; use Doctrine\Common\Collections\Criteria; use Doctrine\ORM\EntityManagerInterface; +use Doctrine\Persistence\ManagerRegistry; +use Doctrine\Persistence\ObjectRepository; class ActionLogManager { /** @var EntityManagerInterface */ private $manager; - public function __construct(EntityManagerInterface $manager) + private ManagerRegistry $registry; + + public function __construct(EntityManagerInterface $manager, ManagerRegistry $registry) { $this->manager = $manager; + $this->registry = $registry; } public function log(ActionLogEntry $entry) { - $this->manager->persist($entry); - $this->manager->flush(); + $repository = $this->getRepository(get_class($entry)); + assert($repository instanceof ActionLogEntryRepository); + $repository->persist($entry, true); } public function findAll($className, array $criteria = [], array $orderBy = ['createdAt' => Criteria::DESC]) { - return $this->manager->getRepository($className)->findBy($criteria, $orderBy); + return $this->getRepository($className)->findBy($criteria, $orderBy); } public function findOne($className, array $criteria = [], array $orderBy = ['createdAt' => Criteria::DESC]) { - return $this->manager->getRepository($className)->findOneBy($criteria, $orderBy); + return $this->getRepository($className)->findOneBy($criteria, $orderBy); + } + + private function getRepository(string $className, string $persistentManagerName = 'mock'): ObjectRepository + { + return $this->registry->getRepository($className, $persistentManagerName); } } From 536c05fc6db4c071aa14b65fda1b1091d5d1909a Mon Sep 17 00:00:00 2001 From: Mikkel Ricky Date: Wed, 31 Jan 2024 10:33:07 +0100 Subject: [PATCH 2/2] Fixed typo --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index d9695cf1..e6254e4c 100644 --- a/README.md +++ b/README.md @@ -180,9 +180,9 @@ Use this during local testing and development. ```yaml # config/services.local.yaml parameters: - aoes_location: 'http://nginx:8080/mock/aeosws' - aoes_username: null - aoes_password: null + aeos_location: 'http://nginx:8080/mock/aeosws' + aeos_username: null + aeos_password: null ``` * List mock AEOS templates to use when editing templates: