mirror of
https://github.com/matrix-org/dendrite.git
synced 2026-01-11 08:03:09 -06:00
Add pseudoID compatibility to invites
This commit is contained in:
parent
0e1b81bb4e
commit
909a1a5e1f
|
|
@ -338,22 +338,54 @@ func sendInvite(
|
||||||
rsAPI roomserverAPI.ClientRoomserverAPI,
|
rsAPI roomserverAPI.ClientRoomserverAPI,
|
||||||
asAPI appserviceAPI.AppServiceInternalAPI, evTime time.Time,
|
asAPI appserviceAPI.AppServiceInternalAPI, evTime time.Time,
|
||||||
) (util.JSONResponse, error) {
|
) (util.JSONResponse, error) {
|
||||||
event, err := buildMembershipEvent(
|
validRoomID, err := spec.NewRoomID(roomID)
|
||||||
ctx, userID, reason, profileAPI, device, spec.Invite,
|
if err != nil {
|
||||||
roomID, false, cfg, evTime, rsAPI, asAPI,
|
return util.JSONResponse{
|
||||||
)
|
Code: http.StatusBadRequest,
|
||||||
|
JSON: spec.InvalidParam("RoomID is invalid"),
|
||||||
|
}, err
|
||||||
|
}
|
||||||
|
inviter, err := spec.NewUserID(device.UserID, true)
|
||||||
|
if err != nil {
|
||||||
|
return util.JSONResponse{
|
||||||
|
Code: http.StatusInternalServerError,
|
||||||
|
JSON: spec.InternalServerError{},
|
||||||
|
}, err
|
||||||
|
}
|
||||||
|
invitee, err := spec.NewUserID(userID, true)
|
||||||
|
if err != nil {
|
||||||
|
return util.JSONResponse{
|
||||||
|
Code: http.StatusBadRequest,
|
||||||
|
JSON: spec.InvalidParam("UserID is invalid"),
|
||||||
|
}, err
|
||||||
|
}
|
||||||
|
profile, err := loadProfile(ctx, userID, cfg, profileAPI, asAPI)
|
||||||
|
if err != nil {
|
||||||
|
return util.JSONResponse{
|
||||||
|
Code: http.StatusInternalServerError,
|
||||||
|
JSON: spec.InternalServerError{},
|
||||||
|
}, err
|
||||||
|
}
|
||||||
|
identity, err := cfg.Matrix.SigningIdentityFor(device.UserDomain())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
util.GetLogger(ctx).WithError(err).Error("buildMembershipEvent failed")
|
|
||||||
return util.JSONResponse{
|
return util.JSONResponse{
|
||||||
Code: http.StatusInternalServerError,
|
Code: http.StatusInternalServerError,
|
||||||
JSON: spec.InternalServerError{},
|
JSON: spec.InternalServerError{},
|
||||||
}, err
|
}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = rsAPI.PerformInvite(ctx, &api.PerformInviteRequest{
|
err = rsAPI.PerformInvite(ctx, &api.PerformInviteRequest{
|
||||||
Event: event,
|
InviteInput: roomserverAPI.InviteInput{
|
||||||
|
RoomID: *validRoomID,
|
||||||
|
Inviter: *inviter,
|
||||||
|
Invitee: *invitee,
|
||||||
|
DisplayName: profile.DisplayName,
|
||||||
|
AvatarURL: profile.AvatarURL,
|
||||||
|
Reason: reason,
|
||||||
|
IsDirect: false,
|
||||||
|
KeyID: identity.KeyID,
|
||||||
|
PrivateKey: identity.PrivateKey,
|
||||||
|
},
|
||||||
InviteRoomState: nil, // ask the roomserver to draw up invite room state for us
|
InviteRoomState: nil, // ask the roomserver to draw up invite room state for us
|
||||||
RoomVersion: event.Version(),
|
|
||||||
SendAsServer: string(device.UserDomain()),
|
SendAsServer: string(device.UserDomain()),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,8 @@ type RoomserverFederationAPI interface {
|
||||||
PerformLeave(ctx context.Context, request *PerformLeaveRequest, response *PerformLeaveResponse) error
|
PerformLeave(ctx context.Context, request *PerformLeaveRequest, response *PerformLeaveResponse) error
|
||||||
// Handle sending an invite to a remote server.
|
// Handle sending an invite to a remote server.
|
||||||
SendInvite(ctx context.Context, event gomatrixserverlib.PDU, strippedState []gomatrixserverlib.InviteStrippedState) (gomatrixserverlib.PDU, error)
|
SendInvite(ctx context.Context, event gomatrixserverlib.PDU, strippedState []gomatrixserverlib.InviteStrippedState) (gomatrixserverlib.PDU, error)
|
||||||
|
// Handle sending an invite to a remote server.
|
||||||
|
SendInviteV3(ctx context.Context, event gomatrixserverlib.ProtoEvent, invitee spec.UserID, version gomatrixserverlib.RoomVersion, strippedState []gomatrixserverlib.InviteStrippedState) (gomatrixserverlib.PDU, error)
|
||||||
// Handle an instruction to peek a room on a remote server.
|
// Handle an instruction to peek a room on a remote server.
|
||||||
PerformOutboundPeek(ctx context.Context, request *PerformOutboundPeekRequest, response *PerformOutboundPeekResponse) error
|
PerformOutboundPeek(ctx context.Context, request *PerformOutboundPeekRequest, response *PerformOutboundPeekResponse) error
|
||||||
// Query the server names of the joined hosts in a room.
|
// Query the server names of the joined hosts in a room.
|
||||||
|
|
|
||||||
|
|
@ -587,6 +587,61 @@ func (r *FederationInternalAPI) SendInvite(
|
||||||
return inviteEvent, nil
|
return inviteEvent, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SendInviteV3 implements api.FederationInternalAPI
|
||||||
|
func (r *FederationInternalAPI) SendInviteV3(
|
||||||
|
ctx context.Context,
|
||||||
|
event gomatrixserverlib.ProtoEvent,
|
||||||
|
invitee spec.UserID,
|
||||||
|
version gomatrixserverlib.RoomVersion,
|
||||||
|
strippedState []gomatrixserverlib.InviteStrippedState,
|
||||||
|
) (gomatrixserverlib.PDU, error) {
|
||||||
|
validRoomID, err := spec.NewRoomID(event.RoomID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
inviter, err := r.rsAPI.QueryUserIDForSender(ctx, *validRoomID, spec.SenderID(event.SenderID))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if event.StateKey == nil {
|
||||||
|
return nil, errors.New("invite must be a state event")
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO (devon): This should be allowed via a relay. Currently only transactions
|
||||||
|
// can be sent to relays. Would need to extend relays to handle invites.
|
||||||
|
if !r.shouldAttemptDirectFederation(invitee.Domain()) {
|
||||||
|
return nil, fmt.Errorf("relay servers have no meaningful response for invite.")
|
||||||
|
}
|
||||||
|
|
||||||
|
logrus.WithFields(logrus.Fields{
|
||||||
|
"user_id": *event.StateKey,
|
||||||
|
"room_id": event.RoomID,
|
||||||
|
"room_version": version,
|
||||||
|
"destination": invitee.Domain(),
|
||||||
|
}).Info("Sending invite")
|
||||||
|
|
||||||
|
inviteReq, err := fclient.NewInviteV3Request(event, version, strippedState)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("gomatrixserverlib.NewInviteV3Request: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
inviteRes, err := r.federation.SendInviteV3(ctx, inviter.Domain(), invitee.Domain(), inviteReq, invitee)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("r.federation.SendInviteV3: failed to send invite: %w", err)
|
||||||
|
}
|
||||||
|
verImpl, err := gomatrixserverlib.GetRoomVersion(version)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
inviteEvent, err := verImpl.NewEventFromUntrustedJSON(inviteRes.Event)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("r.federation.SendInviteV3 failed to decode event response: %w", err)
|
||||||
|
}
|
||||||
|
return inviteEvent, nil
|
||||||
|
}
|
||||||
|
|
||||||
// PerformServersAlive implements api.FederationInternalAPI
|
// PerformServersAlive implements api.FederationInternalAPI
|
||||||
func (r *FederationInternalAPI) PerformBroadcastEDU(
|
func (r *FederationInternalAPI) PerformBroadcastEDU(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ package routing
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"crypto/ed25519"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
@ -29,6 +30,91 @@ import (
|
||||||
"github.com/matrix-org/util"
|
"github.com/matrix-org/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// InviteV3 implements /_matrix/federation/v2/invite/{roomID}/{userID}
|
||||||
|
func InviteV3(
|
||||||
|
httpReq *http.Request,
|
||||||
|
request *fclient.FederationRequest,
|
||||||
|
roomID spec.RoomID,
|
||||||
|
invitedUser spec.UserID,
|
||||||
|
cfg *config.FederationAPI,
|
||||||
|
rsAPI api.FederationRoomserverAPI,
|
||||||
|
keys gomatrixserverlib.JSONVerifier,
|
||||||
|
) util.JSONResponse {
|
||||||
|
inviteReq := fclient.InviteV3Request{}
|
||||||
|
err := json.Unmarshal(request.Content(), &inviteReq)
|
||||||
|
switch e := err.(type) {
|
||||||
|
case gomatrixserverlib.UnsupportedRoomVersionError:
|
||||||
|
return util.JSONResponse{
|
||||||
|
Code: http.StatusBadRequest,
|
||||||
|
JSON: spec.UnsupportedRoomVersion(
|
||||||
|
fmt.Sprintf("Room version %q is not supported by this server.", e.Version),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
case gomatrixserverlib.BadJSONError:
|
||||||
|
return util.JSONResponse{
|
||||||
|
Code: http.StatusBadRequest,
|
||||||
|
JSON: spec.BadJSON(err.Error()),
|
||||||
|
}
|
||||||
|
case nil:
|
||||||
|
if !cfg.Matrix.IsLocalServerName(invitedUser.Domain()) {
|
||||||
|
return util.JSONResponse{
|
||||||
|
Code: http.StatusBadRequest,
|
||||||
|
JSON: spec.InvalidParam("The invited user domain does not belong to this server"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
input := gomatrixserverlib.HandleInviteV3Input{
|
||||||
|
HandleInviteInput: gomatrixserverlib.HandleInviteInput{
|
||||||
|
RoomVersion: inviteReq.RoomVersion(),
|
||||||
|
RoomID: roomID,
|
||||||
|
InvitedUser: invitedUser,
|
||||||
|
KeyID: cfg.Matrix.KeyID,
|
||||||
|
PrivateKey: cfg.Matrix.PrivateKey,
|
||||||
|
Verifier: keys,
|
||||||
|
RoomQuerier: rsAPI,
|
||||||
|
MembershipQuerier: &api.MembershipQuerier{Roomserver: rsAPI},
|
||||||
|
StateQuerier: rsAPI.StateQuerier(),
|
||||||
|
InviteEvent: nil,
|
||||||
|
StrippedState: inviteReq.InviteRoomState(),
|
||||||
|
UserIDQuerier: func(roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID, error) {
|
||||||
|
return rsAPI.QueryUserIDForSender(httpReq.Context(), roomID, senderID)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Origin: request.Origin(),
|
||||||
|
InviteProtoEvent: inviteReq.Event(),
|
||||||
|
SenderIDQuerier: func(roomID spec.RoomID, userID spec.UserID) (spec.SenderID, error) {
|
||||||
|
return rsAPI.QuerySenderIDForUser(httpReq.Context(), roomID, userID)
|
||||||
|
},
|
||||||
|
SenderIDCreator: func(ctx context.Context, userID spec.UserID, roomID spec.RoomID, roomVersion string) (spec.SenderID, ed25519.PrivateKey, error) {
|
||||||
|
// assign a roomNID, otherwise we can't create a private key for the user
|
||||||
|
_, nidErr := rsAPI.AssignRoomNID(ctx, roomID, gomatrixserverlib.RoomVersion(roomVersion))
|
||||||
|
if nidErr != nil {
|
||||||
|
return "", nil, nidErr
|
||||||
|
}
|
||||||
|
key, keyErr := rsAPI.GetOrCreateUserRoomPrivateKey(ctx, userID, roomID)
|
||||||
|
if keyErr != nil {
|
||||||
|
return "", nil, keyErr
|
||||||
|
}
|
||||||
|
|
||||||
|
return spec.SenderIDFromPseudoIDKey(key), key, nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
event, jsonErr := handleInviteV3(httpReq.Context(), input, rsAPI)
|
||||||
|
if jsonErr != nil {
|
||||||
|
return *jsonErr
|
||||||
|
}
|
||||||
|
return util.JSONResponse{
|
||||||
|
Code: http.StatusOK,
|
||||||
|
JSON: fclient.RespInviteV2{Event: event.JSON()},
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return util.JSONResponse{
|
||||||
|
Code: http.StatusBadRequest,
|
||||||
|
JSON: spec.NotJSON("The request body could not be decoded into an invite request. " + err.Error()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// InviteV2 implements /_matrix/federation/v2/invite/{roomID}/{eventID}
|
// InviteV2 implements /_matrix/federation/v2/invite/{roomID}/{eventID}
|
||||||
func InviteV2(
|
func InviteV2(
|
||||||
httpReq *http.Request,
|
httpReq *http.Request,
|
||||||
|
|
@ -204,6 +290,15 @@ func InviteV1(
|
||||||
|
|
||||||
func handleInvite(ctx context.Context, input gomatrixserverlib.HandleInviteInput, rsAPI api.FederationRoomserverAPI) (gomatrixserverlib.PDU, *util.JSONResponse) {
|
func handleInvite(ctx context.Context, input gomatrixserverlib.HandleInviteInput, rsAPI api.FederationRoomserverAPI) (gomatrixserverlib.PDU, *util.JSONResponse) {
|
||||||
inviteEvent, err := gomatrixserverlib.HandleInvite(ctx, input)
|
inviteEvent, err := gomatrixserverlib.HandleInvite(ctx, input)
|
||||||
|
return handleInviteResult(ctx, inviteEvent, err, rsAPI)
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleInviteV3(ctx context.Context, input gomatrixserverlib.HandleInviteV3Input, rsAPI api.FederationRoomserverAPI) (gomatrixserverlib.PDU, *util.JSONResponse) {
|
||||||
|
inviteEvent, err := gomatrixserverlib.HandleInviteV3(ctx, input)
|
||||||
|
return handleInviteResult(ctx, inviteEvent, err, rsAPI)
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleInviteResult(ctx context.Context, inviteEvent gomatrixserverlib.PDU, err error, rsAPI api.FederationRoomserverAPI) (gomatrixserverlib.PDU, *util.JSONResponse) {
|
||||||
switch e := err.(type) {
|
switch e := err.(type) {
|
||||||
case nil:
|
case nil:
|
||||||
case spec.InternalServerError:
|
case spec.InternalServerError:
|
||||||
|
|
@ -245,30 +340,5 @@ func handleInvite(ctx context.Context, input gomatrixserverlib.HandleInviteInput
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return inviteEvent, nil
|
return inviteEvent, nil
|
||||||
}
|
|
||||||
|
|
||||||
// MakeInvite implements /_matrix/federation/v2/make_invite/{roomID}/{userID}
|
|
||||||
func MakeInvite(
|
|
||||||
httpReq *http.Request,
|
|
||||||
request *fclient.FederationRequest,
|
|
||||||
roomID spec.RoomID,
|
|
||||||
userID spec.UserID,
|
|
||||||
cfg *config.FederationAPI,
|
|
||||||
rsAPI api.FederationRoomserverAPI,
|
|
||||||
keys gomatrixserverlib.JSONVerifier,
|
|
||||||
) util.JSONResponse {
|
|
||||||
return util.JSONResponse{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// SendInvite implements /_matrix/federation/v2/send_invite/{roomID}/{eventID}
|
|
||||||
func SendInvite(
|
|
||||||
httpReq *http.Request,
|
|
||||||
request *fclient.FederationRequest,
|
|
||||||
roomID spec.RoomID,
|
|
||||||
eventID string,
|
|
||||||
cfg *config.FederationAPI,
|
|
||||||
rsAPI api.FederationRoomserverAPI,
|
|
||||||
keys gomatrixserverlib.JSONVerifier,
|
|
||||||
) util.JSONResponse {
|
|
||||||
return util.JSONResponse{}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -182,9 +182,6 @@ func MakeJoin(
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendJoin implements the /send_join API
|
// 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(
|
func SendJoin(
|
||||||
httpReq *http.Request,
|
httpReq *http.Request,
|
||||||
request *fclient.FederationRequest,
|
request *fclient.FederationRequest,
|
||||||
|
|
|
||||||
|
|
@ -78,6 +78,7 @@ func Setup(
|
||||||
v2keysmux := keyMux.PathPrefix("/v2").Subrouter()
|
v2keysmux := keyMux.PathPrefix("/v2").Subrouter()
|
||||||
v1fedmux := fedMux.PathPrefix("/v1").Subrouter()
|
v1fedmux := fedMux.PathPrefix("/v1").Subrouter()
|
||||||
v2fedmux := fedMux.PathPrefix("/v2").Subrouter()
|
v2fedmux := fedMux.PathPrefix("/v2").Subrouter()
|
||||||
|
v3fedmux := fedMux.PathPrefix("/v3").Subrouter()
|
||||||
|
|
||||||
wakeup := &FederationWakeups{
|
wakeup := &FederationWakeups{
|
||||||
FsAPI: fsAPI,
|
FsAPI: fsAPI,
|
||||||
|
|
@ -191,8 +192,8 @@ func Setup(
|
||||||
},
|
},
|
||||||
)).Methods(http.MethodPut, http.MethodOptions)
|
)).Methods(http.MethodPut, http.MethodOptions)
|
||||||
|
|
||||||
v2fedmux.Handle("/make_invite/{roomID}/{userID}", MakeFedAPI(
|
v3fedmux.Handle("/invite/{roomID}/{userID}", MakeFedAPI(
|
||||||
"federation_make_invite", cfg.Matrix.ServerName, cfg.Matrix.IsLocalServerName, keys, wakeup,
|
"federation_invite", 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()) {
|
||||||
return util.JSONResponse{
|
return util.JSONResponse{
|
||||||
|
|
@ -215,35 +216,11 @@ func Setup(
|
||||||
JSON: spec.InvalidParam("Invalid RoomID"),
|
JSON: spec.InvalidParam("Invalid RoomID"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return MakeInvite(
|
return InviteV3(
|
||||||
httpReq, request, *roomID, *userID,
|
httpReq, request, *roomID, *userID,
|
||||||
cfg, rsAPI, keys,
|
cfg, rsAPI, keys,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
)).Methods(http.MethodGet, http.MethodOptions)
|
|
||||||
|
|
||||||
v2fedmux.Handle("/send_invite/{roomID}/{eventID}", MakeFedAPI(
|
|
||||||
"federation_send_invite", cfg.Matrix.ServerName, cfg.Matrix.IsLocalServerName, keys, wakeup,
|
|
||||||
func(httpReq *http.Request, request *fclient.FederationRequest, vars map[string]string) util.JSONResponse {
|
|
||||||
if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) {
|
|
||||||
return util.JSONResponse{
|
|
||||||
Code: http.StatusForbidden,
|
|
||||||
JSON: spec.Forbidden("Forbidden by server ACLs"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
roomID, err := spec.NewRoomID(vars["roomID"])
|
|
||||||
if err != nil {
|
|
||||||
return util.JSONResponse{
|
|
||||||
Code: http.StatusBadRequest,
|
|
||||||
JSON: spec.InvalidParam("Invalid RoomID"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return SendInvite(
|
|
||||||
httpReq, request, *roomID, vars["eventID"],
|
|
||||||
cfg, rsAPI, keys,
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)).Methods(http.MethodPut, http.MethodOptions)
|
)).Methods(http.MethodPut, http.MethodOptions)
|
||||||
|
|
||||||
v1fedmux.Handle("/3pid/onbind", httputil.MakeExternalAPI("3pid_onbind",
|
v1fedmux.Handle("/3pid/onbind", httputil.MakeExternalAPI("3pid_onbind",
|
||||||
|
|
|
||||||
|
|
@ -50,9 +50,20 @@ type PerformLeaveResponse struct {
|
||||||
Message interface{} `json:"message,omitempty"`
|
Message interface{} `json:"message,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type InviteInput struct {
|
||||||
|
RoomID spec.RoomID
|
||||||
|
Inviter spec.UserID
|
||||||
|
Invitee spec.UserID
|
||||||
|
DisplayName string
|
||||||
|
AvatarURL string
|
||||||
|
Reason string
|
||||||
|
IsDirect bool
|
||||||
|
KeyID gomatrixserverlib.KeyID
|
||||||
|
PrivateKey ed25519.PrivateKey
|
||||||
|
}
|
||||||
|
|
||||||
type PerformInviteRequest struct {
|
type PerformInviteRequest struct {
|
||||||
RoomVersion gomatrixserverlib.RoomVersion `json:"room_version"`
|
InviteInput InviteInput
|
||||||
Event *types.HeaderedEvent `json:"event"`
|
|
||||||
InviteRoomState []gomatrixserverlib.InviteStrippedState `json:"invite_room_state"`
|
InviteRoomState []gomatrixserverlib.InviteStrippedState `json:"invite_room_state"`
|
||||||
SendAsServer string `json:"send_as_server"`
|
SendAsServer string `json:"send_as_server"`
|
||||||
TransactionID *TransactionID `json:"transaction_id"`
|
TransactionID *TransactionID `json:"transaction_id"`
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,6 @@ import (
|
||||||
"github.com/matrix-org/dendrite/roomserver/types"
|
"github.com/matrix-org/dendrite/roomserver/types"
|
||||||
"github.com/matrix-org/dendrite/setup/config"
|
"github.com/matrix-org/dendrite/setup/config"
|
||||||
"github.com/matrix-org/gomatrixserverlib"
|
"github.com/matrix-org/gomatrixserverlib"
|
||||||
"github.com/matrix-org/gomatrixserverlib/fclient"
|
|
||||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||||
"github.com/matrix-org/util"
|
"github.com/matrix-org/util"
|
||||||
)
|
)
|
||||||
|
|
@ -441,7 +440,6 @@ func (c *Creator) PerformCreateRoom(ctx context.Context, userID spec.UserID, roo
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process the invites.
|
// Process the invites.
|
||||||
var inviteEvent *types.HeaderedEvent
|
|
||||||
for _, invitee := range createRequest.InvitedUsers {
|
for _, invitee := range createRequest.InvitedUsers {
|
||||||
inviteeUserID, userIDErr := spec.NewUserID(invitee, true)
|
inviteeUserID, userIDErr := spec.NewUserID(invitee, true)
|
||||||
if userIDErr != nil {
|
if userIDErr != nil {
|
||||||
|
|
@ -451,59 +449,20 @@ func (c *Creator) PerformCreateRoom(ctx context.Context, userID spec.UserID, roo
|
||||||
JSON: spec.InternalServerError{},
|
JSON: spec.InternalServerError{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
inviteeSenderID, queryErr := c.RSAPI.QuerySenderIDForUser(ctx, roomID, *inviteeUserID)
|
|
||||||
if queryErr != nil {
|
|
||||||
util.GetLogger(ctx).WithError(queryErr).Error("rsapi.QuerySenderIDForUser failed")
|
|
||||||
return "", &util.JSONResponse{
|
|
||||||
Code: http.StatusInternalServerError,
|
|
||||||
JSON: spec.InternalServerError{},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
inviteeString := string(inviteeSenderID)
|
|
||||||
proto := gomatrixserverlib.ProtoEvent{
|
|
||||||
SenderID: string(senderID),
|
|
||||||
RoomID: roomID.String(),
|
|
||||||
Type: "m.room.member",
|
|
||||||
StateKey: &inviteeString,
|
|
||||||
}
|
|
||||||
|
|
||||||
content := gomatrixserverlib.MemberContent{
|
|
||||||
Membership: spec.Invite,
|
|
||||||
DisplayName: createRequest.UserDisplayName,
|
|
||||||
AvatarURL: createRequest.UserAvatarURL,
|
|
||||||
Reason: "",
|
|
||||||
IsDirect: createRequest.IsDirect,
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = proto.SetContent(content); err != nil {
|
|
||||||
return "", &util.JSONResponse{
|
|
||||||
Code: http.StatusInternalServerError,
|
|
||||||
JSON: spec.InternalServerError{},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build the invite event.
|
|
||||||
identity := &fclient.SigningIdentity{
|
|
||||||
ServerName: userID.Domain(),
|
|
||||||
KeyID: createRequest.KeyID,
|
|
||||||
PrivateKey: createRequest.PrivateKey,
|
|
||||||
}
|
|
||||||
inviteEvent, err = eventutil.QueryAndBuildEvent(ctx, &proto, identity, createRequest.EventTime, c.RSAPI, nil)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
util.GetLogger(ctx).WithError(err).Error("buildMembershipEvent failed")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
inviteStrippedState := append(
|
|
||||||
globalStrippedState,
|
|
||||||
gomatrixserverlib.NewInviteStrippedState(inviteEvent.PDU),
|
|
||||||
)
|
|
||||||
// Send the invite event to the roomserver.
|
|
||||||
event := inviteEvent
|
|
||||||
err = c.RSAPI.PerformInvite(ctx, &api.PerformInviteRequest{
|
err = c.RSAPI.PerformInvite(ctx, &api.PerformInviteRequest{
|
||||||
Event: event,
|
InviteInput: api.InviteInput{
|
||||||
InviteRoomState: inviteStrippedState,
|
RoomID: roomID,
|
||||||
RoomVersion: event.Version(),
|
Inviter: userID,
|
||||||
|
Invitee: *inviteeUserID,
|
||||||
|
DisplayName: createRequest.UserDisplayName,
|
||||||
|
AvatarURL: createRequest.UserAvatarURL,
|
||||||
|
Reason: "",
|
||||||
|
IsDirect: createRequest.IsDirect,
|
||||||
|
KeyID: createRequest.KeyID,
|
||||||
|
PrivateKey: createRequest.PrivateKey,
|
||||||
|
},
|
||||||
|
InviteRoomState: globalStrippedState,
|
||||||
SendAsServer: string(userID.Domain()),
|
SendAsServer: string(userID.Domain()),
|
||||||
})
|
})
|
||||||
switch e := err.(type) {
|
switch e := err.(type) {
|
||||||
|
|
|
||||||
|
|
@ -129,48 +129,86 @@ func (r *Inviter) PerformInvite(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
req *api.PerformInviteRequest,
|
req *api.PerformInviteRequest,
|
||||||
) error {
|
) error {
|
||||||
event := req.Event
|
senderID, err := r.RSAPI.QuerySenderIDForUser(ctx, req.InviteInput.RoomID, req.InviteInput.Inviter)
|
||||||
|
if err != nil {
|
||||||
validRoomID, err := spec.NewRoomID(event.RoomID())
|
return err
|
||||||
|
}
|
||||||
|
info, err := r.DB.RoomInfo(ctx, req.InviteInput.RoomID.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
sender, err := r.RSAPI.QueryUserIDForSender(ctx, *validRoomID, event.SenderID())
|
proto := gomatrixserverlib.ProtoEvent{
|
||||||
if err != nil {
|
SenderID: string(senderID),
|
||||||
return spec.InvalidParam("The sender user ID is invalid")
|
RoomID: req.InviteInput.RoomID.String(),
|
||||||
|
Type: "m.room.member",
|
||||||
}
|
}
|
||||||
if !r.Cfg.Matrix.IsLocalServerName(sender.Domain()) {
|
|
||||||
|
content := gomatrixserverlib.MemberContent{
|
||||||
|
Membership: spec.Invite,
|
||||||
|
DisplayName: req.InviteInput.DisplayName,
|
||||||
|
AvatarURL: req.InviteInput.AvatarURL,
|
||||||
|
Reason: req.InviteInput.Reason,
|
||||||
|
IsDirect: req.InviteInput.IsDirect,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := proto.SetContent(content); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !r.Cfg.Matrix.IsLocalServerName(req.InviteInput.Inviter.Domain()) {
|
||||||
return api.ErrInvalidID{Err: fmt.Errorf("the invite must be from a local user")}
|
return api.ErrInvalidID{Err: fmt.Errorf("the invite must be from a local user")}
|
||||||
}
|
}
|
||||||
|
|
||||||
if event.StateKey() == nil || *event.StateKey() == "" {
|
isTargetLocal := r.Cfg.Matrix.IsLocalServerName(req.InviteInput.Invitee.Domain())
|
||||||
return fmt.Errorf("invite must be a state event")
|
|
||||||
}
|
|
||||||
invitedUser, err := r.RSAPI.QueryUserIDForSender(ctx, *validRoomID, spec.SenderID(*event.StateKey()))
|
|
||||||
if err != nil || invitedUser == nil {
|
|
||||||
return spec.InvalidParam("Could not find the matching senderID for this user")
|
|
||||||
}
|
|
||||||
isTargetLocal := r.Cfg.Matrix.IsLocalServerName(invitedUser.Domain())
|
|
||||||
|
|
||||||
invitedSenderID, err := r.RSAPI.QuerySenderIDForUser(ctx, *validRoomID, *invitedUser)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed looking up senderID for invited user")
|
|
||||||
}
|
|
||||||
|
|
||||||
input := gomatrixserverlib.PerformInviteInput{
|
input := gomatrixserverlib.PerformInviteInput{
|
||||||
RoomID: *validRoomID,
|
RoomID: req.InviteInput.RoomID,
|
||||||
InviteEvent: event.PDU,
|
RoomVersion: info.RoomVersion,
|
||||||
InvitedUser: *invitedUser,
|
Inviter: req.InviteInput.Inviter,
|
||||||
InvitedSenderID: invitedSenderID,
|
Invitee: req.InviteInput.Invitee,
|
||||||
IsTargetLocal: isTargetLocal,
|
IsTargetLocal: isTargetLocal,
|
||||||
|
EventTemplate: proto,
|
||||||
StrippedState: req.InviteRoomState,
|
StrippedState: req.InviteRoomState,
|
||||||
|
KeyID: req.InviteInput.KeyID,
|
||||||
|
SigningKey: req.InviteInput.PrivateKey,
|
||||||
MembershipQuerier: &api.MembershipQuerier{Roomserver: r.RSAPI},
|
MembershipQuerier: &api.MembershipQuerier{Roomserver: r.RSAPI},
|
||||||
StateQuerier: &QueryState{r.DB, r.RSAPI},
|
StateQuerier: &QueryState{r.DB, r.RSAPI},
|
||||||
UserIDQuerier: func(roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID, error) {
|
UserIDQuerier: func(roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID, error) {
|
||||||
return r.RSAPI.QueryUserIDForSender(ctx, roomID, senderID)
|
return r.RSAPI.QueryUserIDForSender(ctx, roomID, senderID)
|
||||||
},
|
},
|
||||||
|
SenderIDQuerier: func(roomID spec.RoomID, userID spec.UserID) (spec.SenderID, error) {
|
||||||
|
return r.RSAPI.QuerySenderIDForUser(ctx, roomID, userID)
|
||||||
|
},
|
||||||
|
SenderIDCreator: func(ctx context.Context, userID spec.UserID, roomID spec.RoomID) (spec.SenderID, error) {
|
||||||
|
key, keyErr := r.RSAPI.GetOrCreateUserRoomPrivateKey(ctx, userID, roomID)
|
||||||
|
if keyErr != nil {
|
||||||
|
return "", keyErr
|
||||||
|
}
|
||||||
|
|
||||||
|
return spec.SenderID(spec.Base64Bytes(key).Encode()), nil
|
||||||
|
},
|
||||||
|
EventQuerier: func(ctx context.Context, roomID spec.RoomID, eventsNeeded []gomatrixserverlib.StateKeyTuple) (gomatrixserverlib.LatestEvents, error) {
|
||||||
|
req := api.QueryLatestEventsAndStateRequest{RoomID: roomID.String(), StateToFetch: eventsNeeded}
|
||||||
|
res := api.QueryLatestEventsAndStateResponse{}
|
||||||
|
err := r.RSAPI.QueryLatestEventsAndState(ctx, &req, &res)
|
||||||
|
if err != nil {
|
||||||
|
return gomatrixserverlib.LatestEvents{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
stateEvents := []gomatrixserverlib.PDU{}
|
||||||
|
for _, event := range res.StateEvents {
|
||||||
|
stateEvents = append(stateEvents, event.PDU)
|
||||||
|
}
|
||||||
|
return gomatrixserverlib.LatestEvents{
|
||||||
|
RoomExists: res.RoomExists,
|
||||||
|
StateEvents: stateEvents,
|
||||||
|
PrevEventIDs: res.LatestEvents,
|
||||||
|
Depth: res.Depth,
|
||||||
|
}, nil
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
inviteEvent, err := gomatrixserverlib.PerformInvite(ctx, input, r.FSAPI)
|
inviteEvent, err := gomatrixserverlib.PerformInvite(ctx, input, r.FSAPI)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
switch e := err.(type) {
|
switch e := err.(type) {
|
||||||
|
|
@ -182,20 +220,6 @@ func (r *Inviter) PerformInvite(
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use the returned event if there was one (due to federation), otherwise
|
|
||||||
// send the original invite event to the roomserver.
|
|
||||||
if inviteEvent == nil {
|
|
||||||
inviteEvent = event
|
|
||||||
}
|
|
||||||
|
|
||||||
// if we invited a local user, we can also create a user room key, if it doesn't exist yet.
|
|
||||||
if isTargetLocal && event.Version() == gomatrixserverlib.RoomVersionPseudoIDs {
|
|
||||||
_, err = r.RSAPI.GetOrCreateUserRoomPrivateKey(ctx, *invitedUser, *validRoomID)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to get user room private key: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send the invite event to the roomserver input stream. This will
|
// Send the invite event to the roomserver input stream. This will
|
||||||
// notify existing users in the room about the invite, update the
|
// notify existing users in the room about the invite, update the
|
||||||
// membership table and ensure that the event is ready and available
|
// membership table and ensure that the event is ready and available
|
||||||
|
|
@ -206,7 +230,7 @@ func (r *Inviter) PerformInvite(
|
||||||
{
|
{
|
||||||
Kind: api.KindNew,
|
Kind: api.KindNew,
|
||||||
Event: &types.HeaderedEvent{PDU: inviteEvent},
|
Event: &types.HeaderedEvent{PDU: inviteEvent},
|
||||||
Origin: sender.Domain(),
|
Origin: req.InviteInput.Inviter.Domain(),
|
||||||
SendAsServer: req.SendAsServer,
|
SendAsServer: req.SendAsServer,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -214,7 +238,7 @@ func (r *Inviter) PerformInvite(
|
||||||
inputRes := &api.InputRoomEventsResponse{}
|
inputRes := &api.InputRoomEventsResponse{}
|
||||||
r.Inputer.InputRoomEvents(context.Background(), inputReq, inputRes)
|
r.Inputer.InputRoomEvents(context.Background(), inputReq, inputRes)
|
||||||
if err := inputRes.Err(); err != nil {
|
if err := inputRes.Err(); err != nil {
|
||||||
util.GetLogger(ctx).WithField("event_id", event.EventID()).Error("r.InputRoomEvents failed")
|
util.GetLogger(ctx).WithField("event_id", inviteEvent.EventID()).Error("r.InputRoomEvents failed")
|
||||||
return api.ErrNotAllowed{Err: err}
|
return api.ErrNotAllowed{Err: err}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue