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} 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 { type IncompatibleRoomVersionError struct {
RoomVersion string `json:"room_version"` RoomVersion string `json:"room_version"`
Error string `json:"error"` Error string `json:"error"`

View file

@ -191,6 +191,8 @@ func attemptMakeJoinForRestrictedMembership(
userID string, userID string,
) util.JSONResponse { ) util.JSONResponse {
logger := util.GetLogger(httpReq.Context()).WithField("restricted_join", userID) 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. // 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 // 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. // user who has initiated this join.
found := false found := false
for _, member := range queryRes.JoinEvents { for _, member := range queryRes.JoinEvents {
if member.StateKey == nil {
continue // shouldn't ever happen
}
if *member.StateKey == userID { if *member.StateKey == userID {
found = true found = true
break break
@ -252,11 +251,8 @@ func attemptMakeJoinForRestrictedMembership(
// Now look through all of the join events of the other members. Our goal // 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 // 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. // level to popuate into the `join_authorised_via_users_server` field.
foundUserInAnyRoom = true
for _, member := range queryRes.JoinEvents { 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 // If the user doesn't come from our own server then it's no good, try
// the next one instead. // the next one instead.
_, domain, err := gomatrixserverlib.SplitID('@', *member.StateKey) _, domain, err := gomatrixserverlib.SplitID('@', *member.StateKey)
@ -267,6 +263,12 @@ func attemptMakeJoinForRestrictedMembership(
continue 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 // If the user has the ability to invite to the room then they are a
// suitable candidate for the `join_authorised_via_users_server`. // suitable candidate for the `join_authorised_via_users_server`.
if powerLevels.UserLevel(*member.StateKey) >= powerLevels.Invite { if powerLevels.UserLevel(*member.StateKey) >= powerLevels.Invite {
@ -292,17 +294,16 @@ func attemptMakeJoinForRestrictedMembership(
return jsonerror.InternalServerError() return jsonerror.InternalServerError()
} }
// Sign the event. This is basically our seal of approval that // Sign and return the event. This is basically our seal of approval
// other servers can use to verify that the user we put into the // that other servers can use to verify that the user we put into the
// `join_authorised_via_users_server` field was actually checked // `join_authorised_via_users_server` field was actually checked
// and found by us. // 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{ return util.JSONResponse{
Code: http.StatusOK, Code: http.StatusOK,
JSON: map[string]interface{}{ JSON: map[string]interface{}{
"event": signed, "event": event.Sign(
string(cfg.Matrix.ServerName), cfg.Matrix.KeyID, cfg.Matrix.PrivateKey,
),
"room_version": verRes.RoomVersion, "room_version": verRes.RoomVersion,
}, },
} }
@ -310,10 +311,29 @@ func attemptMakeJoinForRestrictedMembership(
} }
} }
logger.Error("No room matching join rule memberships found") switch {
return util.JSONResponse{ case ableToAuthoriseJoin && foundUserInAnyRoom:
Code: http.StatusForbidden, // We found ourselves in some of the allowed rooms, but none of our
JSON: jsonerror.Forbidden("You are not joined to any allowed rooms"), // 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"),
}
} }
} }