diff --git a/docs/spec/components/responses/conflict.yaml b/docs/spec/components/responses/conflict.yaml new file mode 100644 index 0000000..aa36038 --- /dev/null +++ b/docs/spec/components/responses/conflict.yaml @@ -0,0 +1,5 @@ +description: Conflict +content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/Errors' \ No newline at end of file diff --git a/docs/spec/components/schemas/Link.yaml b/docs/spec/components/schemas/Link.yaml index f28d6c5..f1958a1 100644 --- a/docs/spec/components/schemas/Link.yaml +++ b/docs/spec/components/schemas/Link.yaml @@ -12,7 +12,7 @@ allOf: properties: link: type: string - description: UUID Link to proofs + description: Link to proofs ID (UUID or custom ASCII string) example: '05260b49-2c35-48b9-8300-d39ae48ca312' created_at: type: string diff --git a/docs/spec/paths/v1@links.yaml b/docs/spec/paths/v1@links.yaml index 5948cbc..9c3f671 100644 --- a/docs/spec/paths/v1@links.yaml +++ b/docs/spec/paths/v1@links.yaml @@ -1,6 +1,6 @@ post: tags: - - Proofs + - Links summary: Create Link Proofs description: | Add link to the specified proofs @@ -25,7 +25,12 @@ post: items: type: string example: [550e8400-e29b-41d4-a716-446655440001, 550e8400-e29b-41d4-a716-446655440002, 550e8400-e29b-41d4-a716-446655440003] + link_name: + type: string + description: Link name, must be unique + example: "RarimoAppTeamEmailAndPosition" required: + - user_did - proofs_ids responses: 200: @@ -42,6 +47,8 @@ post: $ref: '#/components/responses/invalidParameter' 401: $ref: '#/components/responses/invalidAuth' + 409: + $ref: '#/components/responses/conflict' 500: $ref: '#/components/responses/internalError' @@ -53,7 +60,7 @@ get: security: - Bearer: [ ] tags: - - Proofs + - Links parameters: - in: path name: 'did' diff --git a/docs/spec/paths/v1@links@{link_id}.yaml b/docs/spec/paths/v1@links@{link_id}.yaml index ff485f9..2989e7e 100644 --- a/docs/spec/paths/v1@links@{link_id}.yaml +++ b/docs/spec/paths/v1@links@{link_id}.yaml @@ -4,12 +4,12 @@ get: Returns information about the all proofs of the link. operationId: proofsByLinkID tags: - - Proofs + - Links parameters: - in: path name: 'link_id' required: true - description: The Link ID + description: The Link ID (UUID or ASCII string) schema: type: string example: "550e8400-e29b-41d4-a716-446655440000" diff --git a/generate.sh b/generate.sh index fb6357a..770b4ab 100755 --- a/generate.sh +++ b/generate.sh @@ -4,8 +4,8 @@ GENERATOR_IMAGE=registry.gitlab.com/tokend/openapi-go-generator:c59241b52b0e37bb [[ ! -x "$(command -v go 2>/dev/null)" ]] && echo "go is not installed" && exit 1 -GENERATED="$(go env GOPATH)/src/github.com/rarimo/rarime-link-svc/resources" -OPENAPI_DIR="$(go env GOPATH)/src/github.com/rarimo/rarime-link-svc/docs/web_deploy" +GENERATED="$PWD/resources" +OPENAPI_DIR="$PWD/docs/web_deploy" PACKAGE_NAME=resources function printHelp { diff --git a/go.mod b/go.mod index d8a8227..773f65d 100644 --- a/go.mod +++ b/go.mod @@ -18,14 +18,13 @@ require ( gitlab.com/distributed_lab/running v0.0.0-20200706131153-4af0e83eb96c gitlab.com/distributed_lab/urlval v3.0.0+incompatible gitlab.com/tokend/keypair v0.0.0-20190412110653-b9d7e0c8b312 + golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa ) require ( github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect github.com/alecthomas/units v0.0.0-20231202071711-9a357b53e9c9 // indirect - github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect github.com/certifi/gocertifi v0.0.0-20200211180108-c7c1fbc02894 // indirect - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect github.com/ethereum/go-ethereum v1.13.8 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/getsentry/raven-go v0.2.0 // indirect @@ -36,17 +35,12 @@ require ( github.com/google/jsonapi v0.0.0-20200226002910-c8283f632fb7 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/holiman/uint256 v1.2.4 // indirect - github.com/iden3/go-iden3-core v1.0.2 // indirect - github.com/iden3/go-iden3-crypto v0.0.15 // indirect - github.com/iden3/go-rapidsnark/types v0.0.3 // indirect - github.com/iden3/go-rapidsnark/verifier v0.0.5 // indirect github.com/jmoiron/sqlx v1.2.0 // indirect github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect github.com/lib/pq v1.10.7 // indirect github.com/magiconair/properties v1.8.0 // indirect github.com/mitchellh/mapstructure v1.4.1 // indirect - github.com/mr-tron/base58 v1.2.0 // indirect github.com/oklog/ulid v1.3.1 // indirect github.com/pelletier/go-toml v1.2.0 // indirect github.com/pkg/errors v0.9.1 // indirect diff --git a/go.sum b/go.sum index dfbafbd..efb3212 100644 --- a/go.sum +++ b/go.sum @@ -19,8 +19,6 @@ github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5 github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496 h1:zV3ejI06GQ59hwDQAvmK1qxOQGB3WuVTRoY0okPTAv0= github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg= github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= -github.com/btcsuite/btcd/btcec/v2 v2.2.0 h1:fzn1qaOt32TuLjFlkzYSsBC35Q3KUjT1SwPxiMSCF5k= -github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU= github.com/certifi/gocertifi v0.0.0-20200211180108-c7c1fbc02894 h1:JLaf/iINcLyjwbtTsCJjc6rtlASgHeIJPrB6QmwURnA= github.com/certifi/gocertifi v0.0.0-20200211180108-c7c1fbc02894/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM= @@ -31,9 +29,6 @@ github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwc github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= @@ -101,14 +96,6 @@ github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T github.com/holiman/uint256 v1.2.4 h1:jUc4Nk8fm9jZabQuqr2JzednajVmBpC+oiTiXZJEApU= github.com/holiman/uint256 v1.2.4/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/iden3/go-iden3-core v1.0.2 h1:HwNDFeqcUv4ybZj5tH+58JKWKarn/qqBpNCqTLxGP0Y= -github.com/iden3/go-iden3-core v1.0.2/go.mod h1:X4PjlJG8OsEQEsSbzzYqqAk2olYGZ2nuGqiUPyEYjOo= -github.com/iden3/go-iden3-crypto v0.0.15 h1:4MJYlrot1l31Fzlo2sF56u7EVFeHHJkxGXXZCtESgK4= -github.com/iden3/go-iden3-crypto v0.0.15/go.mod h1:dLpM4vEPJ3nDHzhWFXDjzkn1qHoBeOT/3UEhXsEsP3E= -github.com/iden3/go-rapidsnark/types v0.0.3 h1:f0s1Qdut1qHe1O67+m+xUVRBPwSXnq5j0xSrBi0jqM4= -github.com/iden3/go-rapidsnark/types v0.0.3/go.mod h1:ApgcaUxKIgSRA6fAeFxK7p+lgXXfG4oA2HN5DhFlfF4= -github.com/iden3/go-rapidsnark/verifier v0.0.5 h1:J7y0ovrEjDQoWtZmlrp4tgGng1A9faMeYsQH4igAEqA= -github.com/iden3/go-rapidsnark/verifier v0.0.5/go.mod h1:KgL3Yr9NehlFDI4EIWVLE3UDUi8ulyjbp7HcXSBfiGI= github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/iris-contrib/blackfriday v2.0.0+incompatible/go.mod h1:UzZ2bDEoaSGPbkg6SAB4att1aAwTmVIx/5gCVqeyUdI= @@ -176,8 +163,6 @@ github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= -github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= -github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/nats-io/nats.go v1.8.1/go.mod h1:BrFz9vVn0fU3AcH9Vn4Kd7W0NpJ651tD5omQ3M8LwxM= github.com/nats-io/nkeys v0.0.2/go.mod h1:dab7URMsZm6Z/jp9Z5UGa87Uutgc2mVpXLC4B7TDb/4= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= @@ -197,10 +182,6 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/poy/onpar v1.1.2 h1:QaNrNiZx0+Nar5dLgTVp5mXkyoVFIbepjyEoGSnhbAY= github.com/poy/onpar v1.1.2/go.mod h1:6X8FLNoxyr9kkmnlqpK6LSoiOtrO6MICtWwEuWkLjzg= -github.com/rarimo/rarime-auth-svc v0.0.1-rc3 h1:KNvI0ifbZ3//A3a4yhKELMzyOP0Y1J5CJA30f0gaRrI= -github.com/rarimo/rarime-auth-svc v0.0.1-rc3/go.mod h1:48c8FsJixnLeWx8F8MDy79FvhU1r0oTU11mwP3JPngQ= -github.com/rarimo/rarime-auth-svc v0.0.1-rc7 h1:+ibnWRdc+fi27JrR3vOPLIXgOdePb29KyUCADt6HqeY= -github.com/rarimo/rarime-auth-svc v0.0.1-rc7/go.mod h1:48c8FsJixnLeWx8F8MDy79FvhU1r0oTU11mwP3JPngQ= github.com/rarimo/rarime-auth-svc v0.0.1-rc8 h1:MBx51/ynR8BaRz5HvcbatYe4hnB2ZDVwM7cmGEepg+Y= github.com/rarimo/rarime-auth-svc v0.0.1-rc8/go.mod h1:48c8FsJixnLeWx8F8MDy79FvhU1r0oTU11mwP3JPngQ= github.com/rarimo/rarime-auth-svc v0.0.1-rc9 h1:JZfq1q3WaaLwa8ICk8RHEx4+ojl/JBE8N5zJ/uHZUwM= @@ -280,6 +261,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ= +golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= diff --git a/internal/assets/migrations/001_initial.sql b/internal/assets/migrations/001_initial.sql index 754e6ab..af36176 100644 --- a/internal/assets/migrations/001_initial.sql +++ b/internal/assets/migrations/001_initial.sql @@ -5,17 +5,18 @@ create table if not exists proofs( created_at timestamp without time zone not null default now(), proof jsonb not null, org_id uuid not null, - type text not null + type text not null, + schema_url text not null ); create table if not exists links( - id uuid primary key not null, + id text primary key not null, user_id text not null, created_at timestamp not null default current_timestamp ); create table if not exists links_to_proofs( - link_id uuid not null, + link_id text not null, proof_id uuid not null, primary key (link_id, proof_id), foreign key (link_id) references links(id) on delete cascade, diff --git a/internal/assets/migrations/002_proof_schema.sql b/internal/assets/migrations/002_proof_schema.sql deleted file mode 100644 index 0dd53cf..0000000 --- a/internal/assets/migrations/002_proof_schema.sql +++ /dev/null @@ -1,5 +0,0 @@ --- +migrate Up -alter table proofs add column schema_url text not null default ''; - --- +migrate Down -alter table proofs drop column schema_url; diff --git a/internal/data/main.go b/internal/data/main.go index 045735d..892203b 100644 --- a/internal/data/main.go +++ b/internal/data/main.go @@ -2,7 +2,6 @@ package data import ( "context" - "github.com/google/uuid" ) @@ -33,7 +32,7 @@ type LinkQ interface { Upsert(l *Link) error Delete(l *Link) error SelectAllCtx(ctx context.Context) ([]*Link, error) - LinkByID(id uuid.UUID, isForUpdate bool) (*Link, error) + LinkByID(id string, isForUpdate bool) (*Link, error) Transaction(fn func(db LinkQ) error) error InsertCtxLinkToProof(ctx context.Context, linksToProof LinksToProof) error GetProofsLinksByUserID(ctx context.Context, userID string) ([]*Link, error) @@ -42,9 +41,9 @@ type LinkQ interface { type LinksToProofQ interface { Insert(l *LinksToProof) error Delete(l *LinksToProof) error - LinksToProofByLinkIDProofIDCtx(ctx context.Context, linkID, proofID uuid.UUID, isForUpdate bool) (*LinksToProof, error) + LinksToProofByLinkIDProofIDCtx(ctx context.Context, linkID string, proofID uuid.UUID, isForUpdate bool) (*LinksToProof, error) SelectAllCtx(ctx context.Context) ([]*LinksToProofQ, error) - GetLinksToProofsByLinkID(ctx context.Context, linkID uuid.UUID) ([]*LinksToProof, error) + GetLinksToProofsByLinkID(ctx context.Context, linkID string) ([]*LinksToProof, error) GetLinksToProofsByProofID(ctx context.Context, proofID uuid.UUID) ([]*LinksToProof, error) } diff --git a/internal/data/pg/links_to_proofs_schemas.go b/internal/data/pg/links_to_proofs_schemas.go index f7a126f..a86a273 100644 --- a/internal/data/pg/links_to_proofs_schemas.go +++ b/internal/data/pg/links_to_proofs_schemas.go @@ -20,7 +20,7 @@ func (q LinksToProofQ) SelectAllCtx(ctx context.Context) ([]*data.LinksToProofQ, return links, nil } -func (q LinksToProofQ) GetLinksToProofsByLinkID(ctx context.Context, linkID uuid.UUID) ([]*data.LinksToProof, error) { +func (q LinksToProofQ) GetLinksToProofsByLinkID(ctx context.Context, linkID string) ([]*data.LinksToProof, error) { stmt := squirrel.Select("*"). From("public.links_to_proofs"). Where(squirrel.Eq{"link_id": linkID}) diff --git a/internal/data/pg/schema.xo.go b/internal/data/pg/schema.xo.go index 04a535d..174508c 100644 --- a/internal/data/pg/schema.xo.go +++ b/internal/data/pg/schema.xo.go @@ -404,7 +404,7 @@ func (q GorpMigrationQ) GorpMigrationByID(id string, isForUpdate bool) (*data.Go // LinkByIDCtx retrieves a row from 'public.links' as a Link. // // Generated from index 'links_pkey'. -func (q LinkQ) LinkByIDCtx(ctx context.Context, id uuid.UUID, isForUpdate bool) (*data.Link, error) { +func (q LinkQ) LinkByIDCtx(ctx context.Context, id string, isForUpdate bool) (*data.Link, error) { // query sqlstr := `SELECT ` + `id, user_id, created_at ` + @@ -430,14 +430,14 @@ func (q LinkQ) LinkByIDCtx(ctx context.Context, id uuid.UUID, isForUpdate bool) // LinkByID retrieves a row from 'public.links' as a Link. // // Generated from index 'links_pkey'. -func (q LinkQ) LinkByID(id uuid.UUID, isForUpdate bool) (*data.Link, error) { +func (q LinkQ) LinkByID(id string, isForUpdate bool) (*data.Link, error) { return q.LinkByIDCtx(context.Background(), id, isForUpdate) } // LinksToProofByLinkIDProofIDCtx retrieves a row from 'public.links_to_proofs' as a LinksToProof. // // Generated from index 'links_to_proofs_pkey'. -func (q LinksToProofQ) LinksToProofByLinkIDProofIDCtx(ctx context.Context, linkID, proofID uuid.UUID, isForUpdate bool) (*data.LinksToProof, error) { +func (q LinksToProofQ) LinksToProofByLinkIDProofIDCtx(ctx context.Context, linkID string, proofID uuid.UUID, isForUpdate bool) (*data.LinksToProof, error) { // query sqlstr := `SELECT ` + `link_id, proof_id ` + @@ -463,7 +463,7 @@ func (q LinksToProofQ) LinksToProofByLinkIDProofIDCtx(ctx context.Context, linkI // LinksToProofByLinkIDProofID retrieves a row from 'public.links_to_proofs' as a LinksToProof. // // Generated from index 'links_to_proofs_pkey'. -func (q LinksToProofQ) LinksToProofByLinkIDProofID(linkID, proofID uuid.UUID, isForUpdate bool) (*data.LinksToProof, error) { +func (q LinksToProofQ) LinksToProofByLinkIDProofID(linkID string, proofID uuid.UUID, isForUpdate bool) (*data.LinksToProof, error) { return q.LinksToProofByLinkIDProofIDCtx(context.Background(), linkID, proofID, isForUpdate) } diff --git a/internal/data/schema.xo.go b/internal/data/schema.xo.go index 070683a..65b8cc9 100644 --- a/internal/data/schema.xo.go +++ b/internal/data/schema.xo.go @@ -73,7 +73,7 @@ type GorpMigration struct { // Link represents a row from 'public.links'. type Link struct { - ID uuid.UUID `db:"id" json:"id" structs:"-"` // id + ID string `db:"id" json:"id" structs:"-"` // id UserID string `db:"user_id" json:"user_id" structs:"user_id"` // user_id CreatedAt time.Time `db:"created_at" json:"created_at" structs:"created_at"` // created_at @@ -81,7 +81,7 @@ type Link struct { // LinksToProof represents a row from 'public.links_to_proofs'. type LinksToProof struct { - LinkID uuid.UUID `db:"link_id" json:"link_id" structs:"-"` // link_id + LinkID string `db:"link_id" json:"link_id" structs:"-"` // link_id ProofID uuid.UUID `db:"proof_id" json:"proof_id" structs:"-"` // proof_id } diff --git a/internal/services/api/handlers/create_proof_link.go b/internal/services/api/handlers/create_proof_link.go index b79d56d..7abedae 100644 --- a/internal/services/api/handlers/create_proof_link.go +++ b/internal/services/api/handlers/create_proof_link.go @@ -3,6 +3,7 @@ package handlers import ( "encoding/json" "net/http" + "strings" "time" "github.com/google/uuid" @@ -12,11 +13,15 @@ import ( "gitlab.com/distributed_lab/ape" "gitlab.com/distributed_lab/ape/problems" "gitlab.com/distributed_lab/logan/v3/errors" + "golang.org/x/exp/utf8string" ) +const maxLinkNameLen = 50 + type ProofLink struct { UserDID string `json:"user_did"` ProofsIds []uuid.UUID `json:"proofs_ids"` + LinkName *string `json:"link_name,omitempty"` } type ProofLinkRequest struct { @@ -30,6 +35,16 @@ func newProofLinkCreateRequest(r *http.Request) (*ProofLinkRequest, error) { return nil, errors.Wrap(err, "failed to decode body") } + if req.Data.LinkName != nil { + if utf8string.NewString(*req.Data.LinkName).IsASCII() { + if len([]rune(*req.Data.LinkName)) > maxLinkNameLen { + return nil, errors.New("link name length is too big") + } + return &req, nil + } + return nil, errors.New("link name is not ASCII") + } + return &req, nil } @@ -46,21 +61,28 @@ func CreateProofLink(w http.ResponseWriter, r *http.Request) { } var ( + linkID string timestamp = time.Now().UTC() - linkID = uuid.New() proofs []data.Proof proofNotFound = errors.New("proof not found") invalidCreator = errors.New("invalid proof creator") ) err = Storage(r).LinkQ().Transaction(func(q data.LinkQ) error { + linkID = uuid.New().String() + if req.Data.LinkName != nil { + linkID = *req.Data.LinkName + } err = q.Insert(&data.Link{ ID: linkID, UserID: req.Data.UserDID, CreatedAt: timestamp, }) - if err != nil { + if strings.Contains(err.Error(), "duplicate key value violates unique constraint") { + ape.RenderErr(w, problems.Conflict()) + return err + } ape.RenderErr(w, problems.InternalError()) return err } @@ -71,7 +93,6 @@ func CreateProofLink(w http.ResponseWriter, r *http.Request) { ape.RenderErr(w, problems.InternalError()) return err } - if p == nil { ape.RenderErr(w, problems.NotFound()) return proofNotFound @@ -88,7 +109,6 @@ func CreateProofLink(w http.ResponseWriter, r *http.Request) { LinkID: linkID, ProofID: proofID, }) - if err != nil { ape.RenderErr(w, problems.InternalError()) return err @@ -110,7 +130,7 @@ func CreateProofLink(w http.ResponseWriter, r *http.Request) { Type: resources.LINKS, }, Attributes: resources.LinkAttributes{ - Link: linkID.String(), + Link: linkID, CreatedAt: timestamp, }, }, diff --git a/internal/services/api/handlers/get_links_by_user.go b/internal/services/api/handlers/get_links_by_user.go index df472f3..ef451ee 100644 --- a/internal/services/api/handlers/get_links_by_user.go +++ b/internal/services/api/handlers/get_links_by_user.go @@ -2,13 +2,14 @@ package handlers import ( "context" + "net/http" validation "github.com/go-ozzo/ozzo-validation/v4" + "github.com/rarimo/rarime-auth-svc/pkg/auth" "github.com/rarimo/rarime-link-svc/resources" "gitlab.com/distributed_lab/ape" "gitlab.com/distributed_lab/ape/problems" "gitlab.com/distributed_lab/urlval" - "net/http" ) type proofsLinksByUserDIDRequest struct { @@ -34,6 +35,11 @@ func GetLinks(w http.ResponseWriter, r *http.Request) { return } + if !auth.Authenticates(UserClaim(r), auth.UserGrant(req.UserDid)) { + ape.RenderErr(w, problems.Unauthorized()) + return + } + proofsLinks, err := Storage(r).LinkQ().GetProofsLinksByUserID(context.Background(), req.UserDid) if err != nil { Log(r).WithError(err).Error("failed to get proofs") @@ -51,12 +57,12 @@ func GetLinks(w http.ResponseWriter, r *http.Request) { linkResponse := resources.LinkResponse{ Data: resources.Link{ Key: resources.Key{ - ID: link.ID.String(), + ID: link.ID, Type: resources.LINKS, }, Attributes: resources.LinkAttributes{ CreatedAt: link.CreatedAt, - Link: link.ID.String(), + Link: link.ID, }, }, } diff --git a/internal/services/api/handlers/get_proofs_by_link.go b/internal/services/api/handlers/get_proofs_by_link.go index f4a3106..261c1c8 100644 --- a/internal/services/api/handlers/get_proofs_by_link.go +++ b/internal/services/api/handlers/get_proofs_by_link.go @@ -1,31 +1,40 @@ package handlers import ( + "net/http" + "github.com/go-chi/chi" "github.com/google/uuid" "github.com/rarimo/rarime-link-svc/resources" "gitlab.com/distributed_lab/ape" "gitlab.com/distributed_lab/ape/problems" "gitlab.com/distributed_lab/logan/v3/errors" - "net/http" + "golang.org/x/exp/utf8string" ) type proofsByLinkID struct { - LinkID uuid.UUID + linkID string } func newLinkByIDRequest(r *http.Request) (proofsByLinkID, error) { linkID := chi.URLParam(r, "link_id") if linkID == "" { - return proofsByLinkID{}, errors.New("user_did is required") + return proofsByLinkID{}, errors.New("link_id is required") } uuidLinkID, err := uuid.Parse(linkID) if err != nil { + if utf8string.NewString(linkID).IsASCII() { + return proofsByLinkID{ + linkID: linkID, + }, nil + } return proofsByLinkID{}, errors.New("invalid link_id") } - return proofsByLinkID{uuidLinkID}, nil + return proofsByLinkID{ + linkID: uuidLinkID.String(), + }, nil } func GetLinkByID(w http.ResponseWriter, r *http.Request) { @@ -35,26 +44,26 @@ func GetLinkByID(w http.ResponseWriter, r *http.Request) { return } - link, err := Storage(r).LinkQ().LinkByID(req.LinkID, false) + link, err := Storage(r).LinkQ().LinkByID(req.linkID, false) if err != nil { Log(r).WithError(err).Error("failed to get link by UUID") ape.RenderErr(w, problems.InternalError()) return } if link == nil { - Log(r).WithField("link_id", req.LinkID).Warn("link not found") + Log(r).WithField("link_id", req.linkID).Warn("link not found") ape.RenderErr(w, problems.NotFound()) return } - links, err := Storage(r).LinksToProofQ().GetLinksToProofsByLinkID(r.Context(), req.LinkID) + links, err := Storage(r).LinksToProofQ().GetLinksToProofsByLinkID(r.Context(), link.ID) if err != nil { Log(r).WithError(err).Error("failed to get link to proofs") ape.RenderErr(w, problems.InternalError()) return } if len(links) == 0 { - Log(r).WithField("link_id", req.LinkID).Warn("links not found") + Log(r).WithField("link_id", req.linkID).Warn("links not found") ape.RenderErr(w, problems.NotFound()) return } @@ -62,12 +71,12 @@ func GetLinkByID(w http.ResponseWriter, r *http.Request) { response := resources.LinkResponse{ Data: resources.Link{ Key: resources.Key{ - ID: link.ID.String(), + ID: link.ID, Type: resources.LINKS, }, Attributes: resources.LinkAttributes{ CreatedAt: link.CreatedAt, - Link: link.ID.String(), + Link: link.ID, }, }, } diff --git a/internal/services/api/main.go b/internal/services/api/main.go index 2dcf331..2d39de4 100644 --- a/internal/services/api/main.go +++ b/internal/services/api/main.go @@ -4,13 +4,12 @@ import ( "context" "time" - "github.com/rarimo/rarime-link-svc/internal/services/proofs_cleaner" - "gitlab.com/distributed_lab/logan/v3" - "github.com/go-chi/chi" "github.com/rarimo/rarime-link-svc/internal/config" "github.com/rarimo/rarime-link-svc/internal/services/api/handlers" + "github.com/rarimo/rarime-link-svc/internal/services/proofs_cleaner" "gitlab.com/distributed_lab/ape" + "gitlab.com/distributed_lab/logan/v3" ) func Run(ctx context.Context, cfg config.Config) { @@ -34,29 +33,31 @@ func Run(ctx context.Context, cfg config.Config) { ), ) - r.Route("/v1", func(r chi.Router) { - r.Route("/proofs", func(r chi.Router) { - r.Group(func(r chi.Router) { - r.Use(handlers.AuthMiddleware(cfg.Auth(), cfg.Log())) - r.Get("/", handlers.GetProofs) - r.Post("/", handlers.CreateProof) - }) + r.Route("/integrations/rarime-link-svc", func(r chi.Router) { + r.Route("/v1", func(r chi.Router) { + r.Route("/proofs", func(r chi.Router) { + r.Group(func(r chi.Router) { + r.Use(handlers.AuthMiddleware(cfg.Auth(), cfg.Log())) + r.Get("/", handlers.GetProofs) + r.Post("/", handlers.CreateProof) + }) - r.Route("/{id}", func(r chi.Router) { - r.Use(handlers.AuthMiddleware(cfg.Auth(), cfg.Log())) - r.Get("/", handlers.ProofByID) + r.Route("/{id}", func(r chi.Router) { + r.Use(handlers.AuthMiddleware(cfg.Auth(), cfg.Log())) + r.Get("/", handlers.ProofByID) + }) }) - }) - r.Route("/links", func(r chi.Router) { - r.Group(func(r chi.Router) { - r.Use(handlers.AuthMiddleware(cfg.Auth(), cfg.Log())) - r.Get("/", handlers.GetLinks) - r.Post("/", handlers.CreateProofLink) - }) + r.Route("/links", func(r chi.Router) { + r.Group(func(r chi.Router) { + r.Use(handlers.AuthMiddleware(cfg.Auth(), cfg.Log())) + r.Get("/", handlers.GetLinks) + r.Post("/", handlers.CreateProofLink) + }) - r.Route("/{link_id}", func(r chi.Router) { - r.Get("/", handlers.GetLinkByID) + r.Route("/{link_id}", func(r chi.Router) { + r.Get("/", handlers.GetLinkByID) + }) }) }) }) diff --git a/resources/model_link_attributes.go b/resources/model_link_attributes.go index 3049748..b4575ff 100644 --- a/resources/model_link_attributes.go +++ b/resources/model_link_attributes.go @@ -9,6 +9,6 @@ import "time" type LinkAttributes struct { // The date and time when the proof was created in the RFC3339 format CreatedAt time.Time `json:"created_at"` - // UUID Link to proofs + // Link to proofs ID (UUID or custom ASCII string) Link string `json:"link"` } diff --git a/resources/model_proof_create.go b/resources/model_proof_create.go index b639c8a..2aaa65a 100644 --- a/resources/model_proof_create.go +++ b/resources/model_proof_create.go @@ -11,8 +11,8 @@ type ProofCreate struct { Proof string `json:"proof"` // The type of the proof ProofType string `json:"proof_type"` - // The user DID - UserDid string `json:"user_did"` // The schema URL of the claim the proof was created based on SchemaUrl string `json:"schema_url"` + // The user DID + UserDid string `json:"user_did"` }