From 51959cf5b5125864d4e505e72489edd1fcada329 Mon Sep 17 00:00:00 2001 From: kgukevin Date: Mon, 6 Sep 2021 23:36:43 -0500 Subject: [PATCH 1/5] Add PATCH registration/attendee endpoint --- common/database/database.go | 1 + common/database/mongo_database.go | 14 ++++ common/datastore/conversions.go | 7 +- common/datastore/validation.go | 5 +- gateway/services/registration.go | 10 +++ .../registration/controller/controller.go | 66 +++++++++++++++++++ .../service/registration_service.go | 22 ++++++- .../registration/tests/registration_test.go | 41 ++++++++++++ 8 files changed, 160 insertions(+), 6 deletions(-) diff --git a/common/database/database.go b/common/database/database.go index a6832a8c..c78e75fe 100644 --- a/common/database/database.go +++ b/common/database/database.go @@ -13,6 +13,7 @@ type Database interface { RemoveAll(collection_name string, query interface{}) (*ChangeResults, error) Insert(collection_name string, item interface{}) error Upsert(collection_name string, selector interface{}, update interface{}) (*ChangeResults, error) + Patch(collection_name string, selector interface{}, patch interface{}) error Update(collection_name string, selector interface{}, update interface{}) error UpdateAll(collection_name string, selector interface{}, update interface{}) (*ChangeResults, error) DropDatabase() error diff --git a/common/database/mongo_database.go b/common/database/mongo_database.go index 223d9df3..3ec50869 100644 --- a/common/database/mongo_database.go +++ b/common/database/mongo_database.go @@ -8,6 +8,7 @@ import ( "github.com/HackIllinois/api/common/config" "gopkg.in/mgo.v2" + "gopkg.in/mgo.v2/bson" ) /* @@ -197,6 +198,19 @@ func (db *MongoDatabase) Upsert(collection_name string, selector interface{}, up return &change_results, convertMgoError(err) } +func (db *MongoDatabase) Patch(collection_name string, selector interface{}, patch interface{}) error { + current_session := db.GetSession() + defer current_session.Close() + + collection := current_session.DB(db.name).C(collection_name) + + // err := collection.Update(selector, bson.M{"$set": patch}) + // err := collection.Update(selector, bson.M{"$set": bson.M{"lastName": "Springer", "firstName": "Jerry"}}) + err := collection.Update(selector, bson.M{"$set": patch}) + + return convertMgoError(err) +} + /* Finds an item based on the given selector and updates it with the data in update */ diff --git a/common/datastore/conversions.go b/common/datastore/conversions.go index 58611bcb..73cf958c 100644 --- a/common/datastore/conversions.go +++ b/common/datastore/conversions.go @@ -59,9 +59,10 @@ func toObject(raw_data interface{}, definition DataStoreDefinition) (interface{} if err != nil { return nil, NewErrInField(field.Name, err) } - } else { - data[field.Name] = getDefaultValue(field.Type) - } + } + // else { + // data[field.Name] = getDefaultValue(field.Type) //removed for registration/attendee patch function + // } } return data, nil diff --git a/common/datastore/validation.go b/common/datastore/validation.go index 4098ac73..4003b0f4 100644 --- a/common/datastore/validation.go +++ b/common/datastore/validation.go @@ -5,8 +5,11 @@ import ( "gopkg.in/go-playground/validator.v9" ) -func (datastore *DataStore) Validate() error { +func (datastore *DataStore) Validate(params ...int) error { validate := validator.New() + if len(params) == 1{ + return nil + } return validateField(datastore.Data, datastore.Definition, validate) } diff --git a/gateway/services/registration.go b/gateway/services/registration.go index 757f8b61..daf077fd 100644 --- a/gateway/services/registration.go +++ b/gateway/services/registration.go @@ -36,6 +36,12 @@ var RegistrationRoutes = arbor.RouteCollection{ "/registration/attendee/", alice.New(middleware.AuthMiddleware([]models.Role{models.ApplicantRole}), middleware.IdentificationMiddleware).ThenFunc(UpdateRegistration).ServeHTTP, }, + arbor.Route{ + "PatchCurrentUserRegistration", + "PATCH", + "/registration/attendee/", + alice.New(middleware.AuthMiddleware([]models.Role{models.ApplicantRole}), middleware.IdentificationMiddleware).ThenFunc(PatchRegistration).ServeHTTP, + }, arbor.Route{ "GetFilteredUserRegistrations", "GET", @@ -97,3 +103,7 @@ func CreateRegistration(w http.ResponseWriter, r *http.Request) { func UpdateRegistration(w http.ResponseWriter, r *http.Request) { arbor.PUT(w, config.REGISTRATION_SERVICE+r.URL.String(), RegistrationFormat, "", r) } + +func PatchRegistration(w http.ResponseWriter, r *http.Request) { + arbor.PATCH(w, config.REGISTRATION_SERVICE+r.URL.String(), RegistrationFormat, "", r) +} diff --git a/services/registration/controller/controller.go b/services/registration/controller/controller.go index 11ab2152..ba67a227 100644 --- a/services/registration/controller/controller.go +++ b/services/registration/controller/controller.go @@ -21,6 +21,7 @@ func SetupController(route *mux.Route) { router.HandleFunc("/attendee/", GetCurrentUserRegistration).Methods("GET") router.HandleFunc("/attendee/", CreateCurrentUserRegistration).Methods("POST") router.HandleFunc("/attendee/", UpdateCurrentUserRegistration).Methods("PUT") + router.HandleFunc("/attendee/", PatchCurrentUserRegistration).Methods("PATCH") router.HandleFunc("/attendee/filter/", GetFilteredUserRegistrations).Methods("GET") router.HandleFunc("/mentor/", GetCurrentMentorRegistration).Methods("GET") @@ -257,6 +258,71 @@ func UpdateCurrentUserRegistration(w http.ResponseWriter, r *http.Request) { json.NewEncoder(w).Encode(updated_registration) } +/* + Endpoint to patch user registration attributes +*/ +func PatchCurrentUserRegistration(w http.ResponseWriter, r *http.Request) { + id := r.Header.Get("HackIllinois-Identity") + + if id == "" { + errors.WriteError(w, r, errors.MalformedRequestError("Must provide id in request.", "Must provide id in request.")) + return + } + + user_registration := datastore.NewDataStore(config.REGISTRATION_DEFINITION) + err := json.NewDecoder(r.Body).Decode(&user_registration) + + if err != nil { + errors.WriteError(w, r, errors.InternalError(err.Error(), "Could not decode user registration information. Possible failure in JSON validation, or invalid registration format.")) + return + } + + user_registration.Data["id"] = id + + user_info, err := service.GetUserInfo(id) + + if err != nil { + errors.WriteError(w, r, errors.InternalError(err.Error(), "Could not get user info.")) + return + } + + original_registration, err := service.GetUserRegistration(id) + + if err != nil { + errors.WriteError(w, r, errors.DatabaseError(err.Error(), "Could not get user's original registration.")) + return + } + + user_registration.Data["github"] = user_info.Username + + user_registration.Data["createdAt"] = original_registration.Data["createdAt"] + user_registration.Data["updatedAt"] = time.Now().Unix() + + err = service.PatchUserRegistration(id, user_registration) + + if err != nil { + errors.WriteError(w, r, errors.InternalError(err.Error(), "Could not update user's registration.")) + return + } + + updated_registration, err := service.GetUserRegistration(id) + + if err != nil { + errors.WriteError(w, r, errors.DatabaseError(err.Error(), "Could not fetch user's updated registration.")) + return + } + + mail_template := "registration_update" + err = service.SendUserMail(id, mail_template) + + if err != nil { + errors.WriteError(w, r, errors.InternalError(err.Error(), "Could not send registration update email.")) + return + } + + json.NewEncoder(w).Encode(updated_registration) +} + /* Endpoint to get user registrations based on filters */ diff --git a/services/registration/service/registration_service.go b/services/registration/service/registration_service.go index 0509f13b..fcc912fe 100644 --- a/services/registration/service/registration_service.go +++ b/services/registration/service/registration_service.go @@ -2,12 +2,13 @@ package service import ( "errors" + "strconv" + "strings" + "github.com/HackIllinois/api/common/database" "github.com/HackIllinois/api/services/registration/config" "github.com/HackIllinois/api/services/registration/models" "gopkg.in/go-playground/validator.v9" - "strconv" - "strings" ) var validate *validator.Validate @@ -89,6 +90,23 @@ func UpdateUserRegistration(id string, user_registration models.UserRegistration return err } +/* + Patches the user registration associated with the given user id +*/ +func PatchUserRegistration(id string, user_registration models.UserRegistration) error { + err := user_registration.Validate(1) + + if err != nil { + return err + } + + selector := database.QuerySelector{"id": id} + + err = db.Patch("attendees", selector, &user_registration) + + return err +} + /* Returns db search query based on given parameters */ diff --git a/services/registration/tests/registration_test.go b/services/registration/tests/registration_test.go index 3af47484..fdd227de 100644 --- a/services/registration/tests/registration_test.go +++ b/services/registration/tests/registration_test.go @@ -162,6 +162,38 @@ func TestUpdateUserRegistrationService(t *testing.T) { CleanupTestDB(t) } +/* + Service level test for patching user registration in the db +*/ +func TestPatchUserRegistrationService(t *testing.T) { + SetupTestDB(t) + base_registration := datastore.NewDataStore(config.REGISTRATION_DEFINITION) + json.Unmarshal([]byte(patch_registration_data), &base_registration) + err := service.PatchUserRegistration("testid", base_registration) + + if err != nil { + t.Fatal(err) + } + + user_registration, err := service.GetUserRegistration("testid") + + if err != nil { + t.Fatal(err) + } + + expected_registration := getBaseUserRegistration() + expected_registration.Data["id"] = "testid" + expected_registration.Data["firstName"] = "John" + expected_registration.Data["lastName"] = "Smith" + expected_registration.Data["email"] = "new_test@gmail.com" + + if !reflect.DeepEqual(user_registration.Data["firstName"], expected_registration.Data["firstName"]) { + t.Errorf("Wrong user info.\nExpected %v\ngot %v\n", expected_registration.Data["firstName"], user_registration.Data["firstName"]) + } + + CleanupTestDB(t) +} + /* Service level test for getting mentor registration from db */ @@ -441,6 +473,15 @@ var user_registration_data string = ` } ` +var patch_registration_data string = ` +{ + "id": "testid", + "firstName": "John", + "lastName": "Smith", + "email": "new_test@gmail.com" +} +` + var mentor_registration_data string = ` { "id": "testid", From 0cc6c7660cd188a24ab5edeb2e3614a720629343 Mon Sep 17 00:00:00 2001 From: kgukevin Date: Mon, 6 Sep 2021 23:55:10 -0500 Subject: [PATCH 2/5] Add PATCH registration/attendee endpoint --- common/database/mongo_database.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/common/database/mongo_database.go b/common/database/mongo_database.go index 3ec50869..26a1b967 100644 --- a/common/database/mongo_database.go +++ b/common/database/mongo_database.go @@ -204,8 +204,6 @@ func (db *MongoDatabase) Patch(collection_name string, selector interface{}, pat collection := current_session.DB(db.name).C(collection_name) - // err := collection.Update(selector, bson.M{"$set": patch}) - // err := collection.Update(selector, bson.M{"$set": bson.M{"lastName": "Springer", "firstName": "Jerry"}}) err := collection.Update(selector, bson.M{"$set": patch}) return convertMgoError(err) From fc4c399df688e9952d25b0d508822c69d0c3ac4b Mon Sep 17 00:00:00 2001 From: kgukevin Date: Wed, 8 Sep 2021 19:41:13 -0500 Subject: [PATCH 3/5] Implements default value stripping to accomodate reinstatement of default value population --- common/database/mongo_database.go | 3 +-- common/datastore/conversions.go | 7 +++---- common/datastore/datastore.go | 12 ++++++++++++ common/datastore/validation.go | 5 +---- services/registration/controller/controller.go | 18 +++++++++--------- .../service/registration_service.go | 6 +++--- 6 files changed, 29 insertions(+), 22 deletions(-) diff --git a/common/database/mongo_database.go b/common/database/mongo_database.go index 26a1b967..88e790ae 100644 --- a/common/database/mongo_database.go +++ b/common/database/mongo_database.go @@ -8,7 +8,6 @@ import ( "github.com/HackIllinois/api/common/config" "gopkg.in/mgo.v2" - "gopkg.in/mgo.v2/bson" ) /* @@ -204,7 +203,7 @@ func (db *MongoDatabase) Patch(collection_name string, selector interface{}, pat collection := current_session.DB(db.name).C(collection_name) - err := collection.Update(selector, bson.M{"$set": patch}) + err := collection.Update(selector, patch) return convertMgoError(err) } diff --git a/common/datastore/conversions.go b/common/datastore/conversions.go index 73cf958c..58611bcb 100644 --- a/common/datastore/conversions.go +++ b/common/datastore/conversions.go @@ -59,10 +59,9 @@ func toObject(raw_data interface{}, definition DataStoreDefinition) (interface{} if err != nil { return nil, NewErrInField(field.Name, err) } - } - // else { - // data[field.Name] = getDefaultValue(field.Type) //removed for registration/attendee patch function - // } + } else { + data[field.Name] = getDefaultValue(field.Type) + } } return data, nil diff --git a/common/datastore/datastore.go b/common/datastore/datastore.go index 5f1ce5f2..53f5198f 100644 --- a/common/datastore/datastore.go +++ b/common/datastore/datastore.go @@ -53,6 +53,18 @@ func NewErrInField(field_name string, err error) error { return ErrorInField{FieldName: field_name, Err: err} } +/* + Strips default values from +*/ +func StripDefaults(form DataStore) DataStore { + for key, element := range form.Data { + if element == 0 || element == 0.0 || element == false || element == nil || element == "" { + delete(form.Data, key) + } + } + return form +} + var conversionFuncs map[string](func(interface{}, DataStoreDefinition) (interface{}, error)) var defaultValues map[string]interface{} diff --git a/common/datastore/validation.go b/common/datastore/validation.go index 4003b0f4..4098ac73 100644 --- a/common/datastore/validation.go +++ b/common/datastore/validation.go @@ -5,11 +5,8 @@ import ( "gopkg.in/go-playground/validator.v9" ) -func (datastore *DataStore) Validate(params ...int) error { +func (datastore *DataStore) Validate() error { validate := validator.New() - if len(params) == 1{ - return nil - } return validateField(datastore.Data, datastore.Definition, validate) } diff --git a/services/registration/controller/controller.go b/services/registration/controller/controller.go index ba67a227..0e7dae05 100644 --- a/services/registration/controller/controller.go +++ b/services/registration/controller/controller.go @@ -269,36 +269,36 @@ func PatchCurrentUserRegistration(w http.ResponseWriter, r *http.Request) { return } - user_registration := datastore.NewDataStore(config.REGISTRATION_DEFINITION) - err := json.NewDecoder(r.Body).Decode(&user_registration) + registration_patch := datastore.NewDataStore(config.REGISTRATION_DEFINITION) + err := json.NewDecoder(r.Body).Decode(®istration_patch) if err != nil { errors.WriteError(w, r, errors.InternalError(err.Error(), "Could not decode user registration information. Possible failure in JSON validation, or invalid registration format.")) return } - user_registration.Data["id"] = id - - user_info, err := service.GetUserInfo(id) + registration_patch.Data["id"] = id if err != nil { errors.WriteError(w, r, errors.InternalError(err.Error(), "Could not get user info.")) return } - original_registration, err := service.GetUserRegistration(id) + user_registration, err := service.GetUserRegistration(id) if err != nil { errors.WriteError(w, r, errors.DatabaseError(err.Error(), "Could not get user's original registration.")) return } - user_registration.Data["github"] = user_info.Username + registration_patch = datastore.StripDefaults(registration_patch) + for key, element := range registration_patch.Data { + user_registration.Data[key] = element + } - user_registration.Data["createdAt"] = original_registration.Data["createdAt"] user_registration.Data["updatedAt"] = time.Now().Unix() - err = service.PatchUserRegistration(id, user_registration) + err = service.PatchUserRegistration(id, *user_registration) if err != nil { errors.WriteError(w, r, errors.InternalError(err.Error(), "Could not update user's registration.")) diff --git a/services/registration/service/registration_service.go b/services/registration/service/registration_service.go index fcc912fe..b6bbf748 100644 --- a/services/registration/service/registration_service.go +++ b/services/registration/service/registration_service.go @@ -93,8 +93,8 @@ func UpdateUserRegistration(id string, user_registration models.UserRegistration /* Patches the user registration associated with the given user id */ -func PatchUserRegistration(id string, user_registration models.UserRegistration) error { - err := user_registration.Validate(1) +func PatchUserRegistration(id string, registration_patch models.UserRegistration) error { + err := registration_patch.Validate() //make sure you remember to revalidate if err != nil { return err @@ -102,7 +102,7 @@ func PatchUserRegistration(id string, user_registration models.UserRegistration) selector := database.QuerySelector{"id": id} - err = db.Patch("attendees", selector, &user_registration) + err = db.Patch("attendees", selector, ®istration_patch) return err } From 1a33813830812bbd6d922a406a91c3dc8f85e24d Mon Sep 17 00:00:00 2001 From: kgukevin Date: Wed, 8 Sep 2021 19:52:42 -0500 Subject: [PATCH 4/5] Uses raw request json without default value population and filters fields with registration definition --- common/datastore/datastore.go | 12 ------------ gateway/services/registration.go | 2 +- services/registration/controller/controller.go | 16 ++++++++++------ 3 files changed, 11 insertions(+), 19 deletions(-) diff --git a/common/datastore/datastore.go b/common/datastore/datastore.go index 53f5198f..5f1ce5f2 100644 --- a/common/datastore/datastore.go +++ b/common/datastore/datastore.go @@ -53,18 +53,6 @@ func NewErrInField(field_name string, err error) error { return ErrorInField{FieldName: field_name, Err: err} } -/* - Strips default values from -*/ -func StripDefaults(form DataStore) DataStore { - for key, element := range form.Data { - if element == 0 || element == 0.0 || element == false || element == nil || element == "" { - delete(form.Data, key) - } - } - return form -} - var conversionFuncs map[string](func(interface{}, DataStoreDefinition) (interface{}, error)) var defaultValues map[string]interface{} diff --git a/gateway/services/registration.go b/gateway/services/registration.go index daf077fd..f043e4c0 100644 --- a/gateway/services/registration.go +++ b/gateway/services/registration.go @@ -40,7 +40,7 @@ var RegistrationRoutes = arbor.RouteCollection{ "PatchCurrentUserRegistration", "PATCH", "/registration/attendee/", - alice.New(middleware.AuthMiddleware([]models.Role{models.ApplicantRole}), middleware.IdentificationMiddleware).ThenFunc(PatchRegistration).ServeHTTP, + alice.New(middleware.AuthMiddleware([]models.Role{models.UserRole}), middleware.IdentificationMiddleware).ThenFunc(PatchRegistration).ServeHTTP, }, arbor.Route{ "GetFilteredUserRegistrations", diff --git a/services/registration/controller/controller.go b/services/registration/controller/controller.go index 0e7dae05..1c1474b7 100644 --- a/services/registration/controller/controller.go +++ b/services/registration/controller/controller.go @@ -2,11 +2,13 @@ package controller import ( "encoding/json" + // "fmt" "net/http" "time" "github.com/HackIllinois/api/common/datastore" "github.com/HackIllinois/api/common/errors" + // "github.com/HackIllinois/api/services/registration" "github.com/HackIllinois/api/services/registration/config" "github.com/HackIllinois/api/services/registration/models" "github.com/HackIllinois/api/services/registration/service" @@ -268,8 +270,8 @@ func PatchCurrentUserRegistration(w http.ResponseWriter, r *http.Request) { errors.WriteError(w, r, errors.MalformedRequestError("Must provide id in request.", "Must provide id in request.")) return } - - registration_patch := datastore.NewDataStore(config.REGISTRATION_DEFINITION) + + var registration_patch map[string]interface{} err := json.NewDecoder(r.Body).Decode(®istration_patch) if err != nil { @@ -277,7 +279,7 @@ func PatchCurrentUserRegistration(w http.ResponseWriter, r *http.Request) { return } - registration_patch.Data["id"] = id + registration_patch["id"] = id if err != nil { errors.WriteError(w, r, errors.InternalError(err.Error(), "Could not get user info.")) @@ -291,9 +293,11 @@ func PatchCurrentUserRegistration(w http.ResponseWriter, r *http.Request) { return } - registration_patch = datastore.StripDefaults(registration_patch) - for key, element := range registration_patch.Data { - user_registration.Data[key] = element + registration_definition := datastore.NewDataStore(config.REGISTRATION_DEFINITION) + for _, field := range registration_definition.Definition.Fields { + if val, ok := registration_patch[field.Name]; ok { + user_registration.Data[field.Name] = val + } } user_registration.Data["updatedAt"] = time.Now().Unix() From 60d6f89ed1b96a739bcadb6baba6964b7311dd52 Mon Sep 17 00:00:00 2001 From: kgukevin Date: Wed, 8 Sep 2021 22:06:56 -0500 Subject: [PATCH 5/5] Make patch database operations atomic --- common/database/mongo_database.go | 3 +- common/datastore/validation.go | 35 +++++++++++++++---- gateway/services/registration.go | 2 +- .../registration/controller/controller.go | 34 ++++++------------ .../service/registration_service.go | 2 +- .../registration/tests/registration_test.go | 12 +++++-- 6 files changed, 53 insertions(+), 35 deletions(-) diff --git a/common/database/mongo_database.go b/common/database/mongo_database.go index 88e790ae..26a1b967 100644 --- a/common/database/mongo_database.go +++ b/common/database/mongo_database.go @@ -8,6 +8,7 @@ import ( "github.com/HackIllinois/api/common/config" "gopkg.in/mgo.v2" + "gopkg.in/mgo.v2/bson" ) /* @@ -203,7 +204,7 @@ func (db *MongoDatabase) Patch(collection_name string, selector interface{}, pat collection := current_session.DB(db.name).C(collection_name) - err := collection.Update(selector, patch) + err := collection.Update(selector, bson.M{"$set": patch}) return convertMgoError(err) } diff --git a/common/datastore/validation.go b/common/datastore/validation.go index 4098ac73..17cbe261 100644 --- a/common/datastore/validation.go +++ b/common/datastore/validation.go @@ -2,16 +2,28 @@ package datastore import ( "fmt" + "gopkg.in/go-playground/validator.v9" ) func (datastore *DataStore) Validate() error { validate := validator.New() - return validateField(datastore.Data, datastore.Definition, validate) + return validateField(datastore.Data, datastore.Definition, validate, false) +} + +func (datastore *DataStore) ValidateNonEmpty() error { + validate := validator.New() + + return validateField(datastore.Data, datastore.Definition, validate, true) } -func validateField(data interface{}, definition DataStoreDefinition, validate *validator.Validate) error { +func validateField( + data interface{}, + definition DataStoreDefinition, + validate *validator.Validate, + ignore_empty bool, +) error { err := validate.Var(data, definition.Validations) if err != nil { @@ -26,7 +38,7 @@ func validateField(data interface{}, definition DataStoreDefinition, validate *v return NewErrTypeMismatch(data, "map[string]interface{}") } - return validateFieldArray(mapped_data, definition, validate) + return validateFieldArray(mapped_data, definition, validate, ignore_empty) case "[]object": data_array, ok := data.([]map[string]interface{}) @@ -35,7 +47,7 @@ func validateField(data interface{}, definition DataStoreDefinition, validate *v } for _, mapped_data := range data_array { - err = validateFieldArray(mapped_data, definition, validate) + err = validateFieldArray(mapped_data, definition, validate, ignore_empty) if err != nil { return err @@ -48,9 +60,20 @@ func validateField(data interface{}, definition DataStoreDefinition, validate *v } } -func validateFieldArray(data map[string]interface{}, definition DataStoreDefinition, validate *validator.Validate) error { +func validateFieldArray( + data map[string]interface{}, + definition DataStoreDefinition, + validate *validator.Validate, + ignore_empty bool, +) error { for _, field := range definition.Fields { - err := validateField(data[field.Name], field, validate) + if ignore_empty { + if _, ok := data[field.Name]; !ok { + continue + } + } + + err := validateField(data[field.Name], field, validate, ignore_empty) if err != nil { return err diff --git a/gateway/services/registration.go b/gateway/services/registration.go index f043e4c0..daf077fd 100644 --- a/gateway/services/registration.go +++ b/gateway/services/registration.go @@ -40,7 +40,7 @@ var RegistrationRoutes = arbor.RouteCollection{ "PatchCurrentUserRegistration", "PATCH", "/registration/attendee/", - alice.New(middleware.AuthMiddleware([]models.Role{models.UserRole}), middleware.IdentificationMiddleware).ThenFunc(PatchRegistration).ServeHTTP, + alice.New(middleware.AuthMiddleware([]models.Role{models.ApplicantRole}), middleware.IdentificationMiddleware).ThenFunc(PatchRegistration).ServeHTTP, }, arbor.Route{ "GetFilteredUserRegistrations", diff --git a/services/registration/controller/controller.go b/services/registration/controller/controller.go index 1c1474b7..d56e3705 100644 --- a/services/registration/controller/controller.go +++ b/services/registration/controller/controller.go @@ -2,13 +2,11 @@ package controller import ( "encoding/json" - // "fmt" "net/http" "time" "github.com/HackIllinois/api/common/datastore" "github.com/HackIllinois/api/common/errors" - // "github.com/HackIllinois/api/services/registration" "github.com/HackIllinois/api/services/registration/config" "github.com/HackIllinois/api/services/registration/models" "github.com/HackIllinois/api/services/registration/service" @@ -271,38 +269,28 @@ func PatchCurrentUserRegistration(w http.ResponseWriter, r *http.Request) { return } - var registration_patch map[string]interface{} - err := json.NewDecoder(r.Body).Decode(®istration_patch) + var patch_data map[string]interface{} + err := json.NewDecoder(r.Body).Decode(&patch_data) if err != nil { errors.WriteError(w, r, errors.InternalError(err.Error(), "Could not decode user registration information. Possible failure in JSON validation, or invalid registration format.")) return } - registration_patch["id"] = id + patch_data["id"] = id - if err != nil { - errors.WriteError(w, r, errors.InternalError(err.Error(), "Could not get user info.")) - return - } - - user_registration, err := service.GetUserRegistration(id) - - if err != nil { - errors.WriteError(w, r, errors.DatabaseError(err.Error(), "Could not get user's original registration.")) - return - } - - registration_definition := datastore.NewDataStore(config.REGISTRATION_DEFINITION) - for _, field := range registration_definition.Definition.Fields { - if val, ok := registration_patch[field.Name]; ok { - user_registration.Data[field.Name] = val + registration_patch := datastore.NewDataStore(config.REGISTRATION_DEFINITION) + for _, field := range registration_patch.Definition.Fields { + if _, ok := patch_data[field.Name]; !ok { + delete(patch_data, field.Name) } } - user_registration.Data["updatedAt"] = time.Now().Unix() + registration_patch.Data = patch_data; + + registration_patch.Data["updatedAt"] = time.Now().Unix() - err = service.PatchUserRegistration(id, *user_registration) + err = service.PatchUserRegistration(id, registration_patch) if err != nil { errors.WriteError(w, r, errors.InternalError(err.Error(), "Could not update user's registration.")) diff --git a/services/registration/service/registration_service.go b/services/registration/service/registration_service.go index b6bbf748..708394d5 100644 --- a/services/registration/service/registration_service.go +++ b/services/registration/service/registration_service.go @@ -94,7 +94,7 @@ func UpdateUserRegistration(id string, user_registration models.UserRegistration Patches the user registration associated with the given user id */ func PatchUserRegistration(id string, registration_patch models.UserRegistration) error { - err := registration_patch.Validate() //make sure you remember to revalidate + err := registration_patch.ValidateNonEmpty() if err != nil { return err diff --git a/services/registration/tests/registration_test.go b/services/registration/tests/registration_test.go index fdd227de..3eedc081 100644 --- a/services/registration/tests/registration_test.go +++ b/services/registration/tests/registration_test.go @@ -167,9 +167,15 @@ func TestUpdateUserRegistrationService(t *testing.T) { */ func TestPatchUserRegistrationService(t *testing.T) { SetupTestDB(t) - base_registration := datastore.NewDataStore(config.REGISTRATION_DEFINITION) - json.Unmarshal([]byte(patch_registration_data), &base_registration) - err := service.PatchUserRegistration("testid", base_registration) + test_registration := datastore.NewDataStore(config.REGISTRATION_DEFINITION) + json.Unmarshal([]byte(patch_registration_data), &test_registration) + test_data := make (map[string]interface{}) + test_data["firstName"] = "John" + test_data["lastName"] = "Smith" + test_data["email"] = "new_test@gmail.com" + test_registration.Data = test_data + fmt.Println(test_registration) + err := service.PatchUserRegistration("testid", test_registration) if err != nil { t.Fatal(err)