diff --git a/api/api.yaml b/api/api.yaml index cc49e3c36..de7eb02cf 100644 --- a/api/api.yaml +++ b/api/api.yaml @@ -987,6 +987,8 @@ paths: type: object '400': $ref: '#/components/responses/400' + '410': + $ref: '#/components/responses/410' '404': $ref: '#/components/responses/404' '500': @@ -2416,6 +2418,12 @@ components: application/json: schema: $ref: '#/components/schemas/GenericErrorMessage' + '410': + description: 'Gone' + content: + application/json: + schema: + $ref: '#/components/schemas/GenericErrorMessage' '422': description: 'Unprocessable Content' content: diff --git a/internal/api/api.gen.go b/internal/api/api.gen.go index 39d9a9a1f..864b3a6aa 100644 --- a/internal/api/api.gen.go +++ b/internal/api/api.gen.go @@ -605,6 +605,9 @@ type N404 = GenericErrorMessage // N409 defines model for 409. type N409 = GenericErrorMessage +// N410 defines model for 410. +type N410 = GenericErrorMessage + // N422 defines model for 422. type N422 = GenericErrorMessage @@ -2838,6 +2841,8 @@ type N404JSONResponse GenericErrorMessage type N409JSONResponse GenericErrorMessage +type N410JSONResponse GenericErrorMessage + type N422JSONResponse GenericErrorMessage type N500JSONResponse GenericErrorMessage @@ -4404,6 +4409,15 @@ func (response GetQrFromStore404JSONResponse) VisitGetQrFromStoreResponse(w http return json.NewEncoder(w).Encode(response) } +type GetQrFromStore410JSONResponse struct{ N410JSONResponse } + +func (response GetQrFromStore410JSONResponse) VisitGetQrFromStoreResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(410) + + return json.NewEncoder(w).Encode(response) +} + type GetQrFromStore500JSONResponse struct{ N500JSONResponse } func (response GetQrFromStore500JSONResponse) VisitGetQrFromStoreResponse(w http.ResponseWriter) error { diff --git a/internal/api/qrcode.go b/internal/api/qrcode.go index e9a72c497..6f29f098c 100644 --- a/internal/api/qrcode.go +++ b/internal/api/qrcode.go @@ -29,6 +29,10 @@ func (s *Server) GetQrFromStore(ctx context.Context, request GetQrFromStoreReque } link, err := s.linkService.GetByID(ctx, *issuerDID, *request.Params.Id, s.cfg.ServerUrl) + if err := s.linkService.Validate(ctx, link); err != nil { + log.Error(ctx, "validating link", "err", err, "link id", *request.Params.Id) + return GetQrFromStore410JSONResponse{N410JSONResponse{err.Error()}}, nil + } if link.AuthorizationRequestMessage == nil { log.Error(ctx, "qr store. Finding qr", "err", err, "id", *request.Params.Id) diff --git a/internal/core/ports/link_service.go b/internal/core/ports/link_service.go index f6f0814e4..f17aff392 100644 --- a/internal/core/ports/link_service.go +++ b/internal/core/ports/link_service.go @@ -62,4 +62,5 @@ type LinkService interface { CreateQRCode(ctx context.Context, issuerDID w3c.DID, linkID uuid.UUID, serverURL string) (*CreateQRCodeResponse, error) IssueOrFetchClaim(ctx context.Context, issuerDID w3c.DID, userDID w3c.DID, linkID uuid.UUID, hostURL string) (*protocol.CredentialsOfferMessage, error) ProcessCallBack(ctx context.Context, issuerDID w3c.DID, message string, linkID uuid.UUID, hostURL string) (*protocol.CredentialsOfferMessage, error) + Validate(ctx context.Context, link *domain.Link) error } diff --git a/internal/core/services/link.go b/internal/core/services/link.go index 78a2469c2..ae799186e 100644 --- a/internal/core/services/link.go +++ b/internal/core/services/link.go @@ -187,7 +187,7 @@ func (ls *Link) CreateQRCode(ctx context.Context, issuerDID w3c.DID, linkID uuid return nil, err } - err = ls.validate(ctx, link) + err = ls.Validate(ctx, link) if err != nil { return nil, err } @@ -248,8 +248,8 @@ func (ls *Link) IssueOrFetchClaim(ctx context.Context, issuerDID w3c.DID, userDI return nil, err } - if err := ls.validate(ctx, link); err != nil { - log.Error(ctx, "cannot validate the link", "err", err) + if err := ls.Validate(ctx, link); err != nil { + log.Error(ctx, "cannot Validate the link", "err", err) return nil, err } @@ -373,7 +373,9 @@ func (ls *Link) ProcessCallBack(ctx context.Context, issuerID w3c.DID, message s return offer, nil } -func (ls *Link) validate(ctx context.Context, link *domain.Link) error { +// Validate - validate the link +// It checks if the link is active, not expired and has not exceeded the maximum number of claims +func (ls *Link) Validate(ctx context.Context, link *domain.Link) error { if link.ValidUntil != nil && time.Now().UTC().After(*link.ValidUntil) { log.Debug(ctx, "cannot issue a credential for an expired link") return ErrLinkAlreadyExpired