Skip to content
This repository was archived by the owner on Jan 15, 2024. It is now read-only.

Commit 1332f3c

Browse files
authored
Merge branch 'master' into remove-deprecate-notice
2 parents db9a358 + 0933c3f commit 1332f3c

File tree

4 files changed

+332
-0
lines changed

4 files changed

+332
-0
lines changed

api_key.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package gapi
2+
3+
import (
4+
"bytes"
5+
"encoding/json"
6+
"fmt"
7+
"net/url"
8+
"strconv"
9+
"time"
10+
)
11+
12+
type CreateAPIKeyRequest struct {
13+
Name string `json:"name"`
14+
Role string `json:"role"`
15+
SecondsToLive int64 `json:"secondsToLive,omitempty"`
16+
}
17+
18+
type CreateAPIKeyResponse struct {
19+
// ID field only returned after Grafana v7.
20+
ID int64 `json:"id,omitempty"`
21+
Name string `json:"name"`
22+
Key string `json:"key"`
23+
}
24+
25+
type GetAPIKeysResponse struct {
26+
ID int64 `json:"id"`
27+
Name string `json:"name"`
28+
Role string `json:"role"`
29+
Expiration time.Time `json:"expiration,omitempty"`
30+
}
31+
32+
type DeleteAPIKeyResponse struct {
33+
Message string `json:"message"`
34+
}
35+
36+
// CreateAPIKey creates a new Grafana API key.
37+
func (c *Client) CreateAPIKey(request CreateAPIKeyRequest) (CreateAPIKeyResponse, error) {
38+
response := CreateAPIKeyResponse{}
39+
40+
data, err := json.Marshal(request)
41+
if err != nil {
42+
return response, err
43+
}
44+
45+
err = c.request("POST", "/api/auth/keys", nil, bytes.NewBuffer(data), &response)
46+
return response, err
47+
}
48+
49+
// GetAPIKeys retrieves a list of all API keys.
50+
func (c *Client) GetAPIKeys(includeExpired bool) ([]*GetAPIKeysResponse, error) {
51+
response := make([]*GetAPIKeysResponse, 0)
52+
53+
query := url.Values{}
54+
query.Add("includeExpired", strconv.FormatBool(includeExpired))
55+
56+
err := c.request("GET", "/api/auth/keys", query, nil, &response)
57+
return response, err
58+
}
59+
60+
// DeleteAPIKey deletes the Grafana API key with the specified ID.
61+
func (c *Client) DeleteAPIKey(id int64) (DeleteAPIKeyResponse, error) {
62+
response := DeleteAPIKeyResponse{}
63+
64+
path := fmt.Sprintf("/api/auth/keys/%d", id)
65+
err := c.request("DELETE", path, nil, nil, &response)
66+
return response, err
67+
}

api_key_test.go

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package gapi
2+
3+
import (
4+
"testing"
5+
6+
"github.com/gobs/pretty"
7+
)
8+
9+
const (
10+
createAPIKeyJSON = `{"name":"key-name", "key":"mock-api-key"}`
11+
deleteAPIKeyJSON = `{"message":"API key deleted"}`
12+
13+
getAPIKeysJSON = `[
14+
{
15+
"id": 1,
16+
"name": "key-name-2",
17+
"role": "Viewer"
18+
},
19+
{
20+
"id": 2,
21+
"name": "key-name-2",
22+
"role": "Admin",
23+
"expiration": "2021-10-30T10:52:03+03:00"
24+
}
25+
]`
26+
)
27+
28+
func TestCreateAPIKey(t *testing.T) {
29+
server, client := gapiTestTools(t, 200, createAPIKeyJSON)
30+
defer server.Close()
31+
32+
req := CreateAPIKeyRequest{
33+
Name: "key-name",
34+
Role: "Viewer",
35+
SecondsToLive: 0,
36+
}
37+
38+
res, err := client.CreateAPIKey(req)
39+
if err != nil {
40+
t.Error(err)
41+
}
42+
43+
t.Log(pretty.PrettyFormat(res))
44+
}
45+
46+
func TestDeleteAPIKey(t *testing.T) {
47+
server, client := gapiTestTools(t, 200, deleteAPIKeyJSON)
48+
defer server.Close()
49+
50+
res, err := client.DeleteAPIKey(int64(1))
51+
if err != nil {
52+
t.Error(err)
53+
}
54+
55+
t.Log(pretty.PrettyFormat(res))
56+
}
57+
58+
func TestGetAPIKeys(t *testing.T) {
59+
server, client := gapiTestTools(t, 200, getAPIKeysJSON)
60+
defer server.Close()
61+
62+
res, err := client.GetAPIKeys(true)
63+
if err != nil {
64+
t.Error(err)
65+
}
66+
67+
t.Log(pretty.PrettyFormat(res))
68+
}

