Compare commits

..

2 Commits

Author SHA1 Message Date
librelad
4b6b05db81 fix(rocketchat): correct the roles call, satisfy the password policy, add enable
Three things running the tools against a live instance exposed:

- roles.addUserToRole takes roleId + username and nothing else. Passing roleName
  fails schema validation with "must NOT have additional properties", and
  roleId + userId is refused for a missing username. Set admin was broken in
  both directions.

- Rocket.Chat enables a password policy by default demanding lower, upper, digit
  AND special at 14+ characters, while generateRandomPassword is alphanumeric.
  Reset failed with "does not meet the server's password policy". Notably
  users.create does NOT enforce the policy, which is why creating an account
  worked and resetting the same account's password did not — an inconsistency
  worth knowing about rather than guessing at. Generated passwords now carry one
  character from each class appended, leaving the generated entropy untouched.

- Deactivation had no counterpart, so "reversible from Admin → Users" was only
  true if you left the WebUI. Adds an Enable tool, matching Stoat's.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 21:39:42 +01:00
librelad
71bc78df27 feat(rocketchat,stoat): user-management tools, sized to what each app supports
Rocket.Chat gets the full five — create, list, reset password, set admin,
deactivate — over its REST API. Two supporting changes make that possible:

  - The first admin is now seeded at install from CFG_ROCKETCHAT_ADMIN_*, and
    the setup wizard is marked completed. Previously the install left a wizard
    for someone to click through, and, more to the point, left no account for
    the tools to authenticate as. Rocket.Chat honours those env vars only while
    no admin exists, so they are inert on every later boot.

  - Calls go out with curl from the host rather than from inside the container.
    The image ships node but no curl, and the base URL is read from the deployed
    compose's ROOT_URL, which the APP_URL tag has already resolved to whatever
    this install actually serves on.

Stoat gets three — list, disable, enable — and the adapter says plainly why it
stops there. Password reset would mean reimplementing its argon2 hashing in
bash, where being subtly wrong writes a hash nothing can verify and locks the
account out with no error at the time. "Make admin" would misrepresent the
model: Stoat's permissions are per-server bitfields on server_members, not a
global flag. Its service containers are distroless with no shell and it has no
admin CLI, so the database is the only durable handle.

Deactivate rather than delete in both, and the destructive actions refuse to
touch the account the tools authenticate as.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 21:32:45 +01:00
10 changed files with 301 additions and 8 deletions

View File

@ -50,6 +50,18 @@ _rocketchatLogin() {
printf '%s %s' "$id" "$token"
}
# Rocket.Chat enables a password policy by default that demands lower, upper,
# digit AND special, at 14+ characters. generateRandomPassword is alphanumeric,
# so a generated password is rejected by users.update with "does not meet the
# server's password policy" — note that users.create does NOT enforce it, which
# is why creating worked while resetting did not.
#
# Appending one character from each class guarantees compliance without
# weakening anything: the entropy of the generated part is untouched.
_rocketchatPassword() {
printf '%s%s' "$(generateRandomPassword)" 'aZ7#'
}
# JSON-encode a bash string so a password containing quotes or backslashes
# cannot break the request body.
_rcJson() {
@ -94,7 +106,7 @@ 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)
[[ -z "$password" ]] && password=$(_rocketchatPassword)
local roles='["user"]'
[[ "$isAdmin" == "true" ]] && roles='["admin","user"]'
@ -120,10 +132,20 @@ try: print(json.load(sys.stdin).get('user',{}).get('_id',''))
except Exception: print('')" 2>/dev/null
}
_rocketchatUsernameOf() {
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('username',''))
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)
[[ -z "$password" ]] && password=$(_rocketchatPassword)
local uid; uid=$(_rocketchatUserId "$who") || return 1
[[ -z "$uid" ]] && { isError "No Rocket.Chat user '$who'."; return 1; }
@ -193,6 +215,21 @@ authAdapter_rocketchat_deleteUser() {
isSuccessful "Rocket.Chat user '$who' deactivated. Re-enable them from Admin → Users."
}
# The counterpart to deleteUser. Deactivation is only a safe default if undoing
# it is equally easy — otherwise the "reversible" claim is theoretical.
authAdapter_rocketchat_enableUser() {
local who="$1"
[[ -z "$who" ]] && { isError "A username or email is required."; return 1; }
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":true}' "$(_rcJson "$uid")")") || return 1
[[ "$(_rocketchatOk "$out")" != "yes" ]] && { isError "Enabling $who failed: $(_rocketchatError "$out")"; return 1; }
isSuccessful "Rocket.Chat user '$who' re-enabled."
}
authAdapter_rocketchat_setAdmin() {
local who="$1" isAdmin="$2"
[[ -z "$who" ]] && { isError "A username or email is required."; return 1; }
@ -203,15 +240,21 @@ authAdapter_rocketchat_setAdmin() {
return 1
fi
local uid; uid=$(_rocketchatUserId "$who") || return 1
[[ -z "$uid" ]] && { isError "No Rocket.Chat user '$who'."; return 1; }
# The endpoint takes roleId + username, and nothing else: passing roleName
# fails schema validation with "must NOT have additional properties", and
# roleId + userId is rejected for a missing username. For built-in roles the
# id and the name happen to be the same string ("admin").
#
# username is resolved from the account rather than assumed from the input,
# so passing an email works here too.
local username
username=$(_rocketchatUsernameOf "$who") || return 1
[[ -z "$username" ]] && { isError "No Rocket.Chat user '$who'."; return 1; }
local endpoint="/api/v1/roles.addUserToRole"
[[ "$target" == "false" ]] && endpoint="/api/v1/roles.removeUserFromRole"
local body
body=$(printf '{"roleName":"admin","username":%s}' "$(_rcJson "${who%%@*}")")
if [[ "$target" == "false" ]]; then
endpoint="/api/v1/roles.removeUserFromRole"
fi
body=$(printf '{"roleId":"admin","username":%s}' "$(_rcJson "$username")")
local out
out=$(_rocketchatApi POST "$endpoint" "$body") || return 1

View File

@ -100,6 +100,21 @@
"required": true
}
]
},
{
"id": "enable_user",
"category": "users",
"label": "Enable User Account",
"description": "Undo a deactivation and let the account sign in again.",
"icon": "✅",
"fields": [
{
"name": "user",
"label": "Username or email",
"type": "text",
"required": true
}
]
}
]
}

