From 0b1e5fdf809fe6deade78ca312ec9e93de3d3a10 Mon Sep 17 00:00:00 2001 From: ievgenii vdovenko Date: Tue, 29 Jul 2025 13:31:09 +0200 Subject: [PATCH] feature: adds audit --- rhodecode/apps/admin/views/users.py | 10 +++++++-- rhodecode/lib/audit_logger.py | 1 + rhodecode/model/user.py | 32 +++++++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/rhodecode/apps/admin/views/users.py b/rhodecode/apps/admin/views/users.py index e9408cc0..79b209fd 100644 --- a/rhodecode/apps/admin/views/users.py +++ b/rhodecode/apps/admin/views/users.py @@ -365,11 +365,16 @@ class UsersView(UserAppView): _user_groups = len(c.user.user_groups) _pull_requests = len(c.user.user_pull_requests) _artifacts = len(c.user.artifacts) + _reviewer = len(c.user.reviewer_pull_requests) def set_flash_repos_if_detached(): if detach_repos: h.flash(_("Detached %s repositories") % _repos, category="success") + def set_flash_reviews_if_deleted(): + if delete_reviewer: + h.flash(_("Removed from %s review(s)") % _reviewer, category="success") + def set_flash_repo_groups_if_detached(): if detach_repo_groups: h.flash(_("Detached %s repository groups") % _repo_groups, category="success") @@ -391,11 +396,11 @@ class UsersView(UserAppView): detach_user_groups = _user_groups > 0 detach_pull_requests = _pull_requests > 0 detach_artifacts = _artifacts > 0 + delete_reviewer = _reviewer > 0 old_values = c.user.get_api_data() try: - ghost_user = User.get_ghost_user() UserModel().delete( c.user, detach_repos=detach_repos, @@ -403,7 +408,7 @@ class UsersView(UserAppView): detach_user_groups=detach_user_groups, detach_pull_requests=detach_pull_requests, detach_artifacts=detach_artifacts, - new_owner=ghost_user, + delete_reviewer=delete_reviewer, ) audit_logger.store_web("user.delete", action_data={"old_data": old_values}, user=c.rhodecode_user) @@ -414,6 +419,7 @@ class UsersView(UserAppView): set_flash_user_groups_if_detached() set_flash_pull_requests_if_detached() set_flash_artifacts_if_detached() + set_flash_reviews_if_deleted() username = h.escape(old_values["username"]) h.flash(_("Successfully deleted user `{}`").format(username), category="success") except ( diff --git a/rhodecode/lib/audit_logger.py b/rhodecode/lib/audit_logger.py index ad24483d..7ffb8e83 100644 --- a/rhodecode/lib/audit_logger.py +++ b/rhodecode/lib/audit_logger.py @@ -63,6 +63,7 @@ ACTIONS_V1 = { "repo.edit.permissions.branch": {}, "repo.archive": {"old_data": {}}, "repo.delete": {"old_data": {}}, + "review.delete": {"review.role": "", "pull_request": {}, "prev_user": {}}, "repo.archive.download": {"user_agent": "", "archive_name": "", "archive_spec": "", "archive_cached": ""}, "repo.permissions.branch_rule.create": {}, "repo.permissions.branch_rule.edit": {}, diff --git a/rhodecode/model/user.py b/rhodecode/model/user.py index e3f6458f..636c119f 100644 --- a/rhodecode/model/user.py +++ b/rhodecode/model/user.py @@ -24,10 +24,12 @@ import logging import traceback import datetime import ipaddress +from typing import List from sqlalchemy.exc import DatabaseError from rhodecode import events +from rhodecode.lib import audit_logger from rhodecode.lib.pyramid_utils import get_current_request from rhodecode.lib.user_log_filter import user_log_filter from rhodecode.lib.utils2 import get_current_rhodecode_user, action_logger_generic, AttributeDict, str2bool @@ -56,6 +58,7 @@ from rhodecode.model.db import ( UserEmailMap, UserIpMap, UserLog, + PullRequestReviewers, ) from rhodecode.model.meta import Session from rhodecode.model.auth_token import AuthTokenModel @@ -508,6 +511,31 @@ class UserModel(BaseModel): a.file_description += " \n::detached artifact from deleted user: %s" % (username,) self.sa.add(a) + def _delete_from_reviews(self, user: User, reviewer_pull_requests: List[PullRequestReviewers]): + for review in reviewer_pull_requests: + if review.role == PullRequestReviewers.ROLE_REVIEWER: + audit_logger.store_web( + "review.delete", + user=get_current_rhodecode_user(), + action_data={ + "review_role": review.role, + "pull_request": { + "id": review.pull_request.pull_request_id, + "title": review.pull_request.title_safe, + }, + "prev_user": { + "username": user.username, + "name": user.name, + "email": user.email, + }, + }, + repo=audit_logger.RepoWrap( + repo_id=review.pull_request.target_repo_id, + repo_name=review.pull_request.target_repo.repo_name, + ), + ) + self.sa.delete(review) + def delete( self, user, @@ -517,6 +545,7 @@ class UserModel(BaseModel): detach_user_groups=False, detach_pull_requests=False, detach_artifacts=False, + delete_reviewer=False, new_owner=None, ): from rhodecode.lib import hooks_base @@ -530,6 +559,9 @@ class UserModel(BaseModel): if user.username in [User.DEFAULT_USER, User.GHOST_USER]: raise DefaultUserException("You can't remove this user since it's crucial for entire application") + if delete_reviewer: + self._delete_from_reviews(user, user.reviewer_pull_requests) + if detach_repos or detach_repo_groups or detach_user_groups or detach_pull_requests or detach_artifacts: new_owner = new_owner or self.cls.get_ghost_user() log.debug("New detached objects owner %s", new_owner)