Skip to content
This repository has been archived by the owner on Dec 12, 2024. It is now read-only.

Commit

Permalink
Added List presentation requests method (#504)
Browse files Browse the repository at this point in the history
  • Loading branch information
andresuribe87 authored Jun 1, 2023
1 parent 1194ecb commit b72eff6
Show file tree
Hide file tree
Showing 9 changed files with 147 additions and 14 deletions.
2 changes: 1 addition & 1 deletion doc/docs.go

Large diffs are not rendered by default.

26 changes: 26 additions & 0 deletions doc/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1467,6 +1467,14 @@ definitions:
$ref: '#/definitions/pkg_server_router.Operation'
type: array
type: object
pkg_server_router.ListPresentationRequestsResponse:
properties:
presentationRequests:
description: The presentation requests matching the query.
items:
$ref: '#/definitions/github_com_tbd54566975_ssi-service_pkg_service_presentation_model.Request'
type: array
type: object
pkg_server_router.ListResponsesResponse:
properties:
responses:
Expand Down Expand Up @@ -3121,6 +3129,24 @@ paths:
tags:
- PresentationDefinitionAPI
/v1/presentations/requests:
get:
consumes:
- application/json
description: Lists all the existing presentation requests
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/pkg_server_router.ListPresentationRequestsResponse'
"500":
description: Internal server error
schema:
type: string
summary: List Presentation Requests
tags:
- PresentationRequestAPI
put:
consumes:
- application/json
Expand Down
29 changes: 29 additions & 0 deletions pkg/server/router/presentation.go
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,35 @@ func (pr PresentationRouter) GetRequest(c *gin.Context) {
framework.Respond(c, GetRequestResponse{Request: request}, http.StatusOK)
}

type ListPresentationRequestsResponse struct {
// The presentation requests matching the query.
Requests []model.Request `json:"presentationRequests"`
}

// ListRequests godoc
//
// @Summary List Presentation Requests
// @Description Lists all the existing presentation requests
// @Tags PresentationRequestAPI
// @Accept json
// @Produce json
// @Success 200 {object} ListPresentationRequestsResponse
// @Failure 500 {string} string "Internal server error"
// @Router /v1/presentations/requests [get]
func (pr PresentationRouter) ListRequests(c *gin.Context) {
svcResponse, err := pr.service.ListRequests(c)

if err != nil {
errMsg := "could not get requests"
framework.LoggingRespondErrWithMsg(c, err, errMsg, http.StatusInternalServerError)
return
}
resp := ListPresentationRequestsResponse{
Requests: svcResponse.PresentationRequests,
}
framework.Respond(c, resp, http.StatusOK)
}

// DeleteRequest godoc
//
// @Summary Delete PresentationRequest
Expand Down
2 changes: 1 addition & 1 deletion pkg/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ func PresentationAPI(rg *gin.RouterGroup, service svcframework.Service, webhookS
presReqAPI := rg.Group(PresentationsPrefix + RequestsPrefix)
presReqAPI.PUT("", presRouter.CreateRequest)
presReqAPI.GET("/:id", presRouter.GetRequest)
// TODO add list requests endpoint https://github.com/TBD54566975/ssi-service/issues/479
presReqAPI.GET("", presRouter.ListRequests)
presReqAPI.PUT("/:id", presRouter.DeleteRequest)

presSubAPI := rg.Group(PresentationsPrefix + SubmissionsPrefix)
Expand Down
62 changes: 60 additions & 2 deletions pkg/server/server_presentation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,45 @@ func TestPresentationAPI(t *testing.T) {
}
})

