From bd195bd735a24a69d20dd36f54bfc807e43901f8 Mon Sep 17 00:00:00 2001 From: joylessorchid Date: Tue, 24 Mar 2026 02:53:18 +0300 Subject: [PATCH] feat: add admin command to setup.sh MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ./setup.sh admin — create admin user directly in DB - Hashes password via bcryptjs (already in dependencies) - Creates both user and better-auth account records - Shows existing admins, offers to promote existing users - Validates email, password length (min 8) - Added to interactive menu and CLI router Co-Authored-By: Claude Opus 4.6 --- setup.sh | 134 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 128 insertions(+), 6 deletions(-) diff --git a/setup.sh b/setup.sh index b3c5af7..28ac965 100644 --- a/setup.sh +++ b/setup.sh @@ -208,6 +208,7 @@ print_usage() { echo -e " ${CYAN}update${NC} Обновить проект (git pull + npm + prisma + rebuild)" echo -e " ${CYAN}doctor${NC} Диагностика и автоисправление проблем" echo -e " ${CYAN}status${NC} Статус всех сервисов" + echo -e " ${CYAN}admin${NC} Создать администратора" echo -e " ${CYAN}logs${NC} [svc] Логи сервиса (по умолчанию: app)" echo -e " ${CYAN}restart${NC} Перезапуск контейнеров" echo -e " ${CYAN}reset${NC} Полный сброс (с подтверждением)" @@ -767,6 +768,122 @@ cmd_update() { echo "" } +# ============================================================ +# COMMAND: admin — создание админа +# ============================================================ + +cmd_admin() { + log_step "Создание администратора" + + # Проверить что PostgreSQL доступен + if ! docker compose exec -T postgres pg_isready -U postgres &>/dev/null; then + log_err "PostgreSQL не запущен. Запусти: ./setup.sh doctor" + return 1 + fi + + # Проверить что таблица users существует + if ! docker compose exec -T postgres psql -U postgres -d liveserver -c "SELECT 1 FROM users LIMIT 0;" &>/dev/null; then + log_err "Таблица users не найдена. Запусти: npx prisma db push" + return 1 + fi + + # Показать существующих админов + local existing_admins + existing_admins=$(docker compose exec -T postgres psql -U postgres -d liveserver -t -c \ + "SELECT email FROM users WHERE role = 'ADMIN';" 2>/dev/null | tr -d ' ' | grep -v '^$' || true) + + if [[ -n "$existing_admins" ]]; then + echo "" + log_info "Существующие админы:" + echo "$existing_admins" | while read -r admin_email; do + echo -e " ${CYAN}${admin_email}${NC}" + done + echo "" + fi + + # Спросить данные + local ADMIN_NAME ADMIN_EMAIL ADMIN_PASS + echo "" + ask "Имя администратора" "Admin" ADMIN_NAME + ask "Email" "" ADMIN_EMAIL + ask_secret "Пароль (мин. 8 символов)" "" ADMIN_PASS + + # Валидация + if [[ -z "$ADMIN_EMAIL" ]]; then + log_err "Email обязателен" + return 1 + fi + + if [[ ${#ADMIN_PASS} -lt 8 ]]; then + log_err "Пароль должен быть минимум 8 символов" + return 1 + fi + + # Проверить что email не занят + local exists + exists=$(docker compose exec -T postgres psql -U postgres -d liveserver -t -c \ + "SELECT count(*) FROM users WHERE email = '${ADMIN_EMAIL}';" 2>/dev/null | tr -d ' ') + + if [[ "$exists" -gt 0 ]]; then + echo "" + if ask_yn "Пользователь ${ADMIN_EMAIL} уже существует. Сделать админом?" "y"; then + docker compose exec -T postgres psql -U postgres -d liveserver -c \ + "UPDATE users SET role = 'ADMIN' WHERE email = '${ADMIN_EMAIL}';" &>/dev/null + log_ok "${ADMIN_EMAIL} теперь ADMIN" + return 0 + else + log_info "Отменено" + return 0 + fi + fi + + # Хешировать пароль через node + bcryptjs (уже в зависимостях) + log_info "Хеширование пароля..." + 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 [[ -z "$HASH" ]]; then + log_err "Не удалось хешировать пароль (bcryptjs не установлен?)" + log_info "Попробуй: npm install && ./setup.sh admin" + return 1 + fi + + # Генерировать ID в стиле cuid + local USER_ID + USER_ID=$(node -e "process.stdout.write(require('crypto').randomBytes(12).toString('hex'))" 2>/dev/null || echo "admin_$(date +%s)") + + # Создать пользователя + 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 + + # Создать аккаунт (better-auth accounts table для email+password) + local ACCOUNT_ID + ACCOUNT_ID=$(node -e "process.stdout.write(require('crypto').randomBytes(12).toString('hex'))" 2>/dev/null || echo "acc_$(date +%s)") + + 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 + echo "" + log_ok "${GREEN}${BOLD}Администратор создан!${NC}" + echo -e " ${CYAN}Email:${NC} ${ADMIN_EMAIL}" + echo -e " ${CYAN}Пароль:${NC} (тот что ввёл)" + echo -e " ${CYAN}Роль:${NC} ADMIN" + echo "" + echo -e " Войди через: ${CYAN}http://localhost:3000/login${NC}" + else + log_err "Не удалось создать аккаунт" + fi +} + # ============================================================ # COMMAND: install (оригинальный setup) # ============================================================ @@ -1168,6 +1285,9 @@ case "$CMD" in doctor|fix) cmd_doctor ;; + admin) + cmd_admin + ;; status|st) cmd_status ;; @@ -1199,9 +1319,10 @@ case "$CMD" in echo -e " ${BOLD}1)${NC} ${CYAN}doctor${NC} — диагностика и исправление" echo -e " ${BOLD}2)${NC} ${CYAN}update${NC} — обновить проект" echo -e " ${BOLD}3)${NC} ${CYAN}status${NC} — статус сервисов" - echo -e " ${BOLD}4)${NC} ${CYAN}restart${NC} — перезапуск контейнеров" - echo -e " ${BOLD}5)${NC} ${CYAN}install${NC} — полная переустановка" - echo -e " ${BOLD}6)${NC} ${CYAN}reset${NC} — сброс всего" + echo -e " ${BOLD}4)${NC} ${CYAN}admin${NC} — создать администратора" + echo -e " ${BOLD}5)${NC} ${CYAN}restart${NC} — перезапуск контейнеров" + echo -e " ${BOLD}6)${NC} ${CYAN}install${NC} — полная переустановка" + echo -e " ${BOLD}7)${NC} ${CYAN}reset${NC} — сброс всего" echo "" ask "Выбери действие" "1" CHOICE @@ -1209,9 +1330,10 @@ case "$CMD" in 1|doctor) cmd_doctor ;; 2|update) cmd_update ;; 3|status) cmd_status ;; - 4|restart) cmd_restart ;; - 5|install) cmd_install ;; - 6|reset) cmd_reset ;; + 4|admin) cmd_admin ;; + 5|restart) cmd_restart ;; + 6|install) cmd_install ;; + 7|reset) cmd_reset ;; *) log_err "Неизвестный выбор: ${CHOICE}"; print_usage ;; esac fi