1//
2// Copyright 2017, 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)
22
23// GroupsService handles communication with the group related methods of
24// the GitLab API.
25//
26// GitLab API docs: https://docs.gitlab.com/ce/api/groups.html
27type GroupsService struct {
28 client *Client
29}
30
31// Group represents a GitLab group.
32//
33// GitLab API docs: https://docs.gitlab.com/ce/api/groups.html
34type Group struct {
35 ID int `json:"id"`
36 Name string `json:"name"`
37 Path string `json:"path"`
38 Description string `json:"description"`
39 Visibility *VisibilityValue `json:"visibility"`
40 LFSEnabled bool `json:"lfs_enabled"`
41 AvatarURL string `json:"avatar_url"`
42 WebURL string `json:"web_url"`
43 RequestAccessEnabled bool `json:"request_access_enabled"`
44 FullName string `json:"full_name"`
45 FullPath string `json:"full_path"`
46 ParentID int `json:"parent_id"`
47 Projects []*Project `json:"projects"`
48 Statistics *StorageStatistics `json:"statistics"`
49 CustomAttributes []*CustomAttribute `json:"custom_attributes"`
50 ShareWithGroupLock bool `json:"share_with_group_lock"`
51 RequireTwoFactorAuth bool `json:"require_two_factor_authentication"`
52 TwoFactorGracePeriod int `json:"two_factor_grace_period"`
53 ProjectCreationLevel string `json:"project_creation_level"`
54 AutoDevopsEnabled bool `json:"auto_devops_enabled"`
55 SubGroupCreationLevel string `json:"subgroup_creation_level"`
56 EmailsDisabled bool `json:"emails_disabled"`
57 RunnersToken string `json:"runners_token"`
58 SharedProjects []*Project `json:"shared_projects"`
59 LDAPCN string `json:"ldap_cn"`
60 LDAPAccess bool `json:"ldap_access"`
61 SharedRunnersMinutesLimit int `json:"shared_runners_minutes_limit"`
62 ExtraSharedRunnersMinutesLimit int `json:"extra_shared_runners_minutes_limit"`
63}
64
65// ListGroupsOptions represents the available ListGroups() options.
66//
67// GitLab API docs: https://docs.gitlab.com/ce/api/groups.html#list-project-groups
68type ListGroupsOptions struct {
69 ListOptions
70 AllAvailable *bool `url:"all_available,omitempty" json:"all_available,omitempty"`
71 MinAccessLevel *AccessLevelValue `url:"min_access_level,omitempty" json:"min_access_level,omitempty"`
72 OrderBy *string `url:"order_by,omitempty" json:"order_by,omitempty"`
73 Owned *bool `url:"owned,omitempty" json:"owned,omitempty"`
74 Search *string `url:"search,omitempty" json:"search,omitempty"`
75 SkipGroups []int `url:"skip_groups,omitempty" json:"skip_groups,omitempty"`
76 Sort *string `url:"sort,omitempty" json:"sort,omitempty"`
77 Statistics *bool `url:"statistics,omitempty" json:"statistics,omitempty"`
78 WithCustomAttributes *bool `url:"with_custom_attributes,omitempty" json:"with_custom_attributes,omitempty"`
79}
80
81// ListGroups gets a list of groups (as user: my groups, as admin: all groups).
82//
83// GitLab API docs:
84// https://docs.gitlab.com/ce/api/groups.html#list-project-groups
85func (s *GroupsService) ListGroups(opt *ListGroupsOptions, options ...OptionFunc) ([]*Group, *Response, error) {
86 req, err := s.client.NewRequest("GET", "groups", opt, options)
87 if err != nil {
88 return nil, nil, err
89 }
90
91 var g []*Group
92 resp, err := s.client.Do(req, &g)
93 if err != nil {
94 return nil, resp, err
95 }
96
97 return g, resp, err
98}
99
100// GetGroup gets all details of a group.
101//
102// GitLab API docs: https://docs.gitlab.com/ce/api/groups.html#details-of-a-group
103func (s *GroupsService) GetGroup(gid interface{}, options ...OptionFunc) (*Group, *Response, error) {
104 group, err := parseID(gid)
105 if err != nil {
106 return nil, nil, err
107 }
108 u := fmt.Sprintf("groups/%s", pathEscape(group))
109
110 req, err := s.client.NewRequest("GET", u, nil, options)
111 if err != nil {
112 return nil, nil, err
113 }
114
115 g := new(Group)
116 resp, err := s.client.Do(req, g)
117 if err != nil {
118 return nil, resp, err
119 }
120
121 return g, resp, err
122}
123
124// CreateGroupOptions represents the available CreateGroup() options.
125//
126// GitLab API docs: https://docs.gitlab.com/ce/api/groups.html#new-group
127type CreateGroupOptions struct {
128 Name *string `url:"name,omitempty" json:"name,omitempty"`
129 Path *string `url:"path,omitempty" json:"path,omitempty"`
130 Description *string `url:"description,omitempty" json:"description,omitempty"`
131 Visibility *VisibilityValue `url:"visibility,omitempty" json:"visibility,omitempty"`
132 LFSEnabled *bool `url:"lfs_enabled,omitempty" json:"lfs_enabled,omitempty"`
133 RequestAccessEnabled *bool `url:"request_access_enabled,omitempty" json:"request_access_enabled,omitempty"`
134 ParentID *int `url:"parent_id,omitempty" json:"parent_id,omitempty"`
135}
136
137// CreateGroup creates a new project group. Available only for users who can
138// create groups.
139//
140// GitLab API docs: https://docs.gitlab.com/ce/api/groups.html#new-group
141func (s *GroupsService) CreateGroup(opt *CreateGroupOptions, options ...OptionFunc) (*Group, *Response, error) {
142 req, err := s.client.NewRequest("POST", "groups", opt, options)
143 if err != nil {
144 return nil, nil, err
145 }
146
147 g := new(Group)
148 resp, err := s.client.Do(req, g)
149 if err != nil {
150 return nil, resp, err
151 }
152
153 return g, resp, err
154}
155
156// TransferGroup transfers a project to the Group namespace. Available only
157// for admin.
158//
159// GitLab API docs:
160// https://docs.gitlab.com/ce/api/groups.html#transfer-project-to-group
161func (s *GroupsService) TransferGroup(gid interface{}, pid interface{}, options ...OptionFunc) (*Group, *Response, error) {
162 group, err := parseID(gid)
163 if err != nil {
164 return nil, nil, err
165 }
166 project, err := parseID(pid)
167 if err != nil {
168 return nil, nil, err
169 }
170 u := fmt.Sprintf("groups/%s/projects/%s", pathEscape(group), pathEscape(project))
171
172 req, err := s.client.NewRequest("POST", u, nil, options)
173 if err != nil {
174 return nil, nil, err
175 }
176
177 g := new(Group)
178 resp, err := s.client.Do(req, g)
179 if err != nil {
180 return nil, resp, err
181 }
182
183 return g, resp, err
184}
185
186// UpdateGroupOptions represents the set of available options to update a Group;
187// as of today these are exactly the same available when creating a new Group.
188//
189// GitLab API docs: https://docs.gitlab.com/ce/api/groups.html#update-group
190type UpdateGroupOptions CreateGroupOptions
191
192// UpdateGroup updates an existing group; only available to group owners and
193// administrators.
194//
195// GitLab API docs: https://docs.gitlab.com/ce/api/groups.html#update-group
196func (s *GroupsService) UpdateGroup(gid interface{}, opt *UpdateGroupOptions, options ...OptionFunc) (*Group, *Response, error) {
197 group, err := parseID(gid)
198 if err != nil {
199 return nil, nil, err
200 }
201 u := fmt.Sprintf("groups/%s", pathEscape(group))
202
203 req, err := s.client.NewRequest("PUT", u, opt, options)
204 if err != nil {
205 return nil, nil, err
206 }
207
208 g := new(Group)
209 resp, err := s.client.Do(req, g)
210 if err != nil {
211 return nil, resp, err
212 }
213
214 return g, resp, err
215}
216
217// DeleteGroup removes group with all projects inside.
218//
219// GitLab API docs: https://docs.gitlab.com/ce/api/groups.html#remove-group
220func (s *GroupsService) DeleteGroup(gid interface{}, options ...OptionFunc) (*Response, error) {
221 group, err := parseID(gid)
222 if err != nil {
223 return nil, err
224 }
225 u := fmt.Sprintf("groups/%s", pathEscape(group))
226
227 req, err := s.client.NewRequest("DELETE", u, nil, options)
228 if err != nil {
229 return nil, err
230 }
231
232 return s.client.Do(req, nil)
233}
234
235// SearchGroup get all groups that match your string in their name or path.
236//
237// GitLab API docs: https://docs.gitlab.com/ce/api/groups.html#search-for-group
238func (s *GroupsService) SearchGroup(query string, options ...OptionFunc) ([]*Group, *Response, error) {
239 var q struct {
240 Search string `url:"search,omitempty" json:"search,omitempty"`
241 }
242 q.Search = query
243
244 req, err := s.client.NewRequest("GET", "groups", &q, options)
245 if err != nil {
246 return nil, nil, err
247 }
248
249 var g []*Group
250 resp, err := s.client.Do(req, &g)
251 if err != nil {
252 return nil, resp, err
253 }
254
255 return g, resp, err
256}
257
258// ListGroupProjectsOptions represents the available ListGroupProjects()
259// options.
260//
261// GitLab API docs:
262// https://docs.gitlab.com/ce/api/groups.html#list-a-group-39-s-projects
263type ListGroupProjectsOptions struct {
264 ListOptions
265 Archived *bool `url:"archived,omitempty" json:"archived,omitempty"`
266 Visibility *VisibilityValue `url:"visibility,omitempty" json:"visibility,omitempty"`
267 OrderBy *string `url:"order_by,omitempty" json:"order_by,omitempty"`
268 Sort *string `url:"sort,omitempty" json:"sort,omitempty"`
269 Search *string `url:"search,omitempty" json:"search,omitempty"`
270 Simple *bool `url:"simple,omitempty" json:"simple,omitempty"`
271 Owned *bool `url:"owned,omitempty" json:"owned,omitempty"`
272 Starred *bool `url:"starred,omitempty" json:"starred,omitempty"`
273 WithIssuesEnabled *bool `url:"with_issues_enabled,omitempty" json:"with_issues_enabled,omitempty"`
274 WithMergeRequestsEnabled *bool `url:"with_merge_requests_enabled,omitempty" json:"with_merge_requests_enabled,omitempty"`
275 WithShared *bool `url:"with_shared,omitempty" json:"with_shared,omitempty"`
276 IncludeSubgroups *bool `url:"include_subgroups,omitempty" json:"include_subgroups,omitempty"`
277 WithCustomAttributes *bool `url:"with_custom_attributes,omitempty" json:"with_custom_attributes,omitempty"`
278}
279
280// ListGroupProjects get a list of group projects
281//
282// GitLab API docs:
283// https://docs.gitlab.com/ce/api/groups.html#list-a-group-39-s-projects
284func (s *GroupsService) ListGroupProjects(gid interface{}, opt *ListGroupProjectsOptions, options ...OptionFunc) ([]*Project, *Response, error) {
285 group, err := parseID(gid)
286 if err != nil {
287 return nil, nil, err
288 }
289 u := fmt.Sprintf("groups/%s/projects", pathEscape(group))
290
291 req, err := s.client.NewRequest("GET", u, opt, options)
292 if err != nil {
293 return nil, nil, err
294 }
295
296 var p []*Project
297 resp, err := s.client.Do(req, &p)
298 if err != nil {
299 return nil, resp, err
300 }
301
302 return p, resp, err
303}
304
305// ListSubgroupsOptions represents the available ListSubgroupsOptions()
306// options.
307//
308// GitLab API docs:
309// https://docs.gitlab.com/ce/api/groups.html#list-a-groups-s-subgroups
310type ListSubgroupsOptions ListGroupsOptions
311
312// ListSubgroups gets a list of subgroups for a given project.
313//
314// GitLab API docs:
315// https://docs.gitlab.com/ce/api/groups.html#list-a-groups-s-subgroups
316func (s *GroupsService) ListSubgroups(gid interface{}, opt *ListSubgroupsOptions, options ...OptionFunc) ([]*Group, *Response, error) {
317 group, err := parseID(gid)
318 if err != nil {
319 return nil, nil, err
320 }
321 u := fmt.Sprintf("groups/%s/subgroups", pathEscape(group))
322
323 req, err := s.client.NewRequest("GET", u, opt, options)
324 if err != nil {
325 return nil, nil, err
326 }
327
328 var g []*Group
329 resp, err := s.client.Do(req, &g)
330 if err != nil {
331 return nil, resp, err
332 }
333
334 return g, resp, err
335}