forked from nytm/go-grafana-api
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathorgs.go
314 lines (250 loc) · 7 KB
/
orgs.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
package gapi
import (
"fmt"
"net/url"
"strings"
)
const (
// OrgUserRoleViewer is the readonly role
OrgUserRoleViewer = "Viewer"
// OrgUserRoleAdmin is the admin role
OrgUserRoleAdmin = "Admin"
// OrgUserRoleEditor is the editing role
OrgUserRoleEditor = "Editor"
)
// ErrInvalidUserRole will be returned when a org user role is unknown
var ErrInvalidUserRole = fmt.Errorf("invalid user role")
// OrgUser is a user of the org
type OrgUser struct {
User
ID int64 `json:"userId"`
Role string `json:"role"`
OrgID int64 `json:"orgId"`
}
// UpdateRole will update the role of the org user to the one given
func (ouser OrgUser) UpdateRole(c *Client, role string) error {
return c.UpdateOrgUserRole(ouser.OrgID, ouser.ID, role)
}
// OrgUsers is a collection of Org user models
type OrgUsers []*OrgUser
// Users returns the user objects from a collection of org users
func (ousers OrgUsers) Users() []*User {
users := []*User{}
for _, ou := range ousers {
users = append(users, &ou.User)
}
return users
}
// FindByLogin returns the org user with the given email from a
// collection of org users, and a false if it was not found
func (ousers OrgUsers) FindByLogin(login string) (*OrgUser, bool) {
for _, u := range ousers {
if u.Login == login {
return u, true
}
}
return &OrgUser{}, false
}
// Org represents an Organisation object in Grafana
type Org struct {
ID int64 `json:"id"`
Name string `json:"name"`
}
func (o Org) String() string {
return o.Name
}
// OrgDataSourceGetter allows getting datasources using an org ID
type OrgDataSourceGetter interface {
DataSourcesByOrgID(int64) ([]*DataSource, error)
}
// DataSources use the given client to return the datasources
// for the organisation
func (o Org) DataSources(c OrgDataSourceGetter) ([]*DataSource, error) {
return c.DataSourcesByOrgID(o.ID)
}
// AddUser will add a user to the organisation
func (o Org) AddUser(c *Client, username, role string) error {
role = AutoFixRole(role)
if !IsUserRoleValid(role) {
return ErrInvalidUserRole
}
acl := map[string]string{"role": role, "loginOrEmail": username}
res, err := c.doJSONRequest("POST", fmt.Sprintf("/api/orgs/%d/users", o.ID), acl)
if err != nil {
return err
}
return res.Error()
}
// Users use the given client to return the users
// for the organisation
func (o Org) Users(c *Client) ([]*OrgUser, error) {
ousers := []*OrgUser{}
res, err := c.doRequest("GET", fmt.Sprintf("/api/orgs/%d/users", o.ID), nil)
if err != nil {
return ousers, err
}
if !res.OK() {
return ousers, res.Error()
}
err = res.BindJSON(&ousers)
return ousers, err
}
// RemoveUser removes the user from the organisation
func (o Org) RemoveUser(c *Client, userID int64) error {
res, err := c.doRequest("DELETE", fmt.Sprintf("/api/orgs/%d/users/%d", o.ID, userID), nil)
if err != nil {
return err
}
return res.Error()
}
// SetHomeDashboard will set the home dashboard of the organisation
func (o Org) SetHomeDashboard(c *Client, dashID int64) error {
if err := c.SwitchCurrentUserOrg(o.ID); err != nil {
return err
}
prefs, err := c.GetCurrentOrgPrefs()
if err != nil {
return err
}
prefs.HomeDashboardID = dashID
return c.UpdateCurrentOrgPrefs(prefs)
}
// Org returns the organisation with the given ID
func (c *Client) Org(id int64) (Org, error) {
org := Org{}
res, err := c.doRequest("GET", fmt.Sprintf("/api/orgs/%d", id), nil)
if err != nil {
return org, err
}
if !res.OK() {
return org, res.Error()
}
err = res.BindJSON(&org)
return org, err
}
// OrgByName returns the organisation with the given name
func (c *Client) OrgByName(name string) (Org, error) {
org := Org{}
// the normal query escape replaces spaces with the plus symbol
// grafana API does not like that, use %20 instead as per API docs
name = url.QueryEscape(name)
name = strings.Replace(name, "+", "%20", -1)
res, err := c.doRequest("GET", fmt.Sprintf("/api/orgs/name/%s", name), nil)
if err != nil {
return org, err
}
if !res.OK() {
return org, res.Error()
}
err = res.BindJSON(&org)
return org, err
}
// Orgs returns all the orgs in Grafana
func (c *Client) Orgs() ([]Org, error) {
orgs := make([]Org, 0)
res, err := c.doRequest("GET", "/api/orgs/", nil)
if err != nil {
return orgs, err
}
if !res.OK() {
return orgs, res.Error()
}
err = res.BindJSON(&orgs)
return orgs, err
}
// NewOrg creates an Org with the given name in Grafana
func (c *Client) NewOrg(name string) (Org, error) {
org := Org{Name: name}
newOrg := map[string]string{"name": name}
res, err := c.doJSONRequest("POST", "/api/orgs", newOrg)
if err != nil {
return org, err
}
if !res.OK() {
return org, res.Error()
}
body := struct {
ID int64 `json:"orgId"`
}{0}
err = res.BindJSON(&body)
if err == nil {
org.ID = body.ID
}
return org, err
}
// UpdateOrgUserRole will update the role for the given user on the given org
func (c *Client) UpdateOrgUserRole(orgID, userID int64, role string) error {
role = AutoFixRole(role)
if !IsUserRoleValid(role) {
return ErrInvalidUserRole
}
path := fmt.Sprintf("/api/orgs/%d/users/%d", orgID, userID)
res, err := c.doJSONRequest("PATCH", path, map[string]string{"role": role})
if err != nil {
return err
}
return res.Error()
}
// DeleteOrg deletes the given org ID from Grafana
func (c *Client) DeleteOrg(id int64) error {
res, err := c.doRequest("DELETE", fmt.Sprintf("/api/orgs/%d", id), nil)
if err != nil {
return err
}
return res.Error()
}
// UserRoleIsValid is deprecated in preference to IsUserRoleValid
var UserRoleIsValid = IsUserRoleValid
// IsUserRoleValid will return true if the given role is valid
func IsUserRoleValid(role string) bool {
switch role {
case OrgUserRoleAdmin:
fallthrough
case OrgUserRoleEditor:
fallthrough
case OrgUserRoleViewer:
return true
}
return false
}
// AutoFixRole will attempt to automatically fix common
// issues when setting user roles using strings. It will
// titleize and correct the miss-spelling of viewer
func AutoFixRole(role string) string {
role = strings.Title(role)
if role == "Veiwer" {
role = OrgUserRoleViewer
}
return role
}
// OrgPrefs represents the organisation preferences
type OrgPrefs struct {
Theme string `json:"theme"`
HomeDashboardID int64 `json:"homeDashboardId"`
Timezone string `json:"timezone"`
}
// GetCurrentOrgPrefs will get the preferences for the organisation in the current
// context, as selected by the SwitchContext method
func (c *Client) GetCurrentOrgPrefs() (*OrgPrefs, error) {
prefs := &OrgPrefs{}
res, err := c.doRequest("GET", "/api/org/preferences", nil)
if err != nil {
return prefs, err
}
if !res.OK() {
return prefs, res.Error()
}
if err := res.BindJSON(prefs); err != nil {
return prefs, err
}
return prefs, nil
}
// UpdateCurrentOrgPrefs will update the preferences of the organisation in the current
// context, as selected by the SwitchContext method
func (c *Client) UpdateCurrentOrgPrefs(prefs *OrgPrefs) error {
res, err := c.doJSONRequest("PUT", "/api/org/preferences", prefs)
if err != nil {
return err
}
return res.Error()
}