View File

@ -0,0 +1,6 @@
#!/bin/bash
appRocketchatEnableUser() {
local args="$1"
authAdapterCall rocketchat enableUser "$(authToolArg "$args" user)"
}

View File

@ -0,0 +1,121 @@
#!/bin/bash
# Stoat user management.
#
# Deliberately the thinnest set of the four, because Stoat gives the least to
# work with. Its service containers are distroless (no shell), it has no admin
# CLI, and its admin HTTP surface is not a stable documented API — so the only
# durable handles are the public auth endpoint and the database itself.
#
# What that rules out, and why:
#
# Password reset — Stoat hashes with argon2 through its own authifier layer.
# Reimplementing that in bash means matching its parameters exactly, and
# getting them subtly wrong writes a hash nothing can verify, silently locking
# the account out with no error at the time. Users reset their own password
# through the app; that path is not worth counterfeiting from a button.
#
# Role/permission editing — Stoat's permissions are per-server bitfields held
# on server_members, not a global admin flag. There is no single "make admin"
# to toggle; it is a server-by-server concept the app models properly and a
# button would misrepresent.
#
# What is left is genuinely useful and genuinely safe: see who exists, and turn
# an account off or back on.
_stoatMongo() {
runFileOp docker exec -i stoat-database mongosh revolt --quiet --eval "$1" 2>&1
}
_stoatMongoFailed() {
local out="$1" what="$2"
# mongosh reports failures as a thrown error rather than a non-zero exit in
# --eval mode, so match on the text.
if [[ "$out" == *MongoServerError* || "$out" == *ReferenceError* || "$out" == *TypeError* ]]; then
isError "$what failed: $(printf '%s' "$out" | head -2 | tr '\n' ' ')"
return 0
fi
return 1
}
# Accounts and profiles are separate collections sharing an _id: `accounts` holds
# the login (email, disabled flag), `users` the profile (username, discriminator).
# Neither alone is a useful view, so join them.
authAdapter_stoat_listUsers() {
local out
out=$(_stoatMongo '
const users = db.users.find({}, {username:1, discriminator:1, display_name:1}).toArray();
const byId = {};
db.accounts.find({}, {email:1, disabled:1}).toArray().forEach(a => byId[a._id] = a);
users.forEach(u => {
const a = byId[u._id] || {};
const handle = u.username + (u.discriminator ? "#" + u.discriminator : "");
const state = a.disabled ? " (disabled)" : "";
print("LP_USER\t" + handle + "\t" + (a.email || "-") + "\t" + (u.display_name || "-") + state);
});
print("LP_TOTAL:" + users.length);
')
_stoatMongoFailed "$out" "Listing users" && return 1
local line total=0
while IFS= read -r line; do
case "$line" in
LP_USER*) IFS=$'\t' read -r _ handle email display <<< "$line"
printf ' %-24s %-30s %s\n' "$handle" "$email" "$display" ;;
LP_TOTAL:*) total="${line#LP_TOTAL:}" ;;
esac
done <<< "$out"
if [[ "$total" == "0" ]]; then
isNotice "No Stoat accounts yet — the first person to register becomes the instance owner."
return 0
fi
isSuccessful "$total Stoat account(s)."
}
# Disabling is Stoat's own reversible state, not a hand-rolled hack: the account
# stays intact and its messages stay readable, the holder just cannot log in.
_stoatSetDisabled() {
local who="$1" disabled="$2" verb="$3"
[[ -z "$who" ]] && { isError "A username or email is required."; return 1; }
local out
out=$(_stoatMongoWho "$who" "$disabled")
_stoatMongoFailed "$out" "$verb $who" && return 1
[[ "$out" == *LP_MISSING* ]] && { isError "No Stoat account matching '$who'."; return 1; }
[[ "$out" != *LP_OK* ]] && { isError "$verb $who failed: $out"; return 1; }
return 0
}
# Kept separate so the account lookup (by email on `accounts`, or by username on
# `users`) lives in one place.
_stoatMongoWho() {
local who="$1" disabled="$2"
_stoatMongo "
const who = $(printf '%s' "$who" | python3 -c 'import sys,json;print(json.dumps(sys.stdin.read()))');
let acct = null;
if (who.includes('@')) {
acct = db.accounts.findOne({email: who});
} else {
const u = db.users.findOne({username: who});
if (u) acct = db.accounts.findOne({_id: u._id});
}
if (!acct) { print('LP_MISSING'); } else {
db.accounts.updateOne({_id: acct._id}, {\$set: {disabled: $disabled}});
print('LP_OK');
}
"
}
authAdapter_stoat_deleteUser() {
local who="$1"
_stoatSetDisabled "$who" "true" "Disabling" || return 1
isSuccessful "Stoat account '$who' disabled — they can no longer sign in. Re-enable it with the Enable tool."
isNotice "Their existing sessions are not revoked by this; restart the app to force everyone to re-authenticate."
}
authAdapter_stoat_enableUser() {
local who="$1"
_stoatSetDisabled "$who" "false" "Enabling" || return 1
isSuccessful "Stoat account '$who' re-enabled."
}

