Update files
This commit is contained in:
parent
d6ed268c4a
commit
a93c95158f
|
|
@ -21,29 +21,40 @@ const OWNER_USERNAMES = new Set(config.moderationOwnerUsernames || []);
|
|||
|
||||
// Проверка доступа к модерации (только для модераторов и админов)
|
||||
const requireModerationAccess = async (req, res, next) => {
|
||||
// Проверить роль пользователя
|
||||
if (!req.user || !['moderator', 'admin'].includes(req.user.role)) {
|
||||
if (!req.user) {
|
||||
return res.status(403).json({ error: 'Недостаточно прав для модерации' });
|
||||
}
|
||||
|
||||
// Для JWT авторизации (без Telegram) - достаточно проверки роли
|
||||
// Для JWT авторизации (без Telegram) - проверяем роль
|
||||
if (!req.user.telegramId) {
|
||||
if (!['moderator', 'admin'].includes(req.user.role)) {
|
||||
return res.status(403).json({ error: 'Недостаточно прав для модерации' });
|
||||
}
|
||||
req.isModerationAdmin = true;
|
||||
req.isOwner = req.user.role === 'admin';
|
||||
return next();
|
||||
}
|
||||
|
||||
// Для Telegram авторизации - проверяем через isModerationAdmin
|
||||
const username = normalizeUsername(req.user?.username);
|
||||
const telegramId = req.user?.telegramId;
|
||||
|
||||
// Владелец или админ по роли - всегда доступ
|
||||
if (OWNER_USERNAMES.has(username) || req.user.role === 'admin') {
|
||||
req.isModerationAdmin = true;
|
||||
req.isOwner = true;
|
||||
return next();
|
||||
}
|
||||
|
||||
// Проверить, является ли пользователь модератором через ModerationAdmin
|
||||
const allowed = await isModerationAdmin({ telegramId, username });
|
||||
if (!allowed) {
|
||||
// Если не модератор по базе, но роль moderator или admin - разрешить
|
||||
if (['moderator', 'admin'].includes(req.user.role)) {
|
||||
req.isModerationAdmin = true;
|
||||
req.isOwner = req.user.role === 'admin';
|
||||
return next();
|
||||
}
|
||||
return res.status(403).json({ error: 'Недостаточно прав для модерации' });
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -309,8 +309,11 @@ router.post('/telegram-widget', authLimiter, async (req, res) => {
|
|||
router.post('/telegram', authLimiter, authenticateModeration, async (req, res) => {
|
||||
try {
|
||||
const user = req.user;
|
||||
const { isModerationAdmin } = require('../services/moderationAdmin');
|
||||
const { normalizeUsername } = require('../services/moderationAdmin');
|
||||
const config = require('../config');
|
||||
|
||||
if (!user || !['moderator', 'admin'].includes(user.role)) {
|
||||
if (!user) {
|
||||
return res.status(403).json({ error: 'Доступ запрещен' });
|
||||
}
|
||||
|
||||
|
|
@ -318,6 +321,21 @@ router.post('/telegram', authLimiter, authenticateModeration, async (req, res) =
|
|||
return res.status(403).json({ error: 'Аккаунт заблокирован' });
|
||||
}
|
||||
|
||||
// Проверить доступ: роль admin/moderator ИЛИ является модератором через ModerationAdmin
|
||||
const username = normalizeUsername(user.username);
|
||||
const telegramId = user.telegramId;
|
||||
const OWNER_USERNAMES = new Set(config.moderationOwnerUsernames || []);
|
||||
|
||||
const isOwner = OWNER_USERNAMES.has(username);
|
||||
const isAdminByRole = ['moderator', 'admin'].includes(user.role);
|
||||
const isAdminByDB = await isModerationAdmin({ telegramId, username });
|
||||
|
||||
if (!isOwner && !isAdminByRole && !isAdminByDB) {
|
||||
return res.status(403).json({
|
||||
error: 'Доступ запрещен. У вас нет прав модератора. Обратитесь к администратору.'
|
||||
});
|
||||
}
|
||||
|
||||
// Обновить время последней активности
|
||||
user.lastActiveAt = new Date();
|
||||
await user.save();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,58 @@
|
|||
#!/bin/bash
|
||||
|
||||
echo "🔍 Проверка состояния бэкенда модерации..."
|
||||
echo ""
|
||||
|
||||
# Проверка 1: Процесс запущен ли на порту 3001
|
||||
echo "1️⃣ Проверка процесса на порту 3001:"
|
||||
if lsof -i :3001 > /dev/null 2>&1; then
|
||||
echo " ✅ Порт 3001 занят процессом:"
|
||||
lsof -i :3001 | grep LISTEN
|
||||
else
|
||||
echo " ❌ Порт 3001 свободен - бэкенд не запущен!"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
# Проверка 2: HTTP запрос к бэкенду
|
||||
echo "2️⃣ Проверка доступности бэкенда:"
|
||||
if curl -s http://localhost:3001/health > /dev/null 2>&1; then
|
||||
echo " ✅ Бэкенд отвечает на /health:"
|
||||
curl -s http://localhost:3001/health | jq . 2>/dev/null || curl -s http://localhost:3001/health
|
||||
else
|
||||
echo " ❌ Бэкенд недоступен по http://localhost:3001/health"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
# Проверка 3: Через Nginx
|
||||
echo "3️⃣ Проверка через Nginx:"
|
||||
if curl -s https://moderation.nkm.guru/api/health > /dev/null 2>&1; then
|
||||
echo " ✅ Nginx проксирует запросы:"
|
||||
curl -s https://moderation.nkm.guru/api/health | jq . 2>/dev/null || curl -s https://moderation.nkm.guru/api/health
|
||||
else
|
||||
echo " ❌ Nginx не может достучаться до бэкенда"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
# Проверка 4: Логи Nginx
|
||||
echo "4️⃣ Последние ошибки из Nginx:"
|
||||
if [ -f /var/log/nginx/moderation-error.log ]; then
|
||||
echo " Последние 5 строк:"
|
||||
tail -5 /var/log/nginx/moderation-error.log
|
||||
else
|
||||
echo " ⚠️ Файл логов не найден: /var/log/nginx/moderation-error.log"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "📋 РЕШЕНИЕ:"
|
||||
echo "Если бэкенд не запущен, выполните:"
|
||||
echo ""
|
||||
echo "cd /Users/glpshchn/Desktop/nakama/moderation/backend"
|
||||
echo "NODE_ENV=production PORT=3001 MODERATION_PORT=3001 node server.js"
|
||||
echo ""
|
||||
echo "Или используйте PM2:"
|
||||
echo "pm2 start moderation/backend/server.js --name moderation-backend --env production"
|
||||
echo "pm2 save"
|
||||
|
||||
|
|
@ -68,8 +68,8 @@ services:
|
|||
dockerfile: Dockerfile.moderation-backend
|
||||
container_name: nakama-moderation-backend
|
||||
restart: unless-stopped
|
||||
expose:
|
||||
- "3001"
|
||||
ports:
|
||||
- "127.0.0.1:3001:3001" # Проброс порта на хост для Nginx
|
||||
environment:
|
||||
- NODE_ENV=production
|
||||
- PORT=3001
|
||||
|
|
|
|||
|
|
@ -0,0 +1,46 @@
|
|||
#!/bin/bash
|
||||
|
||||
echo "🔧 Исправление проблемы с портом бэкенда модерации..."
|
||||
echo ""
|
||||
|
||||
# Остановить и удалить контейнер
|
||||
echo "1️⃣ Остановка контейнера..."
|
||||
docker stop nakama-moderation-backend 2>/dev/null || true
|
||||
docker rm nakama-moderation-backend 2>/dev/null || true
|
||||
|
||||
echo ""
|
||||
|
||||
# Пересобрать и перезапустить
|
||||
echo "2️⃣ Пересборка и запуск контейнера с проброшенным портом..."
|
||||
docker-compose up -d moderation-backend
|
||||
|
||||
echo ""
|
||||
|
||||
# Проверка
|
||||
echo "3️⃣ Проверка доступности порта..."
|
||||
sleep 2
|
||||
|
||||
if lsof -i :3001 > /dev/null 2>&1; then
|
||||
echo " ✅ Порт 3001 доступен:"
|
||||
lsof -i :3001 | grep LISTEN
|
||||
else
|
||||
echo " ⚠️ Порт 3001 еще не доступен, подождите..."
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
# Проверка здоровья
|
||||
echo "4️⃣ Проверка здоровья бэкенда..."
|
||||
sleep 3
|
||||
|
||||
if curl -s http://localhost:3001/health > /dev/null 2>&1; then
|
||||
echo " ✅ Бэкенд отвечает:"
|
||||
curl -s http://localhost:3001/health | jq . 2>/dev/null || curl -s http://localhost:3001/health
|
||||
else
|
||||
echo " ⚠️ Бэкенд еще не готов, проверьте логи:"
|
||||
echo " docker logs nakama-moderation-backend"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "✅ Готово! Теперь Nginx должен иметь доступ к бэкенду на порту 3001"
|
||||
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
#!/bin/bash
|
||||
|
||||
echo "🔍 Проверка конфликтов в nginx конфигурации..."
|
||||
|
||||
# Проверить существующие конфигурации
|
||||
echo "📋 Существующие конфигурации:"
|
||||
ls -la /etc/nginx/sites-enabled/
|
||||
|
||||
echo ""
|
||||
echo "🔍 Поиск moderation.nkm.guru в конфигурациях:"
|
||||
grep -r "moderation.nkm.guru" /etc/nginx/sites-enabled/ 2>/dev/null || echo "Не найдено в sites-enabled"
|
||||
|
||||
echo ""
|
||||
echo "📝 Содержимое /etc/nginx/sites-enabled/nakama (если существует):"
|
||||
if [ -f "/etc/nginx/sites-enabled/nakama" ]; then
|
||||
echo "--- Начало файла nakama ---"
|
||||
head -100 /etc/nginx/sites-enabled/nakama
|
||||
echo "--- Конец ---"
|
||||
else
|
||||
echo "Файл не найден"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "⚠️ РЕШЕНИЕ:"
|
||||
echo "1. Если moderation.nkm.guru уже настроен в /etc/nginx/sites-enabled/nakama:"
|
||||
echo " - Удалите настройки moderation.nkm.guru из этого файла"
|
||||
echo " - Или удалите весь файл если он не нужен"
|
||||
echo ""
|
||||
echo "2. Затем установите новую конфигурацию:"
|
||||
echo " sudo cp nginx-moderation-production.conf /etc/nginx/sites-available/moderation.nkm.guru"
|
||||
echo " sudo ln -sf /etc/nginx/sites-available/moderation.nkm.guru /etc/nginx/sites-enabled/"
|
||||
echo " sudo nginx -t"
|
||||
echo " sudo systemctl reload nginx"
|
||||
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Скрипт для установки конфигурации nginx для модерации
|
||||
|
||||
echo "🔧 Установка конфигурации Nginx для moderation.nkm.guru"
|
||||
|
||||
# Создать директорию если не существует
|
||||
sudo mkdir -p /etc/nginx/sites-available
|
||||
sudo mkdir -p /etc/nginx/sites-enabled
|
||||
|
||||
# Путь к файлу конфигурации
|
||||
CONFIG_FILE="nginx-moderation-production.conf"
|
||||
|
||||
# Проверить существование файла
|
||||
if [ ! -f "$CONFIG_FILE" ]; then
|
||||
echo "❌ Ошибка: Файл $CONFIG_FILE не найден!"
|
||||
echo "Убедитесь что вы в директории проекта"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Скопировать конфигурацию
|
||||
echo "📋 Копирование конфигурации..."
|
||||
sudo cp "$CONFIG_FILE" /etc/nginx/sites-available/moderation.nkm.guru
|
||||
|
||||
# Создать симлинк
|
||||
echo "🔗 Создание симлинка..."
|
||||
sudo ln -sf /etc/nginx/sites-available/moderation.nkm.guru /etc/nginx/sites-enabled/moderation.nkm.guru
|
||||
|
||||
# Проверить конфигурацию
|
||||
echo "✔️ Проверка конфигурации nginx..."
|
||||
if sudo nginx -t; then
|
||||
echo "✅ Конфигурация корректна!"
|
||||
echo "🔄 Перезагрузка nginx..."
|
||||
sudo systemctl reload nginx
|
||||
echo "✅ Готово! Конфигурация применена."
|
||||
else
|
||||
echo "❌ Ошибка в конфигурации nginx!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
|
@ -48,6 +48,78 @@ EMAIL_FROM=noreply@nakama.guru
|
|||
4. Пользователь вводит код, username и пароль
|
||||
5. Аккаунт активируется
|
||||
|
||||
## Деплой БЕЗ Docker (локально)
|
||||
|
||||
### 1. Настройка переменных окружения
|
||||
|
||||
Добавьте в `.env` в корне проекта:
|
||||
|
||||
```bash
|
||||
# Модерация
|
||||
MODERATION_PORT=3001
|
||||
MODERATION_CORS_ORIGIN=https://moderation.nkm.guru
|
||||
VITE_MODERATION_API_URL=https://moderation.nkm.guru/api # ВАЖНО: обязательно HTTPS!
|
||||
|
||||
# Email для кодов подтверждения админа
|
||||
OWNER_EMAIL=aaem9848@gmail.com
|
||||
|
||||
# Email настройки (выберите один вариант выше)
|
||||
EMAIL_PROVIDER=aws
|
||||
# ... остальные настройки email
|
||||
|
||||
# MongoDB (та же база что и основной бэкенд)
|
||||
MONGODB_URI=mongodb://103.80.87.247:27017/nakama
|
||||
|
||||
# JWT (те же ключи что и основной бэкенд)
|
||||
JWT_SECRET=your_jwt_secret
|
||||
JWT_ACCESS_SECRET=your_access_secret
|
||||
JWT_REFRESH_SECRET=your_refresh_secret
|
||||
```
|
||||
|
||||
### 2. Запуск бэкенда модерации
|
||||
|
||||
```bash
|
||||
cd /Users/glpshchn/Desktop/nakama/moderation/backend
|
||||
NODE_ENV=production PORT=3001 MODERATION_PORT=3001 node server.js
|
||||
```
|
||||
|
||||
Или с PM2 (рекомендуется):
|
||||
|
||||
```bash
|
||||
cd /Users/glpshchn/Desktop/nakama
|
||||
pm2 start moderation/backend/server.js --name moderation-backend --env production -- \
|
||||
NODE_ENV=production PORT=3001 MODERATION_PORT=3001
|
||||
pm2 save
|
||||
```
|
||||
|
||||
### 3. Проверка работы бэкенда
|
||||
|
||||
```bash
|
||||
# Проверка бэкенда
|
||||
curl http://localhost:3001/health
|
||||
|
||||
# Проверка через nginx
|
||||
curl https://moderation.nkm.guru/api/health
|
||||
```
|
||||
|
||||
### 4. Настройка Nginx
|
||||
|
||||
```bash
|
||||
# Скопировать конфигурацию
|
||||
sudo cp nginx-moderation-production.conf /etc/nginx/sites-available/moderation.nkm.guru
|
||||
|
||||
# Активировать конфигурацию
|
||||
sudo ln -sf /etc/nginx/sites-available/moderation.nkm.guru /etc/nginx/sites-enabled/
|
||||
|
||||
# Проверить конфигурацию
|
||||
sudo nginx -t
|
||||
|
||||
# Перезагрузить nginx
|
||||
sudo systemctl reload nginx
|
||||
```
|
||||
|
||||
**⚠️ ВАЖНО:** Убедитесь, что в `/etc/nginx/sites-enabled/nakama` нет дублирующих настроек для `moderation.nkm.guru`. Если есть - удалите их, иначе будет конфликт.
|
||||
|
||||
## Деплой с Docker
|
||||
|
||||
### 1. Настройка переменных окружения
|
||||
|
|
@ -126,10 +198,56 @@ docker-compose restart nginx-moderation
|
|||
|
||||
## Troubleshooting
|
||||
|
||||
### 502 Bad Gateway
|
||||
|
||||
Это означает, что Nginx не может подключиться к бэкенду. Проверьте:
|
||||
|
||||
1. **Бэкенд запущен?**
|
||||
```bash
|
||||
curl http://localhost:3001/health
|
||||
# Должен вернуть: {"status":"ok","service":"moderation",...}
|
||||
```
|
||||
|
||||
2. **Порт 3001 свободен?**
|
||||
```bash
|
||||
lsof -i :3001
|
||||
# Должен показать процесс Node.js
|
||||
```
|
||||
|
||||
3. **Логи Nginx:**
|
||||
```bash
|
||||
sudo tail -f /var/log/nginx/moderation-error.log
|
||||
```
|
||||
|
||||
4. **Запустите бэкенд:**
|
||||
```bash
|
||||
cd /Users/glpshchn/Desktop/nakama/moderation/backend
|
||||
NODE_ENV=production PORT=3001 MODERATION_PORT=3001 node server.js
|
||||
```
|
||||
|
||||
### Конфликт конфигурации Nginx
|
||||
|
||||
Если видите ошибки типа "conflicting server name" или "protocol options redefined":
|
||||
|
||||
1. Проверьте дубликаты в `/etc/nginx/sites-enabled/`:
|
||||
```bash
|
||||
grep -r "moderation.nkm.guru" /etc/nginx/sites-enabled/
|
||||
```
|
||||
|
||||
2. Удалите дублирующие настройки из `/etc/nginx/sites-enabled/nakama` (если есть)
|
||||
|
||||
3. Перезагрузите nginx:
|
||||
```bash
|
||||
sudo nginx -t
|
||||
sudo systemctl reload nginx
|
||||
```
|
||||
|
||||
### Email не отправляется
|
||||
|
||||
1. Проверьте настройки EMAIL_PROVIDER в .env
|
||||
2. Проверьте логи: `docker-compose logs moderation-backend`
|
||||
2. Проверьте логи бэкенда:
|
||||
- Если через PM2: `pm2 logs moderation-backend`
|
||||
- Если напрямую: логи в консоли
|
||||
3. Убедитесь что credentials правильные
|
||||
|
||||
### Не работает авторизация
|
||||
|
|
|
|||
|
|
@ -8,8 +8,6 @@
|
|||
<title>Nakama Moderation</title>
|
||||
<!-- Telegram Web App SDK -->
|
||||
<script src="https://telegram.org/js/telegram-web-app.js"></script>
|
||||
<!-- Telegram Login Widget SDK -->
|
||||
<script async src="https://telegram.org/js/telegram-widget.js?22" data-telegram-login="NakamaSpaceBot" data-size="large" data-request-access="write"></script>
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
|
|
|
|||
|
|
@ -154,12 +154,18 @@ export default function App() {
|
|||
const result = await loginTelegram();
|
||||
if (cancelled) return;
|
||||
|
||||
setUser(result.user);
|
||||
setError(null);
|
||||
if (result && result.user) {
|
||||
setUser(result.user);
|
||||
setError(null);
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Telegram авторизация не удалась:', err);
|
||||
// В MiniApp при ошибке показываем ошибку, а не форму входа
|
||||
setError(err?.response?.data?.error || 'Ошибка авторизации. Убедитесь, что у вас есть права модератора.');
|
||||
setLoading(false);
|
||||
return;
|
||||
} catch (err) {
|
||||
console.warn('Telegram авторизация не удалась, пробуем JWT:', err);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -211,7 +217,7 @@ export default function App() {
|
|||
const showLoginForm = error === 'login_required' || (!user && !loading);
|
||||
|
||||
// Инициализировать виджет только если нет WebApp initData и показана форма входа
|
||||
if (!telegramApp?.initData && showLoginForm) {
|
||||
if (!telegramApp?.initData && showLoginForm && telegramWidgetRef.current) {
|
||||
// Глобальная функция для обработки авторизации через виджет
|
||||
window.onTelegramAuth = async (userData) => {
|
||||
console.log('Telegram Login Widget данные:', userData);
|
||||
|
|
@ -256,14 +262,21 @@ export default function App() {
|
|||
const initWidget = () => {
|
||||
// Проверить не загружен ли уже виджет
|
||||
if (document.querySelector('script[src*="telegram-widget"]')) {
|
||||
console.log('[Telegram Widget] Виджет уже загружен');
|
||||
return;
|
||||
}
|
||||
|
||||
const widgetContainer = telegramWidgetRef.current;
|
||||
if (!widgetContainer) {
|
||||
console.warn('[Telegram Widget] Контейнер не найден');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('[Telegram Widget] Инициализация виджета...');
|
||||
|
||||
// Очистить контейнер перед добавлением скрипта
|
||||
widgetContainer.innerHTML = '';
|
||||
|
||||
const script = document.createElement('script');
|
||||
script.async = true;
|
||||
script.src = 'https://telegram.org/js/telegram-widget.js?22';
|
||||
|
|
@ -271,12 +284,21 @@ export default function App() {
|
|||
script.setAttribute('data-size', 'large');
|
||||
script.setAttribute('data-request-access', 'write');
|
||||
script.setAttribute('data-onauth', 'onTelegramAuth');
|
||||
script.setAttribute('data-radius', '10');
|
||||
|
||||
script.onload = () => {
|
||||
console.log('[Telegram Widget] Скрипт загружен');
|
||||
};
|
||||
|
||||
script.onerror = () => {
|
||||
console.error('[Telegram Widget] Ошибка загрузки скрипта');
|
||||
};
|
||||
|
||||
widgetContainer.appendChild(script);
|
||||
};
|
||||
|
||||
// Подождать немного чтобы контейнер был готов
|
||||
const timer = setTimeout(initWidget, 500);
|
||||
const timer = setTimeout(initWidget, 100);
|
||||
return () => {
|
||||
clearTimeout(timer);
|
||||
if (window.onTelegramAuth) {
|
||||
|
|
@ -1305,43 +1327,20 @@ export default function App() {
|
|||
);
|
||||
}
|
||||
|
||||
// Показать форму входа
|
||||
if (error === 'login_required' || (!user && !loading)) {
|
||||
const telegramApp = window.Telegram?.WebApp;
|
||||
const canUseTelegram = telegramApp && telegramApp.initData;
|
||||
// Показать форму входа ТОЛЬКО если это НЕ MiniApp
|
||||
const telegramApp = window.Telegram?.WebApp;
|
||||
const isMiniApp = telegramApp && telegramApp.initData;
|
||||
|
||||
if (error === 'login_required' || (!user && !loading && !isMiniApp)) {
|
||||
return (
|
||||
<div className="fullscreen-center">
|
||||
<div className="login-card">
|
||||
<h1 style={{ marginTop: 0, marginBottom: '24px' }}>Вход в модерацию</h1>
|
||||
|
||||
{/* Telegram авторизация */}
|
||||
{canUseTelegram && (
|
||||
<>
|
||||
<button
|
||||
className="btn primary"
|
||||
onClick={handleTelegramLogin}
|
||||
disabled={authLoading}
|
||||
style={{ width: '100%', justifyContent: 'center', marginBottom: '16px' }}
|
||||
>
|
||||
{authLoading ? <Loader2 className="spin" size={18} /> : '🔐 Войти через Telegram'}
|
||||
</button>
|
||||
<div style={{
|
||||
textAlign: 'center',
|
||||
marginBottom: '24px',
|
||||
padding: '16px',
|
||||
background: 'rgba(255, 255, 255, 0.05)',
|
||||
borderRadius: '8px'
|
||||
}}>
|
||||
<p style={{ margin: 0, fontSize: '14px', color: 'var(--text-secondary)' }}>
|
||||
или
|
||||
</p>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
{/* Telegram авторизация в MiniApp - не показываем, авторизация автоматическая */}
|
||||
|
||||
{/* Telegram Login Widget для обычного браузера */}
|
||||
{!canUseTelegram && (
|
||||
{!isMiniApp && (
|
||||
<>
|
||||
<div
|
||||
id="telegram-login-widget"
|
||||
|
|
@ -1560,16 +1559,21 @@ export default function App() {
|
|||
);
|
||||
}
|
||||
|
||||
// Показать ошибку (особенно важно для MiniApp)
|
||||
if (error && error !== 'login_required') {
|
||||
const telegramApp = window.Telegram?.WebApp;
|
||||
const isMiniApp = telegramApp && telegramApp.initData;
|
||||
|
||||
return (
|
||||
<div className="fullscreen-center">
|
||||
<ShieldCheck size={48} />
|
||||
<p>{error}</p>
|
||||
{error.includes('доступ') && (
|
||||
<p style={{ marginTop: '16px', textAlign: 'center', maxWidth: '400px' }}>{error}</p>
|
||||
{!isMiniApp && error.includes('доступ') && (
|
||||
<button
|
||||
className="btn"
|
||||
onClick={() => {
|
||||
localStorage.removeItem('moderation_token');
|
||||
localStorage.removeItem('moderation_jwt_token');
|
||||
setError('login_required');
|
||||
}}
|
||||
style={{ marginTop: '16px' }}
|
||||
|
|
@ -1577,6 +1581,27 @@ export default function App() {
|
|||
Войти заново
|
||||
</button>
|
||||
)}
|
||||
{isMiniApp && (
|
||||
<button
|
||||
className="btn"
|
||||
onClick={async () => {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
try {
|
||||
const result = await loginTelegram();
|
||||
setUser(result.user);
|
||||
setError(null);
|
||||
} catch (err) {
|
||||
setError(err?.response?.data?.error || 'Ошибка авторизации');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}}
|
||||
style={{ marginTop: '16px' }}
|
||||
>
|
||||
Попробовать снова
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Скрипт для запуска бэкенда модерации
|
||||
|
||||
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
cd "$SCRIPT_DIR"
|
||||
|
||||
echo "🚀 Запуск бэкенда модерации..."
|
||||
echo ""
|
||||
|
||||
# Проверка существования .env
|
||||
if [ ! -f ".env" ]; then
|
||||
echo "⚠️ Файл .env не найден в корне проекта!"
|
||||
echo " Создайте его на основе ENV_EXAMPLE.txt"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Проверка занятости порта
|
||||
if lsof -i :3001 > /dev/null 2>&1; then
|
||||
echo "⚠️ Порт 3001 уже занят!"
|
||||
echo " Остановите существующий процесс или измените порт"
|
||||
lsof -i :3001
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Проверка установки зависимостей
|
||||
if [ ! -d "node_modules" ]; then
|
||||
echo "📦 Установка зависимостей..."
|
||||
npm install
|
||||
fi
|
||||
|
||||
echo "✅ Запуск сервера модерации на порту 3001..."
|
||||
echo ""
|
||||
|
||||
# Запуск с переменными окружения
|
||||
cd moderation/backend
|
||||
NODE_ENV=production \
|
||||
PORT=3001 \
|
||||
MODERATION_PORT=3001 \
|
||||
node server.js
|
||||
|
||||
Loading…
Reference in New Issue