diff --git a/internal/core/services/claims.go b/internal/core/services/claims.go index 243970374..5c8d422c9 100644 --- a/internal/core/services/claims.go +++ b/internal/core/services/claims.go @@ -22,6 +22,7 @@ import ( "github.com/iden3/iden3comm/v2/protocol" shell "github.com/ipfs/go-ipfs-api" "github.com/jackc/pgx/v4" + "github.com/polygonid/sh-id-platform/internal/urn" "github.com/polygonid/sh-id-platform/internal/common" "github.com/polygonid/sh-id-platform/internal/core/domain" @@ -652,10 +653,13 @@ func (c *claim) getAgentCredential(ctx context.Context, basicMessage *ports.Agen return nil, fmt.Errorf("invalid credential fetch request body: %w", err) } - claimID, err := uuid.Parse(fetchRequestBody.ID) + claimID, err := urn.Parse(urn.URN(fetchRequestBody.ID)) if err != nil { - log.Error(ctx, "wrong claimID in agent request body", "err", err) - return nil, fmt.Errorf("invalid claim ID") + claimID, err = uuid.Parse(fetchRequestBody.ID) + if err != nil { + log.Error(ctx, "wrong claimID in agent request body", "err", err) + return nil, fmt.Errorf("invalid claim ID") + } } claim, err := c.icRepo.GetByIdAndIssuer(ctx, c.storage.Pgx, basicMessage.IssuerDID, claimID) @@ -802,7 +806,7 @@ func (c *claim) newVerifiableCredential(ctx context.Context, claimReq *ports.Cre issuanceDate := time.Now().UTC() return verifiable.W3CCredential{ - ID: c.buildCredentialID(*claimReq.DID, vcID, claimReq.SingleIssuer), + ID: string(c.buildCredentialID(vcID)), Context: credentialCtx, Type: credentialType, Expiration: claimReq.Expiration, @@ -819,10 +823,6 @@ func (c *claim) newVerifiableCredential(ctx context.Context, claimReq *ports.Cre }, nil } -func (c *claim) buildCredentialID(issuerDID w3c.DID, credID uuid.UUID, singleIssuer bool) string { - // TODO: review how to build the credential ID - if singleIssuer { - return fmt.Sprintf("%s/v1/credentials/%s", strings.TrimSuffix(c.host, "/"), credID.String()) - } - return fmt.Sprintf("%s/v1/%s/claims/%s", strings.TrimSuffix(c.host, "/"), issuerDID.String(), credID.String()) +func (c *claim) buildCredentialID(credID uuid.UUID) urn.URN { + return urn.FromUUID(credID) } diff --git a/internal/urn/urn.go b/internal/urn/urn.go new file mode 100644 index 000000000..69b298d39 --- /dev/null +++ b/internal/urn/urn.go @@ -0,0 +1,25 @@ +package urn + +import ( + "errors" + + "github.com/google/uuid" +) + +type URN string + +// FromUUID creates a URN from a UUID. +func FromUUID(uuid uuid.UUID) URN { + return URN("urn:uuid:" + uuid.String()) +} + +// Parse extracts a UUID from a URN. +func Parse(u URN) (uuid.UUID, error) { + if len(u) < len("urn:uuid:") { + return uuid.UUID{}, errors.New("invalid uuid URN length") + } + if u[:9] != "urn:uuid:" { + return uuid.UUID{}, errors.New("invalid uuid URN prefix") + } + return uuid.Parse(string(u[9:])) +} diff --git a/internal/urn/urn_test.go b/internal/urn/urn_test.go new file mode 100644 index 000000000..bac33d58a --- /dev/null +++ b/internal/urn/urn_test.go @@ -0,0 +1,36 @@ +package urn + +import ( + "errors" + "testing" + + "github.com/google/uuid" + "github.com/stretchr/testify/assert" +) + +func TestFromUUID(t *testing.T) { + id := uuid.New() + urn := FromUUID(id) + assert.Equal(t, "urn:uuid:"+id.String(), string(urn)) +} + +func TestParse(t *testing.T) { + for _, ts := range []struct { + urn string + err error + }{ + {"", errors.New("invalid uuid URN length")}, + {"urn:uuid:", errors.New("invalid UUID length: 0")}, + {"urn:uuid:1234", errors.New("invalid UUID length: 4")}, + {"urn:uuid:123e4567-e89b-12d3-a456-426614174000", nil}, + } { + t.Run(ts.urn, func(t *testing.T) { + u, err := Parse(URN(ts.urn)) + if err == nil { + assert.Equal(t, ts.urn[9:], u.String()) + } else { + assert.Equal(t, ts.err.Error(), err.Error()) + } + }) + } +}