From 6483969927adb71736b8d4ed7553f8c2988973ce Mon Sep 17 00:00:00 2001 From: Filip Bugarski Date: Wed, 12 Jan 2022 13:24:51 +0100 Subject: [PATCH] MF-1535 - Add API keys functions to SDK (#1536) * Add API keys to sdk. Signed-off-by: Filip Bugarski * Add issue key Signed-off-by: Filip Bugarski * Fix typo Signed-off-by: Filip Bugarski * Fix comments Signed-off-by: Filip Bugarski * Remove unused code Signed-off-by: Filip Bugarski * Fix typo Signed-off-by: Filip Bugarski --- pkg/sdk/go/keys.go | 98 +++++++++++++++++++++++++++++++++++++++++ pkg/sdk/go/responses.go | 47 +++++++++++++++++++- pkg/sdk/go/sdk.go | 21 ++++++++- 3 files changed, 164 insertions(+), 2 deletions(-) create mode 100644 pkg/sdk/go/keys.go diff --git a/pkg/sdk/go/keys.go b/pkg/sdk/go/keys.go new file mode 100644 index 00000000..9b8cf389 --- /dev/null +++ b/pkg/sdk/go/keys.go @@ -0,0 +1,98 @@ +package sdk + +import ( + "bytes" + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + + "github.com/mainflux/mainflux/pkg/errors" +) + +const keysEndpoint = "keys" + +func (sdk mfSDK) Issue(token string, k Key) (issueKeyRes, error) { + data, err := json.Marshal(k) + if err != nil { + return issueKeyRes{}, err + } + + url := fmt.Sprintf("%s/%s", sdk.authURL, keysEndpoint) + + req, err := http.NewRequest(http.MethodPost, url, bytes.NewReader(data)) + if err != nil { + return issueKeyRes{}, err + } + + resp, err := sdk.sendRequest(req, token, string(CTJSON)) + if err != nil { + return issueKeyRes{}, err + } + defer resp.Body.Close() + + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return issueKeyRes{}, err + } + + if resp.StatusCode != http.StatusCreated { + return issueKeyRes{}, errors.Wrap(ErrFailedCreation, errors.New(resp.Status)) + } + + var key issueKeyRes + if err := json.Unmarshal(body, &key); err != nil { + return issueKeyRes{}, err + } + + return key, nil +} + +func (sdk mfSDK) Revoke(id, token string) error { + url := fmt.Sprintf("%s/%s/%s", sdk.authURL, keysEndpoint, id) + req, err := http.NewRequest(http.MethodDelete, url, nil) + if err != nil { + return err + } + + resp, err := sdk.sendRequest(req, token, string(CTJSON)) + if err != nil { + return err + } + + if resp.StatusCode != http.StatusNoContent { + return errors.Wrap(ErrFailedRemoval, errors.New(resp.Status)) + } + + return nil +} + +func (sdk mfSDK) RetrieveKey(id, token string) (retrieveKeyRes, error) { + url := fmt.Sprintf("%s/%s/%s", sdk.authURL, keysEndpoint, id) + req, err := http.NewRequest(http.MethodGet, url, nil) + if err != nil { + return retrieveKeyRes{}, err + } + + resp, err := sdk.sendRequest(req, token, string(CTJSON)) + if err != nil { + return retrieveKeyRes{}, err + } + defer resp.Body.Close() + + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return retrieveKeyRes{}, err + } + + if resp.StatusCode != http.StatusOK { + return retrieveKeyRes{}, errors.Wrap(ErrFailedFetch, errors.New(resp.Status)) + } + + var key retrieveKeyRes + if err := json.Unmarshal(body, &key); err != nil { + return retrieveKeyRes{}, err + } + + return key, nil +} diff --git a/pkg/sdk/go/responses.go b/pkg/sdk/go/responses.go index 4aff0cde..9fd6eafa 100644 --- a/pkg/sdk/go/responses.go +++ b/pkg/sdk/go/responses.go @@ -3,7 +3,12 @@ package sdk -import "github.com/mainflux/mainflux/pkg/transformers/senml" +import ( + "net/http" + "time" + + "github.com/mainflux/mainflux/pkg/transformers/senml" +) type tokenRes struct { Token string `json:"token,omitempty"` @@ -55,3 +60,43 @@ type MembersPage struct { Members []Member `json:"members"` pageRes } + +type issueKeyRes struct { + ID string `json:"id,omitempty"` + Value string `json:"value,omitempty"` + IssuedAt time.Time `json:"issued_at,omitempty"` + ExpiresAt *time.Time `json:"expires_at,omitempty"` +} + +func (res issueKeyRes) Code() int { + return http.StatusCreated +} + +func (res issueKeyRes) Headers() map[string]string { + return map[string]string{} +} + +func (res issueKeyRes) Empty() bool { + return res.Value == "" +} + +type retrieveKeyRes struct { + ID string `json:"id,omitempty"` + IssuerID string `json:"issuer_id,omitempty"` + Subject string `json:"subject,omitempty"` + Type uint32 `json:"type,omitempty"` + IssuedAt time.Time `json:"issued_at,omitempty"` + ExpiresAt *time.Time `json:"expires_at,omitempty"` +} + +func (res retrieveKeyRes) Code() int { + return http.StatusOK +} + +func (res retrieveKeyRes) Headers() map[string]string { + return map[string]string{} +} + +func (res retrieveKeyRes) Empty() bool { + return false +} diff --git a/pkg/sdk/go/sdk.go b/pkg/sdk/go/sdk.go index c1a5a2ac..3175753e 100644 --- a/pkg/sdk/go/sdk.go +++ b/pkg/sdk/go/sdk.go @@ -7,6 +7,7 @@ import ( "crypto/tls" "errors" "net/http" + "time" ) const ( @@ -109,12 +110,21 @@ type Channel struct { Metadata map[string]interface{} `json:"metadata,omitempty"` } -//Member represents mainflux member. +// Member represents group member. type Member struct { ID string Type string } +type Key struct { + ID string + Type uint32 + IssuerID string + Subject string + IssuedAt time.Time + ExpiresAt time.Time +} + // SDK contains Mainflux API. type SDK interface { // CreateUser registers mainflux user. @@ -256,6 +266,15 @@ type SDK interface { // RevokeCert revokes certificate with certID for thing with thingID RevokeCert(thingID, certID, token string) error + + // Issue issues a new key, returning its token value alongside. + Issue(token string, key Key) (issueKeyRes, error) + + // Revoke removes the key with the provided ID that is issued by the user identified by the provided key. + Revoke(token, id string) error + + // RetrieveKey retrieves data for the key identified by the provided ID, that is issued by the user identified by the provided key. + RetrieveKey(token, id string) (retrieveKeyRes, error) } type mfSDK struct {