Добавить установщик XLX системы и веб-панель
Этот коммит содержится в:
@@ -0,0 +1,33 @@
|
||||
# Админка и главный дашборд
|
||||
|
||||
## Главная
|
||||
|
||||
Главная страница доступна по адресу `/`.
|
||||
|
||||
На ней есть:
|
||||
|
||||
- краткое описание сервиса;
|
||||
- карточки статуса DMR/YooKassa/Pi-Star;
|
||||
- форма регистрации пользователя;
|
||||
- вывод ссылки YooKassa и инструкции для перевода по чеку.
|
||||
|
||||
## Админка
|
||||
|
||||
Админка доступна по адресу `/admin`.
|
||||
|
||||
Чтобы загрузить или сохранить настройки, нужно ввести `X-Admin-Token` из `config/config.php`.
|
||||
|
||||
Форма меняет:
|
||||
|
||||
- имя reflector, например `XLX138`;
|
||||
- домен сервера;
|
||||
- sysop callsign и email;
|
||||
- страну;
|
||||
- DMR/YSF/dashboard порты;
|
||||
- модуль по умолчанию;
|
||||
- список активных модулей;
|
||||
- пути установки, исходников и логов;
|
||||
- имя systemd service;
|
||||
- URL репозитория `xlxd`.
|
||||
|
||||
При сохранении с флагом `apply` API пытается обновить `/etc/xlx/xlxd.env`. Если PHP работает без прав записи в `/etc/xlx`, настройки все равно сохранятся в БД, а в админке будет виден готовый env-preview.
|
||||
@@ -56,18 +56,18 @@ XLX Server — это управляемая платформа для DMR-по
|
||||
|
||||
### 2.3 Callsign Verifier
|
||||
|
||||
Модуль проверки позывного по внешним источникам.
|
||||
Модуль проверки позывного по внутренней базе уже зарегистрированных пользователей.
|
||||
|
||||
MVP-логика:
|
||||
|
||||
- пользователь вводит позывной;
|
||||
- система нормализует его в верхний регистр;
|
||||
- проверяет формат;
|
||||
- делает запрос к настроенной базе;
|
||||
- проверяет, что позывной еще не занят в таблице пользователей;
|
||||
- сохраняет результат проверки;
|
||||
- при ошибке отправляет заявку в ручную модерацию.
|
||||
|
||||
Важно: внешний источник проверки должен быть заменяемым адаптером, чтобы не прибивать проект гвоздями к одной базе.
|
||||
Важно: уникальность дополнительно защищена индексом `users.callsign`, поэтому дубль не пройдет даже при одновременной регистрации.
|
||||
|
||||
### 2.4 ID Allocator
|
||||
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
# Установка всей системы
|
||||
|
||||
`scripts/install-system.sh` ставит сразу:
|
||||
|
||||
- Apache + PHP;
|
||||
- MariaDB;
|
||||
- базу и пользователя БД;
|
||||
- web-панель `/`;
|
||||
- админку `/admin`;
|
||||
- `xlxd`;
|
||||
- systemd service для reflector;
|
||||
- `/etc/xlx/xlxd.env`.
|
||||
|
||||
## Без домена
|
||||
|
||||
На чистом Ubuntu/Debian сервере:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/viktor138irk/xlx.git
|
||||
cd xlx
|
||||
sudo bash scripts/install-system.sh
|
||||
```
|
||||
|
||||
Установщик сам выберет адрес:
|
||||
|
||||
1. `XLX_PUBLIC_HOST`, если переменная задана;
|
||||
2. `hostname -f`, если он похож на реальное имя;
|
||||
3. первый IP из `hostname -I`;
|
||||
4. `127.0.0.1` как последний fallback.
|
||||
|
||||
В конце он покажет:
|
||||
|
||||
- URL сайта;
|
||||
- URL админки;
|
||||
- admin token;
|
||||
- webhook URL для YooKassa;
|
||||
- логин и пароль БД.
|
||||
|
||||
## С доменом
|
||||
|
||||
Если домен уже есть:
|
||||
|
||||
```bash
|
||||
sudo XLX_PUBLIC_HOST=xlx.example.ru bash scripts/install-system.sh
|
||||
```
|
||||
|
||||
Если домен появится позже, открой `/admin` и поменяй поле `Домен`. Это обновит настройки `xlxd` без ручного редактирования конфигов.
|
||||
|
||||
## YooKassa
|
||||
|
||||
Можно передать ключи сразу:
|
||||
|
||||
```bash
|
||||
sudo \
|
||||
XLX_PUBLIC_HOST=xlx.example.ru \
|
||||
YOOKASSA_SHOP_ID=123456 \
|
||||
YOOKASSA_SECRET_KEY=secret \
|
||||
bash scripts/install-system.sh
|
||||
```
|
||||
|
||||
Webhook будет такого вида:
|
||||
|
||||
```text
|
||||
http://адрес-сервера/api/webhooks/yookassa?token=секрет
|
||||
```
|
||||
|
||||
Если включишь HTTPS, укажи:
|
||||
|
||||
```bash
|
||||
sudo XLX_PUBLIC_SCHEME=https XLX_PUBLIC_HOST=xlx.example.ru bash scripts/install-system.sh
|
||||
```
|
||||
|
||||
## Повторный запуск
|
||||
|
||||
Скрипт можно запускать повторно. Он:
|
||||
|
||||
- обновит `config/config.php`;
|
||||
- обновит `/etc/xlx/xlxd.env`;
|
||||
- применит SQL-схему;
|
||||
- пересоберет `xlxd`;
|
||||
- перезагрузит Apache.
|
||||
|
||||
Перед повторным запуском с существующей БД лучше передать старый пароль:
|
||||
|
||||
```bash
|
||||
sudo XLX_DB_PASSWORD='старый-пароль' bash scripts/install-system.sh
|
||||
```
|
||||
@@ -0,0 +1,71 @@
|
||||
# Установка XLX reflector
|
||||
|
||||
Проект состоит из двух частей:
|
||||
|
||||
- `xlxd` - сам мультипротокольный XLX reflector;
|
||||
- PHP-панель - регистрация, YooKassa, ручной чек, выдача DMR ID и данных для Pi-Star.
|
||||
|
||||
## Требования
|
||||
|
||||
- Ubuntu 22.04/24.04 или Debian 12.
|
||||
- Публичный статический IP.
|
||||
- DNS-имя, например `xlx.example.com`.
|
||||
- Открытый UDP `62030` для Pi-Star MMDVM.
|
||||
- Root-доступ на сервер.
|
||||
|
||||
## Настройка XLX
|
||||
|
||||
```bash
|
||||
git clone https://github.com/viktor138irk/xlx.git
|
||||
cd xlx
|
||||
sudo mkdir -p /etc/xlx
|
||||
sudo cp config/xlxd.env.example /etc/xlx/xlxd.env
|
||||
sudo nano /etc/xlx/xlxd.env
|
||||
```
|
||||
|
||||
Минимально поменяй:
|
||||
|
||||
```bash
|
||||
XLX_REFLECTOR_NAME=XLX138
|
||||
XLX_SERVER_HOST=xlx.example.com
|
||||
XLX_SYSOP_CALLSIGN=R0XXX
|
||||
XLX_SYSOP_EMAIL=admin@example.com
|
||||
XLX_COUNTRY=RU
|
||||
```
|
||||
|
||||
## Установка сервера
|
||||
|
||||
```bash
|
||||
sudo bash scripts/install-xlxd.sh
|
||||
sudo ./scripts/firewall-ufw.sh
|
||||
sudo systemctl start xlxd
|
||||
sudo systemctl status xlxd
|
||||
```
|
||||
|
||||
Логи:
|
||||
|
||||
```bash
|
||||
sudo tail -f /var/log/xlxd.log
|
||||
```
|
||||
|
||||
## Управление
|
||||
|
||||
```bash
|
||||
sudo systemctl start xlxd
|
||||
sudo systemctl stop xlxd
|
||||
sudo systemctl restart xlxd
|
||||
sudo systemctl status xlxd
|
||||
```
|
||||
|
||||
## Pi-Star
|
||||
|
||||
После оплаты панель выдаст:
|
||||
|
||||
- сервер: `XLX_SERVER_HOST`;
|
||||
- порт: `62030`;
|
||||
- логин: позывной;
|
||||
- пароль: отдельный DMR-пароль;
|
||||
- DMR ID: выданный системой ID;
|
||||
- модуль: `A` по умолчанию.
|
||||
|
||||
Полный DMR-пароль показывается один раз. Если пользователь потерял пароль, нужно выпустить новый.
|
||||
@@ -0,0 +1,123 @@
|
||||
# Регистрация и оплата
|
||||
|
||||
## Сценарий пользователя
|
||||
|
||||
1. Пользователь отправляет позывной, email и пароль кабинета.
|
||||
2. Система нормализует позывной и проверяет, что такого позывного еще нет во внутренней базе.
|
||||
3. Если позывной принят, создается платеж.
|
||||
4. Пользователь выбирает:
|
||||
- оплату через YooKassa;
|
||||
- перевод с отправкой чека на ручную проверку.
|
||||
5. После подтверждения оплаты система:
|
||||
- активирует аккаунт;
|
||||
- назначает внутренний DMR ID;
|
||||
- генерирует отдельный DMR-пароль;
|
||||
- отдает данные подключения Pi-Star.
|
||||
|
||||
## YooKassa
|
||||
|
||||
В `config/config.php`:
|
||||
|
||||
```php
|
||||
'billing' => [
|
||||
'mode' => 'yookassa',
|
||||
'yookassa' => [
|
||||
'shop_id' => '...',
|
||||
'secret_key' => '...',
|
||||
'return_url' => 'https://xlx.example.com/payment/return',
|
||||
'webhook_secret' => 'long-random-token',
|
||||
'capture' => true,
|
||||
],
|
||||
],
|
||||
```
|
||||
|
||||
Webhook URL:
|
||||
|
||||
```text
|
||||
https://xlx.example.com/api/webhooks/yookassa?token=long-random-token
|
||||
```
|
||||
|
||||
Обрабатывается событие:
|
||||
|
||||
```text
|
||||
payment.succeeded
|
||||
```
|
||||
|
||||
Повторный webhook безопасен: если платеж уже оплачен, система вернет текущий доступ без повторной выдачи ID.
|
||||
|
||||
## Перевод с чеком
|
||||
|
||||
Если пользователь оплатил переводом, он отправляет номер или ссылку чека:
|
||||
|
||||
```http
|
||||
POST /api/payments/receipt
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"payment_id": 1,
|
||||
"user_id": 1,
|
||||
"receipt_reference": "https://bank.example/receipt/123",
|
||||
"comment": "Оплата за R0XXX"
|
||||
}
|
||||
```
|
||||
|
||||
Админ подтверждает чек:
|
||||
|
||||
```http
|
||||
POST /api/admin/receipts/approve
|
||||
X-Admin-Token: change_this_long_random_admin_token
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"receipt_id": 1,
|
||||
"admin_user_id": 1
|
||||
}
|
||||
```
|
||||
|
||||
## Основные API
|
||||
|
||||
Регистрация:
|
||||
|
||||
```http
|
||||
POST /api/register
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"callsign": "R0XXX",
|
||||
"email": "user@example.com",
|
||||
"password": "strong-password"
|
||||
}
|
||||
```
|
||||
|
||||
Подтверждение платежа админом:
|
||||
|
||||
```http
|
||||
POST /api/admin/payments/confirm
|
||||
X-Admin-Token: change_this_long_random_admin_token
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"payment_id": 1,
|
||||
"admin_user_id": 1
|
||||
}
|
||||
```
|
||||
|
||||
Экспорт активных пользователей для gateway:
|
||||
|
||||
```http
|
||||
GET /api/admin/access/export
|
||||
X-Admin-Token: change_this_long_random_admin_token
|
||||
```
|
||||
|
||||
## Pi-Star и пароль
|
||||
|
||||
`xlxd` поднимает сам reflector и принимает MMDVM/DMR на UDP `62030`. Персональная проверка логина/пароля на уровне Pi-Star требует отдельного access gateway/proxy или auth-слоя перед reflector.
|
||||
|
||||
В проекте уже есть:
|
||||
|
||||
- хранение отдельного DMR-пароля;
|
||||
- включение/выключение доступа;
|
||||
- экспорт активных пользователей;
|
||||
- единая активация после YooKassa или ручного чека.
|
||||
|
||||
Следующий слой - UDP gateway, который будет читать экспорт активных пользователей и пропускать к `xlxd` только оплаченные подключения.
|
||||
@@ -20,7 +20,7 @@
|
||||
- [ ] форма регистрации;
|
||||
- [ ] нормализация позывного;
|
||||
- [ ] проверка формата позывного;
|
||||
- [ ] адаптер внешней базы позывных;
|
||||
- [x] проверка дублей позывных по внутренней базе;
|
||||
- [ ] ручная модерация спорных заявок;
|
||||
- [ ] автоматическая выдача ID;
|
||||
- [ ] защита от дублей;
|
||||
|
||||
Ссылка в новой задаче
Block a user