From 1ba602b1e28d829040540208a044bcb6e1926141 Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Fri, 10 Jul 2015 15:29:38 -0800 Subject: [PATCH] Move canEdit into payload --- characteristic_types.go | 4 +-- characteristics.go | 4 +-- entities.go | 8 ++--- handlers.go | 8 ++--- helpers.go | 17 ++------- measurements.go | 4 +-- species.go | 78 +++++++++++++++++++++++------------------ strains.go | 76 +++++++++++++++++++++------------------ users.go | 8 ++--- 9 files changed, 106 insertions(+), 101 deletions(-) diff --git a/characteristic_types.go b/characteristic_types.go index 3ab8083..7d036bb 100644 --- a/characteristic_types.go +++ b/characteristic_types.go @@ -57,7 +57,7 @@ func (c *CharacteristicTypes) marshal() ([]byte, error) { return json.Marshal(&CharacteristicTypesJSON{CharacteristicTypes: c}) } -func (c CharacteristicTypeService) list(val *url.Values, claims Claims) (entity, *appError) { +func (c CharacteristicTypeService) list(val *url.Values, claims *Claims) (entity, *appError) { if val == nil { return nil, ErrMustProvideOptionsJSON } @@ -95,7 +95,7 @@ func (c CharacteristicTypeService) list(val *url.Values, claims Claims) (entity, return &characteristic_types, nil } -func (c CharacteristicTypeService) get(id int64, dummy string, claims Claims) (entity, *appError) { +func (c CharacteristicTypeService) get(id int64, dummy string, claims *Claims) (entity, *appError) { var characteristic_type CharacteristicType q := `SELECT ct.*, array_agg(c.id) AS characteristics, 0 AS sort_order FROM characteristic_types ct diff --git a/characteristics.go b/characteristics.go index 700dba0..416383a 100644 --- a/characteristics.go +++ b/characteristics.go @@ -59,7 +59,7 @@ func (c *Characteristics) marshal() ([]byte, error) { return json.Marshal(&CharacteristicsJSON{Characteristics: c}) } -func (c CharacteristicService) list(val *url.Values, claims Claims) (entity, *appError) { +func (c CharacteristicService) list(val *url.Values, claims *Claims) (entity, *appError) { if val == nil { return nil, ErrMustProvideOptionsJSON } @@ -97,7 +97,7 @@ func (c CharacteristicService) list(val *url.Values, claims Claims) (entity, *ap return &characteristics, nil } -func (c CharacteristicService) get(id int64, dummy string, claims Claims) (entity, *appError) { +func (c CharacteristicService) get(id int64, dummy string, claims *Claims) (entity, *appError) { var characteristic Characteristic q := `SELECT c.*, array_agg(m.id) AS measurements, array_agg(st.id) AS strains FROM characteristics c diff --git a/entities.go b/entities.go index a5a83e8..7809bb9 100644 --- a/entities.go +++ b/entities.go @@ -7,19 +7,19 @@ type entity interface { } type getter interface { - get(int64, string, Claims) (entity, *appError) + get(int64, string, *Claims) (entity, *appError) } type lister interface { - list(*url.Values, Claims) (entity, *appError) + list(*url.Values, *Claims) (entity, *appError) } type updater interface { - update(int64, *entity, string, Claims) *appError + update(int64, *entity, string, *Claims) *appError unmarshal([]byte) (entity, error) } type creater interface { - create(*entity, string, Claims) *appError + create(*entity, string, *Claims) *appError unmarshal([]byte) (entity, error) } diff --git a/handlers.go b/handlers.go index c127bfc..ab7fec3 100644 --- a/handlers.go +++ b/handlers.go @@ -129,7 +129,7 @@ func handleGetter(g getter) errorHandler { claims := getClaims(r) - e, appErr := g.get(id, mux.Vars(r)["genus"], claims) + e, appErr := g.get(id, mux.Vars(r)["genus"], &claims) if appErr != nil { return appErr } @@ -150,7 +150,7 @@ func handleLister(l lister) errorHandler { claims := getClaims(r) - es, appErr := l.list(&opt, claims) + es, appErr := l.list(&opt, &claims) if appErr != nil { return appErr } @@ -182,7 +182,7 @@ func handleUpdater(u updater) errorHandler { claims := getClaims(r) - appErr := u.update(id, &e, mux.Vars(r)["genus"], claims) + appErr := u.update(id, &e, mux.Vars(r)["genus"], &claims) if appErr != nil { return appErr } @@ -210,7 +210,7 @@ func handleCreater(c creater) errorHandler { claims := getClaims(r) - appErr := c.create(&e, mux.Vars(r)["genus"], claims) + appErr := c.create(&e, mux.Vars(r)["genus"], &claims) if appErr != nil { return appErr } diff --git a/helpers.go b/helpers.go index a93eec6..8657ef9 100644 --- a/helpers.go +++ b/helpers.go @@ -115,21 +115,10 @@ func getClaims(r *http.Request) Claims { return claims } -func canAdd(claims Claims) bool { +func canAdd(claims *Claims) bool { return claims.Role == "A" || claims.Role == "W" } -func canEdit(claims Claims, id_list map[int64]int64) []int64 { - id := claims.Sub - role := claims.Role - - out := make([]int64, 0) - - for k, v := range id_list { - if (role == "W" && id == v) || role == "A" { - out = append(out, k) - } - } - - return out +func canEdit(claims *Claims, author int64) bool { + return claims.Sub == author || claims.Role == "A" } diff --git a/measurements.go b/measurements.go index 43532a1..5da18c3 100644 --- a/measurements.go +++ b/measurements.go @@ -66,7 +66,7 @@ func (m *Measurements) marshal() ([]byte, error) { return json.Marshal(&MeasurementsJSON{Measurements: m}) } -func (m MeasurementService) list(val *url.Values, claims Claims) (entity, *appError) { +func (m MeasurementService) list(val *url.Values, claims *Claims) (entity, *appError) { if val == nil { return nil, ErrMustProvideOptionsJSON } @@ -138,7 +138,7 @@ func (m MeasurementService) list(val *url.Values, claims Claims) (entity, *appEr return &measurements, nil } -func (m MeasurementService) get(id int64, genus string, claims Claims) (entity, *appError) { +func (m MeasurementService) get(id int64, genus string, claims *Claims) (entity, *appError) { var measurement Measurement q := `SELECT m.*, t.text_measurement_name AS text_measurement_type_name, u.symbol AS unit_type_name, te.name AS test_method_name diff --git a/species.go b/species.go index 2b9880d..7a50353 100644 --- a/species.go +++ b/species.go @@ -8,6 +8,8 @@ import ( "net/http" "net/url" "strings" + + "github.com/jmoiron/modl" ) var ( @@ -21,6 +23,18 @@ func init() { DB.AddTableWithName(SpeciesBase{}, "species").SetKeys(true, "Id") } +func (s *SpeciesBase) PreInsert(e modl.SqlExecutor) error { + ct := currentTime() + s.CreatedAt = ct + s.UpdatedAt = ct + return nil +} + +func (s *SpeciesBase) PreUpdate(e modl.SqlExecutor) error { + s.UpdatedAt = currentTime() + return nil +} + type SpeciesService struct{} // SpeciesBase is what the DB expects to see for inserts/updates @@ -45,13 +59,13 @@ type Species struct { Strains NullSliceInt64 `db:"strains" json:"strains"` TotalStrains int64 `db:"total_strains" json:"totalStrains"` SortOrder int64 `db:"sort_order" json:"sortOrder"` + CanEdit bool `db:"-" json:"canEdit"` } type ManySpecies []*Species type SpeciesMeta struct { - CanAdd bool `json:"canAdd"` - CanEdit []int64 `json:"canEdit"` + CanAdd bool `json:"canAdd"` } type SpeciesPayload struct { @@ -80,7 +94,7 @@ func (s SpeciesService) unmarshal(b []byte) (entity, error) { return &sj, err } -func (s SpeciesService) list(val *url.Values, claims Claims) (entity, *appError) { +func (s SpeciesService) list(val *url.Values, claims *Claims) (entity, *appError) { if val == nil { return nil, ErrMustProvideOptionsJSON } @@ -89,7 +103,7 @@ func (s SpeciesService) list(val *url.Values, claims Claims) (entity, *appError) return nil, newJSONError(err, http.StatusInternalServerError) } - species, err := listSpecies(opt) + species, err := listSpecies(opt, claims) if err != nil { return nil, newJSONError(err, http.StatusInternalServerError) } @@ -99,36 +113,29 @@ func (s SpeciesService) list(val *url.Values, claims Claims) (entity, *appError) return nil, newJSONError(err, http.StatusInternalServerError) } - strains, err := listStrains(*strains_opt) + strains, err := listStrains(*strains_opt, claims) if err != nil { return nil, newJSONError(err, http.StatusInternalServerError) } - edit_list := make(map[int64]int64) - - for _, v := range *species { - edit_list[v.Id] = v.CreatedBy - } - payload := ManySpeciesPayload{ Species: species, Strains: strains, Meta: &SpeciesMeta{ - CanAdd: canAdd(claims), - CanEdit: canEdit(claims, edit_list), + CanAdd: canAdd(claims), }, } return &payload, nil } -func (s SpeciesService) get(id int64, genus string, claims Claims) (entity, *appError) { - species, err := getSpecies(id, genus) +func (s SpeciesService) get(id int64, genus string, claims *Claims) (entity, *appError) { + species, err := getSpecies(id, genus, claims) if err != nil { return nil, newJSONError(err, http.StatusInternalServerError) } - strains, err := strainsFromSpeciesId(id, genus) + strains, err := strainsFromSpeciesId(id, genus, claims) if err != nil { return nil, newJSONError(err, http.StatusInternalServerError) } @@ -137,18 +144,16 @@ func (s SpeciesService) get(id int64, genus string, claims Claims) (entity, *app Species: species, Strains: strains, Meta: &SpeciesMeta{ - CanAdd: canAdd(claims), - CanEdit: canEdit(claims, map[int64]int64{species.Id: species.CreatedBy}), + CanAdd: canAdd(claims), }, } return &payload, nil } -func (s SpeciesService) update(id int64, e *entity, genus string, claims Claims) *appError { +func (s SpeciesService) update(id int64, e *entity, genus string, claims *Claims) *appError { payload := (*e).(*SpeciesPayload) payload.Species.UpdatedBy = claims.Sub - payload.Species.UpdatedAt = currentTime() payload.Species.Id = id genus_id, err := genusIdFromName(genus) @@ -166,12 +171,12 @@ func (s SpeciesService) update(id int64, e *entity, genus string, claims Claims) } // Reload to send back down the wire - species, err := getSpecies(id, genus) + species, err := getSpecies(id, genus, claims) if err != nil { return newJSONError(err, http.StatusInternalServerError) } - strains, err := strainsFromSpeciesId(id, genus) + strains, err := strainsFromSpeciesId(id, genus, claims) if err != nil { return newJSONError(err, http.StatusInternalServerError) } @@ -179,20 +184,16 @@ func (s SpeciesService) update(id int64, e *entity, genus string, claims Claims) payload.Species = species payload.Strains = strains payload.Meta = &SpeciesMeta{ - CanAdd: canAdd(claims), - CanEdit: canEdit(claims, map[int64]int64{species.Id: species.CreatedBy}), + CanAdd: canAdd(claims), } return nil } -func (s SpeciesService) create(e *entity, genus string, claims Claims) *appError { +func (s SpeciesService) create(e *entity, genus string, claims *Claims) *appError { payload := (*e).(*SpeciesPayload) - ct := currentTime() payload.Species.CreatedBy = claims.Sub - payload.Species.CreatedAt = ct payload.Species.UpdatedBy = claims.Sub - payload.Species.UpdatedAt = ct genus_id, err := genusIdFromName(genus) if err != nil { @@ -206,7 +207,7 @@ func (s SpeciesService) create(e *entity, genus string, claims Claims) *appError } // Reload to send back down the wire - species, err := getSpecies(payload.Species.Id, genus) + species, err := getSpecies(payload.Species.Id, genus, claims) if err != nil { return newJSONError(err, http.StatusInternalServerError) } @@ -215,8 +216,7 @@ func (s SpeciesService) create(e *entity, genus string, claims Claims) *appError payload.Species = species payload.Meta = &SpeciesMeta{ - CanAdd: canAdd(claims), - CanEdit: canEdit(claims, map[int64]int64{species.Id: species.CreatedBy}), + CanAdd: canAdd(claims), } return nil } @@ -254,7 +254,7 @@ func strainOptsFromSpecies(opt ListOptions) (*ListOptions, error) { return &ListOptions{Genus: opt.Genus, Ids: relatedStrainIds}, nil } -func strainsFromSpeciesId(id int64, genus string) (*Strains, error) { +func strainsFromSpeciesId(id int64, genus string, claims *Claims) (*Strains, error) { opt := ListOptions{ Genus: genus, Ids: []int64{id}, @@ -265,7 +265,7 @@ func strainsFromSpeciesId(id int64, genus string) (*Strains, error) { return nil, err } - strains, err := listStrains(*strains_opt) + strains, err := listStrains(*strains_opt, claims) if err != nil { return nil, err } @@ -273,7 +273,7 @@ func strainsFromSpeciesId(id int64, genus string) (*Strains, error) { return strains, nil } -func listSpecies(opt ListOptions) (*ManySpecies, error) { +func listSpecies(opt ListOptions, claims *Claims) (*ManySpecies, error) { var vals []interface{} q := `SELECT sp.*, g.genus_name, array_agg(st.id) AS strains, @@ -303,10 +303,15 @@ func listSpecies(opt ListOptions) (*ManySpecies, error) { if err != nil { return nil, err } + + for _, s := range species { + s.CanEdit = canEdit(claims, s.CreatedBy) + } + return &species, nil } -func getSpecies(id int64, genus string) (*Species, error) { +func getSpecies(id int64, genus string, claims *Claims) (*Species, error) { var species Species q := `SELECT sp.*, g.genus_name, array_agg(st.id) AS strains, COUNT(st) AS total_strains, 0 AS sort_order @@ -321,5 +326,8 @@ func getSpecies(id int64, genus string) (*Species, error) { } return nil, err } + + species.CanEdit = canEdit(claims, species.CreatedBy) + return &species, nil } diff --git a/strains.go b/strains.go index 1c4883a..921dd3f 100644 --- a/strains.go +++ b/strains.go @@ -8,6 +8,8 @@ import ( "net/http" "net/url" "strings" + + "github.com/jmoiron/modl" ) var ( @@ -21,6 +23,18 @@ func init() { DB.AddTableWithName(StrainBase{}, "strains").SetKeys(true, "Id") } +func (s *StrainBase) PreInsert(e modl.SqlExecutor) error { + ct := currentTime() + s.CreatedAt = ct + s.UpdatedAt = ct + return nil +} + +func (s *StrainBase) PreUpdate(e modl.SqlExecutor) error { + s.UpdatedAt = currentTime() + return nil +} + type StrainService struct{} // StrainBase is what the DB expects to see for inserts/updates @@ -47,13 +61,13 @@ type Strain struct { Measurements NullSliceInt64 `db:"measurements" json:"measurements"` TotalMeasurements int64 `db:"total_measurements" json:"totalMeasurements"` SortOrder int64 `db:"sort_order" json:"sortOrder"` + CanEdit bool `db:"can_edit" json:"canEdit"` } type Strains []*Strain type StrainMeta struct { - CanAdd bool `json:"canAdd"` - CanEdit []int64 `json:"canEdit"` + CanAdd bool `json:"canAdd"` } type StrainPayload struct { @@ -82,7 +96,7 @@ func (s StrainService) unmarshal(b []byte) (entity, error) { return &sj, err } -func (s StrainService) list(val *url.Values, claims Claims) (entity, *appError) { +func (s StrainService) list(val *url.Values, claims *Claims) (entity, *appError) { if val == nil { return nil, ErrMustProvideOptionsJSON } @@ -91,7 +105,7 @@ func (s StrainService) list(val *url.Values, claims Claims) (entity, *appError) return nil, newJSONError(err, http.StatusInternalServerError) } - strains, err := listStrains(opt) + strains, err := listStrains(opt, claims) if err != nil { return nil, newJSONError(err, http.StatusInternalServerError) } @@ -101,36 +115,29 @@ func (s StrainService) list(val *url.Values, claims Claims) (entity, *appError) return nil, newJSONError(err, http.StatusInternalServerError) } - species, err := listSpecies(*species_opt) + species, err := listSpecies(*species_opt, claims) if err != nil { return nil, newJSONError(err, http.StatusInternalServerError) } - edit_list := make(map[int64]int64) - - for _, v := range *strains { - edit_list[v.Id] = v.CreatedBy - } - payload := StrainsPayload{ Strains: strains, Species: species, Meta: &StrainMeta{ - CanAdd: canAdd(claims), - CanEdit: canEdit(claims, edit_list), + CanAdd: canAdd(claims), }, } return &payload, nil } -func (s StrainService) get(id int64, genus string, claims Claims) (entity, *appError) { - strain, err := getStrain(id, genus) +func (s StrainService) get(id int64, genus string, claims *Claims) (entity, *appError) { + strain, err := getStrain(id, genus, claims) if err != nil { return nil, newJSONError(err, http.StatusInternalServerError) } - species, err := getSpecies(strain.SpeciesId, genus) + species, err := getSpecies(strain.SpeciesId, genus, claims) if err != nil { return nil, newJSONError(err, http.StatusInternalServerError) } @@ -141,18 +148,16 @@ func (s StrainService) get(id int64, genus string, claims Claims) (entity, *appE Strain: strain, Species: &many_species, Meta: &StrainMeta{ - CanAdd: canAdd(claims), - CanEdit: canEdit(claims, map[int64]int64{strain.Id: strain.CreatedBy}), + CanAdd: canAdd(claims), }, } return &payload, nil } -func (s StrainService) update(id int64, e *entity, genus string, claims Claims) *appError { +func (s StrainService) update(id int64, e *entity, genus string, claims *Claims) *appError { payload := (*e).(*StrainPayload) payload.Strain.UpdatedBy = claims.Sub - payload.Strain.UpdatedAt = currentTime() payload.Strain.Id = id count, err := DBH.Update(payload.Strain.StrainBase) @@ -163,12 +168,12 @@ func (s StrainService) update(id int64, e *entity, genus string, claims Claims) return ErrStrainNotUpdatedJSON } - strain, err := getStrain(id, genus) + strain, err := getStrain(id, genus, claims) if err != nil { return newJSONError(err, http.StatusInternalServerError) } - species, err := getSpecies(strain.SpeciesId, genus) + species, err := getSpecies(strain.SpeciesId, genus, claims) if err != nil { return newJSONError(err, http.StatusInternalServerError) } @@ -178,31 +183,27 @@ func (s StrainService) update(id int64, e *entity, genus string, claims Claims) payload.Strain = strain payload.Species = &many_species payload.Meta = &StrainMeta{ - CanAdd: canAdd(claims), - CanEdit: canEdit(claims, map[int64]int64{strain.Id: strain.CreatedBy}), + CanAdd: canAdd(claims), } return nil } -func (s StrainService) create(e *entity, genus string, claims Claims) *appError { +func (s StrainService) create(e *entity, genus string, claims *Claims) *appError { payload := (*e).(*StrainPayload) - ct := currentTime() payload.Strain.CreatedBy = claims.Sub - payload.Strain.CreatedAt = ct payload.Strain.UpdatedBy = claims.Sub - payload.Strain.UpdatedAt = ct if err := DBH.Insert(payload.Strain.StrainBase); err != nil { return newJSONError(err, http.StatusInternalServerError) } - strain, err := getStrain(payload.Strain.Id, genus) + strain, err := getStrain(payload.Strain.Id, genus, claims) if err != nil { return newJSONError(err, http.StatusInternalServerError) } - species, err := getSpecies(strain.SpeciesId, genus) + species, err := getSpecies(strain.SpeciesId, genus, claims) if err != nil { return newJSONError(err, http.StatusInternalServerError) } @@ -212,14 +213,13 @@ func (s StrainService) create(e *entity, genus string, claims Claims) *appError payload.Strain = strain payload.Species = &many_species payload.Meta = &StrainMeta{ - CanAdd: canAdd(claims), - CanEdit: canEdit(claims, map[int64]int64{strain.Id: strain.CreatedBy}), + CanAdd: canAdd(claims), } return nil } -func listStrains(opt ListOptions) (*Strains, error) { +func listStrains(opt ListOptions, claims *Claims) (*Strains, error) { var vals []interface{} q := `SELECT st.*, array_agg(m.id) AS measurements, COUNT(m) AS total_measurements, @@ -249,10 +249,15 @@ func listStrains(opt ListOptions) (*Strains, error) { if err != nil { return nil, err } + + for _, s := range strains { + s.CanEdit = canEdit(claims, s.CreatedBy) + } + return &strains, nil } -func getStrain(id int64, genus string) (*Strain, error) { +func getStrain(id int64, genus string, claims *Claims) (*Strain, error) { var strain Strain q := `SELECT st.*, array_agg(m.id) AS measurements, COUNT(m) AS total_measurements, 0 AS sort_order @@ -268,6 +273,9 @@ func getStrain(id int64, genus string) (*Strain, error) { } return nil, err } + + strain.CanEdit = canEdit(claims, strain.CreatedBy) + return &strain, nil } diff --git a/users.go b/users.go index 2e347f9..e8927e9 100644 --- a/users.go +++ b/users.go @@ -124,7 +124,7 @@ func (u *User) validate() error { return nil } -func (u UserService) list(val *url.Values, claims Claims) (entity, *appError) { +func (u UserService) list(val *url.Values, claims *Claims) (entity, *appError) { if val == nil { return nil, ErrMustProvideOptionsJSON } @@ -145,7 +145,7 @@ func (u UserService) list(val *url.Values, claims Claims) (entity, *appError) { return &users, nil } -func (u UserService) get(id int64, dummy string, claims Claims) (entity, *appError) { +func (u UserService) get(id int64, dummy string, claims *Claims) (entity, *appError) { var user User q := `SELECT id, email, 'password' AS password, name, role, created_at, updated_at, deleted_at @@ -162,7 +162,7 @@ func (u UserService) get(id int64, dummy string, claims Claims) (entity, *appErr return &user, nil } -func (u UserService) update(id int64, e *entity, dummy string, claims Claims) *appError { +func (u UserService) update(id int64, e *entity, dummy string, claims *Claims) *appError { user := (*e).(*User) user.UpdatedAt = currentTime() user.Id = id @@ -177,7 +177,7 @@ func (u UserService) update(id int64, e *entity, dummy string, claims Claims) *a return nil } -func (u UserService) create(e *entity, dummy string, claims Claims) *appError { +func (u UserService) create(e *entity, dummy string, claims *Claims) *appError { user := (*e).(*User) if err := user.validate(); err != nil { return &appError{Error: err, Status: StatusUnprocessableEntity}