Documentation
¶
Overview ¶
Package core ties the store and the Xray supervisor together: mutations go through it so the proxy config is reconciled from the DB after every change.
Index ¶
- func EventPageLimit(n int) int
- func NormalizeACMEHost(target string) string
- type ConnInfo
- type ConnectionsStatus
- type ConnectionsUpdate
- type HealthCheck
- type HealthReport
- type Manager
- func (m *Manager) ActivePaidPlan(u model.User) *model.TariffPlan
- func (m *Manager) AddAdminAudit(ev model.AdminAudit)
- func (m *Manager) AdminAudit(f store.AdminAuditFilter) ([]model.AdminAudit, error)
- func (m *Manager) AdminEventPrefs() map[string]bool
- func (m *Manager) AppLogTail() []string
- func (m *Manager) ApplyConnections(u ConnectionsUpdate) error
- func (m *Manager) ApplyPlanToUser(ctx context.Context, userID int64, planID int64, extendFromCurrent bool) error
- func (m *Manager) ApplyRouting(cfg model.RoutingConfig, warpEnabled, operaEnabled bool, operaCountry string) error
- func (m *Manager) AuditTelegramLinked(ctx context.Context, id int64, username string)
- func (m *Manager) BackupManifest() backup.Manifest
- func (m *Manager) BulkUserAction(ctx context.Context, ids []int64, action string, days int) (int, error)
- func (m *Manager) CancelPayment(ctx context.Context, orderID int64) error
- func (m *Manager) CancelTelegramLink() error
- func (m *Manager) CancelUserPlan(ctx context.Context, userID int64) error
- func (m *Manager) CertPinSHA256() string
- func (m *Manager) ChangeAdminPassword(adminID int64, newPassword string) error
- func (m *Manager) ConfirmPayment(ctx context.Context, orderID int64) error
- func (m *Manager) Connections(id int64) ([]model.Connection, error)
- func (m *Manager) ConnectionsInfo() (*ConnectionsStatus, error)
- func (m *Manager) CreateAdmin(username, password, role string) (model.Admin, error)
- func (m *Manager) CreateRegisteredUser(ctx context.Context, name string) (*model.User, error)
- func (m *Manager) CreateUser(ctx context.Context, name string, dataLimit, expireAt int64) (*model.User, error)
- func (m *Manager) DeleteAdmin(actorID, targetID int64) error
- func (m *Manager) DeleteTariffPlan(id int64) error
- func (m *Manager) DeleteUser(ctx context.Context, id int64) error
- func (m *Manager) EmitWebhook(event string, data any)
- func (m *Manager) EnforceBilling(now int64) error
- func (m *Manager) Events(f store.UserEventFilter) ([]model.UserEvent, error)
- func (m *Manager) FetchRoutingTemplate(url string) (string, error)
- func (m *Manager) FinishSetup() error
- func (m *Manager) GenerateTelegramLinkCode() (string, error)
- func (m *Manager) GenerateUserTgLinkCode(userID int64) (string, error)
- func (m *Manager) GeoCategories() (geosite, geoip []string, err error)
- func (m *Manager) GeoStatus() []geo.FileInfo
- func (m *Manager) HandleCryptoBotWebhook(body []byte, signature string) error
- func (m *Manager) HandleYooKassaWebhook(body []byte) error
- func (m *Manager) HasValidCert() bool
- func (m *Manager) Health() *HealthReport
- func (m *Manager) ListAdmins() ([]model.Admin, error)
- func (m *Manager) ListPaymentOrders(status string) ([]model.PaymentOrder, error)
- func (m *Manager) ListTariffPlans(includeDisabled bool) ([]model.TariffPlan, error)
- func (m *Manager) ListUsers() ([]model.User, error)
- func (m *Manager) Location() *time.Location
- func (m *Manager) MigratePlanUsers(ctx context.Context, fromPlanID, toPlanID int64) (int, error)
- func (m *Manager) OperaHealthy() bool
- func (m *Manager) OperaRunning() bool
- func (m *Manager) PaymentMethods() []string
- func (m *Manager) PaymentStats() (*model.PaymentStats, error)
- func (m *Manager) PaymentWebhookSecret() string
- func (m *Manager) PaymentWebhookURLs() (yookassa, cryptobot string)
- func (m *Manager) PlanName(planID int64) string
- func (m *Manager) PollPendingPayments()
- func (m *Manager) PollStats() error
- func (m *Manager) ProxyCount() int
- func (m *Manager) ProxyCounts() map[string]int
- func (m *Manager) PurgeExpiredUsers()
- func (m *Manager) PurgeOldAdminAudit()
- func (m *Manager) PurgeOldConnections()
- func (m *Manager) PurgeOldEvents()
- func (m *Manager) Reconcile() error
- func (m *Manager) RecordAccess(email, ip string)
- func (m *Manager) RefreshGeo() ([]geo.FileInfo, error)
- func (m *Manager) RefreshProxies()
- func (m *Manager) RegenerateSecretPath() (string, error)
- func (m *Manager) RenameUser(ctx context.Context, id int64, name string) error
- func (m *Manager) RenewTLSIfNeeded() (bool, error)
- func (m *Manager) RequestPlanPayment(ctx context.Context, userID, planID int64) (*model.PaymentOrder, string, error)
- func (m *Manager) ResetAdminPassword(actorID, targetID int64, password string) error
- func (m *Manager) ResetStats() error
- func (m *Manager) ResetTraffic(ctx context.Context, id int64) error
- func (m *Manager) RestartXray() error
- func (m *Manager) RotateSubToken(ctx context.Context, id int64) (*model.User, error)
- func (m *Manager) SaveAdminEventPrefs(prefs map[string]bool) error
- func (m *Manager) SaveBillingSettings(st *model.Settings) error
- func (m *Manager) SaveLocalBackup(expr string, keep int) error
- func (m *Manager) SavePaymentSettings(st *model.Settings) error
- func (m *Manager) SaveSubSettings(st *model.Settings) error
- func (m *Manager) SaveTariffPlan(p *model.TariffPlan) error
- func (m *Manager) SaveTelegram(enabled bool, token, backupCron string) error
- func (m *Manager) SaveTelegramUserBot(enabled bool, token string, regEnabled bool) error
- func (m *Manager) SeedProxies()
- func (m *Manager) SelfTest(ctx context.Context) ([]selftest.Result, error)
- func (m *Manager) SetACMETarget(target, email, provider, eabKID, eabHMAC string) error
- func (m *Manager) SetAdminNotifier(fn func(html string))
- func (m *Manager) SetAdminRole(actorID, targetID int64, role string) error
- func (m *Manager) SetConnGuardWanted(v bool)
- func (m *Manager) SetDecoyTemplate(name string) error
- func (m *Manager) SetPanelName(name string) error
- func (m *Manager) SetPanelTheme(t branding.Theme) error
- func (m *Manager) SetProxyMode(enabled bool, typ string, port int, user, pass string) error
- func (m *Manager) SetResetPeriod(ctx context.Context, id int64, period string) error
- func (m *Manager) SetTimezone(name string) error
- func (m *Manager) SetUserAutoDelete(days int) error
- func (m *Manager) SetUserEnabled(ctx context.Context, id int64, enabled bool) error
- func (m *Manager) SetUserLimits(ctx context.Context, id, dataLimit, expireAt int64, deviceLimit int) error
- func (m *Manager) SetUserNotifier(fn func(chatID int64, html string))
- func (m *Manager) SetXrayDNS(dns string) error
- func (m *Manager) Settings() (*model.Settings, error)
- func (m *Manager) StartPlanPayment(ctx context.Context, userID, planID int64, provider string) (*model.PaymentOrder, error)
- func (m *Manager) StartPlanPaymentReturn(ctx context.Context, userID, planID int64, provider, returnURL string) (*model.PaymentOrder, error)
- func (m *Manager) StartSysstat(diskPath string)
- func (m *Manager) StatsByUser(from, to string) ([]model.UserTotal, error)
- func (m *Manager) StatsSeries(userID int64, from, to string) ([]model.DailyPoint, error)
- func (m *Manager) Store() *store.Store
- func (m *Manager) SubscribeAppLogs() (<-chan string, func())
- func (m *Manager) SubscribeXrayLogs() (<-chan string, func())
- func (m *Manager) Summary() (*Summary, error)
- func (m *Manager) SystemStatus() (*SystemStatus, error)
- func (m *Manager) TLSStatus() (*TLSStatus, error)
- func (m *Manager) TestWebhook(id int64) (int, error)
- func (m *Manager) TrackVPNViewer() func()
- func (m *Manager) TriggerReconcile()
- func (m *Manager) TriggerUserSync()
- func (m *Manager) UnlinkTelegramChat(id int64) error
- func (m *Manager) UnlinkUserTelegram(ctx context.Context, id int64) error
- func (m *Manager) UpdateAdminCredentials(adminID int64, currentPassword, username, password, keepToken string) error
- func (m *Manager) UserEvents(userID int64, limit int, beforeID int64) ([]model.UserEvent, error)
- func (m *Manager) XrayConfig() ([]byte, error)
- func (m *Manager) XrayLogTail() []string
- func (m *Manager) XrayStatus() (running bool, startedAt int64)
- type Summary
- type SystemStatus
- type TLSPaths
- type TLSStatus
- type ValidationError
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func EventPageLimit ¶ added in v0.13.0
EventPageLimit is the effective page size for a requested limit. The HTTP layer applies it too, so its "was this page full?" cursor check compares against the same number the store was actually asked for.
func NormalizeACMEHost ¶ added in v0.5.0
NormalizeACMEHost lowercases domain targets for ACME (CAs canonicalize DNS names; mixed case like WaifuVPN.example.com makes lego reject the order).
Types ¶
type ConnInfo ¶
type ConnInfo struct {
Key string `json:"key"`
// Name is the default protocol label (shown as the input placeholder).
Name string `json:"name"`
// DisplayName is the admin-configured custom node name (empty ⇒ use Name).
DisplayName string `json:"display_name"`
Transport string `json:"transport"`
Security string `json:"security"`
Port string `json:"port"`
Note string `json:"note"`
Enabled bool `json:"enabled"`
// Fingerprint is the protocol's uTLS fingerprint (empty for Hysteria2, which
// has no uTLS — the UI then shows no fingerprint control for it).
Fingerprint string `json:"fingerprint"`
}
ConnInfo describes one client-facing protocol endpoint. Key is the stable identifier used to toggle the protocol; Enabled reports whether it currently appears in user subscriptions.
type ConnectionsStatus ¶
type ConnectionsStatus struct {
Host string `json:"host"`
SNI string `json:"sni"`
WSPath string `json:"ws_path"` // Trojan-WS path
Protocols []ConnInfo `json:"protocols"`
// Hysteria2 base port, hop range, and rotation interval (UDP port-hopping).
HysteriaPort int `json:"hysteria_port"`
HopStart int `json:"hop_start"`
HopEnd int `json:"hop_end"`
HopInterval string `json:"hop_interval"`
// VLESS + gRPC + REALITY parameters (public key / shortId / service name are
// generated by the panel and shown read-only for reference).
RealityPort int `json:"reality_port"`
RealityDest string `json:"reality_dest"`
RealityPublicKey string `json:"reality_public_key"`
RealityShortID string `json:"reality_short_id"`
RealityServiceName string `json:"reality_service_name"`
RealityAntiReplay bool `json:"reality_anti_replay"` // REALITY maxTimeDiff > 0
// Anti-DPI transport hardening (cross-protocol).
TLSFragment bool `json:"tls_fragment"` // sing-box ClientHello fragmentation
TLSMin13 bool `json:"tls_min13"` // require TLS 1.3 on :443
BlockQUIC bool `json:"block_quic"` // drop untunneled browser QUIC in client configs
}
ConnectionsStatus is the public connection surface: where clients connect and how, per protocol.
type ConnectionsUpdate ¶
type ConnectionsUpdate struct {
Protocols map[string]bool `json:"protocols"` // key → enabled
Fingerprints map[string]string `json:"fingerprints"` // key → uTLS fingerprint
Names map[string]string `json:"names"` // key → custom node name ("" = default)
WSPath string `json:"ws_path"`
HysteriaPort int `json:"hysteria_port"`
HopStart int `json:"hop_start"`
HopEnd int `json:"hop_end"`
HopInterval string `json:"hop_interval"`
RealityPort int `json:"reality_port"`
RealityDest string `json:"reality_dest"`
RealityAntiReplay bool `json:"reality_anti_replay"`
// RegenRealityKeys requests a fresh REALITY keypair / shortId / service name.
RegenRealityKeys bool `json:"regen_reality_keys"`
// Anti-DPI transport hardening (cross-protocol).
TLSFragment bool `json:"tls_fragment"`
TLSMin13 bool `json:"tls_min13"`
BlockQUIC bool `json:"block_quic"`
}
ConnectionsUpdate is the full client-facing connection configuration applied in one shot: protocol toggles, link fingerprint, Trojan-WS path, and the Hysteria2 base port / hop range / rotation interval.
type HealthCheck ¶ added in v0.7.0
type HealthCheck struct {
Key string `json:"key"`
Label string `json:"label"`
Status string `json:"status"` // ok | warn | error | info
Detail string `json:"detail"`
Hint string `json:"hint,omitempty"` // shown when the check isn't ok
}
HealthCheck is one diagnostic line shown on the Health page.
type HealthReport ¶ added in v0.7.0
type HealthReport struct {
Status string `json:"status"`
Checks []HealthCheck `json:"checks"`
}
HealthReport aggregates the per-component checks plus the worst overall status.
type Manager ¶
type Manager struct {
// contains filtered or unexported fields
}
Manager is the application service layer.
func New ¶
func New(st *store.Store, sup *xray.Supervisor, opts xray.Options, tls TLSPaths, operaDir string) *Manager
New builds a Manager. opts carries non-DB generation parameters (e.g. the panel's loopback fallback dest); tls carries the managed cert paths; operaDir is where the opera-proxy helper binary is downloaded/run from.
func (*Manager) ActivePaidPlan ¶ added in v0.11.0
func (m *Manager) ActivePaidPlan(u model.User) *model.TariffPlan
ActivePaidPlan returns the user's current tariff when it's a paid plan that is still active (expiry in the future), else nil. This is the "locked" state where only renewal or cancellation is allowed — not switching to another plan. A trial or free plan (price 0) never counts, so upgrading from those stays open.
func (*Manager) AddAdminAudit ¶ added in v0.14.0
func (m *Manager) AddAdminAudit(ev model.AdminAudit)
AddAdminAudit records one event.
func (*Manager) AdminAudit ¶ added in v0.14.0
func (m *Manager) AdminAudit(f store.AdminAuditFilter) ([]model.AdminAudit, error)
AdminAudit returns the admin trail, newest first.
func (*Manager) AdminEventPrefs ¶ added in v0.7.0
AdminEventPrefs returns the per-category on/off map for the settings UI.
func (*Manager) AppLogTail ¶
AppLogTail returns the buffered recent panel log lines (for the dashboard).
func (*Manager) ApplyConnections ¶
func (m *Manager) ApplyConnections(u ConnectionsUpdate) error
ApplyConnections validates and persists the whole connection surface, then does a SINGLE reconcile (and one nft hop refresh) — so a multi-field save restarts Xray at most once instead of once per field. The reconcile is a no-op for the Xray process when only link-level fields (fingerprint, interval) changed.
func (*Manager) ApplyPlanToUser ¶ added in v0.4.0
func (m *Manager) ApplyPlanToUser(ctx context.Context, userID int64, planID int64, extendFromCurrent bool) error
ApplyPlanToUser assigns a tariff and updates limits. extendFromCurrent stacks paid time. planID 0 switches to manual mode: clears plan link and resets limits to unlimited.
func (*Manager) ApplyRouting ¶
func (m *Manager) ApplyRouting(cfg model.RoutingConfig, warpEnabled, operaEnabled bool, operaCountry string) error
ApplyRouting persists the routing config plus the WARP/Opera on/off state in one shot, then reconciles once. The first WARP enable provisions a free WARP account (Cloudflare device registration) and caches the WireGuard credentials; later toggles reuse them. Enabling Opera downloads + launches the helper for the chosen region.
func (*Manager) AuditTelegramLinked ¶ added in v0.13.0
AuditTelegramLinked records that a user bound their Telegram account (the bind itself happens in the user bot, which owns the one-time code).
func (*Manager) BackupManifest ¶
BackupManifest returns a Manifest describing the current server state for inclusion in backup archives.
func (*Manager) BulkUserAction ¶ added in v0.7.0
func (m *Manager) BulkUserAction(ctx context.Context, ids []int64, action string, days int) (int, error)
BulkUserAction applies one action to many users with a SINGLE config sync at the end (instead of one per user), returning how many users were actually affected. Actions: "enable", "disable", "delete", "reset" (traffic), "extend" (push expiry by `days`). "extend" only touches users that already have an expiry — unlimited users are left alone (extending "never" is meaningless) and not counted.
func (*Manager) CancelPayment ¶ added in v0.4.0
func (*Manager) CancelTelegramLink ¶ added in v0.2.0
CancelTelegramLink clears the pending one-time link code (cancels a link request).
func (*Manager) CancelUserPlan ¶ added in v0.11.0
CancelUserPlan cancels a paid subscription immediately: the user is moved to the free plan right away (losing any remaining paid time), matching what EnforceBilling does on expiry — but on demand. With no free plan configured, access is ended instead (plan cleared, expired now). The consumed-trial flag is preserved so cancelling can't reopen a fresh trial.
func (*Manager) CertPinSHA256 ¶
CertPinSHA256 returns the hex SHA-256 of the active leaf certificate, for clients to pin via pinnedPeerCertSha256 when the cert isn't CA-trusted. "" if unavailable.
func (*Manager) ChangeAdminPassword ¶
ChangeAdminPassword hashes and stores a new password for the given admin and lifts that admin's forced-password-change gate (a password the admin picked themselves is exactly what the gate is waiting for).
func (*Manager) ConfirmPayment ¶ added in v0.4.0
ConfirmPayment marks an order paid and applies the plan. Idempotent: the atomic pending→paid claim means a double-submit / retry (or an overlap with the provider webhook on a provider order) applies the plan at most once.
func (*Manager) Connections ¶
func (m *Manager) Connections(id int64) ([]model.Connection, error)
Connections returns a user's recent source IPs.
func (*Manager) ConnectionsInfo ¶
func (m *Manager) ConnectionsInfo() (*ConnectionsStatus, error)
ConnectionsInfo reports the enabled protocols and their connection parameters, derived from settings.
func (*Manager) CreateAdmin ¶ added in v0.14.0
CreateAdmin adds an account with a role and a password the owner picked. The account is gated on a password change at first login: a password chosen by someone else and delivered over a chat window is a bootstrap credential, not a permanent one.
func (*Manager) CreateRegisteredUser ¶ added in v0.4.0
CreateRegisteredUser creates a user from self-registration (trial/free/plain per billing config) and alerts the admin chats about the new signup.
func (*Manager) CreateUser ¶
func (m *Manager) CreateUser(ctx context.Context, name string, dataLimit, expireAt int64) (*model.User, error)
CreateUser creates a user (one credential set for all protocols) with optional data limit (bytes, 0=unlimited) and expiry (unix, 0=never), then reconciles.
func (*Manager) DeleteAdmin ¶ added in v0.14.0
DeleteAdmin removes an account. Deleting it revokes its sessions too (the admin_sessions rows cascade), so a colleague who is let go loses the panel on their next request, not when their cookie happens to expire.
func (*Manager) DeleteTariffPlan ¶ added in v0.4.0
func (*Manager) DeleteUser ¶
DeleteUser removes a user and reconciles.
func (*Manager) EmitWebhook ¶ added in v0.10.0
EmitWebhook fans an event out to all subscribed endpoints. It builds the signed body once per endpoint (each has its own secret) and enqueues the deliveries. Best-effort and non-blocking: any error is logged, never surfaced to the caller.
func (*Manager) EnforceBilling ¶ added in v0.4.0
EnforceBilling downgrades users whose paid/trial period ended to the free plan. It runs off the background poller, so its audit rows are attributed to the system.
func (*Manager) Events ¶ added in v0.13.0
Events returns the global audit trail, newest first (the journal page).
func (*Manager) FetchRoutingTemplate ¶
FetchRoutingTemplate returns the body of a routing-template URL WITHOUT ever blocking the caller on a slow remote when a cached copy exists: a fresh entry is returned as-is, a stale one is returned immediately while a refresh runs in the background (stale-while-revalidate). Only a completely cold cache fetches synchronously — and then with a short budget. This is what keeps the Happ/INCY subscription pull from timing out when GitHub is slow: previously a cold/stale cache forced an inline 8s GET, so the whole subscription response hung.
func (*Manager) FinishSetup ¶
FinishSetup marks the first-run wizard as completed.
func (*Manager) GenerateTelegramLinkCode ¶ added in v0.2.0
GenerateTelegramLinkCode issues a fresh one-time linking code and persists it. The operator sends "/start <code>" to the bot once to authorize their chat; the bot burns the code on use. Refused when the bot is disabled — it isn't polling then, so the code could never be redeemed.
func (*Manager) GenerateUserTgLinkCode ¶ added in v0.4.0
GenerateUserTgLinkCode issues a fresh one-time code for binding a VPN user to the public Telegram bot. It replaces the old sub-token deep link, so a leaked link expires (TelegramLinkCodeTTL) and can't be reused after binding.
func (*Manager) GeoCategories ¶
GeoCategories returns the geosite + geoip category codes from the on-disk databases, parsed once and cached (the .dat files only change on refresh).
func (*Manager) GeoStatus ¶
GeoStatus reports the on-disk state of the geoip/geosite databases (presence, size, last-download time) for the settings UI.
func (*Manager) HandleCryptoBotWebhook ¶ added in v0.6.0
HandleCryptoBotWebhook verifies the signature and confirms a paid invoice.
func (*Manager) HandleYooKassaWebhook ¶ added in v0.6.0
HandleYooKassaWebhook processes a notification. The POST body is not trusted — the payment is re-fetched via the API before the order is confirmed.
func (*Manager) HasValidCert ¶
HasValidCert reports whether a non-expired, CA-issued certificate is present. A self-signed fallback cert is deliberately treated as "not valid" so the renew loop stays in its fast-retry cadence until a real ACME cert is obtained.
func (*Manager) Health ¶ added in v0.7.0
func (m *Manager) Health() *HealthReport
Health gathers the panel's self-diagnostics: the Xray process, last config apply, TLS certificate, disk/RAM headroom, geo databases, and any enabled helper egress lane. Every signal is read from memory/disk — no extra network calls — so the page is cheap to poll.
func (*Manager) ListAdmins ¶ added in v0.14.0
ListAdmins returns the admin roster.
func (*Manager) ListPaymentOrders ¶ added in v0.4.0
func (m *Manager) ListPaymentOrders(status string) ([]model.PaymentOrder, error)
func (*Manager) ListTariffPlans ¶ added in v0.4.0
func (m *Manager) ListTariffPlans(includeDisabled bool) ([]model.TariffPlan, error)
ListTariffPlans returns tariff plans for admin UI.
func (*Manager) ListUsers ¶ added in v0.2.0
ListUsers returns all users, newest first (read-only; used by the Telegram bot).
func (*Manager) Location ¶
Location exposes the operator timezone for handlers that compute date ranges.
func (*Manager) MigratePlanUsers ¶ added in v0.11.0
MigratePlanUsers moves every user currently on fromPlanID to toPlanID (applying the target plan's limits and period). Used when retiring a plan. Returns how many users were moved.
func (*Manager) OperaHealthy ¶
OperaHealthy reports the last probe result for the Opera lane.
func (*Manager) OperaRunning ¶
OperaRunning reports whether the opera-proxy helper is currently up.
func (*Manager) PaymentMethods ¶ added in v0.6.0
PaymentMethods returns the enabled, fully-configured provider keys.
func (*Manager) PaymentStats ¶ added in v0.10.0
func (m *Manager) PaymentStats() (*model.PaymentStats, error)
PaymentStats assembles the revenue dashboard: all-time and per-provider paid totals, revenue since local midnight / the 1st of the month, and the pending backlog. Day/month boundaries use the operator's configured timezone.
func (*Manager) PaymentWebhookSecret ¶ added in v0.6.0
PaymentWebhookSecret returns the random webhook URL segment (may be empty).
func (*Manager) PaymentWebhookURLs ¶ added in v0.6.0
PaymentWebhookURLs returns the public webhook URLs to paste into the provider dashboards. Empty when the host or secret isn't known yet.
func (*Manager) PollPendingPayments ¶ added in v0.6.0
func (m *Manager) PollPendingPayments()
PollPendingPayments is the fallback for missed webhooks: it queries each pending provider order's status and confirms/cancels accordingly.
func (*Manager) PollStats ¶
PollStats reads per-user traffic from Xray, accumulates lifetime totals (handling counter resets on Xray restart), and enforces quotas/expiry.
func (*Manager) ProxyCount ¶
ProxyCount reports how many proxies are currently live across all lanes.
func (*Manager) ProxyCounts ¶ added in v0.14.0
ProxyCounts reports how many proxies each lane currently has, keyed by lane ID (a lane with none is absent). Feeds the per-lane status badges in the panel.
func (*Manager) PurgeExpiredUsers ¶ added in v0.15.0
func (m *Manager) PurgeExpiredUsers()
PurgeExpiredUsers deletes users whose expiry date is further in the past than the configured grace period. Called from the retention sweep; a no-op when the setting is 0 (the default), so an operator who never opts in never loses a user.
Deletion is irreversible, so it is deliberately conservative:
- it keys off expire_at, not the derived `status` (see store.ExpiredUsersBefore) — a user whose plan was renewed has a future expiry and is never a candidate;
- users with no expiry date at all are never touched;
- every deletion is written to the user journal (which outlives the user) and pushed as a webhook, so «где мой пользователь?» always has an answer.
func (*Manager) PurgeOldAdminAudit ¶ added in v0.14.0
func (m *Manager) PurgeOldAdminAudit()
PurgeOldAdminAudit drops trail rows past the retention window. Called from the same slow timer as the user journal's sweep.
func (*Manager) PurgeOldConnections ¶ added in v0.13.0
func (m *Manager) PurgeOldConnections()
PurgeOldConnections drops connection rows whose IP hasn't been seen inside the retention window. Shares the audit sweep's slow timer; safe to call repeatedly.
func (*Manager) PurgeOldEvents ¶ added in v0.13.0
func (m *Manager) PurgeOldEvents()
PurgeOldEvents drops audit rows past the retention window. Called on a slow timer from the service loop; safe to call as often as you like.
func (*Manager) Reconcile ¶
Reconcile regenerates the Xray config from current DB state and applies it. Failures are recorded in settings.last_config_error and returned. It serializes with the live user-sync via applyMu.
func (*Manager) RecordAccess ¶
RecordAccess notes a connection from an Xray access-log line (email "uN" + source IP). Throttled to one DB write per user+IP per 10s to absorb bursts.
func (*Manager) RefreshGeo ¶
RefreshGeo re-downloads the geo databases to their latest version, drops the parsed-category cache, and reloads Xray so routing rules pick up the new data.
func (*Manager) RefreshProxies ¶
func (m *Manager) RefreshProxies()
RefreshProxies reloads the pool from current settings and reconciles if it changed. Runs on a timer and right after the routing config is saved.
func (*Manager) RegenerateSecretPath ¶
RegenerateSecretPath issues a fresh random panel path and persists it. The caller is responsible for swapping the live router. Returns the new path.
func (*Manager) RenameUser ¶
RenameUser updates a user's display name. The name is cosmetic (Xray keys users by "u<id>"), so no config reload is needed.
func (*Manager) RenewTLSIfNeeded ¶
RenewTLSIfNeeded renews an ACME cert when near expiry. It reports whether the certificate actually changed (so the caller can reload Xray only then).
func (*Manager) RequestPlanPayment ¶ added in v0.4.0
func (m *Manager) RequestPlanPayment(ctx context.Context, userID, planID int64) (*model.PaymentOrder, string, error)
RequestPlanPayment opens a pending manual order for a paid plan and returns the payment instructions. To keep a spammed "Pay" button from piling up duplicate orders (and admin pings), it reuses the user's latest still-pending manual order for the same plan instead of creating another.
func (*Manager) ResetAdminPassword ¶ added in v0.14.0
ResetAdminPassword assigns a new password to another admin — for when a colleague is locked out. Like a freshly created account it is gated on a change at first login, and every session that account had is revoked: whoever was using the old password is out.
func (*Manager) ResetStats ¶
ResetStats clears the entire per-day traffic history.
func (*Manager) ResetTraffic ¶
ResetTraffic zeroes a user's usage and re-enables them. The raw counters are re-baselined to the live Xray value so the next stats poll doesn't re-add the user's whole lifetime total back (see store.ResetTraffic).
func (*Manager) RestartXray ¶ added in v0.13.0
RestartXray restarts the Xray child from the config already on disk. Operator- initiated only: it drops every live VPN connection.
func (*Manager) RotateSubToken ¶ added in v0.3.0
RotateSubToken issues a new subscription URL token for a user. Protocol credentials stay the same — only the public /<sub_path>/<token> link changes, so the old URL stops working immediately. Triggers a user sync so any token-derived state is refreshed.
func (*Manager) SaveAdminEventPrefs ¶ added in v0.7.0
SaveAdminEventPrefs persists the admin notification categories from the UI map. A key absent from the map (or false) disables that category.
func (*Manager) SaveBillingSettings ¶ added in v0.4.0
func (*Manager) SaveLocalBackup ¶ added in v0.13.0
SaveLocalBackup validates and persists the scheduled local-backup config: a 5-field cron expression in the operator timezone (empty = scheduling off) and how many archives to retain.
The cron is validated here rather than at fire time on purpose. The scheduler can only log an unparseable expression and skip, which looks exactly like "no backups were due" — so a typo would silently mean no backups at all until the day someone needed one.
func (*Manager) SavePaymentSettings ¶ added in v0.6.0
SavePaymentSettings validates and persists provider config. An empty secret / token is treated as "keep current" so toggling doesn't wipe stored credentials. The webhook secret is generated on first save.
func (*Manager) SaveSubSettings ¶
SaveSubSettings validates and persists the subscription delivery settings. The subscription path must be URL-safe and must not shadow the secret panel path or any reserved panel/system segment.
func (*Manager) SaveTariffPlan ¶ added in v0.4.0
func (m *Manager) SaveTariffPlan(p *model.TariffPlan) error
func (*Manager) SaveTelegram ¶ added in v0.2.0
SaveTelegram validates and persists the Telegram bot configuration: the enable flag, bot token, and backup schedule as a 5-field cron expression (empty = no scheduled backups). The authorized chat set and the pending link code are managed separately (linking happens in the bot / via GenerateTelegramLinkCode).
func (*Manager) SaveTelegramUserBot ¶ added in v0.3.0
SaveTelegramUserBot validates and persists the public user bot configuration: the enable flag, its (separate) bot token, and whether open self-registration is allowed. The token must differ from the admin bot's.
func (*Manager) SeedProxies ¶
func (m *Manager) SeedProxies()
SeedProxies loads the proxy pool synchronously from current settings WITHOUT triggering a reconcile. Called once at startup, before the first reconcile, so Xray comes up a single time with the URL-sourced proxies already in place.
func (*Manager) SelfTest ¶ added in v0.15.0
SelfTest connects to each enabled protocol as a real client — through a throwaway Xray the panel spawns — and reports whether traffic actually flows end-to-end. It answers the question the health page can't: "if I hand a user a link right now, does it work?" See the selftest package for what this does and does not prove.
It tests against a real working user's credentials (the first one currently in the config), because that's what actually gets handed out — a synthetic user could pass while every real link is broken by, say, a bad flow or SNI.
func (*Manager) SetACMETarget ¶
SetACMETarget sets the ACME target (a domain OR an IP address), saves the chosen CA provider (provider = "letsencrypt" | "zerossl"), obtains a certificate, and reloads Xray. host and sni are both set to the target so the cert, the client link address and the SNI all match.
func (*Manager) SetAdminNotifier ¶ added in v0.6.0
SetAdminNotifier registers a callback (the admin bot) that broadcasts a message to all authorized admin chats. Passing nil clears it.
func (*Manager) SetAdminRole ¶ added in v0.14.0
SetAdminRole moves an account between roles.
func (*Manager) SetConnGuardWanted ¶ added in v0.13.0
SetConnGuardWanted records whether the operator left the per-IP connection guard enabled (ROSPANEL_CONNLIMIT != off). Called once at boot.
func (*Manager) SetDecoyTemplate ¶
SetDecoyTemplate persists the chosen masquerade template (caller swaps the live decoy handler).
func (*Manager) SetPanelName ¶ added in v0.5.0
SetPanelName validates and persists the panel display name (empty ⇒ default).
func (*Manager) SetPanelTheme ¶ added in v0.5.0
SetPanelTheme validates and persists the colour theme (each field empty ⇒ the matching default applies).
func (*Manager) SetProxyMode ¶
SetProxyMode persists the forward-proxy inbound (proxy mode) and reloads Xray.
func (*Manager) SetResetPeriod ¶
SetResetPeriod sets a user's automatic quota-reset period (none|daily|weekly| monthly|yearly), anchoring the cycle at now.
func (*Manager) SetTimezone ¶
SetTimezone validates and persists the operator's IANA timezone, then updates the cached location so per-day stats re-bucket immediately.
func (*Manager) SetUserAutoDelete ¶ added in v0.15.0
SetUserAutoDelete configures how many days an expired user is kept before being deleted. 0 disables deletion entirely. The admin-audit row for the change is written by the HTTP layer (see server/audit.go), like every other setting.
func (*Manager) SetUserEnabled ¶
SetUserEnabled enables/disables a user (manual on/off) and reconciles so the proxy config drops or re-adds them.
func (*Manager) SetUserLimits ¶
func (m *Manager) SetUserLimits(ctx context.Context, id, dataLimit, expireAt int64, deviceLimit int) error
SetUserLimits updates a user's quota/expiry/device cap and re-enables them.
func (*Manager) SetUserNotifier ¶ added in v0.6.0
SetUserNotifier registers a callback (the user bot) that pushes a message to a VPN user's Telegram chat. Passing nil clears it.
func (*Manager) SetXrayDNS ¶
SetXrayDNS persists the Xray DNS servers and reloads Xray with the new config.
func (*Manager) StartPlanPayment ¶ added in v0.6.0
func (m *Manager) StartPlanPayment(ctx context.Context, userID, planID int64, provider string) (*model.PaymentOrder, error)
StartPlanPayment creates an order plus a provider payment and returns the order with its hosted pay URL. provider may be "" when exactly one method is enabled. The payer is returned to Telegram after paying (the bot flow).
func (*Manager) StartPlanPaymentReturn ¶ added in v0.11.0
func (m *Manager) StartPlanPaymentReturn(ctx context.Context, userID, planID int64, provider, returnURL string) (*model.PaymentOrder, error)
StartPlanPaymentReturn is StartPlanPayment for the web subscription page: it sends the payer back to returnURL (the sub page) after a card payment instead of to Telegram. returnURL is used by hosted-form providers (YooKassa); CryptoBot ignores it.
func (*Manager) StartSysstat ¶
StartSysstat begins sampling host metrics (CPU/RAM/disk/network) and the live VPN throughput for the dashboard. diskPath selects the filesystem reported under "disk".
func (*Manager) StatsByUser ¶
StatsByUser returns per-user totals over the period.
func (*Manager) StatsSeries ¶
StatsSeries returns per-day traffic between from/to (YYYY-MM-DD); userID 0 = all.
func (*Manager) SubscribeAppLogs ¶
SubscribeAppLogs returns a channel of new panel log lines and an unsubscribe.
func (*Manager) SubscribeXrayLogs ¶
SubscribeXrayLogs returns a channel of new Xray log lines and an unsubscribe.
func (*Manager) SystemStatus ¶
func (m *Manager) SystemStatus() (*SystemStatus, error)
SystemStatus assembles the dashboard payload from the host sampler, the Xray supervisor and the user summary.
func (*Manager) TestWebhook ¶ added in v0.10.0
TestWebhook sends a synchronous "ping" delivery to one endpoint and returns the HTTP status, for the "Test" button in the settings UI. It does not retry.
func (*Manager) TrackVPNViewer ¶
func (m *Manager) TrackVPNViewer() func()
TrackVPNViewer marks one active dashboard-stream subscriber for the life of the returned release func — call `defer mgr.TrackVPNViewer()()`. vpnSpeedLoop only samples Xray (forking `api statsquery` every 3s) while at least one viewer is connected, so an unattended panel costs nothing extra.
func (*Manager) TriggerReconcile ¶
func (m *Manager) TriggerReconcile()
TriggerReconcile requests a FULL config reload (regenerate + restart Xray) for structural changes (protocols, routing, DNS, WARP, TLS, ports). Non-blocking; the reload happens shortly after so the triggering HTTP response flushes first.
func (*Manager) TriggerUserSync ¶
func (m *Manager) TriggerUserSync()
TriggerUserSync requests a live user-set sync (add/remove users via the Xray API, no restart) for user-only changes — far cheaper than a full reload.
func (*Manager) UnlinkTelegramChat ¶ added in v0.2.0
UnlinkTelegramChat removes one authorized chat (revokes its bot access).
func (*Manager) UnlinkUserTelegram ¶ added in v0.13.0
UnlinkUserTelegram detaches a VPN user's Telegram chat.
func (*Manager) UpdateAdminCredentials ¶
func (m *Manager) UpdateAdminCredentials(adminID int64, currentPassword, username, password, keepToken string) error
UpdateAdminCredentials changes the admin's login and/or password. Empty username or password fields are left unchanged. The current password must be supplied and is re-verified first — a stolen session cookie alone must not be enough to rewrite the credentials. On success every other session for this admin is revoked (the caller's keepToken survives), so a previously stolen cookie can't outlive the change.
func (*Manager) UserEvents ¶ added in v0.13.0
UserEvents returns one user's audit trail, newest first (the «Журнал» modal).
func (*Manager) XrayConfig ¶
XrayConfig returns the live on-disk Xray config.json.
func (*Manager) XrayLogTail ¶
XrayLogTail returns the buffered recent Xray log lines.
func (*Manager) XrayStatus ¶
XrayStatus reports whether Xray is running and the unix start time of the current process (which changes on every reload — clients poll it to detect when a config change has finished restarting Xray).
type Summary ¶
type Summary struct {
Users int `json:"users"`
EnabledUsers int `json:"enabled_users"`
TotalUp int64 `json:"total_up"`
TotalDown int64 `json:"total_down"`
TrafficToday int64 `json:"traffic_today"` // up+down for the current local-time day
XrayRunning bool `json:"xray_running"`
CertDaysLeft int `json:"cert_days_left"`
}
Summary is the dashboard overview.
type SystemStatus ¶
type SystemStatus struct {
sysstat.Stats
XrayRunning bool `json:"xray_running"`
XrayUptime int64 `json:"xray_uptime"` // seconds
XrayVersion string `json:"xray_version"`
Goroutines int `json:"goroutines"`
CPUCores int `json:"cpu_cores"`
ProcMem int64 `json:"proc_mem"` // panel process RSS
VPNUp int64 `json:"vpn_up"` // VPN client throughput (bytes/sec)
VPNDown int64 `json:"vpn_down"`
TotalUp int64 `json:"total_up"`
TotalDown int64 `json:"total_down"`
Users int `json:"users"`
EnabledUsers int `json:"enabled_users"`
TrafficToday int64 `json:"traffic_today"`
CertDaysLeft int `json:"cert_days_left"`
}
SystemStatus is the full dashboard payload: host resources plus Xray/panel state.
type TLSStatus ¶
type TLSStatus struct {
Mode string `json:"mode"`
Domain string `json:"domain"`
SNI string `json:"sni"`
ACMEEmail string `json:"acme_email"`
ACMEProvider string `json:"acme_provider"`
Cert *tlsutil.CertInfo `json:"cert"`
}
TLSStatus is the current TLS configuration plus active cert metadata.
type ValidationError ¶
type ValidationError struct{ Msg string }
ValidationError marks an error caused by bad operator input rather than a server fault. The server layer maps it to HTTP 400 (vs 500 for everything else); its message is operator-facing (Russian) and safe to show in the UI.
func (*ValidationError) Error ¶
func (e *ValidationError) Error() string
Source Files
¶
- brute_guard.go
- clog.go
- errors.go
- manager.go
- manager_admin_audit.go
- manager_admins.go
- manager_autodelete.go
- manager_backup.go
- manager_billing.go
- manager_connections.go
- manager_events.go
- manager_health.go
- manager_health_report.go
- manager_notify.go
- manager_opera.go
- manager_payments.go
- manager_proxy.go
- manager_selftest.go
- manager_settings.go
- manager_stats.go
- manager_telegram.go
- manager_tls.go
- manager_users.go
- manager_webhooks.go
- manager_xray.go
- validate.go