| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465 |
- package controller
- import (
- "errors"
- "fmt"
- "net/http"
- "strconv"
- "time"
- "github.com/bytedance/sonic"
- "github.com/gin-gonic/gin"
- "github.com/labring/sealos/service/aiproxy/common/network"
- "github.com/labring/sealos/service/aiproxy/common/random"
- "github.com/labring/sealos/service/aiproxy/middleware"
- "github.com/labring/sealos/service/aiproxy/model"
- )
- // TokenResponse represents the response structure for token endpoints
- type TokenResponse struct {
- *model.Token
- AccessedAt time.Time `json:"accessed_at"`
- }
- func (t *TokenResponse) MarshalJSON() ([]byte, error) {
- type Alias TokenResponse
- return sonic.Marshal(&struct {
- *Alias
- CreatedAt int64 `json:"created_at"`
- ExpiredAt int64 `json:"expired_at"`
- AccessedAt int64 `json:"accessed_at"`
- }{
- Alias: (*Alias)(t),
- CreatedAt: t.CreatedAt.UnixMilli(),
- ExpiredAt: t.ExpiredAt.UnixMilli(),
- AccessedAt: t.AccessedAt.UnixMilli(),
- })
- }
- type (
- AddTokenRequest struct {
- Name string `json:"name"`
- Subnets []string `json:"subnets"`
- Models []string `json:"models"`
- ExpiredAt int64 `json:"expiredAt"`
- Quota float64 `json:"quota"`
- }
- UpdateTokenStatusRequest struct {
- Status int `json:"status"`
- }
- UpdateTokenNameRequest struct {
- Name string `json:"name"`
- }
- )
- func (at *AddTokenRequest) ToToken() *model.Token {
- var expiredAt time.Time
- if at.ExpiredAt > 0 {
- expiredAt = time.UnixMilli(at.ExpiredAt)
- }
- return &model.Token{
- Name: model.EmptyNullString(at.Name),
- Subnets: at.Subnets,
- Models: at.Models,
- ExpiredAt: expiredAt,
- Quota: at.Quota,
- }
- }
- func validateToken(token AddTokenRequest) error {
- if token.Name == "" {
- return errors.New("token name cannot be empty")
- }
- if len(token.Name) > 30 {
- return errors.New("token name is too long")
- }
- if err := network.IsValidSubnets(token.Subnets); err != nil {
- return fmt.Errorf("invalid subnet: %w", err)
- }
- return nil
- }
- func validateTokenUpdate(token AddTokenRequest) error {
- if err := network.IsValidSubnets(token.Subnets); err != nil {
- return fmt.Errorf("invalid subnet: %w", err)
- }
- return nil
- }
- func buildTokenResponse(token *model.Token) *TokenResponse {
- lastRequestAt, _ := model.GetTokenLastRequestTime(token.ID)
- return &TokenResponse{
- Token: token,
- AccessedAt: lastRequestAt,
- }
- }
- func buildTokenResponses(tokens []*model.Token) []*TokenResponse {
- responses := make([]*TokenResponse, len(tokens))
- for i, token := range tokens {
- responses[i] = buildTokenResponse(token)
- }
- return responses
- }
- // Token list handlers
- func GetTokens(c *gin.Context) {
- page, perPage := parsePageParams(c)
- group := c.Query("group")
- order := c.Query("order")
- status, _ := strconv.Atoi(c.Query("status"))
- tokens, total, err := model.GetTokens(group, page, perPage, order, status)
- if err != nil {
- middleware.ErrorResponse(c, http.StatusOK, err.Error())
- return
- }
- middleware.SuccessResponse(c, gin.H{
- "tokens": buildTokenResponses(tokens),
- "total": total,
- })
- }
- func GetGroupTokens(c *gin.Context) {
- group := c.Param("group")
- if group == "" {
- middleware.ErrorResponse(c, http.StatusOK, "group is required")
- return
- }
- page, perPage := parsePageParams(c)
- order := c.Query("order")
- status, _ := strconv.Atoi(c.Query("status"))
- tokens, total, err := model.GetTokens(group, page, perPage, order, status)
- if err != nil {
- middleware.ErrorResponse(c, http.StatusOK, err.Error())
- return
- }
- middleware.SuccessResponse(c, gin.H{
- "tokens": buildTokenResponses(tokens),
- "total": total,
- })
- }
- func SearchTokens(c *gin.Context) {
- page, perPage := parsePageParams(c)
- keyword := c.Query("keyword")
- order := c.Query("order")
- name := c.Query("name")
- key := c.Query("key")
- status, _ := strconv.Atoi(c.Query("status"))
- group := c.Query("group")
- tokens, total, err := model.SearchTokens(group, keyword, page, perPage, order, status, name, key)
- if err != nil {
- middleware.ErrorResponse(c, http.StatusOK, err.Error())
- return
- }
- middleware.SuccessResponse(c, gin.H{
- "tokens": buildTokenResponses(tokens),
- "total": total,
- })
- }
- func SearchGroupTokens(c *gin.Context) {
- group := c.Param("group")
- if group == "" {
- middleware.ErrorResponse(c, http.StatusOK, "group is required")
- return
- }
- page, perPage := parsePageParams(c)
- keyword := c.Query("keyword")
- order := c.Query("order")
- name := c.Query("name")
- key := c.Query("key")
- status, _ := strconv.Atoi(c.Query("status"))
- tokens, total, err := model.SearchTokens(group, keyword, page, perPage, order, status, name, key)
- if err != nil {
- middleware.ErrorResponse(c, http.StatusOK, err.Error())
- return
- }
- middleware.SuccessResponse(c, gin.H{
- "tokens": buildTokenResponses(tokens),
- "total": total,
- })
- }
- // Single token handlers
- func GetToken(c *gin.Context) {
- id, err := strconv.Atoi(c.Param("id"))
- if err != nil {
- middleware.ErrorResponse(c, http.StatusOK, err.Error())
- return
- }
- token, err := model.GetTokenByID(id)
- if err != nil {
- middleware.ErrorResponse(c, http.StatusOK, err.Error())
- return
- }
- middleware.SuccessResponse(c, buildTokenResponse(token))
- }
- func GetGroupToken(c *gin.Context) {
- group := c.Param("group")
- if group == "" {
- middleware.ErrorResponse(c, http.StatusOK, "group is required")
- return
- }
- id, err := strconv.Atoi(c.Param("id"))
- if err != nil {
- middleware.ErrorResponse(c, http.StatusOK, err.Error())
- return
- }
- token, err := model.GetGroupTokenByID(group, id)
- if err != nil {
- middleware.ErrorResponse(c, http.StatusOK, err.Error())
- return
- }
- middleware.SuccessResponse(c, buildTokenResponse(token))
- }
- func AddGroupToken(c *gin.Context) {
- group := c.Param("group")
- var req AddTokenRequest
- if err := c.ShouldBindJSON(&req); err != nil {
- middleware.ErrorResponse(c, http.StatusOK, err.Error())
- return
- }
- if err := validateToken(req); err != nil {
- middleware.ErrorResponse(c, http.StatusOK, "parameter error: "+err.Error())
- return
- }
- token := req.ToToken()
- token.GroupID = group
- token.Key = random.GenerateKey()
- if err := model.InsertToken(token, c.Query("auto_create_group") == "true"); err != nil {
- middleware.ErrorResponse(c, http.StatusOK, err.Error())
- return
- }
- middleware.SuccessResponse(c, &TokenResponse{Token: token})
- }
- // Delete handlers
- func DeleteToken(c *gin.Context) {
- id, err := strconv.Atoi(c.Param("id"))
- if err != nil {
- middleware.ErrorResponse(c, http.StatusOK, err.Error())
- return
- }
- if err := model.DeleteTokenByID(id); err != nil {
- middleware.ErrorResponse(c, http.StatusOK, err.Error())
- return
- }
- middleware.SuccessResponse(c, nil)
- }
- func DeleteTokens(c *gin.Context) {
- var ids []int
- if err := c.ShouldBindJSON(&ids); err != nil {
- middleware.ErrorResponse(c, http.StatusOK, err.Error())
- return
- }
- if err := model.DeleteTokensByIDs(ids); err != nil {
- middleware.ErrorResponse(c, http.StatusOK, err.Error())
- return
- }
- middleware.SuccessResponse(c, nil)
- }
- func DeleteGroupToken(c *gin.Context) {
- group := c.Param("group")
- id, err := strconv.Atoi(c.Param("id"))
- if err != nil {
- middleware.ErrorResponse(c, http.StatusOK, err.Error())
- return
- }
- if err := model.DeleteGroupTokenByID(group, id); err != nil {
- middleware.ErrorResponse(c, http.StatusOK, err.Error())
- return
- }
- middleware.SuccessResponse(c, nil)
- }
- func DeleteGroupTokens(c *gin.Context) {
- group := c.Param("group")
- var ids []int
- if err := c.ShouldBindJSON(&ids); err != nil {
- middleware.ErrorResponse(c, http.StatusOK, err.Error())
- return
- }
- if err := model.DeleteGroupTokensByIDs(group, ids); err != nil {
- middleware.ErrorResponse(c, http.StatusOK, err.Error())
- return
- }
- middleware.SuccessResponse(c, nil)
- }
- // Update handlers
- func UpdateToken(c *gin.Context) {
- id, err := strconv.Atoi(c.Param("id"))
- if err != nil {
- middleware.ErrorResponse(c, http.StatusOK, err.Error())
- return
- }
- var req AddTokenRequest
- if err := c.ShouldBindJSON(&req); err != nil {
- middleware.ErrorResponse(c, http.StatusOK, err.Error())
- return
- }
- if err := validateTokenUpdate(req); err != nil {
- middleware.ErrorResponse(c, http.StatusOK, "parameter error: "+err.Error())
- return
- }
- token := req.ToToken()
- if err := model.UpdateToken(id, token); err != nil {
- middleware.ErrorResponse(c, http.StatusOK, err.Error())
- return
- }
- middleware.SuccessResponse(c, &TokenResponse{Token: token})
- }
- func UpdateGroupToken(c *gin.Context) {
- group := c.Param("group")
- id, err := strconv.Atoi(c.Param("id"))
- if err != nil {
- middleware.ErrorResponse(c, http.StatusOK, err.Error())
- return
- }
- var req AddTokenRequest
- if err := c.ShouldBindJSON(&req); err != nil {
- middleware.ErrorResponse(c, http.StatusOK, err.Error())
- return
- }
- if err := validateTokenUpdate(req); err != nil {
- middleware.ErrorResponse(c, http.StatusOK, "parameter error: "+err.Error())
- return
- }
- token := req.ToToken()
- if err := model.UpdateGroupToken(id, group, token); err != nil {
- middleware.ErrorResponse(c, http.StatusOK, err.Error())
- return
- }
- middleware.SuccessResponse(c, &TokenResponse{Token: token})
- }
- func UpdateTokenStatus(c *gin.Context) {
- id, err := strconv.Atoi(c.Param("id"))
- if err != nil {
- middleware.ErrorResponse(c, http.StatusOK, err.Error())
- return
- }
- var req UpdateTokenStatusRequest
- if err := c.ShouldBindJSON(&req); err != nil {
- middleware.ErrorResponse(c, http.StatusOK, err.Error())
- return
- }
- if err := model.UpdateTokenStatus(id, req.Status); err != nil {
- middleware.ErrorResponse(c, http.StatusOK, err.Error())
- return
- }
- middleware.SuccessResponse(c, nil)
- }
- func UpdateGroupTokenStatus(c *gin.Context) {
- group := c.Param("group")
- id, err := strconv.Atoi(c.Param("id"))
- if err != nil {
- middleware.ErrorResponse(c, http.StatusOK, err.Error())
- return
- }
- var req UpdateTokenStatusRequest
- if err := c.ShouldBindJSON(&req); err != nil {
- middleware.ErrorResponse(c, http.StatusOK, err.Error())
- return
- }
- if err := model.UpdateGroupTokenStatus(group, id, req.Status); err != nil {
- middleware.ErrorResponse(c, http.StatusOK, err.Error())
- return
- }
- middleware.SuccessResponse(c, nil)
- }
- func UpdateTokenName(c *gin.Context) {
- id, err := strconv.Atoi(c.Param("id"))
- if err != nil {
- middleware.ErrorResponse(c, http.StatusOK, err.Error())
- return
- }
- var req UpdateTokenNameRequest
- if err := c.ShouldBindJSON(&req); err != nil {
- middleware.ErrorResponse(c, http.StatusOK, err.Error())
- return
- }
- if err := model.UpdateTokenName(id, req.Name); err != nil {
- middleware.ErrorResponse(c, http.StatusOK, err.Error())
- return
- }
- middleware.SuccessResponse(c, nil)
- }
- func UpdateGroupTokenName(c *gin.Context) {
- group := c.Param("group")
- id, err := strconv.Atoi(c.Param("id"))
- if err != nil {
- middleware.ErrorResponse(c, http.StatusOK, err.Error())
- return
- }
- var req UpdateTokenNameRequest
- if err := c.ShouldBindJSON(&req); err != nil {
- middleware.ErrorResponse(c, http.StatusOK, err.Error())
- return
- }
- if err := model.UpdateGroupTokenName(group, id, req.Name); err != nil {
- middleware.ErrorResponse(c, http.StatusOK, err.Error())
- return
- }
- middleware.SuccessResponse(c, nil)
- }
|