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>
This commit is contained in:
parent
71bc78df27
commit
4b6b05db81
@ -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
|
||||
|
||||
@ -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
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
6
containers/rocketchat/tools/rocketchat_enable_user.sh
Normal file
6
containers/rocketchat/tools/rocketchat_enable_user.sh
Normal file
@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
appRocketchatEnableUser() {
|
||||
local args="$1"
|
||||
authAdapterCall rocketchat enableUser "$(authToolArg "$args" user)"
|
||||
}
|
||||
@ -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"
|
||||
@ -183,6 +184,7 @@ 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"
|
||||
@ -872,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"
|
||||
@ -1200,6 +1204,7 @@ declare -gA LP_FN_ROOT=(
|
||||
[_appReqServiceMsg]="scripts"
|
||||
[appRocketchatCreateAccount]="containers"
|
||||
[appRocketchatDeactivateUser]="containers"
|
||||
[appRocketchatEnableUser]="containers"
|
||||
[appRocketchatListUsers]="containers"
|
||||
[appRocketchatResetPassword]="containers"
|
||||
[appRocketchatSetAdmin]="containers"
|
||||
@ -1296,6 +1301,7 @@ 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"
|
||||
@ -1985,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"
|
||||
@ -2348,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 "$@"; }
|
||||
@ -2444,6 +2453,7 @@ 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 "$@"; }
|
||||
@ -3133,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 "$@"; }
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user