#!/usr/bin/env bash # Staging auth rehearsal helper. # Docs: docs/staging-auth-rehearsal.md # # Does NOT read repo .env or any live secrets file. # Requires DATABASE_URL in the environment for -issue. # # Examples: # export DATABASE_URL='postgres://descrybe:descrybe@localhost:5433/descrybe?sslmode=disable' # ./scripts/staging-auth-rehearsal.sh # print SQL + next steps # ./scripts/staging-auth-rehearsal.sh --issue # also re-issue invites (no SMTP) # ./scripts/staging-auth-rehearsal.sh --issue --dry-run set -euo pipefail ROOT="$(cd "$(dirname "$0")/.." && pwd)" API_DIR="$ROOT/apps/api" MAPS_DIR="${MAPS_DIR:-$ROOT/artifacts}" ISSUE=0 DRY_RUN=0 while [[ $# -gt 0 ]]; do case "$1" in --issue) ISSUE=1; shift ;; --dry-run) DRY_RUN=1; shift ;; --maps-dir) MAPS_DIR="$2"; shift 2 ;; -h|--help) sed -n '1,20p' "$0" exit 0 ;; *) echo "Unknown arg: $1" >&2 exit 2 ;; esac done echo "==> Staging auth rehearsal (no SMTP / link-copy path)" echo " Docs: docs/staging-auth-rehearsal.md" echo if [[ -z "${DATABASE_URL:-}" ]]; then echo "DATABASE_URL is not set. Export it in this shell only (do not paste production secrets into the repo)." echo "Example: export DATABASE_URL='postgres://descrybe:descrybe@localhost:5433/descrybe?sslmode=disable'" echo fi cat <<'EOF' === 1. Promote company admin (preferred: migrator CLI; dry-run first) === cd apps/api go run ./cmd/migrator -list-member-memberships -postgres "$DATABASE_URL" go run ./cmd/migrator -promote-company-admins -email '' -dry-run -postgres "$DATABASE_URL" go run ./cmd/migrator -promote-company-admins -email '' -confirm -postgres "$DATABASE_URL" # SQL alternate (fill UUIDs): -- List SELECT u.id AS user_id, u.email, u.must_set_password, u.is_platform_admin, m.company_id, c.name AS company_name, m.role, m.status FROM memberships m JOIN users u ON u.id = m.user_id JOIN companies c ON c.id = m.company_id WHERE m.status = 'active' ORDER BY c.name, u.email; -- Promote (fill UUIDs) UPDATE memberships SET role = 'admin' WHERE user_id = '' AND company_id = '' AND status = 'active' RETURNING user_id, company_id, role; EOF if [[ "$ISSUE" -eq 0 ]]; then echo "=== 2. Re-issue set-password (skipped) ===" echo "Re-run with --issue after emails are real (not *@legacy.local)." echo " ./scripts/staging-auth-rehearsal.sh --issue" echo echo "=== 3. Login smoke (manual) ===" echo "Copy one URL from migrator stdout or artifacts/password_invites.json" echo "-> open /accept-invite -> set password -> /login -> confirm must_set_password=false" exit 0 fi if [[ -z "${DATABASE_URL:-}" ]]; then echo "DATABASE_URL is required for --issue" >&2 exit 1 fi if [[ -n "${WEB_ORIGIN:-}" ]]; then echo "WEB_ORIGIN=$WEB_ORIGIN" else echo "WEB_ORIGIN unset -> migrator default http://localhost:28472" fi mkdir -p "$MAPS_DIR" cd "$API_DIR" echo "=== 2. Re-issue set-password invites (maps-dir=$MAPS_DIR) ===" ARGS=(-issue-set-password-invites -postgres "$DATABASE_URL" -maps-dir "$MAPS_DIR") if [[ "$DRY_RUN" -eq 1 ]]; then ARGS+=(-dry-run) echo "(dry-run: no invites written)" fi go run ./cmd/migrator "${ARGS[@]}" echo echo "=== 3. Login smoke (manual - no SMTP) ===" echo "1. Copy one emailurl line from stdout above (or $MAPS_DIR/password_invites.json)." echo "2. Open the URL -> set password (at least 8 chars)." echo "3. Sign in at /login with the same email." echo "4. SQL: SELECT email, must_set_password FROM users WHERE lower(email)=lower('');" echo "Do NOT run cmd/mailhooks for this rehearsal."