Skip to content

Commit

Permalink
Merge pull request #521 from 0xPolygonID/hotfix-wrong-qr-code-get-lin…
Browse files Browse the repository at this point in the history
…k-qr-code

fix: get link qr code was using old version of qr codes
  • Loading branch information
martinsaporiti authored Nov 8, 2023
2 parents 60a83b5 + d620a13 commit ed5e0b9
Show file tree
Hide file tree
Showing 11 changed files with 64 additions and 139 deletions.
35 changes: 2 additions & 33 deletions api_ui/api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -997,38 +997,6 @@ components:
type: string
example: "vaccinationCertificate"

QrCodeResponse:
type: object
required:
- id
- typ
- type
- thid
- body
- from
- to
properties:
id:
type: string
example: f7c6cdf9-878e-40c3-89f1-85bf1fb80865
typ:
type: string
example: application/iden3comm-plain-json
type:
type: string
example: https://iden3-communication.io/authorization/1.0/request
thid:
type: string
example: f7c6cdf9-878e-40c3-89f1-85bf1fb80865
body:
$ref: '#/components/schemas/QrCodeBodyResponse'
from:
type: string
example: did:polygonid:polygon:mumbai:2qFpPHotk6oyaX1fcrpQFT4BMnmg8YszUwxYtaoGoe
to:
type: string
example: did:polygonid:polygon:mumbai:2qPtCq1WDpimtqsFPkpbBYzgzDbJ8i3pn9vHDLyF63

QrCodeBodyResponse:
type: object
required:
Expand Down Expand Up @@ -1098,7 +1066,8 @@ components:
- linkDetail
properties:
qrCode:
$ref: '#/components/schemas/QrCodeResponse'
type: string
example: iden3comm://?request_uri=https%3A%2F%2Fissuer-demo.polygonid.me%2Fapi%2Fqr-store%3Fid%3Df780a169-8959-4380-9461-f7200e2ed3f4
status:
type: string
example: done | pending | pendingPublish
Expand Down
29 changes: 3 additions & 26 deletions internal/api_ui/api.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 6 additions & 1 deletion internal/api_ui/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,11 @@ func checkQRfetchURLForCredential(t *testing.T, body []byte) string {
t.Helper()
bodyR := &GetCredentialQrCode200JSONResponse{}
require.NoError(t, json.Unmarshal(body, bodyR))
qrURL, err := url.Parse(bodyR.QrCodeLink)
return parseIden3commQRCodeResponse(t, bodyR.QrCodeLink)
}

