diff --git a/docs/_static/vdr/v2.yaml b/docs/_static/vdr/v2.yaml index 63fdb1aea1..1c8b694df8 100644 --- a/docs/_static/vdr/v2.yaml +++ b/docs/_static/vdr/v2.yaml @@ -12,16 +12,23 @@ paths: post: summary: Creates a new Web DID description: | - A new web DID is created. Only the DID is returned. The DID document can be retrieved using the DID resolution endpoint. + A new web DID and DID Document are created. A single key pair is generated and added to the DID document. The key pair is used for all verificationMethods. - No services are added. The PublicURL needs to be configured. + No services are added. If no ID is given, a random UUID is generated. error returns: - * 412 - PublicURL is not configured + * 400 - Returned in case of malformed DID in the request body * 500 - An error occurred while processing the request operationId: "createDID" tags: - DID + requestBody: + description: Options for the DID creation. + required: false + content: + application/json: + schema: + $ref: '#/components/schemas/CreateDIDOptions' responses: "200": description: "New DID has been created successfully. Returns the DID document." @@ -62,7 +69,7 @@ paths: default: $ref: '../common/error_response.yaml' delete: - summary: Deleted the web DID Document. + summary: Deletes a locally managed Document. description: | error returns: @@ -89,7 +96,7 @@ paths: post: summary: Adds a service to the DID document. description: | - It adds the given service to the DID Document. The ID will be generated and replaced. + It adds the given service to the DID Document. The ID will be generated when not given. error returns: * 400 - Returned in case of malformed DID or service @@ -107,7 +114,7 @@ paths: - DID responses: "200": - description: "New verification method has been created and added successfully. Returns the verification method." + description: "New service has been added successfully. Returns the service." content: application/json: schema: @@ -144,13 +151,13 @@ paths: operationId: deleteService responses: "204": - description: Verification Method was successfully deleted + description: The service was successfully deleted default: $ref: '../common/error_response.yaml' put: summary: Updates a service in the DID document. description: | - It updates the given service in the DID Document. The ID will remain the same. + It updates the given service in the DID Document. error returns: * 400 - Returned in case of malformed DID or service @@ -205,7 +212,7 @@ paths: $ref: '#/components/schemas/VerificationMethod' default: $ref: '../common/error_response.yaml' - /internal/vdr/v2/did/{did}/verificationmethod/{kid}: + /internal/vdr/v2/did/{did}/verificationmethod/{id}: parameters: - name: did in: path @@ -214,9 +221,9 @@ paths: example: did:web:example.com:iam:013c6fda-73e8-45ee-9220-48652dba854b schema: type: string - - name: kid + - name: id in: path - description: URL encoded kid identifying the verification method. + description: URL encoded ID identifying the verification method. required: true example: "did:web:example.com:iam:013c6fda-73e8-45ee-9220-48652dba854b#3106f751-59e3-440f-b57b-39a96a2da6c6" schema: @@ -225,8 +232,6 @@ paths: summary: Delete a specific verification method description: | Removes the verification method from the DID Document. - Revokes the public key with the corresponding key-id. - Note: Other verification methods with different key-ids with the same private key will still be valid. error returns: * 404 - Corresponding DID document or verification method could not be found @@ -241,6 +246,13 @@ paths: $ref: '../common/error_response.yaml' components: schemas: + CreateDIDOptions: + type: object + properties: + id: + type: string + description: The ID of the DID document. If not given, a random UUID is generated. + example: "did:web:example.com:iam:013c6fda-73e8-45ee-9220-48652dba854b" DIDDocument: $ref: '../common/ssi_types.yaml#/components/schemas/DIDDocument' DIDDocumentMetadata: diff --git a/e2e-tests/oauth-flow/rfc021/docker-compose.yml b/e2e-tests/oauth-flow/rfc021/docker-compose.yml index 4f62fcffad..1f7336d20b 100644 --- a/e2e-tests/oauth-flow/rfc021/docker-compose.yml +++ b/e2e-tests/oauth-flow/rfc021/docker-compose.yml @@ -1,7 +1,7 @@ version: "3.7" services: nodeA-backend: - image: "${IMAGE_NODE_A:-nutsfoundation/nuts-node:master}" + image: "${IMAGE_NODE_A:-nutsfoundation/nuts-node:latest}" ports: - "11323:1323" environment: @@ -25,7 +25,7 @@ services: - "../../tls-certs/truststore.pem:/etc/nginx/ssl/truststore.pem:ro" - "./node-A/html:/etc/nginx/html:ro" nodeB: - image: "${IMAGE_NODE_B:-nutsfoundation/nuts-node:master}" + image: "${IMAGE_NODE_B:-nutsfoundation/nuts-node:latest}" ports: - "21323:1323" environment: diff --git a/vdr/api/v2/generated.go b/vdr/api/v2/generated.go index ca2abd7af4..2b604cdd2f 100644 --- a/vdr/api/v2/generated.go +++ b/vdr/api/v2/generated.go @@ -4,6 +4,7 @@ package v2 import ( + "bytes" "context" "encoding/json" "fmt" @@ -21,6 +22,12 @@ const ( JwtBearerAuthScopes = "jwtBearerAuth.Scopes" ) +// CreateDIDOptions defines model for CreateDIDOptions. +type CreateDIDOptions struct { + // Id The ID of the DID document. If not given, a random UUID is generated. + Id *string `json:"id,omitempty"` +} + // DIDResolutionResult defines model for DIDResolutionResult. type DIDResolutionResult struct { // Document A DID document according to the W3C spec following the Nuts Method rules as defined in [Nuts RFC006] @@ -30,6 +37,9 @@ type DIDResolutionResult struct { DocumentMetadata DIDDocumentMetadata `json:"documentMetadata"` } +// CreateDIDJSONRequestBody defines body for CreateDID for application/json ContentType. +type CreateDIDJSONRequestBody = CreateDIDOptions + // RequestEditorFn is the function signature for the RequestEditor callback function type RequestEditorFn func(ctx context.Context, req *http.Request) error @@ -103,8 +113,10 @@ func WithRequestEditorFn(fn RequestEditorFn) ClientOption { // The interface specification for the client above. type ClientInterface interface { - // CreateDID request - CreateDID(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) + // CreateDIDWithBody request with any body + CreateDIDWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) + + CreateDID(ctx context.Context, body CreateDIDJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) // DeleteDID request DeleteDID(ctx context.Context, did string, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -125,11 +137,23 @@ type ClientInterface interface { AddVerificationMethod(ctx context.Context, did string, reqEditors ...RequestEditorFn) (*http.Response, error) // DeleteVerificationMethod request - DeleteVerificationMethod(ctx context.Context, did string, kid string, reqEditors ...RequestEditorFn) (*http.Response, error) + DeleteVerificationMethod(ctx context.Context, did string, id string, reqEditors ...RequestEditorFn) (*http.Response, error) } -func (c *Client) CreateDID(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewCreateDIDRequest(c.Server) +func (c *Client) CreateDIDWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewCreateDIDRequestWithBody(c.Server, contentType, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) CreateDID(ctx context.Context, body CreateDIDJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewCreateDIDRequest(c.Server, body) if err != nil { return nil, err } @@ -212,8 +236,8 @@ func (c *Client) AddVerificationMethod(ctx context.Context, did string, reqEdito return c.Client.Do(req) } -func (c *Client) DeleteVerificationMethod(ctx context.Context, did string, kid string, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewDeleteVerificationMethodRequest(c.Server, did, kid) +func (c *Client) DeleteVerificationMethod(ctx context.Context, did string, id string, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewDeleteVerificationMethodRequest(c.Server, did, id) if err != nil { return nil, err } @@ -224,8 +248,19 @@ func (c *Client) DeleteVerificationMethod(ctx context.Context, did string, kid s return c.Client.Do(req) } -// NewCreateDIDRequest generates requests for CreateDID -func NewCreateDIDRequest(server string) (*http.Request, error) { +// NewCreateDIDRequest calls the generic CreateDID builder with application/json body +func NewCreateDIDRequest(server string, body CreateDIDJSONRequestBody) (*http.Request, error) { + var bodyReader io.Reader + buf, err := json.Marshal(body) + if err != nil { + return nil, err + } + bodyReader = bytes.NewReader(buf) + return NewCreateDIDRequestWithBody(server, "application/json", bodyReader) +} + +// NewCreateDIDRequestWithBody generates requests for CreateDID with any type of body +func NewCreateDIDRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { var err error serverURL, err := url.Parse(server) @@ -243,11 +278,13 @@ func NewCreateDIDRequest(server string) (*http.Request, error) { return nil, err } - req, err := http.NewRequest("POST", queryURL.String(), nil) + req, err := http.NewRequest("POST", queryURL.String(), body) if err != nil { return nil, err } + req.Header.Add("Content-Type", contentType) + return req, nil } @@ -470,7 +507,7 @@ func NewAddVerificationMethodRequest(server string, did string) (*http.Request, } // NewDeleteVerificationMethodRequest generates requests for DeleteVerificationMethod -func NewDeleteVerificationMethodRequest(server string, did string, kid string) (*http.Request, error) { +func NewDeleteVerificationMethodRequest(server string, did string, id string) (*http.Request, error) { var err error var pathParam0 string @@ -482,7 +519,7 @@ func NewDeleteVerificationMethodRequest(server string, did string, kid string) ( var pathParam1 string - pathParam1, err = runtime.StyleParamWithLocation("simple", false, "kid", runtime.ParamLocationPath, kid) + pathParam1, err = runtime.StyleParamWithLocation("simple", false, "id", runtime.ParamLocationPath, id) if err != nil { return nil, err } @@ -553,8 +590,10 @@ func WithBaseURL(baseURL string) ClientOption { // ClientWithResponsesInterface is the interface specification for the client with responses above. type ClientWithResponsesInterface interface { - // CreateDIDWithResponse request - CreateDIDWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*CreateDIDResponse, error) + // CreateDIDWithBodyWithResponse request with any body + CreateDIDWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*CreateDIDResponse, error) + + CreateDIDWithResponse(ctx context.Context, body CreateDIDJSONRequestBody, reqEditors ...RequestEditorFn) (*CreateDIDResponse, error) // DeleteDIDWithResponse request DeleteDIDWithResponse(ctx context.Context, did string, reqEditors ...RequestEditorFn) (*DeleteDIDResponse, error) @@ -575,7 +614,7 @@ type ClientWithResponsesInterface interface { AddVerificationMethodWithResponse(ctx context.Context, did string, reqEditors ...RequestEditorFn) (*AddVerificationMethodResponse, error) // DeleteVerificationMethodWithResponse request - DeleteVerificationMethodWithResponse(ctx context.Context, did string, kid string, reqEditors ...RequestEditorFn) (*DeleteVerificationMethodResponse, error) + DeleteVerificationMethodWithResponse(ctx context.Context, did string, id string, reqEditors ...RequestEditorFn) (*DeleteVerificationMethodResponse, error) } type CreateDIDResponse struct { @@ -831,9 +870,17 @@ func (r DeleteVerificationMethodResponse) StatusCode() int { return 0 } -// CreateDIDWithResponse request returning *CreateDIDResponse -func (c *ClientWithResponses) CreateDIDWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*CreateDIDResponse, error) { - rsp, err := c.CreateDID(ctx, reqEditors...) +// CreateDIDWithBodyWithResponse request with arbitrary body returning *CreateDIDResponse +func (c *ClientWithResponses) CreateDIDWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*CreateDIDResponse, error) { + rsp, err := c.CreateDIDWithBody(ctx, contentType, body, reqEditors...) + if err != nil { + return nil, err + } + return ParseCreateDIDResponse(rsp) +} + +func (c *ClientWithResponses) CreateDIDWithResponse(ctx context.Context, body CreateDIDJSONRequestBody, reqEditors ...RequestEditorFn) (*CreateDIDResponse, error) { + rsp, err := c.CreateDID(ctx, body, reqEditors...) if err != nil { return nil, err } @@ -895,8 +942,8 @@ func (c *ClientWithResponses) AddVerificationMethodWithResponse(ctx context.Cont } // DeleteVerificationMethodWithResponse request returning *DeleteVerificationMethodResponse -func (c *ClientWithResponses) DeleteVerificationMethodWithResponse(ctx context.Context, did string, kid string, reqEditors ...RequestEditorFn) (*DeleteVerificationMethodResponse, error) { - rsp, err := c.DeleteVerificationMethod(ctx, did, kid, reqEditors...) +func (c *ClientWithResponses) DeleteVerificationMethodWithResponse(ctx context.Context, did string, id string, reqEditors ...RequestEditorFn) (*DeleteVerificationMethodResponse, error) { + rsp, err := c.DeleteVerificationMethod(ctx, did, id, reqEditors...) if err != nil { return nil, err } @@ -1223,7 +1270,7 @@ type ServerInterface interface { // Creates a new Web DID // (POST /internal/vdr/v2/did) CreateDID(ctx echo.Context) error - // Deleted the web DID Document. + // Deletes a locally managed Document. // (DELETE /internal/vdr/v2/did/{did}) DeleteDID(ctx echo.Context, did string) error // Resolves a DID document @@ -1242,8 +1289,8 @@ type ServerInterface interface { // (POST /internal/vdr/v2/did/{did}/verificationmethod) AddVerificationMethod(ctx echo.Context, did string) error // Delete a specific verification method - // (DELETE /internal/vdr/v2/did/{did}/verificationmethod/{kid}) - DeleteVerificationMethod(ctx echo.Context, did string, kid string) error + // (DELETE /internal/vdr/v2/did/{did}/verificationmethod/{id}) + DeleteVerificationMethod(ctx echo.Context, did string, id string) error } // ServerInterfaceWrapper converts echo contexts to parameters. @@ -1397,18 +1444,18 @@ func (w *ServerInterfaceWrapper) DeleteVerificationMethod(ctx echo.Context) erro return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter did: %s", err)) } - // ------------- Path parameter "kid" ------------- - var kid string + // ------------- Path parameter "id" ------------- + var id string - err = runtime.BindStyledParameterWithLocation("simple", false, "kid", runtime.ParamLocationPath, ctx.Param("kid"), &kid) + err = runtime.BindStyledParameterWithLocation("simple", false, "id", runtime.ParamLocationPath, ctx.Param("id"), &id) if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter kid: %s", err)) + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter id: %s", err)) } ctx.Set(JwtBearerAuthScopes, []string{}) // Invoke the callback with all the unmarshaled arguments - err = w.Handler.DeleteVerificationMethod(ctx, did, kid) + err = w.Handler.DeleteVerificationMethod(ctx, did, id) return err } @@ -1447,11 +1494,12 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL router.DELETE(baseURL+"/internal/vdr/v2/did/:did/service/:id", wrapper.DeleteService) router.PUT(baseURL+"/internal/vdr/v2/did/:did/service/:id", wrapper.UpdateService) router.POST(baseURL+"/internal/vdr/v2/did/:did/verificationmethod", wrapper.AddVerificationMethod) - router.DELETE(baseURL+"/internal/vdr/v2/did/:did/verificationmethod/:kid", wrapper.DeleteVerificationMethod) + router.DELETE(baseURL+"/internal/vdr/v2/did/:did/verificationmethod/:id", wrapper.DeleteVerificationMethod) } type CreateDIDRequestObject struct { + Body *CreateDIDJSONRequestBody } type CreateDIDResponseObject interface { @@ -1718,7 +1766,7 @@ func (response AddVerificationMethoddefaultApplicationProblemPlusJSONResponse) V type DeleteVerificationMethodRequestObject struct { Did string `json:"did"` - Kid string `json:"kid"` + Id string `json:"id"` } type DeleteVerificationMethodResponseObject interface { @@ -1759,7 +1807,7 @@ type StrictServerInterface interface { // Creates a new Web DID // (POST /internal/vdr/v2/did) CreateDID(ctx context.Context, request CreateDIDRequestObject) (CreateDIDResponseObject, error) - // Deleted the web DID Document. + // Deletes a locally managed Document. // (DELETE /internal/vdr/v2/did/{did}) DeleteDID(ctx context.Context, request DeleteDIDRequestObject) (DeleteDIDResponseObject, error) // Resolves a DID document @@ -1778,7 +1826,7 @@ type StrictServerInterface interface { // (POST /internal/vdr/v2/did/{did}/verificationmethod) AddVerificationMethod(ctx context.Context, request AddVerificationMethodRequestObject) (AddVerificationMethodResponseObject, error) // Delete a specific verification method - // (DELETE /internal/vdr/v2/did/{did}/verificationmethod/{kid}) + // (DELETE /internal/vdr/v2/did/{did}/verificationmethod/{id}) DeleteVerificationMethod(ctx context.Context, request DeleteVerificationMethodRequestObject) (DeleteVerificationMethodResponseObject, error) } @@ -1798,6 +1846,12 @@ type strictHandler struct { func (sh *strictHandler) CreateDID(ctx echo.Context) error { var request CreateDIDRequestObject + var body CreateDIDJSONRequestBody + if err := ctx.Bind(&body); err != nil { + return err + } + request.Body = &body + handler := func(ctx echo.Context, request interface{}) (interface{}, error) { return sh.ssi.CreateDID(ctx.Request().Context(), request.(CreateDIDRequestObject)) } @@ -1970,11 +2024,11 @@ func (sh *strictHandler) AddVerificationMethod(ctx echo.Context, did string) err } // DeleteVerificationMethod operation middleware -func (sh *strictHandler) DeleteVerificationMethod(ctx echo.Context, did string, kid string) error { +func (sh *strictHandler) DeleteVerificationMethod(ctx echo.Context, did string, id string) error { var request DeleteVerificationMethodRequestObject request.Did = did - request.Kid = kid + request.Id = id handler := func(ctx echo.Context, request interface{}) (interface{}, error) { return sh.ssi.DeleteVerificationMethod(ctx.Request().Context(), request.(DeleteVerificationMethodRequestObject))