Roomserver perform join (#1001)

* Add PerformJoin template

* Try roomserver perform join

* Send correct server name to FS API

* Pass through content, try to handle multiple server names

* Fix local server checks

* Don't refer to non-existent error

* Add directory lookups of aliases

* Remove unneeded parameters

* Don't repeat join events into the roomserver

* Unmarshal the content, that would help

* Check if the user is already in the room in the fedeationapi too

* Return incompatible room version error

* Use Membership, don't try more servers than needed

* Review comments, make FS API take list of servernames, dedupe them, break out of loop properly on success

* Tweaks
This commit is contained in:
Neil Alexander 2020-05-04 13:53:47 +01:00 committed by GitHub
parent 36bbb25561
commit 5c894efd0e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 506 additions and 406 deletions

View file

@ -61,9 +61,7 @@ func MakeJoin(
if !remoteSupportsVersion {
return util.JSONResponse{
Code: http.StatusBadRequest,
JSON: jsonerror.UnsupportedRoomVersion(
fmt.Sprintf("Joining server does not support room version %s", verRes.RoomVersion),
),
JSON: jsonerror.IncompatibleRoomVersion(verRes.RoomVersion),
}
}
@ -132,6 +130,9 @@ func MakeJoin(
}
// SendJoin implements the /send_join API
// The make-join send-join dance makes much more sense as a single
// flow so the cyclomatic complexity is high:
// nolint:gocyclo
func SendJoin(
httpReq *http.Request,
request *gomatrixserverlib.FederationRequest,
@ -159,6 +160,16 @@ func SendJoin(
}
}
// Check that a state key is provided.
if event.StateKey() == nil || (event.StateKey() != nil && *event.StateKey() == "") {
return util.JSONResponse{
Code: http.StatusBadRequest,
JSON: jsonerror.BadJSON(
fmt.Sprintf("No state key was provided in the join event."),
),
}
}
// Check that the room ID is correct.
if event.RoomID() != roomID {
return util.JSONResponse{
@ -234,20 +245,34 @@ func SendJoin(
}
}
// Check if the user is already in the room. If they're already in then
// there isn't much point in sending another join event into the room.
alreadyJoined := false
for _, se := range stateAndAuthChainResponse.StateEvents {
if membership, merr := se.Membership(); merr == nil {
if se.StateKey() != nil && *se.StateKey() == *event.StateKey() {
alreadyJoined = (membership == "join")
break
}
}
}
// Send the events to the room server.
// We are responsible for notifying other servers that the user has joined
// the room, so set SendAsServer to cfg.Matrix.ServerName
_, err = producer.SendEvents(
httpReq.Context(),
[]gomatrixserverlib.HeaderedEvent{
event.Headered(stateAndAuthChainResponse.RoomVersion),
},
cfg.Matrix.ServerName,
nil,
)
if err != nil {
util.GetLogger(httpReq.Context()).WithError(err).Error("producer.SendEvents failed")
return jsonerror.InternalServerError()
if !alreadyJoined {
_, err = producer.SendEvents(
httpReq.Context(),
[]gomatrixserverlib.HeaderedEvent{
event.Headered(stateAndAuthChainResponse.RoomVersion),
},
cfg.Matrix.ServerName,
nil,
)
if err != nil {
util.GetLogger(httpReq.Context()).WithError(err).Error("producer.SendEvents failed")
return jsonerror.InternalServerError()
}
}
return util.JSONResponse{