authentic/src/authentic2/manager/journal_views.py

139 lines
4.4 KiB
Python

# authentic2 - versatile identity manager
# Copyright (C) 2010-2020 Entr'ouvert
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# 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 Affero 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/>.
import functools
import uuid
from django import forms
from django.contrib.auth import get_user_model
from django.core.exceptions import PermissionDenied, ValidationError
from django.core.validators import EmailValidator
from django.db.models import Q
from django.utils.translation import ugettext_lazy as _
from authentic2.apps.journal.forms import JournalForm
from authentic2.apps.journal.models import EventType
from authentic2.apps.journal.search_engine import JournalSearchEngine
from authentic2.apps.journal.views import JournalView
from . import views
User = get_user_model()
class JournalSearchEngine(JournalSearchEngine):
def search_by_uuid(self, lexem):
# by user uuid
try:
user_uuid = uuid.UUID(lexem)
except ValueError:
yield self.q_false
else:
yield Q(user__uuid=user_uuid.hex)
search_by_uuid.documentation = _(
'''\
You can use <tt>uuid:1234</tt> to find all events related \
to user whose UUID is <tt>1234</tt>.'''
)
unmatched = None
def lexem_queries(self, lexem):
queries = list(super().lexem_queries(lexem))
if queries:
yield from queries
elif '@' in lexem:
# fallback for raw email
try:
EmailValidator(lexem)
except ValidationError:
pass
else:
yield from super().lexem_queries('email:' + lexem)
yield from super().lexem_queries('username:' + lexem)
def unmatched_lexems_query(self, lexems):
fullname = ' '.join(lexem.strip() for lexem in lexems if lexem.strip())
if fullname:
users = User.objects.find_duplicates(fullname=fullname)
return self.query_for_users(users)
EVENT_TYPE_CHOICES = (
('', _('All')),
(
_('Users'),
(
('login,user.creation,user.registration,sso,password', _('Connection & SSO')),
('password', _('Password')),
(
'password,manager.user.((de)?activation|password|profile|email),^user.deletion,^user.profile',
_('Profile changes'),
),
),
),
(
_('Backoffice'),
(
('manager', _('All')),
('manager.user', _('User management')),
('manager.role', _('Role management')),
),
),
)
class JournalForm(JournalForm):
search_engine_class = JournalSearchEngine
event_type = forms.ChoiceField(required=False, choices=EVENT_TYPE_CHOICES)
def clean_event_type(self):
patterns = self.cleaned_data['event_type'].split(',')
qs_filter = functools.reduce(Q.__or__, (Q(name__regex=pattern) for pattern in patterns))
return EventType.objects.filter(qs_filter)
def get_queryset(self, **kwargs):
qs = super().get_queryset(**kwargs)
event_type = self.cleaned_data.get('event_type')
if event_type:
qs = qs.filter(type__in=event_type)
return qs
class BaseJournalView(views.TitleMixin, views.MediaMixin, views.MultipleOUMixin, JournalView):
template_name = 'authentic2/manager/journal.html'
title = _('Journal')
form_class = JournalForm
def get_context_data(self, **kwargs):
ctx = super().get_context_data(**kwargs)
date_hierarchy = ctx['date_hierarchy']
if date_hierarchy.title:
ctx['title'] = _('Journal of %s') % date_hierarchy.title
return ctx
class GlobalJournalView(views.PermissionMixin, BaseJournalView):
template_name = 'authentic2/manager/journal.html'
permissions_global = True
permissions = ['custom_user.view_user', 'a2_rbac.view_role']
journal = GlobalJournalView.as_view()