feat(debyltech-cloud): limit customers to Files, Activity and signing

Nothing was group-restricted, so customers saw Dashboard, Photos, Office
and the rest, plus Nextcloud's first-run and promo apps.

- Disable for everyone: firstrunwizard, recommendations, related_resources,
  weather_status, survey_client, support, app_api, contactsinteraction,
  photos. A refused disable now fails the play (occ exits 0 on "can't be
  disabled").
- Restrict dashboard and office to staff. defaultapp=dashboard,files so
  staff land on the dashboard and customers fall through to Files.
- libresign groups_request_sign pinned to staff and asserted in verify.
  LibreSign itself is deliberately NOT group-restricted: that also blocks
  anonymous requests and would break public signing links.
- profile.enabled=false; lookup_server="" (lookup_server_connector
  can't be disabled).
- README: what customers can open.

Checked as a probe customer: apps=files,activity,libresign,text,viewer,
lands in Files, can't request signatures; staff land on Dashboard.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Bastian de Byl
2026-09-28 19:48:39 -04:00
co-authored by Claude Opus 5.5
parent c4fe506860
commit 0cc4c1460e
4 changed files with 106 additions and 1 deletions
@@ -530,6 +530,79 @@
changed_when: "'CHANGED' in debyltech_staff_quota.stdout"
loop: "{{ cloud_debyltech_staff_users }}"
# What a customer can reach. Nextcloud had nothing group-restricted, so every
# customer saw Dashboard, Photos, Office and the rest in the app menu.
#
# Disabled outright -- promos, prompts, or directory-ish features a business
# file-and-signing portal has no use for (contactsinteraction silently adds
# whoever shares with you to your address book; app_api only produces a
# setup warning here). lookup_server_connector cannot be disabled (occ refuses)
# -- the empty `lookup_server` system value below switches it off instead.
#
# Restricted to staff: dashboard and office. `defaultapp` below lists
# dashboard first so staff land there and customers fall through to Files.
#
# NOT restricted: libresign. A group restriction is enforced for anonymous
# requests too (AppManager::checkAppForUser returns false for no user), so it
# would break the public signing links sent to outside signers and to any
# customer already logged in. Who may AUTHOR requests is LibreSign's own
# groups_request_sign, pinned to staff below.
- name: disable unneeded apps in debyltech-cloud
become: true
become_user: "{{ podman_user }}"
ansible.builtin.shell: |
set -o pipefail
occ() { podman exec -u www-data debyltech-cloud php occ "$@"; }
if occ app:list --output=json | python3 -c 'import json,sys; sys.exit(0 if sys.argv[1] in json.load(sys.stdin)["enabled"] else 1)' {{ item | quote }}; then
occ app:disable {{ item | quote }}
echo CHANGED
fi
args:
executable: /bin/bash
register: debyltech_app_disable
changed_when: "'CHANGED' in debyltech_app_disable.stdout"
# occ exits 0 even when it refuses ("can't be disabled").
failed_when: debyltech_app_disable.rc != 0 or "can't be disabled" in debyltech_app_disable.stdout
loop:
- firstrunwizard
- recommendations
- related_resources
- weather_status
- survey_client
- support
- app_api
- contactsinteraction
- photos
- name: restrict staff-only apps in debyltech-cloud
become: true
become_user: "{{ podman_user }}"
ansible.builtin.shell: |
set -o pipefail
occ() { podman exec -u www-data debyltech-cloud php occ "$@"; }
want={{ [cloud_debyltech_staff_group] | to_json | quote }}
if [ "$(occ config:app:get {{ item | quote }} enabled || true)" != "$want" ]; then
occ app:enable --groups {{ cloud_debyltech_staff_group | quote }} {{ item | quote }} >/dev/null
echo CHANGED
fi
args:
executable: /bin/bash
register: debyltech_app_restrict
changed_when: "'CHANGED' in debyltech_app_restrict.stdout"
loop:
- dashboard
- office
- name: pin who may request libresign signatures in debyltech-cloud
become: true
become_user: "{{ podman_user }}"
ansible.builtin.command: >
podman exec -u www-data debyltech-cloud
php occ config:app:set libresign groups_request_sign
--value={{ [cloud_debyltech_staff_group] | to_json | quote }}
register: debyltech_request_sign
changed_when: "'is now set to' in debyltech_request_sign.stdout"
# ---------------------------------------------------------------------------
# Branding: debyltechmail, cloned from skudakmail. custom_apps is a persisted
# bind mount, so only enabling and config need reasserting.
@@ -608,6 +681,13 @@
# than Nextcloud's sample Manual/intro video/Readme and Templates folder.
- {k: skeletondirectory, v: ""}
- {k: templatedirectory, v: ""}
# First ENABLED app wins: staff get the dashboard, and customers -- who
# cannot open it (restricted below) -- fall through to Files.
- {k: defaultapp, v: "dashboard,files"}
# No per-account profile pages.
- {k: profile.enabled, v: "false", t: boolean}
# Never query or publish to the global lookup server (lookup.nextcloud.com).
- {k: lookup_server, v: ""}
- {k: loglevel, v: "2", t: integer}
- {k: log_rotate_size, v: "10485760", t: integer}
- {k: mail_template_class, v: "OCA\\Debyltechmail\\Mail\\DebyltechEMailTemplate"}