Documentation
¶
Index ¶
- Variables
- func CredentialFingerprint(username string) string
- func DropAllClients()
- func EnforceIPLimits()
- func GetIPCounts() map[string]int
- func HubAfterStatsFlush()
- func HubPushNodesStatus()
- func HubServe(conn *websocket.Conn, hostname string, deadline time.Time)
- func ManagedCertDir(domain string) string
- func MarkLastUpdate(dt int64)
- func NextConfigSeq() uint64
- func NotifyConfigChanged()
- func SetLastUpdate(dt int64)
- func StartHub()
- func StopHub()
- type AcmeService
- func (a *AcmeService) CheckVhosts(specs []VhostOptions) (drift bool, err error)
- func (a *AcmeService) DetectNginx() NginxStatus
- func (a *AcmeService) EnsureVhost(opt VhostOptions) (*VhostResult, error)
- func (a *AcmeService) IssueWeb(domain, email, method string, force, behindProxy bool) (*IssueResult, error)
- func (a *AcmeService) ListCerts() ([]CertInfo, error)
- func (a *AcmeService) RemoveCert(domain string) error
- func (a *AcmeService) SyncVhosts(specs []VhostOptions) ([]*VhostResult, error)
- type CertInfo
- type CertService
- func (c *CertService) ArchiveLegacy()
- func (c *CertService) DeleteManual(domain string) error
- func (c *CertService) FindByDomain(domain string) (CertInfo, bool, error)
- func (c *CertService) HasManual(domain string) bool
- func (c *CertService) List() ([]CertInfo, error)
- func (c *CertService) SaveManual(domain, certFile, keyFile string) error
- type ClientService
- func (s *ClientService) DepleteClients() ([]uint, []string, error)
- func (s *ClientService) Get(id string) (*[]model.Client, error)
- func (s *ClientService) GetAll() (*[]model.Client, error)
- func (s *ClientService) GetAllWithConfig() (*[]model.Client, error)
- func (s *ClientService) ResetAllClientsTraffic() error
- func (s *ClientService) ResetClients(tx *gorm.DB, dt int64) ([]uint, []string, error)
- func (s *ClientService) Save(tx *gorm.DB, act string, data json.RawMessage, hostname string) ([]uint, error)
- func (s *ClientService) UpdateClientsOnInboundAdd(tx *gorm.DB, initIds string, inboundId uint, hostname string) error
- func (s *ClientService) UpdateClientsOnInboundDelete(tx *gorm.DB, id uint, tag string) error
- func (s *ClientService) UpdateLinksByInboundChange(tx *gorm.DB, inbounds *[]model.Inbound, hostname string, oldTag string) error
- type ConfigService
- func (s *ConfigService) CheckChanges(lu string) (bool, error)
- func (s *ConfigService) CheckOutbound(tag string, link string) core.CheckOutboundResult
- func (s *ConfigService) GetChanges(actor string, chngKey string, count string) []model.Changes
- func (s *ConfigService) GetConfig(data string) (*[]byte, error)
- func (s *ConfigService) RestartCore() error
- func (s *ConfigService) Save(obj string, act string, data json.RawMessage, initUsers string, ...) ([]string, error)
- func (s *ConfigService) StartCore() error
- func (s *ConfigService) StopCore() error
- func (s *ConfigService) TestAcme(domain, email string) error
- type EndpointService
- type Hub
- type InboundService
- func (s *InboundService) FromIds(ids []uint) ([]*model.Inbound, error)
- func (s *InboundService) Get(ids string) (*[]map[string]interface{}, error)
- func (s *InboundService) GetAll() (*[]map[string]interface{}, error)
- func (s *InboundService) GetAllConfig(db *gorm.DB) ([]json.RawMessage, error)
- func (s *InboundService) RestartInbounds(tx *gorm.DB, ids []uint) error
- func (s *InboundService) Save(tx *gorm.DB, act string, data json.RawMessage, initUserIds string, ...) error
- func (s *InboundService) UpdateInboundsUsers(tx *gorm.DB, ids []uint) error
- func (s *InboundService) UpdateOutJsons(tx *gorm.DB, inboundIds []uint, hostname string) error
- type IssueResult
- type LoginGuardService
- type NginxStatus
- type NodeMem
- type NodeService
- func (s *NodeService) GetAll() ([]map[string]interface{}, error)
- func (s *NodeService) GetStatuses() map[uint]NodeStatus
- func (s *NodeService) RefreshAll()
- func (s *NodeService) Save(tx *gorm.DB, act string, data json.RawMessage) error
- func (s *NodeService) TestNode(data json.RawMessage) (NodeStatus, error)
- type NodeStatus
- type NodeSyncService
- func (s *NodeSyncService) AdoptInbounds(nodeId uint, tags []string, actor string) error
- func (s *NodeSyncService) CollectTraffic()
- func (s *NodeSyncService) FetchNodeInbounds(nodeId uint) ([]remoteInbound, error)
- func (s *NodeSyncService) MarkAllDirty()
- func (s *NodeSyncService) Reconcile(nodeId uint) error
- func (s *NodeSyncService) ReconcileAllOnline()
- func (s *NodeSyncService) ReconcileDirtyOnline()
- func (s *NodeSyncService) ReconcileNow(nodeId uint) error
- type OnlineIP
- type OutboundService
- type PanelDataService
- type PanelService
- type ProxyEndpoint
- type ProxySide
- type ServerService
- func (s *ServerService) GenKeypair(keyType string, options string) []string
- func (s *ServerService) GetCpuPercent() float64
- func (s *ServerService) GetDatabaseInfo() map[string]int64
- func (s *ServerService) GetDiskIO() map[string]interface{}
- func (s *ServerService) GetDiskInfo() map[string]interface{}
- func (s *ServerService) GetLogs(count string, level string) []string
- func (s *ServerService) GetMemInfo() map[string]interface{}
- func (s *ServerService) GetNetInfo() map[string]interface{}
- func (s *ServerService) GetSingboxInfo() map[string]interface{}
- func (s *ServerService) GetStatus(request string) *map[string]interface{}
- func (s *ServerService) GetSwapInfo() map[string]interface{}
- func (s *ServerService) GetSystemInfo() map[string]interface{}
- type ServicesService
- func (s *ServicesService) GetAll() (*[]map[string]interface{}, error)
- func (s *ServicesService) GetAllConfig(db *gorm.DB) ([]json.RawMessage, error)
- func (s *ServicesService) RestartServices(tx *gorm.DB, ids []uint) error
- func (s *ServicesService) Save(tx *gorm.DB, act string, data json.RawMessage) error
- type SettingService
- func (s *SettingService) GetAllSetting() (*map[string]string, error)
- func (s *SettingService) GetCertFile() (string, error)
- func (s *SettingService) GetConfig() (string, error)
- func (s *SettingService) GetFinalSubURI(host string) (string, error)
- func (s *SettingService) GetGlobalReset() (string, error)
- func (s *SettingService) GetGlobalResetLast() (int64, error)
- func (s *SettingService) GetKeyFile() (string, error)
- func (s *SettingService) GetListen() (string, error)
- func (s *SettingService) GetLoginGuard() (maxFailures int, windowMinutes int, banMinutes int, err error)
- func (s *SettingService) GetPort() (int, error)
- func (s *SettingService) GetSecret() ([]byte, error)
- func (s *SettingService) GetSessionMaxAge() (int, error)
- func (s *SettingService) GetStatsBucketSeconds() (int64, error)
- func (s *SettingService) GetSubAcmeEmail() (string, error)
- func (s *SettingService) GetSubCertFile() (string, error)
- func (s *SettingService) GetSubCertMode() (string, error)
- func (s *SettingService) GetSubClashExt() (string, error)
- func (s *SettingService) GetSubClashNoDefGrp() (bool, error)
- func (s *SettingService) GetSubClashSprtAll() (bool, error)
- func (s *SettingService) GetSubDomain() (string, error)
- func (s *SettingService) GetSubEncode() (bool, error)
- func (s *SettingService) GetSubJsonExt() (string, error)
- func (s *SettingService) GetSubKeyFile() (string, error)
- func (s *SettingService) GetSubListen() (string, error)
- func (s *SettingService) GetSubNginx() (bool, error)
- func (s *SettingService) GetSubPath() (string, error)
- func (s *SettingService) GetSubPort() (int, error)
- func (s *SettingService) GetSubShowInfo() (bool, error)
- func (s *SettingService) GetSubURI() (string, error)
- func (s *SettingService) GetSubUpdates() (int, error)
- func (s *SettingService) GetTimeLocation() (*time.Location, error)
- func (s *SettingService) GetTrafficAge() (int, error)
- func (s *SettingService) GetWebAcmeEmail() (string, error)
- func (s *SettingService) GetWebCertMode() (string, error)
- func (s *SettingService) GetWebDomain() (string, error)
- func (s *SettingService) GetWebNginx() (bool, error)
- func (s *SettingService) GetWebPath() (string, error)
- func (s *SettingService) GetWebTrustedProxies() ([]netip.Prefix, error)
- func (s *SettingService) GetWebURI() (string, error)
- func (s *SettingService) ProxyVhostSpecs() ([]ProxySide, error)
- func (s *SettingService) ResetSettings() error
- func (s *SettingService) Save(tx *gorm.DB, data json.RawMessage) error
- func (s *SettingService) SaveConfig(tx *gorm.DB, config json.RawMessage) error
- func (s *SettingService) SetConfig(config string) error
- func (s *SettingService) SetGlobalResetLast(value int64) error
- func (s *SettingService) SetPort(port int) error
- func (s *SettingService) SetSubPath(subPath string) error
- func (s *SettingService) SetSubPort(subPort int) error
- func (s *SettingService) SetWebPath(webPath string) error
- type SingBoxConfig
- type StatsService
- type TlsService
- type UpdatePhase
- type UpdateService
- type UpdateStatus
- type UserService
- func (s *UserService) AddToken(username string, expiry int64, desc string) (string, error)
- func (s *UserService) ChangePass(id string, oldPass string, newUser string, newPass string) error
- func (s *UserService) CheckUser(username string, password string, code string, remoteIP string) (*model.User, error)
- func (s *UserService) ClearFirstUserTwoFa() error
- func (s *UserService) DeleteToken(id string) error
- func (s *UserService) DisableTwoFa(username string, password string) error
- func (s *UserService) EnableTwoFa(username string, password string, secret string, code string) error
- func (s *UserService) GetFirstUser() (*model.User, error)
- func (s *UserService) GetUserTokens(username string) (*[]model.Tokens, error)
- func (s *UserService) GetUsers() (*[]model.User, error)
- func (s *UserService) LoadTokens() ([]byte, error)
- func (s *UserService) Login(username string, password string, code string, remoteIP string) (string, error)
- func (s *UserService) UpdateFirstUser(username string, password string) error
- type VhostOptions
- type VhostResult
- type WarpService
Constants ¶
This section is empty.
Variables ¶
var ErrTwoFaRequired = common.NewErrorf("two-factor code required")
ErrTwoFaRequired says the password checked out but the account carries a second factor and the request brought no code. It is the one outcome the caller can tell apart from a plain failure, and only ever after the password matched: answering it earlier would let anyone enumerate which accounts have 2FA enabled, and would do it from an unauthenticated request.
Functions ¶
func CredentialFingerprint ¶ added in v1.7.1
CredentialFingerprint digests the credentials a session for this username was issued under. Sessions are signed cookies with no server-side state (web.go's cookie.NewStore), so changing the password cannot invalidate the ones already handed out -- an old cookie keeps working until it expires on its own. Stamping this into the session and re-checking it on every request is what turns "change the password" into "log every other session out", including the websocket, whose handshake is the only place it authenticates.
An empty result means no session can be vouched for -- a missing or unreadable user row -- and callers must treat it as a rejection rather than as a value to compare against.
Read straight from the DB on every call, deliberately. Caching it and invalidating on the write paths looked cheaper but could not be made correct: `sui admin -reset` writes the row from a *separate process*, and ImportDB swaps the whole database file underneath a running panel -- neither can reach an in-process cache, so both would leave sessions alive that the credential change was supposed to retire. One indexed lookup per authenticated request is the price of that being right.
func DropAllClients ¶ added in v1.6.3
func DropAllClients()
DropAllClients closes every live connection but leaves the hub running. Authentication is handshake-only, so after the admin credentials change an already-open socket would keep streaming the full config — client UUIDs, passwords, subURI — to a tab that authenticated with the old ones. Browsers reconnect within a second; a session that is still valid simply re-auths.
func EnforceIPLimits ¶ added in v1.7.0
func EnforceIPLimits()
EnforceIPLimits scans the live connection table, evicts whatever exceeds each client's cap and republishes the per-client counts. A deployment that uses no limits pays one indexed query per run and nothing else.
func GetIPCounts ¶ added in v1.7.0
func HubAfterStatsFlush ¶ added in v1.6.3
func HubAfterStatsFlush()
HubAfterStatsFlush runs on the StatsJob goroutine right after SaveStats. The onlines payload is built and marshaled here, before crossing any goroutine boundary, so the pre-existing unsynchronized onlineResources access is not widened. It also refreshes stats subscriptions — the stats table only changes at this flush.
func HubPushNodesStatus ¶ added in v1.6.3
func HubPushNodesStatus()
HubPushNodesStatus runs on the NodesJob goroutine after RefreshAll.
func HubServe ¶ added in v1.6.3
HubServe registers an accepted connection and blocks reading it until it drops. Runs on the (hijacked) HTTP handler goroutine.
func ManagedCertDir ¶ added in v1.6.1
ManagedCertDir 返回面板为该域名安装证书的目录。RemoveCert 会把它整个删掉, 所以「设置里的证书路径落在这个目录下」也算正在使用(删除守卫要靠它兜住 域名与路径分岔的情形)。
func MarkLastUpdate ¶ added in v1.6.3
func MarkLastUpdate(dt int64)
MarkLastUpdate advances the change timestamp without waking the hub.
func NextConfigSeq ¶ added in v1.7.1
func NextConfigSeq() uint64
NextConfigSeq allocates a version for a client list assembled outside this package — api/save and api/clients answer with the whole list, and an unversioned one leaves the SPA's high-water mark untouched, so a live push that read the table before the save could still land after it and put the old rows back. Call it BEFORE the read, for the same reason configHalf does: the version has to order this read against a later one.
func NotifyConfigChanged ¶ added in v1.6.3
func NotifyConfigChanged()
NotifyConfigChanged wakes the hub after a LastUpdate bump. Non-blocking and nil-safe: cron jobs may still fire while the hub is shutting down.
func SetLastUpdate ¶ added in v1.6.3
func SetLastUpdate(dt int64)
SetLastUpdate records a config-change timestamp and wakes the websocket hub's debounced full-payload push. CheckChanges' lazy seeding below must NOT go through it — that is a cache warm-up after a restart, not a change.
Only call this OUTSIDE a write transaction. The hub reads the DB on its own pooled connection, so notifying before the commit lands publishes pre-commit state, and since the client stamps its own lastLoad from that push, even a reconnect's lu gate then reports "unchanged" — the stale config sticks. Inside a transaction use MarkLastUpdate and call NotifyConfigChanged after the commit.
func StartHub ¶ added in v1.6.3
func StartHub()
StartHub creates the singleton. Called from app.Start before the web server accepts connections and before the cron jobs first fire.
func StopHub ¶ added in v1.6.3
func StopHub()
StopHub closes every live connection and waits for the hub's goroutines. http.Server.Shutdown ignores hijacked connections, so without this every RestartApp (SIGHUP, api/restartApp) would leak one goroutine pair and one socket per open tab. Called from app.Stop after webServer.Stop — the listener is already closed, so no new handshake can arrive mid-teardown.
Types ¶
type AcmeService ¶ added in v1.4.7
type AcmeService struct{}
AcmeService 是无状态工具,不嵌入 SettingService(避免与 ApiService 已嵌入的 SettingService 产生方法集二义性)。所有入参由调用方传入,不直接读写数据库。
func (*AcmeService) CheckVhosts ¶ added in v1.6.2
func (a *AcmeService) CheckVhosts(specs []VhostOptions) (drift bool, err error)
CheckVhosts answers two questions without writing a byte or reloading nginx:
- would generating this set fail right now (usually a missing certificate), returned as an error;
- is nginx already exactly this, returned as drift=false.
Question 1 serves the save path while the proxy is already on: it cannot rewrite the vhost first (this page is that location), so it saves, restarts, and lets the startup reconciliation write — and a failure in that gap reaches nobody, because by then the service is plaintext. Asking here is the only way to ask without writing.
Question 2 is the self-healing handle: a reconciliation that failed at the last restart, or a file removed by hand, says nothing — the settings page looks fine while the panel is gone from 443. Reporting drift lets the page point at its own "restart panel" button, which re-runs the reconciliation.
func (*AcmeService) DetectNginx ¶ added in v1.4.7
func (a *AcmeService) DetectNginx() NginxStatus
DetectNginx 检测 nginx 是否安装并运行,以及 80 端口是否被占用。Windows 直接返回零值。
func (*AcmeService) EnsureVhost ¶ added in v1.6.1
func (a *AcmeService) EnsureVhost(opt VhostOptions) (*VhostResult, error)
EnsureVhost 为一个域名生成 nginx 反向代理配置并确认它真的生效。
全过程「验证通过才算成功」:nginx -t 不过、和用户已有配置撞 server_name、reload 失败、 或者块压根没进入生效配置,都会删掉文件、把 nginx 恢复原状,再带着 nginx 自己的输出报错。 调用方必须在这里成功之后才把面板/订阅切成明文 HTTP —— 顺序反了就会出现 「服务不再终结 TLS,前面又没人接管」的窗口,而关掉开关的入口正在那个打不开的页面里。
func (*AcmeService) IssueWeb ¶ added in v1.4.7
func (a *AcmeService) IssueWeb(domain, email, method string, force, behindProxy bool) (*IssueResult, error)
IssueWeb 为面板/订阅申请证书并安装到 /root/cert/{域名}/。
- method :standalone / nginx / auto(空视同 auto),解析与可行性校验见 resolveMethod。
- force :域名已有未到期证书时 acme.sh 默认跳过签发,force 时加 --force 强制续期。
- behindProxy:webNginx=true,即反向代理终结 TLS、nginx 是证书消费方(决定 reloadcmd)。
func (*AcmeService) ListCerts ¶ added in v1.4.7
func (a *AcmeService) ListCerts() ([]CertInfo, error)
ListCerts 列出 acme.sh 维护的证书。直接读它的家目录,不调 `acme.sh --list`。 找不到 acme.sh 时返回空列表而不是错误:那只是还没申请过证书,页面该显示空态。
func (*AcmeService) RemoveCert ¶ added in v1.6.1
func (a *AcmeService) RemoveCert(domain string) error
RemoveCert 删除一张证书:先让 acme.sh 忘掉它(不再续期),再删掉安装出去的文件副本。
调用方必须先确认没有服务在用这个域名——面板/订阅正用着的证书被删掉,下次重启就起不来。 那个检查放在调用方(它才读得到设置),这里只管删。 入站 TLS 是否手填了这两个路径不做检查:那要遍历所有 TLS 配置解析 JSON、还要处理软链接 和相对路径,代价和收益不成正比,由前端在确认框里提示。
func (*AcmeService) SyncVhosts ¶ added in v1.6.1
func (a *AcmeService) SyncVhosts(specs []VhostOptions) ([]*VhostResult, error)
SyncVhosts 让 nginx 里「我们生成的那些反代配置」与传入的期望状态一致: specs 里的每个域名各生成一份,而以前生成过、现在不在 specs 里的一律删掉。
删除这一步是必须的,漏了会留下两种坏状态:关掉反代后 443 还在把明文请求转给一个 已经改回 TLS 的端口(502),换域名后旧域名的块还赖在 nginx 里。 清理只扫 s-ui-proxy-* 前缀,碰不到 ACME 验证块,更碰不到用户自己写的配置。
type CertInfo ¶ added in v1.6.1
type CertInfo struct {
Domain string `json:"domain"`
CertFile string `json:"certFile"` // 摆出来供复制:建入站 TLS 时要填进 certificate_path
KeyFile string `json:"keyFile"`
CA string `json:"ca"`
KeyType string `json:"keyType"`
NotAfter int64 `json:"notAfter"` // 0 表示证书文件读不到
NextRenew int64 `json:"nextRenew"` // 0 表示不适用(手动登记的证书)
Managed bool `json:"managed"` // true = acme.sh 维护并自动续期
}
CertInfo 是「域名与证书」页面上的一条记录。 时间统一用 unix 秒回给前端,由前端按浏览器时区渲染并算剩余天数——服务器时区不一定 是用户的,后端算好天数反而会差一天。
type CertService ¶ added in v1.6.1
type CertService struct {
// contains filtered or unexported fields
}
CertService 管手动登记的证书,并把它们与 acme.sh 托管的那些合并成「域名与证书」 页面上的那一份清单。
分工:acme.sh 那半边的事实来源是它自己的家目录(AcmeService 扫盘直接读),只有 手动登记的这半边才落库。同一个域名两边都有时以 acme.sh 为准——它在自动续期, 手动记录多半是升级时归档进来的旧路径。
域名一律以小写存储和比对:DNS 不区分大小写,而 uniqueIndex、合并去重、前端匹配 全是精确比对,混着存会让同一个域名分裂成两条互相矛盾的记录。
字段用具名的 settings 而不是嵌入 SettingService:ApiService 已经嵌入了后者, 这里再嵌入会让 CertService 的方法提升到 ApiService 上产生二义性(AcmeService 那个注释说的也是这件事)。
func (*CertService) ArchiveLegacy ¶ added in v1.6.1
func (c *CertService) ArchiveLegacy()
ArchiveLegacy 把升级前手填在设置里的证书路径归档成手动登记记录。
面板启动时调用,幂等:只在「域名非空 + 两个路径都非空且可读 + 该域名还没有任何 证书」时补一条。设置里的 webCertFile/webKeyFile 不动,面板照旧读它启动——这一步 只是让那份证书在新页面上看得见、可管理,不改变任何现有行为。
不放在 cmd/migration 里:那套迁移只在 `sui migrate` 和导入备份时跑,正常启动 根本不经过,挂在那儿等于对绝大多数升级用户没生效。
成本控制:正常启动在 HasManual(索引 COUNT)就短路了;acme.sh 家目录的全量扫描 只在两侧至少有一侧真要归档时才做,而且只做一次。
func (*CertService) DeleteManual ¶ added in v1.6.1
func (c *CertService) DeleteManual(domain string) error
DeleteManual 删掉一条登记记录。只忘掉路径,不碰证书文件本身——那是用户自己的 文件,多半还被别的服务用着。对不存在的域名是 no-op。
func (*CertService) FindByDomain ¶ added in v1.6.1
func (c *CertService) FindByDomain(domain string) (CertInfo, bool, error)
FindByDomain 查某个域名当前可用的证书。
错误必须上抛而不是吞成「没找到」:调用方拿 found/Managed 决定走哪条分支,把一次 数据库故障当成「不存在」会让删除走错路(acme.sh 托管的被当成手动记录,DeleteManual 删了个寂寞还报成功)。
func (*CertService) HasManual ¶ added in v1.6.1
func (c *CertService) HasManual(domain string) bool
HasManual 判断某个域名有没有手动登记记录。唯一索引上的一次 COUNT,零磁盘 I/O, 给 ArchiveLegacy 当每次启动的快速出口。
func (*CertService) List ¶ added in v1.6.1
func (c *CertService) List() ([]CertInfo, error)
List 返回合并后的证书清单,按域名排序。
func (*CertService) SaveManual ¶ added in v1.6.1
func (c *CertService) SaveManual(domain, certFile, keyFile string) error
SaveManual 登记(或改写)一份自带的证书。
type ClientService ¶
type ClientService struct{}
func (*ClientService) DepleteClients ¶
func (s *ClientService) DepleteClients() ([]uint, []string, error)
DepleteClients disables clients over quota or past expiry and returns both the affected local inbound ids (to hot-restart) and the names whose enable state changed, so the caller can fan those out to nodes. That second list covers BOTH directions: the depletion disable below and the periodic reset's re-enable inside ResetClients — a round that only re-enables still has to reach the nodes, or they keep rejecting a paid-up user. With cluster totals folded into up/down, the quota check is already a whole-cluster judgement.
func (*ClientService) GetAllWithConfig ¶ added in v1.6.4
func (s *ClientService) GetAllWithConfig() (*[]model.Client, error)
GetAllWithConfig adds config for the cluster reconcile diff only: clientDiffers compares it, and an absent key reads as "always different", which would re-push every client every round. Reached solely by the node-facing apiv2 clients read.
func (*ClientService) ResetAllClientsTraffic ¶ added in v1.5.4
func (s *ClientService) ResetAllClientsTraffic() error
ResetAllClientsTraffic zeroes up/down for every client (accumulating into the total counters) and re-enables all of them, in a single bulk update. Used by the global periodic traffic reset; the caller restarts the core afterwards so re-enabled clients take effect.
func (*ClientService) ResetClients ¶
ResetClients applies the per-client periodic reset. It returns the affected local inbound ids (to hot-restart) and the names it re-enabled, which the caller has to fan out to nodes for the same reason DepleteJob fans out a disable: the node keeps rejecting a paid-up user until it hears otherwise.
func (*ClientService) Save ¶
func (s *ClientService) Save(tx *gorm.DB, act string, data json.RawMessage, hostname string) ([]uint, error)
func (*ClientService) UpdateClientsOnInboundAdd ¶
func (*ClientService) UpdateClientsOnInboundDelete ¶
func (*ClientService) UpdateLinksByInboundChange ¶
type ConfigService ¶
type ConfigService struct {
ClientService
TlsService
SettingService
InboundService
OutboundService
ServicesService
EndpointService
NodeService
}
func NewConfigService ¶
func NewConfigService(c *core.Core) *ConfigService
func (*ConfigService) CheckChanges ¶
func (s *ConfigService) CheckChanges(lu string) (bool, error)
func (*ConfigService) CheckOutbound ¶
func (s *ConfigService) CheckOutbound(tag string, link string) core.CheckOutboundResult
func (*ConfigService) GetChanges ¶
func (*ConfigService) RestartCore ¶
func (s *ConfigService) RestartCore() error
func (*ConfigService) Save ¶
func (s *ConfigService) Save(obj string, act string, data json.RawMessage, initUsers string, loginUser string, hostname string) ([]string, error)
func (*ConfigService) StartCore ¶
func (s *ConfigService) StartCore() error
func (*ConfigService) StopCore ¶
func (s *ConfigService) StopCore() error
func (*ConfigService) TestAcme ¶
func (s *ConfigService) TestAcme(domain, email string) error
TestAcme attempts to obtain a certificate for the domain right now, so the UI can verify ACME actually works (domain resolves, port 80 reachable, etc.) BEFORE the user commits the setting. On success the certificate is cached, so the subsequent panel restart serves HTTPS without another challenge.
type EndpointService ¶
type EndpointService struct {
WarpService
}
func (*EndpointService) GetAll ¶
func (o *EndpointService) GetAll() (*[]map[string]interface{}, error)
func (*EndpointService) GetAllConfig ¶
func (o *EndpointService) GetAllConfig(db *gorm.DB) ([]json.RawMessage, error)
func (*EndpointService) Save ¶
func (s *EndpointService) Save(tx *gorm.DB, act string, data json.RawMessage) error
type InboundService ¶
type InboundService struct {
ClientService
}
func (*InboundService) FromIds ¶
func (s *InboundService) FromIds(ids []uint) ([]*model.Inbound, error)
func (*InboundService) Get ¶
func (s *InboundService) Get(ids string) (*[]map[string]interface{}, error)
func (*InboundService) GetAll ¶
func (s *InboundService) GetAll() (*[]map[string]interface{}, error)
func (*InboundService) GetAllConfig ¶
func (s *InboundService) GetAllConfig(db *gorm.DB) ([]json.RawMessage, error)
func (*InboundService) RestartInbounds ¶
func (s *InboundService) RestartInbounds(tx *gorm.DB, ids []uint) error
func (*InboundService) Save ¶
func (s *InboundService) Save(tx *gorm.DB, act string, data json.RawMessage, initUserIds string, hostname string) error
func (*InboundService) UpdateInboundsUsers ¶ added in v1.6.0
func (s *InboundService) UpdateInboundsUsers(tx *gorm.DB, ids []uint) error
func (*InboundService) UpdateOutJsons ¶
type IssueResult ¶ added in v1.4.7
type LoginGuardService ¶ added in v1.7.1
type LoginGuardService struct {
SettingService SettingService
}
LoginGuardService rate-limits password checks. It is deliberately not part of UserService: the counting has to happen even when there is no such user at all, which is exactly the case UserService answers with a nil user.
func (*LoginGuardService) BanRemaining ¶ added in v1.7.1
func (s *LoginGuardService) BanRemaining(ip, username string) time.Duration
BanRemaining reports how long this attempt is refused for, or zero to let it through. A DB error lets the attempt through: the limiter exists to slow guessing down, and failing closed would turn a broken query into a lockout of the panel's only administrator.
func (*LoginGuardService) ClearAll ¶ added in v1.7.1
func (s *LoginGuardService) ClearAll() error
ClearAll removes every partial count and active ban. It is deliberately a CLI recovery operation rather than an unauthenticated endpoint: someone who can reach the database can already reset the admin credentials, while a web endpoint capable of clearing its own limiter would nullify the limiter.
func (*LoginGuardService) RecordFailure ¶ added in v1.7.1
func (s *LoginGuardService) RecordFailure(ip, username string)
RecordFailure counts one failed attempt against both identities. Errors are logged and swallowed: the caller is already on its way to rejecting the login, and a bookkeeping failure should not turn that into a 500.
func (*LoginGuardService) RecordPrompt ¶ added in v1.7.2
func (s *LoginGuardService) RecordPrompt(ip string)
RecordPrompt counts one two-factor prompt against the source address, on its own scope and a budget promptBudgetFactor times the failure budget. Keyed on the address alone: the username axis exists to stop a spray across accounts, and reaching a prompt means the password for this one was already correct. Without this the prompt is the panel's one unmetered bcrypt comparison, and whoever holds a leaked password can drive it without limit.
func (*LoginGuardService) RecordSuccess ¶ added in v1.7.1
func (s *LoginGuardService) RecordSuccess(ip, username string)
RecordSuccess clears partial tallies and rearms a username row whose ban was already served. An active ban is not clearable this way because its request never reaches the password check.
type NginxStatus ¶ added in v1.4.7
type NodeService ¶ added in v1.6.0
type NodeService struct {
}
func (*NodeService) GetAll ¶ added in v1.6.0
func (s *NodeService) GetAll() ([]map[string]interface{}, error)
GetAll returns nodes in panel shape. The token never leaves the server — only a tokenSet flag does.
func (*NodeService) GetStatuses ¶ added in v1.6.0
func (s *NodeService) GetStatuses() map[uint]NodeStatus
GetStatuses returns a copy of the live snapshot for API responses.
func (*NodeService) RefreshAll ¶ added in v1.6.0
func (s *NodeService) RefreshAll()
RefreshAll probes every enabled node with bounded parallelism and atomically swaps in a freshly built snapshot. Called by the @every 5s cron job.
func (*NodeService) Save ¶ added in v1.6.0
func (s *NodeService) Save(tx *gorm.DB, act string, data json.RawMessage) error
func (*NodeService) TestNode ¶ added in v1.6.0
func (s *NodeService) TestNode(data json.RawMessage) (NodeStatus, error)
TestNode probes the node described by the (possibly unsaved) form data with a one-off client, so Test Connection reflects the form, not the DB row. An empty token on an existing node falls back to the stored one.
type NodeStatus ¶ added in v1.6.0
type NodeStatus struct {
State string `json:"state"` // online | offline | core-stopped
Latency int64 `json:"latency"`
Cpu float64 `json:"cpu"`
Mem NodeMem `json:"mem"`
AppVersion string `json:"appVersion"`
CoreVersion string `json:"coreVersion"`
Error string `json:"error,omitempty"`
CheckedAt int64 `json:"checkedAt"`
LastOnline int64 `json:"lastOnline"`
}
type NodeSyncService ¶ added in v1.6.0
type NodeSyncService struct {
NodeService
}
NodeSyncService owns everything that writes TO a node: adopting its inbounds as read-only replicas, and pushing/reconciling the master's clients onto it. Reconcile is the single write channel — first push, offline catch-up, drift repair and the manual button all funnel through it.
func (*NodeSyncService) AdoptInbounds ¶ added in v1.6.0
func (s *NodeSyncService) AdoptInbounds(nodeId uint, tags []string, actor string) error
AdoptInbounds pulls the full panel-shape inbound for each selected tag and stores it as a local replica row (node_id set). tag collisions fail loudly — the tag is the reconciliation key, so we never silently rename.
func (*NodeSyncService) CollectTraffic ¶ added in v1.6.0
func (s *NodeSyncService) CollectTraffic()
CollectTraffic pulls each online node's @cluster client counters and folds the delta since the last collection into the master's per-client totals. The node's clients.up/down are cumulative; a per-(node,client) baseline turns them into deltas, resetting the baseline when the node's counter drops (reset).
func (*NodeSyncService) FetchNodeInbounds ¶ added in v1.6.0
func (s *NodeSyncService) FetchNodeInbounds(nodeId uint) ([]remoteInbound, error)
FetchNodeInbounds lists a node's inbounds, flagging which tags this panel has already adopted as replicas.
func (*NodeSyncService) MarkAllDirty ¶ added in v1.6.0
func (s *NodeSyncService) MarkAllDirty()
func (*NodeSyncService) Reconcile ¶ added in v1.6.0
func (s *NodeSyncService) Reconcile(nodeId uint) error
Reconcile makes a node's @cluster clients match the master's expectation: clients that reference any of this node's replica inbounds. Together with ReconcileNow it is the ONLY path that writes clients to a node.
This is the background entry: single-flight per node plus a 30s backoff so heartbeat/fanout triggers don't stampede. A skip returns nil — the dirty flag stays set and the next heartbeat retries.
func (*NodeSyncService) ReconcileAllOnline ¶ added in v1.6.0
func (s *NodeSyncService) ReconcileAllOnline()
ReconcileAllOnline reconciles all online nodes regardless of dirty flag — the hourly safety net that repairs silent node-side drift.
func (*NodeSyncService) ReconcileDirtyOnline ¶ added in v1.6.0
func (s *NodeSyncService) ReconcileDirtyOnline()
ReconcileDirtyOnline reconciles every enabled node that is online and dirty. Called by the heartbeat so offline-period edits converge once a node returns.
func (*NodeSyncService) ReconcileNow ¶ added in v1.6.0
func (s *NodeSyncService) ReconcileNow(nodeId uint) error
ReconcileNow is the interactive entry (manual sync button, post-adoption push): it skips the backoff — the user asked, so sync — and reports a busy overlap as an error instead of silently doing nothing, so the UI never toasts success for a no-op.
type OnlineIP ¶ added in v1.7.0
type OnlineIP struct {
IP string `json:"ip"`
Since int64 `json:"since"` // unix seconds, converted from the monotonic basis
// Nil when no client has an IP limit: lastActive is only stamped while one
// does, so answering from it there would report connection age as inactivity.
// Unknown is the honest reading, and the UI renders no badge for it.
Idle *bool `json:"idle"`
}
func OnlineIPsOf ¶ added in v1.7.0
OnlineIPsOf lists one client's live source IPs, oldest first. A stopped core means "nobody is connected", not an error.
type OutboundService ¶
type OutboundService struct{}
func (*OutboundService) GetAll ¶
func (o *OutboundService) GetAll() (*[]map[string]interface{}, error)
func (*OutboundService) GetAllConfig ¶
func (o *OutboundService) GetAllConfig(db *gorm.DB) ([]json.RawMessage, error)
func (*OutboundService) Save ¶
func (s *OutboundService) Save(tx *gorm.DB, act string, data json.RawMessage) error
type PanelDataService ¶ added in v1.6.3
type PanelDataService struct {
SettingService
ClientService
TlsService
InboundService
OutboundService
EndpointService
ServicesService
NodeService
StatsService
ServerService
}
PanelDataService assembles the api/load payloads. It exists so the HTTP handler and the websocket hub share one implementation; all embedded services are stateless, so the zero value is ready to use.
func (*PanelDataService) FullPayload ¶ added in v1.6.3
func (s *PanelDataService) FullPayload(hostname string) (map[string]interface{}, error)
FullPayload is LivePayload plus the whole panel config — api/load's response when the lu gate opens. hostname feeds the subscription-URI fallback.
func (*PanelDataService) LivePayload ¶ added in v1.6.3
func (s *PanelDataService) LivePayload() (map[string]interface{}, error)
LivePayload is OnlinesPayload plus live node status — api/load's response when nothing changed since the client's lu.
func (*PanelDataService) OnlinesPayload ¶ added in v1.6.3
func (s *PanelDataService) OnlinesPayload() (map[string]interface{}, error)
OnlinesPayload is onlinesHalf plus the client list — the per-flush live push and api/load's live answer, both of which have to carry it themselves.
Everything here runs on the caller's goroutine, which is what lets HubAfterStatsFlush call it straight after SaveStats and still read onlineResources unsynchronized (see onlinesHalf). Keep it that way: moving either read off this goroutine widens that access.
type PanelService ¶
type PanelService struct {
}
func (*PanelService) RestartPanel ¶
func (s *PanelService) RestartPanel(delay time.Duration) error
RestartPanel 在 delay 之后给自己发 SIGHUP(Windows 上 Kill)触发重启。 delay 是 time.Duration,别传裸数字——那是纳秒,等于立即重启,调用方的 HTTP 响应 会来不及刷出就随 gin server 一起被拆掉。它存在的意义就是留出这段刷响应的时间。
type ProxyEndpoint ¶ added in v1.6.1
type ProxyEndpoint struct {
Name string // 只用于配置里的注释和日志:panel / sub
Path string // 形如 /app/
Listen string // 上游监听地址,空表示 0.0.0.0
Port int
}
ProxyEndpoint 是一个域名下的一条反代规则:把 Path 交给本机的某个端口。 面板和订阅各算一条;两者共用域名时会落进同一个 server 块的两个 location—— 各生成一份 server 块会被 nginx 判 conflicting server name 而忽略掉后一个。
type ProxySide ¶ added in v1.6.2
type ProxySide struct {
Name string // goes into the config comment and the log: panel / subscription
Enabled bool
Domain string
Path string
Listen string
Port int
CertFile string
KeyFile string
}
ProxySide is the reverse-proxy input for one side (panel or subscription). It comes either from the form on save (values not yet in the DB) or from the DB at startup; both must aggregate identically, hence the shared BuildVhostSpecs.
type ServerService ¶
type ServerService struct{}
func (*ServerService) GenKeypair ¶
func (s *ServerService) GenKeypair(keyType string, options string) []string
func (*ServerService) GetCpuPercent ¶
func (s *ServerService) GetCpuPercent() float64
func (*ServerService) GetDatabaseInfo ¶
func (s *ServerService) GetDatabaseInfo() map[string]int64
func (*ServerService) GetDiskIO ¶
func (s *ServerService) GetDiskIO() map[string]interface{}
func (*ServerService) GetDiskInfo ¶
func (s *ServerService) GetDiskInfo() map[string]interface{}
func (*ServerService) GetLogs ¶
func (s *ServerService) GetLogs(count string, level string) []string
func (*ServerService) GetMemInfo ¶
func (s *ServerService) GetMemInfo() map[string]interface{}
func (*ServerService) GetNetInfo ¶
func (s *ServerService) GetNetInfo() map[string]interface{}
func (*ServerService) GetSingboxInfo ¶
func (s *ServerService) GetSingboxInfo() map[string]interface{}
func (*ServerService) GetStatus ¶
func (s *ServerService) GetStatus(request string) *map[string]interface{}
func (*ServerService) GetSwapInfo ¶
func (s *ServerService) GetSwapInfo() map[string]interface{}
func (*ServerService) GetSystemInfo ¶
func (s *ServerService) GetSystemInfo() map[string]interface{}
type ServicesService ¶
type ServicesService struct{}
func (*ServicesService) GetAll ¶
func (s *ServicesService) GetAll() (*[]map[string]interface{}, error)
func (*ServicesService) GetAllConfig ¶
func (s *ServicesService) GetAllConfig(db *gorm.DB) ([]json.RawMessage, error)
func (*ServicesService) RestartServices ¶
func (s *ServicesService) RestartServices(tx *gorm.DB, ids []uint) error
func (*ServicesService) Save ¶
func (s *ServicesService) Save(tx *gorm.DB, act string, data json.RawMessage) error
type SettingService ¶
type SettingService struct {
}
func (*SettingService) GetAllSetting ¶
func (s *SettingService) GetAllSetting() (*map[string]string, error)
func (*SettingService) GetCertFile ¶
func (s *SettingService) GetCertFile() (string, error)
func (*SettingService) GetConfig ¶
func (s *SettingService) GetConfig() (string, error)
func (*SettingService) GetFinalSubURI ¶
func (s *SettingService) GetFinalSubURI(host string) (string, error)
func (*SettingService) GetGlobalReset ¶ added in v1.5.4
func (s *SettingService) GetGlobalReset() (string, error)
GetGlobalReset returns the configured period for resetting all clients' traffic: "off", "weekly", "monthly" or "yearly".
func (*SettingService) GetGlobalResetLast ¶ added in v1.5.4
func (s *SettingService) GetGlobalResetLast() (int64, error)
GetGlobalResetLast returns the unix time of the last global traffic reset.
func (*SettingService) GetKeyFile ¶
func (s *SettingService) GetKeyFile() (string, error)
func (*SettingService) GetListen ¶
func (s *SettingService) GetListen() (string, error)
func (*SettingService) GetLoginGuard ¶ added in v1.7.1
func (s *SettingService) GetLoginGuard() (maxFailures int, windowMinutes int, banMinutes int, err error)
GetLoginGuard returns the login rate limit's three knobs: how many failures are tolerated, over how many minutes, and how many minutes a ban then lasts. Zero or negative failures disables the limiter outright, which is why the caller gets the raw numbers rather than a "enabled" flag -- see loginGuard.
func (*SettingService) GetPort ¶
func (s *SettingService) GetPort() (int, error)
func (*SettingService) GetSecret ¶
func (s *SettingService) GetSecret() ([]byte, error)
func (*SettingService) GetSessionMaxAge ¶
func (s *SettingService) GetSessionMaxAge() (int, error)
func (*SettingService) GetStatsBucketSeconds ¶ added in v1.5.4
func (s *SettingService) GetStatsBucketSeconds() (int64, error)
GetStatsBucketSeconds returns the bucket size (in seconds) that traffic samples are rounded down to before being stored. Larger buckets mean fewer rows at the cost of chart resolution. Falls back to the default on a missing or non-positive value.
func (*SettingService) GetSubAcmeEmail ¶
func (s *SettingService) GetSubAcmeEmail() (string, error)
func (*SettingService) GetSubCertFile ¶
func (s *SettingService) GetSubCertFile() (string, error)
func (*SettingService) GetSubCertMode ¶
func (s *SettingService) GetSubCertMode() (string, error)
func (*SettingService) GetSubClashExt ¶
func (s *SettingService) GetSubClashExt() (string, error)
func (*SettingService) GetSubClashNoDefGrp ¶ added in v1.5.5
func (s *SettingService) GetSubClashNoDefGrp() (bool, error)
GetSubClashNoDefGrp reports whether the default "Proxy"/"Auto" proxy-groups should never be injected into a Clash subscription. When true, the config is left with exactly the groups the user defined.
func (*SettingService) GetSubClashSprtAll ¶ added in v1.5.5
func (s *SettingService) GetSubClashSprtAll() (bool, error)
GetSubClashSprtAll reports whether a case-insensitive "all" entry inside a custom proxy-group's "proxies" list should be expanded into every generated proxy tag.
func (*SettingService) GetSubDomain ¶
func (s *SettingService) GetSubDomain() (string, error)
func (*SettingService) GetSubEncode ¶
func (s *SettingService) GetSubEncode() (bool, error)
func (*SettingService) GetSubJsonExt ¶
func (s *SettingService) GetSubJsonExt() (string, error)
func (*SettingService) GetSubKeyFile ¶
func (s *SettingService) GetSubKeyFile() (string, error)
func (*SettingService) GetSubListen ¶
func (s *SettingService) GetSubListen() (string, error)
func (*SettingService) GetSubNginx ¶ added in v1.6.1
func (s *SettingService) GetSubNginx() (bool, error)
GetSubNginx 是订阅侧的「由反向代理终结 TLS」,语义与 webNginx 对称: 开着时订阅服务只跑明文 HTTP,TLS 交给前面的 nginx。 空字符串表示尚未设置,按 false 处理(避免 ParseBool("") 报错);读失败按 GetWebNginx 同样的理由往上传,不塌成 false。
func (*SettingService) GetSubPath ¶
func (s *SettingService) GetSubPath() (string, error)
func (*SettingService) GetSubPort ¶
func (s *SettingService) GetSubPort() (int, error)
func (*SettingService) GetSubShowInfo ¶
func (s *SettingService) GetSubShowInfo() (bool, error)
func (*SettingService) GetSubURI ¶
func (s *SettingService) GetSubURI() (string, error)
func (*SettingService) GetSubUpdates ¶
func (s *SettingService) GetSubUpdates() (int, error)
func (*SettingService) GetTimeLocation ¶
func (s *SettingService) GetTimeLocation() (*time.Location, error)
func (*SettingService) GetTrafficAge ¶
func (s *SettingService) GetTrafficAge() (int, error)
func (*SettingService) GetWebAcmeEmail ¶
func (s *SettingService) GetWebAcmeEmail() (string, error)
func (*SettingService) GetWebCertMode ¶
func (s *SettingService) GetWebCertMode() (string, error)
func (*SettingService) GetWebDomain ¶
func (s *SettingService) GetWebDomain() (string, error)
func (*SettingService) GetWebNginx ¶ added in v1.4.7
func (s *SettingService) GetWebNginx() (bool, error)
func (*SettingService) GetWebPath ¶
func (s *SettingService) GetWebPath() (string, error)
func (*SettingService) GetWebTrustedProxies ¶ added in v1.7.1
func (s *SettingService) GetWebTrustedProxies() ([]netip.Prefix, error)
GetWebTrustedProxies returns the peers that are allowed to speak for a caller through X-Forwarded-For. This is independent of webNginx: operators using their own nginx, Caddy, tunnel or load balancer still need correct source addresses without asking the panel to manage that proxy.
func (*SettingService) GetWebURI ¶ added in v1.6.0
func (s *SettingService) GetWebURI() (string, error)
GetWebURI 返回面板对外地址的手工覆盖值(空表示未设置,由调用方自行推断)。 反代场景下面板推断不出对外地址,只能靠它,参见 sui uri 与前端 restartApp。
func (*SettingService) ProxyVhostSpecs ¶ added in v1.6.2
func (s *SettingService) ProxyVhostSpecs() ([]ProxySide, error)
ProxyVhostSpecs derives which reverse-proxy vhosts nginx should have from the settings ALREADY PERSISTED in the DB, for the startup reconciliation in app.syncNginxProxy. It shares BuildVhostSpecs with the API path that reads the form; the two must produce identical results.
Every read error is reported rather than defaulted away: the reconciliation deletes any generated vhost whose side comes back disabled, so collapsing a failed read to Enabled=false would tear down a live 443 entrypoint over a transient DB error. Every key here is in defaultValueMap, so a missing row yields the default — reaching this path means the read itself failed.
func (*SettingService) ResetSettings ¶
func (s *SettingService) ResetSettings() error
func (*SettingService) Save ¶
func (s *SettingService) Save(tx *gorm.DB, data json.RawMessage) error
func (*SettingService) SaveConfig ¶
func (s *SettingService) SaveConfig(tx *gorm.DB, config json.RawMessage) error
func (*SettingService) SetConfig ¶
func (s *SettingService) SetConfig(config string) error
func (*SettingService) SetGlobalResetLast ¶ added in v1.5.4
func (s *SettingService) SetGlobalResetLast(value int64) error
func (*SettingService) SetPort ¶
func (s *SettingService) SetPort(port int) error
func (*SettingService) SetSubPath ¶
func (s *SettingService) SetSubPath(subPath string) error
func (*SettingService) SetSubPort ¶
func (s *SettingService) SetSubPort(subPort int) error
func (*SettingService) SetWebPath ¶
func (s *SettingService) SetWebPath(webPath string) error
type SingBoxConfig ¶
type SingBoxConfig struct {
Log json.RawMessage `json:"log"`
Dns json.RawMessage `json:"dns"`
Ntp json.RawMessage `json:"ntp"`
Inbounds []json.RawMessage `json:"inbounds"`
Outbounds []json.RawMessage `json:"outbounds"`
Services []json.RawMessage `json:"services"`
Endpoints []json.RawMessage `json:"endpoints"`
Route json.RawMessage `json:"route"`
Experimental json.RawMessage `json:"experimental"`
}
type StatsService ¶
type StatsService struct {
}
func (*StatsService) DelOldStats ¶
func (s *StatsService) DelOldStats(days int) error
func (*StatsService) GetOnlines ¶
func (s *StatsService) GetOnlines() (onlines, error)
type TlsService ¶
type TlsService struct {
InboundService
ServicesService
}
func (*TlsService) Save ¶
func (s *TlsService) Save(tx *gorm.DB, action string, data json.RawMessage, hostname string) error
type UpdatePhase ¶ added in v1.5.6
type UpdatePhase string
const ( UpdateIdle UpdatePhase = "idle" UpdateChecking UpdatePhase = "checking" UpdateDownloading UpdatePhase = "downloading" UpdateVerifying UpdatePhase = "verifying" UpdateExtracting UpdatePhase = "extracting" UpdateSwapping UpdatePhase = "swapping" UpdateRestarting UpdatePhase = "restarting" UpdateDone UpdatePhase = "done" UpdateFailed UpdatePhase = "failed" )
type UpdateService ¶ added in v1.5.6
type UpdateService struct{}
func (*UpdateService) CanSelfUpdate ¶ added in v1.5.6
func (s *UpdateService) CanSelfUpdate() (bool, string)
CanSelfUpdate reports whether an in-panel update can run here, and if not, a short human-readable reason for the UI.
func (*UpdateService) GetStatus ¶ added in v1.5.6
func (s *UpdateService) GetStatus() UpdateStatus
func (*UpdateService) InDocker ¶ added in v1.5.6
func (s *UpdateService) InDocker() bool
InDocker is exposed so the API layer can tell the UI to warn that a container-layer update reverts when the container is recreated.
func (*UpdateService) LatestRelease ¶ added in v1.5.6
func (s *UpdateService) LatestRelease() (string, error)
LatestRelease returns the tag name of the newest GitHub release.
func (*UpdateService) StartUpdate ¶ added in v1.5.6
func (s *UpdateService) StartUpdate() error
StartUpdate validates the environment, then kicks off the update in the background. It returns immediately; callers poll GetStatus.
type UpdateStatus ¶ added in v1.5.6
type UpdateStatus struct {
Phase UpdatePhase `json:"phase"`
Target string `json:"target"`
Message string `json:"message"`
Error string `json:"error"`
}
type UserService ¶
type UserService struct {
}
func (*UserService) ChangePass ¶
func (*UserService) CheckUser ¶
func (s *UserService) CheckUser(username string, password string, code string, remoteIP string) (*model.User, error)
CheckUser authenticates one login attempt. Every rejection except ErrTwoFaRequired carries the same message -- an unknown user, a wrong password and a wrong TOTP code are indistinguishable to the caller, so the response cannot be used to work out which half was right.
func (*UserService) ClearFirstUserTwoFa ¶ added in v1.7.1
func (s *UserService) ClearFirstUserTwoFa() error
ClearFirstUserTwoFa turns the second factor off without checking a password, and exists for the cases where the password is not what is missing: a lost phone with no recovery code, or a clock that moved backwards past the replay high-water mark so every code is refused. Only the CLI calls it, which already requires shell access to the machine holding the database -- anyone who has that can edit the row by hand anyway.
func (*UserService) DeleteToken ¶
func (s *UserService) DeleteToken(id string) error
func (*UserService) DisableTwoFa ¶ added in v1.7.1
func (s *UserService) DisableTwoFa(username string, password string) error
DisableTwoFa needs the account password. The session alone is not enough: turning the second factor off is exactly what someone who has got hold of an unattended browser would want to do.
func (*UserService) EnableTwoFa ¶ added in v1.7.1
func (s *UserService) EnableTwoFa(username string, password string, secret string, code string) error
EnableTwoFa stores a secret only after the current password and a code from the candidate authenticator both work. The password prevents a stolen session from binding somebody else's phone; the code prevents a mistyped secret or bad phone clock from locking the real user out.
func (*UserService) GetFirstUser ¶
func (s *UserService) GetFirstUser() (*model.User, error)
func (*UserService) GetUserTokens ¶
func (s *UserService) GetUserTokens(username string) (*[]model.Tokens, error)
func (*UserService) LoadTokens ¶
func (s *UserService) LoadTokens() ([]byte, error)
func (*UserService) UpdateFirstUser ¶
func (s *UserService) UpdateFirstUser(username string, password string) error
type VhostOptions ¶ added in v1.6.1
type VhostOptions struct {
Domain string
CertFile string // 设置里手填的证书,仅当 /root/cert/<域名>/ 下那份不存在时才用
KeyFile string
Endpoints []ProxyEndpoint
}
VhostOptions 描述一个域名要生成的整份配置。
func BuildVhostSpecs ¶ added in v1.6.2
func BuildVhostSpecs(sides ...ProxySide) ([]VhostOptions, error)
BuildVhostSpecs groups endpoints by DOMAIN rather than by service: panel and subscription commonly share one, and a server block each makes nginx report a conflicting server name and silently drop one of them. Argument order is location order (panel first), and keeping it fixed is what makes the generated content comparable, so EnsureVhost can short-circuit instead of reloading for nothing.
A side switched ON with no domain is an error, never a silent skip: it reads like "disabled" but the service already runs plaintext, and skipping it shrinks specs — possibly to empty — so SyncVhosts deletes the vhost that was answering on 443.
type VhostResult ¶ added in v1.6.1
type VhostResult struct {
Domain string `json:"domain"`
ConfFile string `json:"confFile"`
CertFile string `json:"certFile"`
URLs []string `json:"urls"`
}
VhostResult 回给前端展示:生成了哪个文件、每个端点的对外地址是什么。
type WarpService ¶
type WarpService struct{}
func (*WarpService) RegisterWarp ¶
func (s *WarpService) RegisterWarp(ep *model.Endpoint) error
func (*WarpService) SetWarpLicense ¶
func (s *WarpService) SetWarpLicense(old_license string, ep *model.Endpoint) error