1package api
2
3const (
4	// ACLCLientType is the client type token
5	ACLClientType = "client"
6
7	// ACLManagementType is the management type token
8	ACLManagementType = "management"
9)
10
11// ACLEntry is used to represent an ACL entry
12type ACLEntry struct {
13	CreateIndex uint64
14	ModifyIndex uint64
15	ID          string
16	Name        string
17	Type        string
18	Rules       string
19}
20
21// ACL can be used to query the ACL endpoints
22type ACL struct {
23	c *Client
24}
25
26// ACL returns a handle to the ACL endpoints
27func (c *Client) ACL() *ACL {
28	return &ACL{c}
29}
30
31// Create is used to generate a new token with the given parameters
32func (a *ACL) Create(acl *ACLEntry, q *WriteOptions) (string, *WriteMeta, error) {
33	r := a.c.newRequest("PUT", "/v1/acl/create")
34	r.setWriteOptions(q)
35	r.obj = acl
36	rtt, resp, err := requireOK(a.c.doRequest(r))
37	if err != nil {
38		return "", nil, err
39	}
40	defer resp.Body.Close()
41
42	wm := &WriteMeta{RequestTime: rtt}
43	var out struct{ ID string }
44	if err := decodeBody(resp, &out); err != nil {
45		return "", nil, err
46	}
47	return out.ID, wm, nil
48}
49
50// Update is used to update the rules of an existing token
51func (a *ACL) Update(acl *ACLEntry, q *WriteOptions) (*WriteMeta, error) {
52	r := a.c.newRequest("PUT", "/v1/acl/update")
53	r.setWriteOptions(q)
54	r.obj = acl
55	rtt, resp, err := requireOK(a.c.doRequest(r))
56	if err != nil {
57		return nil, err
58	}
59	defer resp.Body.Close()
60
61	wm := &WriteMeta{RequestTime: rtt}
62	return wm, nil
63}
64
65// Destroy is used to destroy a given ACL token ID
66func (a *ACL) Destroy(id string, q *WriteOptions) (*WriteMeta, error) {
67	r := a.c.newRequest("PUT", "/v1/acl/destroy/"+id)
68	r.setWriteOptions(q)
69	rtt, resp, err := requireOK(a.c.doRequest(r))
70	if err != nil {
71		return nil, err
72	}
73	resp.Body.Close()
74
75	wm := &WriteMeta{RequestTime: rtt}
76	return wm, nil
77}
78
79// Clone is used to return a new token cloned from an existing one
80func (a *ACL) Clone(id string, q *WriteOptions) (string, *WriteMeta, error) {
81	r := a.c.newRequest("PUT", "/v1/acl/clone/"+id)
82	r.setWriteOptions(q)
83	rtt, resp, err := requireOK(a.c.doRequest(r))
84	if err != nil {
85		return "", nil, err
86	}
87	defer resp.Body.Close()
88
89	wm := &WriteMeta{RequestTime: rtt}
90	var out struct{ ID string }
91	if err := decodeBody(resp, &out); err != nil {
92		return "", nil, err
93	}
94	return out.ID, wm, nil
95}
96
97// Info is used to query for information about an ACL token
98func (a *ACL) Info(id string, q *QueryOptions) (*ACLEntry, *QueryMeta, error) {
99	r := a.c.newRequest("GET", "/v1/acl/info/"+id)
100	r.setQueryOptions(q)
101	rtt, resp, err := requireOK(a.c.doRequest(r))
102	if err != nil {
103		return nil, nil, err
104	}
105	defer resp.Body.Close()
106
107	qm := &QueryMeta{}
108	parseQueryMeta(resp, qm)
109	qm.RequestTime = rtt
110
111	var entries []*ACLEntry
112	if err := decodeBody(resp, &entries); err != nil {
113		return nil, nil, err
114	}
115	if len(entries) > 0 {
116		return entries[0], qm, nil
117	}
118	return nil, qm, nil
119}
120
121// List is used to get all the ACL tokens
122func (a *ACL) List(q *QueryOptions) ([]*ACLEntry, *QueryMeta, error) {
123	r := a.c.newRequest("GET", "/v1/acl/list")
124	r.setQueryOptions(q)
125	rtt, resp, err := requireOK(a.c.doRequest(r))
126	if err != nil {
127		return nil, nil, err
128	}
129	defer resp.Body.Close()
130
131	qm := &QueryMeta{}
132	parseQueryMeta(resp, qm)
133	qm.RequestTime = rtt
134
135	var entries []*ACLEntry
136	if err := decodeBody(resp, &entries); err != nil {
137		return nil, nil, err
138	}
139	return entries, qm, nil
140}
141