From 76e5dec3188fa25f4fa5747a9db262c51a4e9c43 Mon Sep 17 00:00:00 2001 From: Maksym Hrynenko Date: Wed, 11 Dec 2024 14:41:32 +0200 Subject: [PATCH 1/3] feature: implement upsert to update params for users with the same user id --- internal/data/pg/verify_users.go | 30 ++++++++++++++++++------------ internal/data/verify_users.go | 2 +- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/internal/data/pg/verify_users.go b/internal/data/pg/verify_users.go index bba72f4..ba15076 100644 --- a/internal/data/pg/verify_users.go +++ b/internal/data/pg/verify_users.go @@ -6,12 +6,10 @@ import ( "fmt" "time" - "github.com/pkg/errors" - "gitlab.com/distributed_lab/kit/pgdb" - sq "github.com/Masterminds/squirrel" - + "github.com/pkg/errors" "github.com/rarimo/verificator-svc/internal/data" + "gitlab.com/distributed_lab/kit/pgdb" ) type VerifyUsersQ struct { @@ -62,14 +60,14 @@ func (q *VerifyUsersQ) Get() (*data.VerifyUsers, error) { return &result, nil } -func (q *VerifyUsersQ) Insert(VerifyUsers *data.VerifyUsers) error { +func (q *VerifyUsersQ) Upsert(VerifyUsers *data.VerifyUsers) (data.VerifyUsers, error) { + var response data.VerifyUsers proofJSON, err := json.Marshal(VerifyUsers.Proof) if err != nil { - return fmt.Errorf("failed to marshal proof for user %s: %w", VerifyUsers.UserID, err) + return response, fmt.Errorf("failed to marshal proof for user %s: %w", VerifyUsers.UserID, err) } - stmt := sq.Insert(verifyUsersTableName).SetMap(map[string]interface{}{ - "user_id": VerifyUsers.UserID, + newData := map[string]interface{}{ "user_id_hash": VerifyUsers.UserIDHash, "age_lower_bound": VerifyUsers.AgeLowerBound, "nationality": VerifyUsers.Nationality, @@ -83,13 +81,21 @@ func (q *VerifyUsersQ) Insert(VerifyUsers *data.VerifyUsers) error { "anonymous_id": VerifyUsers.AnonymousID, "nullifier": VerifyUsers.Nullifier, "expiration_lower_bound": VerifyUsers.ExpirationLowerBound, - }) + } + + updateStmt, args, _ := sq.Update(" ").SetMap(newData).ToSql() + + newData["user_id"] = VerifyUsers.UserID - if err = q.db.Exec(stmt); err != nil { - return fmt.Errorf("insert user %+v: %w", VerifyUsers, err) + query := sq.Insert(verifyUsersTableName).SetMap(newData). + Suffix("ON CONFLICT (user_id) DO "+updateStmt, args...). + Suffix("RETURNING *") + + if err = q.db.Get(&response, query); err != nil { + return response, errors.Wrap(err, "failed to upsert new row") } - return nil + return response, nil } func (q *VerifyUsersQ) Update(VerifyUsers *data.VerifyUsers) error { diff --git a/internal/data/verify_users.go b/internal/data/verify_users.go index 6deec05..1649705 100644 --- a/internal/data/verify_users.go +++ b/internal/data/verify_users.go @@ -28,7 +28,7 @@ type VerifyUsersQ interface { Get() (*VerifyUsers, error) Select() ([]VerifyUsers, error) Update(*VerifyUsers) error - Insert(*VerifyUsers) error + Upsert(*VerifyUsers) (VerifyUsers, error) Delete() error DeleteByID(*VerifyUsers) error From 1ced894871132d0112efe87ee3ef63709b38571d Mon Sep 17 00:00:00 2001 From: Maksym Hrynenko Date: Wed, 11 Dec 2024 14:42:16 +0200 Subject: [PATCH 2/3] add: helper function to check default ZK date --- internal/service/handlers/helpers/proof_params.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/internal/service/handlers/helpers/proof_params.go b/internal/service/handlers/helpers/proof_params.go index 9a6f57a..54531ba 100644 --- a/internal/service/handlers/helpers/proof_params.go +++ b/internal/service/handlers/helpers/proof_params.go @@ -157,3 +157,7 @@ func CheckUniqueness(selectorInt int, serviceStartTimestamp, identityTimestampUp return status, nil } + +func IsDefaultZKDate(date string) bool { + return date == DefaultDateHex +} From 4991bce6b02b5451edd740623da9dbe79477dace Mon Sep 17 00:00:00 2001 From: Maksym Hrynenko Date: Wed, 11 Dec 2024 14:44:44 +0200 Subject: [PATCH 3/3] update: use Upsert instead of Get/Insert approach, use helper default zk date for clear code --- .../service/handlers/get_proof_parameters.go | 16 +++------------- internal/service/handlers/proof_params.go | 2 +- internal/service/handlers/proof_params_light.go | 2 +- internal/service/handlers/verification_link.go | 17 +++-------------- .../service/handlers/verification_link_light.go | 16 +++------------- 5 files changed, 11 insertions(+), 42 deletions(-) diff --git a/internal/service/handlers/get_proof_parameters.go b/internal/service/handlers/get_proof_parameters.go index a4d8490..fdfc05a 100644 --- a/internal/service/handlers/get_proof_parameters.go +++ b/internal/service/handlers/get_proof_parameters.go @@ -83,22 +83,12 @@ func GetProofParameters(w http.ResponseWriter, r *http.Request) { TimestampUpperBound: TimestampUpperBound, } - existingUser, err := VerifyUsersQ(r).WhereHashID(user.UserIDHash).Get() + dbUser, err := VerifyUsersQ(r).Upsert(user) if err != nil { - Log(r).WithError(err).Errorf("failed to query user with userID [%s]", user.UserIDHash) - ape.RenderErr(w, problems.InternalError()) - return - } - if existingUser != nil { - ape.Render(w, responses.NewProofParametersResponse(*existingUser, proofParameters)) - return - } - - if err = VerifyUsersQ(r).Insert(user); err != nil { - Log(r).WithError(err).Errorf("failed to insert user with userID [%s]", user.UserIDHash) + Log(r).WithError(err).WithField("user", user).Errorf("failed to upsert user with userID [%s]", user.UserIDHash) ape.RenderErr(w, problems.InternalError()) return } - ape.Render(w, responses.NewProofParametersResponse(*user, proofParameters)) + ape.Render(w, responses.NewProofParametersResponse(dbUser, proofParameters)) } diff --git a/internal/service/handlers/proof_params.go b/internal/service/handlers/proof_params.go index ed50cda..372de91 100644 --- a/internal/service/handlers/proof_params.go +++ b/internal/service/handlers/proof_params.go @@ -43,7 +43,7 @@ func GetProofParamsById(w http.ResponseWriter, r *http.Request) { Nationality: existingUser.Nationality, SexEnable: existingUser.SexEnable, NationalityEnable: existingUser.NationalityEnable, - ExpirationLowerBound: existingUser.ExpirationLowerBound != helpers.DefaultDateHex, // If there is non-default value, selector should be enabled + ExpirationLowerBound: !helpers.IsDefaultZKDate(existingUser.ExpirationLowerBound), // If there is non-default value, selector should be enabled }) callbackURL = fmt.Sprintf("%s/integrations/verificator-svc/public/callback/%s", Callback(r).URL, userIDHash) ) diff --git a/internal/service/handlers/proof_params_light.go b/internal/service/handlers/proof_params_light.go index 4b69f0c..3121478 100644 --- a/internal/service/handlers/proof_params_light.go +++ b/internal/service/handlers/proof_params_light.go @@ -43,7 +43,7 @@ func GetProofParamsLightById(w http.ResponseWriter, r *http.Request) { Nationality: existingUser.Nationality, SexEnable: existingUser.SexEnable, NationalityEnable: existingUser.NationalityEnable, - ExpirationLowerBound: existingUser.ExpirationLowerBound != helpers.DefaultDateHex, // If there is non-default value, selector should be enabled + ExpirationLowerBound: !helpers.IsDefaultZKDate(existingUser.ExpirationLowerBound), // If there is non-default value, selector should be enabled }) callbackURL = fmt.Sprintf("%s/integrations/verificator-svc/light/public/callback-sign/%s", Callback(r).URL, userIDHash) ) diff --git a/internal/service/handlers/verification_link.go b/internal/service/handlers/verification_link.go index 287db5a..4d4dcdf 100644 --- a/internal/service/handlers/verification_link.go +++ b/internal/service/handlers/verification_link.go @@ -64,23 +64,12 @@ func VerificationLink(w http.ResponseWriter, r *http.Request) { user.ExpirationLowerBound = helpers.GetExpirationLowerBound(*req.Data.Attributes.ExpirationLowerBound) } - existingUser, err := VerifyUsersQ(r).WhereHashID(user.UserIDHash).Get() + dbUser, err := VerifyUsersQ(r).Upsert(user) if err != nil { - Log(r).WithError(err).Errorf("failed to query user with userID [%s]", user.UserIDHash) + Log(r).WithError(err).WithField("user", user).Errorf("failed to upsert user with userID [%s]", user.UserIDHash) ape.RenderErr(w, problems.InternalError()) return } - if existingUser != nil { - ape.Render(w, responses.NewVerificationLinkResponse(*existingUser, Callback(r).URL)) - return - } - - if err = VerifyUsersQ(r).Insert(user); err != nil { - Log(r).WithError(err).Errorf("failed to insert user with userID [%s]", user.UserIDHash) - ape.RenderErr(w, problems.InternalError()) - return - } - - ape.Render(w, responses.NewVerificationLinkResponse(*user, Callback(r).URL)) + ape.Render(w, responses.NewVerificationLinkResponse(dbUser, Callback(r).URL)) } diff --git a/internal/service/handlers/verification_link_light.go b/internal/service/handlers/verification_link_light.go index 121b05e..1a16540 100644 --- a/internal/service/handlers/verification_link_light.go +++ b/internal/service/handlers/verification_link_light.go @@ -60,23 +60,13 @@ func VerificationLinkLight(w http.ResponseWriter, r *http.Request) { user.ExpirationLowerBound = helpers.GetExpirationLowerBound(*req.Data.Attributes.ExpirationLowerBound) } - existingUser, err := VerifyUsersQ(r).WhereHashID(user.UserIDHash).Get() + dbUser, err := VerifyUsersQ(r).Upsert(user) if err != nil { - Log(r).WithError(err).Errorf("failed to query user with userID [%s]", user.UserIDHash) - ape.RenderErr(w, problems.InternalError()) - return - } - if existingUser != nil { - ape.Render(w, responses.NewVerificationLinkLightResponse(*existingUser, Callback(r).URL)) - return - } - - if err = VerifyUsersQ(r).Insert(user); err != nil { - Log(r).WithError(err).Errorf("failed to insert user with userID [%s]", user.UserIDHash) + Log(r).WithError(err).WithField("user", user).Errorf("failed to upsert user with userID [%s]", user.UserIDHash) ape.RenderErr(w, problems.InternalError()) return } - ape.Render(w, responses.NewVerificationLinkLightResponse(*user, Callback(r).URL)) + ape.Render(w, responses.NewVerificationLinkLightResponse(dbUser, Callback(r).URL)) }