Populate AuthorisedVia properly

This commit is contained in:
Neil Alexander 2022-05-23 14:08:25 +01:00
parent 5e801bb5b1
commit c0d4315583
No known key found for this signature in database
GPG key ID: A02A2019A2BB0944
3 changed files with 48 additions and 17 deletions

View file

@ -105,7 +105,8 @@ func MakeJoin(
// Check if the restricted join is allowed. If the room doesn't // Check if the restricted join is allowed. If the room doesn't
// support restricted joins then this is effectively a no-op. // support restricted joins then this is effectively a no-op.
if res, rerr := checkRestrictedJoin(httpReq, rsAPI, verRes.RoomVersion, roomID, userID); rerr != nil { res, authorisedVia, err := checkRestrictedJoin(httpReq, rsAPI, verRes.RoomVersion, roomID, userID)
if err != nil {
util.GetLogger(httpReq.Context()).WithError(err).Error("checkRestrictedJoin failed") util.GetLogger(httpReq.Context()).WithError(err).Error("checkRestrictedJoin failed")
return jsonerror.InternalServerError() return jsonerror.InternalServerError()
} else if res != nil { } else if res != nil {
@ -119,8 +120,11 @@ func MakeJoin(
Type: "m.room.member", Type: "m.room.member",
StateKey: &userID, StateKey: &userID,
} }
err = builder.SetContent(map[string]interface{}{"membership": gomatrixserverlib.Join}) content := gomatrixserverlib.MemberContent{
if err != nil { Membership: gomatrixserverlib.Join,
AuthorisedVia: authorisedVia,
}
if err = builder.SetContent(content); err != nil {
util.GetLogger(httpReq.Context()).WithError(err).Error("builder.SetContent failed") util.GetLogger(httpReq.Context()).WithError(err).Error("builder.SetContent failed")
return jsonerror.InternalServerError() return jsonerror.InternalServerError()
} }
@ -372,11 +376,11 @@ func checkRestrictedJoin(
rsAPI api.FederationRoomserverAPI, rsAPI api.FederationRoomserverAPI,
roomVersion gomatrixserverlib.RoomVersion, roomVersion gomatrixserverlib.RoomVersion,
roomID, userID string, roomID, userID string,
) (*util.JSONResponse, error) { ) (*util.JSONResponse, string, error) {
if allowRestricted, err := roomVersion.AllowRestrictedJoinsInEventAuth(); err != nil { if allowRestricted, err := roomVersion.AllowRestrictedJoinsInEventAuth(); err != nil {
return nil, err return nil, "", err
} else if !allowRestricted { } else if !allowRestricted {
return nil, nil return nil, "", nil
} }
req := &api.QueryRestrictedJoinAllowedRequest{ req := &api.QueryRestrictedJoinAllowedRequest{
RoomID: roomID, RoomID: roomID,
@ -384,13 +388,13 @@ func checkRestrictedJoin(
} }
res := &api.QueryRestrictedJoinAllowedResponse{} res := &api.QueryRestrictedJoinAllowedResponse{}
if err := rsAPI.QueryRestrictedJoinAllowed(httpReq.Context(), req, res); err != nil { if err := rsAPI.QueryRestrictedJoinAllowed(httpReq.Context(), req, res); err != nil {
return nil, err return nil, "", err
} }
switch { switch {
case !res.Restricted: case !res.Restricted:
// The join rules for the room don't restrict membership. // The join rules for the room don't restrict membership.
return nil, nil return nil, "", nil
case !res.Resident: case !res.Resident:
// The join rules restrict membership but our server isn't currently // The join rules restrict membership but our server isn't currently
@ -401,7 +405,7 @@ func checkRestrictedJoin(
return &util.JSONResponse{ return &util.JSONResponse{
Code: http.StatusBadRequest, Code: http.StatusBadRequest,
JSON: jsonerror.UnableToAuthoriseJoin("This server cannot authorise the join."), JSON: jsonerror.UnableToAuthoriseJoin("This server cannot authorise the join."),
}, nil }, "", nil
case !res.Allowed: case !res.Allowed:
// The join rules restrict membership, our server is in the relevant // The join rules restrict membership, our server is in the relevant
@ -410,13 +414,15 @@ func checkRestrictedJoin(
return &util.JSONResponse{ return &util.JSONResponse{
Code: http.StatusForbidden, Code: http.StatusForbidden,
JSON: jsonerror.Forbidden("You are not joined to any matching rooms."), JSON: jsonerror.Forbidden("You are not joined to any matching rooms."),
}, nil }, "", nil
default: default:
// The join rules restrict membership, our server is in the relevant // The join rules restrict membership, our server is in the relevant
// rooms and the user was allowed to join because they belong to one // rooms and the user was allowed to join because they belong to one
// of the allowed rooms. // of the allowed rooms. We now need to pick one of our own local users
return nil, nil // from within the room to use as the authorising user ID, so that it
// can be referred to from within the membership content.
return nil, res.AuthorisedVia, nil
} }
} }

View file

@ -354,9 +354,10 @@ type QueryRestrictedJoinAllowedRequest struct {
} }
type QueryRestrictedJoinAllowedResponse struct { type QueryRestrictedJoinAllowedResponse struct {
Restricted bool `json:"restricted"` // Is the room membership restricted? Restricted bool `json:"restricted"` // Is the room membership restricted?
Resident bool `json:"resident"` // Is our homeserver in the relevant rooms? Resident bool `json:"resident"` // Is our homeserver in the relevant rooms?
Allowed bool `json:"allowed"` // Is the join allowed by the rules? Allowed bool `json:"allowed"` // Is the join allowed by the rules?
AuthorisedVia string `json:"authorised_via,omitempty"` // The user that authorises the join
} }
// MarshalJSON stringifies the room ID and StateKeyTuple keys so they can be sent over the wire in HTTP API mode. // MarshalJSON stringifies the room ID and StateKeyTuple keys so they can be sent over the wire in HTTP API mode.

View file

@ -824,10 +824,34 @@ func (r *Queryer) QueryRestrictedJoinAllowed(ctx context.Context, req *api.Query
if err != nil { if err != nil {
continue continue
} }
// If the user is in the room then we will allow the membership. // If the user is not in the room then we will skip them.
if isIn { if !isIn {
continue
}
// The user is in the room, so now we will need to authorise the
// join using the user ID of one of our own users in the room. Pick
// one.
joinNIDs, err := r.DB.GetMembershipEventNIDsForRoom(ctx, targetRoomInfo.RoomNID, true, true)
if err != nil || len(joinNIDs) == 0 {
// There should always be more than one join NID at this point
// because we are gated behind GetLocalServerInRoom, but y'know,
// sometimes strange things happen.
continue
}
// For each of the joined users, let's see if we can get a valid
// membership event.
for _, joinNID := range joinNIDs {
events, err := r.DB.Events(ctx, []types.EventNID{joinNID})
if err != nil || len(events) != 1 {
continue
}
event := events[0]
if event.Type() != gomatrixserverlib.MRoomMember || event.StateKey() == nil {
continue // shouldn't happen
}
res.Resident = true res.Resident = true
res.Allowed = true res.Allowed = true
res.AuthorisedVia = *event.StateKey()
return nil return nil
} }
} }