datasource_permissions.go

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
package gapi
2+
3+
import (
4+
"bytes"
5+
"encoding/json"
6+
"fmt"
7+
)
8+
9+
type DatasourcePermissionType int
10+
11+
const (
12+
_ DatasourcePermissionType = iota // 0 is not a valid permission
13+
DatasourcePermissionQuery
14+
)
15+
16+
// DatasourcePermission has information such as a datasource, user, team, role and permission.
17+
type DatasourcePermission struct {
18+
ID int64 `json:"id"`
19+
DatasourceID int64 `json:"datasourceId"`
20+
UserID int64 `json:"userId"`
21+
UserEmail string `json:"userEmail"`
22+
TeamID int64 `json:"teamId"`
23+
24+
// Permission levels are
25+
// 1 = Query
26+
Permission DatasourcePermissionType `json:"permission"`
27+
PermissionName string `json:"permissionName"`
28+
}
29+
30+
type DatasourcePermissionsResponse struct {
31+
DatasourceID int64 `json:"datasourceId"`
32+
Enabled bool `json:"enabled"`
33+
Permissions []*DatasourcePermission `json:"permissions"`
34+
}
35+
36+
type DatasourcePermissionAddPayload struct {
37+
UserID int64 `json:"userId"`
38+
TeamID int64 `json:"teamId"`
39+
Permission DatasourcePermissionType `json:"permission"`
40+
}
41+
42+
// EnableDatasourcePermissions enables the datasource permissions (this is a datasource setting)
43+
func (c *Client) EnableDatasourcePermissions(id int64) error {
44+
path := fmt.Sprintf("/api/datasources/%d/enable-permissions", id)
45+
if err := c.request("POST", path, nil, nil, nil); err != nil {
46+
return fmt.Errorf("error enabling permissions at %s: %w", path, err)
47+
}
48+
return nil
49+
}
50+
51+
// DisableDatasourcePermissions disables the datasource permissions (this is a datasource setting)
52+
func (c *Client) DisableDatasourcePermissions(id int64) error {
53+
path := fmt.Sprintf("/api/datasources/%d/disable-permissions", id)
54+
if err := c.request("POST", path, nil, nil, nil); err != nil {
55+
return fmt.Errorf("error disabling permissions at %s: %w", path, err)
56+
}
57+
return nil
58+
}
59+
60+
// DatasourcePermissions fetches and returns the permissions for the datasource whose ID it's passed.
61+
func (c *Client) DatasourcePermissions(id int64) (*DatasourcePermissionsResponse, error) {
62+
path := fmt.Sprintf("/api/datasources/%d/permissions", id)
63+
var out *DatasourcePermissionsResponse
64+
err := c.request("GET", path, nil, nil, &out)
65+
if err != nil {
66+
return out, fmt.Errorf("error getting permissions at %s: %w", path, err)
67+
}
68+
69+
return out, nil
70+
}
71+
72+
// AddDatasourcePermission adds the given permission item
73+
func (c *Client) AddDatasourcePermission(id int64, item *DatasourcePermissionAddPayload) error {
74+
path := fmt.Sprintf("/api/datasources/%d/permissions", id)
75+
data, err := json.Marshal(item)
76+
if err != nil {
77+
return fmt.Errorf("marshal err: %w", err)
78+
}
79+
80+
if err = c.request("POST", path, nil, bytes.NewBuffer(data), nil); err != nil {
81+
return fmt.Errorf("error adding permissions at %s: %w", path, err)
82+
}
83+
84+
return nil
85+
}
86+
87+
// RemoveDatasourcePermission removes the permission with the given id
88+
func (c *Client) RemoveDatasourcePermission(id, permissionID int64) error {
89+
path := fmt.Sprintf("/api/datasources/%d/permissions/%d", id, permissionID)
90+
if err := c.request("DELETE", path, nil, nil, nil); err != nil {
91+
return fmt.Errorf("error deleting permissions at %s: %w", path, err)
92+
}
93+
94+
return nil
95+
}

