Handle cryptoID invites & leaves
This commit is contained in:
parent
7f7ac0f4fe
commit
227493cc5d
|
@ -15,6 +15,7 @@
|
||||||
package routing
|
package routing
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
|
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
|
||||||
|
@ -23,11 +24,16 @@ import (
|
||||||
"github.com/matrix-org/util"
|
"github.com/matrix-org/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type leaveRoomCryptoIDsResponse struct {
|
||||||
|
PDU json.RawMessage `json:"pdu"`
|
||||||
|
}
|
||||||
|
|
||||||
func LeaveRoomByID(
|
func LeaveRoomByID(
|
||||||
req *http.Request,
|
req *http.Request,
|
||||||
device *api.Device,
|
device *api.Device,
|
||||||
rsAPI roomserverAPI.ClientRoomserverAPI,
|
rsAPI roomserverAPI.ClientRoomserverAPI,
|
||||||
roomID string,
|
roomID string,
|
||||||
|
cryptoIDs bool,
|
||||||
) util.JSONResponse {
|
) util.JSONResponse {
|
||||||
userID, err := spec.NewUserID(device.UserID, true)
|
userID, err := spec.NewUserID(device.UserID, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -45,7 +51,8 @@ func LeaveRoomByID(
|
||||||
leaveRes := roomserverAPI.PerformLeaveResponse{}
|
leaveRes := roomserverAPI.PerformLeaveResponse{}
|
||||||
|
|
||||||
// Ask the roomserver to perform the leave.
|
// Ask the roomserver to perform the leave.
|
||||||
if err := rsAPI.PerformLeave(req.Context(), &leaveReq, &leaveRes); err != nil {
|
leaveEvent, err := rsAPI.PerformLeave(req.Context(), &leaveReq, &leaveRes, cryptoIDs)
|
||||||
|
if err != nil {
|
||||||
if leaveRes.Code != 0 {
|
if leaveRes.Code != 0 {
|
||||||
return util.JSONResponse{
|
return util.JSONResponse{
|
||||||
Code: leaveRes.Code,
|
Code: leaveRes.Code,
|
||||||
|
@ -60,6 +67,8 @@ func LeaveRoomByID(
|
||||||
|
|
||||||
return util.JSONResponse{
|
return util.JSONResponse{
|
||||||
Code: http.StatusOK,
|
Code: http.StatusOK,
|
||||||
JSON: struct{}{},
|
JSON: leaveRoomCryptoIDsResponse{
|
||||||
|
PDU: json.RawMessage(leaveEvent.JSON()),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -443,7 +443,6 @@ func Setup(
|
||||||
return resp.(util.JSONResponse)
|
return resp.(util.JSONResponse)
|
||||||
}, httputil.WithAllowGuests()),
|
}, httputil.WithAllowGuests()),
|
||||||
).Methods(http.MethodPost, http.MethodOptions)
|
).Methods(http.MethodPost, http.MethodOptions)
|
||||||
// TODO: update for cryptoIDs
|
|
||||||
v3mux.Handle("/rooms/{roomID}/leave",
|
v3mux.Handle("/rooms/{roomID}/leave",
|
||||||
httputil.MakeAuthAPI("membership", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
httputil.MakeAuthAPI("membership", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||||
if r := rateLimits.Limit(req, device); r != nil {
|
if r := rateLimits.Limit(req, device); r != nil {
|
||||||
|
@ -454,7 +453,22 @@ func Setup(
|
||||||
return util.ErrorResponse(err)
|
return util.ErrorResponse(err)
|
||||||
}
|
}
|
||||||
return LeaveRoomByID(
|
return LeaveRoomByID(
|
||||||
req, device, rsAPI, vars["roomID"],
|
req, device, rsAPI, vars["roomID"], false,
|
||||||
|
)
|
||||||
|
}, httputil.WithAllowGuests()),
|
||||||
|
).Methods(http.MethodPost, http.MethodOptions)
|
||||||
|
unstableMux.Handle("/org.matrix.msc_cryptoids/rooms/{roomID}/leave",
|
||||||
|
httputil.MakeAuthAPI("membership", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||||
|
logrus.Info("Processing request to /org.matrix.msc_cryptoids/rooms/{roomID}/leave")
|
||||||
|
if r := rateLimits.Limit(req, device); r != nil {
|
||||||
|
return *r
|
||||||
|
}
|
||||||
|
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
|
||||||
|
if err != nil {
|
||||||
|
return util.ErrorResponse(err)
|
||||||
|
}
|
||||||
|
return LeaveRoomByID(
|
||||||
|
req, device, rsAPI, vars["roomID"], true,
|
||||||
)
|
)
|
||||||
}, httputil.WithAllowGuests()),
|
}, httputil.WithAllowGuests()),
|
||||||
).Methods(http.MethodPost, http.MethodOptions)
|
).Methods(http.MethodPost, http.MethodOptions)
|
||||||
|
|
|
@ -32,6 +32,7 @@ import (
|
||||||
"github.com/matrix-org/dendrite/syncapi/synctypes"
|
"github.com/matrix-org/dendrite/syncapi/synctypes"
|
||||||
userapi "github.com/matrix-org/dendrite/userapi/api"
|
userapi "github.com/matrix-org/dendrite/userapi/api"
|
||||||
"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"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
|
@ -171,7 +172,7 @@ func SendEvent(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
e, resErr := generateSendEvent(req.Context(), r, device, roomID, eventType, stateKey, rsAPI, evTime)
|
e, resErr := generateSendEvent(req.Context(), r, device, roomID, eventType, stateKey, rsAPI, evTime, false)
|
||||||
if resErr != nil {
|
if resErr != nil {
|
||||||
return *resErr
|
return *resErr
|
||||||
}
|
}
|
||||||
|
@ -362,7 +363,7 @@ func SendEventCryptoIDs(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
e, resErr := generateSendEvent(req.Context(), r, device, roomID, eventType, stateKey, rsAPI, evTime)
|
e, resErr := generateSendEvent(req.Context(), r, device, roomID, eventType, stateKey, rsAPI, evTime, true)
|
||||||
if resErr != nil {
|
if resErr != nil {
|
||||||
return *resErr
|
return *resErr
|
||||||
}
|
}
|
||||||
|
@ -484,6 +485,7 @@ func generateSendEvent(
|
||||||
roomID, eventType string, stateKey *string,
|
roomID, eventType string, stateKey *string,
|
||||||
rsAPI api.ClientRoomserverAPI,
|
rsAPI api.ClientRoomserverAPI,
|
||||||
evTime time.Time,
|
evTime time.Time,
|
||||||
|
cryptoIDs bool,
|
||||||
) (gomatrixserverlib.PDU, *util.JSONResponse) {
|
) (gomatrixserverlib.PDU, *util.JSONResponse) {
|
||||||
// parse the incoming http request
|
// parse the incoming http request
|
||||||
fullUserID, err := spec.NewUserID(device.UserID, true)
|
fullUserID, err := spec.NewUserID(device.UserID, true)
|
||||||
|
@ -531,12 +533,18 @@ func generateSendEvent(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
identity, err := rsAPI.SigningIdentityFor(ctx, *validRoomID, *fullUserID)
|
var identity fclient.SigningIdentity
|
||||||
if err != nil {
|
if !cryptoIDs {
|
||||||
return nil, &util.JSONResponse{
|
id, err := rsAPI.SigningIdentityFor(ctx, *validRoomID, *fullUserID)
|
||||||
Code: http.StatusInternalServerError,
|
if err != nil {
|
||||||
JSON: spec.InternalServerError{},
|
return nil, &util.JSONResponse{
|
||||||
|
Code: http.StatusInternalServerError,
|
||||||
|
JSON: spec.InternalServerError{},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
identity = id
|
||||||
|
} else {
|
||||||
|
identity.ServerName = spec.ServerName(*senderID)
|
||||||
}
|
}
|
||||||
|
|
||||||
var queryRes api.QueryLatestEventsAndStateResponse
|
var queryRes api.QueryLatestEventsAndStateResponse
|
||||||
|
|
|
@ -228,7 +228,7 @@ func SendServerNotice(
|
||||||
"body": r.Content.Body,
|
"body": r.Content.Body,
|
||||||
"msgtype": r.Content.MsgType,
|
"msgtype": r.Content.MsgType,
|
||||||
}
|
}
|
||||||
e, resErr := generateSendEvent(ctx, request, senderDevice, roomID, "m.room.message", nil, rsAPI, time.Now())
|
e, resErr := generateSendEvent(ctx, request, senderDevice, roomID, "m.room.message", nil, rsAPI, time.Now(), false)
|
||||||
if resErr != nil {
|
if resErr != nil {
|
||||||
logrus.Errorf("failed to send message: %+v", resErr)
|
logrus.Errorf("failed to send message: %+v", resErr)
|
||||||
return *resErr
|
return *resErr
|
||||||
|
|
|
@ -61,7 +61,7 @@ type RoomserverFederationAPI interface {
|
||||||
PerformMakeJoin(ctx context.Context, request *PerformJoinRequest) (gomatrixserverlib.PDU, gomatrixserverlib.RoomVersion, spec.ServerName, error)
|
PerformMakeJoin(ctx context.Context, request *PerformJoinRequest) (gomatrixserverlib.PDU, gomatrixserverlib.RoomVersion, spec.ServerName, error)
|
||||||
PerformSendJoin(ctx context.Context, request *PerformSendJoinRequestCryptoIDs, response *PerformJoinResponse)
|
PerformSendJoin(ctx context.Context, request *PerformSendJoinRequestCryptoIDs, response *PerformJoinResponse)
|
||||||
// Handle an instruction to make_leave & send_leave with a remote server.
|
// Handle an instruction to make_leave & send_leave with a remote server.
|
||||||
PerformLeave(ctx context.Context, request *PerformLeaveRequest, response *PerformLeaveResponse) error
|
PerformLeave(ctx context.Context, request *PerformLeaveRequest, response *PerformLeaveResponse, cryptoIDs bool) 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.
|
// Handle sending an invite to a remote server.
|
||||||
|
|
|
@ -747,6 +747,7 @@ func (r *FederationInternalAPI) PerformLeave(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
request *api.PerformLeaveRequest,
|
request *api.PerformLeaveRequest,
|
||||||
response *api.PerformLeaveResponse,
|
response *api.PerformLeaveResponse,
|
||||||
|
cryptoIDs bool,
|
||||||
) (err error) {
|
) (err error) {
|
||||||
userID, err := spec.NewUserID(request.UserID, true)
|
userID, err := spec.NewUserID(request.UserID, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -85,12 +85,20 @@ func BuildEvent(
|
||||||
}
|
}
|
||||||
builder := verImpl.NewEventBuilderFromProtoEvent(proto)
|
builder := verImpl.NewEventBuilderFromProtoEvent(proto)
|
||||||
|
|
||||||
event, err := builder.Build(
|
var event gomatrixserverlib.PDU
|
||||||
evTime, identity.ServerName, identity.KeyID,
|
if identity.PrivateKey != nil {
|
||||||
identity.PrivateKey,
|
event, err = builder.Build(
|
||||||
)
|
evTime, identity.ServerName, identity.KeyID,
|
||||||
if err != nil {
|
identity.PrivateKey,
|
||||||
return nil, err
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
event, err = builder.BuildWithoutSigning(evTime, identity.ServerName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &types.HeaderedEvent{PDU: event}, nil
|
return &types.HeaderedEvent{PDU: event}, nil
|
||||||
|
|
|
@ -248,7 +248,7 @@ type ClientRoomserverAPI interface {
|
||||||
PerformJoin(ctx context.Context, req *PerformJoinRequest) (roomID string, joinedVia spec.ServerName, err error)
|
PerformJoin(ctx context.Context, req *PerformJoinRequest) (roomID string, joinedVia spec.ServerName, err error)
|
||||||
PerformSendJoinCryptoIDs(ctx context.Context, req *PerformJoinRequestCryptoIDs) error
|
PerformSendJoinCryptoIDs(ctx context.Context, req *PerformJoinRequestCryptoIDs) error
|
||||||
PerformJoinCryptoIDs(ctx context.Context, req *PerformJoinRequest) (join gomatrixserverlib.PDU, roomID string, version gomatrixserverlib.RoomVersion, serverName spec.ServerName, err error)
|
PerformJoinCryptoIDs(ctx context.Context, req *PerformJoinRequest) (join gomatrixserverlib.PDU, roomID string, version gomatrixserverlib.RoomVersion, serverName spec.ServerName, err error)
|
||||||
PerformLeave(ctx context.Context, req *PerformLeaveRequest, res *PerformLeaveResponse) error
|
PerformLeave(ctx context.Context, req *PerformLeaveRequest, res *PerformLeaveResponse, cryptoIDs bool) (gomatrixserverlib.PDU, error)
|
||||||
PerformPublish(ctx context.Context, req *PerformPublishRequest) error
|
PerformPublish(ctx context.Context, req *PerformPublishRequest) error
|
||||||
// PerformForget forgets a rooms history for a specific user
|
// PerformForget forgets a rooms history for a specific user
|
||||||
PerformForget(ctx context.Context, req *PerformForgetRequest, resp *PerformForgetResponse) error
|
PerformForget(ctx context.Context, req *PerformForgetRequest, resp *PerformForgetResponse) error
|
||||||
|
|
|
@ -262,16 +262,18 @@ func (r *RoomserverInternalAPI) PerformLeave(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
req *api.PerformLeaveRequest,
|
req *api.PerformLeaveRequest,
|
||||||
res *api.PerformLeaveResponse,
|
res *api.PerformLeaveResponse,
|
||||||
) error {
|
cryptoIDs bool,
|
||||||
outputEvents, err := r.Leaver.PerformLeave(ctx, req, res)
|
) (gomatrixserverlib.PDU, error) {
|
||||||
|
outputEvents, leaveEvent, err := r.Leaver.PerformLeave(ctx, req, res, cryptoIDs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
sentry.CaptureException(err)
|
sentry.CaptureException(err)
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
if len(outputEvents) == 0 {
|
if len(outputEvents) == 0 {
|
||||||
return nil
|
return leaveEvent, nil
|
||||||
}
|
}
|
||||||
return r.OutputProducer.ProduceRoomEvents(req.RoomID, outputEvents)
|
// TODO: cryptoIDs - what to do with this?
|
||||||
|
return leaveEvent, r.OutputProducer.ProduceRoomEvents(req.RoomID, outputEvents)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RoomserverInternalAPI) PerformForget(
|
func (r *RoomserverInternalAPI) PerformForget(
|
||||||
|
|
|
@ -179,7 +179,7 @@ func (r *Admin) PerformAdminEvacuateUser(
|
||||||
Leaver: *fullUserID,
|
Leaver: *fullUserID,
|
||||||
}
|
}
|
||||||
leaveRes := &api.PerformLeaveResponse{}
|
leaveRes := &api.PerformLeaveResponse{}
|
||||||
outputEvents, err := r.Leaver.PerformLeave(ctx, leaveReq, leaveRes)
|
outputEvents, _, err := r.Leaver.PerformLeave(ctx, leaveReq, leaveRes, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -163,7 +163,7 @@ func (r *Inviter) PerformInvite(
|
||||||
isTargetLocal := r.Cfg.Matrix.IsLocalServerName(req.InviteInput.Invitee.Domain())
|
isTargetLocal := r.Cfg.Matrix.IsLocalServerName(req.InviteInput.Invitee.Domain())
|
||||||
|
|
||||||
signingKey := req.InviteInput.PrivateKey
|
signingKey := req.InviteInput.PrivateKey
|
||||||
if info.RoomVersion == gomatrixserverlib.RoomVersionPseudoIDs {
|
if !cryptoIDs && info.RoomVersion == gomatrixserverlib.RoomVersionPseudoIDs {
|
||||||
signingKey, err = r.RSAPI.GetOrCreateUserRoomPrivateKey(ctx, req.InviteInput.Inviter, req.InviteInput.RoomID)
|
signingKey, err = r.RSAPI.GetOrCreateUserRoomPrivateKey(ctx, req.InviteInput.Inviter, req.InviteInput.RoomID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -665,15 +665,8 @@ func (r *Joiner) performJoinRoomByIDCryptoIDs(
|
||||||
|
|
||||||
// at this point we know we have an existing room
|
// at this point we know we have an existing room
|
||||||
if inRoomRes.RoomVersion == gomatrixserverlib.RoomVersionPseudoIDs {
|
if inRoomRes.RoomVersion == gomatrixserverlib.RoomVersionPseudoIDs {
|
||||||
var pseudoIDKey ed25519.PrivateKey
|
|
||||||
pseudoIDKey, err = r.RSAPI.GetOrCreateUserRoomPrivateKey(ctx, *userID, *roomID)
|
|
||||||
if err != nil {
|
|
||||||
util.GetLogger(ctx).WithError(err).Error("GetOrCreateUserRoomPrivateKey failed")
|
|
||||||
return nil, "", "", "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
mapping := &gomatrixserverlib.MXIDMapping{
|
mapping := &gomatrixserverlib.MXIDMapping{
|
||||||
UserRoomKey: spec.SenderIDFromPseudoIDKey(pseudoIDKey),
|
UserRoomKey: senderID,
|
||||||
UserID: userID.String(),
|
UserID: userID.String(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -685,9 +678,9 @@ func (r *Joiner) performJoinRoomByIDCryptoIDs(
|
||||||
|
|
||||||
// sign the event with the pseudo ID key
|
// sign the event with the pseudo ID key
|
||||||
identity = fclient.SigningIdentity{
|
identity = fclient.SigningIdentity{
|
||||||
ServerName: spec.ServerName(spec.SenderIDFromPseudoIDKey(pseudoIDKey)),
|
ServerName: spec.ServerName(senderID),
|
||||||
KeyID: "ed25519:1",
|
KeyID: "ed25519:1",
|
||||||
PrivateKey: pseudoIDKey,
|
PrivateKey: nil,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ import (
|
||||||
"github.com/matrix-org/dendrite/internal/eventutil"
|
"github.com/matrix-org/dendrite/internal/eventutil"
|
||||||
"github.com/matrix-org/gomatrix"
|
"github.com/matrix-org/gomatrix"
|
||||||
"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"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
@ -52,9 +53,10 @@ func (r *Leaver) PerformLeave(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
req *api.PerformLeaveRequest,
|
req *api.PerformLeaveRequest,
|
||||||
res *api.PerformLeaveResponse,
|
res *api.PerformLeaveResponse,
|
||||||
) ([]api.OutputEvent, error) {
|
cryptoIDs bool,
|
||||||
|
) ([]api.OutputEvent, gomatrixserverlib.PDU, error) {
|
||||||
if !r.Cfg.Matrix.IsLocalServerName(req.Leaver.Domain()) {
|
if !r.Cfg.Matrix.IsLocalServerName(req.Leaver.Domain()) {
|
||||||
return nil, fmt.Errorf("user %q does not belong to this homeserver", req.Leaver.String())
|
return nil, nil, fmt.Errorf("user %q does not belong to this homeserver", req.Leaver.String())
|
||||||
}
|
}
|
||||||
logger := logrus.WithContext(ctx).WithFields(logrus.Fields{
|
logger := logrus.WithContext(ctx).WithFields(logrus.Fields{
|
||||||
"room_id": req.RoomID,
|
"room_id": req.RoomID,
|
||||||
|
@ -62,15 +64,15 @@ func (r *Leaver) PerformLeave(
|
||||||
})
|
})
|
||||||
logger.Info("User requested to leave join")
|
logger.Info("User requested to leave join")
|
||||||
if strings.HasPrefix(req.RoomID, "!") {
|
if strings.HasPrefix(req.RoomID, "!") {
|
||||||
output, err := r.performLeaveRoomByID(context.Background(), req, res)
|
output, event, err := r.performLeaveRoomByID(context.Background(), req, res, cryptoIDs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.WithError(err).Error("Failed to leave room")
|
logger.WithError(err).Error("Failed to leave room")
|
||||||
} else {
|
} else {
|
||||||
logger.Info("User left room successfully")
|
logger.Info("User left room successfully")
|
||||||
}
|
}
|
||||||
return output, err
|
return output, event, err
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("room ID %q is invalid", req.RoomID)
|
return nil, nil, fmt.Errorf("room ID %q is invalid", req.RoomID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// nolint:gocyclo
|
// nolint:gocyclo
|
||||||
|
@ -78,14 +80,15 @@ func (r *Leaver) performLeaveRoomByID(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
req *api.PerformLeaveRequest,
|
req *api.PerformLeaveRequest,
|
||||||
res *api.PerformLeaveResponse, // nolint:unparam
|
res *api.PerformLeaveResponse, // nolint:unparam
|
||||||
) ([]api.OutputEvent, error) {
|
cryptoIDs bool,
|
||||||
|
) ([]api.OutputEvent, gomatrixserverlib.PDU, error) {
|
||||||
roomID, err := spec.NewRoomID(req.RoomID)
|
roomID, err := spec.NewRoomID(req.RoomID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
leaver, err := r.RSAPI.QuerySenderIDForUser(ctx, *roomID, req.Leaver)
|
leaver, err := r.RSAPI.QuerySenderIDForUser(ctx, *roomID, req.Leaver)
|
||||||
if err != nil || leaver == nil {
|
if err != nil || leaver == nil {
|
||||||
return nil, fmt.Errorf("leaver %s has no matching senderID in this room", req.Leaver.String())
|
return nil, nil, fmt.Errorf("leaver %s has no matching senderID in this room", req.Leaver.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there's an invite outstanding for the room then respond to
|
// If there's an invite outstanding for the room then respond to
|
||||||
|
@ -94,7 +97,7 @@ func (r *Leaver) performLeaveRoomByID(
|
||||||
if err == nil && isInvitePending {
|
if err == nil && isInvitePending {
|
||||||
sender, serr := r.RSAPI.QueryUserIDForSender(ctx, *roomID, senderUser)
|
sender, serr := r.RSAPI.QueryUserIDForSender(ctx, *roomID, senderUser)
|
||||||
if serr != nil {
|
if serr != nil {
|
||||||
return nil, fmt.Errorf("failed looking up userID for sender %q: %w", senderUser, serr)
|
return nil, nil, fmt.Errorf("failed looking up userID for sender %q: %w", senderUser, serr)
|
||||||
}
|
}
|
||||||
|
|
||||||
var domain spec.ServerName
|
var domain spec.ServerName
|
||||||
|
@ -107,7 +110,7 @@ func (r *Leaver) performLeaveRoomByID(
|
||||||
domain = sender.Domain()
|
domain = sender.Domain()
|
||||||
}
|
}
|
||||||
if !r.Cfg.Matrix.IsLocalServerName(domain) {
|
if !r.Cfg.Matrix.IsLocalServerName(domain) {
|
||||||
return r.performFederatedRejectInvite(ctx, req, res, domain, eventID, *leaver)
|
return r.performFederatedRejectInvite(ctx, req, res, domain, eventID, *leaver, cryptoIDs)
|
||||||
}
|
}
|
||||||
// check that this is not a "server notice room"
|
// check that this is not a "server notice room"
|
||||||
accData := &userapi.QueryAccountDataResponse{}
|
accData := &userapi.QueryAccountDataResponse{}
|
||||||
|
@ -116,7 +119,7 @@ func (r *Leaver) performLeaveRoomByID(
|
||||||
RoomID: req.RoomID,
|
RoomID: req.RoomID,
|
||||||
DataType: "m.tag",
|
DataType: "m.tag",
|
||||||
}, accData); err != nil {
|
}, accData); err != nil {
|
||||||
return nil, fmt.Errorf("unable to query account data: %w", err)
|
return nil, nil, fmt.Errorf("unable to query account data: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if roomData, ok := accData.RoomAccountData[req.RoomID]; ok {
|
if roomData, ok := accData.RoomAccountData[req.RoomID]; ok {
|
||||||
|
@ -124,13 +127,13 @@ func (r *Leaver) performLeaveRoomByID(
|
||||||
if ok {
|
if ok {
|
||||||
tags := gomatrix.TagContent{}
|
tags := gomatrix.TagContent{}
|
||||||
if err = json.Unmarshal(tagData, &tags); err != nil {
|
if err = json.Unmarshal(tagData, &tags); err != nil {
|
||||||
return nil, fmt.Errorf("unable to unmarshal tag content")
|
return nil, nil, fmt.Errorf("unable to unmarshal tag content")
|
||||||
}
|
}
|
||||||
if _, ok = tags.Tags["m.server_notice"]; ok {
|
if _, ok = tags.Tags["m.server_notice"]; ok {
|
||||||
// mimic the returned values from Synapse
|
// mimic the returned values from Synapse
|
||||||
res.Message = "You cannot reject this invite"
|
res.Message = "You cannot reject this invite"
|
||||||
res.Code = 403
|
res.Code = 403
|
||||||
return nil, spec.LeaveServerNoticeError()
|
return nil, nil, spec.LeaveServerNoticeError()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -149,22 +152,22 @@ func (r *Leaver) performLeaveRoomByID(
|
||||||
}
|
}
|
||||||
latestRes := api.QueryLatestEventsAndStateResponse{}
|
latestRes := api.QueryLatestEventsAndStateResponse{}
|
||||||
if err = helpers.QueryLatestEventsAndState(ctx, r.DB, r.RSAPI, &latestReq, &latestRes); err != nil {
|
if err = helpers.QueryLatestEventsAndState(ctx, r.DB, r.RSAPI, &latestReq, &latestRes); err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
if !latestRes.RoomExists {
|
if !latestRes.RoomExists {
|
||||||
return nil, fmt.Errorf("room %q does not exist", req.RoomID)
|
return nil, nil, fmt.Errorf("room %q does not exist", req.RoomID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now let's see if the user is in the room.
|
// Now let's see if the user is in the room.
|
||||||
if len(latestRes.StateEvents) == 0 {
|
if len(latestRes.StateEvents) == 0 {
|
||||||
return nil, fmt.Errorf("user %q is not a member of room %q", req.Leaver.String(), req.RoomID)
|
return nil, nil, fmt.Errorf("user %q is not a member of room %q", req.Leaver.String(), req.RoomID)
|
||||||
}
|
}
|
||||||
membership, err := latestRes.StateEvents[0].Membership()
|
membership, err := latestRes.StateEvents[0].Membership()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error getting membership: %w", err)
|
return nil, nil, fmt.Errorf("error getting membership: %w", err)
|
||||||
}
|
}
|
||||||
if membership != spec.Join && membership != spec.Invite {
|
if membership != spec.Join && membership != spec.Invite {
|
||||||
return nil, fmt.Errorf("user %q is not joined to the room (membership is %q)", req.Leaver.String(), membership)
|
return nil, nil, fmt.Errorf("user %q is not joined to the room (membership is %q)", req.Leaver.String(), membership)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare the template for the leave event.
|
// Prepare the template for the leave event.
|
||||||
|
@ -177,10 +180,10 @@ func (r *Leaver) performLeaveRoomByID(
|
||||||
Redacts: "",
|
Redacts: "",
|
||||||
}
|
}
|
||||||
if err = proto.SetContent(map[string]interface{}{"membership": "leave"}); err != nil {
|
if err = proto.SetContent(map[string]interface{}{"membership": "leave"}); err != nil {
|
||||||
return nil, fmt.Errorf("eb.SetContent: %w", err)
|
return nil, nil, fmt.Errorf("eb.SetContent: %w", err)
|
||||||
}
|
}
|
||||||
if err = proto.SetUnsigned(struct{}{}); err != nil {
|
if err = proto.SetUnsigned(struct{}{}); err != nil {
|
||||||
return nil, fmt.Errorf("eb.SetUnsigned: %w", err)
|
return nil, nil, fmt.Errorf("eb.SetUnsigned: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// We know that the user is in the room at this point so let's build
|
// We know that the user is in the room at this point so let's build
|
||||||
|
@ -190,39 +193,50 @@ func (r *Leaver) performLeaveRoomByID(
|
||||||
|
|
||||||
validRoomID, err := spec.NewRoomID(req.RoomID)
|
validRoomID, err := spec.NewRoomID(req.RoomID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var buildRes rsAPI.QueryLatestEventsAndStateResponse
|
var buildRes rsAPI.QueryLatestEventsAndStateResponse
|
||||||
identity, err := r.RSAPI.SigningIdentityFor(ctx, *validRoomID, req.Leaver)
|
var identity fclient.SigningIdentity
|
||||||
if err != nil {
|
if !cryptoIDs {
|
||||||
return nil, fmt.Errorf("SigningIdentityFor: %w", err)
|
identity, err = r.RSAPI.SigningIdentityFor(ctx, *validRoomID, req.Leaver)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, fmt.Errorf("SigningIdentityFor: %w", err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
identity = fclient.SigningIdentity{
|
||||||
|
ServerName: spec.ServerName(*leaver),
|
||||||
|
KeyID: "ed25519:1",
|
||||||
|
PrivateKey: nil,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
event, err := eventutil.QueryAndBuildEvent(ctx, &proto, &identity, time.Now(), r.RSAPI, &buildRes)
|
event, err := eventutil.QueryAndBuildEvent(ctx, &proto, &identity, time.Now(), r.RSAPI, &buildRes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("eventutil.QueryAndBuildEvent: %w", err)
|
return nil, nil, fmt.Errorf("eventutil.QueryAndBuildEvent: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Give our leave event to the roomserver input stream. The
|
if !cryptoIDs {
|
||||||
// roomserver will process the membership change and notify
|
// Give our leave event to the roomserver input stream. The
|
||||||
// downstream automatically.
|
// roomserver will process the membership change and notify
|
||||||
inputReq := api.InputRoomEventsRequest{
|
// downstream automatically.
|
||||||
InputRoomEvents: []api.InputRoomEvent{
|
inputReq := api.InputRoomEventsRequest{
|
||||||
{
|
InputRoomEvents: []api.InputRoomEvent{
|
||||||
Kind: api.KindNew,
|
{
|
||||||
Event: event,
|
Kind: api.KindNew,
|
||||||
Origin: req.Leaver.Domain(),
|
Event: event,
|
||||||
SendAsServer: string(req.Leaver.Domain()),
|
Origin: req.Leaver.Domain(),
|
||||||
|
SendAsServer: string(req.Leaver.Domain()),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
}
|
||||||
}
|
inputRes := api.InputRoomEventsResponse{}
|
||||||
inputRes := api.InputRoomEventsResponse{}
|
r.Inputer.InputRoomEvents(ctx, &inputReq, &inputRes)
|
||||||
r.Inputer.InputRoomEvents(ctx, &inputReq, &inputRes)
|
if err = inputRes.Err(); err != nil {
|
||||||
if err = inputRes.Err(); err != nil {
|
return nil, nil, fmt.Errorf("r.InputRoomEvents: %w", err)
|
||||||
return nil, fmt.Errorf("r.InputRoomEvents: %w", err)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, nil
|
return nil, event, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Leaver) performFederatedRejectInvite(
|
func (r *Leaver) performFederatedRejectInvite(
|
||||||
|
@ -231,7 +245,8 @@ func (r *Leaver) performFederatedRejectInvite(
|
||||||
res *api.PerformLeaveResponse, // nolint:unparam
|
res *api.PerformLeaveResponse, // nolint:unparam
|
||||||
inviteDomain spec.ServerName, eventID string,
|
inviteDomain spec.ServerName, eventID string,
|
||||||
leaver spec.SenderID,
|
leaver spec.SenderID,
|
||||||
) ([]api.OutputEvent, error) {
|
cryptoIDs bool,
|
||||||
|
) ([]api.OutputEvent, gomatrixserverlib.PDU, error) {
|
||||||
// Ask the federation sender to perform a federated leave for us.
|
// Ask the federation sender to perform a federated leave for us.
|
||||||
leaveReq := fsAPI.PerformLeaveRequest{
|
leaveReq := fsAPI.PerformLeaveRequest{
|
||||||
RoomID: req.RoomID,
|
RoomID: req.RoomID,
|
||||||
|
@ -239,7 +254,7 @@ func (r *Leaver) performFederatedRejectInvite(
|
||||||
ServerNames: []spec.ServerName{inviteDomain},
|
ServerNames: []spec.ServerName{inviteDomain},
|
||||||
}
|
}
|
||||||
leaveRes := fsAPI.PerformLeaveResponse{}
|
leaveRes := fsAPI.PerformLeaveResponse{}
|
||||||
if err := r.FSAPI.PerformLeave(ctx, &leaveReq, &leaveRes); err != nil {
|
if err := r.FSAPI.PerformLeave(ctx, &leaveReq, &leaveRes, cryptoIDs); err != nil {
|
||||||
// failures in PerformLeave should NEVER stop us from telling other components like the
|
// failures in PerformLeave should NEVER stop us from telling other components like the
|
||||||
// sync API that the invite was withdrawn. Otherwise we can end up with stuck invites.
|
// sync API that the invite was withdrawn. Otherwise we can end up with stuck invites.
|
||||||
util.GetLogger(ctx).WithError(err).Errorf("failed to PerformLeave, still retiring invite event")
|
util.GetLogger(ctx).WithError(err).Errorf("failed to PerformLeave, still retiring invite event")
|
||||||
|
@ -279,5 +294,5 @@ func (r *Leaver) performFederatedRejectInvite(
|
||||||
TargetSenderID: leaver,
|
TargetSenderID: leaver,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -532,6 +532,7 @@ type InviteResponse struct {
|
||||||
InviteState struct {
|
InviteState struct {
|
||||||
Events []json.RawMessage `json:"events"`
|
Events []json.RawMessage `json:"events"`
|
||||||
} `json:"invite_state"`
|
} `json:"invite_state"`
|
||||||
|
OneTimePseudoID string `json:"one_time_pseudoid,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewInviteResponse creates an empty response with initialised arrays.
|
// NewInviteResponse creates an empty response with initialised arrays.
|
||||||
|
@ -539,6 +540,8 @@ func NewInviteResponse(ctx context.Context, rsAPI api.QuerySenderIDAPI, event *t
|
||||||
res := InviteResponse{}
|
res := InviteResponse{}
|
||||||
res.InviteState.Events = []json.RawMessage{}
|
res.InviteState.Events = []json.RawMessage{}
|
||||||
|
|
||||||
|
res.OneTimePseudoID = *event.PDU.StateKey()
|
||||||
|
|
||||||
// First see if there's invite_room_state in the unsigned key of the invite.
|
// First see if there's invite_room_state in the unsigned key of the invite.
|
||||||
// If there is then unmarshal it into the response. This will contain the
|
// If there is then unmarshal it into the response. This will contain the
|
||||||
// partial room state such as join rules, room name etc.
|
// partial room state such as join rules, room name etc.
|
||||||
|
|
|
@ -858,15 +858,15 @@ type Ed25519Key struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *UserInternalAPI) ClaimOneTimePseudoID(ctx context.Context, roomID spec.RoomID, userID spec.UserID) (spec.SenderID, error) {
|
func (a *UserInternalAPI) ClaimOneTimePseudoID(ctx context.Context, roomID spec.RoomID, userID spec.UserID) (spec.SenderID, error) {
|
||||||
pseudoIDs, err := a.KeyDatabase.ClaimOneTimePseudoID(ctx, userID, "ed25519")
|
pseudoID, err := a.KeyDatabase.ClaimOneTimePseudoID(ctx, userID, "ed25519")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
logrus.Infof("Claimed one time pseuodID: %v", pseudoIDs)
|
logrus.Infof("Claimed one time pseuodID: %s", pseudoID)
|
||||||
|
|
||||||
if pseudoIDs != nil {
|
if pseudoID != nil {
|
||||||
for key, value := range pseudoIDs.KeyJSON {
|
for key, value := range pseudoID.KeyJSON {
|
||||||
keyParts := strings.Split(key, ":")
|
keyParts := strings.Split(key, ":")
|
||||||
if keyParts[0] == "ed25519" {
|
if keyParts[0] == "ed25519" {
|
||||||
var key_bytes Ed25519Key
|
var key_bytes Ed25519Key
|
||||||
|
|
Loading…
Reference in a new issue