audit-logs: expose tailoed audit logs in repository view

This commit is contained in:
Marcin Kuzminski 2017-10-08 12:11:04 +02:00
parent b900d908c5
commit abf63a445f
6 changed files with 115 additions and 8 deletions

View file

@ -431,6 +431,11 @@ def includeme(config):
name='strip_execute',
pattern='/{repo_name:.*?[^/]}/settings/strip_execute', repo_route=True)
# Audit logs
config.add_route(
name='edit_repo_audit_logs',
pattern='/{repo_name:.*?[^/]}/settings/audit_logs', repo_route=True)
# ATOM/RSS Feed
config.add_route(
name='rss_feed_home',

View file

@ -0,0 +1,65 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2017-2017 RhodeCode GmbH
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License, version 3
# (only), as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# This program is dual-licensed. If you wish to learn more about the
# RhodeCode Enterprise Edition, including its added features, Support services,
# and proprietary license terms, please see https://rhodecode.com/licenses/
import logging
from pyramid.view import view_config
from rhodecode.apps._base import RepoAppView
from rhodecode.lib import helpers as h
from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
from rhodecode.lib.utils2 import safe_int
from rhodecode.model.repo import RepoModel
log = logging.getLogger(__name__)
class AuditLogsView(RepoAppView):
def load_default_context(self):
c = self._get_local_tmpl_context()
self._register_global_c(c)
return c
@LoginRequired()
@HasRepoPermissionAnyDecorator('repository.admin')
@view_config(
route_name='edit_repo_audit_logs', request_method='GET',
renderer='rhodecode:templates/admin/repos/repo_edit.mako')
def repo_audit_logs(self):
_ = self.request.translate
c = self.load_default_context()
c.db_repo = self.db_repo
c.active = 'audit'
p = safe_int(self.request.GET.get('page', 1), 1)
filter_term = self.request.GET.get('filter')
user_log = RepoModel().get_repo_log(c.db_repo, filter_term)
def url_generator(**kw):
if filter_term:
kw['filter'] = filter_term
return self.request.current_route_path(_query=kw)
c.audit_logs = h.Page(
user_log, page=p, items_per_page=10, url=url_generator)
c.filter_term = filter_term
return self._get_template_context(c)

View file

@ -18,11 +18,11 @@
# RhodeCode Enterprise Edition, including its added features, Support services,
# and proprietary license terms, please see https://rhodecode.com/licenses/
import logging
import os
import re
import shutil
import time
import logging
import traceback
import datetime
@ -30,21 +30,22 @@ from pyramid.threadlocal import get_current_request
from zope.cachedescriptors.property import Lazy as LazyProperty
from rhodecode import events
from rhodecode.lib import helpers as h
from rhodecode.lib.auth import HasUserGroupPermissionAny
from rhodecode.lib.caching_query import FromCache
from rhodecode.lib.exceptions import AttachedForksError
from rhodecode.lib.hooks_base import log_delete_repository
from rhodecode.lib.user_log_filter import user_log_filter
from rhodecode.lib.utils import make_db_config
from rhodecode.lib.utils2 import (
safe_str, safe_unicode, remove_prefix, obfuscate_url_pw,
get_current_rhodecode_user, safe_int, datetime_to_time, action_logger_generic)
get_current_rhodecode_user, safe_int, datetime_to_time,
action_logger_generic)
from rhodecode.lib.vcs.backends import get_backend
from rhodecode.model import BaseModel
from rhodecode.model.db import (_hash_key,
Repository, UserRepoToPerm, UserGroupRepoToPerm, UserRepoGroupToPerm,
UserGroupRepoGroupToPerm, User, Permission, Statistics, UserGroup,
RepoGroup, RepositoryField)
from rhodecode.model.db import (
_hash_key, joinedload, or_, Repository, UserRepoToPerm, UserGroupRepoToPerm,
UserRepoGroupToPerm, UserGroupRepoGroupToPerm, User, Permission,
Statistics, UserGroup, RepoGroup, RepositoryField, UserLog)
from rhodecode.model.settings import VcsSettingsModel
@ -182,6 +183,17 @@ class RepoModel(BaseModel):
'repo_commit', repo_name=safe_str(repo.repo_name),
commit_id=commit_id)
def get_repo_log(self, repo, filter_term):
repo_log = UserLog.query()\
.filter(or_(UserLog.repository_id == repo.repo_id,
UserLog.repository_name == repo.repo_name))\
.options(joinedload(UserLog.user))\
.options(joinedload(UserLog.repository))\
.order_by(UserLog.action_date.desc())
repo_log = user_log_filter(repo_log, filter_term)
return repo_log
@classmethod
def update_repoinfo(cls, repositories=None):
if not repositories:

View file

@ -85,6 +85,9 @@
<li class="${'active' if c.active=='strip' else ''}">
<a href="${h.route_path('edit_repo_strip', repo_name=c.repo_name)}">${_('Strip')}</a>
</li>
<li class="${'active' if c.active=='audit' else ''}">
<a href="${h.route_path('edit_repo_audit_logs', repo_name=c.repo_name)}">${_('Audit logs')}</a>
</li>
</ul>
</div>

View file

@ -0,0 +1,22 @@
## -*- coding: utf-8 -*-
<%namespace name="base" file="/base/base.mako"/>
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">${_('Repository Audit Logs')} -
${_ungettext('%s entry', '%s entries', c.audit_logs.item_count) % (c.audit_logs.item_count)}
</h3>
</div>
<div class="panel-body">
${h.form(None, id_="filter_form", method="get")}
<input class="q_filter_box ${'' if c.filter_term else 'initial'}" id="j_filter" size="15" type="text" name="filter" value="${c.filter_term or ''}" placeholder="${_('audit filter...')}"/>
<input type='submit' value="${_('filter')}" class="btn" />
${h.end_form()}
<p class="tooltip filterexample" style="position: inherit" title="${h.tooltip(h.journal_filter_help(c.pyramid_request))}">${_('Example Queries')}</p>
<%include file="/admin/admin_log_base.mako" />
</div>
</div>

View file

@ -44,7 +44,7 @@
<li class="${'active' if c.active=='emails' else ''}"><a href="${h.route_path('edit_user_emails', user_id=c.user.user_id)}">${_('Emails')}</a></li>
<li class="${'active' if c.active=='ips' else ''}"><a href="${h.route_path('edit_user_ips', user_id=c.user.user_id)}">${_('Ip Whitelist')}</a></li>
<li class="${'active' if c.active=='groups' else ''}"><a href="${h.route_path('edit_user_groups_management', user_id=c.user.user_id)}">${_('User Groups Management')}</a></li>
<li class="${'active' if c.active=='audit' else ''}"><a href="${h.route_path('edit_user_audit_logs', user_id=c.user.user_id)}">${_('User audit')}</a></li>
<li class="${'active' if c.active=='audit' else ''}"><a href="${h.route_path('edit_user_audit_logs', user_id=c.user.user_id)}">${_('Audit logs')}</a></li>
</ul>
</div>