-
Notifications
You must be signed in to change notification settings - Fork 55
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support adding/removing services and keys to an ion DID #562
Changes from 3 commits
3a4fb90
e70388b
b36fce8
0b955f3
5311f6f
60821bd
8b48809
33f6710
fc53eaf
61a1a9e
2b5bd4f
39b7824
38c99f4
1b19f92
7a7b672
ac761e5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,6 +7,7 @@ import ( | |
|
||
"github.com/TBD54566975/ssi-sdk/crypto" | ||
didsdk "github.com/TBD54566975/ssi-sdk/did" | ||
"github.com/TBD54566975/ssi-sdk/did/ion" | ||
"github.com/TBD54566975/ssi-sdk/did/resolution" | ||
"github.com/gin-gonic/gin" | ||
"github.com/goccy/go-json" | ||
|
@@ -127,6 +128,100 @@ func (dr DIDRouter) CreateDIDByMethod(c *gin.Context) { | |
framework.Respond(c, resp, http.StatusCreated) | ||
} | ||
|
||
type StateChange struct { | ||
ServicesToAdd []didsdk.Service `json:"servicesToAdd,omitempty"` | ||
ServiceIDsToRemove []string `json:"serviceIdsToRemove,omitempty"` | ||
PublicKeysToAdd []ion.PublicKey `json:"publicKeysToAdd,omitempty"` | ||
PublicKeyIDsToRemove []string `json:"publicKeyIdsToRemove"` | ||
} | ||
|
||
type UpdateDIDByMethodRequest struct { | ||
// Expected to be populated when `method == "ion"`. Describes the changes that are requested. | ||
StateChange StateChange `json:"stateChange" validate:"required"` | ||
} | ||
|
||
type UpdateDIDByMethodResponse struct { | ||
DID didsdk.Document `json:"did,omitempty"` | ||
} | ||
|
||
// UpdateDIDByMethod godoc | ||
// | ||
// @Summary Updates a DID document. | ||
// @Description Updates a DID for which SSI is the custodian. The DID must have been previously created by calling | ||
// @Description the "Create DID Document" endpoint. Currently, only ION dids support updates. | ||
// @Tags DecentralizedIdentityAPI | ||
// @Accept json | ||
// @Produce json | ||
// @Param method path string true "Method" | ||
// @Param id path string true "ID" | ||
// @Param request body UpdateDIDByMethodRequest true "request body" | ||
// @Success 201 {object} UpdateDIDByMethodResponse | ||
// @Failure 400 {string} string "Bad request" | ||
// @Failure 500 {string} string "Internal server error" | ||
// @Router /v1/dids/{method}/{id} [put] | ||
func (dr DIDRouter) UpdateDIDByMethod(c *gin.Context) { | ||
method := framework.GetParam(c, MethodParam) | ||
if method == nil { | ||
errMsg := "update DID by method request missing method parameter" | ||
framework.LoggingRespondErrMsg(c, errMsg, http.StatusBadRequest) | ||
return | ||
} | ||
if *method != didsdk.IONMethod.String() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this logic is better suited for the service layer, though it is OK to duplicate it There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The service layer method is called The external facing API is open for evolution. The internal is specific so it's more clear and it's easier to maintain. |
||
framework.LoggingRespondErrMsg(c, "ion is the only method supported", http.StatusBadRequest) | ||
} | ||
|
||
id := framework.GetParam(c, IDParam) | ||
if id == nil { | ||
errMsg := fmt.Sprintf("update DID request missing id parameter for method: %s", *method) | ||
framework.LoggingRespondErrMsg(c, errMsg, http.StatusBadRequest) | ||
return | ||
} | ||
var request UpdateDIDByMethodRequest | ||
invalidRequest := "invalid update DID request" | ||
if err := framework.Decode(c.Request, &request); err != nil { | ||
framework.LoggingRespondErrWithMsg(c, err, invalidRequest, http.StatusBadRequest) | ||
return | ||
} | ||
|
||
if err := framework.ValidateRequest(request); err != nil { | ||
framework.LoggingRespondErrWithMsg(c, err, invalidRequest, http.StatusBadRequest) | ||
return | ||
} | ||
|
||
updateDIDRequest, err := toUpdateIONDIDRequest(*id, request) | ||
if err != nil { | ||
errMsg := fmt.Sprintf("%s: could not update DID for method<%s>", invalidRequest, *method) | ||
framework.LoggingRespondErrWithMsg(c, err, errMsg, http.StatusBadRequest) | ||
return | ||
} | ||
updateIONDIDResponse, err := dr.service.UpdateIONDID(c, *updateDIDRequest) | ||
if err != nil { | ||
errMsg := fmt.Sprintf("could not create DID for method<%s>", *method) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is this the right error message? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed |
||
framework.LoggingRespondErrWithMsg(c, err, errMsg, http.StatusInternalServerError) | ||
return | ||
} | ||
|
||
resp := CreateDIDByMethodResponse{DID: updateIONDIDResponse.DID} | ||
framework.Respond(c, resp, http.StatusCreated) | ||
|
||
} | ||
|
||
func toUpdateIONDIDRequest(id string, request UpdateDIDByMethodRequest) (*did.UpdateIONDIDRequest, error) { | ||
didION := ion.ION(id) | ||
if !didION.IsValid() { | ||
return nil, errors.Errorf("invalid ion did %s", id) | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. could check to see whether any of the updates are set to make sure it's not a no-op There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I added this validation to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sounds good |
||
return &did.UpdateIONDIDRequest{ | ||
DID: didION, | ||
StateChange: ion.StateChange{ | ||
ServicesToAdd: request.StateChange.ServicesToAdd, | ||
ServiceIDsToRemove: request.StateChange.ServiceIDsToRemove, | ||
PublicKeysToAdd: request.StateChange.PublicKeysToAdd, | ||
PublicKeyIDsToRemove: request.StateChange.PublicKeyIDsToRemove, | ||
}, | ||
}, nil | ||
} | ||
|
||
// toCreateDIDRequest converts CreateDIDByMethodRequest to did.CreateDIDRequest, parsing options according to method | ||
func toCreateDIDRequest(m didsdk.Method, request CreateDIDByMethodRequest) (*did.CreateDIDRequest, error) { | ||
createRequest := did.CreateDIDRequest{ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this works until we support update for other methods, then we'll probably want to reconsider this API
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree. Since we don't have other examples, I think this makes sense for now.