manager: display templated user info in sidebar (#81389)
gitea/authentic/pipeline/head This commit looks good
Details
gitea/authentic/pipeline/head This commit looks good
Details
This commit is contained in:
parent
ae2f54e98b
commit
952072cd0c
|
@ -1017,3 +1017,18 @@ class ServicesSettingsForm(forms.Form):
|
|||
)
|
||||
if RUNTIME_SETTINGS[setting.key]['type'] == 'colour':
|
||||
self.fields[setting.key].widget = forms.TextInput(attrs={'type': 'color'})
|
||||
|
||||
|
||||
class UsersAdvancedConfigurationForm(forms.Form):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
for setting in Setting.objects.filter_namespace('users'):
|
||||
self.fields[setting.key] = forms.CharField(
|
||||
initial=setting.value,
|
||||
label=RUNTIME_SETTINGS[setting.key]['name'],
|
||||
required=False,
|
||||
)
|
||||
|
||||
if RUNTIME_SETTINGS[setting.key]['type'] == 'text':
|
||||
self.fields[setting.key].widget = forms.Textarea()
|
||||
|
|
|
@ -143,5 +143,11 @@
|
|||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if sidebar_advanced_info %}
|
||||
<div id="advanced-info">
|
||||
{{ sidebar_advanced_info|safe }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
</aside>
|
||||
{% endblock %}
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
{% extends "authentic2/manager/form.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block breadcrumb %}
|
||||
{{ block.super }}
|
||||
<a href="{% url 'a2-manager-users' %}">{% trans 'Users' %}</a>
|
||||
<a href="#">{% trans "Edit users management advanced configuration" %}</a>
|
||||
{% endblock %}
|
||||
|
||||
{% block page_title %}
|
||||
{% trans "Edit users management advanced configuration" %}
|
||||
{% endblock %}
|
|
@ -58,6 +58,11 @@ urlpatterns = required(
|
|||
user_views.user_import_report,
|
||||
name='a2-manager-users-import-report',
|
||||
),
|
||||
path(
|
||||
'users/advanced/',
|
||||
user_views.users_advanced_configuration_view,
|
||||
name='a2-manager-users-advanced-configuration',
|
||||
),
|
||||
path('users/<int:ou_pk>/add/', user_views.user_add, name='a2-manager-user-add'),
|
||||
path('users/<int:pk>/', user_views.user_detail, name='a2-manager-user-detail'),
|
||||
path('users/<int:pk>/edit/', user_views.user_edit, name='a2-manager-user-edit'),
|
||||
|
|
|
@ -43,7 +43,7 @@ from authentic2.a2_rbac.models import OrganizationalUnit, Role, RoleParenting
|
|||
from authentic2.a2_rbac.utils import get_default_ou
|
||||
from authentic2.apps.journal.views import JournalViewWithContext
|
||||
from authentic2.backends.ldap_backend import LDAPBackend
|
||||
from authentic2.models import Attribute, PasswordReset
|
||||
from authentic2.models import Attribute, PasswordReset, Setting
|
||||
from authentic2.utils import hooks, spooler, switch_user
|
||||
from authentic2.utils.misc import (
|
||||
get_password_authenticator,
|
||||
|
@ -53,6 +53,7 @@ from authentic2.utils.misc import (
|
|||
select_next_url,
|
||||
send_password_reset_mail,
|
||||
)
|
||||
from authentic2.utils.template import Template
|
||||
from authentic2_idp_oidc.models import OIDCAuthorization, OIDCClient
|
||||
|
||||
from . import app_settings
|
||||
|
@ -67,6 +68,7 @@ from .forms import (
|
|||
UserEditForm,
|
||||
UserNewImportForm,
|
||||
UserRoleSearchForm,
|
||||
UsersAdvancedConfigurationForm,
|
||||
UserSearchForm,
|
||||
)
|
||||
from .journal_views import BaseJournalView
|
||||
|
@ -153,11 +155,17 @@ class UsersView(HideOUColumnMixin, BaseTableView):
|
|||
self.can_add = False
|
||||
extra_actions = ctx['extra_actions'] = []
|
||||
if self.request.user.has_perm('custom_user.admin_user'):
|
||||
extra_actions.append(
|
||||
{
|
||||
'url': reverse('a2-manager-users-imports'),
|
||||
'label': _('Import users'),
|
||||
}
|
||||
extra_actions.extend(
|
||||
[
|
||||
{
|
||||
'url': reverse('a2-manager-users-imports'),
|
||||
'label': _('Import users'),
|
||||
},
|
||||
{
|
||||
'url': reverse('a2-manager-users-advanced-configuration'),
|
||||
'label': _('Users management advanced configuration'),
|
||||
},
|
||||
]
|
||||
)
|
||||
return ctx
|
||||
|
||||
|
@ -426,6 +434,15 @@ class UserDetailView(OtherActionsMixin, BaseDetailView):
|
|||
role_qs = role_qs.filter(ou=instance.ou)
|
||||
return user.filter_by_perm('a2_rbac.manage_members_role', role_qs).exists()
|
||||
|
||||
def render_sidebar_advanced_info(self, context=None):
|
||||
value = ''
|
||||
if setting := Setting.objects.filter(key='users:backoffice_sidebar_template').first():
|
||||
value = setting.value
|
||||
if value and ('{{' in value or '{%' in value):
|
||||
template = Template(value)
|
||||
value = template.render(context=context)
|
||||
return value
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
kwargs['default_ou'] = get_default_ou
|
||||
roles = self.object.roles_and_parents().order_by('ou__name', 'name')
|
||||
|
@ -478,6 +495,7 @@ class UserDetailView(OtherActionsMixin, BaseDetailView):
|
|||
days=self.object.ou.clean_unused_accounts_deletion
|
||||
)
|
||||
ctx = super().get_context_data(**kwargs)
|
||||
ctx['sidebar_advanced_info'] = self.render_sidebar_advanced_info(ctx)
|
||||
return ctx
|
||||
|
||||
|
||||
|
@ -1041,3 +1059,24 @@ class UserJournal(PermissionMixin, JournalViewWithContext, BaseJournalView):
|
|||
|
||||
|
||||
user_journal = UserJournal.as_view()
|
||||
|
||||
|
||||
class UsersAdvancedConfigurationView(FormView):
|
||||
template_name = 'authentic2/manager/users_advanced_configuration.html'
|
||||
form_class = UsersAdvancedConfigurationForm
|
||||
title = _('Edit users management advanced configuration')
|
||||
success_url = '..'
|
||||
permissions = ['authentic2.change_user']
|
||||
|
||||
def form_valid(self, form):
|
||||
for key, value in form.cleaned_data.items():
|
||||
try:
|
||||
setting = Setting.objects.get(key=key)
|
||||
except Setting.DoesNotExist:
|
||||
continue
|
||||
setting.value = value
|
||||
setting.save()
|
||||
return super().form_valid(form)
|
||||
|
||||
|
||||
users_advanced_configuration_view = UsersAdvancedConfigurationView.as_view()
|
||||
|
|
|
@ -9,12 +9,13 @@ def initialize_services_runtime_settings(apps, schema_editor):
|
|||
if Setting.objects.filter(key__startswith='sso:').count() == 4:
|
||||
return
|
||||
for key, data in RUNTIME_SETTINGS.items():
|
||||
Setting.objects.get_or_create(
|
||||
key=key,
|
||||
defaults={
|
||||
'value': data['value'],
|
||||
},
|
||||
)
|
||||
if key.startswith('sso:'):
|
||||
Setting.objects.get_or_create(
|
||||
key=key,
|
||||
defaults={
|
||||
'value': data['value'],
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
def clear_services_runtime_settings(apps, schema_editor):
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
from django.db import migrations
|
||||
|
||||
|
||||
def initialize_users_advanced_config(apps, schema_editor):
|
||||
from authentic2.utils.misc import RUNTIME_SETTINGS
|
||||
|
||||
Setting = apps.get_model('authentic2', 'Setting')
|
||||
|
||||
if Setting.objects.filter(key__startswith='users:').count() == 1:
|
||||
return
|
||||
for key, data in RUNTIME_SETTINGS.items():
|
||||
if key.startswith('users:'):
|
||||
Setting.objects.get_or_create(
|
||||
key=key,
|
||||
defaults={
|
||||
'value': data['value'],
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
def clear_users_advanced_config(apps, schema_editor):
|
||||
Setting = apps.get_model('authentic2', 'Setting')
|
||||
|
||||
# default config has been extended, do not try to revert it
|
||||
if Setting.objects.filter(key__startswith='users:').count() != 1:
|
||||
return
|
||||
|
||||
Setting.objects.filter(key__startswith='users:').delete()
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('authentic2', '0049_apiclient_allowed_user_attributes'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(initialize_users_advanced_config, reverse_code=clear_users_advanced_config),
|
||||
]
|
|
@ -1386,4 +1386,9 @@ RUNTIME_SETTINGS = {
|
|||
'value': '',
|
||||
'type': 'url',
|
||||
},
|
||||
'users:backoffice_sidebar_template': {
|
||||
'name': _('Backoffice sidebar templated information'),
|
||||
'value': '',
|
||||
'type': 'text',
|
||||
},
|
||||
}
|
||||
|
|
|
@ -1404,6 +1404,28 @@ def test_manager_services_settings(app, admin):
|
|||
assert Setting.objects.get(key='sso:generic_service_name').value == 'Some other name'
|
||||
|
||||
|
||||
def test_manager_users_advanced_configuration_settings(app, admin):
|
||||
for setting in Setting.objects.filter_namespace('users'):
|
||||
assert setting.value == ''
|
||||
|
||||
resp = login(app, admin, 'a2-manager-services-settings')
|
||||
resp.form.submit()
|
||||
|
||||
for setting in Setting.objects.filter_namespace('sso'):
|
||||
assert setting.value == ''
|
||||
|
||||
# test value is saved correctly
|
||||
resp = app.get(reverse('a2-manager-users-advanced-configuration'))
|
||||
resp.form.set('users:backoffice_sidebar_template', 'Foo {{ user }}')
|
||||
resp.form.submit()
|
||||
|
||||
assert Setting.objects.get(key='users:backoffice_sidebar_template').value == 'Foo {{ user }}'
|
||||
|
||||
# test form is prefilled with the right value
|
||||
resp = app.get(reverse('a2-manager-users-advanced-configuration'))
|
||||
assert resp.form['users:backoffice_sidebar_template'].value == 'Foo {{ user }}'
|
||||
|
||||
|
||||
def test_manager_menu_json(app, admin):
|
||||
expected = [
|
||||
{
|
||||
|
|
|
@ -72,3 +72,15 @@ def test_migration_custom_user_0047_initialize_services_runtime_settings(transac
|
|||
assert Setting.objects.filter(key__startswith='sso:').count() == 4
|
||||
for setting in Setting.objects.filter(key__startswith='sso:'):
|
||||
assert setting.value == ''
|
||||
|
||||
|
||||
def test_migration_custom_user_0050_initialize_users_advanced_configuration(transactional_db, migration):
|
||||
old_apps = migration.before([('authentic2', '0049_apiclient_allowed_user_attributes')])
|
||||
Setting = old_apps.get_model('authentic2', 'Setting')
|
||||
before = Setting.objects.count()
|
||||
|
||||
new_apps = migration.apply([('authentic2', '0050_initialize_users_advanced_configuration')])
|
||||
Setting = new_apps.get_model('authentic2', 'Setting')
|
||||
assert Setting.objects.count() == before + 1
|
||||
assert Setting.objects.filter(key__startswith='users:').count() == 1
|
||||
assert Setting.objects.get(key='users:backoffice_sidebar_template').value == ''
|
||||
|
|
|
@ -35,7 +35,7 @@ from authentic2.a2_rbac.utils import get_default_ou, get_operation, get_view_use
|
|||
from authentic2.apps.journal.models import Event
|
||||
from authentic2.custom_user.models import User
|
||||
from authentic2.manager import user_import
|
||||
from authentic2.models import Attribute, AttributeValue, UserExternalId
|
||||
from authentic2.models import Attribute, AttributeValue, Setting, UserExternalId
|
||||
from authentic2_idp_oidc.models import OIDCAuthorization, OIDCClient
|
||||
|
||||
from .utils import get_link_from_mail, login, logout
|
||||
|
@ -1331,6 +1331,49 @@ def test_manager_user_authorizations_breadcrumb(app, superuser, simple_user):
|
|||
]
|
||||
|
||||
|
||||
def test_manager_user_sidebar_template_value(app, superuser, simple_user):
|
||||
resp = login(app, superuser)
|
||||
|
||||
user_detail_url = reverse('a2-manager-user-detail', kwargs={'pk': simple_user.id})
|
||||
setting = Setting.objects.get(key='users:backoffice_sidebar_template')
|
||||
|
||||
# correct template
|
||||
setting.value = 'User {{ object }} may have temporary roles.'
|
||||
setting.save()
|
||||
|
||||
resp = app.get(user_detail_url, status=200)
|
||||
assert 'User Jôhn Dôe may have temporary roles.' in resp.pyquery('#advanced-info')[0].text
|
||||
|
||||
# condition correctly evaluated
|
||||
setting.value = '{% if not object %}Foo{% else %}Bar{% endif %}'
|
||||
setting.save()
|
||||
|
||||
resp = app.get(user_detail_url, status=200)
|
||||
assert 'Bar' in resp.pyquery('#advanced-info')[0].text
|
||||
assert 'Foo' not in resp.pyquery('#advanced-info')[0].text
|
||||
|
||||
# missing context key rendered to empty value, no error
|
||||
setting.value = 'User {{ user }} may have temporary roles.'
|
||||
setting.save()
|
||||
|
||||
resp = app.get(user_detail_url, status=200)
|
||||
assert 'User may have temporary roles.' in resp.pyquery('#advanced-info')[0].text
|
||||
|
||||
# erroneous template not rendered
|
||||
setting.value = 'User {{ user %} may have temporary roles.'
|
||||
setting.save()
|
||||
|
||||
resp = app.get(user_detail_url, status=200)
|
||||
assert 'User {{ user %} may have temporary roles.' in resp.pyquery('#advanced-info')[0].text
|
||||
|
||||
# html is also rendered
|
||||
setting.value = '<strong>User {{ object.email }} may have temporary roles.</strong>'
|
||||
setting.save()
|
||||
|
||||
resp = app.get(user_detail_url, status=200)
|
||||
assert 'User user@example.net may have temporary roles.' in resp.pyquery('#advanced-info strong')[0].text
|
||||
|
||||
|
||||
def test_manager_user_roles_breadcrumb(app, superuser, simple_user):
|
||||
resp = login(app, superuser)
|
||||
user_roles_url = reverse('a2-manager-user-roles', kwargs={'pk': simple_user.id})
|
||||
|
|
Loading…
Reference in New Issue