Eleven app configs declared CFG_<APP>_AUTH_PROFILE as a "capability tier for the WebUI auth tools". Nothing read it — not a shell script, not the frontend, and it was never emitted into apps.json, so the WebUI could not have acted on it even in principle. The job it was meant to do is already done, and done better: authAdapterCanDo tests `declare -F authAdapter_<app>_<method>`, so what an app can do is derived from the functions it actually implements. A declared tier is a second source of truth that can only drift — traefik declared single_password while its adapter implements setPassword only, and linkding declared nothing at all while shipping a full multi-user adapter, and neither mismatch had any effect. Removed the key and its comment from all eleven configs, and replaced the stale contract note in auth_adapter.sh with what the dispatcher really does. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
83 lines
3.1 KiB
Bash
83 lines
3.1 KiB
Bash
#!/bin/bash
|
|
|
|
# Universal user/credential adapter for app tools.
|
|
#
|
|
# An app opts in by implementing adapter functions in
|
|
# containers/<app>/scripts/<app>_auth.sh:
|
|
# authAdapter_<app>_setPassword "$user" "$password"
|
|
# authAdapter_<app>_createUser "$user" "$password" "$email" "$isAdmin"
|
|
# authAdapter_<app>_listUsers
|
|
#
|
|
# What an app can do is discovered from which of those exist (authAdapterCanDo),
|
|
# not declared anywhere. There used to be a CFG_<APP>_AUTH_PROFILE key naming a
|
|
# capability tier, but nothing ever read it — it was a second source of truth
|
|
# that could only drift out of step with the functions actually implemented.
|
|
#
|
|
# Tool wrappers call authAdapterCall <app> <method> <args...>. The
|
|
# dispatcher checks the function exists, runs it, and refreshes apps.json
|
|
# via webuiPatchAppConfigJson so new admin creds surface in the WebUI.
|
|
|
|
authAdapterCanDo() {
|
|
local app="$1" method="$2"
|
|
declare -F "authAdapter_${app}_${method}" >/dev/null 2>&1
|
|
}
|
|
|
|
authAdapterCall() {
|
|
local app="$1" method="$2"
|
|
shift 2
|
|
local fn="authAdapter_${app}_${method}"
|
|
if ! declare -F "$fn" >/dev/null 2>&1; then
|
|
isError "Auth adapter for '$app' does not implement '$method'."
|
|
return 1
|
|
fi
|
|
"$fn" "$@"
|
|
local rc=$?
|
|
if (( rc == 0 )) && declare -F webuiPatchAppConfigJson >/dev/null 2>&1; then
|
|
webuiPatchAppConfigJson "$app" >/dev/null 2>&1 || true
|
|
fi
|
|
return $rc
|
|
}
|
|
|
|
# Persist a value to CFG_<APP>_<KEY> in the per-app config file.
|
|
#
|
|
# Adapters call with the bare name (ADMIN_PASSWORD), but a key whose value is
|
|
# generated carries a slot number (CFG_<APP>_ADMIN_PASSWORD_1). Resolve to the
|
|
# slot when the bare key isn't there, so an adapter never has to know how a
|
|
# credential is numbered — and so adding a slot to a config can't quietly
|
|
# disconnect the adapter that writes it.
|
|
#
|
|
# updateConfigOption only rewrites a key that already exists; handed a name that
|
|
# is absent it just prints a notice. That is a silent failure from the caller's
|
|
# side: the app's password really did change, but the config and the WebUI carry
|
|
# on showing the old one. Hence the explicit return 1 and warning below.
|
|
authPersistCfg() {
|
|
local app="$1" key="$2" value="$3"
|
|
local cfg="${containers_dir}${app}/${app}.config"
|
|
[[ ! -f "$cfg" ]] && cfg="${install_containers_dir}/${app}/${app}.config"
|
|
[[ ! -f "$cfg" ]] && return 1
|
|
|
|
local app_upper="${app^^}"
|
|
app_upper="${app_upper//-/_}"
|
|
local name="CFG_${app_upper}_${key}"
|
|
|
|
if ! grep -q "^${name}=" "$cfg" 2>/dev/null; then
|
|
local slotted
|
|
slotted=$(grep -oE "^CFG_${app_upper}_${key}_[0-9]+=" "$cfg" 2>/dev/null | head -1)
|
|
if [[ -n "$slotted" ]]; then
|
|
name="${slotted%=}"
|
|
else
|
|
isNotice "$app has no ${name} (or numbered slot) in $(basename "$cfg") — the new value was applied to the app but not recorded in its config."
|
|
return 1
|
|
fi
|
|
fi
|
|
|
|
updateConfigOption "$name" "$value" "$cfg"
|
|
}
|
|
|
|
# Read a tool-modal arg (pipe-encoded) and unescape pipes.
|
|
authToolArg() {
|
|
local v
|
|
v=$(toolArgsGet "$1" "$2") || true
|
|
printf '%s' "${v//%7C/|}"
|
|
}
|