···487487 }
488488 })
489489490490- router.PUT("/branding/:key", func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
491491- key := p.ByName("key")
492492- if key == "" {
493493- errors.WriteHTTPBadRequest(w, "key required", nil)
494494- return
495495- }
496496-497497- // get broadcaster from query param or use default
498498- broadcasterID := r.URL.Query().Get("broadcaster")
499499- if broadcasterID == "" {
500500- broadcasterID = a.CLI.BroadcasterHost
501501- }
502502-503503- // read body
504504- data, err := io.ReadAll(r.Body)
505505- if err != nil {
506506- errors.WriteHTTPBadRequest(w, "unable to read request body", err)
507507- return
508508- }
509509-510510- // validate size based on key type
511511- maxSize := 500 * 1024 // 500KB default for logos
512512- if key == "favicon" {
513513- maxSize = 100 * 1024 // 100KB for favicons
514514- } else if key == "siteTitle" || key == "siteDescription" || key == "primaryColor" || key == "accentColor" || key == "defaultStreamKey" || key == "defaultStreamer" {
515515- maxSize = 1024 // 1KB for text values
516516- }
517517- if len(data) > maxSize {
518518- errors.WriteHTTPBadRequest(w, fmt.Sprintf("blob too large (max %d bytes)", maxSize), nil)
519519- return
520520- }
521521-522522- // determine mime type from content-type header
523523- mimeType := r.Header.Get("Content-Type")
524524- if mimeType == "" {
525525- mimeType = "application/octet-stream"
526526- }
527527-528528- // store in database
529529- err = a.StatefulDB.PutBrandingBlob(broadcasterID, key, mimeType, data)
530530- if err != nil {
531531- errors.WriteHTTPInternalServerError(w, "unable to store branding blob", err)
532532- return
533533- }
534534-535535- // invalidate cache
536536- cacheKey := fmt.Sprintf("%s:%s", broadcasterID, key)
537537- a.XRPCServer.BrandingCache.Delete(cacheKey)
538538-539539- w.WriteHeader(http.StatusNoContent)
540540- })
541541-542542- router.DELETE("/branding/:key", func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
543543- key := p.ByName("key")
544544- if key == "" {
545545- errors.WriteHTTPBadRequest(w, "key required", nil)
546546- return
547547- }
548548-549549- // get broadcaster from query param or use default
550550- broadcasterID := r.URL.Query().Get("broadcaster")
551551- if broadcasterID == "" {
552552- broadcasterID = a.CLI.BroadcasterHost
553553- }
554554-555555- err := a.StatefulDB.DeleteBrandingBlob(broadcasterID, key)
556556- if err != nil {
557557- errors.WriteHTTPInternalServerError(w, "unable to delete branding blob", err)
558558- return
559559- }
560560-561561- // invalidate cache
562562- cacheKey := fmt.Sprintf("%s:%s", broadcasterID, key)
563563- a.XRPCServer.BrandingCache.Delete(cacheKey)
564564-565565- w.WriteHeader(http.StatusNoContent)
566566- })
567567-568490 router.POST("/notification-blast", func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
569491 var payload notificationpkg.NotificationBlast
570492 if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
+2
pkg/config/config.go
···137137 WebsocketURL string
138138 BehindHTTPSProxy bool
139139 SegmentDebugDir string
140140+ AdminDIDs []string
140141 Syndicate []string
141142}
142143···235236 cli.StringSliceFlag(fs, &cli.Replicators, "replicators", []string{ReplicatorWebsocket}, "list of replication protocols to use (http, iroh)")
236237 fs.StringVar(&cli.WebsocketURL, "websocket-url", "", "override the websocket (ws:// or wss://) url to use for replication (normally not necessary, used for testing)")
237238 fs.BoolVar(&cli.BehindHTTPSProxy, "behind-https-proxy", false, "set to true if this node is behind an https proxy and we should report https URLs even though the node isn't serving HTTPS")
239239+ cli.StringSliceFlag(fs, &cli.AdminDIDs, "admin-dids", []string{}, "comma-separated list of DIDs that are authorized to modify branding and other admin operations")
238240 cli.StringSliceFlag(fs, &cli.Syndicate, "syndicate", []string{}, "list of DIDs that we should rebroadcast ('*' for everybody)")
239241240242 fs.Bool("external-signing", true, "DEPRECATED, does nothing.")