Files
computer-playbook/roles/web-app-suitecrm/templates/compose.yml.j2
kevinveenbirkenbach d2abd332f0 fix(web-app-suitecrm): let the external-auth provisioning path create its user
SuiteCRM 8.10.2 tightened User::hasSaveAccess() from return true to is_admin($current_user) for a record without an id, and restrictAdminOnlyFields() now forces status Inactive on such a record. CreateUser::create() runs while the browser is still anonymous, because it is the LDAP and SAML auto-create path, so every FIRST login of a directory account ends in RuntimeException: Not authorized and HTTP 500 on POST /login. The pre-existing administrator is unaffected, which is why one persona passes and one fails in both auth modes. 451f63cbdd carried the role from 8.9.1 to 8.10.2; 8.9.1 exempted a new record from both guards.

The patch raises the admin context around that one save and restores it in a finally, rather than relaxing the guards, which stay closed for every request-driven save. create() has a single caller in its own file, createExternalAuthUser, which sets is_admin 0 and external_auth_only 1 before calling, so the raised context cannot mint an administrator. patch runs with -F0 so a hunk upstream has moved fails the build instead of landing somewhere else.

The patch path is derived once in vars/main.yml and reaches the Dockerfile as a build arg, following the role's existing SUITECRM_ENTRYPOINT_SCRIPT_* shape, so the file name is written once.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
(cherry picked from commit 495d23dbde)

# Conflicts:
#	roles/web-app-suitecrm/vars/main.yml
2026-10-16 13:29:07 +02:00

35 lines
1.9 KiB
Django/Jinja

{% include 'roles/sys-svc-compose/templates/base.yml.j2' %}
{% set service_name = SUITECRM_SERVICE %}
{{ service_name }}:
{{ lookup('template', 'roles/sys-svc-container/templates/build.yml.j2') | indent(4) }}
args:
SUITECRM_BASE_IMAGE: "{{ SUITECRM_BASE_IMAGE }}"
SUITECRM_BASE_VERSION: "{{ SUITECRM_BASE_VERSION }}"
SUITECRM_APP_VERSION: "{{ SUITECRM_APP_VERSION }}"
SUITECRM_PHPREDIS_VERSION: "{{ SUITECRM_PHPREDIS_VERSION }}"
SUITECRM_ENTRYPOINT_SCRIPT_HOST_REL: "{{ SUITECRM_ENTRYPOINT_SCRIPT_HOST_REL }}"
SUITECRM_ENTRYPOINT_SCRIPT_DOCKER: "{{ SUITECRM_ENTRYPOINT_SCRIPT_DOCKER }}"
SUITECRM_EXTERNAL_AUTH_PATCH_HOST_REL: "{{ SUITECRM_EXTERNAL_AUTH_PATCH_HOST_REL }}"
SUITECRM_EXTERNAL_AUTH_PATCH_DOCKER: "{{ SUITECRM_EXTERNAL_AUTH_PATCH_DOCKER }}"
SUITECRM_LDAP_EXTENSION_DIR: "{{ SUITECRM_LDAP_EXTENSION_DIR }}"
SUITECRM_APP_DIR: "{{ SUITECRM_APP_DIR }}"
SUITECRM_PHP_MEMORY_LIMIT: "{{ SUITECRM_PHP_MEMORY_LIMIT }}"
SUITECRM_SEED_DIR: "{{ SUITECRM_SEED_DIR }}"
SUITECRM_WEB_USER: "{{ SUITECRM_WEB_USER }}"
SUITECRM_WEB_GROUP: "{{ SUITECRM_WEB_GROUP }}"
{{ lookup('compose_only', 'container_name', SUITECRM_CONTAINER) }}
{{ lookup('container_image', application_id, 'suitecrm', version=SUITECRM_APP_VERSION) }}
init: true
stop_signal: SIGTERM
stop_grace_period: 30s
{% include 'roles/sys-svc-container/templates/base.yml.j2' %}
{{ lookup('container_extra_hosts', host_alias=true) | indent(4) }}
{{ lookup('container_healthcheck', service_name) | indent(4) }}
{{ lookup('container_ports', ['suitecrm', 'http', DOCKER_BIND_HOST]) | indent(4) }}
{{ lookup('container_depends_on', application_id) | indent(4) }}
{{ lookup('container_networks') | indent(4) }}
{{ lookup('container_volumes', service_name) | indent(4) }}
{{ lookup('compose_volumes') }}
{{ lookup('compose_networks') }}