feat(server): web 用户中心后端(2/3) — 订阅 URL 端点
- GET /v1/me/subscription:返回 {url}=<SUB_BASE 或请求 host>/sub/<token>,
首次访问按需生成 users.sub_token。
- POST /v1/me/subscription/reset:轮换 sub_token,返回新 url。
- GET /sub/{token}(公开,无 JWT):按 token 查用户 dp_uuid,取首个活跃节点,
复用 httpapi.BuildClientConfig 渲染 sing-box 客户端配置返回(仅在配置了节点存储时挂载)。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -258,8 +258,19 @@ func mountV1(r chi.Router, sqlDB *sql.DB, rdb *redis.Client, nodeSvc *nodes.Serv
|
||||
|
||||
// ── Nodes + Connect ───────────────────────────────────────────────────────
|
||||
var nodeAPI *httpapi.NodeAPI
|
||||
var nodeStore nodes.NodeStore
|
||||
if nodeSvc != nil {
|
||||
nodeAPI = httpapi.NewNodeAPI(nodeSvc.Store(), nodeSvc.Hub(), os.Getenv("NODE_DERIVE_KEY"))
|
||||
nodeStore = nodeSvc.Store()
|
||||
nodeAPI = httpapi.NewNodeAPI(nodeStore, nodeSvc.Hub(), os.Getenv("NODE_DERIVE_KEY"))
|
||||
}
|
||||
|
||||
// ── Subscription URL (web user-center 订阅导入) ───────────────────────────
|
||||
subAPI := httpapi.NewSubscriptionAPI(sqlDB, nodeStore, os.Getenv("NODE_DERIVE_KEY"), os.Getenv("SUB_BASE"))
|
||||
|
||||
// Public subscription endpoint (no JWT): clients fetch their sing-box config
|
||||
// from the per-user URL. Only available when a node store is configured.
|
||||
if nodeStore != nil {
|
||||
r.Get("/sub/{token}", subAPI.ServeSub)
|
||||
}
|
||||
|
||||
// ─── Mount under /v1 ─────────────────────────────────────────────────────
|
||||
@@ -286,6 +297,8 @@ func mountV1(r chi.Router, sqlDB *sql.DB, rdb *redis.Client, nodeSvc *nodes.Serv
|
||||
devicesHandler.RegisterRoutes(me)
|
||||
// Web 用户中心调用 /v1/me/redeem;app 仍用 /v1/redeem。两者同处理器。
|
||||
me.Post("/redeem", redeemHandler.ServeHTTP)
|
||||
me.Get("/subscription", subAPI.GetSubscription)
|
||||
me.Post("/subscription/reset", subAPI.ResetSubscription)
|
||||
})
|
||||
protected.Post("/redeem", redeemHandler.ServeHTTP)
|
||||
protected.Get("/usage", usageHandler.ServeHTTP)
|
||||
|
||||
Reference in New Issue
Block a user