Repository: xanzy/go-gitlab
Pull request #756 (2020-01-07 19:01:58)

implements user activate/deactivate features
From GitLab 12.4 it is now possible to deactivate a user.
See https://docs.gitlab.com/ce/user/admin_area/activating_deactivating_users.html#deactivating-a-user
for more details.

This commit implements the matching API entries:
* deactivate: https://docs.gitlab.com/ce/api/users.html#deactivate-user
* activate: https://docs.gitlab.com/ce/api/users.html#activate-user


Patch:
diff --git a/users.go b/users.go
index c8015cd..5917a0a 100644
--- a/users.go
+++ b/users.go
@@ -24,9 +24,11 @@ import (
 
 // List a couple of standard errors.
 var (
-	ErrUserBlockPrevented   = errors.New("Cannot block a user that is already blocked by LDAP synchronization")
-	ErrUserNotFound         = errors.New("User does not exist")
-	ErrUserUnblockPrevented = errors.New("Cannot unblock a user that is blocked by LDAP synchronization")
+	ErrUserActivatePrevented   = errors.New("Cannot activate a user that is blocked by admin or by LDAP synchronization")
+	ErrUserBlockPrevented      = errors.New("Cannot block a user that is already blocked by LDAP synchronization")
+	ErrUserDeactivatePrevented = errors.New("Cannot deactivate a user that is blocked by admin or by LDAP synchronization, or that has any activity in past 180 days")
+	ErrUserNotFound            = errors.New("User does not exist")
+	ErrUserUnblockPrevented    = errors.New("Cannot unblock a user that is blocked by LDAP synchronization")
 )
 
 // UsersService handles communication with the user related methods of
@@ -489,6 +491,62 @@ func (s *UsersService) UnblockUser(user int, options ...OptionFunc) error {
 	}
 }
 
+// DeactivateUser deactivate the specified user. Available only for admin.
+//
+// GitLab API docs: https://docs.gitlab.com/ce/api/users.html#deactivate-user
+func (s *UsersService) DeactivateUser(user int, options ...OptionFunc) error {
+	u := fmt.Sprintf("users/%d/deactivate", user)
+
+	req, err := s.client.NewRequest("POST", u, nil, options)
+	if err != nil {
+		return err
+	}
+
+	resp, err := s.client.Do(req, nil)
+	if err != nil && resp == nil {
+		return err
+	}
+
+	switch resp.StatusCode {
+	case 201:
+		return nil
+	case 403:
+		return ErrUserDeactivatePrevented
+	case 404:
+		return ErrUserNotFound
+	default:
+		return fmt.Errorf("Received unexpected result code: %d", resp.StatusCode)
+	}
+}
+
+// ActivateUser activate the specified user. Available only for admin.
+//
+// GitLab API docs: https://docs.gitlab.com/ce/api/users.html#activate-user
+func (s *UsersService) ActivateUser(user int, options ...OptionFunc) error {
+	u := fmt.Sprintf("users/%d/activate", user)
+
+	req, err := s.client.NewRequest("POST", u, nil, options)
+	if err != nil {
+		return err
+	}
+
+	resp, err := s.client.Do(req, nil)
+	if err != nil && resp == nil {
+		return err
+	}
+
+	switch resp.StatusCode {
+	case 201:
+		return nil
+	case 403:
+		return ErrUserActivatePrevented
+	case 404:
+		return ErrUserNotFound
+	default:
+		return fmt.Errorf("Received unexpected result code: %d", resp.StatusCode)
+	}
+}
+
 // Email represents an Email.
 //
 // GitLab API docs: https://doc.gitlab.com/ce/api/users.html#list-emails


Test patch:
diff --git a/users_test.go b/users_test.go
index d777394..6022ea6 100644
--- a/users_test.go
+++ b/users_test.go
@@ -163,3 +163,99 @@ func TestUnblockUser_BadResponseFromNet(t *testing.T) {
 		t.Errorf("Users.UnblockUser error.\nExpected: %+v\n     Got: %+v", want, err)
 	}
 }
+
+func TestDeactivateUser(t *testing.T) {
+	mux, server, client := setup()
+	defer teardown(server)
+
+	path := fmt.Sprintf("/%susers/1/deactivate", apiVersionPath)
+	mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "POST")
+		w.WriteHeader(http.StatusCreated)
+	})
+
+	err := client.Users.DeactivateUser(1)
+	if err != nil {
+		t.Errorf("Users.DeactivateUser returned error: %v", err)
+	}
+}
+
+func TestDeactivateUser_UserNotFound(t *testing.T) {
+	mux, server, client := setup()
+	defer teardown(server)
+
+	path := fmt.Sprintf("/%susers/1/deactivate", apiVersionPath)
+	mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "POST")
+		w.WriteHeader(http.StatusNotFound)
+	})
+
+	err := client.Users.DeactivateUser(1)
+	if err != ErrUserNotFound {
+		t.Errorf("Users.DeactivateUser error.\nExpected: %+v\n     Got: %+v", ErrUserNotFound, err)
+	}
+}
+
+func TestDeactivateUser_DeactivatePrevented(t *testing.T) {
+	mux, server, client := setup()
+	defer teardown(server)
+
+	path := fmt.Sprintf("/%susers/1/deactivate", apiVersionPath)
+	mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "POST")
+		w.WriteHeader(http.StatusForbidden)
+	})
+
+	err := client.Users.DeactivateUser(1)
+	if err != ErrUserDeactivatePrevented {
+		t.Errorf("Users.DeactivateUser error.\nExpected: %+v\n     Got: %+v", ErrUserDeactivatePrevented, err)
+	}
+}
+
+func TestActivateUser(t *testing.T) {
+	mux, server, client := setup()
+	defer teardown(server)
+
+	path := fmt.Sprintf("/%susers/1/activate", apiVersionPath)
+	mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "POST")
+		w.WriteHeader(http.StatusCreated)
+	})
+
+	err := client.Users.ActivateUser(1)
+	if err != nil {
+		t.Errorf("Users.ActivateUser returned error: %v", err)
+	}
+}
+
+func TestActivateUser_ActivatePrevented(t *testing.T) {
+	mux, server, client := setup()
+	defer teardown(server)
+
+	path := fmt.Sprintf("/%susers/1/activate", apiVersionPath)
+	mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "POST")
+		w.WriteHeader(http.StatusForbidden)
+	})
+
+	err := client.Users.ActivateUser(1)
+	if err != ErrUserActivatePrevented {
+		t.Errorf("Users.ActivateUser error.\nExpected: %+v\n     Got: %+v", ErrUserActivatePrevented, err)
+	}
+}
+
+func TestActivateUser_UserNotFound(t *testing.T) {
+	mux, server, client := setup()
+	defer teardown(server)
+
+	path := fmt.Sprintf("/%susers/1/activate", apiVersionPath)
+	mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "POST")
+		w.WriteHeader(http.StatusNotFound)
+	})
+
+	err := client.Users.ActivateUser(1)
+	if err != ErrUserNotFound {
+		t.Errorf("Users.ActivateUser error.\nExpected: %+v\n     Got: %+v", ErrUserNotFound, err)
+	}
+}