View File

@ -94,3 +94,8 @@ CFG_STOAT_PORT_1="stoat-caddy|webui|random:80|public|tcp|false|true|true|Web Int
# external port would be advertised wrongly and voice would fail to connect.
# Not Traefik-managed — WebRTC is not HTTP.
CFG_STOAT_PORT_2="stoat-livekit|voice-tcp|7881:7881|public|tcp|false|false|false|LiveKit voice/video (TCP fallback)|"
# AUTH_PROFILE = capability tier for the WebUI auth tools (single_password | user_password | multi_user)
# Stoat exposes no safe way to set a password or grant a role from outside the
# app, so these tools list and enable/disable only — see scripts/stoat_auth.sh.
CFG_STOAT_AUTH_PROFILE=multi_user

View File

@ -0,0 +1,44 @@
{
"tools": [
{
"id": "list_users",
"category": "users",
"label": "List Users",
"description": "Every Stoat account, with its email and whether it is disabled.",
"icon": "📋",
"fields": []
},
{
"id": "disable_user",
"category": "users",
"label": "Disable User Account",
"description": "Block sign-in without deleting the account or its messages. Reversible.",
"icon": "🚫",
"destructive": true,
"confirm": "The user will not be able to sign in again until re-enabled.",
"fields": [
{
"name": "user",
"label": "Username or email",
"type": "text",
"required": true
}
]
},
{
"id": "enable_user",
"category": "users",
"label": "Enable User Account",
"description": "Undo a disable and let the account sign in again.",
"icon": "✅",
"fields": [
{
"name": "user",
"label": "Username or email",
"type": "text",
"required": true
}
]
}
]
}

View File

@ -0,0 +1,6 @@
#!/bin/bash
appStoatDisableUser() {
local args="$1"
authAdapterCall stoat deleteUser "$(authToolArg "$args" user)"
}

View File

