Files
netrunner-backend/Cargo.toml
T
nineap 375b333978 Ролевая админка (Owner/Moderator/Partner) + оплата через @CryptoBot
Ролевая система вместо привязки к Telegram
----------------------------------------
Раньше единственный способ получить админ-доступ — admin_guard, пускавший
по ADMIN_TG_ID или role=="admin" (без сеттера для роли). Заменяет на
Owner/Moderator/Partner:

- migrations/0005_roles_and_partners.sql — username/password_hash на users
  (NULL у обычных Ghost/Telegram-юзеров, тот же паттерн, что и у seed_hash/
  tg_id), can_manage_nodes, commission_percent, partner_code,
  referred_by_partner_id; новые таблицы partner_commissions и
  withdrawal_requests.
- auth/guard.rs — admin_guard заменён на owner_guard/staff_guard/
  node_manage_guard/partner_guard; ADMIN_TG_ID убран из ApiState и main.rs.
- auth/service.rs — hash_password/login_staff со случайной Argon2-солью на
  каждого юзера (не общий фиксированный ARGON_SALT, который годится для
  высокоэнтропийных seed-логинов, но не для человеческих паролей).
- POST /api/v1/auth/admin/login — вход модератора/партнёра/овнера паролем,
  переиспользует существующий issue_session().
- --create-owner CLI-флаг (main.rs) со скрытым вводом пароля (rpassword) —
  вместо ручного SQL для создания первого владельца с VPS-консоли.
- src/modules/staff/ — эндпоинты создания модераторов/партнёров, переключения
  can_manage_nodes, списка заявок на вывод и их approve/reject/paid.
- Комиссия партнёра начисляется в BillingService::confirm_payment отдельным
  шагом после существующей рефералки, пересчитывается через
  get_plan_price(invoice.plan_name, invoice.currency) — НЕ через
  invoice.amount напрямую, потому что у провайдеров разная внутренняя
  единица (TON — nanoTON+2% буфер, CryptoBot — фиатные центы напрямую).
- bot.rs — /start p_XXXXXX привязывает покупателя к партнёру по коду
  (first-wins, до существующих веток numeric-tg_id-рефералки и кода входа).
- frontend/ — AdminLogin/AdminLayout/StaffPage/WithdrawalsPage/EarningsPage
  поверх существующего Vite-админ-фронта (без отдельного проекта).

Оплата через @CryptoBot
------------------------
- modules/billing/providers/cryptobot.rs — новый PaymentProvider (Crypto Pay
  API), плюс попутно исправлены два реальных бага в существующем коде:
  confirm_payment был жёстко завязан на TON-провайдера при любом инвойсе, и
  InvoiceRecord не хранил currency, из-за чего TON-курс молча применялся ко
  всем провайдерам вместо родной валюты инвойса.
- bot.rs — экран выбора способа оплаты для CryptoBot-инвойсов.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-08 22:53:02 +07:00

50 lines
1.6 KiB
TOML

[package]
name = "netrunner-control-plane"
version = "0.2.0"
edition = "2021"
[dependencies]
tokio = { version = "1.40", features = ["full"] }
axum = { version = "0.8.9", features = ["macros"] }
tower = "0.5.3"
tower-http = { version = "0.6.8", features = ["fs", "trace", "cors"] }
tower_governor = "0.8"
teloxide = { version = "0.17", features = ["macros", "rustls"] }
# 🔥 ИСПРАВЛЕНО: Включаем "migrate" для автоматического создания баз в тестах
sqlx = { version = "0.8", features = ["runtime-tokio-rustls", "postgres", "uuid", "chrono", "migrate", "rust_decimal"] }
redis = { version = "1.2.0", features = ["tokio-comp", "aio", "connection-manager"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
uuid = { version = "1.10", features = ["v4", "serde"] }
chrono = { version = "0.4", features = ["serde"] }
thiserror = "2.0.18"
async-trait = "0.1"
tokio-util = { version = "0.7", features = ["rt"] }
jsonwebtoken = { version = "10.3", default-features = false, features = ["use_pem", "rust_crypto"] }
hmac = "0.13.0"
sha2 = "0.11.0"
hex = "0.4"
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter", "json"] }
metrics = "0.24.3"
metrics-exporter-prometheus = "0.18.1"
dotenvy = "0.15"
clap = { version = "4.6.1", features = ["derive"] }
ssh2 = "0.9.5"
rand = "0.8"
argon2 = "0.5"
rpassword = "7.5"
rust_decimal = { version = "1.42.0", features = ["serde"] }
reqwest = { version = "0.11", features = ["json"] }
[profile.release]
opt-level = 3
lto = "thin"
codegen-units = 16
panic = "abort"
strip = true