Muse needs a trusted path to create and disable per-user long-lived relay tokens so billing, routing, and downgrade logic can stay inside new-api instead of leaking back into Muse. This adds a small internal route group guarded by a shared secret, provisions a mirror user plus a dedicated long-lived token, and exposes disable/status/revoke operations for the control plane. The sync path stores the Muse user id in remark as a temporary lookup anchor until Muse persists the returned new-api ids. Constraint: Must reuse new-api billing/token model behavior without adding schema changes in phase 1 Constraint: Must avoid CreateUser side effects such as signup quota grants for mirrored internal users Rejected: Reusing existing self-service token controllers | they only manage the authenticated owner and cannot return control-plane ids/keys Rejected: Keying mirror users by username/email alone | unstable and collision-prone for external identity sync Confidence: medium Scope-risk: moderate Reversibility: clean Directive: Treat remark-based muse_user_id lookup as a phase-1 bridge; prefer persisted new_api_user_id from Muse binding records for later operations Tested: go test ./controller ./service ./middleware -run MuseInternal -count=1 Tested: go test ./controller ./service ./middleware -count=1 Not-tested: Full relay/data-plane integration against a live Muse control-plane caller
68 lines
1.4 KiB
Go
68 lines
1.4 KiB
Go
package controller
|
|
|
|
import (
|
|
"errors"
|
|
"strconv"
|
|
|
|
"github.com/QuantumNous/new-api/common"
|
|
museDTO "github.com/QuantumNous/new-api/dto"
|
|
"github.com/QuantumNous/new-api/service"
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
func SyncMuseUser(c *gin.Context) {
|
|
var req museDTO.SyncMuseUserRequest
|
|
if err := common.DecodeJson(c.Request.Body, &req); err != nil {
|
|
common.ApiError(c, errors.New("invalid request body"))
|
|
return
|
|
}
|
|
response, err := service.SyncMuseUser(req)
|
|
if err != nil {
|
|
common.ApiError(c, err)
|
|
return
|
|
}
|
|
common.ApiSuccess(c, response)
|
|
}
|
|
|
|
func DisableMuseUser(c *gin.Context) {
|
|
userID, err := strconv.Atoi(c.Param("id"))
|
|
if err != nil {
|
|
common.ApiError(c, errors.New("invalid user id"))
|
|
return
|
|
}
|
|
response, err := service.DisableMuseUserByID(userID)
|
|
if err != nil {
|
|
common.ApiError(c, err)
|
|
return
|
|
}
|
|
common.ApiSuccess(c, response)
|
|
}
|
|
|
|
func RevokeMuseToken(c *gin.Context) {
|
|
tokenID, err := strconv.Atoi(c.Param("id"))
|
|
if err != nil {
|
|
common.ApiError(c, errors.New("invalid token id"))
|
|
return
|
|
}
|
|
response, err := service.RevokeMuseToken(tokenID)
|
|
if err != nil {
|
|
common.ApiError(c, err)
|
|
return
|
|
}
|
|
common.ApiSuccess(c, response)
|
|
}
|
|
|
|
func GetMuseUserStatus(c *gin.Context) {
|
|
userID, err := strconv.Atoi(c.Param("id"))
|
|
if err != nil {
|
|
common.ApiError(c, errors.New("invalid user id"))
|
|
return
|
|
}
|
|
response, err := service.GetMuseUserStatus(userID)
|
|
if err != nil {
|
|
common.ApiError(c, err)
|
|
return
|
|
}
|
|
common.ApiSuccess(c, response)
|
|
}
|