func parseIden3commQRCodeResponse(t *testing.T, input string) string {
qrURL, err := url.Parse(input)
require.NoError(t, err)
assert.Equal(t, "iden3comm", qrURL.Scheme)
vals, err := url.ParseQuery(qrURL.RawQuery)
Expand All @@ -169,6 +173,7 @@ func checkQRfetchURLForCredential(t *testing.T, body []byte) string {
require.True(t, found)
fetchURL, err := url.QueryUnescape(val[0])
require.NoError(t, err)

return fetchURL
}

Expand Down
27 changes: 0 additions & 27 deletions internal/api_ui/responses.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (

"github.com/polygonid/sh-id-platform/internal/common"
"github.com/polygonid/sh-id-platform/internal/core/domain"
linkstate "github.com/polygonid/sh-id-platform/pkg/link"
"github.com/polygonid/sh-id-platform/pkg/schema"
)

Expand Down Expand Up @@ -279,32 +278,6 @@ func getLinkResponses(links []domain.Link) []Link {
return res
}

func getLinkQrCodeResponse(linkQrCode *linkstate.QRCodeMessage) *QrCodeResponse {
if linkQrCode == nil {
return nil
}
credentials := make([]QrCodeCredentialResponse, len(linkQrCode.Body.Credentials))
for i, c := range linkQrCode.Body.Credentials {
credentials[i] = QrCodeCredentialResponse{
Id: c.ID,
Description: c.Description,
}
}

return &QrCodeResponse{
Id: linkQrCode.ID,
Thid: linkQrCode.ThreadID,
Typ: linkQrCode.Typ,
Type: linkQrCode.Type,
From: linkQrCode.From,
To: linkQrCode.To,
Body: QrCodeBodyResponse{
Url: linkQrCode.Body.URL,
Credentials: credentials,
},
}
}

func getRevocationStatusResponse(rs *verifiable.RevocationStatus) RevocationStatusResponse {
response := RevocationStatusResponse{}
response.Issuer.State = rs.Issuer.State
Expand Down
2 changes: 1 addition & 1 deletion internal/api_ui/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -611,7 +611,7 @@ func (s *Server) GetLinkQRCode(ctx context.Context, request GetLinkQRCodeRequest
if getQRCodeResponse.State.Status == link_state.StatusPending || getQRCodeResponse.State.Status == link_state.StatusDone || getQRCodeResponse.State.Status == link_state.StatusPendingPublish {
return GetLinkQRCode200JSONResponse{
Status: common.ToPointer(getQRCodeResponse.State.Status),
QrCode: getLinkQrCodeResponse(getQRCodeResponse.State.QRCode),
QrCode: getQRCodeResponse.State.QRCode,
LinkDetail: getLinkSimpleResponse(*getQRCodeResponse.Link),
}, nil
}
Expand Down
62 changes: 28 additions & 34 deletions internal/api_ui/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1786,7 +1786,6 @@ func TestServer_GetCredentialQrCode(t *testing.T) {

type expected struct {
message *string
response QrCodeResponse
httpCode int
}

Expand All @@ -1812,19 +1811,6 @@ func TestServer_GetCredentialQrCode(t *testing.T) {
Id: createdClaim.ID,
},
expected: expected{
response: QrCodeResponse{
Body: QrCodeBodyResponse{
Credentials: []QrCodeCredentialResponse{
{
Description: schema,
Id: createdClaim.ID.String(),
},
},
Url: "",
},
From: did.String(),
To: createdClaim.OtherIdentifier,
},
httpCode: http.StatusOK,
},
},
Expand Down Expand Up @@ -1854,11 +1840,6 @@ func TestServer_GetCredentialQrCode(t *testing.T) {
// Let's verify the QR body
realQR := protocol.CredentialsOfferMessage{}
require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &realQR))

require.Equal(t, tc.expected.response.From, realQR.From)
require.Equal(t, tc.expected.response.To, realQR.To)
require.Equal(t, len(tc.expected.response.Body.Credentials), len(realQR.Body.Credentials))

case http.StatusBadRequest:
var response GetCredential400JSONResponse
require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &response))
Expand Down Expand Up @@ -3795,10 +3776,11 @@ func TestServer_GetLinkQRCode(t *testing.T) {
sessionRepository := repositories.NewSessionCached(cachex)
revocationStatusResolver := revocation_status.NewRevocationStatusResolver(cfg.CredentialStatus)
rhsFactory := reverse_hash.NewFactory(cfg.CredentialStatus.RHS.URL, nil, commonEth.HexToAddress(cfg.CredentialStatus.OnchainTreeStore.SupportedTreeStoreContract), reverse_hash.DefaultRHSTimeOut)
identityService := services.NewIdentity(keyStore, identityRepo, mtRepo, identityStateRepo, mtService, nil, claimsRepo, revocationRepository, connectionsRepository, storage, nil, nil, pubsub.NewMock(), cfg.CredentialStatus, rhsFactory, revocationStatusResolver)
claimsService := services.NewClaim(claimsRepo, identityService, nil, mtService, identityStateRepo, schemaLoader, storage, cfg.CredentialStatus.DirectStatus.GetURL(), pubsub.NewMock(), ipfsGatewayURL, revocationStatusResolver)
qrService := services.NewQrStoreService(cachex)
identityService := services.NewIdentity(keyStore, identityRepo, mtRepo, identityStateRepo, mtService, qrService, claimsRepo, revocationRepository, connectionsRepository, storage, nil, nil, pubsub.NewMock(), cfg.CredentialStatus, rhsFactory, revocationStatusResolver)
claimsService := services.NewClaim(claimsRepo, identityService, qrService, mtService, identityStateRepo, schemaLoader, storage, cfg.CredentialStatus.DirectStatus.GetURL(), pubsub.NewMock(), ipfsGatewayURL, revocationStatusResolver)
connectionsService := services.NewConnection(connectionsRepository, storage)
linkService := services.NewLinkService(storage, claimsService, nil, claimsRepo, linkRepository, schemaRepository, schemaLoader, sessionRepository, pubsub.NewMock(), ipfsGatewayURL)
linkService := services.NewLinkService(storage, claimsService, qrService, claimsRepo, linkRepository, schemaRepository, schemaLoader, sessionRepository, pubsub.NewMock(), ipfsGatewayURL)
iden, err := identityService.Create(ctx, "polygon-test", &ports.DIDCreationOptions{Method: method, Blockchain: blockchain, Network: network, KeyType: BJJ})
require.NoError(t, err)

Expand All @@ -3813,7 +3795,7 @@ func TestServer_GetLinkQRCode(t *testing.T) {
cfg.APIUI.IssuerDID = *did
cfg.APIUI.ServerURL = "http://localhost/issuer-admin"

server := NewServer(&cfg, NewIdentityMock(), claimsService, NewSchemaMock(), connectionsService, linkService, nil, NewPublisherMock(), NewPackageManagerMock(), nil)
server := NewServer(&cfg, NewIdentityMock(), claimsService, NewSchemaMock(), connectionsService, linkService, qrService, NewPublisherMock(), NewPackageManagerMock(), nil)

validUntil := common.ToPointer(time.Date(2023, 8, 15, 14, 30, 45, 0, time.Local))
credentialExpiration := common.ToPointer(time.Date(2025, 8, 15, 14, 30, 45, 0, time.Local))
Expand Down Expand Up @@ -3842,10 +3824,16 @@ func TestServer_GetLinkQRCode(t *testing.T) {
To: userDID.String(),
}

qrCodeBytes, err := json.Marshal(qrcode)
require.NoError(t, err)

linkDetail := getLinkResponse(*link)
id, err := qrService.Store(ctx, qrCodeBytes, 100*time.Second)
require.NoError(t, err)
qrCodeLink := qrService.ToURL("http://localhost:3002", id)

type expected struct {
qrCode *linkState.QRCodeMessage
qrCode *string
linkDetail Link
status string
httpCode int
Expand Down Expand Up @@ -3901,10 +3889,10 @@ func TestServer_GetLinkQRCode(t *testing.T) {
name: "Happy path",
id: link.ID,
sessionID: sessionID,
state: linkState.NewStateDone(qrcode),
state: linkState.NewStateDone(qrCodeLink),
expected: expected{
linkDetail: linkDetail,
qrCode: qrcode,
qrCode: common.ToPointer(qrCodeLink),
status: "done",
httpCode: http.StatusOK,
},
Expand All @@ -3930,17 +3918,23 @@ func TestServer_GetLinkQRCode(t *testing.T) {
if tc.expected.status == "pending" {
assert.Equal(t, tc.expected.status, *response.Status)
} else {
assert.NotNil(t, response.QrCode.Body)
assert.Equal(t, tc.expected.qrCode.Body.Credentials[0].ID, response.QrCode.Body.Credentials[0].Id)
assert.Equal(t, tc.expected.qrCode.Body.Credentials[0].Description, response.QrCode.Body.Credentials[0].Description)
assert.Equal(t, tc.expected.qrCode.Body.URL, response.QrCode.Body.Url)
assert.NotNil(t, response.QrCode.Id)
assert.Equal(t, tc.expected.qrCode.Type, response.QrCode.Type)
assert.Equal(t, tc.expected.qrCode.Typ, response.QrCode.Typ)
assert.Equal(t, tc.expected.qrCode.From, response.QrCode.From)
assert.Equal(t, tc.expected.linkDetail.Id, response.LinkDetail.Id)
assert.Equal(t, tc.expected.linkDetail.SchemaType, response.LinkDetail.SchemaType)
assert.Equal(t, tc.expected.status, *response.Status)
require.NotNil(t, response.QrCode)
assert.Equal(t, *tc.expected.qrCode, *response.QrCode)
qrLink := parseIden3commQRCodeResponse(t, *response.QrCode)

// Now let's fetch the original QR using the url
rr := httptest.NewRecorder()
req, err := http.NewRequest(http.MethodGet, qrLink, nil)
require.NoError(t, err)
handler.ServeHTTP(rr, req)
require.Equal(t, http.StatusOK, rr.Code)

// Let's verify the QR body
realQR := protocol.CredentialsOfferMessage{}
require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &realQR))
}
}
})
Expand Down
14 changes: 13 additions & 1 deletion internal/core/services/link.go
Original file line number Diff line number Diff line change
Expand Up @@ -302,8 +302,20 @@ func (ls *Link) IssueClaim(ctx context.Context, sessionID string, issuerDID w3c.
To: userDID.String(),
}

