You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

210 regels
6.4 KiB

  1. package controller
  2. import (
  3. "fmt"
  4. "net/http"
  5. "strconv"
  6. "strings"
  7. "github.com/QuantumNous/new-api/common"
  8. "github.com/QuantumNous/new-api/model"
  9. "github.com/QuantumNous/new-api/service"
  10. "github.com/gin-gonic/gin"
  11. "gorm.io/gorm"
  12. )
  13. type AdminVideoChannelBinding struct {
  14. Group string `json:"group"`
  15. Family string `json:"family"`
  16. ChannelID int `json:"channel_id"`
  17. }
  18. type adminVideoChannelBindingRequest struct {
  19. Bindings []AdminVideoChannelBinding `json:"bindings"`
  20. }
  21. type validatedAdminVideoChannelBinding struct {
  22. AdminVideoChannelBinding
  23. ChannelType int
  24. }
  25. type AdminVideoChannelCandidate struct {
  26. ID int `json:"id"`
  27. Name string `json:"name"`
  28. Type int `json:"type"`
  29. }
  30. type adminVideoChannelBindingRow struct {
  31. Group string `json:"group"`
  32. ChannelID int `json:"channel_id"`
  33. ChannelName string `json:"channel_name"`
  34. ChannelType int `json:"channel_type"`
  35. Candidates []AdminVideoChannelCandidate `json:"candidates"`
  36. }
  37. type adminVideoChannelBindingFamily struct {
  38. Key string `json:"key"`
  39. Name string `json:"name"`
  40. Bindings []adminVideoChannelBindingRow `json:"bindings"`
  41. }
  42. func videoAssetFamilyFromString(value string) (service.VideoAssetFamily, bool) {
  43. family := service.VideoAssetFamily(strings.TrimSpace(value))
  44. for _, candidate := range service.VideoAssetFamilies() {
  45. if family == candidate {
  46. return family, true
  47. }
  48. }
  49. return "", false
  50. }
  51. func GetUserVideoChannelBindings(c *gin.Context) {
  52. userID, err := strconv.Atoi(c.Param("id"))
  53. if err != nil || userID <= 0 {
  54. common.ApiErrorMsg(c, "invalid user id")
  55. return
  56. }
  57. if _, err = model.GetUserById(userID, false); err != nil {
  58. common.ApiError(c, err)
  59. return
  60. }
  61. groups, err := model.GetUserConcreteTokenGroups(userID)
  62. if err != nil {
  63. common.ApiError(c, err)
  64. return
  65. }
  66. visibleGroupSet := make(map[string]struct{}, len(groups))
  67. families := make([]adminVideoChannelBindingFamily, 0, len(service.VideoAssetFamilies()))
  68. for _, family := range service.VideoAssetFamilies() {
  69. rows := make([]adminVideoChannelBindingRow, 0, len(groups))
  70. for _, group := range groups {
  71. candidates, err := service.GetVideoAssetChannelCandidates(group, family)
  72. if err != nil {
  73. common.ApiError(c, err)
  74. return
  75. }
  76. if len(candidates) == 0 {
  77. continue
  78. }
  79. visibleGroupSet[group] = struct{}{}
  80. row := adminVideoChannelBindingRow{Group: group, Candidates: make([]AdminVideoChannelCandidate, 0, len(candidates))}
  81. for _, channel := range candidates {
  82. row.Candidates = append(row.Candidates, AdminVideoChannelCandidate{ID: channel.Id, Name: channel.Name, Type: channel.Type})
  83. }
  84. bindings, err := model.GetUserAssetChannelsByTypes(userID, service.VideoAssetChannelTypesForFamily(family), group)
  85. if err != nil {
  86. common.ApiError(c, err)
  87. return
  88. }
  89. for _, binding := range bindings {
  90. for _, candidate := range candidates {
  91. if candidate.Id == binding.ChannelId {
  92. row.ChannelID = candidate.Id
  93. row.ChannelName = candidate.Name
  94. row.ChannelType = candidate.Type
  95. break
  96. }
  97. }
  98. if row.ChannelID != 0 {
  99. break
  100. }
  101. }
  102. rows = append(rows, row)
  103. }
  104. families = append(families, adminVideoChannelBindingFamily{Key: string(family), Name: strings.ToUpper(string(family[:1])) + string(family[1:]), Bindings: rows})
  105. }
  106. visibleGroups := make([]string, 0, len(visibleGroupSet))
  107. for _, group := range groups {
  108. if _, ok := visibleGroupSet[group]; ok {
  109. visibleGroups = append(visibleGroups, group)
  110. }
  111. }
  112. c.JSON(http.StatusOK, gin.H{"success": true, "message": "", "data": gin.H{"groups": visibleGroups, "families": families}})
  113. }
  114. func SetUserVideoChannelBindings(c *gin.Context) {
  115. userID, err := strconv.Atoi(c.Param("id"))
  116. if err != nil || userID <= 0 {
  117. common.ApiErrorMsg(c, "invalid user id")
  118. return
  119. }
  120. if _, err = model.GetUserById(userID, false); err != nil {
  121. common.ApiError(c, err)
  122. return
  123. }
  124. var request adminVideoChannelBindingRequest
  125. if err := c.ShouldBindJSON(&request); err != nil {
  126. common.ApiErrorMsg(c, err.Error())
  127. return
  128. }
  129. groups, err := model.GetUserConcreteTokenGroups(userID)
  130. if err != nil {
  131. common.ApiError(c, err)
  132. return
  133. }
  134. allowedGroups := make(map[string]struct{}, len(groups))
  135. for _, group := range groups {
  136. allowedGroups[group] = struct{}{}
  137. }
  138. requested := make(map[string]validatedAdminVideoChannelBinding, len(request.Bindings))
  139. for _, binding := range request.Bindings {
  140. binding.Group = strings.TrimSpace(binding.Group)
  141. family, ok := videoAssetFamilyFromString(binding.Family)
  142. if !ok || binding.Group == "" || binding.Group == "auto" || binding.ChannelID <= 0 {
  143. common.ApiErrorMsg(c, "invalid video channel binding")
  144. return
  145. }
  146. if _, ok := allowedGroups[binding.Group]; !ok {
  147. common.ApiErrorMsg(c, "token group is not available for this user")
  148. return
  149. }
  150. key := binding.Group + "\x00" + string(family)
  151. if _, exists := requested[key]; exists {
  152. common.ApiErrorMsg(c, "duplicate video channel binding")
  153. return
  154. }
  155. candidates, err := service.GetVideoAssetChannelCandidates(binding.Group, family)
  156. if err != nil {
  157. common.ApiError(c, err)
  158. return
  159. }
  160. channelType := 0
  161. for _, candidate := range candidates {
  162. if candidate.Id == binding.ChannelID {
  163. channelType = candidate.Type
  164. break
  165. }
  166. }
  167. if channelType == 0 {
  168. common.ApiErrorMsg(c, "channel is not available for this video family and token group")
  169. return
  170. }
  171. binding.Family = string(family)
  172. requested[key] = validatedAdminVideoChannelBinding{AdminVideoChannelBinding: binding, ChannelType: channelType}
  173. }
  174. if err := model.DB.Transaction(func(tx *gorm.DB) error {
  175. for _, group := range groups {
  176. for _, family := range service.VideoAssetFamilies() {
  177. key := group + "\x00" + string(family)
  178. binding, exists := requested[key]
  179. channelTypes := service.VideoAssetChannelTypesForFamily(family)
  180. if err := model.DeleteUserAssetChannelsByTypesWithTx(tx, userID, channelTypes, group); err != nil {
  181. return err
  182. }
  183. if !exists {
  184. continue
  185. }
  186. if err := model.BindUserAssetChannelWithTx(tx, userID, binding.ChannelType, group, binding.ChannelID); err != nil {
  187. return err
  188. }
  189. }
  190. }
  191. return nil
  192. }); err != nil {
  193. common.ApiError(c, err)
  194. return
  195. }
  196. model.RecordLog(userID, model.LogTypeManage, fmt.Sprintf("updated video channel bindings for user %d", userID))
  197. c.JSON(http.StatusOK, gin.H{"success": true, "message": ""})
  198. }