Change to using switch on err types with nonexistent rooms

This commit is contained in:
Devon Hudson 2023-05-12 11:35:37 -06:00
parent a77f7e385a
commit 822618e8f7
No known key found for this signature in database
GPG key ID: CD06B18E77F6A628
15 changed files with 111 additions and 58 deletions

View file

@ -31,7 +31,7 @@ func AdminEvacuateRoom(req *http.Request, rsAPI roomserverAPI.ClientRoomserverAP
} }
affected, err := rsAPI.PerformAdminEvacuateRoom(req.Context(), vars["roomID"]) affected, err := rsAPI.PerformAdminEvacuateRoom(req.Context(), vars["roomID"])
switch err { switch err.(type) {
case nil: case nil:
case eventutil.ErrRoomNoExists: case eventutil.ErrRoomNoExists:
return util.JSONResponse{ return util.JSONResponse{
@ -231,10 +231,10 @@ func AdminDownloadState(req *http.Request, device *api.Device, rsAPI roomserverA
} }
} }
if err = rsAPI.PerformAdminDownloadState(req.Context(), roomID, device.UserID, spec.ServerName(serverName)); err != nil { if err = rsAPI.PerformAdminDownloadState(req.Context(), roomID, device.UserID, spec.ServerName(serverName)); err != nil {
if errors.Is(err, eventutil.ErrRoomNoExists) { if errors.Is(err, eventutil.ErrRoomNoExists{}) {
return util.JSONResponse{ return util.JSONResponse{
Code: 200, Code: 200,
JSON: spec.NotFound(eventutil.ErrRoomNoExists.Error()), JSON: spec.NotFound(err.Error()),
} }
} }
logrus.WithError(err).WithFields(logrus.Fields{ logrus.WithError(err).WithFields(logrus.Fields{

View file

@ -16,7 +16,6 @@ package routing
import ( import (
"encoding/json" "encoding/json"
"errors"
"net/http" "net/http"
"time" "time"
@ -114,17 +113,16 @@ func JoinRoomByIDOrAlias(
Code: e.Code, Code: e.Code,
JSON: json.RawMessage(e.Message), JSON: json.RawMessage(e.Message),
} }
case eventutil.ErrRoomNoExists:
response = util.JSONResponse{
Code: http.StatusNotFound,
JSON: spec.NotFound(e.Error()),
}
default: default:
response = util.JSONResponse{ response = util.JSONResponse{
Code: http.StatusInternalServerError, Code: http.StatusInternalServerError,
JSON: spec.InternalServerError(), JSON: spec.InternalServerError(),
} }
if errors.Is(err, eventutil.ErrRoomNoExists) {
response = util.JSONResponse{
Code: http.StatusNotFound,
JSON: spec.NotFound(e.Error()),
}
}
} }
done <- response done <- response
}() }()

View file

@ -398,28 +398,33 @@ func checkAndProcessThreepid(
req.Context(), device, body, cfg, rsAPI, profileAPI, req.Context(), device, body, cfg, rsAPI, profileAPI,
roomID, evTime, roomID, evTime,
) )
if err == threepid.ErrMissingParameter { switch e := err.(type) {
case nil:
case threepid.ErrMissingParameter:
util.GetLogger(req.Context()).WithError(err).Error("threepid.CheckAndProcessInvite failed")
return inviteStored, &util.JSONResponse{ return inviteStored, &util.JSONResponse{
Code: http.StatusBadRequest, Code: http.StatusBadRequest,
JSON: spec.BadJSON(err.Error()), JSON: spec.BadJSON(err.Error()),
} }
} else if err == threepid.ErrNotTrusted { case threepid.ErrNotTrusted:
util.GetLogger(req.Context()).WithError(err).Error("threepid.CheckAndProcessInvite failed")
return inviteStored, &util.JSONResponse{ return inviteStored, &util.JSONResponse{
Code: http.StatusBadRequest, Code: http.StatusBadRequest,
JSON: spec.NotTrusted(body.IDServer), JSON: spec.NotTrusted(body.IDServer),
} }
} else if err == eventutil.ErrRoomNoExists { case eventutil.ErrRoomNoExists:
util.GetLogger(req.Context()).WithError(err).Error("threepid.CheckAndProcessInvite failed")
return inviteStored, &util.JSONResponse{ return inviteStored, &util.JSONResponse{
Code: http.StatusNotFound, Code: http.StatusNotFound,
JSON: spec.NotFound(err.Error()), JSON: spec.NotFound(err.Error()),
} }
} else if e, ok := err.(gomatrixserverlib.BadJSONError); ok { case gomatrixserverlib.BadJSONError:
util.GetLogger(req.Context()).WithError(err).Error("threepid.CheckAndProcessInvite failed")
return inviteStored, &util.JSONResponse{ return inviteStored, &util.JSONResponse{
Code: http.StatusBadRequest, Code: http.StatusBadRequest,
JSON: spec.BadJSON(e.Error()), JSON: spec.BadJSON(e.Error()),
} }
} default:
if err != nil {
util.GetLogger(req.Context()).WithError(err).Error("threepid.CheckAndProcessInvite failed") util.GetLogger(req.Context()).WithError(err).Error("threepid.CheckAndProcessInvite failed")
er := spec.InternalServerError() er := spec.InternalServerError()
return inviteStored, &er return inviteStored, &er

View file

@ -16,6 +16,7 @@ package routing
import ( import (
"context" "context"
"errors"
"net/http" "net/http"
"time" "time"
@ -131,7 +132,7 @@ func SendRedaction(
var queryRes roomserverAPI.QueryLatestEventsAndStateResponse var queryRes roomserverAPI.QueryLatestEventsAndStateResponse
e, err := eventutil.QueryAndBuildEvent(req.Context(), &proto, cfg.Matrix, identity, time.Now(), rsAPI, &queryRes) e, err := eventutil.QueryAndBuildEvent(req.Context(), &proto, cfg.Matrix, identity, time.Now(), rsAPI, &queryRes)
if err == eventutil.ErrRoomNoExists { if errors.Is(err, eventutil.ErrRoomNoExists{}) {
return util.JSONResponse{ return util.JSONResponse{
Code: http.StatusNotFound, Code: http.StatusNotFound,
JSON: spec.NotFound("Room does not exist"), JSON: spec.NotFound("Room does not exist"),

View file

@ -284,28 +284,30 @@ func generateSendEvent(
var queryRes api.QueryLatestEventsAndStateResponse var queryRes api.QueryLatestEventsAndStateResponse
e, err := eventutil.QueryAndBuildEvent(ctx, &proto, cfg.Matrix, identity, evTime, rsAPI, &queryRes) e, err := eventutil.QueryAndBuildEvent(ctx, &proto, cfg.Matrix, identity, evTime, rsAPI, &queryRes)
if err == eventutil.ErrRoomNoExists { switch specificErr := err.(type) {
case nil:
case eventutil.ErrRoomNoExists:
return nil, &util.JSONResponse{ return nil, &util.JSONResponse{
Code: http.StatusNotFound, Code: http.StatusNotFound,
JSON: spec.NotFound("Room does not exist"), JSON: spec.NotFound("Room does not exist"),
} }
} else if e, ok := err.(gomatrixserverlib.BadJSONError); ok { case gomatrixserverlib.BadJSONError:
return nil, &util.JSONResponse{ return nil, &util.JSONResponse{
Code: http.StatusBadRequest, Code: http.StatusBadRequest,
JSON: spec.BadJSON(e.Error()), JSON: spec.BadJSON(specificErr.Error()),
} }
} else if e, ok := err.(gomatrixserverlib.EventValidationError); ok { case gomatrixserverlib.EventValidationError:
if e.Code == gomatrixserverlib.EventValidationTooLarge { if specificErr.Code == gomatrixserverlib.EventValidationTooLarge {
return nil, &util.JSONResponse{ return nil, &util.JSONResponse{
Code: http.StatusRequestEntityTooLarge, Code: http.StatusRequestEntityTooLarge,
JSON: spec.BadJSON(e.Error()), JSON: spec.BadJSON(specificErr.Error()),
} }
} }
return nil, &util.JSONResponse{ return nil, &util.JSONResponse{
Code: http.StatusBadRequest, Code: http.StatusBadRequest,
JSON: spec.BadJSON(e.Error()), JSON: spec.BadJSON(specificErr.Error()),
} }
} else if err != nil { default:
util.GetLogger(ctx).WithError(err).Error("eventutil.BuildEvent failed") util.GetLogger(ctx).WithError(err).Error("eventutil.BuildEvent failed")
resErr := spec.InternalServerError() resErr := spec.InternalServerError()
return nil, &resErr return nil, &resErr

View file

@ -74,12 +74,15 @@ func RequestEmailToken(req *http.Request, threePIDAPI api.ClientUserAPI, cfg *co
} }
resp.SID, err = threepid.CreateSession(req.Context(), body, cfg, client) resp.SID, err = threepid.CreateSession(req.Context(), body, cfg, client)
if err == threepid.ErrNotTrusted { switch err.(type) {
case nil:
case threepid.ErrNotTrusted:
util.GetLogger(req.Context()).WithError(err).Error("threepid.CreateSession failed")
return util.JSONResponse{ return util.JSONResponse{
Code: http.StatusBadRequest, Code: http.StatusBadRequest,
JSON: spec.NotTrusted(body.IDServer), JSON: spec.NotTrusted(body.IDServer),
} }
} else if err != nil { default:
util.GetLogger(req.Context()).WithError(err).Error("threepid.CreateSession failed") util.GetLogger(req.Context()).WithError(err).Error("threepid.CreateSession failed")
return spec.InternalServerError() return spec.InternalServerError()
} }
@ -102,12 +105,15 @@ func CheckAndSave3PIDAssociation(
// Check if the association has been validated // Check if the association has been validated
verified, address, medium, err := threepid.CheckAssociation(req.Context(), body.Creds, cfg, client) verified, address, medium, err := threepid.CheckAssociation(req.Context(), body.Creds, cfg, client)
if err == threepid.ErrNotTrusted { switch err.(type) {
case nil:
case threepid.ErrNotTrusted:
util.GetLogger(req.Context()).WithError(err).Error("threepid.CheckAssociation failed")
return util.JSONResponse{ return util.JSONResponse{
Code: http.StatusBadRequest, Code: http.StatusBadRequest,
JSON: spec.NotTrusted(body.Creds.IDServer), JSON: spec.NotTrusted(body.Creds.IDServer),
} }
} else if err != nil { default:
util.GetLogger(req.Context()).WithError(err).Error("threepid.CheckAssociation failed") util.GetLogger(req.Context()).WithError(err).Error("threepid.CheckAssociation failed")
return spec.InternalServerError() return spec.InternalServerError()
} }

View file

@ -68,7 +68,7 @@ func UpgradeRoom(
JSON: spec.Forbidden(e.Error()), JSON: spec.Forbidden(e.Error()),
} }
default: default:
if errors.Is(err, eventutil.ErrRoomNoExists) { if errors.Is(err, eventutil.ErrRoomNoExists{}) {
return util.JSONResponse{ return util.JSONResponse{
Code: http.StatusNotFound, Code: http.StatusNotFound,
JSON: spec.NotFound("Room does not exist"), JSON: spec.NotFound("Room does not exist"),

View file

@ -64,14 +64,34 @@ type idServerStoreInviteResponse struct {
} }
var ( var (
// ErrMissingParameter is the error raised if a request for 3PID invite has errMissingParameter = fmt.Errorf("'address', 'id_server' and 'medium' must all be supplied")
// an incomplete body errNotTrusted = fmt.Errorf("untrusted server")
ErrMissingParameter = errors.New("'address', 'id_server' and 'medium' must all be supplied")
// ErrNotTrusted is the error raised if an identity server isn't in the list
// of trusted servers in the configuration file.
ErrNotTrusted = errors.New("untrusted server")
) )
// ErrMissingParameter is the error raised if a request for 3PID invite has
// an incomplete body
type ErrMissingParameter struct{}
func (e ErrMissingParameter) Error() string {
return errMissingParameter.Error()
}
func (e ErrMissingParameter) Unwrap() error {
return errMissingParameter
}
// ErrNotTrusted is the error raised if an identity server isn't in the list
// of trusted servers in the configuration file.
type ErrNotTrusted struct{}
func (e ErrNotTrusted) Error() string {
return errNotTrusted.Error()
}
func (e ErrNotTrusted) Unwrap() error {
return errNotTrusted
}
// CheckAndProcessInvite analyses the body of an incoming membership request. // CheckAndProcessInvite analyses the body of an incoming membership request.
// If the fields relative to a third-party-invite are all supplied, lookups the // If the fields relative to a third-party-invite are all supplied, lookups the
// matching Matrix ID from the given identity server. If no Matrix ID is // matching Matrix ID from the given identity server. If no Matrix ID is
@ -99,7 +119,7 @@ func CheckAndProcessInvite(
} else if body.Address == "" || body.IDServer == "" || body.Medium == "" { } else if body.Address == "" || body.IDServer == "" || body.Medium == "" {
// If at least one of the 3PID-specific fields is supplied but not all // If at least one of the 3PID-specific fields is supplied but not all
// of them, return an error // of them, return an error
err = ErrMissingParameter err = ErrMissingParameter{}
return return
} }

View file

@ -186,5 +186,5 @@ func isTrusted(idServer string, cfg *config.ClientAPI) error {
return nil return nil
} }
} }
return ErrNotTrusted return ErrNotTrusted{}
} }

View file

@ -119,20 +119,24 @@ func MakeJoin(
RoomVersion: roomVersion, RoomVersion: roomVersion,
} }
event, err := eventutil.QueryAndBuildEvent(httpReq.Context(), proto, cfg.Matrix, identity, time.Now(), rsAPI, &queryRes) event, err := eventutil.QueryAndBuildEvent(httpReq.Context(), proto, cfg.Matrix, identity, time.Now(), rsAPI, &queryRes)
if err == eventutil.ErrRoomNoExists { switch e := err.(type) {
case nil:
case eventutil.ErrRoomNoExists:
util.GetLogger(httpReq.Context()).WithError(err).Error("eventutil.BuildEvent failed")
return nil, nil, &util.JSONResponse{ return nil, nil, &util.JSONResponse{
Code: http.StatusNotFound, Code: http.StatusNotFound,
JSON: spec.NotFound("Room does not exist"), JSON: spec.NotFound("Room does not exist"),
} }
} else if e, ok := err.(gomatrixserverlib.BadJSONError); ok { case gomatrixserverlib.BadJSONError:
util.GetLogger(httpReq.Context()).WithError(err).Error("eventutil.BuildEvent failed")
return nil, nil, &util.JSONResponse{ return nil, nil, &util.JSONResponse{
Code: http.StatusBadRequest, Code: http.StatusBadRequest,
JSON: spec.BadJSON(e.Error()), JSON: spec.BadJSON(e.Error()),
} }
} else if err != nil { default:
util.GetLogger(httpReq.Context()).WithError(err).Error("eventutil.BuildEvent failed") util.GetLogger(httpReq.Context()).WithError(err).Error("eventutil.BuildEvent failed")
e := spec.InternalServerError() internalErr := spec.InternalServerError()
return nil, nil, &e return nil, nil, &internalErr
} }
stateEvents := make([]gomatrixserverlib.PDU, len(queryRes.StateEvents)) stateEvents := make([]gomatrixserverlib.PDU, len(queryRes.StateEvents))

View file

@ -75,17 +75,21 @@ func MakeLeave(
var queryRes api.QueryLatestEventsAndStateResponse var queryRes api.QueryLatestEventsAndStateResponse
event, err := eventutil.QueryAndBuildEvent(httpReq.Context(), &proto, cfg.Matrix, identity, time.Now(), rsAPI, &queryRes) event, err := eventutil.QueryAndBuildEvent(httpReq.Context(), &proto, cfg.Matrix, identity, time.Now(), rsAPI, &queryRes)
if err == eventutil.ErrRoomNoExists { switch e := err.(type) {
case nil:
case eventutil.ErrRoomNoExists:
util.GetLogger(httpReq.Context()).WithError(err).Error("eventutil.BuildEvent failed")
return util.JSONResponse{ return util.JSONResponse{
Code: http.StatusNotFound, Code: http.StatusNotFound,
JSON: spec.NotFound("Room does not exist"), JSON: spec.NotFound("Room does not exist"),
} }
} else if e, ok := err.(gomatrixserverlib.BadJSONError); ok { case gomatrixserverlib.BadJSONError:
util.GetLogger(httpReq.Context()).WithError(err).Error("eventutil.BuildEvent failed")
return util.JSONResponse{ return util.JSONResponse{
Code: http.StatusBadRequest, Code: http.StatusBadRequest,
JSON: spec.BadJSON(e.Error()), JSON: spec.BadJSON(e.Error()),
} }
} else if err != nil { default:
util.GetLogger(httpReq.Context()).WithError(err).Error("eventutil.BuildEvent failed") util.GetLogger(httpReq.Context()).WithError(err).Error("eventutil.BuildEvent failed")
return spec.InternalServerError() return spec.InternalServerError()
} }

View file

@ -31,7 +31,17 @@ import (
// ErrRoomNoExists is returned when trying to lookup the state of a room that // ErrRoomNoExists is returned when trying to lookup the state of a room that
// doesn't exist // doesn't exist
var ErrRoomNoExists = errors.New("room does not exist") var errRoomNoExists = fmt.Errorf("room does not exist")
type ErrRoomNoExists struct{}
func (e ErrRoomNoExists) Error() string {
return errRoomNoExists.Error()
}
func (e ErrRoomNoExists) Unwrap() error {
return errRoomNoExists
}
// QueryAndBuildEvent builds a Matrix event using the event builder and roomserver query // QueryAndBuildEvent builds a Matrix event using the event builder and roomserver query
// API client provided. If also fills roomserver query API response (if provided) // API client provided. If also fills roomserver query API response (if provided)
@ -116,7 +126,7 @@ func addPrevEventsToEvent(
queryRes *api.QueryLatestEventsAndStateResponse, queryRes *api.QueryLatestEventsAndStateResponse,
) error { ) error {
if !queryRes.RoomExists { if !queryRes.RoomExists {
return ErrRoomNoExists return ErrRoomNoExists{}
} }
verImpl, err := gomatrixserverlib.GetRoomVersion(queryRes.RoomVersion) verImpl, err := gomatrixserverlib.GetRoomVersion(queryRes.RoomVersion)

View file

@ -52,7 +52,7 @@ func (r *Admin) PerformAdminEvacuateRoom(
return nil, err return nil, err
} }
if roomInfo == nil || roomInfo.IsStub() { if roomInfo == nil || roomInfo.IsStub() {
return nil, eventutil.ErrRoomNoExists return nil, eventutil.ErrRoomNoExists{}
} }
memberNIDs, err := r.DB.GetMembershipEventNIDsForRoom(ctx, roomInfo.RoomNID, true, true) memberNIDs, err := r.DB.GetMembershipEventNIDsForRoom(ctx, roomInfo.RoomNID, true, true)
@ -240,7 +240,7 @@ func (r *Admin) PerformAdminDownloadState(
} }
if roomInfo == nil || roomInfo.IsStub() { if roomInfo == nil || roomInfo.IsStub() {
return eventutil.ErrRoomNoExists return eventutil.ErrRoomNoExists{}
} }
fwdExtremities, _, depth, err := r.DB.LatestEventIDs(ctx, roomInfo.RoomNID) fwdExtremities, _, depth, err := r.DB.LatestEventIDs(ctx, roomInfo.RoomNID)

View file

@ -286,7 +286,7 @@ func (r *Joiner) performJoinRoomByID(
} }
event, err := eventutil.QueryAndBuildEvent(ctx, &proto, r.Cfg.Matrix, identity, time.Now(), r.RSAPI, &buildRes) event, err := eventutil.QueryAndBuildEvent(ctx, &proto, r.Cfg.Matrix, identity, time.Now(), r.RSAPI, &buildRes)
switch err { switch err.(type) {
case nil: case nil:
// The room join is local. Send the new join event into the // The room join is local. Send the new join event into the
// roomserver. First of all check that the user isn't already // roomserver. First of all check that the user isn't already
@ -328,7 +328,7 @@ func (r *Joiner) performJoinRoomByID(
// Otherwise we'll try a federated join as normal, since it's quite // Otherwise we'll try a federated join as normal, since it's quite
// possible that the room still exists on other servers. // possible that the room still exists on other servers.
if len(req.ServerNames) == 0 { if len(req.ServerNames) == 0 {
return "", "", eventutil.ErrRoomNoExists return "", "", eventutil.ErrRoomNoExists{}
} }
} }

View file

@ -274,7 +274,7 @@ func publishNewRoomAndUnpublishOldRoom(
func (r *Upgrader) validateRoomExists(ctx context.Context, roomID string) error { func (r *Upgrader) validateRoomExists(ctx context.Context, roomID string) error {
if _, err := r.URSAPI.QueryRoomVersionForRoom(ctx, roomID); err != nil { if _, err := r.URSAPI.QueryRoomVersionForRoom(ctx, roomID); err != nil {
return eventutil.ErrRoomNoExists return eventutil.ErrRoomNoExists{}
} }
return nil return nil
} }
@ -556,15 +556,18 @@ func (r *Upgrader) makeHeaderedEvent(ctx context.Context, evTime time.Time, user
} }
var queryRes api.QueryLatestEventsAndStateResponse var queryRes api.QueryLatestEventsAndStateResponse
headeredEvent, err := eventutil.QueryAndBuildEvent(ctx, &proto, r.Cfg.Matrix, identity, evTime, r.URSAPI, &queryRes) headeredEvent, err := eventutil.QueryAndBuildEvent(ctx, &proto, r.Cfg.Matrix, identity, evTime, r.URSAPI, &queryRes)
if err == eventutil.ErrRoomNoExists { switch e := err.(type) {
return nil, err case nil:
} else if e, ok := err.(gomatrixserverlib.BadJSONError); ok { case eventutil.ErrRoomNoExists:
return nil, e return nil, e
} else if e, ok := err.(gomatrixserverlib.EventValidationError); ok { case gomatrixserverlib.BadJSONError:
return nil, e return nil, e
} else if err != nil { case gomatrixserverlib.EventValidationError:
return nil, e
default:
return nil, fmt.Errorf("failed to build new %q event: %w", proto.Type, err) return nil, fmt.Errorf("failed to build new %q event: %w", proto.Type, err)
} }
// check to see if this user can perform this operation // check to see if this user can perform this operation
stateEvents := make([]gomatrixserverlib.PDU, len(queryRes.StateEvents)) stateEvents := make([]gomatrixserverlib.PDU, len(queryRes.StateEvents))
for i := range queryRes.StateEvents { for i := range queryRes.StateEvents {