Quellcode durchsuchen

Clean up guild bridge/unbridge provisioning APIs

Tulir Asokan vor 2 Jahren
Ursprung
Commit
88908bf11b
1 geänderte Dateien mit 82 neuen und 34 gelöschten Zeilen
  1. 82 34
      provisioning.go

+ 82 - 34
provisioning.go

@@ -14,6 +14,7 @@ import (
 	"github.com/gorilla/websocket"
 	log "maunium.net/go/maulogger/v2"
 
+	"maunium.net/go/mautrix/bridge/bridgeconfig"
 	"maunium.net/go/mautrix/id"
 
 	"go.mau.fi/mautrix-discord/remoteauth"
@@ -50,9 +51,8 @@ func newProvisioningAPI(br *DiscordBridge) *ProvisioningAPI {
 	r.HandleFunc("/v1/reconnect", p.reconnect).Methods(http.MethodPost)
 
 	r.HandleFunc("/v1/guilds", p.guildsList).Methods(http.MethodGet)
-	r.HandleFunc("/v1/guilds/{guildID}/bridge", p.guildsBridge).Methods(http.MethodPost)
-	r.HandleFunc("/v1/guilds/{guildID}/unbridge", p.guildsUnbridge).Methods(http.MethodPost)
-	r.HandleFunc("/v1/guilds/{guildID}/joinentire", p.guildsJoinEntire).Methods(http.MethodPost)
+	r.HandleFunc("/v1/guilds/{guildID}", p.guildsBridge).Methods(http.MethodPost)
+	r.HandleFunc("/v1/guilds/{guildID}", p.guildsUnbridge).Methods(http.MethodDelete)
 
 	return p
 }
@@ -415,68 +415,116 @@ func (p *ProvisioningAPI) reconnect(w http.ResponseWriter, r *http.Request) {
 	}
 }
 
+type guildEntry struct {
+	ID         string        `json:"id"`
+	Name       string        `json:"name"`
+	AvatarURL  id.ContentURI `json:"avatar_url"`
+	MXID       id.RoomID     `json:"mxid"`
+	AutoBridge bool          `json:"auto_bridge_channels"`
+}
+
+type respGuildsList struct {
+	Guilds []guildEntry `json:"guilds"`
+}
+
 func (p *ProvisioningAPI) guildsList(w http.ResponseWriter, r *http.Request) {
 	user := r.Context().Value("user").(*User)
 
-	var data []map[string]interface{}
+	var resp respGuildsList
+	resp.Guilds = []guildEntry{}
 	for _, userGuild := range user.GetPortals() {
 		guild := p.bridge.GetGuildByID(userGuild.DiscordID, false)
 		if guild == nil {
 			continue
 		}
-		data = append(data, map[string]interface{}{
-			"name": guild.Name,
-			"id":   guild.ID,
-			"mxid": guild.MXID,
+		resp.Guilds = append(resp.Guilds, guildEntry{
+			ID:         guild.ID,
+			Name:       guild.PlainName,
+			AvatarURL:  guild.AvatarURL,
+			MXID:       guild.MXID,
+			AutoBridge: guild.AutoBridgeChannels,
 		})
 	}
 
-	jsonResponse(w, http.StatusOK, data)
+	jsonResponse(w, http.StatusOK, resp)
+}
+
+type reqBridgeGuild struct {
+	AutoCreateChannels bool `json:"auto_create_channels"`
+}
+
+type respBridgeGuild struct {
+	Success bool      `json:"success"`
+	MXID    id.RoomID `json:"mxid"`
 }
 
 func (p *ProvisioningAPI) guildsBridge(w http.ResponseWriter, r *http.Request) {
 	user := r.Context().Value("user").(*User)
+	guildID := mux.Vars(r)["guildID"]
 
-	guildID, _ := mux.Vars(r)["guildID"]
+	var body reqBridgeGuild
+	if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
+		p.log.Errorln("Failed to parse bridge request:", err)
+		jsonResponse(w, http.StatusBadRequest, Error{
+			Error:   "Failed to parse request body",
+			ErrCode: "bad request",
+		})
+		return
+	}
 
-	if err := user.bridgeGuild(guildID, false); err != nil {
+	guild := user.bridge.GetGuildByID(guildID, false)
+	if guild == nil {
 		jsonResponse(w, http.StatusNotFound, Error{
-			Error:   err.Error(),
+			Error:   "Guild not found",
 			ErrCode: "M_NOT_FOUND",
 		})
+		return
+	}
+	alreadyExists := guild.MXID == ""
+	if err := user.bridgeGuild(guildID, body.AutoCreateChannels); err != nil {
+		p.log.Errorfln("Error bridging %s: %v", guildID, err)
+		jsonResponse(w, http.StatusInternalServerError, Error{
+			Error:   "Internal error while trying to bridge guild",
+			ErrCode: "guild bridge failed",
+		})
+	} else if alreadyExists {
+		jsonResponse(w, http.StatusOK, respBridgeGuild{
+			Success: true,
+			MXID:    guild.MXID,
+		})
 	} else {
-		w.WriteHeader(http.StatusCreated)
+		jsonResponse(w, http.StatusCreated, respBridgeGuild{
+			Success: true,
+			MXID:    guild.MXID,
+		})
 	}
 }
 
 func (p *ProvisioningAPI) guildsUnbridge(w http.ResponseWriter, r *http.Request) {
+	guildID := mux.Vars(r)["guildID"]
 	user := r.Context().Value("user").(*User)
-
-	guildID, _ := mux.Vars(r)["guildID"]
-
-	if err := user.unbridgeGuild(guildID); err != nil {
+	if user.PermissionLevel < bridgeconfig.PermissionLevelAdmin {
+		jsonResponse(w, http.StatusForbidden, Error{
+			Error:   "Only bridge admins can unbridge guilds",
+			ErrCode: "M_FORBIDDEN",
+		})
+	} else if guild := user.bridge.GetGuildByID(guildID, false); guild == nil {
 		jsonResponse(w, http.StatusNotFound, Error{
-			Error:   err.Error(),
+			Error:   "Guild not found",
 			ErrCode: "M_NOT_FOUND",
 		})
-
-		return
-	}
-
-	w.WriteHeader(http.StatusNoContent)
-}
-
-func (p *ProvisioningAPI) guildsJoinEntire(w http.ResponseWriter, r *http.Request) {
-	user := r.Context().Value("user").(*User)
-
-	guildID, _ := mux.Vars(r)["guildID"]
-
-	if err := user.bridgeGuild(guildID, true); err != nil {
+	} else if !guild.AutoBridgeChannels && guild.MXID == "" {
 		jsonResponse(w, http.StatusNotFound, Error{
-			Error:   err.Error(),
-			ErrCode: "M_NOT_FOUND",
+			Error:   "That guild is not bridged",
+			ErrCode: "not bridged",
+		})
+	} else if err := user.unbridgeGuild(guildID); err != nil {
+		p.log.Errorfln("Error unbridging %s: %v", guildID, err)
+		jsonResponse(w, http.StatusInternalServerError, Error{
+			Error:   "Internal error while trying to unbridge guild",
+			ErrCode: "guild unbridge failed",
 		})
 	} else {
-		w.WriteHeader(http.StatusCreated)
+		w.WriteHeader(http.StatusNoContent)
 	}
 }