Improve error reporting

This commit is contained in:
Neil Alexander 2021-11-09 13:53:30 +00:00
parent 16b32316c2
commit 4d20122d77
No known key found for this signature in database
GPG key ID: A02A2019A2BB0944
2 changed files with 43 additions and 17 deletions

View file

@ -155,6 +155,12 @@ func UnableToAuthoriseJoin(msg string) *MatrixError {
return &MatrixError{"M_UNABLE_TO_AUTHORISE_JOIN", msg}
}
// UnableToGrantJoin is an error that is returned when a server that we
// are trying to join via doesn't have a user with power to invite.
func UnableToGrantJoin(msg string) *MatrixError {
return &MatrixError{"M_UNABLE_TO_GRANT_JOIN", msg}
}
type IncompatibleRoomVersionError struct {
RoomVersion string `json:"room_version"`
Error string `json:"error"`

View file

@ -191,6 +191,8 @@ func attemptMakeJoinForRestrictedMembership(
userID string,
) util.JSONResponse {
logger := util.GetLogger(httpReq.Context()).WithField("restricted_join", userID)
foundUserInAnyRoom := false
ableToAuthoriseJoin := false
// As a last effort, see if any of the restricted join rules match.
// If so, we might be able to modify and sign the event so that it
@ -234,9 +236,6 @@ func attemptMakeJoinForRestrictedMembership(
// user who has initiated this join.
found := false
for _, member := range queryRes.JoinEvents {
if member.StateKey == nil {
continue // shouldn't ever happen
}
if *member.StateKey == userID {
found = true
break
@ -252,11 +251,8 @@ func attemptMakeJoinForRestrictedMembership(
// Now look through all of the join events of the other members. Our goal
// is to try and find a user from our own server that has a suitable power
// level to popuate into the `join_authorised_via_users_server` field.
foundUserInAnyRoom = true
for _, member := range queryRes.JoinEvents {
if member.StateKey == nil {
continue // shouldn't ever happen
}
// If the user doesn't come from our own server then it's no good, try
// the next one instead.
_, domain, err := gomatrixserverlib.SplitID('@', *member.StateKey)
@ -267,6 +263,12 @@ func attemptMakeJoinForRestrictedMembership(
continue
}
// We have a user who is joined to the room, so we can authorise joins.
// We will only be able to "grant" joins if any of our users have the
// power to invite other users — this flag helps us to return the right
// error code if not.
ableToAuthoriseJoin = true
// If the user has the ability to invite to the room then they are a
// suitable candidate for the `join_authorised_via_users_server`.
if powerLevels.UserLevel(*member.StateKey) >= powerLevels.Invite {
@ -292,17 +294,16 @@ func attemptMakeJoinForRestrictedMembership(
return jsonerror.InternalServerError()
}
// Sign the event. This is basically our seal of approval that
// other servers can use to verify that the user we put into the
// Sign and return the event. This is basically our seal of approval
// that other servers can use to verify that the user we put into the
// `join_authorised_via_users_server` field was actually checked
// and found by us.
signed := event.Sign(string(cfg.Matrix.ServerName), cfg.Matrix.KeyID, cfg.Matrix.PrivateKey)
// Otherwise, the new join event looks good, so return it.
return util.JSONResponse{
Code: http.StatusOK,
JSON: map[string]interface{}{
"event": signed,
"event": event.Sign(
string(cfg.Matrix.ServerName), cfg.Matrix.KeyID, cfg.Matrix.PrivateKey,
),
"room_version": verRes.RoomVersion,
},
}
@ -310,11 +311,30 @@ func attemptMakeJoinForRestrictedMembership(
}
}
logger.Error("No room matching join rule memberships found")
switch {
case ableToAuthoriseJoin && foundUserInAnyRoom:
// We found ourselves in some of the allowed rooms, but none of our
// users had a suitable power level to invite other users, so we
// don't have the ability to grant joins.
return util.JSONResponse{
Code: http.StatusBadRequest,
JSON: jsonerror.UnableToGrantJoin("None of the users from this homeserver have the power to invite"),
}
case ableToAuthoriseJoin && !foundUserInAnyRoom:
// We found ourselves in some of the allowed rooms, but none of them
// seemed to contain the joining user.
return util.JSONResponse{
Code: http.StatusForbidden,
JSON: jsonerror.Forbidden("You are not joined to any allowed rooms"),
}
default:
// We don't seem to be joined to any of the allowed rooms, so we
// can't even check if the join is supposed to be allowed or not.
return util.JSONResponse{
Code: http.StatusBadRequest,
JSON: jsonerror.UnableToAuthoriseJoin("This homeserver isn't joined to any of the allowed rooms"),
}
}
}
// SendJoin implements the /send_join API