Skip to content

Commit

Permalink
fix issues with nil KYC dates processing, handling face after social (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
ice-cronus authored Jun 24, 2024
1 parent 650956f commit 2222fdb
Show file tree
Hide file tree
Showing 13 changed files with 120 additions and 76 deletions.
16 changes: 8 additions & 8 deletions cmd/eskimo-hut/kyc.go
Original file line number Diff line number Diff line change
Expand Up @@ -292,14 +292,6 @@ func (s *service) TryResetKYCSteps( //nolint:gocritic,funlen,gocognit,revive,cyc
if err != nil {
return nil, server.Unexpected(errors.Wrapf(err, "failed to CheckQuizStatus for userID:%v", req.Data.UserID))
}
kycFaceAvailable := false
if req.Data.NextKYCStep != nil &&
(*req.Data.NextKYCStep == users.FacialRecognitionKYCStep || *req.Data.NextKYCStep == users.LivenessDetectionKYCStep) {
kycFaceAvailable, err = s.faceKycClient.CheckStatus(ctx, req.Data.UserID, *req.Data.NextKYCStep)
if err != nil {
return nil, server.Unexpected(err)
}
}
resp, err := s.usersProcessor.TryResetKYCSteps(ctx, s.faceKycClient, req.Data.UserID)
if err = errors.Wrapf(err, "failed to TryResetKYCSteps for userID:%v", req.Data.UserID); err != nil {
switch {
Expand All @@ -309,6 +301,14 @@ func (s *service) TryResetKYCSteps( //nolint:gocritic,funlen,gocognit,revive,cyc
return nil, server.Unexpected(err)
}
}
kycFaceAvailable := false
if req.Data.NextKYCStep != nil &&
(*req.Data.NextKYCStep == users.FacialRecognitionKYCStep || *req.Data.NextKYCStep == users.LivenessDetectionKYCStep) {
kycFaceAvailable, err = s.faceKycClient.CheckStatus(ctx, resp, *req.Data.NextKYCStep)
if err != nil {
return nil, server.Unexpected(err)
}
}

return server.OK(&User{User: resp, QuizStatus: quizStatus, KycFaceAvailable: kycFaceAvailable, Checksum: resp.Checksum()}), nil
}
2 changes: 1 addition & 1 deletion cmd/eskimo-hut/users.go
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,7 @@ func (s *service) DeleteUser( //nolint:gocritic // False negative.
if err := server.Auth(ctx).DeleteUser(ctx, req.Data.UserID); err != nil && !errors.Is(err, auth.ErrUserNotFound) {
return nil, server.Unexpected(errors.Wrapf(err, "failed to delete auth user:%#v", req.Data.UserID))
}
if err := s.faceKycClient.Reset(ctx, req.Data.UserID, false); err != nil {
if err := s.faceKycClient.Reset(ctx, &users.User{PublicUserInformation: users.PublicUserInformation{ID: req.Data.UserID}}, false); err != nil {
return nil, server.Unexpected(errors.Wrapf(err, "failed to delete users face:%#v", req.Data.UserID))
}

Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ require (
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
github.com/quic-go/qpack v0.4.0 // indirect
github.com/quic-go/quic-go v0.45.0 // indirect
github.com/quic-go/quic-go v0.45.1 // indirect
github.com/refraction-networking/utls v1.6.6 // indirect
github.com/rs/zerolog v1.33.0 // indirect
github.com/sagikazarmark/locafero v0.6.0 // indirect
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -326,8 +326,8 @@ github.com/prometheus/prometheus v0.53.0 h1:vOnhpUKrDv954jnVBvhG/ZQJ3kqscnKI+Hbd
github.com/prometheus/prometheus v0.53.0/go.mod h1:RZDkzs+ShMBDkAPQkLEaLBXpjmDcjhNxU2drUVPgKUU=
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
github.com/quic-go/quic-go v0.45.0 h1:OHmkQGM37luZITyTSu6ff03HP/2IrwDX1ZFiNEhSFUE=
github.com/quic-go/quic-go v0.45.0/go.mod h1:1dLehS7TIR64+vxGR70GDcatWTOtMX2PUtnKsjbTurI=
github.com/quic-go/quic-go v0.45.1 h1:tPfeYCk+uZHjmDRwHHQmvHRYL2t44ROTujLeFVBmjCA=
github.com/quic-go/quic-go v0.45.1/go.mod h1:1dLehS7TIR64+vxGR70GDcatWTOtMX2PUtnKsjbTurI=
github.com/refraction-networking/utls v1.6.6 h1:igFsYBUJPYM8Rno9xUuDoM5GQrVEqY4llzEXOkL43Ig=
github.com/refraction-networking/utls v1.6.6/go.mod h1:BC3O4vQzye5hqpmDTWUqi4P5DDhzJfkV1tdqtawQIH0=
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
Expand Down
4 changes: 2 additions & 2 deletions kyc/face/contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ type (
ThreeDiVi threedivi.Config `mapstructure:",squash"` //nolint:tagliatelle // .
}
Client interface {
Reset(ctx context.Context, userID string, fetchState bool) error
CheckStatus(ctx context.Context, userID string, nextKYCStep users.KYCStep) (available bool, err error)
Reset(ctx context.Context, user *users.User, fetchState bool) error
CheckStatus(ctx context.Context, user *users.User, nextKYCStep users.KYCStep) (available bool, err error)
}
)

Expand Down
12 changes: 6 additions & 6 deletions kyc/face/face.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,22 @@ func New(usersRep UserRepository) Client {
return &client{client: threedivi.New3Divi(usersRep, &cfg.ThreeDiVi)}
}

func (c *client) CheckStatus(ctx context.Context, userID string, nextKYCStep users.KYCStep) (bool, error) {
func (c *client) CheckStatus(ctx context.Context, user *users.User, nextKYCStep users.KYCStep) (bool, error) {
kycFaceAvailable := false
if hasResult, err := c.client.CheckAndUpdateStatus(ctx, userID); err != nil {
return false, errors.Wrapf(err, "failed to update face auth status for user ID %s", userID)
if hasResult, err := c.client.CheckAndUpdateStatus(ctx, user); err != nil {
return false, errors.Wrapf(err, "failed to update face auth status for user ID %s", user.ID)
} else if !hasResult || nextKYCStep == users.LivenessDetectionKYCStep {
availabilityErr := c.client.Available(ctx)
if availabilityErr == nil {
kycFaceAvailable = true
} else {
log.Error(errors.Wrapf(err, "face auth is unavailable for userID %v KYCStep %v", userID, nextKYCStep))
log.Error(errors.Wrapf(err, "face auth is unavailable for userID %v KYCStep %v", user.ID, nextKYCStep))
}
}

return kycFaceAvailable, nil
}

func (c *client) Reset(ctx context.Context, userID string, fetchState bool) error {
return errors.Wrapf(c.client.Reset(ctx, userID, fetchState), "failed to reset face auth state for userID %s", userID)
func (c *client) Reset(ctx context.Context, user *users.User, fetchState bool) error {
return errors.Wrapf(c.client.Reset(ctx, user, fetchState), "failed to reset face auth state for userID %s", user.ID)
}
4 changes: 2 additions & 2 deletions kyc/face/internal/contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import (
type (
Client interface {
Available(ctx context.Context) error
CheckAndUpdateStatus(ctx context.Context, userID string) (hasFaceKYCResult bool, err error)
Reset(ctx context.Context, userID string, fetchState bool) error
CheckAndUpdateStatus(ctx context.Context, user *users.User) (hasFaceKYCResult bool, err error)
Reset(ctx context.Context, user *users.User, fetchState bool) error
}
UserRepository interface {
ModifyUser(ctx context.Context, usr *users.User, profilePicture *multipart.FileHeader) (*users.UserProfile, error)
Expand Down
77 changes: 50 additions & 27 deletions kyc/face/internal/threedivi/threedivi.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,12 +116,12 @@ func (*threeDivi) activeUsers(data []byte) (int, error) {
return openConns / connsPerUser, nil
}

func (t *threeDivi) CheckAndUpdateStatus(ctx context.Context, userID string) (hasFaceKYCResult bool, err error) {
bafApplicant, err := t.searchIn3DiviForApplicant(ctx, userID)
func (t *threeDivi) CheckAndUpdateStatus(ctx context.Context, user *users.User) (hasFaceKYCResult bool, err error) {
bafApplicant, err := t.searchIn3DiviForApplicant(ctx, user.ID)
if err != nil && !errors.Is(err, errFaceAuthNotStarted) {
return false, errors.Wrapf(err, "failed to sync face auth status from 3divi BAF")
}
usr := t.parseApplicant(userID, bafApplicant)
usr := t.parseApplicant(user, bafApplicant)
hasFaceKYCResult = (usr.KYCStepPassed != nil && *usr.KYCStepPassed >= users.LivenessDetectionKYCStep) ||
(usr.KYCStepBlocked != nil && *usr.KYCStepBlocked > users.NoneKYCStep)
_, mErr := t.users.ModifyUser(ctx, usr, nil)
Expand All @@ -130,14 +130,14 @@ func (t *threeDivi) CheckAndUpdateStatus(ctx context.Context, userID string) (ha
}

//nolint:funlen,revive // .
func (t *threeDivi) Reset(ctx context.Context, userID string, fetchState bool) error {
bafApplicant, err := t.searchIn3DiviForApplicant(ctx, userID)
func (t *threeDivi) Reset(ctx context.Context, user *users.User, fetchState bool) error {
bafApplicant, err := t.searchIn3DiviForApplicant(ctx, user.ID)
if err != nil {
if errors.Is(err, errFaceAuthNotStarted) {
return nil
}

return errors.Wrapf(err, "failed to find matching applicant for userID %v", userID)
return errors.Wrapf(err, "failed to find matching applicant for userID %v", user.ID)
}
var resp *req.Response
if resp, err = req.
Expand All @@ -160,48 +160,71 @@ func (t *threeDivi) Reset(ctx context.Context, userID string, fetchState bool) e
SetHeader("Authorization", fmt.Sprintf("Bearer %v", t.cfg.ThreeDiVi.BAFToken)).
SetHeader("X-Secret-Api-Token", t.cfg.ThreeDiVi.SecretAPIToken).
Delete(fmt.Sprintf("%v/publicapi/api/v2/private/Applicants/%v", t.cfg.ThreeDiVi.BAFHost, bafApplicant.ApplicantID)); err != nil {
return errors.Wrapf(err, "failed to delete face auth state for userID:%v", userID)
return errors.Wrapf(err, "failed to delete face auth state for userID:%v", user.ID)
} else if statusCode := resp.GetStatusCode(); statusCode != http.StatusOK && statusCode != http.StatusNoContent {
return errors.Errorf("[%v]failed to delete face auth state for userID:%v", statusCode, userID)
return errors.Errorf("[%v]failed to delete face auth state for userID:%v", statusCode, user.ID)
} else if _, err2 := resp.ToBytes(); err2 != nil {
return errors.Wrapf(err2, "failed to read body of delete face auth state request for userID:%v", userID)
return errors.Wrapf(err2, "failed to read body of delete face auth state request for userID:%v", user.ID)
} else { //nolint:revive // .
if fetchState {
_, err = t.CheckAndUpdateStatus(ctx, userID)
_, err = t.CheckAndUpdateStatus(ctx, user)

return errors.Wrapf(err, "failed to check user's face auth state after reset for userID %v", userID)
return errors.Wrapf(err, "failed to check user's face auth state after reset for userID %v", user.ID)
}

return nil
}
}

func (*threeDivi) parseApplicant(userID string, bafApplicant *applicant) *users.User {
usr := new(users.User)
usr.ID = userID
//nolint:funlen //.
func (*threeDivi) parseApplicant(user *users.User, bafApplicant *applicant) *users.User {
updUser := new(users.User)
updUser.ID = user.ID
if bafApplicant != nil && bafApplicant.LastValidationResponse != nil && bafApplicant.Status == statusPassed {
passedTime := time.New(bafApplicant.LastValidationResponse.CreatedAt)
times := []*time.Time{passedTime, passedTime}
usr.KYCStepsLastUpdatedAt = &times
stepPassed := users.LivenessDetectionKYCStep
usr.KYCStepPassed = &stepPassed
} else {
var nilDates []*time.Time
usr.KYCStepsLastUpdatedAt = &nilDates
usr.KYCStepsCreatedAt = &nilDates
stepPassed := users.NoneKYCStep
usr.KYCStepPassed = &stepPassed
if user.KYCStepsCreatedAt != nil && len(*user.KYCStepsCreatedAt) >= int(users.LivenessDetectionKYCStep) {
updUser.KYCStepsCreatedAt = user.KYCStepsCreatedAt
updUser.KYCStepsLastUpdatedAt = user.KYCStepsLastUpdatedAt
(*updUser.KYCStepsCreatedAt)[stepIdx(users.FacialRecognitionKYCStep)] = passedTime
(*updUser.KYCStepsCreatedAt)[stepIdx(users.LivenessDetectionKYCStep)] = passedTime
(*updUser.KYCStepsLastUpdatedAt)[stepIdx(users.FacialRecognitionKYCStep)] = passedTime
(*updUser.KYCStepsLastUpdatedAt)[stepIdx(users.LivenessDetectionKYCStep)] = passedTime
} else {
times := []*time.Time{passedTime, passedTime}
updUser.KYCStepsLastUpdatedAt = &times
stepPassed := users.LivenessDetectionKYCStep
updUser.KYCStepPassed = &stepPassed
}
} else if user.KYCStepsCreatedAt != nil && len(*user.KYCStepsCreatedAt) >= int(users.LivenessDetectionKYCStep) {
updUser.KYCStepsCreatedAt = user.KYCStepsCreatedAt
updUser.KYCStepsLastUpdatedAt = user.KYCStepsLastUpdatedAt
(*updUser.KYCStepsCreatedAt)[stepIdx(users.FacialRecognitionKYCStep)] = nil
(*updUser.KYCStepsCreatedAt)[stepIdx(users.LivenessDetectionKYCStep)] = nil
(*updUser.KYCStepsLastUpdatedAt)[stepIdx(users.FacialRecognitionKYCStep)] = nil
(*updUser.KYCStepsLastUpdatedAt)[stepIdx(users.LivenessDetectionKYCStep)] = nil
}
switch {
case bafApplicant != nil && bafApplicant.LastValidationResponse != nil && bafApplicant.Status == statusFailed && bafApplicant.HasRiskEvents:
kycStepBlocked := users.FacialRecognitionKYCStep
usr.KYCStepBlocked = &kycStepBlocked
updUser.KYCStepBlocked = &kycStepBlocked
default:
kycStepBlocked := users.NoneKYCStep
usr.KYCStepBlocked = &kycStepBlocked
updUser.KYCStepBlocked = &kycStepBlocked
}
user.KYCStepsLastUpdatedAt = updUser.KYCStepsLastUpdatedAt
user.KYCStepsCreatedAt = updUser.KYCStepsCreatedAt
if updUser.KYCStepPassed != nil {
user.KYCStepPassed = updUser.KYCStepPassed
}
if updUser.KYCStepBlocked != nil {
user.KYCStepBlocked = updUser.KYCStepBlocked
}

return usr
return updUser
}

func stepIdx(step users.KYCStep) int {
return int(step) - 1
}

func (t *threeDivi) searchIn3DiviForApplicant(ctx context.Context, userID users.UserID) (*applicant, error) {
Expand Down
13 changes: 10 additions & 3 deletions kyc/social/social.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,11 @@ func (r *repository) VerifyPost(ctx context.Context, metadata *VerificationMetad
if err != nil {
return nil, errors.Wrapf(err, "failed to GetUserByID: %v", metadata.UserID)
}

if err = r.validateKycStep(user.User, metadata.KYCStep, now); err != nil {
return nil, errors.Wrap(err, "failed to validateKycStep")
}

skippedCount, err := r.verifySkipped(ctx, metadata, now)
if err != nil {
return nil, errors.Wrapf(err, "failed to verifySkipped for metadata:%#v", metadata)
Expand Down Expand Up @@ -264,14 +266,15 @@ func (r *repository) VerifyPost(ctx context.Context, metadata *VerificationMetad
}

func (r *repository) validateKycStep(user *users.User, kycStep users.KYCStep, now *time.Time) error {
if user.KYCStepPassed == nil ||
allowSocialBeforeFace := true
if !allowSocialBeforeFace && (user.KYCStepPassed == nil ||
*user.KYCStepPassed < kycStep-1 ||
(user.KYCStepPassed != nil &&
*user.KYCStepPassed == kycStep-1 &&
user.KYCStepsLastUpdatedAt != nil &&
len(*user.KYCStepsLastUpdatedAt) >= int(kycStep) &&
!(*user.KYCStepsLastUpdatedAt)[kycStep-1].IsNil() &&
now.Sub(*(*user.KYCStepsLastUpdatedAt)[kycStep-1].Time) < r.cfg.DelayBetweenSessions) {
now.Sub(*(*user.KYCStepsLastUpdatedAt)[kycStep-1].Time) < r.cfg.DelayBetweenSessions)) {
return ErrNotAvailable
} else if user.KYCStepPassed != nil && *user.KYCStepPassed >= kycStep {
return ErrDuplicate
Expand All @@ -280,14 +283,18 @@ func (r *repository) validateKycStep(user *users.User, kycStep users.KYCStep, no
return nil
}

//nolint:revive,funlen // Nope.
//nolint:revive,funlen,gocognit // Nope.
func (r *repository) modifyUser(ctx context.Context, success, skip bool, kycStep users.KYCStep, now *time.Time, user *users.User) error {
usr := new(users.User)
usr.ID = user.ID
usr.KYCStepsLastUpdatedAt = user.KYCStepsLastUpdatedAt
switch {
case success:
usr.KYCStepPassed = &kycStep
if usr.KYCStepsLastUpdatedAt == nil {
emptyFaceRecognition := []*time.Time{nil, nil}
usr.KYCStepsLastUpdatedAt = &emptyFaceRecognition
}
if len(*usr.KYCStepsLastUpdatedAt) < int(kycStep) {
*usr.KYCStepsLastUpdatedAt = append(*usr.KYCStepsLastUpdatedAt, now)
} else {
Expand Down
2 changes: 1 addition & 1 deletion users/contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ type (
IsEmailUsedBySomebodyElse(ctx context.Context, userID, email string) (bool, error)
}
ResetKycClient interface {
Reset(ctx context.Context, userID string, fetchState bool) error
Reset(ctx context.Context, user *User, fetchState bool) error
}
WriteRepository interface {
CreateUser(ctx context.Context, usr *User, clientIP net.IP) error
Expand Down
26 changes: 13 additions & 13 deletions users/kyc.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,14 @@ func (r *repository) TryResetKYCSteps(ctx context.Context, resetClient ResetKycC
r.sanitizeUserForUI(&resp.User)

return &resp.User, nil
} else if err = r.resetKYCSteps(ctx, resetClient, userID, resp.KYCStepsToReset); err != nil {
} else if err = r.resetKYCSteps(ctx, resetClient, &resp.User, resp.KYCStepsToReset); err != nil {
return nil, errors.Wrapf(err, "failed to resetKYCSteps for userID:%v", userID)
}

return r.TryResetKYCSteps(ctx, resetClient, userID)
}

func (r *repository) resetKYCSteps(ctx context.Context, resetClient ResetKycClient, userID string, kycStepsToBeReset []KYCStep) error {
func (r *repository) resetKYCSteps(ctx context.Context, resetClient ResetKycClient, user *User, kycStepsToBeReset []KYCStep) error {
kycStepResetPipelines := make(map[KYCStep]struct{}, len(kycStepsToBeReset))
for _, kycStep := range kycStepsToBeReset {
if kycStep == LivenessDetectionKYCStep || kycStep == FacialRecognitionKYCStep {
Expand All @@ -54,7 +54,7 @@ func (r *repository) resetKYCSteps(ctx context.Context, resetClient ResetKycClie
for kycStep := range kycStepResetPipelines {
go func(step KYCStep) {
defer wg.Done()
errs <- errors.Wrapf(r.resetKYCStep(ctx, resetClient, userID, step), "failed to resetKYCStep(%v) for userID:%v", step, userID)
errs <- errors.Wrapf(r.resetKYCStep(ctx, resetClient, user, step), "failed to resetKYCStep(%v) for userID:%v", step, user.ID)
}(kycStep)
}
wg.Wait()
Expand All @@ -64,39 +64,39 @@ func (r *repository) resetKYCSteps(ctx context.Context, resetClient ResetKycClie
responses = append(responses, err)
}
if err := multierror.Append(nil, responses...).ErrorOrNil(); err != nil {
return errors.Wrapf(err, "atleast one resetKYCStep failed for userID:%v", userID)
return errors.Wrapf(err, "atleast one resetKYCStep failed for userID:%v", user.ID)
}
_, err := storage.Exec(ctx, r.db, `DELETE FROM kyc_steps_reset_requests WHERE user_id = $1`, userID)
_, err := storage.Exec(ctx, r.db, `DELETE FROM kyc_steps_reset_requests WHERE user_id = $1`, user.ID)

return errors.Wrapf(err, "failed to delete kyc step reset request for userID:%v", userID)
return errors.Wrapf(err, "failed to delete kyc step reset request for userID:%v", user.ID)
}

func (r *repository) resetKYCStep(ctx context.Context, resetClient ResetKycClient, userID string, step KYCStep) error {
func (r *repository) resetKYCStep(ctx context.Context, resetClient ResetKycClient, user *User, step KYCStep) error {
switch step { //nolint:exhaustive // Not needed yet.
case FacialRecognitionKYCStep:
if err := resetClient.Reset(ctx, userID, true); err != nil {
return errors.Wrapf(err, "failed to resetFacialRecognitionKYCStep for userID:%v", userID)
if err := resetClient.Reset(ctx, user, true); err != nil {
return errors.Wrapf(err, "failed to resetFacialRecognitionKYCStep for userID:%v", user.ID)
}
default:
log.Error(errors.Errorf("reset for KYCStep[%v] not implemented, userID:%v", step, userID))
log.Error(errors.Errorf("reset for KYCStep[%v] not implemented, userID:%v", step, user.ID))

return nil
}

sql := `UPDATE kyc_steps_reset_requests
SET kyc_steps_to_reset = array_remove(kyc_steps_to_reset, $2::smallint)
WHERE user_id = $1`
if updated, err := storage.Exec(ctx, r.db, sql, userID, step); err != nil || updated == 0 {
if updated, err := storage.Exec(ctx, r.db, sql, user.ID, step); err != nil || updated == 0 {
if updated == 0 {
err = errors.Wrapf(ErrNotFound, "failed to remove step[%v] from kyc_steps_reset_requests for userID:%v", step, userID)
err = errors.Wrapf(ErrNotFound, "failed to remove step[%v] from kyc_steps_reset_requests for userID:%v", step, user.ID)
}
if storage.IsErr(err, storage.ErrCheckFailed) {
// This happens if the resulting array is empty, at which point we need to delete the entire entry,
// but we're not going to do that here, cuz it's going to happen anyway in r.resetKYCSteps.
err = nil
}
if err != nil {
return errors.Wrapf(err, "[db]failed to resetKYCStep[%v] for userID:%v", step, userID)
return errors.Wrapf(err, "[db]failed to resetKYCStep[%v] for userID:%v", step, user.ID)
}
}

Expand Down
7 changes: 5 additions & 2 deletions users/users.go
Original file line number Diff line number Diff line change
Expand Up @@ -295,9 +295,12 @@ func (r *repository) buildRepeatableKYCSteps(usr *User) {
if r.cfg.IntervalBetweenRepeatableKYCSteps == 0 {
log.Panic(errors.New("`intervalBetweenRepeatableKYCSteps` config is missing"))
}
nextDate := (*usr.KYCStepsLastUpdatedAt)[LivenessDetectionKYCStep-1].Add(r.cfg.IntervalBetweenRepeatableKYCSteps)
date := (*usr.KYCStepsLastUpdatedAt)[LivenessDetectionKYCStep-1]
repeatableKYCSteps := make(map[KYCStep]*time.Time, 1)
repeatableKYCSteps[LivenessDetectionKYCStep] = time.New(nextDate)
if !date.IsNil() {
nextDate := date.Add(r.cfg.IntervalBetweenRepeatableKYCSteps)
repeatableKYCSteps[LivenessDetectionKYCStep] = time.New(nextDate)
}
usr.RepeatableKYCSteps = &repeatableKYCSteps
}

Expand Down
Loading

0 comments on commit 2222fdb

Please sign in to comment.