feat: create first admin during ./setup.sh install

Step 6/7 asks for admin name/email/password and creates the user
directly in the database. Can be skipped (creates later via ./setup.sh admin).
Also fixed PgBouncer wait_for_service to use nc instead of pg_isready.
This commit is contained in:
2026-03-24 03:47:11 +03:00
parent 59c0cdad5f
commit e59ba0ab97

View File

@@ -891,7 +891,7 @@ cmd_admin() {
cmd_install() {
# --- Step 1: Check & install dependencies ---
log_step "Шаг 1/6 — Проверка и установка зависимостей"
log_step "Шаг 1/7 — Проверка и установка зависимостей"
local MISSING=0
install_if_missing docker "https://docs.docker.com/get-docker/" || MISSING=1
@@ -912,7 +912,7 @@ cmd_install() {
log_ok "Node.js: $NODE_VER"
# --- Step 2: Choose mode ---
log_step "Шаг 2/6 — Режим запуска"
log_step "Шаг 2/7 — Режим запуска"
echo ""
echo -e " ${BOLD}1)${NC} Локальная разработка (localhost, без SSL)"
@@ -947,7 +947,7 @@ cmd_install() {
fi
# --- Step 3: Configure environment ---
log_step "Шаг 3/6 — Настройка окружения"
log_step "Шаг 3/7 — Настройка окружения"
local PG_PASSWORD MINIO_USER MINIO_PASS AUTH_SECRET DEV_ACCESS_KEY S3_BUCKET
PG_PASSWORD=$(generate_password)
@@ -1011,7 +1011,7 @@ cmd_install() {
fi
# --- Step 4: Generate .env ---
log_step "Шаг 4/6 — Генерация .env"
log_step "Шаг 4/7 — Генерация .env"
local APP_URL S3_ENDPOINT
if [[ "$MODE" == "2" ]]; then
@@ -1075,7 +1075,7 @@ ENVEOF
log_ok ".env создан"
# --- Step 5: Install & setup ---
log_step "Шаг 5/6 — Установка и настройка"
log_step "Шаг 5/7 — Установка и настройка"
if [[ ! -d "node_modules" ]]; then
echo -e " Установка npm зависимостей..."
@@ -1103,7 +1103,7 @@ ENVEOF
wait_for_service "PostgreSQL" "docker compose exec -T postgres pg_isready -U postgres" 30 || exit 1
wait_for_service "Redis" "docker compose exec -T redis redis-cli ping 2>/dev/null | grep -q PONG" 15 || exit 1
wait_for_service "PgBouncer" "docker compose exec -T pgbouncer pg_isready -h 127.0.0.1 -p 6432" 15 || \
wait_for_service "PgBouncer" "docker compose exec -T pgbouncer sh -c 'echo | nc -w 2 127.0.0.1 6432'" 15 || \
log_warn "PgBouncer не отвечает — продолжаем без него"
echo -e " Применение миграций..."
@@ -1126,8 +1126,59 @@ ENVEOF
fi
fi
# --- Step 6: Done ---
log_step "Шаг 6/6Готово!"
# --- Step 6: First admin ---
log_step "Шаг 6/7Первый администратор"
echo ""
echo -e " ${BOLD}Создай аккаунт администратора для входа в систему.${NC}"
echo ""
local ADMIN_NAME ADMIN_EMAIL ADMIN_PASS
ask "Имя администратора" "Admin" ADMIN_NAME
ask "Email" "" ADMIN_EMAIL
ask_secret "Пароль (мин. 8 символов)" "" ADMIN_PASS
if [[ -n "$ADMIN_EMAIL" && ${#ADMIN_PASS} -ge 8 ]]; then
local HASH
HASH=$(node -e "
const bcrypt = require('bcryptjs');
const hash = bcrypt.hashSync(process.argv[1], 10);
process.stdout.write(hash);
" "$ADMIN_PASS" 2>/dev/null)
if [[ -n "$HASH" ]]; then
local USER_ID ACCOUNT_ID
USER_ID=$(node -e "process.stdout.write(require('crypto').randomBytes(12).toString('hex'))" 2>/dev/null)
ACCOUNT_ID=$(node -e "process.stdout.write(require('crypto').randomBytes(12).toString('hex'))" 2>/dev/null)
docker compose exec -T postgres psql -U postgres -d liveserver -c "
INSERT INTO users (id, email, name, \"emailVerified\", role, \"createdAt\", \"updatedAt\")
VALUES ('${USER_ID}', '${ADMIN_EMAIL}', '${ADMIN_NAME}', true, 'ADMIN', NOW(), NOW());
" &>/dev/null
docker compose exec -T postgres psql -U postgres -d liveserver -c "
INSERT INTO accounts (id, \"userId\", \"accountId\", \"providerId\", \"password\", \"createdAt\", \"updatedAt\")
VALUES ('${ACCOUNT_ID}', '${USER_ID}', '${USER_ID}', 'credential', '${HASH}', NOW(), NOW());
" &>/dev/null
if [[ $? -eq 0 ]]; then
log_ok "Администратор создан: ${ADMIN_EMAIL}"
else
log_warn "Не удалось создать админа — создай позже: ./setup.sh admin"
fi
else
log_warn "bcryptjs не готов — создай админа позже: ./setup.sh admin"
fi
else
if [[ -z "$ADMIN_EMAIL" ]]; then
log_info "Пропущено — создай позже: ./setup.sh admin"
else
log_err "Пароль должен быть мин. 8 символов — создай позже: ./setup.sh admin"
fi
fi
# --- Step 7: Done ---
log_step "Шаг 7/7 — Готово!"
echo ""
if [[ "$MODE" == "2" ]]; then