diff --git a/containers/gitea/gitea.config b/containers/gitea/gitea.config index c31e3dc..572661d 100755 --- a/containers/gitea/gitea.config +++ b/containers/gitea/gitea.config @@ -71,4 +71,12 @@ CFG_GITEA_PORT_2="gitea-service|ssh|random:22|private|tcp|false|false|false|Git CFG_GITEA_AUTH_PROFILE=multi_user CFG_GITEA_ADMIN_USER= CFG_GITEA_ADMIN_EMAIL= -CFG_GITEA_ADMIN_PASSWORD_1=RANDOMIZEDPASSWORD2 +# +# Recorded by the auth tools, not by the installer. Gitea seeds no account at +# install — the first admin is created from the WebUI (Create Account), and the +# adapter writes the username and password here so the credentials card can show +# them. Deliberately empty and unslotted: a generated password would name an +# account that does not exist, and the slot number marks a value the installer +# generates. +# +CFG_GITEA_ADMIN_PASSWORD= diff --git a/containers/invidious/invidious.config b/containers/invidious/invidious.config index ec1ac9a..4285177 100755 --- a/containers/invidious/invidious.config +++ b/containers/invidious/invidious.config @@ -69,4 +69,12 @@ CFG_INVIDIOUS_PORT_1="invidious-service|webui|random:3000|public|tcp|false|true| CFG_INVIDIOUS_AUTH_PROFILE=multi_user CFG_INVIDIOUS_ADMIN_USER= CFG_INVIDIOUS_ADMIN_EMAIL= -CFG_INVIDIOUS_ADMIN_PASSWORD_1=RANDOMIZEDPASSWORD2 +# +# Recorded by the auth tools, not by the installer. Invidious seeds no account at +# install — the first admin is created from the WebUI (Create Account), and the +# adapter writes the username and password here so the credentials card can show +# them. Deliberately empty and unslotted: a generated password would name an +# account that does not exist, and the slot number marks a value the installer +# generates. +# +CFG_INVIDIOUS_ADMIN_PASSWORD= diff --git a/containers/mattermost/mattermost.config b/containers/mattermost/mattermost.config index db12942..bc863dc 100644 --- a/containers/mattermost/mattermost.config +++ b/containers/mattermost/mattermost.config @@ -80,3 +80,11 @@ CFG_MATTERMOST_AUTH_PROFILE=multi_user # Email of the account the WebUI card advertises; set by whoever runs the setup # wizard or the create-account tool, and kept in step by the reset-password tool. CFG_MATTERMOST_ADMIN_EMAIL= +# Written by the reset-password tool when it acts on ADMIN_EMAIL's account, so +# the card can show a working credential. Empty and unslotted on purpose: +# Mattermost seeds no account at install (the first one comes from its own signup +# wizard), so a generated password would name an account that does not exist, and +# the slot number marks a value the installer generates. Without this key +# declared, authPersistCfg has nothing to write to and the reset is never +# recorded. +CFG_MATTERMOST_ADMIN_PASSWORD= diff --git a/containers/rocketchat/docker-compose.yml b/containers/rocketchat/docker-compose.yml index 06ca3ff..d86bc8a 100644 --- a/containers/rocketchat/docker-compose.yml +++ b/containers/rocketchat/docker-compose.yml @@ -34,7 +34,18 @@ services: - MONGO_URL=mongodb://rocketchat-db:27017/rocketchat?replicaSet=rs0 - MONGO_OPLOG_URL=mongodb://rocketchat-db:27017/local?replicaSet=rs0 - DEPLOY_METHOD=docker - - OVERWRITE_SETTING_Show_Setup_Wizard=pending + # Seed the first admin instead of leaving a setup wizard for someone + # to click through. These are honoured only while no admin exists, so + # they are inert on every boot after the first — and marking the + # wizard completed is what stops Rocket.Chat asking anyway. + # + # It also gives LibrePortal a credential to drive the REST API with, + # which is what the Tools tab needs; without a seeded admin there is + # no account to authenticate as. + - OVERWRITE_SETTING_Show_Setup_Wizard=completed + - ADMIN_USERNAME=ROCKETCHAT_ADMIN_USERNAME_DATA #LIBREPORTAL|ROCKETCHAT_ADMIN_USERNAME_TAG|ROCKETCHAT_ADMIN_USERNAME_DATA + - ADMIN_PASS=ROCKETCHAT_ADMIN_PASSWORD_1_DATA #LIBREPORTAL|ROCKETCHAT_ADMIN_PASSWORD_1_TAG|ROCKETCHAT_ADMIN_PASSWORD_1_DATA + - ADMIN_EMAIL=ROCKETCHAT_ADMIN_EMAIL_DATA #LIBREPORTAL|ROCKETCHAT_ADMIN_EMAIL_TAG|ROCKETCHAT_ADMIN_EMAIL_DATA depends_on: - rocketchat-db labels: diff --git a/containers/rocketchat/rocketchat.config b/containers/rocketchat/rocketchat.config index 895915f..9cb6673 100644 --- a/containers/rocketchat/rocketchat.config +++ b/containers/rocketchat/rocketchat.config @@ -25,6 +25,13 @@ CFG_ROCKETCHAT_HEALTHCHECK=true CFG_ROCKETCHAT_AUTHELIA=false CFG_ROCKETCHAT_HEADSCALE=false CFG_ROCKETCHAT_MONITORING=false +# First admin, seeded on the very first boot (Rocket.Chat ignores these once an +# admin exists). Also the credential the Tools tab authenticates with, so +# changing the password here without changing it in the app breaks user +# management — use the reset-password tool, which keeps both in step. +CFG_ROCKETCHAT_ADMIN_USERNAME=admin +CFG_ROCKETCHAT_ADMIN_EMAIL=admin@example.com +CFG_ROCKETCHAT_ADMIN_PASSWORD_1=RANDOMIZEDPASSWORD1 # # ============================================================================= # METADATA @@ -68,3 +75,6 @@ CFG_ROCKETCHAT_NETWORK=default # - description: human-readable description of the service # CFG_ROCKETCHAT_PORT_1="rocketchat-service|webui|random:3000|public|tcp|false|true|true|Web Interface||rocketchat" + +# AUTH_PROFILE = capability tier for the WebUI auth tools (single_password | user_password | multi_user) +CFG_ROCKETCHAT_AUTH_PROFILE=multi_user diff --git a/containers/rocketchat/scripts/rocketchat_auth.sh b/containers/rocketchat/scripts/rocketchat_auth.sh new file mode 100644 index 0000000..33632e4 --- /dev/null +++ b/containers/rocketchat/scripts/rocketchat_auth.sh @@ -0,0 +1,220 @@ +#!/bin/bash + +# Rocket.Chat user management, via its REST API. +# +# Called with curl from the host rather than from inside the container: the +# Rocket.Chat image ships node but no curl or wget, and shelling out to node +# just to make an HTTP request would mean embedding JavaScript in bash for no +# benefit. The base URL is read from ROOT_URL in the deployed compose, which the +# APP_URL tag has already resolved to whatever this install actually serves on — +# https://host behind Traefik, http://ip:port on a LAN-only box. +# +# Authentication uses the admin seeded at install (CFG_ROCKETCHAT_ADMIN_*). +# Rocket.Chat has no local/socket admin path like Mattermost's, so there is no +# way round needing a real account here. + +_rocketchatBaseUrl() { + local compose="${containers_dir}rocketchat/docker-compose.yml" + local url + url=$(runFileOp grep -oP '^\s*-\s*ROOT_URL=\K\S+' "$compose" 2>/dev/null | head -1) + url="${url%%#*}" + printf '%s' "${url%/}" +} + +# Echoes " " on success. Both are needed: Rocket.Chat wants +# them as separate X-User-Id / X-Auth-Token headers on every subsequent call. +_rocketchatLogin() { + local base="$1" + local user="${CFG_ROCKETCHAT_ADMIN_USERNAME:-admin}" + local pass="${CFG_ROCKETCHAT_ADMIN_PASSWORD_1}" + + if [[ -z "$pass" || "$pass" == RANDOMIZEDPASSWORD* ]]; then + isError "No Rocket.Chat admin password in rocketchat.config — cannot authenticate." + return 1 + fi + + local res + res=$(curl -sS -m 20 -X POST "$base/api/v1/login" \ + -H 'Content-Type: application/json' \ + --data-binary "$(printf '{"user":%s,"password":%s}' \ + "$(_rcJson "$user")" "$(_rcJson "$pass")")" 2>&1) + + local id token + id=$(printf '%s' "$res" | python3 -c "import sys,json;d=json.load(sys.stdin);print(d.get('data',{}).get('userId',''))" 2>/dev/null) + token=$(printf '%s' "$res" | python3 -c "import sys,json;d=json.load(sys.stdin);print(d.get('data',{}).get('authToken',''))" 2>/dev/null) + + if [[ -z "$id" || -z "$token" ]]; then + isError "Rocket.Chat admin login failed. Check CFG_ROCKETCHAT_ADMIN_USERNAME / _PASSWORD_1." + return 1 + fi + printf '%s %s' "$id" "$token" +} + +# JSON-encode a bash string so a password containing quotes or backslashes +# cannot break the request body. +_rcJson() { + printf '%s' "$1" | python3 -c "import sys,json;print(json.dumps(sys.stdin.read()))" +} + +# _rocketchatApi [json body] +_rocketchatApi() { + local method="$1" path="$2" body="$3" + local base; base=$(_rocketchatBaseUrl) + [[ -z "$base" ]] && { isError "Could not read Rocket.Chat's ROOT_URL from its compose file."; return 1; } + + local creds; creds=$(_rocketchatLogin "$base") || return 1 + local id="${creds%% *}" token="${creds##* }" + + if [[ -n "$body" ]]; then + curl -sS -m 30 -X "$method" "$base$path" \ + -H "X-User-Id: $id" -H "X-Auth-Token: $token" \ + -H 'Content-Type: application/json' --data-binary "$body" + else + curl -sS -m 30 -X "$method" "$base$path" \ + -H "X-User-Id: $id" -H "X-Auth-Token: $token" + fi +} + +# Rocket.Chat answers 200 with {"success":false,"error":"..."} rather than an +# HTTP error, so success has to be read out of the body. +_rocketchatOk() { + printf '%s' "$1" | python3 -c "import sys,json +try: print('yes' if json.load(sys.stdin).get('success') else 'no') +except Exception: print('no')" 2>/dev/null +} + +_rocketchatError() { + printf '%s' "$1" | python3 -c "import sys,json +try: + d=json.load(sys.stdin); print(d.get('error') or d.get('message') or 'unknown error') +except Exception: print('could not parse the API response')" 2>/dev/null +} + +authAdapter_rocketchat_createUser() { + local email="$1" password="$2" username="$3" isAdmin="$4" + [[ -z "$email" ]] && { isError "An email address is required."; return 1; } + [[ -z "$username" ]] && username="${email%@*}" + [[ -z "$password" ]] && password=$(generateRandomPassword) + + local roles='["user"]' + [[ "$isAdmin" == "true" ]] && roles='["admin","user"]' + + local body out + body=$(printf '{"email":%s,"name":%s,"password":%s,"username":%s,"roles":%s,"joinDefaultChannels":true,"requirePasswordChange":false,"verified":true}' \ + "$(_rcJson "$email")" "$(_rcJson "$username")" "$(_rcJson "$password")" "$(_rcJson "$username")" "$roles") + out=$(_rocketchatApi POST /api/v1/users.create "$body") || return 1 + + [[ "$(_rocketchatOk "$out")" != "yes" ]] && { isError "Creating $email failed: $(_rocketchatError "$out")"; return 1; } + isSuccessful "Rocket.Chat user created — Email: $email — Username: $username — Password: $password" +} + +# Resolve a username or email to Rocket.Chat's internal user id, which is what +# every mutating endpoint wants. +_rocketchatUserId() { + local who="$1" field="username" + [[ "$who" == *@* ]] && field="email" + local out + out=$(_rocketchatApi GET "/api/v1/users.info?${field}=${who}") || return 1 + printf '%s' "$out" | python3 -c "import sys,json +try: print(json.load(sys.stdin).get('user',{}).get('_id','')) +except Exception: print('')" 2>/dev/null +} + +authAdapter_rocketchat_setPassword() { + local who="$1" password="$2" + [[ -z "$who" ]] && { isError "A username or email is required."; return 1; } + [[ -z "$password" ]] && password=$(generateRandomPassword) + + local uid; uid=$(_rocketchatUserId "$who") || return 1 + [[ -z "$uid" ]] && { isError "No Rocket.Chat user '$who'."; return 1; } + + local body out + body=$(printf '{"userId":%s,"data":{"password":%s,"requirePasswordChange":false}}' \ + "$(_rcJson "$uid")" "$(_rcJson "$password")") + out=$(_rocketchatApi POST /api/v1/users.update "$body") || return 1 + + [[ "$(_rocketchatOk "$out")" != "yes" ]] && { isError "Resetting $who failed: $(_rocketchatError "$out")"; return 1; } + + # If this is the account the tools authenticate as, the config has to follow + # or every later tool call fails to log in. + if [[ "$who" == "${CFG_ROCKETCHAT_ADMIN_USERNAME:-admin}" || "$who" == "${CFG_ROCKETCHAT_ADMIN_EMAIL:-}" ]]; then + authPersistCfg rocketchat ADMIN_PASSWORD "$password" + fi + + isSuccessful "Rocket.Chat password set for $who — New password: $password" +} + +authAdapter_rocketchat_listUsers() { + local out + out=$(_rocketchatApi GET '/api/v1/users.list?count=500') || return 1 + [[ "$(_rocketchatOk "$out")" != "yes" ]] && { isError "Listing users failed: $(_rocketchatError "$out")"; return 1; } + + local rendered + rendered=$(printf '%s' "$out" | python3 -c " +import sys, json +d = json.load(sys.stdin) +users = d.get('users', []) +for u in users: + roles = ','.join(u.get('roles') or []) or 'user' + state = '' if u.get('active', True) else ' (deactivated)' + email = (u.get('emails') or [{}])[0].get('address', '-') + print(' %-22s %-30s %s%s' % (u.get('username', '-'), email, roles, state)) +print('LP_TOTAL:%d' % d.get('total', len(users))) +" 2>/dev/null) + + local line total=0 + while IFS= read -r line; do + case "$line" in + LP_TOTAL:*) total="${line#LP_TOTAL:}" ;; + *) [[ -n "$line" ]] && printf '%s\n' "$line" ;; + esac + done <<< "$rendered" + isSuccessful "$total Rocket.Chat account(s)." +} + +# Deactivate, not delete. users.delete purges the account and its messages with +# no undo; setting active=false revokes access and is reversible from the admin +# UI, which is the safer default behind a single button. +authAdapter_rocketchat_deleteUser() { + local who="$1" + [[ -z "$who" ]] && { isError "A username or email is required."; return 1; } + + if [[ "$who" == "${CFG_ROCKETCHAT_ADMIN_USERNAME:-admin}" || "$who" == "${CFG_ROCKETCHAT_ADMIN_EMAIL:-}" ]]; then + isError "Refusing to deactivate '$who' — it is the admin these tools authenticate as." + return 1 + fi + + local uid; uid=$(_rocketchatUserId "$who") || return 1 + [[ -z "$uid" ]] && { isError "No Rocket.Chat user '$who'."; return 1; } + + local out + out=$(_rocketchatApi POST /api/v1/users.setActiveStatus "$(printf '{"userId":%s,"activeStatus":false}' "$(_rcJson "$uid")")") || return 1 + [[ "$(_rocketchatOk "$out")" != "yes" ]] && { isError "Deactivating $who failed: $(_rocketchatError "$out")"; return 1; } + isSuccessful "Rocket.Chat user '$who' deactivated. Re-enable them from Admin → Users." +} + +authAdapter_rocketchat_setAdmin() { + local who="$1" isAdmin="$2" + [[ -z "$who" ]] && { isError "A username or email is required."; return 1; } + local target="false"; [[ "$isAdmin" == "true" ]] && target="true" + + if [[ "$target" == "false" && ( "$who" == "${CFG_ROCKETCHAT_ADMIN_USERNAME:-admin}" || "$who" == "${CFG_ROCKETCHAT_ADMIN_EMAIL:-}" ) ]]; then + isError "Refusing to demote '$who' — it is the admin these tools authenticate as." + return 1 + fi + + local uid; uid=$(_rocketchatUserId "$who") || return 1 + [[ -z "$uid" ]] && { isError "No Rocket.Chat user '$who'."; return 1; } + + local endpoint="/api/v1/roles.addUserToRole" + local body + body=$(printf '{"roleName":"admin","username":%s}' "$(_rcJson "${who%%@*}")") + if [[ "$target" == "false" ]]; then + endpoint="/api/v1/roles.removeUserFromRole" + fi + + local out + out=$(_rocketchatApi POST "$endpoint" "$body") || return 1 + [[ "$(_rocketchatOk "$out")" != "yes" ]] && { isError "Changing admin status for $who failed: $(_rocketchatError "$out")"; return 1; } + isSuccessful "Rocket.Chat user '$who' admin → $target." +} diff --git a/containers/rocketchat/tools/rocketchat.tools.json b/containers/rocketchat/tools/rocketchat.tools.json new file mode 100644 index 0000000..911ca3b --- /dev/null +++ b/containers/rocketchat/tools/rocketchat.tools.json @@ -0,0 +1,105 @@ +{ + "tools": [ + { + "id": "create_account", + "category": "users", + "label": "Create User Account", + "description": "Add a Rocket.Chat user. Tick \"Make admin\" for full rights.", + "icon": "👤", + "fields": [ + { + "name": "email", + "label": "Email", + "type": "text", + "placeholder": "user@example.com", + "required": true + }, + { + "name": "username", + "label": "Username", + "type": "text", + "placeholder": "Leave blank to derive from the email" + }, + { + "name": "password", + "label": "Password", + "type": "password", + "placeholder": "Leave blank to generate" + }, + { + "name": "admin", + "label": "Make admin", + "type": "checkbox", + "default": false + } + ] + }, + { + "id": "list_users", + "category": "users", + "label": "List Users", + "description": "Every account, with roles and whether it is deactivated.", + "icon": "📋", + "fields": [] + }, + { + "id": "reset_password", + "category": "users", + "label": "Reset User Password", + "description": "Set a new password for an existing user.", + "icon": "🔑", + "fields": [ + { + "name": "user", + "label": "Username or email", + "type": "text", + "required": true + }, + { + "name": "password", + "label": "New password", + "type": "password", + "placeholder": "Leave blank to generate" + } + ] + }, + { + "id": "set_admin", + "category": "users", + "label": "Set Admin Status", + "description": "Grant or revoke the admin role.", + "icon": "👑", + "fields": [ + { + "name": "user", + "label": "Username or email", + "type": "text", + "required": true + }, + { + "name": "admin", + "label": "Make admin", + "type": "checkbox", + "default": false + } + ] + }, + { + "id": "deactivate_user", + "category": "users", + "label": "Deactivate User Account", + "description": "Revoke access without deleting messages. Reversible from Admin → Users.", + "icon": "🚫", + "destructive": true, + "confirm": "The user will be signed out and unable to log in.", + "fields": [ + { + "name": "user", + "label": "Username or email", + "type": "text", + "required": true + } + ] + } + ] +} diff --git a/containers/rocketchat/tools/rocketchat_create_account.sh b/containers/rocketchat/tools/rocketchat_create_account.sh new file mode 100644 index 0000000..f377f76 --- /dev/null +++ b/containers/rocketchat/tools/rocketchat_create_account.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +appRocketchatCreateAccount() { + local args="$1" + authAdapterCall rocketchat createUser \ + "$(authToolArg "$args" email)" \ + "$(authToolArg "$args" password)" \ + "$(authToolArg "$args" username)" \ + "$(authToolArg "$args" admin)" +} diff --git a/containers/rocketchat/tools/rocketchat_deactivate_user.sh b/containers/rocketchat/tools/rocketchat_deactivate_user.sh new file mode 100644 index 0000000..cc85a53 --- /dev/null +++ b/containers/rocketchat/tools/rocketchat_deactivate_user.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +appRocketchatDeactivateUser() { + local args="$1" + authAdapterCall rocketchat deleteUser "$(authToolArg "$args" user)" +} diff --git a/containers/rocketchat/tools/rocketchat_list_users.sh b/containers/rocketchat/tools/rocketchat_list_users.sh new file mode 100644 index 0000000..656713e --- /dev/null +++ b/containers/rocketchat/tools/rocketchat_list_users.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +appRocketchatListUsers() { + authAdapterCall rocketchat listUsers +} diff --git a/containers/rocketchat/tools/rocketchat_reset_password.sh b/containers/rocketchat/tools/rocketchat_reset_password.sh new file mode 100644 index 0000000..bede644 --- /dev/null +++ b/containers/rocketchat/tools/rocketchat_reset_password.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +appRocketchatResetPassword() { + local args="$1" + authAdapterCall rocketchat setPassword \ + "$(authToolArg "$args" user)" \ + "$(authToolArg "$args" password)" +} diff --git a/containers/rocketchat/tools/rocketchat_set_admin.sh b/containers/rocketchat/tools/rocketchat_set_admin.sh new file mode 100644 index 0000000..badeaec --- /dev/null +++ b/containers/rocketchat/tools/rocketchat_set_admin.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +appRocketchatSetAdmin() { + local args="$1" + authAdapterCall rocketchat setAdmin \ + "$(authToolArg "$args" user)" \ + "$(authToolArg "$args" admin)" +} diff --git a/docs/guide/upgrade-notes.md b/docs/guide/upgrade-notes.md index 163cb56..f39c626 100644 --- a/docs/guide/upgrade-notes.md +++ b/docs/guide/upgrade-notes.md @@ -160,8 +160,8 @@ are preserved from then on. The convention is now uniform: **if a config key holds a generated value, its name ends in a slot number.** `CFG__DB_PASSWORD` became -`CFG__DB_PASSWORD_1`, `CFG_GITEA_ADMIN_PASSWORD` became -`CFG_GITEA_ADMIN_PASSWORD_1`, and so on — 40 keys across the catalog. An app +`CFG__DB_PASSWORD_1`, `CFG_STALWART_ADMIN_PASSWORD` became +`CFG_STALWART_ADMIN_PASSWORD_1`, and so on — 38 keys across the catalog. An app that needs a second credential of the same kind just adds `_2`; nothing has to be registered, because the tag name is derived from the key. diff --git a/scripts/source/files/arrays/function_manifest.sh b/scripts/source/files/arrays/function_manifest.sh index 38df2d2..af4485d 100644 --- a/scripts/source/files/arrays/function_manifest.sh +++ b/scripts/source/files/arrays/function_manifest.sh @@ -85,6 +85,11 @@ declare -gA LP_FN_MAP=( [_appReqHasDomain]="checks/requirements/check_app_install.sh" [_appReqServiceInstalled]="checks/requirements/check_app_install.sh" [_appReqServiceMsg]="checks/requirements/check_app_install.sh" + [appRocketchatCreateAccount]="rocketchat/tools/rocketchat_create_account.sh" + [appRocketchatDeactivateUser]="rocketchat/tools/rocketchat_deactivate_user.sh" + [appRocketchatListUsers]="rocketchat/tools/rocketchat_list_users.sh" + [appRocketchatResetPassword]="rocketchat/tools/rocketchat_reset_password.sh" + [appRocketchatSetAdmin]="rocketchat/tools/rocketchat_set_admin.sh" [appScanAvailable]="app/app_scan_available.sh" [appSetupComposeTags_gluetun]="gluetun/scripts/gluetun_compose_tags.sh" [appSetupComposeTags_matrix]="matrix/scripts/matrix_compose_tags.sh" @@ -173,6 +178,11 @@ declare -gA LP_FN_MAP=( [authAdapter_nextcloud_listUsers]="nextcloud/scripts/nextcloud_auth.sh" [authAdapter_nextcloud_setAdmin]="nextcloud/scripts/nextcloud_auth.sh" [authAdapter_nextcloud_setPassword]="nextcloud/scripts/nextcloud_auth.sh" + [authAdapter_rocketchat_createUser]="rocketchat/scripts/rocketchat_auth.sh" + [authAdapter_rocketchat_deleteUser]="rocketchat/scripts/rocketchat_auth.sh" + [authAdapter_rocketchat_listUsers]="rocketchat/scripts/rocketchat_auth.sh" + [authAdapter_rocketchat_setAdmin]="rocketchat/scripts/rocketchat_auth.sh" + [authAdapter_rocketchat_setPassword]="rocketchat/scripts/rocketchat_auth.sh" [authAdapter_traefik_setPassword]="traefik/scripts/traefik_auth.sh" [authelia_install_post]="authelia/scripts/authelia_install_hooks.sh" [authelia_install_post_compose]="authelia/scripts/authelia_install_hooks.sh" @@ -779,6 +789,7 @@ declare -gA LP_FN_MAP=( [processBcryptPassword]="config/password/bcrypt/password_process_bcrypt.sh" [prometheus_install_post_compose]="prometheus/scripts/prometheus_install_hooks.sh" [prometheus_install_post_start]="prometheus/scripts/prometheus_install_hooks.sh" + [_rcJson]="rocketchat/scripts/rocketchat_auth.sh" [readTaskField]="task/crontab_task_processor.sh" [reclaimDockerSpace]="cli/commands/system/cli_system_commands.sh" [reconcileConfigFile]="config/core/variables/config_scan_variables.sh" @@ -848,8 +859,14 @@ declare -gA LP_FN_MAP=( [restoreFirstRunBulk]="restore/restore_first_run.sh" [restoreFirstRunDiscover]="restore/restore_first_run.sh" [restorePickSnapshot]="restore/restore_app_pick.sh" + [_rocketchatApi]="rocketchat/scripts/rocketchat_auth.sh" + [_rocketchatBaseUrl]="rocketchat/scripts/rocketchat_auth.sh" + [_rocketchatError]="rocketchat/scripts/rocketchat_auth.sh" [rocketchat_install_post]="rocketchat/scripts/rocketchat_install_hooks.sh" [rocketchat_install_post_start]="rocketchat/scripts/rocketchat_install_hooks.sh" + [_rocketchatLogin]="rocketchat/scripts/rocketchat_auth.sh" + [_rocketchatOk]="rocketchat/scripts/rocketchat_auth.sh" + [_rocketchatUserId]="rocketchat/scripts/rocketchat_auth.sh" [runAppCfg]="docker/command/run_privileged.sh" [runAsManager]="docker/command/run_privileged.sh" [runBackupOp]="docker/command/run_privileged.sh" @@ -1171,6 +1188,11 @@ declare -gA LP_FN_ROOT=( [_appReqHasDomain]="scripts" [_appReqServiceInstalled]="scripts" [_appReqServiceMsg]="scripts" + [appRocketchatCreateAccount]="containers" + [appRocketchatDeactivateUser]="containers" + [appRocketchatListUsers]="containers" + [appRocketchatResetPassword]="containers" + [appRocketchatSetAdmin]="containers" [appScanAvailable]="scripts" [appSetupComposeTags_gluetun]="containers" [appSetupComposeTags_matrix]="containers" @@ -1259,6 +1281,11 @@ declare -gA LP_FN_ROOT=( [authAdapter_nextcloud_listUsers]="containers" [authAdapter_nextcloud_setAdmin]="containers" [authAdapter_nextcloud_setPassword]="containers" + [authAdapter_rocketchat_createUser]="containers" + [authAdapter_rocketchat_deleteUser]="containers" + [authAdapter_rocketchat_listUsers]="containers" + [authAdapter_rocketchat_setAdmin]="containers" + [authAdapter_rocketchat_setPassword]="containers" [authAdapter_traefik_setPassword]="containers" [authelia_install_post]="containers" [authelia_install_post_compose]="containers" @@ -1865,6 +1892,7 @@ declare -gA LP_FN_ROOT=( [processBcryptPassword]="scripts" [prometheus_install_post_compose]="containers" [prometheus_install_post_start]="containers" + [_rcJson]="containers" [readTaskField]="scripts" [reclaimDockerSpace]="scripts" [reconcileConfigFile]="scripts" @@ -1934,8 +1962,14 @@ declare -gA LP_FN_ROOT=( [restoreFirstRunBulk]="scripts" [restoreFirstRunDiscover]="scripts" [restorePickSnapshot]="scripts" + [_rocketchatApi]="containers" + [_rocketchatBaseUrl]="containers" + [_rocketchatError]="containers" [rocketchat_install_post]="containers" [rocketchat_install_post_start]="containers" + [_rocketchatLogin]="containers" + [_rocketchatOk]="containers" + [_rocketchatUserId]="containers" [runAppCfg]="scripts" [runAsManager]="scripts" [runBackupOp]="scripts" @@ -2292,6 +2326,11 @@ _appPostStartIntegrations() { unset -f _appPostStartIntegrations; __lpAutoload " _appReqHasDomain() { unset -f _appReqHasDomain; __lpAutoload "${install_scripts_dir}checks/requirements/check_app_install.sh"; _appReqHasDomain "$@"; } _appReqServiceInstalled() { unset -f _appReqServiceInstalled; __lpAutoload "${install_scripts_dir}checks/requirements/check_app_install.sh"; _appReqServiceInstalled "$@"; } _appReqServiceMsg() { unset -f _appReqServiceMsg; __lpAutoload "${install_scripts_dir}checks/requirements/check_app_install.sh"; _appReqServiceMsg "$@"; } +appRocketchatCreateAccount() { unset -f appRocketchatCreateAccount; __lpAutoload "${install_containers_dir}rocketchat/tools/rocketchat_create_account.sh"; appRocketchatCreateAccount "$@"; } +appRocketchatDeactivateUser() { unset -f appRocketchatDeactivateUser; __lpAutoload "${install_containers_dir}rocketchat/tools/rocketchat_deactivate_user.sh"; appRocketchatDeactivateUser "$@"; } +appRocketchatListUsers() { unset -f appRocketchatListUsers; __lpAutoload "${install_containers_dir}rocketchat/tools/rocketchat_list_users.sh"; appRocketchatListUsers "$@"; } +appRocketchatResetPassword() { unset -f appRocketchatResetPassword; __lpAutoload "${install_containers_dir}rocketchat/tools/rocketchat_reset_password.sh"; appRocketchatResetPassword "$@"; } +appRocketchatSetAdmin() { unset -f appRocketchatSetAdmin; __lpAutoload "${install_containers_dir}rocketchat/tools/rocketchat_set_admin.sh"; appRocketchatSetAdmin "$@"; } appScanAvailable() { unset -f appScanAvailable; __lpAutoload "${install_scripts_dir}app/app_scan_available.sh"; appScanAvailable "$@"; } appSetupComposeTags_gluetun() { unset -f appSetupComposeTags_gluetun; __lpAutoload "${install_containers_dir}gluetun/scripts/gluetun_compose_tags.sh"; appSetupComposeTags_gluetun "$@"; } appSetupComposeTags_matrix() { unset -f appSetupComposeTags_matrix; __lpAutoload "${install_containers_dir}matrix/scripts/matrix_compose_tags.sh"; appSetupComposeTags_matrix "$@"; } @@ -2380,6 +2419,11 @@ authAdapter_nextcloud_deleteUser() { unset -f authAdapter_nextcloud_deleteUser; authAdapter_nextcloud_listUsers() { unset -f authAdapter_nextcloud_listUsers; __lpAutoload "${install_containers_dir}nextcloud/scripts/nextcloud_auth.sh"; authAdapter_nextcloud_listUsers "$@"; } authAdapter_nextcloud_setAdmin() { unset -f authAdapter_nextcloud_setAdmin; __lpAutoload "${install_containers_dir}nextcloud/scripts/nextcloud_auth.sh"; authAdapter_nextcloud_setAdmin "$@"; } authAdapter_nextcloud_setPassword() { unset -f authAdapter_nextcloud_setPassword; __lpAutoload "${install_containers_dir}nextcloud/scripts/nextcloud_auth.sh"; authAdapter_nextcloud_setPassword "$@"; } +authAdapter_rocketchat_createUser() { unset -f authAdapter_rocketchat_createUser; __lpAutoload "${install_containers_dir}rocketchat/scripts/rocketchat_auth.sh"; authAdapter_rocketchat_createUser "$@"; } +authAdapter_rocketchat_deleteUser() { unset -f authAdapter_rocketchat_deleteUser; __lpAutoload "${install_containers_dir}rocketchat/scripts/rocketchat_auth.sh"; authAdapter_rocketchat_deleteUser "$@"; } +authAdapter_rocketchat_listUsers() { unset -f authAdapter_rocketchat_listUsers; __lpAutoload "${install_containers_dir}rocketchat/scripts/rocketchat_auth.sh"; authAdapter_rocketchat_listUsers "$@"; } +authAdapter_rocketchat_setAdmin() { unset -f authAdapter_rocketchat_setAdmin; __lpAutoload "${install_containers_dir}rocketchat/scripts/rocketchat_auth.sh"; authAdapter_rocketchat_setAdmin "$@"; } +authAdapter_rocketchat_setPassword() { unset -f authAdapter_rocketchat_setPassword; __lpAutoload "${install_containers_dir}rocketchat/scripts/rocketchat_auth.sh"; authAdapter_rocketchat_setPassword "$@"; } authAdapter_traefik_setPassword() { unset -f authAdapter_traefik_setPassword; __lpAutoload "${install_containers_dir}traefik/scripts/traefik_auth.sh"; authAdapter_traefik_setPassword "$@"; } authelia_install_post() { unset -f authelia_install_post; __lpAutoload "${install_containers_dir}authelia/scripts/authelia_install_hooks.sh"; authelia_install_post "$@"; } authelia_install_post_compose() { unset -f authelia_install_post_compose; __lpAutoload "${install_containers_dir}authelia/scripts/authelia_install_hooks.sh"; authelia_install_post_compose "$@"; } @@ -2986,6 +3030,7 @@ portUpdateComposeTags() { unset -f portUpdateComposeTags; __lpAutoload "${instal processBcryptPassword() { unset -f processBcryptPassword; __lpAutoload "${install_scripts_dir}config/password/bcrypt/password_process_bcrypt.sh"; processBcryptPassword "$@"; } prometheus_install_post_compose() { unset -f prometheus_install_post_compose; __lpAutoload "${install_containers_dir}prometheus/scripts/prometheus_install_hooks.sh"; prometheus_install_post_compose "$@"; } prometheus_install_post_start() { unset -f prometheus_install_post_start; __lpAutoload "${install_containers_dir}prometheus/scripts/prometheus_install_hooks.sh"; prometheus_install_post_start "$@"; } +_rcJson() { unset -f _rcJson; __lpAutoload "${install_containers_dir}rocketchat/scripts/rocketchat_auth.sh"; _rcJson "$@"; } readTaskField() { unset -f readTaskField; __lpAutoload "${install_scripts_dir}task/crontab_task_processor.sh"; readTaskField "$@"; } reclaimDockerSpace() { unset -f reclaimDockerSpace; __lpAutoload "${install_scripts_dir}cli/commands/system/cli_system_commands.sh"; reclaimDockerSpace "$@"; } reconcileConfigFile() { unset -f reconcileConfigFile; __lpAutoload "${install_scripts_dir}config/core/variables/config_scan_variables.sh"; reconcileConfigFile "$@"; } @@ -3055,8 +3100,14 @@ restoreFilesRehydratePreStart() { unset -f restoreFilesRehydratePreStart; __lpAu restoreFirstRunBulk() { unset -f restoreFirstRunBulk; __lpAutoload "${install_scripts_dir}restore/restore_first_run.sh"; restoreFirstRunBulk "$@"; } restoreFirstRunDiscover() { unset -f restoreFirstRunDiscover; __lpAutoload "${install_scripts_dir}restore/restore_first_run.sh"; restoreFirstRunDiscover "$@"; } restorePickSnapshot() { unset -f restorePickSnapshot; __lpAutoload "${install_scripts_dir}restore/restore_app_pick.sh"; restorePickSnapshot "$@"; } +_rocketchatApi() { unset -f _rocketchatApi; __lpAutoload "${install_containers_dir}rocketchat/scripts/rocketchat_auth.sh"; _rocketchatApi "$@"; } +_rocketchatBaseUrl() { unset -f _rocketchatBaseUrl; __lpAutoload "${install_containers_dir}rocketchat/scripts/rocketchat_auth.sh"; _rocketchatBaseUrl "$@"; } +_rocketchatError() { unset -f _rocketchatError; __lpAutoload "${install_containers_dir}rocketchat/scripts/rocketchat_auth.sh"; _rocketchatError "$@"; } rocketchat_install_post() { unset -f rocketchat_install_post; __lpAutoload "${install_containers_dir}rocketchat/scripts/rocketchat_install_hooks.sh"; rocketchat_install_post "$@"; } rocketchat_install_post_start() { unset -f rocketchat_install_post_start; __lpAutoload "${install_containers_dir}rocketchat/scripts/rocketchat_install_hooks.sh"; rocketchat_install_post_start "$@"; } +_rocketchatLogin() { unset -f _rocketchatLogin; __lpAutoload "${install_containers_dir}rocketchat/scripts/rocketchat_auth.sh"; _rocketchatLogin "$@"; } +_rocketchatOk() { unset -f _rocketchatOk; __lpAutoload "${install_containers_dir}rocketchat/scripts/rocketchat_auth.sh"; _rocketchatOk "$@"; } +_rocketchatUserId() { unset -f _rocketchatUserId; __lpAutoload "${install_containers_dir}rocketchat/scripts/rocketchat_auth.sh"; _rocketchatUserId "$@"; } runAppCfg() { unset -f runAppCfg; __lpAutoload "${install_scripts_dir}docker/command/run_privileged.sh"; runAppCfg "$@"; } runAsManager() { unset -f runAsManager; __lpAutoload "${install_scripts_dir}docker/command/run_privileged.sh"; runAsManager "$@"; } runBackupOp() { unset -f runBackupOp; __lpAutoload "${install_scripts_dir}docker/command/run_privileged.sh"; runBackupOp "$@"; } diff --git a/scripts/webui/data/generators/categories/webui_create_app_field_mappings.sh b/scripts/webui/data/generators/categories/webui_create_app_field_mappings.sh index e296b31..5ee0f11 100755 --- a/scripts/webui/data/generators/categories/webui_create_app_field_mappings.sh +++ b/scripts/webui/data/generators/categories/webui_create_app_field_mappings.sh @@ -462,13 +462,25 @@ PORTEOF "tooltip": "Object store root password (auto-generated), shared by MinIO and the bucket-creation job.", "advanced": true }, + "ROCKETCHAT_ADMIN_PASSWORD_1": { + "category": "general", + "label": "Rocket.Chat Admin Password", + "type": "password", + "tooltip": "Password for the admin account seeded on install" + }, + "ADMIN_USER": { + "category": "general", + "label": "Admin Username", + "type": "text", + "tooltip": "Username of the admin account the credentials card shows" + }, "ADGUARD_ADMIN_PASSWORD_1": { "category": "general", "label": "AdGuard Admin Password", "type": "password", "tooltip": "AdGuard Home admin password (auto-generated)" }, - "GITEA_ADMIN_PASSWORD_1": { + "GITEA_ADMIN_PASSWORD": { "category": "general", "label": "Gitea Admin Password", "type": "password", @@ -487,7 +499,7 @@ PORTEOF "type": "password", "tooltip": "Password protecting the Headscale endpoint" }, - "INVIDIOUS_ADMIN_PASSWORD_1": { + "INVIDIOUS_ADMIN_PASSWORD": { "category": "general", "label": "Invidious Admin Password", "type": "password",