Move MakeLeave to GMSL (#3085)

Basically the same API shape as for `/make_join`
https://github.com/matrix-org/gomatrixserverlib/pull/385
This commit is contained in:
Till 2023-05-23 19:37:04 +02:00 committed by GitHub
parent 2eae8dc489
commit 5d6221d191
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 108 additions and 89 deletions

View File

@ -99,7 +99,7 @@ func MakeJoin(
} }
req := api.QueryServerJoinedToRoomRequest{ req := api.QueryServerJoinedToRoomRequest{
ServerName: cfg.Matrix.ServerName, ServerName: request.Destination(),
RoomID: roomID.String(), RoomID: roomID.String(),
} }
res := api.QueryServerJoinedToRoomResponse{} res := api.QueryServerJoinedToRoomResponse{}
@ -162,13 +162,13 @@ func MakeJoin(
switch e := internalErr.(type) { switch e := internalErr.(type) {
case nil: case nil:
case spec.InternalServerError: case spec.InternalServerError:
util.GetLogger(httpReq.Context()).WithError(internalErr) util.GetLogger(httpReq.Context()).WithError(internalErr).Error("failed to handle make_join request")
return util.JSONResponse{ return util.JSONResponse{
Code: http.StatusInternalServerError, Code: http.StatusInternalServerError,
JSON: spec.InternalServerError{}, JSON: spec.InternalServerError{},
} }
case spec.MatrixError: case spec.MatrixError:
util.GetLogger(httpReq.Context()).WithError(internalErr) util.GetLogger(httpReq.Context()).WithError(internalErr).Error("failed to handle make_join request")
code := http.StatusInternalServerError code := http.StatusInternalServerError
switch e.ErrCode { switch e.ErrCode {
case spec.ErrorForbidden: case spec.ErrorForbidden:
@ -186,13 +186,13 @@ func MakeJoin(
JSON: e, JSON: e,
} }
case spec.IncompatibleRoomVersionError: case spec.IncompatibleRoomVersionError:
util.GetLogger(httpReq.Context()).WithError(internalErr) util.GetLogger(httpReq.Context()).WithError(internalErr).Error("failed to handle make_join request")
return util.JSONResponse{ return util.JSONResponse{
Code: http.StatusBadRequest, Code: http.StatusBadRequest,
JSON: e, JSON: e,
} }
default: default:
util.GetLogger(httpReq.Context()).WithError(internalErr) util.GetLogger(httpReq.Context()).WithError(internalErr).Error("failed to handle make_join request")
return util.JSONResponse{ return util.JSONResponse{
Code: http.StatusBadRequest, Code: http.StatusBadRequest,
JSON: spec.Unknown("unknown error"), JSON: spec.Unknown("unknown error"),

View File

@ -34,108 +34,115 @@ func MakeLeave(
request *fclient.FederationRequest, request *fclient.FederationRequest,
cfg *config.FederationAPI, cfg *config.FederationAPI,
rsAPI api.FederationRoomserverAPI, rsAPI api.FederationRoomserverAPI,
roomID, userID string, roomID spec.RoomID, userID spec.UserID,
) util.JSONResponse { ) util.JSONResponse {
_, domain, err := gomatrixserverlib.SplitID('@', userID) roomVersion, err := rsAPI.QueryRoomVersionForRoom(httpReq.Context(), roomID.String())
if err != nil { if err != nil {
return util.JSONResponse{ util.GetLogger(httpReq.Context()).WithError(err).Error("failed obtaining room version")
Code: http.StatusBadRequest,
JSON: spec.BadJSON("Invalid UserID"),
}
}
if domain != request.Origin() {
return util.JSONResponse{
Code: http.StatusForbidden,
JSON: spec.Forbidden("The leave must be sent by the server of the user"),
}
}
// Try building an event for the server
proto := gomatrixserverlib.ProtoEvent{
Sender: userID,
RoomID: roomID,
Type: "m.room.member",
StateKey: &userID,
}
err = proto.SetContent(map[string]interface{}{"membership": spec.Leave})
if err != nil {
util.GetLogger(httpReq.Context()).WithError(err).Error("proto.SetContent failed")
return util.JSONResponse{ return util.JSONResponse{
Code: http.StatusInternalServerError, Code: http.StatusInternalServerError,
JSON: spec.InternalServerError{}, JSON: spec.InternalServerError{},
} }
} }
identity, err := cfg.Matrix.SigningIdentityFor(request.Destination()) req := api.QueryServerJoinedToRoomRequest{
if err != nil { ServerName: request.Destination(),
RoomID: roomID.String(),
}
res := api.QueryServerJoinedToRoomResponse{}
if err := rsAPI.QueryServerJoinedToRoom(httpReq.Context(), &req, &res); err != nil {
util.GetLogger(httpReq.Context()).WithError(err).Error("rsAPI.QueryServerJoinedToRoom failed")
return util.JSONResponse{ return util.JSONResponse{
Code: http.StatusNotFound, Code: http.StatusInternalServerError,
JSON: spec.NotFound( JSON: spec.InternalServerError{},
fmt.Sprintf("Server name %q does not exist", request.Destination()),
),
} }
} }
var queryRes api.QueryLatestEventsAndStateResponse createLeaveTemplate := func(proto *gomatrixserverlib.ProtoEvent) (gomatrixserverlib.PDU, []gomatrixserverlib.PDU, error) {
event, err := eventutil.QueryAndBuildEvent(httpReq.Context(), &proto, cfg.Matrix, identity, time.Now(), rsAPI, &queryRes) identity, err := cfg.Matrix.SigningIdentityFor(request.Destination())
switch e := err.(type) { if err != nil {
case nil: util.GetLogger(httpReq.Context()).WithError(err).Errorf("obtaining signing identity for %s failed", request.Destination())
case eventutil.ErrRoomNoExists: return nil, nil, spec.NotFound(fmt.Sprintf("Server name %q does not exist", request.Destination()))
util.GetLogger(httpReq.Context()).WithError(err).Error("eventutil.BuildEvent failed")
return util.JSONResponse{
Code: http.StatusNotFound,
JSON: spec.NotFound("Room does not exist"),
} }
case gomatrixserverlib.BadJSONError:
util.GetLogger(httpReq.Context()).WithError(err).Error("eventutil.BuildEvent failed") queryRes := api.QueryLatestEventsAndStateResponse{}
event, err := eventutil.QueryAndBuildEvent(httpReq.Context(), proto, cfg.Matrix, identity, time.Now(), rsAPI, &queryRes)
switch e := err.(type) {
case nil:
case eventutil.ErrRoomNoExists:
util.GetLogger(httpReq.Context()).WithError(err).Error("eventutil.BuildEvent failed")
return nil, nil, spec.NotFound("Room does not exist")
case gomatrixserverlib.BadJSONError:
util.GetLogger(httpReq.Context()).WithError(err).Error("eventutil.BuildEvent failed")
return nil, nil, spec.BadJSON(e.Error())
default:
util.GetLogger(httpReq.Context()).WithError(err).Error("eventutil.BuildEvent failed")
return nil, nil, spec.InternalServerError{}
}
stateEvents := make([]gomatrixserverlib.PDU, len(queryRes.StateEvents))
for i, stateEvent := range queryRes.StateEvents {
stateEvents[i] = stateEvent.PDU
}
return event, stateEvents, nil
}
input := gomatrixserverlib.HandleMakeLeaveInput{
UserID: userID,
RoomID: roomID,
RoomVersion: roomVersion,
RequestOrigin: request.Origin(),
LocalServerName: cfg.Matrix.ServerName,
LocalServerInRoom: res.RoomExists && res.IsInRoom,
BuildEventTemplate: createLeaveTemplate,
}
response, internalErr := gomatrixserverlib.HandleMakeLeave(input)
switch e := internalErr.(type) {
case nil:
case spec.InternalServerError:
util.GetLogger(httpReq.Context()).WithError(internalErr).Error("failed to handle make_leave request")
return util.JSONResponse{ return util.JSONResponse{
Code: http.StatusBadRequest, Code: http.StatusInternalServerError,
JSON: spec.BadJSON(e.Error()), JSON: spec.InternalServerError{},
}
case spec.MatrixError:
util.GetLogger(httpReq.Context()).WithError(internalErr).Error("failed to handle make_leave request")
code := http.StatusInternalServerError
switch e.ErrCode {
case spec.ErrorForbidden:
code = http.StatusForbidden
case spec.ErrorNotFound:
code = http.StatusNotFound
case spec.ErrorBadJSON:
code = http.StatusBadRequest
}
return util.JSONResponse{
Code: code,
JSON: e,
} }
default: default:
util.GetLogger(httpReq.Context()).WithError(err).Error("eventutil.BuildEvent failed") util.GetLogger(httpReq.Context()).WithError(internalErr).Error("failed to handle make_leave request")
return util.JSONResponse{
Code: http.StatusBadRequest,
JSON: spec.Unknown("unknown error"),
}
}
if response == nil {
util.GetLogger(httpReq.Context()).Error("gmsl.HandleMakeLeave returned invalid response")
return util.JSONResponse{ return util.JSONResponse{
Code: http.StatusInternalServerError, Code: http.StatusInternalServerError,
JSON: spec.InternalServerError{}, JSON: spec.InternalServerError{},
} }
} }
// If the user has already left then just return their last leave
// event. This means that /send_leave will be a no-op, which helps
// to reject invites multiple times - hopefully.
for _, state := range queryRes.StateEvents {
if !state.StateKeyEquals(userID) {
continue
}
if mem, merr := state.Membership(); merr == nil && mem == spec.Leave {
return util.JSONResponse{
Code: http.StatusOK,
JSON: map[string]interface{}{
"room_version": event.Version(),
"event": state,
},
}
}
}
// Check that the leave is allowed or not
stateEvents := make([]gomatrixserverlib.PDU, len(queryRes.StateEvents))
for i := range queryRes.StateEvents {
stateEvents[i] = queryRes.StateEvents[i].PDU
}
provider := gomatrixserverlib.NewAuthEvents(stateEvents)
if err = gomatrixserverlib.Allowed(event, &provider); err != nil {
return util.JSONResponse{
Code: http.StatusForbidden,
JSON: spec.Forbidden(err.Error()),
}
}
return util.JSONResponse{ return util.JSONResponse{
Code: http.StatusOK, Code: http.StatusOK,
JSON: map[string]interface{}{ JSON: map[string]interface{}{
"room_version": event.Version(), "event": response.LeaveTemplateEvent,
"event": proto, "room_version": response.RoomVersion,
}, },
} }
} }

View File

@ -412,7 +412,7 @@ func Setup(
}, },
)).Methods(http.MethodPut) )).Methods(http.MethodPut)
v1fedmux.Handle("/make_leave/{roomID}/{eventID}", MakeFedAPI( v1fedmux.Handle("/make_leave/{roomID}/{userID}", MakeFedAPI(
"federation_make_leave", cfg.Matrix.ServerName, cfg.Matrix.IsLocalServerName, keys, wakeup, "federation_make_leave", cfg.Matrix.ServerName, cfg.Matrix.IsLocalServerName, keys, wakeup,
func(httpReq *http.Request, request *fclient.FederationRequest, vars map[string]string) util.JSONResponse { func(httpReq *http.Request, request *fclient.FederationRequest, vars map[string]string) util.JSONResponse {
if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) { if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) {
@ -421,10 +421,22 @@ func Setup(
JSON: spec.Forbidden("Forbidden by server ACLs"), JSON: spec.Forbidden("Forbidden by server ACLs"),
} }
} }
roomID := vars["roomID"] roomID, err := spec.NewRoomID(vars["roomID"])
eventID := vars["eventID"] if err != nil {
return util.JSONResponse{
Code: http.StatusBadRequest,
JSON: spec.InvalidParam("Invalid RoomID"),
}
}
userID, err := spec.NewUserID(vars["userID"], true)
if err != nil {
return util.JSONResponse{
Code: http.StatusBadRequest,
JSON: spec.InvalidParam("Invalid UserID"),
}
}
return MakeLeave( return MakeLeave(
httpReq, request, cfg, rsAPI, roomID, eventID, httpReq, request, cfg, rsAPI, *roomID, *userID,
) )
}, },
)).Methods(http.MethodGet) )).Methods(http.MethodGet)