@ -0,0 +1,6 @@
#!/bin/bash
appStoatEnableUser() {
local args="$1"
authAdapterCall stoat enableUser "$(authToolArg "$args" user)"
}

View File

@ -0,0 +1,5 @@
#!/bin/bash
appStoatListUsers() {
authAdapterCall stoat listUsers
}

View File

@ -87,6 +87,7 @@ declare -gA LP_FN_MAP=(
[_appReqServiceMsg]="checks/requirements/check_app_install.sh"
[appRocketchatCreateAccount]="rocketchat/tools/rocketchat_create_account.sh"
[appRocketchatDeactivateUser]="rocketchat/tools/rocketchat_deactivate_user.sh"
[appRocketchatEnableUser]="rocketchat/tools/rocketchat_enable_user.sh"
[appRocketchatListUsers]="rocketchat/tools/rocketchat_list_users.sh"
[appRocketchatResetPassword]="rocketchat/tools/rocketchat_reset_password.sh"
[appRocketchatSetAdmin]="rocketchat/tools/rocketchat_set_admin.sh"
@ -100,6 +101,9 @@ declare -gA LP_FN_MAP=(
[appSetupComposeTags_vaultwarden]="vaultwarden/scripts/vaultwarden_compose_tags.sh"
[appSetupComposeTags_wireguard]="wireguard/scripts/wireguard_compose_tags.sh"
[appStatus]="app/app_status.sh"
[appStoatDisableUser]="stoat/tools/stoat_disable_user.sh"
[appStoatEnableUser]="stoat/tools/stoat_enable_user.sh"
[appStoatListUsers]="stoat/tools/stoat_list_users.sh"
[appTraefikExtraMiddlewares_onlyoffice]="onlyoffice/scripts/onlyoffice_traefik.sh"
[appTraefikResetPassword]="traefik/tools/traefik_reset_password.sh"
[appTraefikSkipsDefaultMiddleware_onlyoffice]="onlyoffice/scripts/onlyoffice_traefik.sh"
@ -180,9 +184,13 @@ declare -gA LP_FN_MAP=(
[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_enableUser]="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_stoat_deleteUser]="stoat/scripts/stoat_auth.sh"
[authAdapter_stoat_enableUser]="stoat/scripts/stoat_auth.sh"
[authAdapter_stoat_listUsers]="stoat/scripts/stoat_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"
@ -866,7 +874,9 @@ declare -gA LP_FN_MAP=(
[rocketchat_install_post_start]="rocketchat/scripts/rocketchat_install_hooks.sh"
[_rocketchatLogin]="rocketchat/scripts/rocketchat_auth.sh"
[_rocketchatOk]="rocketchat/scripts/rocketchat_auth.sh"
[_rocketchatPassword]="rocketchat/scripts/rocketchat_auth.sh"
[_rocketchatUserId]="rocketchat/scripts/rocketchat_auth.sh"
[_rocketchatUsernameOf]="rocketchat/scripts/rocketchat_auth.sh"
[runAppCfg]="docker/command/run_privileged.sh"
[runAsManager]="docker/command/run_privileged.sh"
[runBackupOp]="docker/command/run_privileged.sh"
@ -935,6 +945,10 @@ declare -gA LP_FN_MAP=(
[stoat_install_post_compose]="stoat/scripts/stoat_install_hooks.sh"
[stoat_install_post_start]="stoat/scripts/stoat_install_hooks.sh"
[stoat_install_pre]="stoat/scripts/stoat_install_hooks.sh"
[_stoatMongo]="stoat/scripts/stoat_auth.sh"
[_stoatMongoFailed]="stoat/scripts/stoat_auth.sh"
[_stoatMongoWho]="stoat/scripts/stoat_auth.sh"
[_stoatSetDisabled]="stoat/scripts/stoat_auth.sh"
[_stoatWriteSecrets]="stoat/scripts/stoat_install_hooks.sh"
[_stoatWriteUrlFiles]="stoat/scripts/stoat_install_hooks.sh"
[stopCrowdsec]="crowdsec/crowdsec.sh"
@ -1190,6 +1204,7 @@ declare -gA LP_FN_ROOT=(
[_appReqServiceMsg]="scripts"
[appRocketchatCreateAccount]="containers"
[appRocketchatDeactivateUser]="containers"
[appRocketchatEnableUser]="containers"
[appRocketchatListUsers]="containers"
[appRocketchatResetPassword]="containers"
[appRocketchatSetAdmin]="containers"
@ -1203,6 +1218,9 @@ declare -gA LP_FN_ROOT=(
[appSetupComposeTags_vaultwarden]="containers"
[appSetupComposeTags_wireguard]="containers"
[appStatus]="scripts"
[appStoatDisableUser]="containers"
[appStoatEnableUser]="containers"
[appStoatListUsers]="containers"
[appTraefikExtraMiddlewares_onlyoffice]="containers"
[appTraefikResetPassword]="containers"
[appTraefikSkipsDefaultMiddleware_onlyoffice]="containers"
@ -1283,9 +1301,13 @@ declare -gA LP_FN_ROOT=(
[authAdapter_nextcloud_setPassword]="containers"
[authAdapter_rocketchat_createUser]="containers"
[authAdapter_rocketchat_deleteUser]="containers"
[authAdapter_rocketchat_enableUser]="containers"
[authAdapter_rocketchat_listUsers]="containers"
[authAdapter_rocketchat_setAdmin]="containers"
[authAdapter_rocketchat_setPassword]="containers"
[authAdapter_stoat_deleteUser]="containers"
[authAdapter_stoat_enableUser]="containers"
[authAdapter_stoat_listUsers]="containers"
[authAdapter_traefik_setPassword]="containers"
[authelia_install_post]="containers"
[authelia_install_post_compose]="containers"
@ -1969,7 +1991,9 @@ declare -gA LP_FN_ROOT=(
[rocketchat_install_post_start]="containers"
[_rocketchatLogin]="containers"
[_rocketchatOk]="containers"
[_rocketchatPassword]="containers"
[_rocketchatUserId]="containers"
[_rocketchatUsernameOf]="containers"
[runAppCfg]="scripts"
[runAsManager]="scripts"
[runBackupOp]="scripts"
@ -2038,6 +2062,10 @@ declare -gA LP_FN_ROOT=(
[stoat_install_post_compose]="containers"
[stoat_install_post_start]="containers"
[stoat_install_pre]="containers"
[_stoatMongo]="containers"
[_stoatMongoFailed]="containers"
[_stoatMongoWho]="containers"
[_stoatSetDisabled]="containers"
[_stoatWriteSecrets]="containers"
[_stoatWriteUrlFiles]="containers"
[stopCrowdsec]="containers"
@ -2328,6 +2356,7 @@ _appReqServiceInstalled() { unset -f _appReqServiceInstalled; __lpAutoload "${in
_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 "$@"; }
appRocketchatEnableUser() { unset -f appRocketchatEnableUser; __lpAutoload "${install_containers_dir}rocketchat/tools/rocketchat_enable_user.sh"; appRocketchatEnableUser "$@"; }
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 "$@"; }
@ -2341,6 +2370,9 @@ appSetupComposeTags_speedtest() { unset -f appSetupComposeTags_speedtest; __lpAu
appSetupComposeTags_vaultwarden() { unset -f appSetupComposeTags_vaultwarden; __lpAutoload "${install_containers_dir}vaultwarden/scripts/vaultwarden_compose_tags.sh"; appSetupComposeTags_vaultwarden "$@"; }
appSetupComposeTags_wireguard() { unset -f appSetupComposeTags_wireguard; __lpAutoload "${install_containers_dir}wireguard/scripts/wireguard_compose_tags.sh"; appSetupComposeTags_wireguard "$@"; }
appStatus() { unset -f appStatus; __lpAutoload "${install_scripts_dir}app/app_status.sh"; appStatus "$@"; }
appStoatDisableUser() { unset -f appStoatDisableUser; __lpAutoload "${install_containers_dir}stoat/tools/stoat_disable_user.sh"; appStoatDisableUser "$@"; }
appStoatEnableUser() { unset -f appStoatEnableUser; __lpAutoload "${install_containers_dir}stoat/tools/stoat_enable_user.sh"; appStoatEnableUser "$@"; }
appStoatListUsers() { unset -f appStoatListUsers; __lpAutoload "${install_containers_dir}stoat/tools/stoat_list_users.sh"; appStoatListUsers "$@"; }
appTraefikExtraMiddlewares_onlyoffice() { unset -f appTraefikExtraMiddlewares_onlyoffice; __lpAutoload "${install_containers_dir}onlyoffice/scripts/onlyoffice_traefik.sh"; appTraefikExtraMiddlewares_onlyoffice "$@"; }
appTraefikResetPassword() { unset -f appTraefikResetPassword; __lpAutoload "${install_containers_dir}traefik/tools/traefik_reset_password.sh"; appTraefikResetPassword "$@"; }
appTraefikSkipsDefaultMiddleware_onlyoffice() { unset -f appTraefikSkipsDefaultMiddleware_onlyoffice; __lpAutoload "${install_containers_dir}onlyoffice/scripts/onlyoffice_traefik.sh"; appTraefikSkipsDefaultMiddleware_onlyoffice "$@"; }
@ -2421,9 +2453,13 @@ authAdapter_nextcloud_setAdmin() { unset -f authAdapter_nextcloud_setAdmin; __lp
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_enableUser() { unset -f authAdapter_rocketchat_enableUser; __lpAutoload "${install_containers_dir}rocketchat/scripts/rocketchat_auth.sh"; authAdapter_rocketchat_enableUser "$@"; }
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_stoat_deleteUser() { unset -f authAdapter_stoat_deleteUser; __lpAutoload "${install_containers_dir}stoat/scripts/stoat_auth.sh"; authAdapter_stoat_deleteUser "$@"; }
authAdapter_stoat_enableUser() { unset -f authAdapter_stoat_enableUser; __lpAutoload "${install_containers_dir}stoat/scripts/stoat_auth.sh"; authAdapter_stoat_enableUser "$@"; }
authAdapter_stoat_listUsers() { unset -f authAdapter_stoat_listUsers; __lpAutoload "${install_containers_dir}stoat/scripts/stoat_auth.sh"; authAdapter_stoat_listUsers "$@"; }
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 "$@"; }
@ -3107,7 +3143,9 @@ rocketchat_install_post() { unset -f rocketchat_install_post; __lpAutoload "${in
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 "$@"; }
_rocketchatPassword() { unset -f _rocketchatPassword; __lpAutoload "${install_containers_dir}rocketchat/scripts/rocketchat_auth.sh"; _rocketchatPassword "$@"; }
_rocketchatUserId() { unset -f _rocketchatUserId; __lpAutoload "${install_containers_dir}rocketchat/scripts/rocketchat_auth.sh"; _rocketchatUserId "$@"; }
_rocketchatUsernameOf() { unset -f _rocketchatUsernameOf; __lpAutoload "${install_containers_dir}rocketchat/scripts/rocketchat_auth.sh"; _rocketchatUsernameOf "$@"; }
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 "$@"; }
@ -3176,6 +3214,10 @@ stoat_install_post() { unset -f stoat_install_post; __lpAutoload "${install_cont
stoat_install_post_compose() { unset -f stoat_install_post_compose; __lpAutoload "${install_containers_dir}stoat/scripts/stoat_install_hooks.sh"; stoat_install_post_compose "$@"; }
stoat_install_post_start() { unset -f stoat_install_post_start; __lpAutoload "${install_containers_dir}stoat/scripts/stoat_install_hooks.sh"; stoat_install_post_start "$@"; }
stoat_install_pre() { unset -f stoat_install_pre; __lpAutoload "${install_containers_dir}stoat/scripts/stoat_install_hooks.sh"; stoat_install_pre "$@"; }
_stoatMongo() { unset -f _stoatMongo; __lpAutoload "${install_containers_dir}stoat/scripts/stoat_auth.sh"; _stoatMongo "$@"; }
_stoatMongoFailed() { unset -f _stoatMongoFailed; __lpAutoload "${install_containers_dir}stoat/scripts/stoat_auth.sh"; _stoatMongoFailed "$@"; }
_stoatMongoWho() { unset -f _stoatMongoWho; __lpAutoload "${install_containers_dir}stoat/scripts/stoat_auth.sh"; _stoatMongoWho "$@"; }
_stoatSetDisabled() { unset -f _stoatSetDisabled; __lpAutoload "${install_containers_dir}stoat/scripts/stoat_auth.sh"; _stoatSetDisabled "$@"; }
_stoatWriteSecrets() { unset -f _stoatWriteSecrets; __lpAutoload "${install_containers_dir}stoat/scripts/stoat_install_hooks.sh"; _stoatWriteSecrets "$@"; }
_stoatWriteUrlFiles() { unset -f _stoatWriteUrlFiles; __lpAutoload "${install_containers_dir}stoat/scripts/stoat_install_hooks.sh"; _stoatWriteUrlFiles "$@"; }
stopCrowdsec() { unset -f stopCrowdsec; __lpAutoload "${install_containers_dir}crowdsec/crowdsec.sh"; stopCrowdsec "$@"; }