diff --git a/README.md b/README.md index 53d6065..3642d9b 100644 --- a/README.md +++ b/README.md @@ -1,134 +1,79 @@ -# XLX Server +# XLX Server — панель управления XLX/DMR-рефлектором с платной регистрацией -Собственный XLX/DMR-сервер для пользователей Pi-Star. +Серверная часть частного XLX-рефлектора: устанавливает и обслуживает `xlxd` (мультипротокольный рефлектор XLX для DMR/D-STAR/YSF), а поверх него даёт PHP-панель, в которой радиолюбитель регистрируется по позывному, оплачивает доступ (YooKassa или ручной перевод с чеком) и получает внутренний DMR ID и отдельный пароль для подключения хотспота Pi-Star. Администратору панель даёт status/start/stop/restart `xlxd`, редактирование его конфигурационных файлов (`xlxd.blacklist`, `xlxd.whitelist`, `xlxd.interlink`, `xlxd.terminal`) и дашборд последних событий из лога рефлектора. -## Что уже есть +Проект — серверный ответ на репозиторий `pistar` (скрипты, которые прописывают чужие рефлекторы в хотспоты): здесь рефлектор свой, с учётом пользователей и оплатой. -- платная регистрация; -- проверка позывного по внутренней базе зарегистрированных пользователей; -- YooKassa; -- ручной перевод с подтверждением по чеку; -- автоматическая выдача внутреннего DMR ID; -- отдельный DMR-пароль для Pi-Star; -- установка и управление `xlxd`; -- главный пользовательский дашборд `/`; -- админка настроек `xlxd` `/admin`; -- управление `xlxd` из админки: status/start/stop/restart; -- графический редактор `/xlxd/xlxd.blacklist`, `xlxd.whitelist`, `xlxd.interlink`, `xlxd.terminal`; -- статистика последних событий и вызовов на главной; -- экспорт активных пользователей для будущего access gateway. +## Стек -## Компоненты +- PHP 8 без фреймворка: свой автозагрузчик (`bootstrap.php`, префикс `Xlx\`), роутинг на `if` в `public/index.php`, PDO. +- MariaDB/MySQL, схема в `database/schema.sql`. +- Apache 2 + `libapache2-mod-php`, `FallbackResource /index.php`. +- systemd (`xlxd.service`), Bash-установщики, `sudoers`-правило для управления сервисом от `www-data`. +- Frontend: ванильные HTML/CSS/JS (`public/assets`), без сборки и зависимостей. +- Внешние зависимости: `xlxd` (сборка из `https://github.com/LX3JL/xlxd.git`), API YooKassa `https://api.yookassa.ru/v3`. +- Железо/протоколы: DMR (UDP 62030 для Pi-Star/MMDVM), YSF (42000), дашборд `xlxd` (8080). -- `xlxd` - мультипротокольный XLX reflector. -- `public/index.php` - PHP API и web routes. -- `public/assets` - стили и JS дашбордов. -- `src/Domain` - регистрация, проверка дублей позывного, оплата, выдача ID, настройки XLX. -- `database/schema.sql` - схема MariaDB/MySQL. -- `scripts/install-xlxd.sh` - установка и сборка `xlxd`. -- `scripts/xlx-control` - start/stop/status для systemd. +## Структура -## Быстрый старт XLX +| Путь | Назначение | +|---|---| +| `bootstrap.php` | Автозагрузчик, выбор конфига (`config/config.php`, иначе `config/config.example.php`), таймзона. | +| `public/index.php` | Единственная точка входа: HTML-страницы `/` и `/admin`, JSON API, webhook YooKassa. | +| `public/views/home.php` | Публичная страница: описание рефлектора, проверка позывного, форма регистрации. | +| `public/views/admin.php` | Админка: поле admin token, форма настроек `xlxd`, редактор конфиг-файлов, управление сервисом. | +| `public/assets/app.js`, `admin.js`, `styles.css` | Логика форм и запросов к API, стили. | +| `src/Support/Config.php` | Доступ к конфигу через точечные ключи (`billing.yookassa.shop_id`). | +| `src/Support/Database.php` | Создание PDO. | +| `src/Support/Input.php`, `Response.php` | Чтение JSON-тела запроса, JSON-ответы и ошибки. | +| `src/Support/Security.php` | Нормализация и валидация позывного (`/^[A-Z0-9][A-Z0-9\/-]{2,18}$/`), генерация пароля, подсказка пароля, проверка admin-токена. | +| `src/Domain/RegistrationService.php` | Проверка позывного на дубли по локальной базе, регистрация пользователя, создание платежа. | +| `src/Domain/PaymentService.php` | Создание платежа по тарифу, подтверждение вручную, приём и одобрение чека, обработка платежа YooKassa, продление `access_expires_at`. | +| `src/Domain/YooKassaClient.php` | HTTP-клиент YooKassa: создание платежа с ключом идемпотентности, чтение платежа. | +| `src/Domain/IdAllocator.php` | Выдача внутреннего DMR ID из диапазона (по умолчанию 9000001–9099999) с обработкой гонок по unique-индексу. | +| `src/Domain/AccessCredentialService.php` | Генерация и ротация отдельного DMR-пароля (хранится хешем, в базе остаётся только подсказка вида `abc...xyz`). | +| `src/Domain/AccessExportService.php` | CSV активных пользователей: позывной, DMR ID, username, подсказка пароля, срок доступа. | +| `src/Domain/XlxdSettingsService.php` | Настройки `xlxd` в таблице `server_settings`, рендер `/etc/xlx/xlxd.env`, запись файла при `apply=true`. | +| `src/Domain/XlxdConfigFileService.php` | Чтение и запись четырёх файлов `xlxd` из `XLX_INSTALL_PATH` (blacklist/whitelist/interlink/terminal). | +| `src/Domain/XlxdRuntimeService.php` | `systemctl is-active/is-enabled`, `sudo -n systemctl start|stop|restart`, парсинг последних строк `/var/log/xlxd.log`, счётчики для дашборда. | +| `database/schema.sql` | Таблицы: `users`, `callsign_checks`, `dmr_ids`, `tariffs`, `payments`, `payment_receipts`, `access_credentials`, `server_settings`, `connection_logs`, `audit_logs`, `xlx_service_events` + тариф по умолчанию (300 RUB / 30 дней). | +| `scripts/install-system.sh` | Полный установщик: пакеты, MariaDB, схема, генерация `config/config.php`, `/etc/xlx/xlxd.env`, Apache vhost, sudoers, сборка `xlxd`, вывод admin-токена и webhook URL. | +| `scripts/install-xlxd.sh` | Только сборка и установка `xlxd` из исходников, установка `xlx-control` и юнита. | +| `scripts/xlx-control` | start/stop/restart/status/render-modules для `xlxd`, генерация `xlxd.module` из списка модулей. | +| `scripts/firewall-ufw.sh` | Открытие портов ufw: 22/80/443 TCP и 8880, 10001, 10002, 30001, 30051, 42000, 62030 UDP. | +| `deploy/apache/xlx-panel.conf` | Шаблон vhost с плейсхолдерами `__PANEL_PORT__`, `__PUBLIC_DIR__`. | +| `deploy/systemd/xlxd.service` | Юнит `xlxd` типа forking через `xlx-control`. | +| `docs/` | `ARCHITECTURE.md`, `ROADMAP.md`, `INSTALL_SYSTEM.md`, `INSTALL_XLXD.md`, `PAYMENTS_AND_REGISTRATION.md`, `ADMIN_DASHBOARD.md`. | +| `README.upstream.md` | Прежний README автора. | -Для полной установки панели, базы, YooKassa-заготовки и самого `xlxd` используй общий установщик. +## Как запустить -### Установка без домена +Полная установка на чистый Ubuntu/Debian-сервер (от root): ```bash sudo apt update sudo apt install -y git -git clone https://github.com/viktor138irk/xlx.git +git clone <адрес репозитория> xlx cd xlx sudo bash scripts/install-system.sh ``` -Web-панель устанавливается в `/opt/xlx-server`, поэтому Apache не зависит от папки, где был выполнен `git clone`. +Панель копируется в `/opt/xlx-server`, поэтому каталог клона после установки не нужен. Порт панели выбирается автоматически: 80, иначе 8088/8090/8091/8099. В конце установщик печатает адрес сайта, адрес админки, admin token, webhook URL для YooKassa и реквизиты БД — их нужно сохранить, повторно они не показываются. -Установщик сам выберет адрес сервера: - -1. `XLX_PUBLIC_HOST`, если переменная задана; -2. `hostname -f`; -3. первый IP из `hostname -I`; -4. `127.0.0.1`, если ничего не найдено. - -В конце установки будут показаны: - -- адрес сайта; -- адрес админки; -- admin token; -- webhook URL для YooKassa; -- логин и пароль БД. - -### Установка с доменом - -```bash -sudo apt update -sudo apt install -y git -git clone https://github.com/viktor138irk/xlx.git -cd xlx -sudo XLX_PUBLIC_HOST=xlx.example.ru bash scripts/install-system.sh -``` - -Если домен появится позже, его можно поменять в админке `/admin`. - -### Установка с YooKassa +С доменом и платежами: ```bash sudo \ XLX_PUBLIC_HOST=xlx.example.ru \ - YOOKASSA_SHOP_ID=123456 \ - YOOKASSA_SECRET_KEY=secret_key \ - bash scripts/install-system.sh -``` - -Webhook для YooKassa установщик выведет в конце. Он выглядит так: - -```text -http://адрес-сервера/api/webhooks/yookassa?token=секрет -``` - -Если сервер работает через HTTPS: - -```bash -sudo \ XLX_PUBLIC_SCHEME=https \ - XLX_PUBLIC_HOST=xlx.example.ru \ - YOOKASSA_SHOP_ID=123456 \ - YOOKASSA_SECRET_KEY=secret_key \ + YOOKASSA_SHOP_ID= \ + YOOKASSA_SECRET_KEY=<см. .env / secret store> \ bash scripts/install-system.sh ``` -### После установки - -Открой: - -- `/` - главная страница и регистрация пользователей; -- `/admin` - админка настроек `xlxd`; -- `/api/health` - проверка API. - -Для Pi-Star нужен UDP порт `62030`. Также обычно открывают: +Только рефлектор, без панели: ```bash -sudo bash scripts/firewall-ufw.sh -``` - -### Управление XLX - -```bash -sudo systemctl start xlxd -sudo systemctl stop xlxd -sudo systemctl restart xlxd -sudo systemctl status xlxd -sudo tail -f /var/log/xlxd.log -``` - -### Только установка reflector - -Если нужна только сборка и запуск `xlxd` без полной панели: - -```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 @@ -136,15 +81,78 @@ sudo bash scripts/install-xlxd.sh sudo systemctl start xlxd ``` -## Документация +Эксплуатация: -- `docs/INSTALL_SYSTEM.md` - установка всей системы без привязки к домену или IP. -- `docs/INSTALL_XLXD.md` - установка reflector. -- `docs/PAYMENTS_AND_REGISTRATION.md` - регистрация, YooKassa и чеки. -- `docs/ADMIN_DASHBOARD.md` - главная и админка. +```bash +sudo systemctl {start|stop|restart|status} xlxd +sudo tail -f /var/log/xlxd.log +sudo bash scripts/firewall-ufw.sh +``` -## Статус +Основные маршруты: -v0.2.0-dev. +| Метод и путь | Назначение | +|---|---| +| `GET /`, `GET /dashboard` | Публичная страница и регистрация. | +| `GET /admin` | Админка. | +| `GET /api/health` | Проверка живости API. | +| `GET /api/dashboard/stats` | Статус сервиса, счётчики, последние события лога. | +| `GET /api/callsigns/check?callsign=` | Проверка формата и занятости позывного. | +| `POST /api/register` | Регистрация: позывной, email, пароль. | +| `POST /api/payments/receipt` | Отправка номера/ссылки чека при ручном переводе. | +| `POST /api/webhooks/yookassa?token=` | Webhook YooKassa, обрабатывается только событие `payment.succeeded`. | +| `POST /api/admin/payments/confirm` | Ручное подтверждение платежа. | +| `POST /api/admin/receipts/approve` | Одобрение чека. | +| `GET /api/admin/access/export` | CSV активных пользователей. | +| `GET/POST /api/admin/xlxd/settings` | Чтение и сохранение настроек `xlxd` (с опциональной записью `xlxd.env`). | +| `GET/POST /api/admin/xlxd/config-files` | Чтение и запись blacklist/whitelist/interlink/terminal. | +| `GET/POST /api/admin/xlxd/runtime` | Статус и управление сервисом (`start`, `stop`, `restart`, `status`). | -Следующий шаг - UDP access gateway для жесткой проверки оплаченного доступа перед `xlxd`. +Все `/api/admin/*` требуют заголовок `X-Admin-Token` со значением admin-токена. + +## Конфигурация + +Конфиг — `config/config.example.php`, все значения читаются из переменных окружения. Установщик генерирует `config/config.php`, который через `putenv()` задаёт значения и подключает example-файл. Реальные секреты после установки лежат в `config/config.php` и `/etc/xlx/xlxd.env` на сервере; в репозитории только плейсхолдеры `change_me`. + +| Переменная | Назначение | Пример | +|---|---|---| +| `XLX_PUBLIC_HOST` | Домен или IP панели | `xlx.example.ru` | +| `XLX_PUBLIC_SCHEME` | Схема для base URL | `https` | +| `XLX_PANEL_PORT` | Порт Apache для панели | `80` | +| `XLX_APP_ENV`, `XLX_DEBUG`, `XLX_TIMEZONE` | Окружение, отладка, таймзона | `production`, `0`, `Europe/Moscow` | +| `XLX_DB_HOST`, `XLX_DB_PORT`, `XLX_DB_NAME`, `XLX_DB_USER`, `XLX_DB_PASSWORD` | Доступ к БД | `127.0.0.1`, `3306`, `xlx_server`, `xlx_user`, см. вывод установщика | +| `XLX_REFLECTOR_NAME` | Имя рефлектора | `XLX391` | +| `XLX_SYSOP_CALLSIGN`, `XLX_SYSOP_EMAIL`, `XLX_COUNTRY` | Данные сисопа | `N0CALL`, `admin@example.ru`, `RU` | +| `XLX_DMR_PORT`, `XLX_YSF_PORT`, `XLX_DASHBOARD_PORT` | Порты рефлектора | `62030`, `42000`, `8080` | +| `XLX_DEFAULT_MODULE`, `XLX_MODULES` | Модуль по умолчанию и список модулей | `A`, `ABCDEFGHIJKLMNOPQRSTUVWXYZ` | +| `XLX_CONFIG_PATH`, `XLX_INSTALL_PATH`, `XLX_SOURCE_PATH`, `XLX_LOG_PATH`, `XLX_SERVICE_NAME` | Пути и имя сервиса | `/etc/xlx`, `/xlxd`, `/usr/src/xlxd`, `/var/log/xlxd.log`, `xlxd` | +| `XLX_REPO_URL` | Репозиторий исходников `xlxd` | `https://github.com/LX3JL/xlxd.git` | +| `XLX_MIN_ID`, `XLX_MAX_ID` | Диапазон выдаваемых внутренних DMR ID | `9000001`, `9099999` | +| `XLX_BILLING_MODE`, `XLX_CURRENCY`, `XLX_DEFAULT_DURATION_DAYS` | Режим оплаты, валюта, срок доступа | `yookassa`, `RUB`, `30` | +| `XLX_MANUAL_TRANSFER_ENABLED`, `XLX_MANUAL_TRANSFER_INSTRUCTIONS` | Ручной перевод и текст инструкции | `1`, произвольный текст | +| `YOOKASSA_SHOP_ID`, `YOOKASSA_SECRET_KEY` | Реквизиты магазина YooKassa | см. `config/config.php` на сервере | +| `YOOKASSA_RETURN_URL`, `YOOKASSA_WEBHOOK_SECRET`, `YOOKASSA_CAPTURE` | Возврат после оплаты, токен webhook, автосписание | `/payment/return`, случайный токен, `1` | +| `XLX_SESSION_NAME`, `XLX_PASSWORD_MIN_LENGTH`, `XLX_DMR_PASSWORD_LENGTH` | Имя сессии, минимальная длина пароля кабинета, длина DMR-пароля | `xlx_session`, `10`, `16` | +| `XLX_ADMIN_TOKEN` | Токен для `X-Admin-Token` | генерируется установщиком (48 символов) | +| `XLX_APP_DIR` | Каталог установки панели | `/opt/xlx-server` | + +Файл `/etc/xlx/xlxd.env` (шаблон `config/xlxd.env.example`) читают `xlx-control` и юнит systemd. + +## Состояние + +Прототип, доведённый до устанавливаемого состояния, работа остановлена. Все 12 коммитов сделаны в один день — 2026-05-18, последний коммит 2026-05-18. `VERSION` — `0.2.0-dev`. + +Установщик, схема БД, API регистрации и оплаты, управление `xlxd` и редактор его конфигов написаны и внутренне согласованы. На боевом сервере проект не подтверждён из кода. + +## Что не доделано + +- Ключевой пункт из плана автора — UDP access gateway, который должен реально пускать к `xlxd` только оплаченных пользователей, — не реализован. Сейчас оплата и выданный DMR-пароль ни на что не влияют: `xlxd` принимает подключения по своим правилам, а связь панели с ним ограничена CSV-экспортом (`/api/admin/access/export`) и ручным редактированием whitelist/blacklist. +- Нет личного кабинета и вообще авторизации пользователей: пароль при регистрации хешируется и сохраняется, но маршрута логина и сессий нет, хотя настройки сессии в конфиге есть. Пользователь получает DMR ID и пароль один раз в ответе на `POST /api/register` и посмотреть их повторно не может. +- Админка защищена одним статическим токеном в заголовке, который вводится в поле на странице; ролей `moderator`/`admin` из схемы БД код не использует, `admin_user_id` приходит с клиента и не проверяется. +- Таблицы `callsign_checks`, `connection_logs`, `audit_logs`, `xlx_service_events` созданы, но код в них ничего не пишет. Дашборд «последние события» парсит текстовый лог `/var/log/xlxd.log`, а не БД. +- Проверка позывного идёт только по локальной базе зарегистрированных; сверки с внешним реестром (RadioID/QRZ) нет, хотя поле `source` в `callsign_checks` это предполагает. +- Тарифов в UI нет — используется единственная запись, вставленная схемой (300 RUB / 30 дней); управления тарифами и продлением из админки нет. +- `docs/ROADMAP.md` почти целиком не отмечен: из ~70 пунктов выполнено 4. Не сделаны миграции БД, бэкапы и обновления, rate-limit, SSL helper, уведомления пользователю, автопродление. +- Тестов нет вообще, CI нет, зависимостей Composer нет. +- Маркеров TODO/FIXME в коде нет — незавершённость видна по roadmap и пустым таблицам. +- `README.upstream.md` описывает часть возможностей как готовые (например, «экспорт активных пользователей для будущего access gateway»), что стоит сверять с этим списком. diff --git a/README.upstream.md b/README.upstream.md new file mode 100644 index 0000000..53d6065 --- /dev/null +++ b/README.upstream.md @@ -0,0 +1,150 @@ +# XLX Server + +Собственный XLX/DMR-сервер для пользователей Pi-Star. + +## Что уже есть + +- платная регистрация; +- проверка позывного по внутренней базе зарегистрированных пользователей; +- YooKassa; +- ручной перевод с подтверждением по чеку; +- автоматическая выдача внутреннего DMR ID; +- отдельный DMR-пароль для Pi-Star; +- установка и управление `xlxd`; +- главный пользовательский дашборд `/`; +- админка настроек `xlxd` `/admin`; +- управление `xlxd` из админки: status/start/stop/restart; +- графический редактор `/xlxd/xlxd.blacklist`, `xlxd.whitelist`, `xlxd.interlink`, `xlxd.terminal`; +- статистика последних событий и вызовов на главной; +- экспорт активных пользователей для будущего access gateway. + +## Компоненты + +- `xlxd` - мультипротокольный XLX reflector. +- `public/index.php` - PHP API и web routes. +- `public/assets` - стили и JS дашбордов. +- `src/Domain` - регистрация, проверка дублей позывного, оплата, выдача ID, настройки XLX. +- `database/schema.sql` - схема MariaDB/MySQL. +- `scripts/install-xlxd.sh` - установка и сборка `xlxd`. +- `scripts/xlx-control` - start/stop/status для systemd. + +## Быстрый старт XLX + +Для полной установки панели, базы, YooKassa-заготовки и самого `xlxd` используй общий установщик. + +### Установка без домена + +```bash +sudo apt update +sudo apt install -y git +git clone https://github.com/viktor138irk/xlx.git +cd xlx +sudo bash scripts/install-system.sh +``` + +Web-панель устанавливается в `/opt/xlx-server`, поэтому Apache не зависит от папки, где был выполнен `git clone`. + +Установщик сам выберет адрес сервера: + +1. `XLX_PUBLIC_HOST`, если переменная задана; +2. `hostname -f`; +3. первый IP из `hostname -I`; +4. `127.0.0.1`, если ничего не найдено. + +В конце установки будут показаны: + +- адрес сайта; +- адрес админки; +- admin token; +- webhook URL для YooKassa; +- логин и пароль БД. + +### Установка с доменом + +```bash +sudo apt update +sudo apt install -y git +git clone https://github.com/viktor138irk/xlx.git +cd xlx +sudo XLX_PUBLIC_HOST=xlx.example.ru bash scripts/install-system.sh +``` + +Если домен появится позже, его можно поменять в админке `/admin`. + +### Установка с YooKassa + +```bash +sudo \ + XLX_PUBLIC_HOST=xlx.example.ru \ + YOOKASSA_SHOP_ID=123456 \ + YOOKASSA_SECRET_KEY=secret_key \ + bash scripts/install-system.sh +``` + +Webhook для YooKassa установщик выведет в конце. Он выглядит так: + +```text +http://адрес-сервера/api/webhooks/yookassa?token=секрет +``` + +Если сервер работает через HTTPS: + +```bash +sudo \ + XLX_PUBLIC_SCHEME=https \ + XLX_PUBLIC_HOST=xlx.example.ru \ + YOOKASSA_SHOP_ID=123456 \ + YOOKASSA_SECRET_KEY=secret_key \ + bash scripts/install-system.sh +``` + +### После установки + +Открой: + +- `/` - главная страница и регистрация пользователей; +- `/admin` - админка настроек `xlxd`; +- `/api/health` - проверка API. + +Для Pi-Star нужен UDP порт `62030`. Также обычно открывают: + +```bash +sudo bash scripts/firewall-ufw.sh +``` + +### Управление XLX + +```bash +sudo systemctl start xlxd +sudo systemctl stop xlxd +sudo systemctl restart xlxd +sudo systemctl status xlxd +sudo tail -f /var/log/xlxd.log +``` + +### Только установка reflector + +Если нужна только сборка и запуск `xlxd` без полной панели: + +```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 +sudo bash scripts/install-xlxd.sh +sudo systemctl start xlxd +``` + +## Документация + +- `docs/INSTALL_SYSTEM.md` - установка всей системы без привязки к домену или IP. +- `docs/INSTALL_XLXD.md` - установка reflector. +- `docs/PAYMENTS_AND_REGISTRATION.md` - регистрация, YooKassa и чеки. +- `docs/ADMIN_DASHBOARD.md` - главная и админка. + +## Статус + +v0.2.0-dev. + +Следующий шаг - UDP access gateway для жесткой проверки оплаченного доступа перед `xlxd`.