Use standard errors instead of JSON responses in threepid

This commit is contained in:
Brendan Abolivier 2017-09-07 16:55:59 +01:00
parent bdc71b4757
commit ba221c41c5
No known key found for this signature in database
GPG key ID: 8EF1500759F70623
4 changed files with 65 additions and 58 deletions

View file

@ -65,8 +65,13 @@ func RequestEmailToken(req *http.Request, accountDB *accounts.Database, cfg conf
} }
resp.SID, err = threepid.CreateSession(body, cfg) resp.SID, err = threepid.CreateSession(body, cfg)
if err != nil { if err == threepid.ErrNotTrusted {
return threepid.ProcessIDServerError(req, err) return util.JSONResponse{
Code: 400,
JSON: jsonerror.NotTrusted(body.IDServer),
}
} else if err != nil {
return httputil.LogThenError(req, err)
} }
return util.JSONResponse{ return util.JSONResponse{
@ -87,8 +92,13 @@ func CheckAndSave3PIDAssociation(
// Check if the association has been validated // Check if the association has been validated
verified, address, medium, err := threepid.CheckAssociation(body.Creds, cfg) verified, address, medium, err := threepid.CheckAssociation(body.Creds, cfg)
if err != nil { if err == threepid.ErrNotTrusted {
return threepid.ProcessIDServerError(req, err) return util.JSONResponse{
Code: 400,
JSON: jsonerror.NotTrusted(body.Creds.IDServer),
}
} else if err != nil {
return httputil.LogThenError(req, err)
} }
if !verified { if !verified {
@ -103,8 +113,14 @@ func CheckAndSave3PIDAssociation(
if body.Bind { if body.Bind {
// Publish the association on the identity server if requested // Publish the association on the identity server if requested
if err = threepid.PublishAssociation(body.Creds, device.UserID, cfg); err != nil { err = threepid.PublishAssociation(body.Creds, device.UserID, cfg)
return threepid.ProcessIDServerError(req, err) if err == threepid.ErrNotTrusted {
return util.JSONResponse{
Code: 400,
JSON: jsonerror.NotTrusted(body.Creds.IDServer),
}
} else if err != nil {
return httputil.LogThenError(req, err)
} }
} }

View file

@ -26,15 +26,11 @@ import (
"github.com/matrix-org/dendrite/clientapi/auth/authtypes" "github.com/matrix-org/dendrite/clientapi/auth/authtypes"
"github.com/matrix-org/dendrite/clientapi/auth/storage/accounts" "github.com/matrix-org/dendrite/clientapi/auth/storage/accounts"
"github.com/matrix-org/dendrite/clientapi/events" "github.com/matrix-org/dendrite/clientapi/events"
"github.com/matrix-org/dendrite/clientapi/httputil"
"github.com/matrix-org/dendrite/clientapi/jsonerror"
"github.com/matrix-org/dendrite/clientapi/producers" "github.com/matrix-org/dendrite/clientapi/producers"
"github.com/matrix-org/dendrite/common" "github.com/matrix-org/dendrite/common"
"github.com/matrix-org/dendrite/common/config" "github.com/matrix-org/dendrite/common/config"
"github.com/matrix-org/dendrite/roomserver/api" "github.com/matrix-org/dendrite/roomserver/api"
"github.com/matrix-org/gomatrixserverlib" "github.com/matrix-org/gomatrixserverlib"
"github.com/matrix-org/util"
) )
// MembershipRequest represents the body of an incoming POST request // MembershipRequest represents the body of an incoming POST request
@ -66,22 +62,10 @@ type idServerStoreInviteResponse struct {
PublicKeys []common.PublicKey `json:"public_keys"` PublicKeys []common.PublicKey `json:"public_keys"`
} }
// ProcessIDServerError differentiate errors caused by the absence of the identity var (
// server in the list of trusted servers in the configuration file from normal ErrMissingParameter = errors.New("'address', 'id_server' and 'medium' must all be supplied")
// errors caused by a failure in a process. ErrNotTrusted = errors.New("Untrusted server")
// Returns the representation of a 400 error in the former case (without logging), )
// and the one of a 500 error in the latter (with logging of the error).
func ProcessIDServerError(req *http.Request, err error) util.JSONResponse {
// Check whether this is an
mErr, ok := err.(*jsonerror.MatrixError)
if !ok || mErr.ErrCode != "M_SERVER_NOT_TRUSTED" {
return httputil.LogThenError(req, err)
}
return util.JSONResponse{
Code: 400,
JSON: mErr,
}
}
// 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
@ -100,24 +84,21 @@ func CheckAndProcessInvite(
req *http.Request, device *authtypes.Device, body *MembershipRequest, req *http.Request, device *authtypes.Device, body *MembershipRequest,
cfg config.Dendrite, queryAPI api.RoomserverQueryAPI, db *accounts.Database, cfg config.Dendrite, queryAPI api.RoomserverQueryAPI, db *accounts.Database,
producer *producers.RoomserverProducer, membership string, roomID string, producer *producers.RoomserverProducer, membership string, roomID string,
) *util.JSONResponse { ) (inviteStoredOnIDServer bool, err error) {
if membership != "invite" || (body.Address == "" && body.IDServer == "" && body.Medium == "") { if membership != "invite" || (body.Address == "" && body.IDServer == "" && body.Medium == "") {
// If none of the 3PID-specific fields are supplied, it's a standard invite // If none of the 3PID-specific fields are supplied, it's a standard invite
// so return nil for it to be processed as such // so return nil for it to be processed as such
return nil return
} 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
return &util.JSONResponse{ err = ErrMissingParameter
Code: 400, return
JSON: jsonerror.BadJSON("'address', 'id_server' and 'medium' must all be supplied"),
}
} }
lookupRes, storeInviteRes, err := queryIDServer(req, db, cfg, device, body, roomID) lookupRes, storeInviteRes, err := queryIDServer(req, db, cfg, device, body, roomID)
if err != nil { if err != nil {
resErr := ProcessIDServerError(req, err) return
return &resErr
} }
if lookupRes.MXID == "" { if lookupRes.MXID == "" {
@ -125,28 +106,16 @@ func CheckAndProcessInvite(
// "m.room.third_party_invite" have to be emitted from the data in // "m.room.third_party_invite" have to be emitted from the data in
// storeInviteRes. // storeInviteRes.
err = emit3PIDInviteEvent(body, storeInviteRes, device, roomID, cfg, queryAPI, producer) err = emit3PIDInviteEvent(body, storeInviteRes, device, roomID, cfg, queryAPI, producer)
if err == events.ErrRoomNoExists { inviteStoredOnIDServer = err == nil
return &util.JSONResponse{
Code: 404,
JSON: jsonerror.NotFound(err.Error()),
}
} else if err != nil {
resErr := httputil.LogThenError(req, err)
return &resErr
}
// If everything went well, returns with an empty response. return
return &util.JSONResponse{
Code: 200,
JSON: struct{}{},
}
} }
// A Matrix ID have been found: set it in the body request and let the process // A Matrix ID have been found: set it in the body request and let the process
// continue to create a "m.room.member" event with an "invite" membership // continue to create a "m.room.member" event with an "invite" membership
body.UserID = lookupRes.MXID body.UserID = lookupRes.MXID
return nil return
} }
// queryIDServer handles all the requests to the identity server, starting by // queryIDServer handles all the requests to the identity server, starting by
@ -163,7 +132,7 @@ func queryIDServer(
device *authtypes.Device, body *MembershipRequest, roomID string, device *authtypes.Device, body *MembershipRequest, roomID string,
) (lookupRes *idServerLookupResponse, storeInviteRes *idServerStoreInviteResponse, err error) { ) (lookupRes *idServerLookupResponse, storeInviteRes *idServerStoreInviteResponse, err error) {
if err = isTrusted(body.IDServer, cfg); err != nil { if err = isTrusted(body.IDServer, cfg); err != nil {
return nil, nil, err return
} }
// Lookup the 3PID // Lookup the 3PID
@ -270,7 +239,6 @@ func queryIDServerStoreInvite(
} }
if resp.StatusCode != http.StatusOK { if resp.StatusCode != http.StatusOK {
// TODO: Log the error supplied with the identity server?
errMsg := fmt.Sprintf("Identity server %s responded with a %d error code", body.IDServer, resp.StatusCode) errMsg := fmt.Sprintf("Identity server %s responded with a %d error code", body.IDServer, resp.StatusCode)
return nil, errors.New(errMsg) return nil, errors.New(errMsg)
} }
@ -296,7 +264,6 @@ func queryIDServerPubKey(idServerName string, keyID string) ([]byte, error) {
} }
if resp.StatusCode != http.StatusOK { if resp.StatusCode != http.StatusOK {
// TODO: Log the error supplied with the identity server?
errMsg := fmt.Sprintf("Couldn't retrieve key %s from server %s", keyID, idServerName) errMsg := fmt.Sprintf("Couldn't retrieve key %s from server %s", keyID, idServerName)
return nil, errors.New(errMsg) return nil, errors.New(errMsg)
} }
@ -318,7 +285,6 @@ func checkIDServerSignatures(body *MembershipRequest, res *idServerLookupRespons
return err return err
} }
// TODO: Check if the domain is part of a list of trusted ID servers
signatures, ok := res.Signatures[body.IDServer] signatures, ok := res.Signatures[body.IDServer]
if !ok { if !ok {
return errors.New("No signature for domain " + body.IDServer) return errors.New("No signature for domain " + body.IDServer)

View file

@ -23,7 +23,6 @@ import (
"strconv" "strconv"
"strings" "strings"
"github.com/matrix-org/dendrite/clientapi/jsonerror"
"github.com/matrix-org/dendrite/common/config" "github.com/matrix-org/dendrite/common/config"
) )
@ -175,5 +174,5 @@ func isTrusted(idServer string, cfg config.Dendrite) error {
return nil return nil
} }
} }
return jsonerror.NotTrusted(idServer) return ErrNotTrusted
} }

View file

@ -47,10 +47,36 @@ func SendMembership(
return *reqErr return *reqErr
} }
if res := threepid.CheckAndProcessInvite( inviteStored, err := threepid.CheckAndProcessInvite(
req, device, &body, cfg, queryAPI, accountDB, producer, membership, roomID, req, device, &body, cfg, queryAPI, accountDB, producer, membership, roomID,
); res != nil { )
return *res if err == threepid.ErrMissingParameter {
return util.JSONResponse{
Code: 400,
JSON: jsonerror.BadJSON(err.Error()),
}
} else if err == threepid.ErrNotTrusted {
return util.JSONResponse{
Code: 400,
JSON: jsonerror.NotTrusted(body.IDServer),
}
} else if err == events.ErrRoomNoExists {
return util.JSONResponse{
Code: 404,
JSON: jsonerror.NotFound(err.Error()),
}
} else if err != nil {
return httputil.LogThenError(req, err)
}
// If an invite has been stored on an identity server, it means that a
// m.room.third_party_invite event has been emitted and that we shouldn't
// emit a m.room.member one.
if inviteStored {
return util.JSONResponse{
Code: 200,
JSON: struct{}{},
}
} }
event, err := buildMembershipEvent( event, err := buildMembershipEvent(