diff --git a/docs/gl_objects/users.rst b/docs/gl_objects/users.rst index 01efefa7e..53b00e277 100644 --- a/docs/gl_objects/users.rst +++ b/docs/gl_objects/users.rst @@ -72,6 +72,11 @@ Activate/Deactivate a user:: user.activate() user.deactivate() +Ban/Unban a user:: + + user.ban() + user.unban() + Follow/Unfollow a user:: user.follow() diff --git a/gitlab/exceptions.py b/gitlab/exceptions.py index 3da399c54..251ef7b25 100644 --- a/gitlab/exceptions.py +++ b/gitlab/exceptions.py @@ -186,6 +186,14 @@ class GitlabActivateError(GitlabOperationError): pass +class GitlabBanError(GitlabOperationError): + pass + + +class GitlabUnbanError(GitlabOperationError): + pass + + class GitlabSubscribeError(GitlabOperationError): pass diff --git a/gitlab/v4/objects/users.py b/gitlab/v4/objects/users.py index acd3b2f76..9e76bd5d0 100644 --- a/gitlab/v4/objects/users.py +++ b/gitlab/v4/objects/users.py @@ -283,6 +283,48 @@ def activate(self, **kwargs: Any) -> Union[Dict[str, Any], requests.Response]: self._attrs["state"] = "active" return server_data + @cli.register_custom_action("User") + @exc.on_http_error(exc.GitlabBanError) + def ban(self, **kwargs: Any) -> Union[Dict[str, Any], requests.Response]: + """Ban the user. + + Args: + **kwargs: Extra options to send to the server (e.g. sudo) + + Raises: + GitlabAuthenticationError: If authentication is not correct + GitlabBanError: If the user could not be banned + + Returns: + Whether the user has been banned + """ + path = f"/users/{self.encoded_id}/ban" + server_data = self.manager.gitlab.http_post(path, **kwargs) + if server_data: + self._attrs["state"] = "banned" + return server_data + + @cli.register_custom_action("User") + @exc.on_http_error(exc.GitlabUnbanError) + def unban(self, **kwargs: Any) -> Union[Dict[str, Any], requests.Response]: + """Unban the user. + + Args: + **kwargs: Extra options to send to the server (e.g. sudo) + + Raises: + GitlabAuthenticationError: If authentication is not correct + GitlabUnbanError: If the user could not be unbanned + + Returns: + Whether the user has been unbanned + """ + path = f"/users/{self.encoded_id}/unban" + server_data = self.manager.gitlab.http_post(path, **kwargs) + if server_data: + self._attrs["state"] = "active" + return server_data + class UserManager(CRUDMixin, RESTManager): _path = "/users" diff --git a/tests/functional/api/test_users.py b/tests/functional/api/test_users.py index 0c5803408..5629063a7 100644 --- a/tests/functional/api/test_users.py +++ b/tests/functional/api/test_users.py @@ -37,6 +37,16 @@ def test_block_user(gl, user): assert user in users +def test_ban_user(gl, user): + user.ban() + retrieved_user = gl.users.get(user.id) + assert retrieved_user.state == "banned" + + user.unban() + retrieved_user = gl.users.get(user.id) + assert retrieved_user.state == "active" + + def test_delete_user(gl, wait_for_sidekiq): new_user = gl.users.create( { diff --git a/tests/unit/objects/test_users.py b/tests/unit/objects/test_users.py index a2ea5dec9..1c8959375 100644 --- a/tests/unit/objects/test_users.py +++ b/tests/unit/objects/test_users.py @@ -80,6 +80,32 @@ def resp_activate(): yield rsps +@pytest.fixture +def resp_ban(): + with responses.RequestsMock() as rsps: + rsps.add( + method=responses.POST, + url="http://localhost/api/v4/users/1/ban", + json={}, + content_type="application/json", + status=201, + ) + yield rsps + + +@pytest.fixture +def resp_unban(): + with responses.RequestsMock() as rsps: + rsps.add( + method=responses.POST, + url="http://localhost/api/v4/users/1/unban", + json={}, + content_type="application/json", + status=201, + ) + yield rsps + + @pytest.fixture def resp_get_user_status(): content = { @@ -216,6 +242,14 @@ def test_user_activate_deactivate(user, resp_activate): user.deactivate() +def test_user_ban(user, resp_ban): + user.ban() + + +def test_user_unban(user, resp_unban): + user.unban() + + def test_delete_user_identity(user, resp_delete_user_identity): user.identityproviders.delete("test_provider")
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: