feat: add admin command to setup.sh
- ./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 <noreply@anthropic.com>
This commit is contained in:
@@ -208,6 +208,7 @@ print_usage() {
|
|||||||
echo -e " ${CYAN}update${NC} Обновить проект (git pull + npm + prisma + rebuild)"
|
echo -e " ${CYAN}update${NC} Обновить проект (git pull + npm + prisma + rebuild)"
|
||||||
echo -e " ${CYAN}doctor${NC} Диагностика и автоисправление проблем"
|
echo -e " ${CYAN}doctor${NC} Диагностика и автоисправление проблем"
|
||||||
echo -e " ${CYAN}status${NC} Статус всех сервисов"
|
echo -e " ${CYAN}status${NC} Статус всех сервисов"
|
||||||
|
echo -e " ${CYAN}admin${NC} Создать администратора"
|
||||||
echo -e " ${CYAN}logs${NC} [svc] Логи сервиса (по умолчанию: app)"
|
echo -e " ${CYAN}logs${NC} [svc] Логи сервиса (по умолчанию: app)"
|
||||||
echo -e " ${CYAN}restart${NC} Перезапуск контейнеров"
|
echo -e " ${CYAN}restart${NC} Перезапуск контейнеров"
|
||||||
echo -e " ${CYAN}reset${NC} Полный сброс (с подтверждением)"
|
echo -e " ${CYAN}reset${NC} Полный сброс (с подтверждением)"
|
||||||
@@ -767,6 +768,122 @@ cmd_update() {
|
|||||||
echo ""
|
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)
|
# COMMAND: install (оригинальный setup)
|
||||||
# ============================================================
|
# ============================================================
|
||||||
@@ -1168,6 +1285,9 @@ case "$CMD" in
|
|||||||
doctor|fix)
|
doctor|fix)
|
||||||
cmd_doctor
|
cmd_doctor
|
||||||
;;
|
;;
|
||||||
|
admin)
|
||||||
|
cmd_admin
|
||||||
|
;;
|
||||||
status|st)
|
status|st)
|
||||||
cmd_status
|
cmd_status
|
||||||
;;
|
;;
|
||||||
@@ -1199,9 +1319,10 @@ case "$CMD" in
|
|||||||
echo -e " ${BOLD}1)${NC} ${CYAN}doctor${NC} — диагностика и исправление"
|
echo -e " ${BOLD}1)${NC} ${CYAN}doctor${NC} — диагностика и исправление"
|
||||||
echo -e " ${BOLD}2)${NC} ${CYAN}update${NC} — обновить проект"
|
echo -e " ${BOLD}2)${NC} ${CYAN}update${NC} — обновить проект"
|
||||||
echo -e " ${BOLD}3)${NC} ${CYAN}status${NC} — статус сервисов"
|
echo -e " ${BOLD}3)${NC} ${CYAN}status${NC} — статус сервисов"
|
||||||
echo -e " ${BOLD}4)${NC} ${CYAN}restart${NC} — перезапуск контейнеров"
|
echo -e " ${BOLD}4)${NC} ${CYAN}admin${NC} — создать администратора"
|
||||||
echo -e " ${BOLD}5)${NC} ${CYAN}install${NC} — полная переустановка"
|
echo -e " ${BOLD}5)${NC} ${CYAN}restart${NC} — перезапуск контейнеров"
|
||||||
echo -e " ${BOLD}6)${NC} ${CYAN}reset${NC} — сброс всего"
|
echo -e " ${BOLD}6)${NC} ${CYAN}install${NC} — полная переустановка"
|
||||||
|
echo -e " ${BOLD}7)${NC} ${CYAN}reset${NC} — сброс всего"
|
||||||
echo ""
|
echo ""
|
||||||
ask "Выбери действие" "1" CHOICE
|
ask "Выбери действие" "1" CHOICE
|
||||||
|
|
||||||
@@ -1209,9 +1330,10 @@ case "$CMD" in
|
|||||||
1|doctor) cmd_doctor ;;
|
1|doctor) cmd_doctor ;;
|
||||||
2|update) cmd_update ;;
|
2|update) cmd_update ;;
|
||||||
3|status) cmd_status ;;
|
3|status) cmd_status ;;
|
||||||
4|restart) cmd_restart ;;
|
4|admin) cmd_admin ;;
|
||||||
5|install) cmd_install ;;
|
5|restart) cmd_restart ;;
|
||||||
6|reset) cmd_reset ;;
|
6|install) cmd_install ;;
|
||||||
|
7|reset) cmd_reset ;;
|
||||||
*) log_err "Неизвестный выбор: ${CHOICE}"; print_usage ;;
|
*) log_err "Неизвестный выбор: ${CHOICE}"; print_usage ;;
|
||||||
esac
|
esac
|
||||||
fi
|
fi
|
||||||
|
|||||||
Reference in New Issue
Block a user