Skip to content

Commit b296e1b

Browse files
authored
add scoped tokens (#1022)
Add scoped tokens: Tokens can be scoped to an organization with the --org parameter
2 parents ab356cb + f24b1ed commit b296e1b

3 files changed

Lines changed: 61 additions & 13 deletions

File tree

internal/cmd/auth_createapitokens.go

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@ import (
66

77
"github.com/spf13/cobra"
88
"github.com/tursodatabase/turso-cli/internal"
9-
"github.com/tursodatabase/turso-cli/internal/prompt"
109
)
1110

11+
var mintOrgFlag string
12+
1213
func init() {
1314
apiTokensCmd.AddCommand(createApiTokensCmd)
15+
createApiTokensCmd.Flags().StringVar(&mintOrgFlag, "org", "", "Organization to restrict the token to")
1416
}
1517

1618
var createApiTokensCmd = &cobra.Command{
@@ -29,16 +31,32 @@ var createApiTokensCmd = &cobra.Command{
2931
}
3032

3133
name := strings.TrimSpace(args[0])
32-
description := fmt.Sprintf("Creating api token %s", internal.Emph(name))
33-
bar := prompt.Spinner(description)
34-
defer bar.Stop()
3534

36-
data, err := client.ApiTokens.Create(name)
35+
// Validate organization if provided
36+
if mintOrgFlag != "" {
37+
orgs, err := client.Organizations.List()
38+
if err != nil {
39+
return fmt.Errorf("failed to list organizations: %w", err)
40+
}
41+
42+
found := false
43+
for _, org := range orgs {
44+
if org.Slug == mintOrgFlag {
45+
found = true
46+
break
47+
}
48+
}
49+
50+
if !found {
51+
return fmt.Errorf("organization %s not found", internal.Emph(mintOrgFlag))
52+
}
53+
}
54+
55+
data, err := client.ApiTokens.CreateWithOrg(name, mintOrgFlag)
3756
if err != nil {
3857
return err
3958
}
4059

41-
bar.Stop()
4260
fmt.Println(data.Value)
4361
return nil
4462
},

internal/cmd/auth_listapitokens.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,13 @@ var listApiTokensCmd = &cobra.Command{
3131

3232
data := [][]string{}
3333
for _, apiToken := range apiTokens {
34-
data = append(data, []string{apiToken.Name})
34+
org := apiToken.Organization
35+
if org == "" {
36+
org = "all"
37+
}
38+
data = append(data, []string{apiToken.Name, org, apiToken.CreatedAt})
3539
}
36-
printTable([]string{"Name"}, data)
40+
printTable([]string{"Name", "Organization", "Created At"}, data)
3741

3842
return nil
3943
},

internal/turso/apiTokens.go

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
11
package turso
22

33
import (
4+
"bytes"
5+
"encoding/json"
46
"fmt"
57
"net/http"
68
)
79

810
type ApiToken struct {
9-
ID string `json:"dbId"`
10-
Name string
11-
Owner uint
12-
PubKey []byte
11+
ID string `json:"id"`
12+
Name string `json:"name"`
13+
Organization string `json:"organization,omitempty"`
14+
CreatedAt string `json:"created_at"`
15+
Owner uint `json:"-"`
16+
PubKey []byte `json:"-"`
1317
}
1418

1519
type ApiTokensClient client
@@ -39,9 +43,31 @@ type CreateApiToken struct {
3943
}
4044

4145
func (a *ApiTokensClient) Create(name string) (CreateApiToken, error) {
46+
return a.CreateWithOrg(name, "")
47+
}
48+
49+
func (a *ApiTokensClient) CreateWithOrg(name string, organization string) (CreateApiToken, error) {
4250
url := fmt.Sprintf("/v2/auth/api-tokens/%s", name)
4351

44-
res, err := a.client.Post(url, nil)
52+
var res *http.Response
53+
var err error
54+
55+
if organization != "" {
56+
reqBody := struct {
57+
Organization string `json:"organization"`
58+
}{
59+
Organization: organization,
60+
}
61+
jsonData, marshalErr := json.Marshal(reqBody)
62+
if marshalErr != nil {
63+
return CreateApiToken{}, fmt.Errorf("failed to marshal request body: %w", marshalErr)
64+
}
65+
body := bytes.NewReader(jsonData)
66+
res, err = a.client.Post(url, body)
67+
} else {
68+
res, err = a.client.Post(url, nil)
69+
}
70+
4571
if err != nil {
4672
return CreateApiToken{}, fmt.Errorf("failed to create token: %s", err)
4773
}

0 commit comments

Comments
 (0)