|
- package controller
-
- import (
- "fmt"
- "net/http"
- "strconv"
- "strings"
-
- "github.com/QuantumNous/new-api/common"
- "github.com/QuantumNous/new-api/model"
- "github.com/QuantumNous/new-api/service"
- "github.com/gin-gonic/gin"
- "gorm.io/gorm"
- )
-
- type AdminVideoChannelBinding struct {
- Group string `json:"group"`
- Family string `json:"family"`
- ChannelID int `json:"channel_id"`
- }
-
- type adminVideoChannelBindingRequest struct {
- Bindings []AdminVideoChannelBinding `json:"bindings"`
- }
-
- type validatedAdminVideoChannelBinding struct {
- AdminVideoChannelBinding
- ChannelType int
- }
-
- type AdminVideoChannelCandidate struct {
- ID int `json:"id"`
- Name string `json:"name"`
- Type int `json:"type"`
- }
-
- type adminVideoChannelBindingRow struct {
- Group string `json:"group"`
- ChannelID int `json:"channel_id"`
- ChannelName string `json:"channel_name"`
- ChannelType int `json:"channel_type"`
- Candidates []AdminVideoChannelCandidate `json:"candidates"`
- }
-
- type adminVideoChannelBindingFamily struct {
- Key string `json:"key"`
- Name string `json:"name"`
- Bindings []adminVideoChannelBindingRow `json:"bindings"`
- }
-
- func videoAssetFamilyFromString(value string) (service.VideoAssetFamily, bool) {
- family := service.VideoAssetFamily(strings.TrimSpace(value))
- for _, candidate := range service.VideoAssetFamilies() {
- if family == candidate {
- return family, true
- }
- }
- return "", false
- }
-
- func GetUserVideoChannelBindings(c *gin.Context) {
- userID, err := strconv.Atoi(c.Param("id"))
- if err != nil || userID <= 0 {
- common.ApiErrorMsg(c, "invalid user id")
- return
- }
- if _, err = model.GetUserById(userID, false); err != nil {
- common.ApiError(c, err)
- return
- }
- groups, err := model.GetUserConcreteTokenGroups(userID)
- if err != nil {
- common.ApiError(c, err)
- return
- }
- visibleGroupSet := make(map[string]struct{}, len(groups))
- families := make([]adminVideoChannelBindingFamily, 0, len(service.VideoAssetFamilies()))
- for _, family := range service.VideoAssetFamilies() {
- rows := make([]adminVideoChannelBindingRow, 0, len(groups))
- for _, group := range groups {
- candidates, err := service.GetVideoAssetChannelCandidates(group, family)
- if err != nil {
- common.ApiError(c, err)
- return
- }
- if len(candidates) == 0 {
- continue
- }
- visibleGroupSet[group] = struct{}{}
- row := adminVideoChannelBindingRow{Group: group, Candidates: make([]AdminVideoChannelCandidate, 0, len(candidates))}
- for _, channel := range candidates {
- row.Candidates = append(row.Candidates, AdminVideoChannelCandidate{ID: channel.Id, Name: channel.Name, Type: channel.Type})
- }
- bindings, err := model.GetUserAssetChannelsByTypes(userID, service.VideoAssetChannelTypesForFamily(family), group)
- if err != nil {
- common.ApiError(c, err)
- return
- }
- for _, binding := range bindings {
- for _, candidate := range candidates {
- if candidate.Id == binding.ChannelId {
- row.ChannelID = candidate.Id
- row.ChannelName = candidate.Name
- row.ChannelType = candidate.Type
- break
- }
- }
- if row.ChannelID != 0 {
- break
- }
- }
- rows = append(rows, row)
- }
- families = append(families, adminVideoChannelBindingFamily{Key: string(family), Name: strings.ToUpper(string(family[:1])) + string(family[1:]), Bindings: rows})
- }
- visibleGroups := make([]string, 0, len(visibleGroupSet))
- for _, group := range groups {
- if _, ok := visibleGroupSet[group]; ok {
- visibleGroups = append(visibleGroups, group)
- }
- }
- c.JSON(http.StatusOK, gin.H{"success": true, "message": "", "data": gin.H{"groups": visibleGroups, "families": families}})
- }
-
- func SetUserVideoChannelBindings(c *gin.Context) {
- userID, err := strconv.Atoi(c.Param("id"))
- if err != nil || userID <= 0 {
- common.ApiErrorMsg(c, "invalid user id")
- return
- }
- if _, err = model.GetUserById(userID, false); err != nil {
- common.ApiError(c, err)
- return
- }
- var request adminVideoChannelBindingRequest
- if err := c.ShouldBindJSON(&request); err != nil {
- common.ApiErrorMsg(c, err.Error())
- return
- }
- groups, err := model.GetUserConcreteTokenGroups(userID)
- if err != nil {
- common.ApiError(c, err)
- return
- }
- allowedGroups := make(map[string]struct{}, len(groups))
- for _, group := range groups {
- allowedGroups[group] = struct{}{}
- }
- requested := make(map[string]validatedAdminVideoChannelBinding, len(request.Bindings))
- for _, binding := range request.Bindings {
- binding.Group = strings.TrimSpace(binding.Group)
- family, ok := videoAssetFamilyFromString(binding.Family)
- if !ok || binding.Group == "" || binding.Group == "auto" || binding.ChannelID <= 0 {
- common.ApiErrorMsg(c, "invalid video channel binding")
- return
- }
- if _, ok := allowedGroups[binding.Group]; !ok {
- common.ApiErrorMsg(c, "token group is not available for this user")
- return
- }
- key := binding.Group + "\x00" + string(family)
- if _, exists := requested[key]; exists {
- common.ApiErrorMsg(c, "duplicate video channel binding")
- return
- }
- candidates, err := service.GetVideoAssetChannelCandidates(binding.Group, family)
- if err != nil {
- common.ApiError(c, err)
- return
- }
- channelType := 0
- for _, candidate := range candidates {
- if candidate.Id == binding.ChannelID {
- channelType = candidate.Type
- break
- }
- }
- if channelType == 0 {
- common.ApiErrorMsg(c, "channel is not available for this video family and token group")
- return
- }
- binding.Family = string(family)
- requested[key] = validatedAdminVideoChannelBinding{AdminVideoChannelBinding: binding, ChannelType: channelType}
- }
- if err := model.DB.Transaction(func(tx *gorm.DB) error {
- for _, group := range groups {
- for _, family := range service.VideoAssetFamilies() {
- key := group + "\x00" + string(family)
- binding, exists := requested[key]
- channelTypes := service.VideoAssetChannelTypesForFamily(family)
- if err := model.DeleteUserAssetChannelsByTypesWithTx(tx, userID, channelTypes, group); err != nil {
- return err
- }
- if !exists {
- continue
- }
- if err := model.BindUserAssetChannelWithTx(tx, userID, binding.ChannelType, group, binding.ChannelID); err != nil {
- return err
- }
- }
- }
- return nil
- }); err != nil {
- common.ApiError(c, err)
- return
- }
- model.RecordLog(userID, model.LogTypeManage, fmt.Sprintf("updated video channel bindings for user %d", userID))
- c.JSON(http.StatusOK, gin.H{"success": true, "message": ""})
- }
|