2
go.mod
View File

@ -22,7 +22,7 @@ require (
github.com/matrix-org/dugong v0.0.0-20210921133753-66e6b1c67e2e github.com/matrix-org/dugong v0.0.0-20210921133753-66e6b1c67e2e
github.com/matrix-org/go-sqlite3-js v0.0.0-20220419092513-28aa791a1c91 github.com/matrix-org/go-sqlite3-js v0.0.0-20220419092513-28aa791a1c91
github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530 github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530
github.com/matrix-org/gomatrixserverlib v0.0.0-20230519160810-b92e84b02a7c github.com/matrix-org/gomatrixserverlib v0.0.0-20230523164045-3fddabebb511
github.com/matrix-org/pinecone v0.11.1-0.20230210171230-8c3b24f2649a github.com/matrix-org/pinecone v0.11.1-0.20230210171230-8c3b24f2649a
github.com/matrix-org/util v0.0.0-20221111132719-399730281e66 github.com/matrix-org/util v0.0.0-20221111132719-399730281e66
github.com/mattn/go-sqlite3 v1.14.16 github.com/mattn/go-sqlite3 v1.14.16

4
go.sum
View File

@ -323,8 +323,8 @@ github.com/matrix-org/go-sqlite3-js v0.0.0-20220419092513-28aa791a1c91 h1:s7fexw
github.com/matrix-org/go-sqlite3-js v0.0.0-20220419092513-28aa791a1c91/go.mod h1:e+cg2q7C7yE5QnAXgzo512tgFh1RbQLC0+jozuegKgo= github.com/matrix-org/go-sqlite3-js v0.0.0-20220419092513-28aa791a1c91/go.mod h1:e+cg2q7C7yE5QnAXgzo512tgFh1RbQLC0+jozuegKgo=
github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530 h1:kHKxCOLcHH8r4Fzarl4+Y3K5hjothkVW5z7T1dUM11U= github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530 h1:kHKxCOLcHH8r4Fzarl4+Y3K5hjothkVW5z7T1dUM11U=
github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530/go.mod h1:/gBX06Kw0exX1HrwmoBibFA98yBk/jxKpGVeyQbff+s= github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530/go.mod h1:/gBX06Kw0exX1HrwmoBibFA98yBk/jxKpGVeyQbff+s=
github.com/matrix-org/gomatrixserverlib v0.0.0-20230519160810-b92e84b02a7c h1:EF04pmshcDmBQOrBQbzT5htyTivetfyvR70gX2hB9AM= github.com/matrix-org/gomatrixserverlib v0.0.0-20230523164045-3fddabebb511 h1:om6z/WEVZMxZfgtiyfp5r5ubAObGMyRrnlVD07gIRY4=
github.com/matrix-org/gomatrixserverlib v0.0.0-20230519160810-b92e84b02a7c/go.mod h1:H9V9N3Uqn1bBJqYJNGK1noqtgJTaCEhtTdcH/mp50uU= github.com/matrix-org/gomatrixserverlib v0.0.0-20230523164045-3fddabebb511/go.mod h1:H9V9N3Uqn1bBJqYJNGK1noqtgJTaCEhtTdcH/mp50uU=
github.com/matrix-org/pinecone v0.11.1-0.20230210171230-8c3b24f2649a h1:awrPDf9LEFySxTLKYBMCiObelNx/cBuv/wzllvCCH3A= github.com/matrix-org/pinecone v0.11.1-0.20230210171230-8c3b24f2649a h1:awrPDf9LEFySxTLKYBMCiObelNx/cBuv/wzllvCCH3A=
github.com/matrix-org/pinecone v0.11.1-0.20230210171230-8c3b24f2649a/go.mod h1:HchJX9oKMXaT2xYFs0Ha/6Zs06mxLU8k6F1ODnrGkeQ= github.com/matrix-org/pinecone v0.11.1-0.20230210171230-8c3b24f2649a/go.mod h1:HchJX9oKMXaT2xYFs0Ha/6Zs06mxLU8k6F1ODnrGkeQ=
github.com/matrix-org/util v0.0.0-20221111132719-399730281e66 h1:6z4KxomXSIGWqhHcfzExgkH3Z3UkIXry4ibJS4Aqz2Y= github.com/matrix-org/util v0.0.0-20221111132719-399730281e66 h1:6z4KxomXSIGWqhHcfzExgkH3Z3UkIXry4ibJS4Aqz2Y=