Skip to content

Commit

Permalink
split the social kyc config into 2 separate jsons, one for each socia…
Browse files Browse the repository at this point in the history
…l kyc step
  • Loading branch information
ice-ares committed Jul 9, 2024
1 parent f0d0e4d commit f2dd67a
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 59 deletions.
16 changes: 7 additions & 9 deletions kyc/social/contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,29 +119,27 @@ type (
db *storage.DB
}

kycConfigJSON struct {
kycConfigJSON1 struct {
Social1KYC struct {
xPostPatternTemplate *template.Template `json:"-"` //nolint:revive // .
XPostPattern string `json:"xPostPattern"`
XPostLink string `json:"xPostLink"`
} `json:"social1-kyc"` //nolint:tagliatelle // .
}
kycConfigJSON2 struct {
Social2KYC struct {
xPostPatternTemplate *template.Template `json:"-"` //nolint:revive // .
XPostPattern string `json:"xPostPattern"`
XPostLink string `json:"xPostLink"`
} `json:"social2-kyc"` //nolint:tagliatelle // .
DynamicDistributionSocialKYC []*struct {
xPostPatternTemplate *template.Template `json:"-"` //nolint:revive // .
XPostPattern string `json:"xPostPattern"`
XPostLink string `json:"xPostLink"`
KYCStep users.KYCStep `json:"step"` //nolint:tagliatelle // .
} `json:"dynamic-distribution-kyc"` //nolint:tagliatelle // .
}

config struct {
alertFrequency *sync.Map // .map[users.KYCStep]stdlibtime.Duration.
kycConfigJSON *atomic.Pointer[kycConfigJSON]
ConfigJSONURL string `yaml:"config-json-url" mapstructure:"config-json-url"` //nolint:tagliatelle // .
kycConfigJSON1 *atomic.Pointer[kycConfigJSON1]
kycConfigJSON2 *atomic.Pointer[kycConfigJSON2]
ConfigJSONURL1 string `yaml:"config-json-url1" mapstructure:"config-json-url1"` //nolint:tagliatelle // .
ConfigJSONURL2 string `yaml:"config-json-url2" mapstructure:"config-json-url2"` //nolint:tagliatelle // .
Environment string `yaml:"environment" mapstructure:"environment"`
AlertSlackWebhook string `yaml:"alert-slack-webhook" mapstructure:"alert-slack-webhook"` //nolint:tagliatelle // .
TenantName string `yaml:"tenant-name" mapstructure:"tenant-name"` //nolint:tagliatelle // .
Expand Down
88 changes: 56 additions & 32 deletions kyc/social/remote_kyc_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ package social

import (
"context"
"fmt"
"net/http"
"strings"
"sync/atomic"
Expand All @@ -27,23 +26,28 @@ func init() { //nolint:gochecknoinits // It's the only way to tweak the client.
func (r *repository) startKYCConfigJSONSyncer(ctx context.Context) {
ticker := stdlibtime.NewTicker(stdlibtime.Minute)
defer ticker.Stop()
r.cfg.kycConfigJSON = new(atomic.Pointer[kycConfigJSON])
log.Panic(errors.Wrap(r.syncKYCConfigJSON(ctx), "failed to syncKYCConfigJSON")) //nolint:revive // .
r.cfg.kycConfigJSON1 = new(atomic.Pointer[kycConfigJSON1])
r.cfg.kycConfigJSON2 = new(atomic.Pointer[kycConfigJSON2])
log.Panic(errors.Wrap(r.syncKYCConfigJSON1(ctx), "failed to syncKYCConfigJSON1")) //nolint:revive // .
log.Panic(errors.Wrap(r.syncKYCConfigJSON2(ctx), "failed to syncKYCConfigJSON2"))

for {
select {
case <-ticker.C:
reqCtx, cancel := context.WithTimeout(ctx, requestDeadline)
log.Error(errors.Wrap(r.syncKYCConfigJSON(reqCtx), "failed to syncKYCConfigJSON"))
log.Error(errors.Wrap(r.syncKYCConfigJSON1(reqCtx), "failed to syncKYCConfigJSON1"))
cancel()
reqCtx, cancel = context.WithTimeout(ctx, requestDeadline)
log.Error(errors.Wrap(r.syncKYCConfigJSON2(reqCtx), "failed to syncKYCConfigJSON2"))
cancel()
case <-ctx.Done():
return
}
}
}

//nolint:funlen,gomnd,nestif // .
func (r *repository) syncKYCConfigJSON(ctx context.Context) error {
//nolint:funlen,gomnd,nestif,dupl,revive // .
func (r *repository) syncKYCConfigJSON1(ctx context.Context) error {
if resp, err := req.
SetContext(ctx).
SetRetryCount(25).
Expand All @@ -62,48 +66,68 @@ func (r *repository) syncKYCConfigJSON(ctx context.Context) error {
SetHeader("Cache-Control", "no-cache, no-store, must-revalidate").
SetHeader("Pragma", "no-cache").
SetHeader("Expires", "0").
Get(r.cfg.ConfigJSONURL); err != nil {
return errors.Wrapf(err, "failed to get fetch `%v`", r.cfg.ConfigJSONURL)
Get(r.cfg.ConfigJSONURL1); err != nil {
return errors.Wrapf(err, "failed to get fetch `%v`", r.cfg.ConfigJSONURL1)
} else if data, err2 := resp.ToBytes(); err2 != nil {
return errors.Wrapf(err2, "failed to read body of `%v`", r.cfg.ConfigJSONURL)
return errors.Wrapf(err2, "failed to read body of `%v`", r.cfg.ConfigJSONURL1)
} else { //nolint:revive // .
var kycConfig kycConfigJSON
var kycConfig kycConfigJSON1
if err = json.UnmarshalContext(ctx, data, &kycConfig); err != nil {
return errors.Wrapf(err, "failed to unmarshal into %#v, data: %v", kycConfig, string(data))
}
if body := string(data); !strings.Contains(body, "social1-kyc") && !strings.Contains(body, "social2-kyc") {
if body := string(data); !strings.Contains(body, "social1-kyc") {
return errors.Errorf("there's something wrong with the KYCConfigJSON body: %v", body)
}
if err = r.initKYCConfig(&kycConfig); err != nil {
return errors.Wrapf(err, "failed to init KYCConfigJSON %+v", &kycConfig)
if pattern := kycConfig.Social1KYC.XPostPattern; pattern != "" {
if kycConfig.Social1KYC.xPostPatternTemplate, err = template.New("kycCfg.Social1KYC.XPostPattern").Parse(pattern); err != nil {
return errors.Wrapf(err, "failed to parse kycCfg.Social1KYC.xPostPatternTemplate `%v`", pattern)
}
}
r.cfg.kycConfigJSON.Swap(&kycConfig)
r.cfg.kycConfigJSON1.Swap(&kycConfig)

return nil
}
}

func (*repository) initKYCConfig(kycCfg *kycConfigJSON) (err error) {
if pattern := kycCfg.Social1KYC.XPostPattern; pattern != "" {
kycCfg.Social1KYC.xPostPatternTemplate, err = template.New("kycCfg.Social1KYC.XPostPattern").Parse(pattern)
if err != nil {
return errors.Wrapf(err, "failed to parse kycCfg.Social1KYC.xPostPatternTemplate `%v`", pattern)
//nolint:funlen,gomnd,nestif,dupl,revive // .
func (r *repository) syncKYCConfigJSON2(ctx context.Context) error {
if resp, err := req.
SetContext(ctx).
SetRetryCount(25).
SetRetryBackoffInterval(10*stdlibtime.Millisecond, 1*stdlibtime.Second).
SetRetryHook(func(resp *req.Response, err error) {
if err != nil {
log.Error(errors.Wrap(err, "failed to fetch KYCConfigJSON, retrying...")) //nolint:revive // .
} else {
log.Error(errors.Errorf("failed to fetch KYCConfigJSON with status code:%v, retrying...", resp.GetStatusCode())) //nolint:revive // .
}
}).
SetRetryCondition(func(resp *req.Response, err error) bool {
return err != nil || resp.GetStatusCode() != http.StatusOK
}).
SetHeader("Accept", "application/json").
SetHeader("Cache-Control", "no-cache, no-store, must-revalidate").
SetHeader("Pragma", "no-cache").
SetHeader("Expires", "0").
Get(r.cfg.ConfigJSONURL2); err != nil {
return errors.Wrapf(err, "failed to get fetch `%v`", r.cfg.ConfigJSONURL2)
} else if data, err2 := resp.ToBytes(); err2 != nil {
return errors.Wrapf(err2, "failed to read body of `%v`", r.cfg.ConfigJSONURL2)
} else { //nolint:revive // .
var kycConfig kycConfigJSON2
if err = json.UnmarshalContext(ctx, data, &kycConfig); err != nil {
return errors.Wrapf(err, "failed to unmarshal into %#v, data: %v", kycConfig, string(data))
}
}
if pattern := kycCfg.Social2KYC.XPostPattern; pattern != "" {
kycCfg.Social2KYC.xPostPatternTemplate, err = template.New("kycCfg.Social2KYC.XPostPattern").Parse(pattern)
if err != nil {
return errors.Wrapf(err, "failed to parse kycCfg.Social2KYC.xPostPatternTemplate `%v`", pattern)
if body := string(data); !strings.Contains(body, "social2-kyc") {
return errors.Errorf("there's something wrong with the KYCConfigJSON body: %v", body)
}
}
for ix, dynKYCCfg := range kycCfg.DynamicDistributionSocialKYC {
if pattern := dynKYCCfg.XPostPattern; pattern != "" {
dynKYCCfg.xPostPatternTemplate, err = template.New(fmt.Sprintf("dynKYCCfg%v.XPostPattern", ix)).Parse(pattern)
if err != nil {
return errors.Wrapf(err, "failed to parse dynKYCCfg%v.XPostPattern `%v`", ix, pattern)
if pattern := kycConfig.Social2KYC.XPostPattern; pattern != "" {
if kycConfig.Social2KYC.xPostPatternTemplate, err = template.New("kycCfg.Social2KYC.XPostPattern").Parse(pattern); err != nil {
return errors.Wrapf(err, "failed to parse kycCfg.Social2KYC.xPostPatternTemplate `%v`", pattern)
}
}
}
r.cfg.kycConfigJSON2.Swap(&kycConfig)

return nil
return nil
}
}
24 changes: 6 additions & 18 deletions kyc/social/social.go
Original file line number Diff line number Diff line change
Expand Up @@ -418,17 +418,11 @@ func (r *repository) expectedPostSubtext(user *users.User, metadata *Verificatio
var tmpl *template.Template
switch metadata.KYCStep { //nolint:exhaustive // Not needed. Everything else is validated before this.
case users.Social1KYCStep:
tmpl = r.cfg.kycConfigJSON.Load().Social1KYC.xPostPatternTemplate
tmpl = r.cfg.kycConfigJSON1.Load().Social1KYC.xPostPatternTemplate
case users.Social2KYCStep:
tmpl = r.cfg.kycConfigJSON.Load().Social2KYC.xPostPatternTemplate
tmpl = r.cfg.kycConfigJSON2.Load().Social2KYC.xPostPatternTemplate
default:
for _, val := range r.cfg.kycConfigJSON.Load().DynamicDistributionSocialKYC {
if val != nil && val.KYCStep == metadata.KYCStep {
tmpl = val.xPostPatternTemplate

break
}
}
panic(fmt.Sprintf("social step `%v` not implemented ", metadata.KYCStep))
}
if tmpl != nil {
bf := new(bytes.Buffer)
Expand All @@ -445,17 +439,11 @@ func (r *repository) expectedPostURL(metadata *VerificationMetadata) (url string
if metadata.Social == TwitterType {
switch metadata.KYCStep { //nolint:exhaustive // Not needed. Everything else is validated before this.
case users.Social1KYCStep:
url = r.cfg.kycConfigJSON.Load().Social1KYC.XPostLink
url = r.cfg.kycConfigJSON1.Load().Social1KYC.XPostLink
case users.Social2KYCStep:
url = r.cfg.kycConfigJSON.Load().Social2KYC.XPostLink
url = r.cfg.kycConfigJSON2.Load().Social2KYC.XPostLink
default:
for _, val := range r.cfg.kycConfigJSON.Load().DynamicDistributionSocialKYC {
if val != nil && val.KYCStep == metadata.KYCStep {
url = val.XPostLink

break
}
}
panic(fmt.Sprintf("social step `%v` not implemented ", metadata.KYCStep))
}

url = strings.Replace(url, `https://x.com`, "", 1)
Expand Down

0 comments on commit f2dd67a

Please sign in to comment.