aboutsummaryrefslogtreecommitdiff
path: root/clientapi
diff options
context:
space:
mode:
authorNeil Alexander <neilalexander@users.noreply.github.com>2020-04-29 15:29:39 +0100
committerGitHub <noreply@github.com>2020-04-29 15:29:39 +0100
commit64e94e9a6f0a138e7fe771f540b57988bc344b59 (patch)
tree9ef06d96a4c5f0bd59ea55dad8d7f74646898894 /clientapi
parenta308e61331f549ae0964f83dff88abc282033ed3 (diff)
Join room support in federation sender (#989)
* Implement PerformJoinRequest * Rename perform functions * Check send join response * Temporary wiring to test federation sender room joins * Actually pass through the config * Make sure membership content shows join
Diffstat (limited to 'clientapi')
-rw-r--r--clientapi/routing/joinroom.go122
-rw-r--r--clientapi/routing/routing.go3
2 files changed, 13 insertions, 112 deletions
diff --git a/clientapi/routing/joinroom.go b/clientapi/routing/joinroom.go
index d0dee7c2..f55d1b6a 100644
--- a/clientapi/routing/joinroom.go
+++ b/clientapi/routing/joinroom.go
@@ -27,12 +27,11 @@ import (
"github.com/matrix-org/dendrite/clientapi/producers"
"github.com/matrix-org/dendrite/common"
"github.com/matrix-org/dendrite/common/config"
- "github.com/matrix-org/dendrite/roomserver/api"
+ federationSenderAPI "github.com/matrix-org/dendrite/federationsender/api"
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
"github.com/matrix-org/gomatrix"
"github.com/matrix-org/gomatrixserverlib"
"github.com/matrix-org/util"
- "github.com/sirupsen/logrus"
)
// JoinRoomByIDOrAlias implements the "/join/{roomIDOrAlias}" API.
@@ -46,6 +45,7 @@ func JoinRoomByIDOrAlias(
producer *producers.RoomserverProducer,
queryAPI roomserverAPI.RoomserverQueryAPI,
aliasAPI roomserverAPI.RoomserverAliasAPI,
+ fsAPI federationSenderAPI.FederationSenderInternalAPI,
keyRing gomatrixserverlib.KeyRing,
accountDB accounts.Database,
) util.JSONResponse {
@@ -79,7 +79,8 @@ func JoinRoomByIDOrAlias(
content["avatar_url"] = profile.AvatarURL
r := joinRoomReq{
- req, evTime, content, device.UserID, cfg, federation, producer, queryAPI, aliasAPI, keyRing,
+ req, evTime, content, device.UserID, cfg, federation, producer,
+ queryAPI, aliasAPI, fsAPI, keyRing,
}
if strings.HasPrefix(roomIDOrAlias, "!") {
@@ -107,6 +108,7 @@ type joinRoomReq struct {
producer *producers.RoomserverProducer
queryAPI roomserverAPI.RoomserverQueryAPI
aliasAPI roomserverAPI.RoomserverAliasAPI
+ fsAPI federationSenderAPI.FederationSenderInternalAPI
keyRing gomatrixserverlib.KeyRing
}
@@ -326,72 +328,16 @@ func (r joinRoomReq) joinRoomUsingServers(
// server was invalid this returns an error.
// Otherwise this returns a JSONResponse.
func (r joinRoomReq) joinRoomUsingServer(roomID string, server gomatrixserverlib.ServerName) (*util.JSONResponse, error) {
- // Ask the room server for information about room versions.
- var request api.QueryRoomVersionCapabilitiesRequest
- var response api.QueryRoomVersionCapabilitiesResponse
- if err := r.queryAPI.QueryRoomVersionCapabilities(r.req.Context(), &request, &response); err != nil {
- return nil, err
- }
- var supportedVersions []gomatrixserverlib.RoomVersion
- for version := range response.AvailableRoomVersions {
- supportedVersions = append(supportedVersions, version)
- }
- respMakeJoin, err := r.federation.MakeJoin(r.req.Context(), server, roomID, r.userID, supportedVersions)
- if err != nil {
- // TODO: Check if the user was not allowed to join the room.
- return nil, fmt.Errorf("r.federation.MakeJoin: %w", err)
- }
-
- // Set all the fields to be what they should be, this should be a no-op
- // but it's possible that the remote server returned us something "odd"
- err = r.writeToBuilder(&respMakeJoin.JoinEvent, roomID)
- if err != nil {
- return nil, fmt.Errorf("r.writeToBuilder: %w", err)
- }
-
- if respMakeJoin.RoomVersion == "" {
- respMakeJoin.RoomVersion = gomatrixserverlib.RoomVersionV1
- }
- if _, err = respMakeJoin.RoomVersion.EventFormat(); err != nil {
- return &util.JSONResponse{
- Code: http.StatusBadRequest,
- JSON: jsonerror.UnsupportedRoomVersion(
- fmt.Sprintf("Room version '%s' is not supported", respMakeJoin.RoomVersion),
- ),
- }, nil
- }
-
- event, err := respMakeJoin.JoinEvent.Build(
- r.evTime, r.cfg.Matrix.ServerName, r.cfg.Matrix.KeyID,
- r.cfg.Matrix.PrivateKey, respMakeJoin.RoomVersion,
- )
- if err != nil {
- return nil, fmt.Errorf("respMakeJoin.JoinEvent.Build: %w", err)
+ fedJoinReq := federationSenderAPI.PerformJoinRequest{
+ RoomID: roomID,
+ UserID: r.userID,
+ ServerName: server,
}
-
- respSendJoin, err := r.federation.SendJoin(r.req.Context(), server, event, respMakeJoin.RoomVersion)
- if err != nil {
- return nil, fmt.Errorf("r.federation.SendJoin: %w", err)
- }
-
- if err = r.checkSendJoinResponse(event, server, respMakeJoin, respSendJoin); err != nil {
+ fedJoinRes := federationSenderAPI.PerformJoinResponse{}
+ if err := r.fsAPI.PerformJoin(r.req.Context(), &fedJoinReq, &fedJoinRes); err != nil {
return nil, err
}
- util.GetLogger(r.req.Context()).WithFields(logrus.Fields{
- "room_id": roomID,
- "num_auth_events": len(respSendJoin.AuthEvents),
- "num_state_events": len(respSendJoin.StateEvents),
- }).Info("Room join signature and auth verification passed")
-
- if err = r.producer.SendEventWithState(
- r.req.Context(),
- respSendJoin.ToRespState(),
- event.Headered(respMakeJoin.RoomVersion),
- ); err != nil {
- util.GetLogger(r.req.Context()).WithError(err).Error("r.producer.SendEventWithState")
- }
-
return &util.JSONResponse{
Code: http.StatusOK,
// TODO: Put the response struct somewhere common.
@@ -400,49 +346,3 @@ func (r joinRoomReq) joinRoomUsingServer(roomID string, server gomatrixserverlib
}{roomID},
}, nil
}
-
-// checkSendJoinResponse checks that all of the signatures are correct
-// and that the join is allowed by the supplied state.
-func (r joinRoomReq) checkSendJoinResponse(
- event gomatrixserverlib.Event,
- server gomatrixserverlib.ServerName,
- respMakeJoin gomatrixserverlib.RespMakeJoin,
- respSendJoin gomatrixserverlib.RespSendJoin,
-) error {
- // A list of events that we have retried, if they were not included in
- // the auth events supplied in the send_join.
- retries := map[string]bool{}
-
-retryCheck:
- // TODO: Can we expand Check here to return a list of missing auth
- // events rather than failing one at a time?
- if err := respSendJoin.Check(r.req.Context(), r.keyRing, event); err != nil {
- switch e := err.(type) {
- case gomatrixserverlib.MissingAuthEventError:
- // Check that we haven't already retried for this event, prevents
- // us from ending up in endless loops
- if !retries[e.AuthEventID] {
- // Ask the server that we're talking to right now for the event
- tx, txerr := r.federation.GetEvent(r.req.Context(), server, e.AuthEventID)
- if txerr != nil {
- return fmt.Errorf("r.federation.GetEvent: %w", txerr)
- }
- // For each event returned, add it to the auth events.
- for _, pdu := range tx.PDUs {
- ev, everr := gomatrixserverlib.NewEventFromUntrustedJSON(pdu, respMakeJoin.RoomVersion)
- if everr != nil {
- return fmt.Errorf("gomatrixserverlib.NewEventFromUntrustedJSON: %w", everr)
- }
- respSendJoin.AuthEvents = append(respSendJoin.AuthEvents, ev)
- }
- // Mark the event as retried and then give the check another go.
- retries[e.AuthEventID] = true
- goto retryCheck
- }
- return fmt.Errorf("respSendJoin (after retries): %w", e)
- default:
- return fmt.Errorf("respSendJoin: %w", err)
- }
- }
- return nil
-}
diff --git a/clientapi/routing/routing.go b/clientapi/routing/routing.go
index 9ab22cbe..e62b5193 100644
--- a/clientapi/routing/routing.go
+++ b/clientapi/routing/routing.go
@@ -101,7 +101,8 @@ func Setup(
return util.ErrorResponse(err)
}
return JoinRoomByIDOrAlias(
- req, device, vars["roomIDOrAlias"], cfg, federation, producer, queryAPI, aliasAPI, keyRing, accountDB,
+ req, device, vars["roomIDOrAlias"], cfg, federation, producer,
+ queryAPI, aliasAPI, federationSender, keyRing, accountDB,
)
}),
).Methods(http.MethodPost, http.MethodOptions)