From a880fdea82a0cf144056d715af6c49c467def7ef Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Thu, 1 Oct 2015 14:45:36 -0700 Subject: [PATCH] Errors package --- api/characteristics.go | 47 +++++++++++++++++----------------- api/helpers.go | 10 ++++++++ api/measurements.go | 29 +++++++++++---------- api/species.go | 31 +++++++++++----------- api/strains.go | 41 ++++++++++++++--------------- api/users.go | 54 ++++++++++++++++++--------------------- errors/auth.go | 7 +++++ errors/characteristics.go | 8 ++++++ errors/helpers.go | 7 +++++ errors/measurements.go | 7 +++++ errors/species.go | 8 ++++++ errors/strains.go | 8 ++++++ errors/types.go | 7 +++++ errors/users.go | 11 ++++++++ handlers/handlers.go | 30 +++++++++++----------- handlers/helpers.go | 10 ++++++++ helpers/helpers.go | 3 --- models/characteristics.go | 9 ++----- models/measurements.go | 10 ++------ models/species.go | 9 ++----- models/strains.go | 9 ++----- models/users.go | 17 ++++-------- types/error_json.go | 7 ----- types/null_slice_int64.go | 5 ++-- 24 files changed, 215 insertions(+), 169 deletions(-) create mode 100644 api/helpers.go create mode 100644 errors/auth.go create mode 100644 errors/characteristics.go create mode 100644 errors/helpers.go create mode 100644 errors/measurements.go create mode 100644 errors/species.go create mode 100644 errors/strains.go create mode 100644 errors/types.go create mode 100644 errors/users.go create mode 100644 handlers/helpers.go diff --git a/api/characteristics.go b/api/characteristics.go index 8727a00..d210a16 100644 --- a/api/characteristics.go +++ b/api/characteristics.go @@ -5,6 +5,7 @@ import ( "net/http" "net/url" + "github.com/thermokarst/bactdb/errors" "github.com/thermokarst/bactdb/helpers" "github.com/thermokarst/bactdb/models" "github.com/thermokarst/bactdb/payloads" @@ -21,46 +22,46 @@ func (c CharacteristicService) Unmarshal(b []byte) (types.Entity, error) { func (c CharacteristicService) List(val *url.Values, claims *types.Claims) (types.Entity, *types.AppError) { if val == nil { - return nil, helpers.ErrMustProvideOptionsJSON + return nil, NewJSONError(errors.MustProvideOptions, http.StatusInternalServerError) } var opt helpers.ListOptions if err := helpers.SchemaDecoder.Decode(&opt, *val); err != nil { - return nil, types.NewJSONError(err, http.StatusInternalServerError) + return nil, NewJSONError(err, http.StatusInternalServerError) } characteristics, err := models.ListCharacteristics(opt, claims) if err != nil { - return nil, types.NewJSONError(err, http.StatusInternalServerError) + return nil, NewJSONError(err, http.StatusInternalServerError) } strains_opt, err := models.StrainOptsFromCharacteristics(opt) if err != nil { - return nil, types.NewJSONError(err, http.StatusInternalServerError) + return nil, NewJSONError(err, http.StatusInternalServerError) } strains, err := models.ListStrains(*strains_opt, claims) if err != nil { - return nil, types.NewJSONError(err, http.StatusInternalServerError) + return nil, NewJSONError(err, http.StatusInternalServerError) } species_opt, err := models.SpeciesOptsFromStrains(*strains_opt) if err != nil { - return nil, types.NewJSONError(err, http.StatusInternalServerError) + return nil, NewJSONError(err, http.StatusInternalServerError) } species, err := models.ListSpecies(*species_opt, claims) if err != nil { - return nil, types.NewJSONError(err, http.StatusInternalServerError) + return nil, NewJSONError(err, http.StatusInternalServerError) } measurements_opt, err := models.MeasurementOptsFromCharacteristics(opt) if err != nil { - return nil, types.NewJSONError(err, http.StatusInternalServerError) + return nil, NewJSONError(err, http.StatusInternalServerError) } measurements, err := models.ListMeasurements(*measurements_opt, claims) if err != nil { - return nil, types.NewJSONError(err, http.StatusInternalServerError) + return nil, NewJSONError(err, http.StatusInternalServerError) } payload := payloads.Characteristics{ @@ -79,27 +80,27 @@ func (c CharacteristicService) List(val *url.Values, claims *types.Claims) (type func (c CharacteristicService) Get(id int64, genus string, claims *types.Claims) (types.Entity, *types.AppError) { characteristic, err := models.GetCharacteristic(id, genus, claims) if err != nil { - return nil, types.NewJSONError(err, http.StatusInternalServerError) + return nil, NewJSONError(err, http.StatusInternalServerError) } strains, strain_opts, err := models.StrainsFromCharacteristicId(id, genus, claims) if err != nil { - return nil, types.NewJSONError(err, http.StatusInternalServerError) + return nil, NewJSONError(err, http.StatusInternalServerError) } species_opt, err := models.SpeciesOptsFromStrains(*strain_opts) if err != nil { - return nil, types.NewJSONError(err, http.StatusInternalServerError) + return nil, NewJSONError(err, http.StatusInternalServerError) } species, err := models.ListSpecies(*species_opt, claims) if err != nil { - return nil, types.NewJSONError(err, http.StatusInternalServerError) + return nil, NewJSONError(err, http.StatusInternalServerError) } measurements, _, err := models.MeasurementsFromCharacteristicId(id, genus, claims) if err != nil { - return nil, types.NewJSONError(err, http.StatusInternalServerError) + return nil, NewJSONError(err, http.StatusInternalServerError) } payload := payloads.Characteristic{ @@ -120,7 +121,7 @@ func (c CharacteristicService) Update(id int64, e *types.Entity, genus string, c // First, handle Characteristic Type id, err := models.InsertOrGetCharacteristicType(payload.Characteristic.CharacteristicType, claims) if err != nil { - return types.NewJSONError(err, http.StatusInternalServerError) + return NewJSONError(err, http.StatusInternalServerError) } payload.Characteristic.CanEdit = helpers.CanEdit(claims, payload.Characteristic.CreatedBy) @@ -129,26 +130,26 @@ func (c CharacteristicService) Update(id int64, e *types.Entity, genus string, c // TODO: fix this count, err := models.DBH.Update(payload.Characteristic.CharacteristicBase) if err != nil { - return types.NewJSONError(err, http.StatusInternalServerError) + return NewJSONError(err, http.StatusInternalServerError) } if count != 1 { // TODO: fix this - return types.NewJSONError(models.ErrCharacteristicNotUpdated, http.StatusBadRequest) + return NewJSONError(errors.CharacteristicNotUpdated, http.StatusBadRequest) } strains, strain_opts, err := models.StrainsFromCharacteristicId(id, genus, claims) if err != nil { - return types.NewJSONError(err, http.StatusInternalServerError) + return NewJSONError(err, http.StatusInternalServerError) } species_opt, err := models.SpeciesOptsFromStrains(*strain_opts) if err != nil { - return types.NewJSONError(err, http.StatusInternalServerError) + return NewJSONError(err, http.StatusInternalServerError) } species, err := models.ListSpecies(*species_opt, claims) if err != nil { - return types.NewJSONError(err, http.StatusInternalServerError) + return NewJSONError(err, http.StatusInternalServerError) } payload.Strains = strains @@ -166,19 +167,19 @@ func (c CharacteristicService) Create(e *types.Entity, genus string, claims *typ id, err := models.InsertOrGetCharacteristicType(payload.Characteristic.CharacteristicType, claims) if err != nil { - return types.NewJSONError(err, http.StatusInternalServerError) + return NewJSONError(err, http.StatusInternalServerError) } payload.Characteristic.CharacteristicTypeId = id // TODO: fix this err = models.DBH.Insert(payload.Characteristic.CharacteristicBase) if err != nil { - return types.NewJSONError(err, http.StatusInternalServerError) + return NewJSONError(err, http.StatusInternalServerError) } characteristic, err := models.GetCharacteristic(payload.Characteristic.Id, genus, claims) if err != nil { - return types.NewJSONError(err, http.StatusInternalServerError) + return NewJSONError(err, http.StatusInternalServerError) } payload.Characteristic = characteristic diff --git a/api/helpers.go b/api/helpers.go new file mode 100644 index 0000000..f6c0317 --- /dev/null +++ b/api/helpers.go @@ -0,0 +1,10 @@ +package api + +import "github.com/thermokarst/bactdb/types" + +func NewJSONError(err error, status int) *types.AppError { + return &types.AppError{ + Error: types.ErrorJSON{Err: err}, + Status: status, + } +} diff --git a/api/measurements.go b/api/measurements.go index d09c38c..0e708b6 100644 --- a/api/measurements.go +++ b/api/measurements.go @@ -5,6 +5,7 @@ import ( "net/http" "net/url" + "github.com/thermokarst/bactdb/errors" "github.com/thermokarst/bactdb/helpers" "github.com/thermokarst/bactdb/models" "github.com/thermokarst/bactdb/payloads" @@ -21,36 +22,36 @@ func (s MeasurementService) Unmarshal(b []byte) (types.Entity, error) { func (m MeasurementService) List(val *url.Values, claims *types.Claims) (types.Entity, *types.AppError) { if val == nil { - return nil, helpers.ErrMustProvideOptionsJSON + return nil, NewJSONError(errors.MustProvideOptions, http.StatusInternalServerError) } var opt helpers.MeasurementListOptions if err := helpers.SchemaDecoder.Decode(&opt, *val); err != nil { - return nil, types.NewJSONError(err, http.StatusInternalServerError) + return nil, NewJSONError(err, http.StatusInternalServerError) } measurements, err := models.ListMeasurements(opt, claims) if err != nil { - return nil, types.NewJSONError(err, http.StatusInternalServerError) + return nil, NewJSONError(err, http.StatusInternalServerError) } char_opts, err := models.CharacteristicOptsFromMeasurements(opt) if err != nil { - return nil, types.NewJSONError(err, http.StatusInternalServerError) + return nil, NewJSONError(err, http.StatusInternalServerError) } characteristics, err := models.ListCharacteristics(*char_opts, claims) if err != nil { - return nil, types.NewJSONError(err, http.StatusInternalServerError) + return nil, NewJSONError(err, http.StatusInternalServerError) } strain_opts, err := models.StrainOptsFromMeasurements(opt) if err != nil { - return nil, types.NewJSONError(err, http.StatusInternalServerError) + return nil, NewJSONError(err, http.StatusInternalServerError) } strains, err := models.ListStrains(*strain_opts, claims) if err != nil { - return nil, types.NewJSONError(err, http.StatusInternalServerError) + return nil, NewJSONError(err, http.StatusInternalServerError) } payload := payloads.Measurements{ @@ -65,7 +66,7 @@ func (m MeasurementService) List(val *url.Values, claims *types.Claims) (types.E func (m MeasurementService) Get(id int64, genus string, claims *types.Claims) (types.Entity, *types.AppError) { measurement, err := models.GetMeasurement(id, genus, claims) if err != nil { - return nil, types.NewJSONError(err, http.StatusInternalServerError) + return nil, NewJSONError(err, http.StatusInternalServerError) } payload := payloads.Measurement{ @@ -83,7 +84,7 @@ func (s MeasurementService) Update(id int64, e *types.Entity, genus string, clai if payload.Measurement.TextMeasurementType.Valid { id, err := models.GetTextMeasurementTypeId(payload.Measurement.TextMeasurementType.String) if err != nil { - return types.NewJSONError(err, http.StatusInternalServerError) + return NewJSONError(err, http.StatusInternalServerError) } payload.Measurement.TextMeasurementTypeId.Int64 = id payload.Measurement.TextMeasurementTypeId.Valid = true @@ -92,16 +93,16 @@ func (s MeasurementService) Update(id int64, e *types.Entity, genus string, clai // TODO: fix this count, err := models.DBH.Update(payload.Measurement.MeasurementBase) if err != nil { - return types.NewJSONError(err, http.StatusInternalServerError) + return NewJSONError(err, http.StatusInternalServerError) } if count != 1 { // TODO: fix this - return types.NewJSONError(models.ErrStrainNotUpdated, http.StatusBadRequest) + return NewJSONError(errors.StrainNotUpdated, http.StatusBadRequest) } measurement, err := models.GetMeasurement(id, genus, claims) if err != nil { - return types.NewJSONError(err, http.StatusInternalServerError) + return NewJSONError(err, http.StatusInternalServerError) } payload.Measurement = measurement @@ -114,7 +115,7 @@ func (m MeasurementService) Delete(id int64, genus string, claims *types.Claims) // TODO: fix this _, err := models.DBH.Exec(q, id) if err != nil { - return types.NewJSONError(err, http.StatusInternalServerError) + return NewJSONError(err, http.StatusInternalServerError) } return nil } @@ -126,7 +127,7 @@ func (m MeasurementService) Create(e *types.Entity, genus string, claims *types. // TODO: fix this if err := models.DBH.Insert(payload.Measurement.MeasurementBase); err != nil { - return types.NewJSONError(err, http.StatusInternalServerError) + return NewJSONError(err, http.StatusInternalServerError) } return nil diff --git a/api/species.go b/api/species.go index 23950db..fc4ea36 100644 --- a/api/species.go +++ b/api/species.go @@ -5,6 +5,7 @@ import ( "net/http" "net/url" + "github.com/thermokarst/bactdb/errors" "github.com/thermokarst/bactdb/helpers" "github.com/thermokarst/bactdb/models" "github.com/thermokarst/bactdb/payloads" @@ -21,26 +22,26 @@ func (s SpeciesService) Unmarshal(b []byte) (types.Entity, error) { func (s SpeciesService) List(val *url.Values, claims *types.Claims) (types.Entity, *types.AppError) { if val == nil { - return nil, helpers.ErrMustProvideOptionsJSON + return nil, NewJSONError(errors.MustProvideOptions, http.StatusInternalServerError) } var opt helpers.ListOptions if err := helpers.SchemaDecoder.Decode(&opt, *val); err != nil { - return nil, types.NewJSONError(err, http.StatusInternalServerError) + return nil, NewJSONError(err, http.StatusInternalServerError) } species, err := models.ListSpecies(opt, claims) if err != nil { - return nil, types.NewJSONError(err, http.StatusInternalServerError) + return nil, NewJSONError(err, http.StatusInternalServerError) } strains_opt, err := models.StrainOptsFromSpecies(opt) if err != nil { - return nil, types.NewJSONError(err, http.StatusInternalServerError) + return nil, NewJSONError(err, http.StatusInternalServerError) } strains, err := models.ListStrains(*strains_opt, claims) if err != nil { - return nil, types.NewJSONError(err, http.StatusInternalServerError) + return nil, NewJSONError(err, http.StatusInternalServerError) } payload := payloads.ManySpecies{ @@ -57,12 +58,12 @@ func (s SpeciesService) List(val *url.Values, claims *types.Claims) (types.Entit func (s SpeciesService) Get(id int64, genus string, claims *types.Claims) (types.Entity, *types.AppError) { species, err := models.GetSpecies(id, genus, claims) if err != nil { - return nil, types.NewJSONError(err, http.StatusInternalServerError) + return nil, NewJSONError(err, http.StatusInternalServerError) } strains, err := models.StrainsFromSpeciesId(id, genus, claims) if err != nil { - return nil, types.NewJSONError(err, http.StatusInternalServerError) + return nil, NewJSONError(err, http.StatusInternalServerError) } payload := payloads.Species{ @@ -83,29 +84,29 @@ func (s SpeciesService) Update(id int64, e *types.Entity, genus string, claims * genus_id, err := models.GenusIdFromName(genus) if err != nil { - return types.NewJSONError(err, http.StatusInternalServerError) + return NewJSONError(err, http.StatusInternalServerError) } payload.Species.SpeciesBase.GenusID = genus_id // TODO: fix this count, err := models.DBH.Update(payload.Species.SpeciesBase) if err != nil { - return types.NewJSONError(err, http.StatusInternalServerError) + return NewJSONError(err, http.StatusInternalServerError) } if count != 1 { // TODO: fix this - return types.NewJSONError(models.ErrSpeciesNotUpdated, http.StatusBadRequest) + return NewJSONError(errors.SpeciesNotUpdated, http.StatusBadRequest) } // Reload to send back down the wire species, err := models.GetSpecies(id, genus, claims) if err != nil { - return types.NewJSONError(err, http.StatusInternalServerError) + return NewJSONError(err, http.StatusInternalServerError) } strains, err := models.StrainsFromSpeciesId(id, genus, claims) if err != nil { - return types.NewJSONError(err, http.StatusInternalServerError) + return NewJSONError(err, http.StatusInternalServerError) } payload.Species = species @@ -124,20 +125,20 @@ func (s SpeciesService) Create(e *types.Entity, genus string, claims *types.Clai genus_id, err := models.GenusIdFromName(genus) if err != nil { - return types.NewJSONError(err, http.StatusInternalServerError) + return NewJSONError(err, http.StatusInternalServerError) } payload.Species.SpeciesBase.GenusID = genus_id // TODO: fix this err = models.DBH.Insert(payload.Species.SpeciesBase) if err != nil { - return types.NewJSONError(err, http.StatusInternalServerError) + return NewJSONError(err, http.StatusInternalServerError) } // Reload to send back down the wire species, err := models.GetSpecies(payload.Species.Id, genus, claims) if err != nil { - return types.NewJSONError(err, http.StatusInternalServerError) + return NewJSONError(err, http.StatusInternalServerError) } // Note, no strains when new species diff --git a/api/strains.go b/api/strains.go index 1233230..bb3ad22 100644 --- a/api/strains.go +++ b/api/strains.go @@ -5,6 +5,7 @@ import ( "net/http" "net/url" + "github.com/thermokarst/bactdb/errors" "github.com/thermokarst/bactdb/helpers" "github.com/thermokarst/bactdb/models" "github.com/thermokarst/bactdb/payloads" @@ -21,36 +22,36 @@ func (s StrainService) Unmarshal(b []byte) (types.Entity, error) { func (s StrainService) List(val *url.Values, claims *types.Claims) (types.Entity, *types.AppError) { if val == nil { - return nil, helpers.ErrMustProvideOptionsJSON + return nil, NewJSONError(errors.MustProvideOptions, http.StatusInternalServerError) } var opt helpers.ListOptions if err := helpers.SchemaDecoder.Decode(&opt, *val); err != nil { - return nil, types.NewJSONError(err, http.StatusInternalServerError) + return nil, NewJSONError(err, http.StatusInternalServerError) } strains, err := models.ListStrains(opt, claims) if err != nil { - return nil, types.NewJSONError(err, http.StatusInternalServerError) + return nil, NewJSONError(err, http.StatusInternalServerError) } species_opt, err := models.SpeciesOptsFromStrains(opt) if err != nil { - return nil, types.NewJSONError(err, http.StatusInternalServerError) + return nil, NewJSONError(err, http.StatusInternalServerError) } species, err := models.ListSpecies(*species_opt, claims) if err != nil { - return nil, types.NewJSONError(err, http.StatusInternalServerError) + return nil, NewJSONError(err, http.StatusInternalServerError) } characteristics_opt, err := models.CharacteristicsOptsFromStrains(opt) if err != nil { - return nil, types.NewJSONError(err, http.StatusInternalServerError) + return nil, NewJSONError(err, http.StatusInternalServerError) } characteristics, err := models.ListCharacteristics(*characteristics_opt, claims) if err != nil { - return nil, types.NewJSONError(err, http.StatusInternalServerError) + return nil, NewJSONError(err, http.StatusInternalServerError) } characteristic_ids := []int64{} @@ -73,7 +74,7 @@ func (s StrainService) List(val *url.Values, claims *types.Claims) (types.Entity measurements, err := models.ListMeasurements(measurement_opt, claims) if err != nil { - return nil, types.NewJSONError(err, http.StatusInternalServerError) + return nil, NewJSONError(err, http.StatusInternalServerError) } payload := payloads.Strains{ @@ -92,23 +93,23 @@ func (s StrainService) List(val *url.Values, claims *types.Claims) (types.Entity func (s StrainService) Get(id int64, genus string, claims *types.Claims) (types.Entity, *types.AppError) { strain, err := models.GetStrain(id, genus, claims) if err != nil { - return nil, types.NewJSONError(err, http.StatusInternalServerError) + return nil, NewJSONError(err, http.StatusInternalServerError) } species, err := models.GetSpecies(strain.SpeciesId, genus, claims) if err != nil { - return nil, types.NewJSONError(err, http.StatusInternalServerError) + return nil, NewJSONError(err, http.StatusInternalServerError) } opt := helpers.ListOptions{Genus: genus, Ids: []int64{id}} characteristics_opt, err := models.CharacteristicsOptsFromStrains(opt) if err != nil { - return nil, types.NewJSONError(err, http.StatusInternalServerError) + return nil, NewJSONError(err, http.StatusInternalServerError) } characteristics, err := models.ListCharacteristics(*characteristics_opt, claims) if err != nil { - return nil, types.NewJSONError(err, http.StatusInternalServerError) + return nil, NewJSONError(err, http.StatusInternalServerError) } characteristic_ids := []int64{} @@ -126,7 +127,7 @@ func (s StrainService) Get(id int64, genus string, claims *types.Claims) (types. measurements, err := models.ListMeasurements(measurement_opt, claims) if err != nil { - return nil, types.NewJSONError(err, http.StatusInternalServerError) + return nil, NewJSONError(err, http.StatusInternalServerError) } var many_species models.ManySpecies = []*models.Species{species} @@ -152,21 +153,21 @@ func (s StrainService) Update(id int64, e *types.Entity, genus string, claims *t // TODO: fix this count, err := models.DBH.Update(payload.Strain.StrainBase) if err != nil { - return types.NewJSONError(err, http.StatusInternalServerError) + return NewJSONError(err, http.StatusInternalServerError) } if count != 1 { // TODO: fix this - return types.NewJSONError(models.ErrStrainNotUpdated, http.StatusBadRequest) + return NewJSONError(errors.StrainNotUpdated, http.StatusBadRequest) } strain, err := models.GetStrain(id, genus, claims) if err != nil { - return types.NewJSONError(err, http.StatusInternalServerError) + return NewJSONError(err, http.StatusInternalServerError) } species, err := models.GetSpecies(strain.SpeciesId, genus, claims) if err != nil { - return types.NewJSONError(err, http.StatusInternalServerError) + return NewJSONError(err, http.StatusInternalServerError) } var many_species models.ManySpecies = []*models.Species{species} @@ -187,17 +188,17 @@ func (s StrainService) Create(e *types.Entity, genus string, claims *types.Claim // TODO: fix this if err := models.DBH.Insert(payload.Strain.StrainBase); err != nil { - return types.NewJSONError(err, http.StatusInternalServerError) + return NewJSONError(err, http.StatusInternalServerError) } strain, err := models.GetStrain(payload.Strain.Id, genus, claims) if err != nil { - return types.NewJSONError(err, http.StatusInternalServerError) + return NewJSONError(err, http.StatusInternalServerError) } species, err := models.GetSpecies(strain.SpeciesId, genus, claims) if err != nil { - return types.NewJSONError(err, http.StatusInternalServerError) + return NewJSONError(err, http.StatusInternalServerError) } var many_species models.ManySpecies = []*models.Species{species} diff --git a/api/users.go b/api/users.go index 45ac7ac..d0053ed 100644 --- a/api/users.go +++ b/api/users.go @@ -2,7 +2,6 @@ package api import ( "encoding/json" - "errors" "fmt" "log" "net/http" @@ -13,6 +12,7 @@ import ( "github.com/thermokarst/bactdb/Godeps/_workspace/src/github.com/mailgun/mailgun-go" "github.com/thermokarst/bactdb/Godeps/_workspace/src/golang.org/x/crypto/bcrypt" "github.com/thermokarst/bactdb/auth" + "github.com/thermokarst/bactdb/errors" "github.com/thermokarst/bactdb/helpers" "github.com/thermokarst/bactdb/models" "github.com/thermokarst/bactdb/payloads" @@ -20,11 +20,7 @@ import ( ) var ( - // TODO: fix this - ErrUserNotFoundJSON = types.NewJSONError(models.ErrUserNotFound, http.StatusNotFound) - ErrUserNotUpdatedJSON = types.NewJSONError(models.ErrUserNotUpdated, http.StatusBadRequest) - ErrEmailAddressTakenJSON = types.NewJSONError(models.ErrEmailAddressTaken, http.StatusBadRequest) - MgAccts = make(map[string]mailgun.Mailgun) + MgAccts = make(map[string]mailgun.Mailgun) ) type UserService struct{} @@ -37,11 +33,11 @@ func (u UserService) Unmarshal(b []byte) (types.Entity, error) { func (u UserService) List(val *url.Values, claims *types.Claims) (types.Entity, *types.AppError) { if val == nil { - return nil, helpers.ErrMustProvideOptionsJSON + return nil, NewJSONError(errors.MustProvideOptions, http.StatusInternalServerError) } var opt helpers.ListOptions if err := helpers.SchemaDecoder.Decode(&opt, *val); err != nil { - return nil, types.NewJSONError(err, http.StatusInternalServerError) + return nil, NewJSONError(err, http.StatusInternalServerError) } // TODO: fix this @@ -52,7 +48,7 @@ func (u UserService) List(val *url.Values, claims *types.Claims) (types.Entity, WHERE verified IS TRUE AND deleted_at IS NULL;` if err := models.DBH.Select(&users, sql); err != nil { - return nil, types.NewJSONError(err, http.StatusInternalServerError) + return nil, NewJSONError(err, http.StatusInternalServerError) } return &users, nil } @@ -61,7 +57,7 @@ func (u UserService) Get(id int64, dummy string, claims *types.Claims) (types.En user, err := models.DbGetUserById(id) user.Password = "" if err != nil { - return nil, types.NewJSONError(err, http.StatusInternalServerError) + return nil, NewJSONError(err, http.StatusInternalServerError) } user.CanEdit = claims.Role == "A" || id == claims.Sub @@ -80,7 +76,7 @@ func (u UserService) Update(id int64, e *types.Entity, dummy string, claims *typ original_user, err := models.DbGetUserById(id) if err != nil { - return types.NewJSONError(err, http.StatusInternalServerError) + return NewJSONError(err, http.StatusInternalServerError) } user.Id = id @@ -96,10 +92,10 @@ func (u UserService) Update(id int64, e *types.Entity, dummy string, claims *typ count, err := models.DBH.Update(user) user.Password = "" if err != nil { - return types.NewJSONError(err, http.StatusInternalServerError) + return NewJSONError(err, http.StatusInternalServerError) } if count != 1 { - return ErrUserNotUpdatedJSON + return NewJSONError(errors.UserNotUpdated, http.StatusInternalServerError) } return nil @@ -115,7 +111,7 @@ func (u UserService) Create(e *types.Entity, dummy string, claims *types.Claims) user.UpdatedAt = ct hash, err := bcrypt.GenerateFromPassword([]byte(user.Password), 12) if err != nil { - return types.NewJSONError(err, http.StatusInternalServerError) + return NewJSONError(err, http.StatusInternalServerError) } user.Password = string(hash) user.Role = "R" @@ -125,10 +121,10 @@ func (u UserService) Create(e *types.Entity, dummy string, claims *types.Claims) if err := models.DBH.Insert(user); err != nil { if err, ok := err.(*pq.Error); ok { if err.Code == "23505" { - return ErrEmailAddressTakenJSON + return NewJSONError(errors.EmailAddressTaken, http.StatusInternalServerError) } } - return types.NewJSONError(err, http.StatusInternalServerError) + return NewJSONError(err, http.StatusInternalServerError) } user.Password = "password" // don't want to send the hashed PW back to the client @@ -137,12 +133,12 @@ func (u UserService) Create(e *types.Entity, dummy string, claims *types.Claims) // TODO: move helpers.GenerateNonce nonce, err := helpers.GenerateNonce() if err != nil { - return types.NewJSONError(err, http.StatusInternalServerError) + return NewJSONError(err, http.StatusInternalServerError) } // TODO: fix this _, err = models.DBH.Exec(q, user.Id, nonce, claims.Ref, ct) if err != nil { - return types.NewJSONError(err, http.StatusInternalServerError) + return NewJSONError(err, http.StatusInternalServerError) } // Send out confirmation email @@ -161,7 +157,7 @@ func (u UserService) Create(e *types.Entity, dummy string, claims *types.Claims) _, _, err := mg.Send(m) if err != nil { log.Printf("%+v\n", err) - return types.NewJSONError(err, http.StatusInternalServerError) + return NewJSONError(err, http.StatusInternalServerError) } } @@ -179,16 +175,16 @@ func HandleUserVerify(w http.ResponseWriter, r *http.Request) *types.AppError { } if err := models.DBH.SelectOne(&ver, q, nonce); err != nil { log.Print(err) - return types.NewJSONError(err, http.StatusInternalServerError) + return NewJSONError(err, http.StatusInternalServerError) } if ver.User_id == 0 { - return types.NewJSONError(errors.New("No user found"), http.StatusInternalServerError) + return NewJSONError(errors.UserNotFound, http.StatusInternalServerError) } var user models.User if err := models.DBH.Get(&user, ver.User_id); err != nil { - return types.NewJSONError(err, http.StatusInternalServerError) + return NewJSONError(err, http.StatusInternalServerError) } user.UpdatedAt = helpers.CurrentTime() @@ -196,16 +192,16 @@ func HandleUserVerify(w http.ResponseWriter, r *http.Request) *types.AppError { count, err := models.DBH.Update(&user) if err != nil { - return types.NewJSONError(err, http.StatusInternalServerError) + return NewJSONError(err, http.StatusInternalServerError) } if count != 1 { - return types.NewJSONError(errors.New("Count 0"), http.StatusInternalServerError) + return NewJSONError(errors.UserNotUpdated, http.StatusInternalServerError) } q = `DELETE FROM verification WHERE user_id=$1;` _, err = models.DBH.Exec(q, user.Id) if err != nil { - return types.NewJSONError(err, http.StatusInternalServerError) + return NewJSONError(err, http.StatusInternalServerError) } fmt.Fprintln(w, `{"msg":"All set! Please log in."}`) return nil @@ -214,16 +210,16 @@ func HandleUserVerify(w http.ResponseWriter, r *http.Request) *types.AppError { func HandleUserLockout(w http.ResponseWriter, r *http.Request) *types.AppError { email := r.FormValue("email") if email == "" { - return types.NewJSONError(errors.New("missing email"), http.StatusInternalServerError) + return NewJSONError(errors.UserMissingEmail, http.StatusInternalServerError) } token, err := auth.Middleware.CreateToken(email) if err != nil { - return types.NewJSONError(err, http.StatusInternalServerError) + return NewJSONError(err, http.StatusInternalServerError) } origin := r.Header.Get("Origin") hostUrl, err := url.Parse(origin) if err != nil { - return types.NewJSONError(err, http.StatusInternalServerError) + return NewJSONError(err, http.StatusInternalServerError) } hostUrl.Path += "/users/lockoutauthenticate" params := url.Values{} @@ -246,7 +242,7 @@ func HandleUserLockout(w http.ResponseWriter, r *http.Request) *types.AppError { _, _, err := mg.Send(m) if err != nil { log.Printf("%+v\n", err) - return types.NewJSONError(err, http.StatusInternalServerError) + return NewJSONError(err, http.StatusInternalServerError) } } diff --git a/errors/auth.go b/errors/auth.go new file mode 100644 index 0000000..2471797 --- /dev/null +++ b/errors/auth.go @@ -0,0 +1,7 @@ +package errors + +import "errors" + +var ( + ExpiredToken = errors.New("this token has expired") +) diff --git a/errors/characteristics.go b/errors/characteristics.go new file mode 100644 index 0000000..abeae29 --- /dev/null +++ b/errors/characteristics.go @@ -0,0 +1,8 @@ +package errors + +import "errors" + +var ( + CharacteristicNotFound = errors.New("Characteristic not found") + CharacteristicNotUpdated = errors.New("Characteristic not updated") +) diff --git a/errors/helpers.go b/errors/helpers.go new file mode 100644 index 0000000..7135380 --- /dev/null +++ b/errors/helpers.go @@ -0,0 +1,7 @@ +package errors + +import "errors" + +var ( + MustProvideOptions = errors.New("Must provide necessary options") +) diff --git a/errors/measurements.go b/errors/measurements.go new file mode 100644 index 0000000..d034d59 --- /dev/null +++ b/errors/measurements.go @@ -0,0 +1,7 @@ +package errors + +import "errors" + +var ( + MeasurementNotFound = errors.New("Measurement not found") +) diff --git a/errors/species.go b/errors/species.go new file mode 100644 index 0000000..fbd8379 --- /dev/null +++ b/errors/species.go @@ -0,0 +1,8 @@ +package errors + +import "errors" + +var ( + SpeciesNotFound = errors.New("Species not found") + SpeciesNotUpdated = errors.New("Species not updated") +) diff --git a/errors/strains.go b/errors/strains.go new file mode 100644 index 0000000..4fda22e --- /dev/null +++ b/errors/strains.go @@ -0,0 +1,8 @@ +package errors + +import "errors" + +var ( + StrainNotFound = errors.New("Strain not found") + StrainNotUpdated = errors.New("Strain not updated") +) diff --git a/errors/types.go b/errors/types.go new file mode 100644 index 0000000..b237e47 --- /dev/null +++ b/errors/types.go @@ -0,0 +1,7 @@ +package errors + +import "errors" + +var ( + SourceNotByteSlice = errors.New("Scan source was not []byte") +) diff --git a/errors/users.go b/errors/users.go new file mode 100644 index 0000000..8a0a59d --- /dev/null +++ b/errors/users.go @@ -0,0 +1,11 @@ +package errors + +import "errors" + +var ( + UserNotFound = errors.New("No user found") + UserNotUpdated = errors.New("Count 0") + UserMissingEmail = errors.New("Missing email") + InvalidEmailOrPassword = errors.New("Invalid email or password") + EmailAddressTaken = errors.New("Email address is already registered") +) diff --git a/handlers/handlers.go b/handlers/handlers.go index 167d96a..46c5516 100644 --- a/handlers/handlers.go +++ b/handlers/handlers.go @@ -2,7 +2,6 @@ package handlers import ( "encoding/json" - "errors" "fmt" "io/ioutil" "net/http" @@ -18,6 +17,7 @@ import ( "github.com/thermokarst/bactdb/Godeps/_workspace/src/github.com/thermokarst/jwt" "github.com/thermokarst/bactdb/api" "github.com/thermokarst/bactdb/auth" + "github.com/thermokarst/bactdb/errors" "github.com/thermokarst/bactdb/helpers" "github.com/thermokarst/bactdb/models" "github.com/thermokarst/bactdb/types" @@ -32,7 +32,7 @@ func verifyClaims(claims []byte, r *http.Request) error { return err } if currentTime.After(time.Unix(c.Exp, 0)) { - return errors.New("this token has expired") + return errors.ExpiredToken } context.Set(r, "claims", c) return nil @@ -99,7 +99,7 @@ func handleGetter(g api.Getter) errorHandler { return func(w http.ResponseWriter, r *http.Request) *types.AppError { id, err := strconv.ParseInt(mux.Vars(r)["Id"], 10, 0) if err != nil { - return types.NewJSONError(err, http.StatusInternalServerError) + return NewJSONError(err, http.StatusInternalServerError) } claims := helpers.GetClaims(r) @@ -111,7 +111,7 @@ func handleGetter(g api.Getter) errorHandler { data, err := e.Marshal() if err != nil { - return types.NewJSONError(err, http.StatusInternalServerError) + return NewJSONError(err, http.StatusInternalServerError) } w.Write(data) return nil @@ -131,7 +131,7 @@ func handleLister(l api.Lister) errorHandler { } data, err := es.Marshal() if err != nil { - return types.NewJSONError(err, http.StatusInternalServerError) + return NewJSONError(err, http.StatusInternalServerError) } w.Write(data) return nil @@ -142,17 +142,17 @@ func handleUpdater(u api.Updater) errorHandler { return func(w http.ResponseWriter, r *http.Request) *types.AppError { id, err := strconv.ParseInt(mux.Vars(r)["Id"], 10, 0) if err != nil { - return types.NewJSONError(err, http.StatusInternalServerError) + return NewJSONError(err, http.StatusInternalServerError) } bodyBytes, err := ioutil.ReadAll(r.Body) if err != nil { - return types.NewJSONError(err, http.StatusInternalServerError) + return NewJSONError(err, http.StatusInternalServerError) } e, err := u.Unmarshal(bodyBytes) if err != nil { - return types.NewJSONError(err, http.StatusInternalServerError) + return NewJSONError(err, http.StatusInternalServerError) } claims := helpers.GetClaims(r) @@ -164,7 +164,7 @@ func handleUpdater(u api.Updater) errorHandler { data, err := e.Marshal() if err != nil { - return types.NewJSONError(err, http.StatusInternalServerError) + return NewJSONError(err, http.StatusInternalServerError) } w.Write(data) return nil @@ -175,12 +175,12 @@ func handleCreater(c api.Creater) errorHandler { return func(w http.ResponseWriter, r *http.Request) *types.AppError { bodyBytes, err := ioutil.ReadAll(r.Body) if err != nil { - return types.NewJSONError(err, http.StatusInternalServerError) + return NewJSONError(err, http.StatusInternalServerError) } e, err := c.Unmarshal(bodyBytes) if err != nil { - return types.NewJSONError(err, http.StatusInternalServerError) + return NewJSONError(err, http.StatusInternalServerError) } claims := helpers.GetClaims(r) @@ -192,7 +192,7 @@ func handleCreater(c api.Creater) errorHandler { data, err := e.Marshal() if err != nil { - return types.NewJSONError(err, http.StatusInternalServerError) + return NewJSONError(err, http.StatusInternalServerError) } w.Write(data) return nil @@ -203,7 +203,7 @@ func handleDeleter(d api.Deleter) errorHandler { return func(w http.ResponseWriter, r *http.Request) *types.AppError { id, err := strconv.ParseInt(mux.Vars(r)["Id"], 10, 0) if err != nil { - return types.NewJSONError(err, http.StatusInternalServerError) + return NewJSONError(err, http.StatusInternalServerError) } claims := helpers.GetClaims(r) @@ -296,12 +296,12 @@ func tokenRefresh(j *jwt.Middleware) errorHandler { claims := helpers.GetClaims(r) user, err := models.DbGetUserById(claims.Sub) if err != nil { - return types.NewJSONError(err, http.StatusInternalServerError) + return NewJSONError(err, http.StatusInternalServerError) } user.Password = "" token, err := auth.Middleware.CreateToken(user.Email) if err != nil { - return types.NewJSONError(err, http.StatusInternalServerError) + return NewJSONError(err, http.StatusInternalServerError) } data, _ := json.Marshal(struct { Token string `json:"token"` diff --git a/handlers/helpers.go b/handlers/helpers.go new file mode 100644 index 0000000..acaa24a --- /dev/null +++ b/handlers/helpers.go @@ -0,0 +1,10 @@ +package handlers + +import "github.com/thermokarst/bactdb/types" + +func NewJSONError(err error, status int) *types.AppError { + return &types.AppError{ + Error: types.ErrorJSON{Err: err}, + Status: status, + } +} diff --git a/helpers/helpers.go b/helpers/helpers.go index a2e5500..c47573a 100644 --- a/helpers/helpers.go +++ b/helpers/helpers.go @@ -3,7 +3,6 @@ package helpers import ( "crypto/rand" "encoding/base64" - "errors" "fmt" "net/http" "time" @@ -15,8 +14,6 @@ import ( ) var ( - ErrMustProvideOptions = errors.New("Must provide necessary options") - ErrMustProvideOptionsJSON = types.NewJSONError(ErrMustProvideOptions, http.StatusBadRequest) StatusUnprocessableEntity = 422 MustProvideAValue = "Must provide a value" SchemaDecoder = schema.NewDecoder() diff --git a/models/characteristics.go b/models/characteristics.go index a913c61..a155bc5 100644 --- a/models/characteristics.go +++ b/models/characteristics.go @@ -2,19 +2,14 @@ package models import ( "database/sql" - "errors" "fmt" "github.com/thermokarst/bactdb/Godeps/_workspace/src/github.com/jmoiron/modl" + "github.com/thermokarst/bactdb/errors" "github.com/thermokarst/bactdb/helpers" "github.com/thermokarst/bactdb/types" ) -var ( - ErrCharacteristicNotFound = errors.New("Characteristic not found") - ErrCharacteristicNotUpdated = errors.New("Characteristic not updated") -) - func init() { DB.AddTableWithName(CharacteristicBase{}, "characteristics").SetKeys(true, "Id") } @@ -199,7 +194,7 @@ func GetCharacteristic(id int64, genus string, claims *types.Claims) (*Character GROUP BY c.id, ct.characteristic_type_name;` if err := DBH.SelectOne(&characteristic, q, genus, id); err != nil { if err == sql.ErrNoRows { - return nil, ErrCharacteristicNotFound + return nil, errors.CharacteristicNotFound } return nil, err } diff --git a/models/measurements.go b/models/measurements.go index 1bfa6dd..faa8ea2 100644 --- a/models/measurements.go +++ b/models/measurements.go @@ -3,20 +3,14 @@ package models import ( "database/sql" "encoding/json" - "errors" "fmt" - "net/http" "github.com/thermokarst/bactdb/Godeps/_workspace/src/github.com/jmoiron/modl" + "github.com/thermokarst/bactdb/errors" "github.com/thermokarst/bactdb/helpers" "github.com/thermokarst/bactdb/types" ) -var ( - ErrMeasurementNotFound = errors.New("Measurement not found") - ErrMeasurementNotFoundJSON = types.NewJSONError(ErrMeasurementNotFound, http.StatusNotFound) -) - func init() { DB.AddTableWithName(MeasurementBase{}, "measurements").SetKeys(true, "Id") } @@ -205,7 +199,7 @@ func GetMeasurement(id int64, genus string, claims *types.Claims) (*Measurement, WHERE m.id=$2;` if err := DBH.SelectOne(&measurement, q, genus, id); err != nil { if err == sql.ErrNoRows { - return nil, ErrMeasurementNotFound + return nil, errors.MeasurementNotFound } return nil, err } diff --git a/models/species.go b/models/species.go index e88faed..e5268f2 100644 --- a/models/species.go +++ b/models/species.go @@ -2,20 +2,15 @@ package models import ( "database/sql" - "errors" "fmt" "strings" "github.com/thermokarst/bactdb/Godeps/_workspace/src/github.com/jmoiron/modl" + "github.com/thermokarst/bactdb/errors" "github.com/thermokarst/bactdb/helpers" "github.com/thermokarst/bactdb/types" ) -var ( - ErrSpeciesNotFound = errors.New("Species not found") - ErrSpeciesNotUpdated = errors.New("Species not updated") -) - func init() { DB.AddTableWithName(SpeciesBase{}, "species").SetKeys(true, "Id") } @@ -163,7 +158,7 @@ func GetSpecies(id int64, genus string, claims *types.Claims) (*Species, error) GROUP BY sp.id, g.genus_name;` if err := DBH.SelectOne(&species, q, genus, id); err != nil { if err == sql.ErrNoRows { - return nil, ErrSpeciesNotFound + return nil, errors.SpeciesNotFound } return nil, err } diff --git a/models/strains.go b/models/strains.go index a386031..2269c12 100644 --- a/models/strains.go +++ b/models/strains.go @@ -2,20 +2,15 @@ package models import ( "database/sql" - "errors" "fmt" "strings" "github.com/thermokarst/bactdb/Godeps/_workspace/src/github.com/jmoiron/modl" + "github.com/thermokarst/bactdb/errors" "github.com/thermokarst/bactdb/helpers" "github.com/thermokarst/bactdb/types" ) -var ( - ErrStrainNotFound = errors.New("Strain not found") - ErrStrainNotUpdated = errors.New("Strain not updated") -) - func init() { DB.AddTableWithName(StrainBase{}, "strains").SetKeys(true, "Id") } @@ -126,7 +121,7 @@ func GetStrain(id int64, genus string, claims *types.Claims) (*Strain, error) { GROUP BY st.id;` if err := DBH.SelectOne(&strain, q, genus, id); err != nil { if err == sql.ErrNoRows { - return nil, ErrStrainNotFound + return nil, errors.StrainNotFound } return nil, err } diff --git a/models/users.go b/models/users.go index 1cf56a8..a885de8 100644 --- a/models/users.go +++ b/models/users.go @@ -3,21 +3,14 @@ package models import ( "database/sql" "encoding/json" - "errors" "regexp" "github.com/thermokarst/bactdb/Godeps/_workspace/src/golang.org/x/crypto/bcrypt" + "github.com/thermokarst/bactdb/errors" "github.com/thermokarst/bactdb/helpers" "github.com/thermokarst/bactdb/types" ) -var ( - ErrUserNotFound = errors.New("User not found") - ErrUserNotUpdated = errors.New("User not updated") - ErrInvalidEmailOrPassword = errors.New("Invalid email or password") - ErrEmailAddressTaken = errors.New("Email address already registered") -) - func init() { DB.AddTableWithName(UserBase{}, "users").SetKeys(true, "Id") } @@ -114,10 +107,10 @@ func DbAuthenticate(email string, password string) error { AND verified IS TRUE AND deleted_at IS NULL;` if err := DBH.SelectOne(&user, q, email); err != nil { - return ErrInvalidEmailOrPassword + return errors.InvalidEmailOrPassword } if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password)); err != nil { - return ErrInvalidEmailOrPassword + return errors.InvalidEmailOrPassword } return nil } @@ -131,7 +124,7 @@ func DbGetUserById(id int64) (*User, error) { AND deleted_at IS NULL;` if err := DBH.SelectOne(&user, q, id); err != nil { if err == sql.ErrNoRows { - return nil, ErrUserNotFound + return nil, errors.UserNotFound } return nil, err } @@ -148,7 +141,7 @@ func DbGetUserByEmail(email string) (*User, error) { AND deleted_at IS NULL;` if err := DBH.SelectOne(&user, q, email); err != nil { if err == sql.ErrNoRows { - return nil, ErrUserNotFound + return nil, errors.UserNotFound } return nil, err } diff --git a/types/error_json.go b/types/error_json.go index 45e4f9f..439eaf4 100644 --- a/types/error_json.go +++ b/types/error_json.go @@ -19,10 +19,3 @@ type AppError struct { Error error Status int } - -func NewJSONError(err error, status int) *AppError { - return &AppError{ - Error: ErrorJSON{Err: err}, - Status: status, - } -} diff --git a/types/null_slice_int64.go b/types/null_slice_int64.go index fb1ce87..1c71c8d 100644 --- a/types/null_slice_int64.go +++ b/types/null_slice_int64.go @@ -1,9 +1,10 @@ package types import ( - "errors" "strconv" "strings" + + "github.com/thermokarst/bactdb/errors" ) type NullSliceInt64 []int64 @@ -11,7 +12,7 @@ type NullSliceInt64 []int64 func (i *NullSliceInt64) Scan(src interface{}) error { asBytes, ok := src.([]byte) if !ok { - return errors.New("Scan source was not []byte") + return errors.SourceNotByteSlice } asString := string(asBytes) (*i) = strToIntSlice(asString)