fix: feat: disinto init — prompt for disinto-admin password instead of hardcoding it (#620)
Some checks failed
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
ci/woodpecker/pr/smoke-init Pipeline failed

This commit is contained in:
Claude 2026-04-10 18:19:16 +00:00
parent 56dee64c97
commit fd67a6afc6

View file

@ -540,6 +540,86 @@ activate_woodpecker_repo() {
_activate_woodpecker_repo_impl "$@"
}
# ── Password prompt helper ────────────────────────────────────────────────────
# Prompts for FORGE_ADMIN_PASS with confirmation.
# Returns 0 on success, 1 on failure.
# Usage: prompt_admin_password [<env_file>]
prompt_admin_password() {
local env_file="${1:-${FACTORY_ROOT}/.env}"
# Check if password already exists in .env (resumable init)
if grep -q '^FORGE_ADMIN_PASS=' "$env_file" 2>/dev/null; then
echo "Forge: FORGE_ADMIN_PASS already set (resuming from .env)"
return 0
fi
# Non-interactive mode without pre-exported password
if [ "$auto_yes" = true ]; then
if [ -z "${FORGE_ADMIN_PASS:-}" ]; then
echo "Error: FORGE_ADMIN_PASS environment variable is required in non-interactive mode" >&2
echo " Export the password before running: export FORGE_ADMIN_PASS='<your-password>'" >&2
exit 1
fi
# Write the pre-exported password to .env
if grep -q '^FORGE_ADMIN_PASS=' "$env_file" 2>/dev/null; then
sed -i "s|^FORGE_ADMIN_PASS=.*|FORGE_ADMIN_PASS=${FORGE_ADMIN_PASS}|" "$env_file"
else
printf 'FORGE_ADMIN_PASS=%s\n' "$FORGE_ADMIN_PASS" >> "$env_file"
fi
echo "Forge: FORGE_ADMIN_PASS set from environment"
return 0
fi
# Interactive mode: prompt for password with confirmation
if [ -t 0 ]; then
local pass1 pass2 min_length=8 attempts=0 max_attempts=3
echo "Forge: Setting disinto-admin password"
echo " Password must be at least ${min_length} characters"
echo ""
while [ "$attempts" -lt "$max_attempts" ]; do
attempts=$((attempts + 1))
# First attempt (or retry): read password
printf "Enter password [%d/%d]: " "$attempts" "$max_attempts"
IFS= read -rs -p '' pass1
echo ""
# Read confirmation
printf "Confirm password: "
IFS= read -rs -p '' pass2
echo ""
# Validate length
if [ "${#pass1}" -lt "$min_length" ]; then
echo "Error: password must be at least ${min_length} characters (got ${#pass1})" >&2
continue
fi
# Validate match
if [ "$pass1" != "$pass2" ]; then
echo "Error: passwords do not match" >&2
continue
fi
# Success: write to .env
printf 'FORGE_ADMIN_PASS=%s\n' "$pass1" >> "$env_file"
echo "Forge: FORGE_ADMIN_PASS set (saved to .env)"
return 0
done
echo "Error: exceeded ${max_attempts} attempts — password not set" >&2
return 1
fi
# Non-interactive, no TTY, no pre-exported password
echo "Error: FORGE_ADMIN_PASS is not set and cannot prompt (no TTY)" >&2
echo " Either:" >&2
echo " 1) Export the password before running: export FORGE_ADMIN_PASS='<your-password>'" >&2
echo " 2) Run interactively (attach a TTY) to be prompted" >&2
exit 1
}
# ── init command ─────────────────────────────────────────────────────────────
disinto_init() {
@ -652,6 +732,10 @@ p.write_text(text)
touch "${FACTORY_ROOT}/.env"
fi
# Prompt for FORGE_ADMIN_PASS before setup_forge
# This ensures the password is set before Forgejo user creation
prompt_admin_password "${FACTORY_ROOT}/.env"
# Set up local Forgejo instance (provision if needed, create users/tokens/repo)
if [ "$rotate_tokens" = true ]; then
echo "Note: Forcing token rotation (tokens/passwords will be regenerated)"