diff --git a/docs/spec/components/schemas/Proof.yaml b/docs/spec/components/schemas/Proof.yaml index 09c7d96..f20e814 100644 --- a/docs/spec/components/schemas/Proof.yaml +++ b/docs/spec/components/schemas/Proof.yaml @@ -13,6 +13,7 @@ allOf: - proof_type - org_id - schema_url + - operator properties: creator: type: string @@ -35,3 +36,7 @@ allOf: schema_url: type: string description: The schema URL of the claim the proof was created based on + operator: + type: string + description: The operator that will be used to check the proof + example: "$eq" diff --git a/docs/spec/components/schemas/ProofCreate.yaml b/docs/spec/components/schemas/ProofCreate.yaml index 96bd0e3..9d6a9b2 100644 --- a/docs/spec/components/schemas/ProofCreate.yaml +++ b/docs/spec/components/schemas/ProofCreate.yaml @@ -5,6 +5,7 @@ required: - org_id - user_did - schema_url + - operator properties: user_did: type: string @@ -22,3 +23,6 @@ properties: schema_url: type: string description: The schema URL of the claim the proof was created based on + operator: + type: string + description: The operator that will be used to check the proof diff --git a/internal/assets/migrations/002_proof_operator.sql b/internal/assets/migrations/002_proof_operator.sql new file mode 100644 index 0000000..5046a4b --- /dev/null +++ b/internal/assets/migrations/002_proof_operator.sql @@ -0,0 +1,7 @@ +-- +migrate Up +create type proof_operator as enum('$noop', '$eq', '$lt', '$gt', '$in', '$nin', '$ne'); +alter table proofs add column operator proof_operator not null; + +-- +migrate Down +alter table proofs drop column operator; +drop type proof_operator; diff --git a/internal/data/main.go b/internal/data/main.go index 892203b..47c4cb3 100644 --- a/internal/data/main.go +++ b/internal/data/main.go @@ -2,6 +2,7 @@ package data import ( "context" + "github.com/google/uuid" ) diff --git a/internal/data/pg/schema.xo.go b/internal/data/pg/schema.xo.go index 174508c..b1a86a2 100644 --- a/internal/data/pg/schema.xo.go +++ b/internal/data/pg/schema.xo.go @@ -292,18 +292,18 @@ func (s Storage) ProofQ() data.ProofQ { return NewProofQ(s.DB()) } -var colsProof = `id, creator, created_at, proof, org_id, type, schema_url` +var colsProof = `id, creator, created_at, proof, org_id, type, schema_url, operator` // InsertCtx inserts a Proof to the database. func (q ProofQ) InsertCtx(ctx context.Context, p *data.Proof) error { // sql insert query, primary key must be provided sqlstr := `INSERT INTO public.proofs (` + - `id, creator, created_at, proof, org_id, type, schema_url` + + `id, creator, created_at, proof, org_id, type, schema_url, operator` + `) VALUES (` + - `$1, $2, $3, $4, $5, $6, $7` + + `$1, $2, $3, $4, $5, $6, $7, $8` + `)` // run - err := q.db.ExecRawContext(ctx, sqlstr, p.ID, p.Creator, p.CreatedAt, p.Proof, p.OrgID, p.Type, p.SchemaURL) + err := q.db.ExecRawContext(ctx, sqlstr, p.ID, p.Creator, p.CreatedAt, p.Proof, p.OrgID, p.Type, p.SchemaURL, p.Operator) return errors.Wrap(err, "failed to execute insert query") } @@ -316,10 +316,10 @@ func (q ProofQ) Insert(p *data.Proof) error { func (q ProofQ) UpdateCtx(ctx context.Context, p *data.Proof) error { // update with composite primary key sqlstr := `UPDATE public.proofs SET ` + - `creator = $1, proof = $2, org_id = $3, type = $4, schema_url = $5 ` + - `WHERE id = $6` + `creator = $1, proof = $2, org_id = $3, type = $4, schema_url = $5, operator = $6 ` + + `WHERE id = $7` // run - err := q.db.ExecRawContext(ctx, sqlstr, p.Creator, p.Proof, p.OrgID, p.Type, p.SchemaURL, p.ID) + err := q.db.ExecRawContext(ctx, sqlstr, p.Creator, p.Proof, p.OrgID, p.Type, p.SchemaURL, p.Operator, p.ID) return errors.Wrap(err, "failed to execute update") } @@ -332,15 +332,15 @@ func (q ProofQ) Update(p *data.Proof) error { func (q ProofQ) UpsertCtx(ctx context.Context, p *data.Proof) error { // upsert sqlstr := `INSERT INTO public.proofs (` + - `id, creator, created_at, proof, org_id, type, schema_url` + + `id, creator, created_at, proof, org_id, type, schema_url, operator` + `) VALUES (` + - `$1, $2, $3, $4, $5, $6, $7` + + `$1, $2, $3, $4, $5, $6, $7, $8` + `)` + ` ON CONFLICT (id) DO ` + `UPDATE SET ` + - `creator = EXCLUDED.creator, proof = EXCLUDED.proof, org_id = EXCLUDED.org_id, type = EXCLUDED.type, schema_url = EXCLUDED.schema_url ` + `creator = EXCLUDED.creator, proof = EXCLUDED.proof, org_id = EXCLUDED.org_id, type = EXCLUDED.type, schema_url = EXCLUDED.schema_url, operator = EXCLUDED.operator ` // run - if err := q.db.ExecRawContext(ctx, sqlstr, p.ID, p.Creator, p.CreatedAt, p.Proof, p.OrgID, p.Type, p.SchemaURL); err != nil { + if err := q.db.ExecRawContext(ctx, sqlstr, p.ID, p.Creator, p.CreatedAt, p.Proof, p.OrgID, p.Type, p.SchemaURL, p.Operator); err != nil { return errors.Wrap(err, "failed to execute upsert stmt") } return nil @@ -473,7 +473,7 @@ func (q LinksToProofQ) LinksToProofByLinkIDProofID(linkID string, proofID uuid.U func (q ProofQ) ProofByIDCtx(ctx context.Context, id uuid.UUID, isForUpdate bool) (*data.Proof, error) { // query sqlstr := `SELECT ` + - `id, creator, created_at, proof, org_id, type, schema_url ` + + `id, creator, created_at, proof, org_id, type, schema_url, operator ` + `FROM public.proofs ` + `WHERE id = $1` // run diff --git a/internal/data/proofs.go b/internal/data/proofs.go new file mode 100644 index 0000000..c484b87 --- /dev/null +++ b/internal/data/proofs.go @@ -0,0 +1,36 @@ +package data + +type ProofOperator string + +const ( + Noop ProofOperator = "$noop" + Eq ProofOperator = "$eq" + Lt ProofOperator = "$lt" + Gt ProofOperator = "$gt" + In ProofOperator = "$in" + Nin ProofOperator = "$nin" + Ne ProofOperator = "$ne" +) + +func (o ProofOperator) String() string { + return string(o) +} + +var proofOperatorStrConv = map[string]ProofOperator{ + "$noop": Noop, + "$eq": Eq, + "$lt": Lt, + "$gt": Gt, + "$in": In, + "$nin": Nin, + "$ne": Ne, +} + +func ProofOperatorFromString(data string) (ProofOperator, bool) { + res, ok := proofOperatorStrConv[data] + return res, ok +} + +func MustProofOperatorFromString(data string) ProofOperator { + return proofOperatorStrConv[data] +} diff --git a/internal/data/schema.xo.go b/internal/data/schema.xo.go index 65b8cc9..9e78ab9 100644 --- a/internal/data/schema.xo.go +++ b/internal/data/schema.xo.go @@ -88,12 +88,13 @@ type LinksToProof struct { // Proof represents a row from 'public.proofs'. type Proof struct { - ID uuid.UUID `db:"id" json:"id" structs:"-"` // id - Creator string `db:"creator" json:"creator" structs:"creator"` // creator - CreatedAt time.Time `db:"created_at" json:"created_at" structs:"created_at"` // created_at - Proof xo.Jsonb `db:"proof" json:"proof" structs:"proof"` // proof - OrgID uuid.UUID `db:"org_id" json:"org_id" structs:"org_id"` // org_id - Type string `db:"type" json:"type" structs:"type"` // type - SchemaURL string `db:"schema_url" json:"schema_url" structs:"schema_url"` // schema_url + ID uuid.UUID `db:"id" json:"id" structs:"-"` // id + Creator string `db:"creator" json:"creator" structs:"creator"` // creator + CreatedAt time.Time `db:"created_at" json:"created_at" structs:"created_at"` // created_at + Proof xo.Jsonb `db:"proof" json:"proof" structs:"proof"` // proof + OrgID uuid.UUID `db:"org_id" json:"org_id" structs:"org_id"` // org_id + Type string `db:"type" json:"type" structs:"type"` // type + SchemaURL string `db:"schema_url" json:"schema_url" structs:"schema_url"` // schema_url + Operator ProofOperator `db:"operator" json:"operator" structs:"operator"` // operator } diff --git a/internal/services/api/handlers/create_proof.go b/internal/services/api/handlers/create_proof.go index 15c669e..116fba1 100644 --- a/internal/services/api/handlers/create_proof.go +++ b/internal/services/api/handlers/create_proof.go @@ -38,6 +38,12 @@ func newProofCreateRequest(r *http.Request) (*proofCreateRequest, error) { } } + if err := validation.Validate(req.Data.Operator, ValidationOperator); err != nil { + return nil, validation.Errors{ + "data/operator": errors.Wrap(err, "invalid operator value"), + } + } + return &req, nil } @@ -67,6 +73,7 @@ func CreateProof(w http.ResponseWriter, r *http.Request) { Type: req.Data.ProofType, OrgID: orgID, SchemaURL: req.Data.SchemaUrl, + Operator: data.MustProofOperatorFromString(req.Data.Operator), } err = Storage(r).ProofQ().Insert(&proof) @@ -89,6 +96,7 @@ func CreateProof(w http.ResponseWriter, r *http.Request) { ProofType: proof.Type, OrgId: proof.OrgID.String(), SchemaUrl: req.Data.SchemaUrl, + Operator: proof.Operator.String(), }, }, Included: resources.Included{}, diff --git a/internal/services/api/handlers/get_proof.go b/internal/services/api/handlers/get_proof.go index 9db2113..03c73f5 100644 --- a/internal/services/api/handlers/get_proof.go +++ b/internal/services/api/handlers/get_proof.go @@ -66,6 +66,7 @@ func ProofByID(w http.ResponseWriter, r *http.Request) { ProofType: proof.Type, OrgId: proof.OrgID.String(), SchemaUrl: proof.SchemaURL, + Operator: proof.Operator.String(), }, }, Included: resources.Included{}, diff --git a/internal/services/api/handlers/get_proofs_by_link.go b/internal/services/api/handlers/get_proofs_by_link.go index 261c1c8..ef10293 100644 --- a/internal/services/api/handlers/get_proofs_by_link.go +++ b/internal/services/api/handlers/get_proofs_by_link.go @@ -101,6 +101,7 @@ func GetLinkByID(w http.ResponseWriter, r *http.Request) { ProofType: proof.Type, OrgId: proof.OrgID.String(), SchemaUrl: proof.SchemaURL, + Operator: proof.Operator.String(), }, }) } diff --git a/internal/services/api/handlers/validation.go b/internal/services/api/handlers/validation.go new file mode 100644 index 0000000..ea26a30 --- /dev/null +++ b/internal/services/api/handlers/validation.go @@ -0,0 +1,16 @@ +package handlers + +import ( + validation "github.com/go-ozzo/ozzo-validation/v4" + "github.com/rarimo/rarime-link-svc/internal/data" +) + +var ( + ErrOperator = validation.NewError("validation_is_operator", "must be a valid operator") + ValidationOperator = validation.NewStringRuleWithError(isOperator, ErrOperator) +) + +func isOperator(op string) bool { + _, ok := data.ProofOperatorFromString(op) + return ok +} diff --git a/internal/services/proofs_cleaner/main.go b/internal/services/proofs_cleaner/main.go index bc27aab..946e562 100644 --- a/internal/services/proofs_cleaner/main.go +++ b/internal/services/proofs_cleaner/main.go @@ -2,11 +2,12 @@ package proofs_cleaner import ( "context" + "time" + "github.com/rarimo/rarime-link-svc/internal/config" "github.com/rarimo/rarime-link-svc/internal/data" "gitlab.com/distributed_lab/logan/v3" "gitlab.com/distributed_lab/running" - "time" ) type ProofsCleaner struct { diff --git a/resources/model_proof_attributes.go b/resources/model_proof_attributes.go index 31ff939..6338901 100644 --- a/resources/model_proof_attributes.go +++ b/resources/model_proof_attributes.go @@ -11,6 +11,8 @@ type ProofAttributes struct { CreatedAt time.Time `json:"created_at"` // The ID of the user who created the proof Creator string `json:"creator"` + // The operator that will be used to check the proof + Operator string `json:"operator"` // The ID of the organization that issued the proof's claim OrgId string `json:"org_id"` // The proof object in JSON string format diff --git a/resources/model_proof_create.go b/resources/model_proof_create.go index 2aaa65a..64f1ff2 100644 --- a/resources/model_proof_create.go +++ b/resources/model_proof_create.go @@ -5,6 +5,8 @@ package resources type ProofCreate struct { + // The operator that will be used to check the proof + Operator string `json:"operator"` // The ID of the organization that issued the proof's claim OrgId string `json:"org_id"` // The proof object in JSON string format