users.go

  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	"errors"
 21	"fmt"
 22	"time"
 23)
 24
 25// List a couple of standard errors.
 26var (
 27	ErrUserBlockPrevented   = errors.New("Cannot block a user that is already blocked by LDAP synchronization")
 28	ErrUserNotFound         = errors.New("User does not exist")
 29	ErrUserUnblockPrevented = errors.New("Cannot unblock a user that is blocked by LDAP synchronization")
 30)
 31
 32// UsersService handles communication with the user related methods of
 33// the GitLab API.
 34//
 35// GitLab API docs: https://docs.gitlab.com/ce/api/users.html
 36type UsersService struct {
 37	client *Client
 38}
 39
 40// User represents a GitLab user.
 41//
 42// GitLab API docs: https://docs.gitlab.com/ee/api/users.html
 43type User struct {
 44	ID                        int                `json:"id"`
 45	Username                  string             `json:"username"`
 46	Email                     string             `json:"email"`
 47	Name                      string             `json:"name"`
 48	State                     string             `json:"state"`
 49	CreatedAt                 *time.Time         `json:"created_at"`
 50	Bio                       string             `json:"bio"`
 51	Location                  string             `json:"location"`
 52	PublicEmail               string             `json:"public_email"`
 53	Skype                     string             `json:"skype"`
 54	Linkedin                  string             `json:"linkedin"`
 55	Twitter                   string             `json:"twitter"`
 56	WebsiteURL                string             `json:"website_url"`
 57	Organization              string             `json:"organization"`
 58	ExternUID                 string             `json:"extern_uid"`
 59	Provider                  string             `json:"provider"`
 60	ThemeID                   int                `json:"theme_id"`
 61	LastActivityOn            *ISOTime           `json:"last_activity_on"`
 62	ColorSchemeID             int                `json:"color_scheme_id"`
 63	IsAdmin                   bool               `json:"is_admin"`
 64	AvatarURL                 string             `json:"avatar_url"`
 65	CanCreateGroup            bool               `json:"can_create_group"`
 66	CanCreateProject          bool               `json:"can_create_project"`
 67	ProjectsLimit             int                `json:"projects_limit"`
 68	CurrentSignInAt           *time.Time         `json:"current_sign_in_at"`
 69	LastSignInAt              *time.Time         `json:"last_sign_in_at"`
 70	ConfirmedAt               *time.Time         `json:"confirmed_at"`
 71	TwoFactorEnabled          bool               `json:"two_factor_enabled"`
 72	Identities                []*UserIdentity    `json:"identities"`
 73	External                  bool               `json:"external"`
 74	PrivateProfile            bool               `json:"private_profile"`
 75	SharedRunnersMinutesLimit int                `json:"shared_runners_minutes_limit"`
 76	CustomAttributes          []*CustomAttribute `json:"custom_attributes"`
 77}
 78
 79// UserIdentity represents a user identity.
 80type UserIdentity struct {
 81	Provider  string `json:"provider"`
 82	ExternUID string `json:"extern_uid"`
 83}
 84
 85// ListUsersOptions represents the available ListUsers() options.
 86//
 87// GitLab API docs: https://docs.gitlab.com/ce/api/users.html#list-users
 88type ListUsersOptions struct {
 89	ListOptions
 90	Active  *bool `url:"active,omitempty" json:"active,omitempty"`
 91	Blocked *bool `url:"blocked,omitempty" json:"blocked,omitempty"`
 92
 93	// The options below are only available for admins.
 94	Search               *string    `url:"search,omitempty" json:"search,omitempty"`
 95	Username             *string    `url:"username,omitempty" json:"username,omitempty"`
 96	ExternalUID          *string    `url:"extern_uid,omitempty" json:"extern_uid,omitempty"`
 97	Provider             *string    `url:"provider,omitempty" json:"provider,omitempty"`
 98	CreatedBefore        *time.Time `url:"created_before,omitempty" json:"created_before,omitempty"`
 99	CreatedAfter         *time.Time `url:"created_after,omitempty" json:"created_after,omitempty"`
100	OrderBy              *string    `url:"order_by,omitempty" json:"order_by,omitempty"`
101	Sort                 *string    `url:"sort,omitempty" json:"sort,omitempty"`
102	WithCustomAttributes *bool      `url:"with_custom_attributes,omitempty" json:"with_custom_attributes,omitempty"`
103}
104
105// ListUsers gets a list of users.
106//
107// GitLab API docs: https://docs.gitlab.com/ce/api/users.html#list-users
108func (s *UsersService) ListUsers(opt *ListUsersOptions, options ...OptionFunc) ([]*User, *Response, error) {
109	req, err := s.client.NewRequest("GET", "users", opt, options)
110	if err != nil {
111		return nil, nil, err
112	}
113
114	var usr []*User
115	resp, err := s.client.Do(req, &usr)
116	if err != nil {
117		return nil, resp, err
118	}
119
120	return usr, resp, err
121}
122
123// GetUser gets a single user.
124//
125// GitLab API docs: https://docs.gitlab.com/ce/api/users.html#single-user
126func (s *UsersService) GetUser(user int, options ...OptionFunc) (*User, *Response, error) {
127	u := fmt.Sprintf("users/%d", user)
128
129	req, err := s.client.NewRequest("GET", u, nil, options)
130	if err != nil {
131		return nil, nil, err
132	}
133
134	usr := new(User)
135	resp, err := s.client.Do(req, usr)
136	if err != nil {
137		return nil, resp, err
138	}
139
140	return usr, resp, err
141}
142
143// CreateUserOptions represents the available CreateUser() options.
144//
145// GitLab API docs: https://docs.gitlab.com/ce/api/users.html#user-creation
146type CreateUserOptions struct {
147	Email            *string `url:"email,omitempty" json:"email,omitempty"`
148	Password         *string `url:"password,omitempty" json:"password,omitempty"`
149	ResetPassword    *bool   `url:"reset_password,omitempty" json:"reset_password,omitempty"`
150	Username         *string `url:"username,omitempty" json:"username,omitempty"`
151	Name             *string `url:"name,omitempty" json:"name,omitempty"`
152	Skype            *string `url:"skype,omitempty" json:"skype,omitempty"`
153	Linkedin         *string `url:"linkedin,omitempty" json:"linkedin,omitempty"`
154	Twitter          *string `url:"twitter,omitempty" json:"twitter,omitempty"`
155	WebsiteURL       *string `url:"website_url,omitempty" json:"website_url,omitempty"`
156	Organization     *string `url:"organization,omitempty" json:"organization,omitempty"`
157	ProjectsLimit    *int    `url:"projects_limit,omitempty" json:"projects_limit,omitempty"`
158	ExternUID        *string `url:"extern_uid,omitempty" json:"extern_uid,omitempty"`
159	Provider         *string `url:"provider,omitempty" json:"provider,omitempty"`
160	Bio              *string `url:"bio,omitempty" json:"bio,omitempty"`
161	Location         *string `url:"location,omitempty" json:"location,omitempty"`
162	Admin            *bool   `url:"admin,omitempty" json:"admin,omitempty"`
163	CanCreateGroup   *bool   `url:"can_create_group,omitempty" json:"can_create_group,omitempty"`
164	SkipConfirmation *bool   `url:"skip_confirmation,omitempty" json:"skip_confirmation,omitempty"`
165	External         *bool   `url:"external,omitempty" json:"external,omitempty"`
166}
167
168// CreateUser creates a new user. Note only administrators can create new users.
169//
170// GitLab API docs: https://docs.gitlab.com/ce/api/users.html#user-creation
171func (s *UsersService) CreateUser(opt *CreateUserOptions, options ...OptionFunc) (*User, *Response, error) {
172	req, err := s.client.NewRequest("POST", "users", opt, options)
173	if err != nil {
174		return nil, nil, err
175	}
176
177	usr := new(User)
178	resp, err := s.client.Do(req, usr)
179	if err != nil {
180		return nil, resp, err
181	}
182
183	return usr, resp, err
184}
185
186// ModifyUserOptions represents the available ModifyUser() options.
187//
188// GitLab API docs: https://docs.gitlab.com/ce/api/users.html#user-modification
189type ModifyUserOptions struct {
190	Email              *string `url:"email,omitempty" json:"email,omitempty"`
191	Password           *string `url:"password,omitempty" json:"password,omitempty"`
192	Username           *string `url:"username,omitempty" json:"username,omitempty"`
193	Name               *string `url:"name,omitempty" json:"name,omitempty"`
194	Skype              *string `url:"skype,omitempty" json:"skype,omitempty"`
195	Linkedin           *string `url:"linkedin,omitempty" json:"linkedin,omitempty"`
196	Twitter            *string `url:"twitter,omitempty" json:"twitter,omitempty"`
197	WebsiteURL         *string `url:"website_url,omitempty" json:"website_url,omitempty"`
198	Organization       *string `url:"organization,omitempty" json:"organization,omitempty"`
199	ProjectsLimit      *int    `url:"projects_limit,omitempty" json:"projects_limit,omitempty"`
200	ExternUID          *string `url:"extern_uid,omitempty" json:"extern_uid,omitempty"`
201	Provider           *string `url:"provider,omitempty" json:"provider,omitempty"`
202	Bio                *string `url:"bio,omitempty" json:"bio,omitempty"`
203	Location           *string `url:"location,omitempty" json:"location,omitempty"`
204	Admin              *bool   `url:"admin,omitempty" json:"admin,omitempty"`
205	CanCreateGroup     *bool   `url:"can_create_group,omitempty" json:"can_create_group,omitempty"`
206	SkipReconfirmation *bool   `url:"skip_reconfirmation,omitempty" json:"skip_reconfirmation,omitempty"`
207	External           *bool   `url:"external,omitempty" json:"external,omitempty"`
208}
209
210// ModifyUser modifies an existing user. Only administrators can change attributes
211// of a user.
212//
213// GitLab API docs: https://docs.gitlab.com/ce/api/users.html#user-modification
214func (s *UsersService) ModifyUser(user int, opt *ModifyUserOptions, options ...OptionFunc) (*User, *Response, error) {
215	u := fmt.Sprintf("users/%d", user)
216
217	req, err := s.client.NewRequest("PUT", u, opt, options)
218	if err != nil {
219		return nil, nil, err
220	}
221
222	usr := new(User)
223	resp, err := s.client.Do(req, usr)
224	if err != nil {
225		return nil, resp, err
226	}
227
228	return usr, resp, err
229}
230
231// DeleteUser deletes a user. Available only for administrators. This is an
232// idempotent function, calling this function for a non-existent user id still
233// returns a status code 200 OK. The JSON response differs if the user was
234// actually deleted or not. In the former the user is returned and in the
235// latter not.
236//
237// GitLab API docs: https://docs.gitlab.com/ce/api/users.html#user-deletion
238func (s *UsersService) DeleteUser(user int, options ...OptionFunc) (*Response, error) {
239	u := fmt.Sprintf("users/%d", user)
240
241	req, err := s.client.NewRequest("DELETE", u, nil, options)
242	if err != nil {
243		return nil, err
244	}
245
246	return s.client.Do(req, nil)
247}
248
249// CurrentUser gets currently authenticated user.
250//
251// GitLab API docs: https://docs.gitlab.com/ce/api/users.html#current-user
252func (s *UsersService) CurrentUser(options ...OptionFunc) (*User, *Response, error) {
253	req, err := s.client.NewRequest("GET", "user", nil, options)
254	if err != nil {
255		return nil, nil, err
256	}
257
258	usr := new(User)
259	resp, err := s.client.Do(req, usr)
260	if err != nil {
261		return nil, resp, err
262	}
263
264	return usr, resp, err
265}
266
267// SSHKey represents a SSH key.
268//
269// GitLab API docs: https://docs.gitlab.com/ce/api/users.html#list-ssh-keys
270type SSHKey struct {
271	ID        int        `json:"id"`
272	Title     string     `json:"title"`
273	Key       string     `json:"key"`
274	CreatedAt *time.Time `json:"created_at"`
275}
276
277// ListSSHKeys gets a list of currently authenticated user's SSH keys.
278//
279// GitLab API docs: https://docs.gitlab.com/ce/api/users.html#list-ssh-keys
280func (s *UsersService) ListSSHKeys(options ...OptionFunc) ([]*SSHKey, *Response, error) {
281	req, err := s.client.NewRequest("GET", "user/keys", nil, options)
282	if err != nil {
283		return nil, nil, err
284	}
285
286	var k []*SSHKey
287	resp, err := s.client.Do(req, &k)
288	if err != nil {
289		return nil, resp, err
290	}
291
292	return k, resp, err
293}
294
295// ListSSHKeysForUserOptions represents the available ListSSHKeysForUser() options.
296//
297// GitLab API docs:
298// https://docs.gitlab.com/ce/api/users.html#list-ssh-keys-for-user
299type ListSSHKeysForUserOptions ListOptions
300
301// ListSSHKeysForUser gets a list of a specified user's SSH keys. Available
302// only for admin
303//
304// GitLab API docs:
305// https://docs.gitlab.com/ce/api/users.html#list-ssh-keys-for-user
306func (s *UsersService) ListSSHKeysForUser(user int, opt *ListSSHKeysForUserOptions, options ...OptionFunc) ([]*SSHKey, *Response, error) {
307	u := fmt.Sprintf("users/%d/keys", user)
308
309	req, err := s.client.NewRequest("GET", u, opt, options)
310	if err != nil {
311		return nil, nil, err
312	}
313
314	var k []*SSHKey
315	resp, err := s.client.Do(req, &k)
316	if err != nil {
317		return nil, resp, err
318	}
319
320	return k, resp, err
321}
322
323// GetSSHKey gets a single key.
324//
325// GitLab API docs: https://docs.gitlab.com/ce/api/users.html#single-ssh-key
326func (s *UsersService) GetSSHKey(key int, options ...OptionFunc) (*SSHKey, *Response, error) {
327	u := fmt.Sprintf("user/keys/%d", key)
328
329	req, err := s.client.NewRequest("GET", u, nil, options)
330	if err != nil {
331		return nil, nil, err
332	}
333
334	k := new(SSHKey)
335	resp, err := s.client.Do(req, k)
336	if err != nil {
337		return nil, resp, err
338	}
339
340	return k, resp, err
341}
342
343// AddSSHKeyOptions represents the available AddSSHKey() options.
344//
345// GitLab API docs: https://docs.gitlab.com/ce/api/projects.html#add-ssh-key
346type AddSSHKeyOptions struct {
347	Title *string `url:"title,omitempty" json:"title,omitempty"`
348	Key   *string `url:"key,omitempty" json:"key,omitempty"`
349}
350
351// AddSSHKey creates a new key owned by the currently authenticated user.
352//
353// GitLab API docs: https://docs.gitlab.com/ce/api/users.html#add-ssh-key
354func (s *UsersService) AddSSHKey(opt *AddSSHKeyOptions, options ...OptionFunc) (*SSHKey, *Response, error) {
355	req, err := s.client.NewRequest("POST", "user/keys", opt, options)
356	if err != nil {
357		return nil, nil, err
358	}
359
360	k := new(SSHKey)
361	resp, err := s.client.Do(req, k)
362	if err != nil {
363		return nil, resp, err
364	}
365
366	return k, resp, err
367}
368
369// AddSSHKeyForUser creates new key owned by specified user. Available only for
370// admin.
371//
372// GitLab API docs: https://docs.gitlab.com/ce/api/users.html#add-ssh-key-for-user
373func (s *UsersService) AddSSHKeyForUser(user int, opt *AddSSHKeyOptions, options ...OptionFunc) (*SSHKey, *Response, error) {
374	u := fmt.Sprintf("users/%d/keys", user)
375
376	req, err := s.client.NewRequest("POST", u, opt, options)
377	if err != nil {
378		return nil, nil, err
379	}
380
381	k := new(SSHKey)
382	resp, err := s.client.Do(req, k)
383	if err != nil {
384		return nil, resp, err
385	}
386
387	return k, resp, err
388}
389
390// DeleteSSHKey deletes key owned by currently authenticated user. This is an
391// idempotent function and calling it on a key that is already deleted or not
392// available results in 200 OK.
393//
394// GitLab API docs:
395// https://docs.gitlab.com/ce/api/users.html#delete-ssh-key-for-current-owner
396func (s *UsersService) DeleteSSHKey(key int, options ...OptionFunc) (*Response, error) {
397	u := fmt.Sprintf("user/keys/%d", key)
398
399	req, err := s.client.NewRequest("DELETE", u, nil, options)
400	if err != nil {
401		return nil, err
402	}
403
404	return s.client.Do(req, nil)
405}
406
407// DeleteSSHKeyForUser deletes key owned by a specified user. Available only
408// for admin.
409//
410// GitLab API docs:
411// https://docs.gitlab.com/ce/api/users.html#delete-ssh-key-for-given-user
412func (s *UsersService) DeleteSSHKeyForUser(user, key int, options ...OptionFunc) (*Response, error) {
413	u := fmt.Sprintf("users/%d/keys/%d", user, key)
414
415	req, err := s.client.NewRequest("DELETE", u, nil, options)
416	if err != nil {
417		return nil, err
418	}
419
420	return s.client.Do(req, nil)
421}
422
423// BlockUser blocks the specified user. Available only for admin.
424//
425// GitLab API docs: https://docs.gitlab.com/ce/api/users.html#block-user
426func (s *UsersService) BlockUser(user int, options ...OptionFunc) error {
427	u := fmt.Sprintf("users/%d/block", user)
428
429	req, err := s.client.NewRequest("POST", u, nil, options)
430	if err != nil {
431		return err
432	}
433
434	resp, err := s.client.Do(req, nil)
435	if err != nil && resp == nil {
436		return err
437	}
438
439	switch resp.StatusCode {
440	case 201:
441		return nil
442	case 403:
443		return ErrUserBlockPrevented
444	case 404:
445		return ErrUserNotFound
446	default:
447		return fmt.Errorf("Received unexpected result code: %d", resp.StatusCode)
448	}
449}
450
451// UnblockUser unblocks the specified user. Available only for admin.
452//
453// GitLab API docs: https://docs.gitlab.com/ce/api/users.html#unblock-user
454func (s *UsersService) UnblockUser(user int, options ...OptionFunc) error {
455	u := fmt.Sprintf("users/%d/unblock", user)
456
457	req, err := s.client.NewRequest("POST", u, nil, options)
458	if err != nil {
459		return err
460	}
461
462	resp, err := s.client.Do(req, nil)
463	if err != nil && resp == nil {
464		return err
465	}
466
467	switch resp.StatusCode {
468	case 201:
469		return nil
470	case 403:
471		return ErrUserUnblockPrevented
472	case 404:
473		return ErrUserNotFound
474	default:
475		return fmt.Errorf("Received unexpected result code: %d", resp.StatusCode)
476	}
477}
478
479// Email represents an Email.
480//
481// GitLab API docs: https://doc.gitlab.com/ce/api/users.html#list-emails
482type Email struct {
483	ID    int    `json:"id"`
484	Email string `json:"email"`
485}
486
487// ListEmails gets a list of currently authenticated user's Emails.
488//
489// GitLab API docs: https://docs.gitlab.com/ce/api/users.html#list-emails
490func (s *UsersService) ListEmails(options ...OptionFunc) ([]*Email, *Response, error) {
491	req, err := s.client.NewRequest("GET", "user/emails", nil, options)
492	if err != nil {
493		return nil, nil, err
494	}
495
496	var e []*Email
497	resp, err := s.client.Do(req, &e)
498	if err != nil {
499		return nil, resp, err
500	}
501
502	return e, resp, err
503}
504
505// ListEmailsForUserOptions represents the available ListEmailsForUser() options.
506//
507// GitLab API docs:
508// https://docs.gitlab.com/ce/api/users.html#list-emails-for-user
509type ListEmailsForUserOptions ListOptions
510
511// ListEmailsForUser gets a list of a specified user's Emails. Available
512// only for admin
513//
514// GitLab API docs:
515// https://docs.gitlab.com/ce/api/users.html#list-emails-for-user
516func (s *UsersService) ListEmailsForUser(user int, opt *ListEmailsForUserOptions, options ...OptionFunc) ([]*Email, *Response, error) {
517	u := fmt.Sprintf("users/%d/emails", user)
518
519	req, err := s.client.NewRequest("GET", u, opt, options)
520	if err != nil {
521		return nil, nil, err
522	}
523
524	var e []*Email
525	resp, err := s.client.Do(req, &e)
526	if err != nil {
527		return nil, resp, err
528	}
529
530	return e, resp, err
531}
532
533// GetEmail gets a single email.
534//
535// GitLab API docs: https://docs.gitlab.com/ce/api/users.html#single-email
536func (s *UsersService) GetEmail(email int, options ...OptionFunc) (*Email, *Response, error) {
537	u := fmt.Sprintf("user/emails/%d", email)
538
539	req, err := s.client.NewRequest("GET", u, nil, options)
540	if err != nil {
541		return nil, nil, err
542	}
543
544	e := new(Email)
545	resp, err := s.client.Do(req, e)
546	if err != nil {
547		return nil, resp, err
548	}
549
550	return e, resp, err
551}
552
553// AddEmailOptions represents the available AddEmail() options.
554//
555// GitLab API docs: https://docs.gitlab.com/ce/api/projects.html#add-email
556type AddEmailOptions struct {
557	Email *string `url:"email,omitempty" json:"email,omitempty"`
558}
559
560// AddEmail creates a new email owned by the currently authenticated user.
561//
562// GitLab API docs: https://docs.gitlab.com/ce/api/users.html#add-email
563func (s *UsersService) AddEmail(opt *AddEmailOptions, options ...OptionFunc) (*Email, *Response, error) {
564	req, err := s.client.NewRequest("POST", "user/emails", opt, options)
565	if err != nil {
566		return nil, nil, err
567	}
568
569	e := new(Email)
570	resp, err := s.client.Do(req, e)
571	if err != nil {
572		return nil, resp, err
573	}
574
575	return e, resp, err
576}
577
578// AddEmailForUser creates new email owned by specified user. Available only for
579// admin.
580//
581// GitLab API docs: https://docs.gitlab.com/ce/api/users.html#add-email-for-user
582func (s *UsersService) AddEmailForUser(user int, opt *AddEmailOptions, options ...OptionFunc) (*Email, *Response, error) {
583	u := fmt.Sprintf("users/%d/emails", user)
584
585	req, err := s.client.NewRequest("POST", u, opt, options)
586	if err != nil {
587		return nil, nil, err
588	}
589
590	e := new(Email)
591	resp, err := s.client.Do(req, e)
592	if err != nil {
593		return nil, resp, err
594	}
595
596	return e, resp, err
597}
598
599// DeleteEmail deletes email owned by currently authenticated user. This is an
600// idempotent function and calling it on a key that is already deleted or not
601// available results in 200 OK.
602//
603// GitLab API docs:
604// https://docs.gitlab.com/ce/api/users.html#delete-email-for-current-owner
605func (s *UsersService) DeleteEmail(email int, options ...OptionFunc) (*Response, error) {
606	u := fmt.Sprintf("user/emails/%d", email)
607
608	req, err := s.client.NewRequest("DELETE", u, nil, options)
609	if err != nil {
610		return nil, err
611	}
612
613	return s.client.Do(req, nil)
614}
615
616// DeleteEmailForUser deletes email owned by a specified user. Available only
617// for admin.
618//
619// GitLab API docs:
620// https://docs.gitlab.com/ce/api/users.html#delete-email-for-given-user
621func (s *UsersService) DeleteEmailForUser(user, email int, options ...OptionFunc) (*Response, error) {
622	u := fmt.Sprintf("users/%d/emails/%d", user, email)
623
624	req, err := s.client.NewRequest("DELETE", u, nil, options)
625	if err != nil {
626		return nil, err
627	}
628
629	return s.client.Do(req, nil)
630}
631
632// ImpersonationToken represents an impersonation token.
633//
634// GitLab API docs:
635// https://docs.gitlab.com/ce/api/users.html#get-all-impersonation-tokens-of-a-user
636type ImpersonationToken struct {
637	ID        int        `json:"id"`
638	Name      string     `json:"name"`
639	Active    bool       `json:"active"`
640	Token     string     `json:"token"`
641	Scopes    []string   `json:"scopes"`
642	Revoked   bool       `json:"revoked"`
643	CreatedAt *time.Time `json:"created_at"`
644	ExpiresAt *ISOTime   `json:"expires_at"`
645}
646
647// GetAllImpersonationTokensOptions represents the available
648// GetAllImpersonationTokens() options.
649//
650// GitLab API docs:
651// https://docs.gitlab.com/ce/api/users.html#get-all-impersonation-tokens-of-a-user
652type GetAllImpersonationTokensOptions struct {
653	ListOptions
654	State *string `url:"state,omitempty" json:"state,omitempty"`
655}
656
657// GetAllImpersonationTokens retrieves all impersonation tokens of a user.
658//
659// GitLab API docs:
660// https://docs.gitlab.com/ce/api/users.html#get-all-impersonation-tokens-of-a-user
661func (s *UsersService) GetAllImpersonationTokens(user int, opt *GetAllImpersonationTokensOptions, options ...OptionFunc) ([]*ImpersonationToken, *Response, error) {
662	u := fmt.Sprintf("users/%d/impersonation_tokens", user)
663
664	req, err := s.client.NewRequest("GET", u, opt, options)
665	if err != nil {
666		return nil, nil, err
667	}
668
669	var ts []*ImpersonationToken
670	resp, err := s.client.Do(req, &ts)
671	if err != nil {
672		return nil, resp, err
673	}
674
675	return ts, resp, err
676}
677
678// GetImpersonationToken retrieves an impersonation token of a user.
679//
680// GitLab API docs:
681// https://docs.gitlab.com/ce/api/users.html#get-an-impersonation-token-of-a-user
682func (s *UsersService) GetImpersonationToken(user, token int, options ...OptionFunc) (*ImpersonationToken, *Response, error) {
683	u := fmt.Sprintf("users/%d/impersonation_tokens/%d", user, token)
684
685	req, err := s.client.NewRequest("GET", u, nil, options)
686	if err != nil {
687		return nil, nil, err
688	}
689
690	t := new(ImpersonationToken)
691	resp, err := s.client.Do(req, &t)
692	if err != nil {
693		return nil, resp, err
694	}
695
696	return t, resp, err
697}
698
699// CreateImpersonationTokenOptions represents the available
700// CreateImpersonationToken() options.
701//
702// GitLab API docs:
703// https://docs.gitlab.com/ce/api/users.html#create-an-impersonation-token
704type CreateImpersonationTokenOptions struct {
705	Name      *string    `url:"name,omitempty" json:"name,omitempty"`
706	Scopes    *[]string  `url:"scopes,omitempty" json:"scopes,omitempty"`
707	ExpiresAt *time.Time `url:"expires_at,omitempty" json:"expires_at,omitempty"`
708}
709
710// CreateImpersonationToken creates an impersonation token.
711//
712// GitLab API docs:
713// https://docs.gitlab.com/ce/api/users.html#create-an-impersonation-token
714func (s *UsersService) CreateImpersonationToken(user int, opt *CreateImpersonationTokenOptions, options ...OptionFunc) (*ImpersonationToken, *Response, error) {
715	u := fmt.Sprintf("users/%d/impersonation_tokens", user)
716
717	req, err := s.client.NewRequest("POST", u, opt, options)
718	if err != nil {
719		return nil, nil, err
720	}
721
722	t := new(ImpersonationToken)
723	resp, err := s.client.Do(req, &t)
724	if err != nil {
725		return nil, resp, err
726	}
727
728	return t, resp, err
729}
730
731// RevokeImpersonationToken revokes an impersonation token.
732//
733// GitLab API docs:
734// https://docs.gitlab.com/ce/api/users.html#revoke-an-impersonation-token
735func (s *UsersService) RevokeImpersonationToken(user, token int, options ...OptionFunc) (*Response, error) {
736	u := fmt.Sprintf("users/%d/impersonation_tokens/%d", user, token)
737
738	req, err := s.client.NewRequest("DELETE", u, nil, options)
739	if err != nil {
740		return nil, err
741	}
742
743	return s.client.Do(req, nil)
744}
745
746// UserActivity represents an entry in the user/activities response
747//
748// GitLab API docs:
749// https://docs.gitlab.com/ce/api/users.html#get-user-activities-admin-only
750type UserActivity struct {
751	Username       string   `json:"username"`
752	LastActivityOn *ISOTime `json:"last_activity_on"`
753}
754
755// GetUserActivitiesOptions represents the options for GetUserActivities
756//
757// GitLap API docs:
758// https://docs.gitlab.com/ce/api/users.html#get-user-activities-admin-only
759type GetUserActivitiesOptions struct {
760	From *ISOTime `url:"from,omitempty" json:"from,omitempty"`
761}
762
763// GetUserActivities retrieves user activities (admin only)
764//
765// GitLab API docs:
766// https://docs.gitlab.com/ce/api/users.html#get-user-activities-admin-only
767func (s *UsersService) GetUserActivities(opt *GetUserActivitiesOptions, options ...OptionFunc) ([]*UserActivity, *Response, error) {
768	req, err := s.client.NewRequest("GET", "user/activities", opt, options)
769	if err != nil {
770		return nil, nil, err
771	}
772
773	var t []*UserActivity
774	resp, err := s.client.Do(req, &t)
775	if err != nil {
776		return nil, resp, err
777	}
778
779	return t, resp, err
780}
781
782// UserStatus represents the current status of a user
783//
784// GitLab API docs:
785// https://docs.gitlab.com/ce/api/users.html#user-status
786type UserStatus struct {
787	Emoji       string `json:"emoji"`
788	Message     string `json:"message"`
789	MessageHTML string `json:"message_html"`
790}
791
792// CurrentUserStatus retrieves the user status
793//
794// GitLab API docs:
795// https://docs.gitlab.com/ce/api/users.html#user-status
796func (s *UsersService) CurrentUserStatus(options ...OptionFunc) (*UserStatus, *Response, error) {
797	req, err := s.client.NewRequest("GET", "user/status", nil, options)
798	if err != nil {
799		return nil, nil, err
800	}
801
802	status := new(UserStatus)
803	resp, err := s.client.Do(req, status)
804	if err != nil {
805		return nil, resp, err
806	}
807
808	return status, resp, err
809}
810
811// GetUserStatus retrieves a user's status
812//
813// GitLab API docs:
814// https://docs.gitlab.com/ce/api/users.html#get-the-status-of-a-user
815func (s *UsersService) GetUserStatus(user int, options ...OptionFunc) (*UserStatus, *Response, error) {
816	u := fmt.Sprintf("users/%d/status", user)
817
818	req, err := s.client.NewRequest("GET", u, nil, options)
819	if err != nil {
820		return nil, nil, err
821	}
822
823	status := new(UserStatus)
824	resp, err := s.client.Do(req, status)
825	if err != nil {
826		return nil, resp, err
827	}
828
829	return status, resp, err
830}
831
832// UserStatusOptions represents the options required to set the status
833//
834// GitLab API docs:
835// https://docs.gitlab.com/ce/api/users.html#set-user-status
836type UserStatusOptions struct {
837	Emoji   *string `url:"emoji,omitempty" json:"emoji,omitempty"`
838	Message *string `url:"message,omitempty" json:"message,omitempty"`
839}
840
841// SetUserStatus sets the user's status
842//
843// GitLab API docs:
844// https://docs.gitlab.com/ce/api/users.html#set-user-status
845func (s *UsersService) SetUserStatus(opt *UserStatusOptions, options ...OptionFunc) (*UserStatus, *Response, error) {
846	req, err := s.client.NewRequest("PUT", "user/status", opt, options)
847	if err != nil {
848		return nil, nil, err
849	}
850
851	status := new(UserStatus)
852	resp, err := s.client.Do(req, status)
853	if err != nil {
854		return nil, resp, err
855	}
856
857	return status, resp, err
858}