t.Run("List returns empty", func(tt *testing.T) {
t.Run("List presentation requests returns empty", func(tt *testing.T) {
s := setupTestDB(tt)
pRouter, _ := setupPresentationRouter(tt, s)

req := httptest.NewRequest(http.MethodGet, "https://ssi-service.com/v1/presentations/requests", nil)
w := httptest.NewRecorder()
c := newRequestContext(w, req)
pRouter.ListRequests(c)
assert.True(tt, util.Is2xxResponse(w.Code))

var resp router.ListPresentationRequestsResponse
assert.NoError(tt, json.NewDecoder(w.Body).Decode(&resp))
assert.Empty(tt, resp.Requests)
})

t.Run("List presentation requests returns many requests", func(tt *testing.T) {
s := setupTestDB(tt)
pRouter, didService := setupPresentationRouter(tt, s)
issuerDID := createDID(tt, didService)
def := createPresentationDefinition(tt, pRouter)
req1 := createPresentationRequest(tt, pRouter, def.PresentationDefinition.ID, issuerDID.DID)
req2 := createPresentationRequest(tt, pRouter, def.PresentationDefinition.ID, issuerDID.DID)

req := httptest.NewRequest(http.MethodGet, "https://ssi-service.com/v1/presentations/requests", nil)
w := httptest.NewRecorder()
c := newRequestContext(w, req)
pRouter.ListRequests(c)
assert.True(tt, util.Is2xxResponse(w.Code))

var resp router.ListPresentationRequestsResponse
assert.NoError(tt, json.NewDecoder(w.Body).Decode(&resp))
assert.Len(tt, resp.Requests, 2)
assert.ElementsMatch(tt, resp.Requests, []model.Request{
*req1.Request,
*req2.Request,
})
})

t.Run("List definitions returns empty", func(tt *testing.T) {
s := setupTestDB(tt)
pRouter, _ := setupPresentationRouter(tt, s)

Expand All @@ -129,7 +167,7 @@ func TestPresentationAPI(t *testing.T) {
assert.Empty(tt, resp.Definitions)
})

t.Run("List returns many definitions", func(tt *testing.T) {
t.Run("List definitions returns many definitions", func(tt *testing.T) {
s := setupTestDB(tt)
pRouter, _ := setupPresentationRouter(tt, s)
def1 := createPresentationDefinition(tt, pRouter)
Expand Down Expand Up @@ -517,6 +555,26 @@ func TestPresentationAPI(t *testing.T) {

}

func createPresentationRequest(t *testing.T, pRouter *router.PresentationRouter, definitionID string, issuerDID didsdk.Document) router.CreateRequestResponse {
request := router.CreateRequestRequest{
CommonCreateRequestRequest: &router.CommonCreateRequestRequest{
IssuerDID: issuerDID.ID,
IssuerKID: issuerDID.VerificationMethod[0].ID,
},
PresentationDefinitionID: definitionID,
}
value := newRequestValue(t, request)
req := httptest.NewRequest(http.MethodPut, "https://ssi-service.com/v1/presentations/requests", value)
w := httptest.NewRecorder()
c := newRequestContext(w, req)
pRouter.CreateRequest(c)
require.True(t, util.Is2xxResponse(w.Code))

var resp router.CreateRequestResponse
require.NoError(t, json.NewDecoder(w.Body).Decode(&resp))
return resp
}

func setupPresentationRouter(t *testing.T, s storage.ServiceStorage) (*router.PresentationRouter, *did.Service) {
keyStoreService := testKeyStoreService(t, s)
didService := testDIDService(t, s, keyStoreService)
Expand Down
4 changes: 4 additions & 0 deletions pkg/service/presentation/model/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,10 @@ type GetRequestResponse struct {
PresentationRequest Request `json:"presentationRequest"`
}

type ListRequestsResponse struct {
PresentationRequests []Request `json:"presentationRequests"`
}

type DeleteRequestRequest struct {
ID string `json:"id" validate:"required"`
}
Expand Down
28 changes: 25 additions & 3 deletions pkg/service/presentation/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ import (
"github.com/tbd54566975/ssi-service/pkg/storage"
)

const presentationRequestNamespace = "presentation_request"

type Service struct {
storage presentationstorage.Storage
keystore *keystore.Service
Expand All @@ -35,6 +37,7 @@ type Service struct {
resolver resolution.Resolver
schema *schema.Service
verifier *credential.Verifier
reqStorage common.RequestStorage
}

func (s Service) Type() framework.Type {
Expand Down Expand Up @@ -73,6 +76,7 @@ func NewPresentationService(config config.PresentationServiceConfig, s storage.S
if err != nil {
return nil, sdkutil.LoggingErrorMsg(err, "could not instantiate verifier")
}
requestStorage := common.NewRequestStorage(s, presentationRequestNamespace)
service := Service{
storage: presentationStorage,
keystore: keystore,
Expand All @@ -81,6 +85,7 @@ func NewPresentationService(config config.PresentationServiceConfig, s storage.S
resolver: resolver,
schema: schema,
verifier: verifier,
reqStorage: requestStorage,
}
if !service.Status().IsReady() {
return nil, errors.New(service.Status().Message)
Expand Down Expand Up @@ -132,6 +137,23 @@ func (s Service) GetPresentationDefinition(ctx context.Context,
}, nil
}

func (s Service) ListRequests(ctx context.Context) (*model.ListRequestsResponse, error) {
requests, err := s.reqStorage.ListRequests(ctx)
if err != nil {
return nil, errors.Wrap(err, "listing from storage")
}
reqs := make([]model.Request, 0, len(requests))
for _, storedReq := range requests {
storedReq := storedReq
r, err := serviceModel(&storedReq)
if err != nil {
return nil, err
}
reqs = append(reqs, *r)
}
return &model.ListRequestsResponse{PresentationRequests: reqs}, nil
}

func (s Service) DeletePresentationDefinition(ctx context.Context, request model.DeletePresentationDefinitionRequest) error {
logrus.Debugf("deleting presentation definition: %s", request.ID)

Expand Down Expand Up @@ -319,7 +341,7 @@ func (s Service) CreateRequest(ctx context.Context, req model.CreateRequestReque
if err != nil {
return nil, errors.Wrap(err, "creating stored request")
}
if err := s.storage.StoreRequest(ctx, *stored); err != nil {
if err := s.reqStorage.StoreRequest(ctx, *stored); err != nil {
return nil, errors.Wrap(err, "storing signed document")
}
return serviceModel(stored)
Expand All @@ -328,7 +350,7 @@ func (s Service) CreateRequest(ctx context.Context, req model.CreateRequestReque
func (s Service) GetRequest(ctx context.Context, request *model.GetRequestRequest) (*model.Request, error) {
logrus.Debugf("getting presentation request: %s", request.ID)

storedRequest, err := s.storage.GetRequest(ctx, request.ID)
storedRequest, err := s.reqStorage.GetRequest(ctx, request.ID)
if err != nil {
return nil, errors.Wrapf(err, "getting signed document with id: %s", request.ID)
}
Expand All @@ -342,7 +364,7 @@ func (s Service) GetRequest(ctx context.Context, request *model.GetRequestReques
func (s Service) DeleteRequest(ctx context.Context, request model.DeleteRequestRequest) error {
logrus.Debugf("deleting presentation request: %s", request.ID)

if err := s.storage.DeleteRequest(ctx, request.ID); err != nil {
if err := s.reqStorage.DeleteRequest(ctx, request.ID); err != nil {
return sdkutil.LoggingNewErrorf("could not delete presentation request with id: %s", request.ID)
}

Expand Down
6 changes: 1 addition & 5 deletions pkg/service/presentation/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ import (
"github.com/sirupsen/logrus"
"go.einride.tech/aip/filtering"

"github.com/tbd54566975/ssi-service/pkg/service/common"

opstorage "github.com/tbd54566975/ssi-service/pkg/service/operation/storage"
"github.com/tbd54566975/ssi-service/pkg/service/operation/storage/namespace"
opsubmission "github.com/tbd54566975/ssi-service/pkg/service/operation/submission"
Expand All @@ -22,12 +20,10 @@ import (

const (
presentationDefinitionNamespace = "presentation_definition"
presentationRequestNamespace = "presentation_request"
)

type Storage struct {
db storage.ServiceStorage
common.RequestStorage
}

func (ps *Storage) UpdateSubmission(ctx context.Context, id string, approved bool, reason string, opID string) (prestorage.StoredSubmission, opstorage.StoredOperation, error) {
Expand Down Expand Up @@ -98,7 +94,7 @@ func NewPresentationStorage(db storage.ServiceStorage) (prestorage.Storage, erro
if db == nil {
return nil, errors.New("db reference is nil")
}
return &Storage{db: db, RequestStorage: common.NewRequestStorage(db, presentationRequestNamespace)}, nil
return &Storage{db: db}, nil
}

func (ps *Storage) StoreDefinition(ctx context.Context, presentation prestorage.StoredDefinition) error {
Expand Down
2 changes: 0 additions & 2 deletions pkg/service/presentation/storage/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"github.com/TBD54566975/ssi-sdk/credential"
"github.com/TBD54566975/ssi-sdk/credential/exchange"
"github.com/pkg/errors"
"github.com/tbd54566975/ssi-service/pkg/service/common"
opstorage "github.com/tbd54566975/ssi-service/pkg/service/operation/storage"
"github.com/tbd54566975/ssi-service/pkg/service/operation/submission"
"go.einride.tech/aip/filtering"
Expand All @@ -21,7 +20,6 @@ type StoredDefinition struct {

type Storage interface {
DefinitionStorage
common.RequestStorage
SubmissionStorage
}

Expand Down

0 comments on commit b72eff6

Please sign in to comment.