add admin creation to deployment
Build & Push / Pipeline Tests (push) Successful in 1m52s
Test / Type Check (all packages) (push) Successful in 52s
Build & Push / Build & Push Docker Image (push) Successful in 25s
Test / API Unit Tests (push) Successful in 1m6s
Test / Homepage Unit Tests (push) Successful in 45s
Test / Carplace Unit Tests (push) Successful in 44s
Test / Admin Unit Tests (push) Successful in 42s
Test / Dashboard Unit Tests (push) Successful in 42s
Test / API Integration Tests (push) Successful in 1m7s
Build & Push / Pipeline Tests (push) Successful in 1m52s
Test / Type Check (all packages) (push) Successful in 52s
Build & Push / Build & Push Docker Image (push) Successful in 25s
Test / API Unit Tests (push) Successful in 1m6s
Test / Homepage Unit Tests (push) Successful in 45s
Test / Carplace Unit Tests (push) Successful in 44s
Test / Admin Unit Tests (push) Successful in 42s
Test / Dashboard Unit Tests (push) Successful in 42s
Test / API Integration Tests (push) Successful in 1m7s
This commit is contained in:
@@ -40,24 +40,33 @@ async function main() {
|
||||
normalizeDatabaseUrlForExecution()
|
||||
|
||||
const email = requireValue('email', 'ADMIN_EMAIL').toLowerCase()
|
||||
const password = requireValue('password', 'ADMIN_PASSWORD')
|
||||
const firstName = readValue('first-name', 'ADMIN_FIRST_NAME', 'Admin').trim()
|
||||
const lastName = readValue('last-name', 'ADMIN_LAST_NAME', 'User').trim()
|
||||
const role = readValue('role', 'ADMIN_ROLE', 'SUPER_ADMIN').trim().toUpperCase()
|
||||
const updateExisting = readBoolean('update-existing', 'ADMIN_UPDATE_EXISTING', false)
|
||||
|
||||
if (!ADMIN_ROLES.has(role)) {
|
||||
throw new Error(`Invalid ADMIN_ROLE "${role}". Use one of: ${Array.from(ADMIN_ROLES).join(', ')}`)
|
||||
}
|
||||
|
||||
if (password.length < 8) {
|
||||
throw new Error('Admin password must be at least 8 characters long.')
|
||||
}
|
||||
const checkOnly = process.argv.includes('--check')
|
||||
|
||||
const { PrismaClient } = require('../packages/database/generated')
|
||||
const prisma = new PrismaClient()
|
||||
try {
|
||||
const existing = await prisma.adminUser.findUnique({ where: { email } })
|
||||
|
||||
if (checkOnly) {
|
||||
console.log(existing ? 'EXISTS' : 'MISSING')
|
||||
process.exitCode = existing ? 0 : 1
|
||||
return
|
||||
}
|
||||
|
||||
const password = requireValue('password', 'ADMIN_PASSWORD')
|
||||
const firstName = readValue('first-name', 'ADMIN_FIRST_NAME', 'Admin').trim()
|
||||
const lastName = readValue('last-name', 'ADMIN_LAST_NAME', 'User').trim()
|
||||
const role = readValue('role', 'ADMIN_ROLE', 'SUPER_ADMIN').trim().toUpperCase()
|
||||
const updateExisting = readBoolean('update-existing', 'ADMIN_UPDATE_EXISTING', false)
|
||||
|
||||
if (!ADMIN_ROLES.has(role)) {
|
||||
throw new Error(`Invalid ADMIN_ROLE "${role}". Use one of: ${Array.from(ADMIN_ROLES).join(', ')}`)
|
||||
}
|
||||
|
||||
if (password.length < 8) {
|
||||
throw new Error('Admin password must be at least 8 characters long.')
|
||||
}
|
||||
|
||||
const passwordHash = await bcrypt.hash(password, 12)
|
||||
|
||||
if (existing) {
|
||||
|
||||
@@ -406,6 +406,79 @@ run_prod_migrations() {
|
||||
prod_compose run --rm migrate
|
||||
}
|
||||
|
||||
# Ensures a platform admin account exists for the production database, prompting
|
||||
# interactively only when stdin is a TTY. Runs inside the API container so it can
|
||||
# reach Postgres on the internal Docker network (production Postgres is not exposed
|
||||
# to the host).
|
||||
#
|
||||
# Behavior:
|
||||
# - Admin already exists -> ask whether to update the password (y/N). If yes,
|
||||
# prompt for a new password and update it. If no, keep
|
||||
# the existing password and continue deployment.
|
||||
# - Admin does not exist -> create it and prompt for a password.
|
||||
ensure_prod_admin() {
|
||||
export_env_value_if_unset ADMIN_SEED_EMAIL
|
||||
export_env_value_if_unset ADMIN_SEED_FIRST_NAME
|
||||
export_env_value_if_unset ADMIN_SEED_LAST_NAME
|
||||
|
||||
local email="${ADMIN_SEED_EMAIL:-rentaldrivego@gmail.com}"
|
||||
local first_name="${ADMIN_SEED_FIRST_NAME:-Super}"
|
||||
local last_name="${ADMIN_SEED_LAST_NAME:-Admin}"
|
||||
|
||||
if [[ ! -t 0 ]]; then
|
||||
echo "Skipping interactive admin setup (stdin is not a TTY)."
|
||||
return 0
|
||||
fi
|
||||
|
||||
local admin_exists=0
|
||||
echo "Checking admin user ${email}..."
|
||||
if prod_compose run --rm \
|
||||
-v "${ROOT_DIR}/scripts:/app/scripts:ro" \
|
||||
-e ADMIN_EMAIL="${email}" \
|
||||
api node scripts/create-admin-user.cjs --check; then
|
||||
admin_exists=1
|
||||
fi
|
||||
|
||||
if [[ ${admin_exists} -eq 1 ]]; then
|
||||
echo "Admin user ${email} already exists."
|
||||
local update_answer
|
||||
read -r -p "Update its password? [y/N] " update_answer
|
||||
case "${update_answer}" in
|
||||
y|Y|yes|YES|Yes) ;;
|
||||
*)
|
||||
echo "Keeping existing admin password."
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
else
|
||||
echo "Admin user ${email} does not exist; it will be created."
|
||||
fi
|
||||
|
||||
local password=""
|
||||
while [[ ${#password} -lt 8 ]]; do
|
||||
if ! read -r -s -p "Enter admin password (min 8 characters): " password; then
|
||||
echo
|
||||
echo "No password provided; aborting admin setup." >&2
|
||||
return 1
|
||||
fi
|
||||
echo
|
||||
if [[ ${#password} -lt 8 ]]; then
|
||||
echo "Password must be at least 8 characters." >&2
|
||||
fi
|
||||
done
|
||||
|
||||
prod_compose run --rm \
|
||||
-v "${ROOT_DIR}/scripts:/app/scripts:ro" \
|
||||
-e ADMIN_EMAIL="${email}" \
|
||||
-e ADMIN_PASSWORD="${password}" \
|
||||
-e ADMIN_FIRST_NAME="${first_name}" \
|
||||
-e ADMIN_LAST_NAME="${last_name}" \
|
||||
-e ADMIN_UPDATE_EXISTING=true \
|
||||
api node scripts/create-admin-user.cjs
|
||||
|
||||
echo "Admin user ${email} is ready."
|
||||
}
|
||||
|
||||
wait_for_healthy() {
|
||||
local service="$1"
|
||||
local timeout="${2:-120}"
|
||||
|
||||
@@ -25,6 +25,9 @@ wait_for_healthy postgres 120
|
||||
echo "Running database migrations"
|
||||
run_prod_migrations
|
||||
|
||||
echo "Ensuring platform admin account"
|
||||
ensure_prod_admin
|
||||
|
||||
echo "Starting application services"
|
||||
prod_compose up -d api homepage carplace dashboard admin
|
||||
wait_for_healthy api 180
|
||||
|
||||
Reference in New Issue
Block a user