mirror of
https://github.com/matrix-org/dendrite.git
synced 2025-12-11 17:03:10 -06:00
Merge branch 'master' into markjh/context
This commit is contained in:
commit
094c8d80af
|
|
@ -86,6 +86,8 @@ func (c *RoomserverProducer) SendInputRoomEvents(ires []api.InputRoomEvent) erro
|
|||
}
|
||||
|
||||
// SendInvite writes the invite event to the roomserver input API.
|
||||
// This should only be needed for invite events that occur outside of a known room.
|
||||
// If we are in the room then the event should be sent using the SendEvents method.
|
||||
func (c *RoomserverProducer) SendInvite(inviteEvent gomatrixserverlib.Event) error {
|
||||
request := api.InputRoomEventsRequest{
|
||||
InputInviteEvents: []api.InputInviteEvent{{Event: inviteEvent}},
|
||||
|
|
|
|||
|
|
@ -254,6 +254,7 @@ func queryIDServerStoreInvite(
|
|||
|
||||
// queryIDServerPubKey requests a public key identified with a given ID to the
|
||||
// a given identity server and returns the matching base64-decoded public key.
|
||||
// We assume that the ID server is trusted at this point.
|
||||
// Returns an error if the request couldn't be sent, if its body couldn't be parsed
|
||||
// or if the key couldn't be decoded from base64.
|
||||
func queryIDServerPubKey(idServerName string, keyID string) ([]byte, error) {
|
||||
|
|
@ -280,6 +281,7 @@ func queryIDServerPubKey(idServerName string, keyID string) ([]byte, error) {
|
|||
// If no signature can be found for the ID server's domain, returns an error, else
|
||||
// iterates over the signature for the said domain, retrieves the matching public
|
||||
// key, and verify it.
|
||||
// We assume that the ID server is trusted at this point.
|
||||
// Returns nil if all the verifications succeeded.
|
||||
// Returns an error if something failed in the process.
|
||||
func checkIDServerSignatures(body *MembershipRequest, res *idServerLookupResponse) error {
|
||||
|
|
|
|||
|
|
@ -85,6 +85,16 @@ func Setup(
|
|||
},
|
||||
))
|
||||
|
||||
v1fedmux.Handle("/exchange_third_party_invite/{roomID}", common.MakeFedAPI(
|
||||
"exchange_third_party_invite", cfg.Matrix.ServerName, keys,
|
||||
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest) util.JSONResponse {
|
||||
vars := mux.Vars(httpReq)
|
||||
return writers.ExchangeThirdPartyInvite(
|
||||
httpReq, request, vars["roomID"], query, cfg, federation, producer,
|
||||
)
|
||||
},
|
||||
))
|
||||
|
||||
v1fedmux.Handle("/event/{eventID}", common.MakeFedAPI(
|
||||
"federation_get_event", cfg.Matrix.ServerName, keys,
|
||||
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest) util.JSONResponse {
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/httputil"
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/clientapi/producers"
|
||||
"github.com/matrix-org/dendrite/common"
|
||||
"github.com/matrix-org/dendrite/common/config"
|
||||
|
|
@ -49,6 +50,8 @@ type invites struct {
|
|||
Invites []invite `json:"invites"`
|
||||
}
|
||||
|
||||
var errNotInRoom = errors.New("the server isn't currently in the room")
|
||||
|
||||
// CreateInvitesFrom3PIDInvites implements POST /_matrix/federation/v1/3pid/onbind
|
||||
func CreateInvitesFrom3PIDInvites(
|
||||
req *http.Request, queryAPI api.RoomserverQueryAPI, cfg config.Dendrite,
|
||||
|
|
@ -83,6 +86,78 @@ func CreateInvitesFrom3PIDInvites(
|
|||
}
|
||||
}
|
||||
|
||||
// ExchangeThirdPartyInvite implements PUT /_matrix/federation/v1/exchange_third_party_invite/{roomID}
|
||||
func ExchangeThirdPartyInvite(
|
||||
httpReq *http.Request,
|
||||
request *gomatrixserverlib.FederationRequest,
|
||||
roomID string,
|
||||
queryAPI api.RoomserverQueryAPI,
|
||||
cfg config.Dendrite,
|
||||
federation *gomatrixserverlib.FederationClient,
|
||||
producer *producers.RoomserverProducer,
|
||||
) util.JSONResponse {
|
||||
var builder gomatrixserverlib.EventBuilder
|
||||
if err := json.Unmarshal(request.Content(), &builder); err != nil {
|
||||
return util.JSONResponse{
|
||||
Code: 400,
|
||||
JSON: jsonerror.NotJSON("The request body could not be decoded into valid JSON. " + err.Error()),
|
||||
}
|
||||
}
|
||||
|
||||
// Check that the room ID is correct.
|
||||
if builder.RoomID != roomID {
|
||||
return util.JSONResponse{
|
||||
Code: 400,
|
||||
JSON: jsonerror.BadJSON("The room ID in the request path must match the room ID in the invite event JSON"),
|
||||
}
|
||||
}
|
||||
|
||||
// Check that the state key is correct.
|
||||
_, targetDomain, err := gomatrixserverlib.SplitID('@', *builder.StateKey)
|
||||
if err != nil {
|
||||
return util.JSONResponse{
|
||||
Code: 400,
|
||||
JSON: jsonerror.BadJSON("The event's state key isn't a Matrix user ID"),
|
||||
}
|
||||
}
|
||||
|
||||
// Check that the target user is from the requesting homeserver.
|
||||
if targetDomain != request.Origin() {
|
||||
return util.JSONResponse{
|
||||
Code: 400,
|
||||
JSON: jsonerror.BadJSON("The event's state key doesn't have the same domain as the request's origin"),
|
||||
}
|
||||
}
|
||||
|
||||
// Auth and build the event from what the remote server sent us
|
||||
event, err := buildMembershipEvent(&builder, queryAPI, cfg)
|
||||
if err == errNotInRoom {
|
||||
return util.JSONResponse{
|
||||
Code: 404,
|
||||
JSON: jsonerror.NotFound("Unknown room " + roomID),
|
||||
}
|
||||
} else if err != nil {
|
||||
return httputil.LogThenError(httpReq, err)
|
||||
}
|
||||
|
||||
// Ask the requesting server to sign the newly created event so we know it
|
||||
// acknowledged it
|
||||
signedEvent, err := federation.SendInvite(httpReq.Context(), request.Origin(), *event)
|
||||
if err != nil {
|
||||
return httputil.LogThenError(httpReq, err)
|
||||
}
|
||||
|
||||
// Send the event to the roomserver
|
||||
if err = producer.SendEvents([]gomatrixserverlib.Event{signedEvent.Event}, cfg.Matrix.ServerName); err != nil {
|
||||
return httputil.LogThenError(httpReq, err)
|
||||
}
|
||||
|
||||
return util.JSONResponse{
|
||||
Code: 200,
|
||||
JSON: struct{}{},
|
||||
}
|
||||
}
|
||||
|
||||
// createInviteFrom3PIDInvite processes an invite provided by the identity server
|
||||
// and creates a m.room.member event (with "invite" membership) from it.
|
||||
// Returns an error if there was a problem building the event or fetching the
|
||||
|
|
@ -111,6 +186,26 @@ func createInviteFrom3PIDInvite(
|
|||
return nil, err
|
||||
}
|
||||
|
||||
event, err := buildMembershipEvent(builder, queryAPI, cfg)
|
||||
if err == errNotInRoom {
|
||||
return nil, sendToRemoteServer(ctx, inv, federation, cfg, *builder)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return event, nil
|
||||
}
|
||||
|
||||
// buildMembershipEvent uses a builder for a m.room.member invite event derived
|
||||
// from a third-party invite to auth and build the said event. Returns the said
|
||||
// event.
|
||||
// Returns errNotInRoom if the server is not in the room the invite is for.
|
||||
// Returns an error if something failed during the process.
|
||||
func buildMembershipEvent(
|
||||
builder *gomatrixserverlib.EventBuilder, queryAPI api.RoomserverQueryAPI,
|
||||
cfg config.Dendrite,
|
||||
) (*gomatrixserverlib.Event, error) {
|
||||
eventsNeeded, err := gomatrixserverlib.StateNeededForEventBuilder(builder)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -128,7 +223,7 @@ func createInviteFrom3PIDInvite(
|
|||
|
||||
if !queryRes.RoomExists {
|
||||
// Use federation to auth the event
|
||||
return nil, sendToRemoteServer(ctx, inv, federation, cfg, *builder)
|
||||
return nil, errNotInRoom
|
||||
}
|
||||
|
||||
// Auth the event locally
|
||||
|
|
@ -141,7 +236,7 @@ func createInviteFrom3PIDInvite(
|
|||
authEvents.AddEvent(&queryRes.StateEvents[i])
|
||||
}
|
||||
|
||||
if err = fillDisplayName(builder, content, authEvents); err != nil {
|
||||
if err = fillDisplayName(builder, authEvents); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
|
@ -154,11 +249,8 @@ func createInviteFrom3PIDInvite(
|
|||
eventID := fmt.Sprintf("$%s:%s", util.RandomString(16), cfg.Matrix.ServerName)
|
||||
now := time.Now()
|
||||
event, err := builder.Build(eventID, now, cfg.Matrix.ServerName, cfg.Matrix.KeyID, cfg.Matrix.PrivateKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &event, nil
|
||||
return &event, err
|
||||
}
|
||||
|
||||
// sendToRemoteServer uses federation to send an invite provided by an identity
|
||||
|
|
@ -205,9 +297,13 @@ func sendToRemoteServer(
|
|||
// found. Returning an error isn't necessary in this case as the event will be
|
||||
// rejected by gomatrixserverlib.
|
||||
func fillDisplayName(
|
||||
builder *gomatrixserverlib.EventBuilder, content common.MemberContent,
|
||||
authEvents gomatrixserverlib.AuthEvents,
|
||||
builder *gomatrixserverlib.EventBuilder, authEvents gomatrixserverlib.AuthEvents,
|
||||
) error {
|
||||
var content common.MemberContent
|
||||
if err := json.Unmarshal(builder.Content, &content); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Look for the m.room.third_party_invite event
|
||||
thirdPartyInviteEvent, _ := authEvents.ThirdPartyInvite(content.ThirdPartyInvite.Signed.Token)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue