mirror of
https://github.com/mainflux/mainflux.git
synced 2025-04-26 13:48:53 +08:00
NOISSUE - Add API keys functions to CLI (#1537)
* Add API keys to cli Signed-off-by: Filip Bugarski <filipbugarski@gmail.com> * Fix typo Signed-off-by: Filip Bugarski <filipbugarski@gmail.com> * Fix issue func, and sdk Signed-off-by: Filip Bugarski <filipbugarski@gmail.com> * Remove email, hide type and fix name Signed-off-by: Filip Bugarski <filipbugarski@gmail.com> * Remove type and add README Signed-off-by: Filip Bugarski <filipbugarski@gmail.com> * Fix issue response Signed-off-by: Filip Bugarski <filipbugarski@gmail.com> * Fix magic number and move struct to private Signed-off-by: Filip Bugarski <filipbugarski@gmail.com> * Remove const and import auth Signed-off-by: Filip Bugarski <filipbugarski@gmail.com> * Removing auth Signed-off-by: Filip Bugarski <filipbugarski@gmail.com> Co-authored-by: Dušan Borovčanin <dusan.borovcanin@mainflux.com>
This commit is contained in:
parent
81b2a1a2d3
commit
4f56986c8e
@ -240,3 +240,17 @@ mainflux-cli groups members <group_id> <user_auth_token>
|
||||
```bash
|
||||
mainflux-cli groups membership <user_id> <user_auth_token>
|
||||
```
|
||||
|
||||
### Keys management
|
||||
#### Issue a new Key
|
||||
```bash
|
||||
mainflux-cli keys issue <duration> <user_auth_token>
|
||||
```
|
||||
#### Remove API key from database
|
||||
```bash
|
||||
mainflux-cli keys revoke <key_id> <user_auth_token>
|
||||
```
|
||||
#### Retrieve API key with given id
|
||||
```bash
|
||||
mainflux-cli keys retrieve <key_id> <user_auth_token>
|
||||
```
|
||||
|
93
cli/keys.go
Normal file
93
cli/keys.go
Normal file
@ -0,0 +1,93 @@
|
||||
// Copyright (c) Mainflux
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package cli
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var cmdAPIKeys = []cobra.Command{
|
||||
{
|
||||
Use: "issue",
|
||||
Short: "issue <duration> <user_auth_token>",
|
||||
Long: `Issues a new Key`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if len(args) != 2 {
|
||||
logUsage(cmd.Short)
|
||||
return
|
||||
}
|
||||
|
||||
d, err := time.ParseDuration(args[0])
|
||||
if err != nil {
|
||||
logError(err)
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := sdk.Issue(args[1], d)
|
||||
if err != nil {
|
||||
logError(err)
|
||||
return
|
||||
}
|
||||
|
||||
logJSON(resp)
|
||||
},
|
||||
},
|
||||
{
|
||||
Use: "revoke",
|
||||
Short: "revoke <key_id> <user_auth_token>",
|
||||
Long: `Removes API key from database`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if len(args) != 2 {
|
||||
logUsage(cmd.Short)
|
||||
return
|
||||
}
|
||||
|
||||
if err := sdk.Revoke(args[0], args[1]); err != nil {
|
||||
logError(err)
|
||||
return
|
||||
}
|
||||
|
||||
logOK()
|
||||
},
|
||||
},
|
||||
{
|
||||
Use: "retrieve",
|
||||
Short: "retrieve <key_id> <user_auth_token>",
|
||||
Long: `Retrieves API key with given id`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if len(args) != 2 {
|
||||
logUsage(cmd.Short)
|
||||
return
|
||||
}
|
||||
|
||||
rk, err := sdk.RetrieveKey(args[0], args[1])
|
||||
if err != nil {
|
||||
logError(err)
|
||||
return
|
||||
}
|
||||
|
||||
logJSON(rk)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// NewKeysCmd returns keys command.
|
||||
func NewKeysCmd() *cobra.Command {
|
||||
cmd := cobra.Command{
|
||||
Use: "keys",
|
||||
Short: "Keys management",
|
||||
Long: `Keys management: issue, revoke, or retrieve API key.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
logUsage("keys [issue | revoke | retrieve]")
|
||||
},
|
||||
}
|
||||
|
||||
for i := range cmdAPIKeys {
|
||||
cmd.AddCommand(&cmdAPIKeys[i])
|
||||
}
|
||||
|
||||
return &cmd
|
||||
}
|
@ -50,6 +50,7 @@ func main() {
|
||||
provisionCmd := cli.NewProvisionCmd()
|
||||
bootstrapCmd := cli.NewBootstrapCmd()
|
||||
certsCmd := cli.NewCertsCmd()
|
||||
keysCmd := cli.NewKeysCmd()
|
||||
|
||||
// Root Commands
|
||||
rootCmd.AddCommand(healthCmd)
|
||||
@ -61,6 +62,7 @@ func main() {
|
||||
rootCmd.AddCommand(provisionCmd)
|
||||
rootCmd.AddCommand(bootstrapCmd)
|
||||
rootCmd.AddCommand(certsCmd)
|
||||
rootCmd.AddCommand(keysCmd)
|
||||
|
||||
// Root Flags
|
||||
rootCmd.PersistentFlags().StringVarP(
|
||||
|
@ -6,43 +6,59 @@ import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/mainflux/mainflux/pkg/errors"
|
||||
)
|
||||
|
||||
type keyReq struct {
|
||||
Type uint32 `json:"type,omitempty"`
|
||||
Duration time.Duration `json:"duration,omitempty"`
|
||||
}
|
||||
|
||||
const keysEndpoint = "keys"
|
||||
|
||||
func (sdk mfSDK) Issue(token string, k Key) (issueKeyRes, error) {
|
||||
data, err := json.Marshal(k)
|
||||
const (
|
||||
// LoginKey is temporary User key received on successfull login.
|
||||
LoginKey uint32 = iota
|
||||
// RecoveryKey represents a key for resseting password.
|
||||
RecoveryKey
|
||||
// APIKey enables the one to act on behalf of the user.
|
||||
APIKey
|
||||
)
|
||||
|
||||
func (sdk mfSDK) Issue(token string, d time.Duration) (KeyRes, error) {
|
||||
datareq := keyReq{Type: APIKey, Duration: d}
|
||||
data, err := json.Marshal(datareq)
|
||||
if err != nil {
|
||||
return issueKeyRes{}, err
|
||||
return KeyRes{}, 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
|
||||
return KeyRes{}, err
|
||||
}
|
||||
|
||||
resp, err := sdk.sendRequest(req, token, string(CTJSON))
|
||||
if err != nil {
|
||||
return issueKeyRes{}, err
|
||||
return KeyRes{}, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return issueKeyRes{}, err
|
||||
return KeyRes{}, err
|
||||
}
|
||||
|
||||
if resp.StatusCode != http.StatusCreated {
|
||||
return issueKeyRes{}, errors.Wrap(ErrFailedCreation, errors.New(resp.Status))
|
||||
return KeyRes{}, errors.Wrap(ErrFailedCreation, errors.New(resp.Status))
|
||||
}
|
||||
|
||||
var key issueKeyRes
|
||||
var key KeyRes
|
||||
if err := json.Unmarshal(body, &key); err != nil {
|
||||
return issueKeyRes{}, err
|
||||
return KeyRes{}, err
|
||||
}
|
||||
|
||||
return key, nil
|
||||
|
@ -61,22 +61,22 @@ type MembersPage struct {
|
||||
pageRes
|
||||
}
|
||||
|
||||
type issueKeyRes struct {
|
||||
type KeyRes 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 {
|
||||
func (res KeyRes) Code() int {
|
||||
return http.StatusCreated
|
||||
}
|
||||
|
||||
func (res issueKeyRes) Headers() map[string]string {
|
||||
func (res KeyRes) Headers() map[string]string {
|
||||
return map[string]string{}
|
||||
}
|
||||
|
||||
func (res issueKeyRes) Empty() bool {
|
||||
func (res KeyRes) Empty() bool {
|
||||
return res.Value == ""
|
||||
}
|
||||
|
||||
@ -84,7 +84,6 @@ 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"`
|
||||
}
|
||||
|
@ -270,7 +270,7 @@ type SDK interface {
|
||||
RevokeCert(thingID, certID, token string) error
|
||||
|
||||
// Issue issues a new key, returning its token value alongside.
|
||||
Issue(token string, key Key) (issueKeyRes, error)
|
||||
Issue(token string, duration time.Duration) (KeyRes, 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
|
||||
|
Loading…
x
Reference in New Issue
Block a user