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

@ -357,6 +357,7 @@ type QueryRestrictedJoinAllowedResponse struct {
Restricted bool `json:"restricted"` // Is the room membership restricted?
Resident bool `json:"resident"` // Is our homeserver in the relevant rooms?
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.

View file

@ -824,10 +824,34 @@ func (r *Queryer) QueryRestrictedJoinAllowed(ctx context.Context, req *api.Query
if err != nil {
continue
}
// If the user is in the room then we will allow the membership.
if isIn {
// If the user is not in the room then we will skip them.
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.Allowed = true
res.AuthorisedVia = *event.StateKey()
return nil
}
}