Skip to content

Commit

Permalink
Merge branch 'main' of github.com:matrix-org/gomatrixserverlib into s…
Browse files Browse the repository at this point in the history
…7evink/eventsize
  • Loading branch information
S7evinK committed Jul 7, 2023
2 parents da261f0 + ad3d32b commit 866ea9a
Show file tree
Hide file tree
Showing 18 changed files with 1,622 additions and 160 deletions.
9 changes: 8 additions & 1 deletion eventauth.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,8 +186,9 @@ func accumulateStateNeeded(result *StateNeeded, eventType string, sender spec.Se
}
result.Create = true
result.PowerLevels = true
result.Member = append(result.Member, string(sender))
if stateKey != nil {
result.Member = append(result.Member, string(sender), *stateKey)
result.Member = append(result.Member, *stateKey)
}
if content.Membership == spec.Join || content.Membership == spec.Knock || content.Membership == spec.Invite {
result.JoinRules = true
Expand Down Expand Up @@ -887,6 +888,9 @@ func (e *eventAllower) commonChecks(event PDU) error {
if err != nil {
return err
}
if userID == nil {
return errorf("userID not found for sender %q in room %q", event.SenderID(), event.RoomID())
}
if err := e.create.UserIDAllowed(*userID); err != nil {
return err
}
Expand Down Expand Up @@ -990,6 +994,9 @@ func (m *membershipAllower) membershipAllowed(event PDU) error { // nolint: gocy
if err != nil {
return err
}
if sender == nil {
return errorf("userID not found for sender %q in room %q", m.senderID, event.RoomID())
}
if err := m.create.UserIDAllowed(*sender); err != nil {
return err
}
Expand Down
52 changes: 29 additions & 23 deletions eventcrypto.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,35 +42,42 @@ func VerifyEventSignatures(ctx context.Context, e PDU, verifier JSONVerifier, us
panic("UserIDForSender func is nil")
}

var serverName spec.ServerName
needed := map[spec.ServerName]struct{}{}

// The sender should have signed the event in all cases.
validRoomID, err := spec.NewRoomID(e.RoomID())
if err != nil {
return err
}
sender, err := userIDForSender(*validRoomID, e.SenderID())
if err != nil {
return fmt.Errorf("invalid sender userID: %w", err)
}
serverName := sender.Domain()
needed[serverName] = struct{}{}

verImpl, err := GetRoomVersion(e.Version())
if err != nil {
return err
}

// In room versions 1 and 2, we should also check that the server
// that created the event is included too. This is probably the
// same as the sender.
format := verImpl.EventIDFormat()
if format == EventIDFormatV1 {
_, serverName, err = SplitID('$', e.EventID())
// The sender should have signed the event in all cases.
switch e.Version() {
case RoomVersionPseudoIDs:
needed[spec.ServerName(e.SenderID())] = struct{}{}
default:
validRoomID, err := spec.NewRoomID(e.RoomID())
if err != nil {
return fmt.Errorf("failed to split event ID: %w", err)
return err
}
sender, err := userIDForSender(*validRoomID, e.SenderID())
if err != nil {
return fmt.Errorf("invalid sender userID: %w", err)
}
if sender != nil {
serverName = sender.Domain()
needed[serverName] = struct{}{}
}

// In room versions 1 and 2, we should also check that the server
// that created the event is included too. This is probably the
// same as the sender.
format := verImpl.EventIDFormat()
if format == EventIDFormatV1 {
_, serverName, err = SplitID('$', e.EventID())
if err != nil {
return fmt.Errorf("failed to split event ID: %w", err)
}
needed[serverName] = struct{}{}
}
needed[serverName] = struct{}{}
}

// Special checks for membership events.
Expand All @@ -92,8 +99,7 @@ func VerifyEventSignatures(ctx context.Context, e PDU, verifier JSONVerifier, us
if membership == spec.Invite {
switch e.Version() {
case RoomVersionPseudoIDs:
// TODO: (pseudoIDs) revisit this logic for event signing
needed[spec.ServerName(e.SenderID())] = struct{}{}
needed[spec.ServerName(*e.StateKey())] = struct{}{}
default:
_, serverName, err = SplitID('@', *e.StateKey())
if err != nil {
Expand Down
19 changes: 19 additions & 0 deletions fclient/federationclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ type FederationClient interface {
MakeLeave(ctx context.Context, origin, s spec.ServerName, roomID, userID string) (res RespMakeLeave, err error)
SendLeave(ctx context.Context, origin, s spec.ServerName, event gomatrixserverlib.PDU) (err error)
SendInviteV2(ctx context.Context, origin, s spec.ServerName, request InviteV2Request) (res RespInviteV2, err error)
SendInviteV3(ctx context.Context, origin, s spec.ServerName, request InviteV3Request, userID spec.UserID) (res RespInviteV2, err error)

GetEvent(ctx context.Context, origin, s spec.ServerName, eventID string) (res gomatrixserverlib.Transaction, err error)

Expand Down Expand Up @@ -123,6 +124,7 @@ func (ac *federationClient) doRequest(ctx context.Context, r FederationRequest,

var federationPathPrefixV1 = "/_matrix/federation/v1"
var federationPathPrefixV2 = "/_matrix/federation/v2"
var federationPathPrefixV3 = "/_matrix/federation/v3"

// SendTransaction sends a transaction
func (ac *federationClient) SendTransaction(
Expand Down Expand Up @@ -409,6 +411,23 @@ func (ac *federationClient) SendInviteV2(
return
}

// SendInviteV3 sends an invite m.room.member event to an invited server to be
// signed by it. This is used to invite a user that is not on the local server.
// V3 sends a partial event to allow the invitee to populate the mxid_mapping.
func (ac *federationClient) SendInviteV3(
ctx context.Context, origin, s spec.ServerName, request InviteV3Request, userID spec.UserID,
) (res RespInviteV2, err error) {
path := federationPathPrefixV3 + "/invite/" +
url.PathEscape(request.Event().RoomID) + "/" +
url.PathEscape(userID.String())
req := NewFederationRequest("PUT", origin, s, path)
if err = req.SetContent(request); err != nil {
return
}
err = ac.doRequest(ctx, req, &res)
return
}

// ExchangeThirdPartyInvite sends the builder of a m.room.member event of
// "invite" membership derived from a response from invites sent by an identity
// server.
Expand Down
62 changes: 62 additions & 0 deletions fclient/invitev3.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package fclient

import (
"encoding/json"

"github.com/matrix-org/gomatrixserverlib"
)

func NewInviteV3Request(event gomatrixserverlib.ProtoEvent, version gomatrixserverlib.RoomVersion, state []gomatrixserverlib.InviteStrippedState) (
request InviteV3Request, err error,
) {
if !gomatrixserverlib.KnownRoomVersion(version) {
err = gomatrixserverlib.UnsupportedRoomVersionError{
Version: version,
}
return
}
request.fields.inviteV2RequestHeaders = inviteV2RequestHeaders{
RoomVersion: version,
InviteRoomState: state,
}
request.fields.Event = event
return
}

// InviteV3Request is used in the body of a /_matrix/federation/v3/invite request.
type InviteV3Request struct {
fields struct {
inviteV2RequestHeaders
Event gomatrixserverlib.ProtoEvent `json:"event"`
}
}

// MarshalJSON implements json.Marshaller
func (i InviteV3Request) MarshalJSON() ([]byte, error) {
return json.Marshal(i.fields)
}

// UnmarshalJSON implements json.Unmarshaller
func (i *InviteV3Request) UnmarshalJSON(data []byte) error {
err := json.Unmarshal(data, &i.fields)
if err != nil {
return err
}
return err
}

// Event returns the invite event.
func (i *InviteV3Request) Event() gomatrixserverlib.ProtoEvent {
return i.fields.Event
}

// RoomVersion returns the room version of the invited room.
func (i *InviteV3Request) RoomVersion() gomatrixserverlib.RoomVersion {
return i.fields.RoomVersion
}

// InviteRoomState returns stripped state events for the room, containing
// enough information for the client to identify the room.
func (i *InviteV3Request) InviteRoomState() []gomatrixserverlib.InviteStrippedState {
return i.fields.InviteRoomState
}
79 changes: 79 additions & 0 deletions fclient/invitev3_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package fclient

import (
"encoding/json"
"testing"

"github.com/matrix-org/gomatrixserverlib"
"github.com/matrix-org/gomatrixserverlib/spec"
)

func TestMarshalInviteV3Request(t *testing.T) {
expected := `{"room_version":"org.matrix.msc4014","invite_room_state":[],"event":{"sender":"@test:localhost","room_id":"!19Mp0U9hjajeIiw1:localhost","type":"m.room.name","state_key":"","prev_events":["upCsBqUhNUgT2/+zkzg8TbqdQpWWKQnZpGJc6KcbUC4"],"auth_events":["abjkiDSg1RkuZrbj2jZoGMlQaaj1Ue3Jhi7I7NlKfXY","X7RUj46hM/8sUHNBIFkStbOauPvbDzjSdH4NibYWnko","k9eM6utkCH8vhLW9/oRsH74jOBS/6RVK42iGDFbylno"],"depth":7,"signatures":{"localhost":{"ed25519:u9kP":"5IzSuRXkxvbTp0vZhhXYZeOe+619iG3AybJXr7zfNn/4vHz4TH7qSJVQXSaHHvcTcDodAKHnTG1WDulgO5okAQ"}},"content":{"name":"test3"}}}`

senderID := "@test:localhost"
roomID := "!19Mp0U9hjajeIiw1:localhost"
eventType := "m.room.name"
stateKey := ""
prevEvents := []string{"upCsBqUhNUgT2/+zkzg8TbqdQpWWKQnZpGJc6KcbUC4"}
authEvents := []string{"abjkiDSg1RkuZrbj2jZoGMlQaaj1Ue3Jhi7I7NlKfXY", "X7RUj46hM/8sUHNBIFkStbOauPvbDzjSdH4NibYWnko", "k9eM6utkCH8vhLW9/oRsH74jOBS/6RVK42iGDFbylno"}
depth := int64(7)
signatures := spec.RawJSON(`{"localhost": {"ed25519:u9kP": "5IzSuRXkxvbTp0vZhhXYZeOe+619iG3AybJXr7zfNn/4vHz4TH7qSJVQXSaHHvcTcDodAKHnTG1WDulgO5okAQ"}}`)
content := spec.RawJSON(`{"name":"test3"}`)

output := gomatrixserverlib.ProtoEvent{
SenderID: senderID,
RoomID: roomID,
Type: eventType,
StateKey: &stateKey,
PrevEvents: prevEvents,
AuthEvents: authEvents,
Depth: depth,
Signature: signatures,
Content: content,
}

inviteReq, err := NewInviteV3Request(output, gomatrixserverlib.RoomVersionPseudoIDs, []gomatrixserverlib.InviteStrippedState{})
if err != nil {
t.Fatal(err)
}

j, err := json.Marshal(inviteReq)
if err != nil {
t.Fatal(err)
}

if string(j) != expected {
t.Fatalf("\nresult: %q\nwanted: %q", string(j), expected)
}

var newRequest InviteV3Request
err = json.Unmarshal(j, &newRequest)
if err != nil {
t.Fatal(err)
}

if newRequest.RoomVersion() != gomatrixserverlib.RoomVersionPseudoIDs {
t.Fatalf("unmatched room version. expected: %v, got: %v", gomatrixserverlib.RoomVersionPseudoIDs, newRequest.RoomVersion())
}
if len(newRequest.InviteRoomState()) != 0 {
t.Fatalf("invite room state should not have any events")
}
if newRequest.Event().SenderID != senderID {
t.Fatalf("unmatched senderID. expected: %v, got: %v", newRequest.Event().SenderID, senderID)

}
if newRequest.Event().RoomID != roomID {
t.Fatalf("unmatched roomID. expected: %v, got: %v", newRequest.Event().RoomID, roomID)
}
if newRequest.Event().Type != eventType {
t.Fatalf("unmatched type. expected: %v, got: %v", newRequest.Event().Type, eventType)

}
if *newRequest.Event().StateKey != stateKey {
t.Fatalf("unmatched state key. expected: %v, got: %v", *newRequest.Event().StateKey, stateKey)
}
if newRequest.Event().Depth != depth {
t.Fatalf("unmatched depth. expected: %v, got: %v", newRequest.Event().Depth, depth)
}
}
Loading

0 comments on commit 866ea9a

Please sign in to comment.