Skip to content

Commit

Permalink
CMC post link duplicate check. (#241)
Browse files Browse the repository at this point in the history
  • Loading branch information
ice-myles authored Nov 22, 2024
1 parent d848f1e commit 5d873ec
Show file tree
Hide file tree
Showing 7 changed files with 33 additions and 21 deletions.
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ require (
require (
cel.dev/expr v0.18.0 // indirect
cloud.google.com/go v0.116.0 // indirect
cloud.google.com/go/auth v0.10.2 // indirect
cloud.google.com/go/auth/oauth2adapt v0.2.5 // indirect
cloud.google.com/go/auth v0.11.0 // indirect
cloud.google.com/go/auth/oauth2adapt v0.2.6 // indirect
cloud.google.com/go/compute/metadata v0.5.2 // indirect
cloud.google.com/go/firestore v1.17.0 // indirect
cloud.google.com/go/iam v1.2.2 // indirect
Expand Down Expand Up @@ -184,7 +184,7 @@ require (
golang.org/x/text v0.20.0 // indirect
golang.org/x/time v0.8.0 // indirect
golang.org/x/tools v0.27.0 // indirect
google.golang.org/api v0.208.0 // indirect
google.golang.org/api v0.209.0 // indirect
google.golang.org/appengine/v2 v2.0.6 // indirect
google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20241118233622-e639e219e697 // indirect
Expand Down
12 changes: 6 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ cel.dev/expr v0.18.0/go.mod h1:MrpN08Q+lEBs+bGYdLxxHkZoUSsCp0nSKTs0nTymJgw=
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.116.0 h1:B3fRrSDkLRt5qSHWe40ERJvhvnQwdZiHu0bJOpldweE=
cloud.google.com/go v0.116.0/go.mod h1:cEPSRWPzZEswwdr9BxE6ChEn01dWlTaF05LiC2Xs70U=
cloud.google.com/go/auth v0.10.2 h1:oKF7rgBfSHdp/kuhXtqU/tNDr0mZqhYbEh+6SiqzkKo=
cloud.google.com/go/auth v0.10.2/go.mod h1:xxA5AqpDrvS+Gkmo9RqrGGRh6WSNKKOXhY3zNOr38tI=
cloud.google.com/go/auth/oauth2adapt v0.2.5 h1:2p29+dePqsCHPP1bqDJcKj4qxRyYCcbzKpFyKGt3MTk=
cloud.google.com/go/auth/oauth2adapt v0.2.5/go.mod h1:AlmsELtlEBnaNTL7jCj8VQFLy6mbZv0s4Q7NGBeQ5E8=
cloud.google.com/go/auth v0.11.0 h1:Ic5SZz2lsvbYcWT5dfjNWgw6tTlGi2Wc8hyQSC9BstA=
cloud.google.com/go/auth v0.11.0/go.mod h1:xxA5AqpDrvS+Gkmo9RqrGGRh6WSNKKOXhY3zNOr38tI=
cloud.google.com/go/auth/oauth2adapt v0.2.6 h1:V6a6XDu2lTwPZWOawrAa9HUK+DB2zfJyTuciBG5hFkU=
cloud.google.com/go/auth/oauth2adapt v0.2.6/go.mod h1:AlmsELtlEBnaNTL7jCj8VQFLy6mbZv0s4Q7NGBeQ5E8=
cloud.google.com/go/compute/metadata v0.5.2 h1:UxK4uu/Tn+I3p2dYWTfiX4wva7aYlKixAHn3fyqngqo=
cloud.google.com/go/compute/metadata v0.5.2/go.mod h1:C66sj2AluDcIqakBq/M8lw8/ybHgOZqin2obFxa/E5k=
cloud.google.com/go/firestore v1.17.0 h1:iEd1LBbkDZTFsLw3sTH50eyg4qe8eoG6CjocmEXO9aQ=
Expand Down Expand Up @@ -563,8 +563,8 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.208.0 h1:8Y62MUGRviQnnP9/41/bYAGySPKAN9iwzV96ZvhwyVE=
google.golang.org/api v0.208.0/go.mod h1:I53S168Yr/PNDNMi5yPnDc0/LGRZO6o7PoEbl/HY3CM=
google.golang.org/api v0.209.0 h1:Ja2OXNlyRlWCWu8o+GgI4yUn/wz9h/5ZfFbKz+dQX+w=
google.golang.org/api v0.209.0/go.mod h1:I53S168Yr/PNDNMi5yPnDc0/LGRZO6o7PoEbl/HY3CM=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine/v2 v2.0.6 h1:LvPZLGuchSBslPBp+LAhihBeGSiRh1myRoYK4NtuBIw=
Expand Down
5 changes: 5 additions & 0 deletions kyc/social/DDL.sql
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ CREATE TABLE IF NOT EXISTS socials (
social text NOT NULL CHECK (social = 'twitter' OR social = 'facebook'),
user_handle text NOT NULL,
PRIMARY KEY (social, user_handle));
ALTER TABLE socials
DROP CONSTRAINT socials_social_check;
ALTER TABLE socials
ADD CONSTRAINT socials_social_check
CHECK (social = 'twitter' OR social = 'facebook' OR social = 'cmc');

ALTER TABLE socials DROP CONSTRAINT socials_pkey, ADD PRIMARY KEY (social, user_handle);
ALTER TABLE socials DROP CONSTRAINT IF EXISTS socials_social_user_handle_key;
Expand Down
1 change: 1 addition & 0 deletions kyc/social/contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ type (
VerifyPost(ctx context.Context, metadata *VerificationMetadata) (*Verification, error)
SkipVerification(ctx context.Context, kycStep users.KYCStep, userID string) error
ExpectedPostTemplateText(user *users.User, vm *VerificationMetadata) string
SaveSocial(ctx context.Context, socialType Type, userID, userHandle string) error
}
UserRepository interface {
GetUserByID(ctx context.Context, userID string) (*users.UserProfile, error)
Expand Down
20 changes: 11 additions & 9 deletions kyc/social/social.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ func (r *repository) VerifyPost(ctx context.Context, metadata *VerificationMetad
}
if userHandle != "" { //nolint:nestif // .
userHandle = strings.ToLower(userHandle)
if err = r.saveSocial(ctx, metadata.Social, metadata.UserID, userHandle); err != nil {
if err = r.SaveSocial(ctx, metadata.Social, metadata.UserID, userHandle); err != nil {
if storage.IsErr(err, storage.ErrDuplicate) {
log.Error(errors.Wrapf(err, "[duplicate]social verification failed for KYCStep:%v,Social:%v,Language:%v,userID:%v,userHandle:%v",
metadata.KYCStep, metadata.Social, metadata.Language, metadata.UserID, userHandle))
Expand Down Expand Up @@ -335,16 +335,18 @@ func (r *repository) saveUnsuccessfulAttempt(ctx context.Context, now *time.Time
return errors.Wrapf(err, "failed to `%v`; kycStep:%v,userId:%v,social:%v,reason:%v", sql, metadata.KYCStep, metadata.UserID, metadata.Social, reason)
}

func (r *repository) saveSocial(ctx context.Context, socialType Type, userID, userHandle string) error {
func (r *repository) SaveSocial(ctx context.Context, socialType Type, userID, userHandle string) error {
sql := `INSERT INTO socials(user_id,social,user_handle) VALUES ($1,$2,$3)`
_, err := storage.Exec(ctx, r.db, sql, userID, socialType, userHandle)
if err != nil && storage.IsErr(err, storage.ErrDuplicate, "pk") {
sql = `SELECT true AS bogus WHERE EXISTS (SELECT 1 FROM socials WHERE user_id = $1 AND social = $2 AND lower(user_handle) = $3)`
if _, err2 := storage.ExecOne[struct{ Bogus bool }](ctx, r.db, sql, userID, socialType, userHandle); err2 == nil {
return nil
} else if !storage.IsErr(err2, storage.ErrNotFound) {
err = errors.Wrapf(err2, "failed to check if user used the same userhandle previously; userID:%v, social:%v, userHandle:%v",
userID, socialType, userHandle)
if socialType != CMCType {
if err != nil && storage.IsErr(err, storage.ErrDuplicate, "pk") {
sql = `SELECT true AS bogus WHERE EXISTS (SELECT 1 FROM socials WHERE user_id = $1 AND social = $2 AND lower(user_handle) = $3)`
if _, err2 := storage.ExecOne[struct{ Bogus bool }](ctx, r.db, sql, userID, socialType, userHandle); err2 == nil {
return nil
} else if !storage.IsErr(err2, storage.ErrNotFound) {
err = errors.Wrapf(err2, "failed to check if user used the same userhandle previously; userID:%v, social:%v, userHandle:%v",
userID, socialType, userHandle)
}
}
}

Expand Down
6 changes: 3 additions & 3 deletions kyc/social/social_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,15 @@ func TestSocialSave(t *testing.T) {
helperRemoveSocials(t, db, userName)

t.Run("OK", func(t *testing.T) {
err := repo.saveSocial(ctx, TwitterType, userName, "foo")
err := repo.SaveSocial(ctx, TwitterType, userName, "foo")
require.NoError(t, err)

err = repo.saveSocial(ctx, TwitterType, userName, "bar")
err = repo.SaveSocial(ctx, TwitterType, userName, "bar")
require.NoError(t, err)
})

t.Run("Duplicate", func(t *testing.T) {
err := repo.saveSocial(ctx, TwitterType, userName, "foo")
err := repo.SaveSocial(ctx, TwitterType, userName, "foo")
require.ErrorIs(t, err, storage.ErrDuplicate)

reason := DetectReason(terror.New(err, map[string]any{"user_handle": "foo"}))
Expand Down
4 changes: 4 additions & 0 deletions kyc/verification_scenarios/verification_scenarios.go
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,10 @@ func (r *repository) VerifyCMC(ctx context.Context, metadata *VerificationMetada
return errors.Wrapf(ErrVerificationNotPassed,
"can't verify post for cmc verifier userID:%v,reason:%v", metadata.UserID, err.Error())
}
if sErr := r.socialRepo.SaveSocial(ctx, social.CMCType, metadata.UserID, metadata.CMCProfileLink); sErr != nil {
return errors.Wrapf(ErrVerificationNotPassed,
"can't save social for userID:%v for post link: %v, reason: %v", metadata.UserID, metadata.CMCProfileLink, social.DetectReason(sErr))
}

return nil
}
Expand Down

0 comments on commit 5d873ec

Please sign in to comment.