1//
2// Copyright 2021, Sander van Harmelen
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8//     http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
16
17package gitlab
18
19import (
20	"fmt"
21	"net/http"
22	"time"
23)
24
25// AccessRequest represents a access request for a group or project.
26//
27// GitLab API docs:
28// https://docs.gitlab.com/ce/api/access_requests.html
29type AccessRequest struct {
30	ID          int              `json:"id"`
31	Username    string           `json:"username"`
32	Name        string           `json:"name"`
33	State       string           `json:"state"`
34	CreatedAt   *time.Time       `json:"created_at"`
35	RequestedAt *time.Time       `json:"requested_at"`
36	AccessLevel AccessLevelValue `json:"access_level"`
37}
38
39// AccessRequestsService handles communication with the project/group
40// access requests related methods of the GitLab API.
41//
42// GitLab API docs: https://docs.gitlab.com/ce/api/access_requests.html
43type AccessRequestsService struct {
44	client *Client
45}
46
47// ListAccessRequestsOptions represents the available
48// ListProjectAccessRequests() or ListGroupAccessRequests() options.
49//
50// GitLab API docs:
51// https://docs.gitlab.com/ce/api/access_requests.html#list-access-requests-for-a-group-or-project
52type ListAccessRequestsOptions ListOptions
53
54// ListProjectAccessRequests gets a list of access requests
55// viewable by the authenticated user.
56//
57// GitLab API docs:
58// https://docs.gitlab.com/ce/api/access_requests.html#list-access-requests-for-a-group-or-project
59func (s *AccessRequestsService) ListProjectAccessRequests(pid interface{}, opt *ListAccessRequestsOptions, options ...RequestOptionFunc) ([]*AccessRequest, *Response, error) {
60	project, err := parseID(pid)
61	if err != nil {
62		return nil, nil, err
63	}
64	u := fmt.Sprintf("projects/%s/access_requests", pathEscape(project))
65
66	req, err := s.client.NewRequest(http.MethodGet, u, opt, options)
67	if err != nil {
68		return nil, nil, err
69	}
70
71	var ars []*AccessRequest
72	resp, err := s.client.Do(req, &ars)
73	if err != nil {
74		return nil, resp, err
75	}
76
77	return ars, resp, err
78}
79
80// ListGroupAccessRequests gets a list of access requests
81// viewable by the authenticated user.
82//
83// GitLab API docs:
84// https://docs.gitlab.com/ce/api/access_requests.html#list-access-requests-for-a-group-or-project
85func (s *AccessRequestsService) ListGroupAccessRequests(gid interface{}, opt *ListAccessRequestsOptions, options ...RequestOptionFunc) ([]*AccessRequest, *Response, error) {
86	group, err := parseID(gid)
87	if err != nil {
88		return nil, nil, err
89	}
90	u := fmt.Sprintf("groups/%s/access_requests", pathEscape(group))
91
92	req, err := s.client.NewRequest(http.MethodGet, u, opt, options)
93	if err != nil {
94		return nil, nil, err
95	}
96
97	var ars []*AccessRequest
98	resp, err := s.client.Do(req, &ars)
99	if err != nil {
100		return nil, resp, err
101	}
102
103	return ars, resp, err
104}
105
106// RequestProjectAccess requests access for the authenticated user
107// to a group or project.
108//
109// GitLab API docs:
110// https://docs.gitlab.com/ce/api/access_requests.html#request-access-to-a-group-or-project
111func (s *AccessRequestsService) RequestProjectAccess(pid interface{}, options ...RequestOptionFunc) (*AccessRequest, *Response, error) {
112	project, err := parseID(pid)
113	if err != nil {
114		return nil, nil, err
115	}
116	u := fmt.Sprintf("projects/%s/access_requests", pathEscape(project))
117
118	req, err := s.client.NewRequest(http.MethodPost, u, nil, options)
119	if err != nil {
120		return nil, nil, err
121	}
122
123	ar := new(AccessRequest)
124	resp, err := s.client.Do(req, ar)
125	if err != nil {
126		return nil, resp, err
127	}
128
129	return ar, resp, err
130}
131
132// RequestGroupAccess requests access for the authenticated user
133// to a group or project.
134//
135// GitLab API docs:
136// https://docs.gitlab.com/ce/api/access_requests.html#request-access-to-a-group-or-project
137func (s *AccessRequestsService) RequestGroupAccess(gid interface{}, options ...RequestOptionFunc) (*AccessRequest, *Response, error) {
138	group, err := parseID(gid)
139	if err != nil {
140		return nil, nil, err
141	}
142	u := fmt.Sprintf("groups/%s/access_requests", pathEscape(group))
143
144	req, err := s.client.NewRequest(http.MethodPost, u, nil, options)
145	if err != nil {
146		return nil, nil, err
147	}
148
149	ar := new(AccessRequest)
150	resp, err := s.client.Do(req, ar)
151	if err != nil {
152		return nil, resp, err
153	}
154
155	return ar, resp, err
156}
157
158// ApproveAccessRequestOptions represents the available
159// ApproveProjectAccessRequest() and ApproveGroupAccessRequest() options.
160//
161// GitLab API docs:
162// https://docs.gitlab.com/ce/api/access_requests.html#approve-an-access-request
163type ApproveAccessRequestOptions struct {
164	AccessLevel *AccessLevelValue `url:"access_level,omitempty" json:"access_level,omitempty"`
165}
166
167// ApproveProjectAccessRequest approves an access request for the given user.
168//
169// GitLab API docs:
170// https://docs.gitlab.com/ce/api/access_requests.html#approve-an-access-request
171func (s *AccessRequestsService) ApproveProjectAccessRequest(pid interface{}, user int, opt *ApproveAccessRequestOptions, options ...RequestOptionFunc) (*AccessRequest, *Response, error) {
172	project, err := parseID(pid)
173	if err != nil {
174		return nil, nil, err
175	}
176	u := fmt.Sprintf("projects/%s/access_requests/%d/approve", pathEscape(project), user)
177
178	req, err := s.client.NewRequest(http.MethodPut, u, opt, options)
179	if err != nil {
180		return nil, nil, err
181	}
182
183	ar := new(AccessRequest)
184	resp, err := s.client.Do(req, ar)
185	if err != nil {
186		return nil, resp, err
187	}
188
189	return ar, resp, err
190}
191
192// ApproveGroupAccessRequest approves an access request for the given user.
193//
194// GitLab API docs:
195// https://docs.gitlab.com/ce/api/access_requests.html#approve-an-access-request
196func (s *AccessRequestsService) ApproveGroupAccessRequest(gid interface{}, user int, opt *ApproveAccessRequestOptions, options ...RequestOptionFunc) (*AccessRequest, *Response, error) {
197	group, err := parseID(gid)
198	if err != nil {
199		return nil, nil, err
200	}
201	u := fmt.Sprintf("groups/%s/access_requests/%d/approve", pathEscape(group), user)
202
203	req, err := s.client.NewRequest(http.MethodPut, u, opt, options)
204	if err != nil {
205		return nil, nil, err
206	}
207
208	ar := new(AccessRequest)
209	resp, err := s.client.Do(req, ar)
210	if err != nil {
211		return nil, resp, err
212	}
213
214	return ar, resp, err
215}
216
217// DenyProjectAccessRequest denies an access request for the given user.
218//
219// GitLab API docs:
220// https://docs.gitlab.com/ce/api/access_requests.html#deny-an-access-request
221func (s *AccessRequestsService) DenyProjectAccessRequest(pid interface{}, user int, options ...RequestOptionFunc) (*Response, error) {
222	project, err := parseID(pid)
223	if err != nil {
224		return nil, err
225	}
226	u := fmt.Sprintf("projects/%s/access_requests/%d", pathEscape(project), user)
227
228	req, err := s.client.NewRequest(http.MethodDelete, u, nil, options)
229	if err != nil {
230		return nil, err
231	}
232
233	return s.client.Do(req, nil)
234}
235
236// DenyGroupAccessRequest denies an access request for the given user.
237//
238// GitLab API docs:
239// https://docs.gitlab.com/ce/api/access_requests.html#deny-an-access-request
240func (s *AccessRequestsService) DenyGroupAccessRequest(gid interface{}, user int, options ...RequestOptionFunc) (*Response, error) {
241	group, err := parseID(gid)
242	if err != nil {
243		return nil, err
244	}
245	u := fmt.Sprintf("groups/%s/access_requests/%d", pathEscape(group), user)
246
247	req, err := s.client.NewRequest(http.MethodDelete, u, nil, options)
248	if err != nil {
249		return nil, err
250	}
251
252	return s.client.Do(req, nil)
253}
254