qrCodeBytes, err := json.Marshal(r)
if err != nil {
log.Error(ctx, "cannot marshal the qr code", "err", err)
return err
}

id, err := ls.qrService.Store(ctx, qrCodeBytes, DefaultQRBodyTTL)
if err != nil {
log.Error(ctx, "cannot store the qr code", "err", err)
return err
}

if link.CredentialSignatureProof {
err = ls.sessionManager.SetLink(ctx, linkState.CredentialStateCacheKey(linkID.String(), sessionID), *linkState.NewStateDone(r))
err = ls.sessionManager.SetLink(ctx, linkState.CredentialStateCacheKey(linkID.String(), sessionID), *linkState.NewStateDone(ls.qrService.ToURL(hostURL, id)))
} else {
err = ls.sessionManager.SetLink(ctx, linkState.CredentialStateCacheKey(linkID.String(), sessionID), *linkState.NewStatePendingPublish())
}
Expand Down
3 changes: 2 additions & 1 deletion internal/core/services/tests/link_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ func Test_link_issueClaim(t *testing.T) {
assert.NoError(t, err)

linkRepository := repositories.NewLink(*storage)
linkService := services.NewLinkService(storage, claimsService, nil, claimsRepo, linkRepository, schemaRepository, docLoader, sessionRepository, pubsub.NewMock(), ipfsGateway)
qrService := services.NewQrStoreService(cachex)
linkService := services.NewLinkService(storage, claimsService, qrService, claimsRepo, linkRepository, schemaRepository, docLoader, sessionRepository, pubsub.NewMock(), ipfsGateway)

tomorrow := time.Now().Add(24 * time.Hour)
nextWeek := time.Now().Add(7 * 24 * time.Hour)
Expand Down
10 changes: 5 additions & 5 deletions pkg/link/link_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ type QRCodeMessage struct {

// State - Link state.
type State struct {
Status string `json:"status,omitempty"`
Message string `json:"message,omitempty"`
QRCode *QRCodeMessage `json:"qrcode,omitempty"`
Status string `json:"status,omitempty"`
Message string `json:"message,omitempty"`
QRCode *string `json:"qrcode,omitempty"`
}

// NewStatePending - TODO
Expand All @@ -73,10 +73,10 @@ func NewStateError(err error) *State {
}

// NewStateDone - TODO
func NewStateDone(qrcode *QRCodeMessage) *State {
func NewStateDone(qrCodeLink string) *State {
state := &State{
Status: StatusDone,
QRCode: qrcode,
QRCode: &qrCodeLink,
}
return state
}
Expand Down
4 changes: 2 additions & 2 deletions ui/src/adapters/api/credentials.ts
Original file line number Diff line number Diff line change
Expand Up @@ -448,13 +448,13 @@ export async function getIssuedQRCode({
}

export type ImportQRCode = {
qrCode?: unknown;
qrCode: string;
status: "done" | "pending" | "pendingPublish";
};

const importQRCodeParser = getStrictParser<ImportQRCode>()(
z.object({
qrCode: z.unknown(),
qrCode: z.string(),
status: z.union([z.literal("done"), z.literal("pendingPublish"), z.literal("pending")]),
})
);
Expand Down
10 changes: 2 additions & 8 deletions ui/src/components/credentials/ClaimCredentialModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,7 @@ import { QRCodeSVG } from "qrcode.react";
import { ReactComponent as IconClose } from "src/assets/icons/x.svg";
import { CLOSE } from "src/utils/constants";

export function ClaimCredentialModal({
onClose,
qrCode,
}: {
onClose: () => void;
qrCode: unknown;
}) {
export function ClaimCredentialModal({ onClose, qrCode }: { onClose: () => void; qrCode: string }) {
return (
<Modal
centered
Expand All @@ -35,7 +29,7 @@ export function ClaimCredentialModal({
includeMargin
level="H"
style={{ height: 300 }}
value={JSON.stringify(qrCode)}
value={qrCode}
/>
</Modal>
);
Expand Down

0 comments on commit ed5e0b9

Please sign in to comment.