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

Commit

Permalink
Merge remote-tracking branch 'origin/main' into sip-3-implementation-…
Browse files Browse the repository at this point in the history
…of-signing-ose-101

* origin/main:
  Update mage spec (#117)
  get dids by method (#116)
  • Loading branch information
gabe committed Sep 29, 2022
2 parents a3696b7 + bacfbeb commit 6c04fa4
Show file tree
Hide file tree
Showing 10 changed files with 1,248 additions and 29 deletions.
1,071 changes: 1,049 additions & 22 deletions doc/swagger.yaml

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion magefile.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ func Spec() error {
logrus.Fatal(err)
return err
}
return sh.Run(swagCommand, "init", "-g", "cmd/main.go", "--pd", "-o", "docs", "-ot", "yaml")
return sh.Run(swagCommand, "init", "-g", "cmd/main.go", "--pd", "-o", "doc", "-ot", "yaml")
}

func runCITests(extraTestArgs ...string) error {
Expand Down
36 changes: 36 additions & 0 deletions pkg/server/router/did.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,3 +152,39 @@ func (dr DIDRouter) GetDIDByMethod(ctx context.Context, w http.ResponseWriter, _
resp := GetDIDByMethodResponse{DID: gotDID.DID}
return framework.Respond(ctx, w, resp, http.StatusOK)
}

type GetDIDsByMethodResponse struct {
DIDs []didsdk.DIDDocument `json:"dids,omitempty"`
}

// GetDIDsByMethod godoc
// @Summary Get DIDs
// @Description Get DIDs by method
// @Tags DecentralizedIdentityAPI
// @Accept json
// @Produce json
// @Param method path string true "Method"
// @Success 200 {object} GetDIDsByMethodResponse
// @Failure 400 {string} string "Bad request"
// @Router /v1/dids/{method} [get]
func (dr DIDRouter) GetDIDsByMethod(ctx context.Context, w http.ResponseWriter, _ *http.Request) error {
method := framework.GetParam(ctx, MethodParam)
if method == nil {
errMsg := "get DIDs by method request missing method parameter"
logrus.Error(errMsg)
return framework.NewRequestErrorMsg(errMsg, http.StatusBadRequest)
}

// TODO(gabe) check if the method is supported, to tell whether this is a bad req or internal error
// TODO(gabe) differentiate between internal errors and not found DIDs
getDIDsRequest := did.GetDIDsRequest{Method: did.Method(*method)}
gotDIDs, err := dr.service.GetDIDsByMethod(getDIDsRequest)
if err != nil {
errMsg := fmt.Sprintf("could not get DIDs for method: %s", *method)
logrus.WithError(err).Error(errMsg)
return framework.NewRequestError(errors.Wrap(err, errMsg), http.StatusBadRequest)
}

resp := GetDIDsByMethodResponse{DIDs: gotDIDs.DIDs}
return framework.Respond(ctx, w, resp, http.StatusOK)
}
21 changes: 21 additions & 0 deletions pkg/server/router/did_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,5 +79,26 @@ func TestDIDRouter(t *testing.T) {

// make sure it's the same value
assert.Equal(tt, createDIDResponse.DID.ID, getDIDResponse.DID.ID)

// create a second DID
createDIDResponse2, err := didService.CreateDIDByMethod(did.CreateDIDRequest{Method: did.KeyMethod, KeyType: crypto.Ed25519})
assert.NoError(tt, err)
assert.NotEmpty(tt, createDIDResponse2)

// get all DIDs back
getDIDsResponse, err := didService.GetDIDsByMethod(did.GetDIDsRequest{Method: did.KeyMethod})
assert.NoError(tt, err)
assert.NotEmpty(tt, getDIDsResponse)
assert.Len(tt, getDIDsResponse.DIDs, 2)

knownDIDs := map[string]bool{createDIDResponse.DID.ID: true, createDIDResponse2.DID.ID: true}
for _, did := range getDIDsResponse.DIDs {
if _, ok := knownDIDs[did.ID]; !ok {
tt.Error("got unknown DID")
} else {
delete(knownDIDs, did.ID)
}
}
assert.Len(tt, knownDIDs, 0)
})
}
1 change: 1 addition & 0 deletions pkg/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ func (s *SSIServer) DecentralizedIdentityAPI(service svcframework.Service) (err

s.Handle(http.MethodGet, handlerPath, didRouter.GetDIDMethods)
s.Handle(http.MethodPut, path.Join(handlerPath, "/:method"), didRouter.CreateDIDByMethod)
s.Handle(http.MethodGet, path.Join(handlerPath, "/:method"), didRouter.GetDIDsByMethod)
s.Handle(http.MethodGet, path.Join(handlerPath, "/:method/:id"), didRouter.GetDIDByMethod)
return
}
Expand Down
106 changes: 102 additions & 4 deletions pkg/server/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,21 +146,25 @@ func TestDIDAPI(t *testing.T) {
assert.Error(tt, err)
assert.Contains(tt, err.Error(), "invalid create DID request")

// reset recorder between calls
w.Flush()

// with body, bad key type
createDIDRequest := router.CreateDIDByMethodRequest{KeyType: "bad"}
requestReader := newRequestValue(tt, createDIDRequest)
req = httptest.NewRequest(http.MethodPut, "https://ssi-service.com/v1/dids/key", requestReader)
w = httptest.NewRecorder()

err = didService.CreateDIDByMethod(newRequestContextWithParams(params), w, req)
assert.Error(tt, err)
assert.Contains(tt, err.Error(), "could not create DID for method<key> with key type: bad")

// reset recorder between calls
w.Flush()

// with body, good key type
createDIDRequest = router.CreateDIDByMethodRequest{KeyType: crypto.Ed25519}
requestReader = newRequestValue(tt, createDIDRequest)
req = httptest.NewRequest(http.MethodPut, "https://ssi-service.com/v1/dids/key", requestReader)
w = httptest.NewRecorder()

err = didService.CreateDIDByMethod(newRequestContextWithParams(params), w, req)
assert.NoError(tt, err)
Expand Down Expand Up @@ -197,6 +201,9 @@ func TestDIDAPI(t *testing.T) {
assert.Error(tt, err)
assert.Contains(tt, err.Error(), "could not get DID for method<bad>")

// reset recorder between calls
w.Flush()

// good method, bad id
badParams1 := map[string]string{
"method": "key",
Expand All @@ -206,12 +213,13 @@ func TestDIDAPI(t *testing.T) {
assert.Error(tt, err)
assert.Contains(tt, err.Error(), "could not get DID for method<key> with id: worse")

// reset recorder between calls
w.Flush()
// store a DID
createDIDRequest := router.CreateDIDByMethodRequest{KeyType: crypto.Ed25519}
requestReader := newRequestValue(tt, createDIDRequest)
params := map[string]string{"method": "key"}
req = httptest.NewRequest(http.MethodPut, "https://ssi-service.com/v1/dids/key", requestReader)
w = httptest.NewRecorder()

err = didService.CreateDIDByMethod(newRequestContextWithParams(params), w, req)
assert.NoError(tt, err)
Expand All @@ -220,11 +228,13 @@ func TestDIDAPI(t *testing.T) {
err = json.NewDecoder(w.Body).Decode(&createdDID)
assert.NoError(tt, err)

// reset recorder between calls
w.Flush()

// get it back
createdID := createdDID.DID.ID
getDIDPath := fmt.Sprintf("https://ssi-service.com/v1/dids/key/%s", createdID)
req = httptest.NewRequest(http.MethodGet, getDIDPath, nil)
w = httptest.NewRecorder()

// good params
goodParams := map[string]string{
Expand All @@ -239,6 +249,94 @@ func TestDIDAPI(t *testing.T) {
assert.NoError(tt, err)
assert.Equal(tt, createdID, resp.DID.ID)
})

t.Run("Test Get DIDs By Method", func(tt *testing.T) {
bolt, err := storage.NewBoltDB()

// remove the db file after the test
tt.Cleanup(func() {
_ = bolt.Close()
_ = os.Remove(storage.DBFile)
})

_, keyStore := testKeyStore(tt, bolt)
didService := testDIDRouter(tt, bolt, keyStore)

// get DIDs by method
req := httptest.NewRequest(http.MethodGet, "https://ssi-service.com/v1/dids/bad", nil)
w := httptest.NewRecorder()

// bad params
badParams := map[string]string{
"method": "bad",
}
err = didService.GetDIDsByMethod(newRequestContextWithParams(badParams), w, req)
assert.Error(tt, err)
assert.Contains(tt, err.Error(), "could not get DIDs for method: bad")

// good method
goodParams := map[string]string{
"method": "key",
}
err = didService.GetDIDsByMethod(newRequestContextWithParams(goodParams), w, req)
assert.NoError(tt, err)
var gotDIDs router.GetDIDByMethodResponse
err = json.NewDecoder(w.Body).Decode(&gotDIDs)
assert.NoError(tt, err)
assert.Empty(tt, gotDIDs)

// reset recorder between calls
w.Flush()

// store two DIDs
createDIDRequest := router.CreateDIDByMethodRequest{KeyType: crypto.Ed25519}
requestReader := newRequestValue(tt, createDIDRequest)
params := map[string]string{"method": "key"}
req = httptest.NewRequest(http.MethodPut, "https://ssi-service.com/v1/dids/key", requestReader)

err = didService.CreateDIDByMethod(newRequestContextWithParams(params), w, req)
assert.NoError(tt, err)

var createdDID router.CreateDIDByMethodResponse
err = json.NewDecoder(w.Body).Decode(&createdDID)
assert.NoError(tt, err)

// reset recorder between calls
w.Flush()

requestReader = newRequestValue(tt, createDIDRequest)
req = httptest.NewRequest(http.MethodPut, "https://ssi-service.com/v1/dids/key", requestReader)

err = didService.CreateDIDByMethod(newRequestContextWithParams(params), w, req)
assert.NoError(tt, err)

var createdDID2 router.CreateDIDByMethodResponse
err = json.NewDecoder(w.Body).Decode(&createdDID2)
assert.NoError(tt, err)

// reset recorder between calls
w.Flush()

// get all dids for method

req = httptest.NewRequest(http.MethodGet, "https://ssi-service.com/v1/dids/key", requestReader)
err = didService.GetDIDsByMethod(newRequestContextWithParams(params), w, req)
assert.NoError(tt, err)

var gotDIDsResponse router.GetDIDsByMethodResponse
err = json.NewDecoder(w.Body).Decode(&gotDIDsResponse)
assert.NoError(tt, err)

knownDIDs := map[string]bool{createdDID.DID.ID: true, createdDID2.DID.ID: true}
for _, did := range gotDIDsResponse.DIDs {
if _, ok := knownDIDs[did.ID]; !ok {
tt.Error("got unknown DID")
} else {
delete(knownDIDs, did.ID)
}
}
assert.Len(tt, knownDIDs, 0)
})
}

func TestSchemaAPI(t *testing.T) {
Expand Down
11 changes: 11 additions & 0 deletions pkg/service/did/did.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ type Service struct {
type MethodHandler interface {
CreateDID(request CreateDIDRequest) (*CreateDIDResponse, error)
GetDID(request GetDIDRequest) (*GetDIDResponse, error)
GetDIDs(method Method) (*GetDIDsResponse, error)
}

func NewDIDService(config config.DIDServiceConfig, s storage.ServiceStorage, keyStore *keystore.Service) (*Service, error) {
Expand Down Expand Up @@ -116,6 +117,16 @@ func (s *Service) GetDIDByMethod(request GetDIDRequest) (*GetDIDResponse, error)
return handler.GetDID(request)
}

func (s *Service) GetDIDsByMethod(request GetDIDsRequest) (*GetDIDsResponse, error) {
method := request.Method
handler, err := s.getHandler(method)
if err != nil {
errMsg := fmt.Sprintf("could not get handler for method<%s>", method)
return nil, util.LoggingErrorMsg(err, errMsg)
}
return handler.GetDIDs(method)
}

func (s *Service) getHandler(method Method) (MethodHandler, error) {
handler, ok := s.handlers[method]
if !ok {
Expand Down
15 changes: 15 additions & 0 deletions pkg/service/did/key.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,21 @@ func (h *keyDIDHandler) GetDID(request GetDIDRequest) (*GetDIDResponse, error) {
return &GetDIDResponse{DID: gotDID.DID}, nil
}

func (h *keyDIDHandler) GetDIDs(method Method) (*GetDIDsResponse, error) {

logrus.Debugf("getting DIDs for method: %s", method)

gotDIDs, err := h.storage.GetDIDs(string(method))
if err != nil {
return nil, fmt.Errorf("error getting DIDs for method: %s", method)
}
var dids []did.DIDDocument
for _, did := range gotDIDs {
dids = append(dids, did.DID)
}
return &GetDIDsResponse{DIDs: dids}, nil
}

func privateKeyToBase58(privKey interface{}) (string, error) {
if haveBytes, ok := privKey.([]byte); ok {
return base58.Encode(haveBytes), nil
Expand Down
9 changes: 9 additions & 0 deletions pkg/service/did/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,12 @@ type GetDIDRequest struct {
type GetDIDResponse struct {
DID didsdk.DIDDocument `json:"did"`
}

type GetDIDsRequest struct {
Method Method `json:"method" validate:"required"`
}

// GetDIDsResponse is the JSON-serializable response for getting all DIDs for a given method
type GetDIDsResponse struct {
DIDs []didsdk.DIDDocument `json:"dids"`
}
5 changes: 3 additions & 2 deletions pkg/service/did/storage/bolt.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (

"github.com/goccy/go-json"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"

"github.com/tbd54566975/ssi-service/internal/util"
"github.com/tbd54566975/ssi-service/pkg/storage"
Expand Down Expand Up @@ -79,8 +80,8 @@ func (b BoltDIDStorage) GetDIDs(method string) ([]StoredDID, error) {
return nil, util.LoggingErrorMsg(err, couldNotGetDIDsErr)
}
if len(gotDIDs) == 0 {
err := fmt.Errorf("no DIDs found for method: %s", method)
return nil, util.LoggingErrorMsg(err, "could not get stored DIDs")
logrus.Infof("no DIDs found for method: %s", method)
return nil, nil
}
var stored []StoredDID
for _, didBytes := range gotDIDs {
Expand Down

0 comments on commit 6c04fa4

Please sign in to comment.