datasource_permissions_test.go

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
package gapi
2+
3+
import (
4+
"testing"
5+
6+
"github.com/gobs/pretty"
7+
)
8+
9+
const (
10+
getDatasourcePermissionsJSON = `{
11+
"datasourceId": 1,
12+
"enabled": true,
13+
"permissions": [
14+
{
15+
"datasourceId": 1,
16+
"userId": 1,
17+
"userLogin": "user",
18+
"userEmail": "user@test.com",
19+
"userAvatarUrl": "/avatar/46d229b033af06a191ff2267bca9ae56",
20+
"permission": 1,
21+
"permissionName": "Query",
22+
"created": "2017-06-20T02:00:00+02:00",
23+
"updated": "2017-06-20T02:00:00+02:00"
24+
},
25+
{
26+
"datasourceId": 2,
27+
"teamId": 1,
28+
"team": "A Team",
29+
"teamAvatarUrl": "/avatar/46d229b033af06a191ff2267bca9ae56",
30+
"permission": 1,
31+
"permissionName": "Query",
32+
"created": "2017-06-20T02:00:00+02:00",
33+
"updated": "2017-06-20T02:00:00+02:00"
34+
}
35+
]
36+
}`
37+
addDatasourcePermissionsJSON = `{
38+
"message": "Datasource permission added"
39+
}`
40+
)
41+
42+
func TestDatasourcePermissions(t *testing.T) {
43+
server, client := gapiTestTools(t, 200, getDatasourcePermissionsJSON)
44+
defer server.Close()
45+
46+
resp, err := client.DatasourcePermissions(1)
47+
if err != nil {
48+
t.Fatal(err)
49+
}
50+
51+
t.Log(pretty.PrettyFormat(resp))
52+
53+
expects := []*DatasourcePermission{
54+
{
55+
DatasourceID: 1,
56+
UserID: 1,
57+
TeamID: 0,
58+
Permission: 1,
59+
PermissionName: "Query",
60+
},
61+
{
62+
DatasourceID: 2,
63+
UserID: 0,
64+
TeamID: 1,
65+
Permission: 1,
66+
PermissionName: "Query",
67+
},
68+
}
69+
70+
for i, expect := range expects {
71+
t.Run("check data", func(t *testing.T) {
72+
if resp.Permissions[i].DatasourceID != expect.DatasourceID ||
73+
resp.Permissions[i].UserID != expect.UserID ||
74+
resp.Permissions[i].TeamID != expect.TeamID ||
75+
resp.Permissions[i].Permission != expect.Permission ||
76+
resp.Permissions[i].PermissionName != expect.PermissionName {
77+
t.Error("Not correctly parsing returned datasource permission")
78+
}
79+
})
80+
}
81+
}
82+
83+
func TestAddDatasourcePermissions(t *testing.T) {
84+
server, client := gapiTestTools(t, 200, addDatasourcePermissionsJSON)
85+
defer server.Close()
86+
87+
for _, item := range []*DatasourcePermissionAddPayload{
88+
{
89+
TeamID: 1,
90+
Permission: 1,
91+
},
92+
{
93+
UserID: 11,
94+
Permission: 1,
95+
},
96+
} {
97+
err := client.AddDatasourcePermission(1, item)
98+
if err != nil {
99+
t.Error(err)
100+
}
101+
}
102+
}

0 commit comments

Comments
 (0)