diff --git a/config.yaml b/config.yaml index 26c2ae4..420e314 100644 --- a/config.yaml +++ b/config.yaml @@ -11,6 +11,7 @@ verifier: sha256: "./sha256_verification_key.json" master_certs_path: "./masterList.dev.pem" allowed_age: 18 + registration_timeout: 1h issuer: base_url: "http://localhost:3002/v1" diff --git a/internal/assets/migrations/001_initial.sql b/internal/assets/migrations/001_initial.sql index 9775e14..9951475 100644 --- a/internal/assets/migrations/001_initial.sql +++ b/internal/assets/migrations/001_initial.sql @@ -3,7 +3,8 @@ create table claims( id uuid primary key, user_did text not null, issuer_did text not null, - document_hash text not null + document_hash text not null, + created_at timestamp default now() ); -- +migrate Down diff --git a/internal/config/verifier.go b/internal/config/verifier.go index 6562ea2..c38e0a4 100644 --- a/internal/config/verifier.go +++ b/internal/config/verifier.go @@ -1,10 +1,12 @@ package config import ( + "os" + "time" + "gitlab.com/distributed_lab/figure/v3" "gitlab.com/distributed_lab/kit/comfig" "gitlab.com/distributed_lab/kit/kv" - "os" ) type VerifierConfiger interface { @@ -12,9 +14,10 @@ type VerifierConfiger interface { } type VerifierConfig struct { - VerificationKeys map[string][]byte - MasterCerts []byte - AllowedAge int + VerificationKeys map[string][]byte + MasterCerts []byte + AllowedAge int + RegistrationTimeout time.Duration } type verifier struct { @@ -34,10 +37,12 @@ func (v *verifier) VerifierConfig() *VerifierConfig { VerificationKeysPaths map[string]string `fig:"verification_keys_paths,required"` MasterCertsPath string `fig:"master_certs_path,required"` AllowedAge int `fig:"allowed_age,required"` + RegistrationTimeout time.Duration `fig:"registration_timeout"` }{} err := figure. Out(&newCfg). + With(figure.BaseHooks). From(kv.MustGetStringMap(v.getter, "verifier")). Please() if err != nil { @@ -60,9 +65,10 @@ func (v *verifier) VerifierConfig() *VerifierConfig { } return &VerifierConfig{ - VerificationKeys: verificationKeys, - MasterCerts: masterCerts, - AllowedAge: newCfg.AllowedAge, + VerificationKeys: verificationKeys, + MasterCerts: masterCerts, + AllowedAge: newCfg.AllowedAge, + RegistrationTimeout: newCfg.RegistrationTimeout, } }).(*VerifierConfig) } diff --git a/internal/data/claims.go b/internal/data/claims.go index 91f261c..4adcbd5 100644 --- a/internal/data/claims.go +++ b/internal/data/claims.go @@ -1,6 +1,9 @@ package data -import "github.com/google/uuid" +import ( + "github.com/google/uuid" + "time" +) type ClaimQ interface { New() ClaimQ @@ -18,4 +21,5 @@ type Claim struct { UserDID string `db:"user_did" structs:"user_did"` IssuerDID string `db:"issuer_did" structs:"issuer_did"` DocumentHash string `db:"document_hash" structs:"document_hash"` + CreatedAt time.Time `db:"created_at" structs:"-"` } diff --git a/internal/service/api/handlers/create_identity.go b/internal/service/api/handlers/create_identity.go index 28c5a92..de111e2 100644 --- a/internal/service/api/handlers/create_identity.go +++ b/internal/service/api/handlers/create_identity.go @@ -116,7 +116,7 @@ func CreateIdentity(w http.ResponseWriter, r *http.Request) { return } - masterQ := MasterQ(r) + masterQ := MasterQ(r).New() claim, err := masterQ.Claim().ResetFilter(). FilterBy("user_did", req.Data.ID). @@ -178,7 +178,7 @@ func CreateIdentity(w http.ResponseWriter, r *http.Request) { if err := masterQ.Transaction(func(db data.MasterQ) error { // check if there are any claims for this document already - claims, err := db.Claim().ResetFilter(). + claimsToRevoke, err := db.Claim().ResetFilter(). FilterBy("document_hash", hash.String()). ForUpdate(). Select() @@ -188,7 +188,13 @@ func CreateIdentity(w http.ResponseWriter, r *http.Request) { } // revoke if so - for _, claimToRevoke := range claims { + for _, claimToRevoke := range claimsToRevoke { + timeoutExpiration := claimToRevoke.CreatedAt.UTC().Add(cfg.RegistrationTimeout) + if time.Now().UTC().Before(timeoutExpiration) { + ape.RenderErr(w, problems.TooManyRequests()) + return errors.New("registration timeout is not expired") + } + if err := revokeOutdatedClaim(db, iss, claimToRevoke.ID); err != nil { ape.RenderErr(w, problems.InternalError()) return errors.Wrap(err, "failed to revoke outdated claim")