Implement inactive user deletion, Implement deletion form as macro

This commit is contained in:
Götz 2019-05-15 03:00:37 +02:00
parent 407958ba9d
commit 2dd8a0d4df
9 changed files with 135 additions and 94 deletions

View File

@ -8,6 +8,7 @@ from django.contrib.auth.models import Group, User
from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ObjectDoesNotExist
from django.db import IntegrityError from django.db import IntegrityError
from django.shortcuts import render, redirect, HttpResponse from django.shortcuts import render, redirect, HttpResponse
from datetime import datetime, timedelta
from account_helper.models import Realm from account_helper.models import Realm
from account_manager.utils.mail_utils import realm_send_mail from account_manager.utils.mail_utils import realm_send_mail
@ -105,10 +106,15 @@ def base_dn_available(base_dn):
@is_realm_admin @is_realm_admin
def realm_detail(request, realm_id): def realm_detail(request, realm_id):
realm = Realm.objects.get(id=realm_id) realm = Realm.objects.get(id=realm_id)
LdapUser.base_dn = realm.ldap_base_dn
inactive_users = LdapUser.get_inactive_users().count()
logger.info(inactive_users)
ldap_admin_group, ldap_default_group = get_default_admin_group(realm) ldap_admin_group, ldap_default_group = get_default_admin_group(realm)
return render(request, 'realm/realm_detailed.jinja2', return render(request, 'realm/realm_detailed.jinja2',
{'realm': realm, 'ldap_admin_group': ldap_admin_group, 'ldap_default_group': ldap_default_group}) {'realm': realm, 'ldap_admin_group': ldap_admin_group, 'ldap_default_group': ldap_default_group,
'inactive_user_count': inactive_users, 'users_count': LdapUser.objects.all().count()})
def get_default_admin_group(realm): def get_default_admin_group(realm):

View File

@ -1,5 +1,6 @@
# Create your models here. # Create your models here.
import re import re
from datetime import datetime, timedelta
from django.contrib.auth.models import User from django.contrib.auth.models import User
@ -101,6 +102,12 @@ class LdapUser(Model):
user_wrappers.append({'user': user, 'active': False}) user_wrappers.append({'user': user, 'active': False})
return user_wrappers return user_wrappers
@staticmethod
def get_inactive_users():
last_semester = datetime.now() - timedelta(days=182)
return (LdapUser.objects.filter(last_login__lte=last_semester) | LdapUser.objects.exclude(
last_login__lte=datetime.now() + timedelta(days=1)))
class LdapGroup(Model): class LdapGroup(Model):
""" """

View File

@ -51,6 +51,8 @@ urlpatterns = [
name='realm-multiple-user-delete-confirm'), name='realm-multiple-user-delete-confirm'),
path('realm/<int:realm_id>/user/delete/multiple/', user_views.realm_multiple_user_delete, path('realm/<int:realm_id>/user/delete/multiple/', user_views.realm_multiple_user_delete,
name='realm-multiple-user-delete'), name='realm-multiple-user-delete'),
path('realm/<int:realm_id>/user/delete/multiple/inactive/', user_views.realm_multiple_user_delete_inactive,
name='realm-multiple-user-delete-inactive'),
# Realm Group # Realm Group
path('realm/<int:realm_id>/groups/', group_views.realm_groups, name='realm-group-list'), path('realm/<int:realm_id>/groups/', group_views.realm_groups, name='realm-group-list'),

View File

@ -246,6 +246,28 @@ def realm_multiple_user_delete(request, realm_id):
return redirect('realm-user-list', realm.id) return redirect('realm-user-list', realm.id)
@login_required
@is_realm_admin
def realm_multiple_user_delete_inactive(request, realm_id):
realm = Realm.objects.get(id=realm_id)
if request.method == 'POST':
form = UserDeleteListForm(request.POST)
if form.is_valid():
ldap_users = form.cleaned_data['ldap_users']
blocked_users, deletable_users = get_deletable_blocked_users(ldap_users, realm)
return render(request, 'realm/realm_user_multiple_delete.jinja2',
{'form': form, 'realm': realm, 'deletable_users': deletable_users,
'blocked_users': blocked_users,
'confirm': True})
LdapUser.base_dn = realm.ldap_base_dn
inactive_users = LdapUser.get_inactive_users()
# TODO: Form not valid
form = UserDeleteListForm()
return render(request, 'realm/realm_user_multiple_delete_confirm.jinja2',
{'form': form, 'realm': realm, 'users': inactive_users, })
@login_required @login_required
@is_realm_admin @is_realm_admin
def realm_multiple_user_delete_confirm(request, realm_id): def realm_multiple_user_delete_confirm(request, realm_id):

View File

@ -16,7 +16,7 @@
id="data-table-search-input"> id="data-table-search-input">
<label for="data-table-search-input">Suche</label> <label for="data-table-search-input">Suche</label>
</div> </div>
{{ mform.user_select_table_input(form.members, users) }} {{ mform.user_select_table_input(users, field=form.members) }}
<div class="d-flex mt-4"> <div class="d-flex mt-4">
<button type="submit" class="btn btn-primary mr-auto p-2">Speichern</button> <button type="submit" class="btn btn-primary mr-auto p-2">Speichern</button>
<a href="{{ url('realm-group-list', args = [realm.id]) }}" <a href="{{ url('realm-group-list', args = [realm.id]) }}"

View File

@ -288,20 +288,32 @@
</div> </div>
{% endmacro %} {% endmacro %}
{% macro user_select_table_input(field, users, css_classes='') -%} {% macro user_select_table_input(users, deletable_users=[], blocked_users=[], field=None, name=None, css_classes='',show_lastlogin=False, checkbox_label_classes='') -%}
<table class="table table-hover table-striped table-inverse table-bordered data-table"> <table class="table table-hover table-striped table-inverse table-bordered data-table">
<thead> <thead>
<tr> <tr>
<th scope="col" class="text-center"> <th scope="col" class="text-center">
<input type="checkbox" {% if not deletable_users and not blocked_users %}
class="table-checkbox-control-input" <input type="checkbox"
id="delete-all-checkbox" class="table-checkbox-control-input"
><label class="table-checkbox-control-label table-checkbox-control-label-add" for="delete-all-checkbox"></label> id="delete-all-checkbox"
><label class="
{% if checkbox_label_classes %}{{ checkbox_label_classes }}{% else %}table-checkbox-control-label table-checkbox-control-label-add{% endif %}"
for="delete-all-checkbox"></label>
{% endif %}
</th> </th>
<th scope="col">Nutzername</th> <th scope="col">Nutzername</th>
<th scope="col">E-Mail</th> <th scope="col">E-Mail</th>
<th scope="col">Vorname</th> <th scope="col">Vorname</th>
<th scope="col">Nachname</th> <th scope="col">Nachname</th>
{% if show_lastlogin %}
<th scope="col">Letzter Login</th>
{% endif %}
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@ -311,12 +323,18 @@
<input type="checkbox" <input type="checkbox"
class="table-checkbox-control-input multiple-select-checkbox" class="table-checkbox-control-input multiple-select-checkbox"
aria-describedby="{{ choice_label }}_help" aria-describedby="{{ choice_label }}_help"
name="{{ field.html_name }}" name="{% if field %}{{ field.html_name }}{% else %}{{ name }}{% endif %}"
id="{{ user.username }}_{{ loop.index }}" id="{{ user.username }}_{{ loop.index }}"
value="{{ user.username }}" value="{{ user.username }}"
{% if field.value() and user.username in field.value() %}checked{% endif %} {% if field and field.value() and user.username in field.value() %}checked{% endif %}
> >
<label class="table-checkbox-control-label table-checkbox-control-label-add" for="{{ user.username }}_{{ loop.index }}"> <label class="
{% if checkbox_label_classes %}{{ checkbox_label_classes }}{% else %}table-checkbox-control-label table-checkbox-control-label-add{% endif %}"
for="{{ user.username }}_{{ loop.index }}">
</label> </label>
</td> </td>
@ -324,6 +342,69 @@
<td>{{ user.email }}</td> <td>{{ user.email }}</td>
<td>{{ user.first_name }}</td> <td>{{ user.first_name }}</td>
<td>{{ user.last_name }}</td> <td>{{ user.last_name }}</td>
{% if show_lastlogin %}
<td class="text-center">
{% if user.last_login %}
{{ user.last_login.strftime('%Y-%m-%d') }}
{% else %}
<i class="far fa-times-circle text-danger"></i><span class="d-none">+</span>
{% endif %}
</td>
{% endif %}
</tr>
{% endfor %}
{% for user in deletable_users %}
<tr>
<td class="text-center">
<input type="checkbox"
class="table-checkbox-control-input multiple-select-checkbox"
id="user_{{ loop.index }}"
value="{{ user.username }}"
name="ldap_users"
checked
disabled
><label class="table-checkbox-control-label" for="user_{{ loop.index }}"></label>
</td>
<td>{{ user.username }}</td>
<td>{{ user.email }}</td>
<td>{{ user.first_name }}</td>
<td>{{ user.last_name }}</td>
{% if show_lastlogin %}
<td class="text-center">
{% if user.last_login %}
{{ user.last_login.strftime('%Y-%m-%d') }}
{% else %}
<i class="far fa-times-circle text-danger"></i><span class="d-none">+</span>
{% endif %}
</td>
{% endif %}
</tr>
<input type="checkbox" value="{{ user.username }}" name="ldap_users" checked hidden>
{% endfor %}
{% for user in blocked_users %}
<tr>
<td class="text-center">
<input type="checkbox"
class="table-checkbox-control-input delete-checkbox"
id="user_{{ loop.index }}"
value="{{ user.username }}"
name="ldap_users"
disabled
><label class="table-checkbox-control-label" for="user_{{ loop.index }}"></label>
</td>
<td>{{ user.username }}</td>
<td>{{ user.email }}</td>
<td>{{ user.first_name }}</td>
<td>{{ user.last_name }}</td>
{% if show_lastlogin %}
<td class="text-center">
{% if user.last_login %}
{{ user.last_login.strftime('%Y-%m-%d') }}
{% else %}
<i class="far fa-times-circle text-danger"></i><span class="d-none">+</span>
{% endif %}
</td>
{% endif %}
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>

View File

@ -21,6 +21,11 @@
{% block detail_content %} {% block detail_content %}
<ul class="list-group list-group-flush w-100"> <ul class="list-group list-group-flush w-100">
<li class="list-group-item">LDAP Organisationseinheit: {{ realm.ldap_base_dn }}</li> <li class="list-group-item">LDAP Organisationseinheit: {{ realm.ldap_base_dn }}</li>
<li class="list-group-item">Nutzeranzahl: {{ users_count }}</li>
<li class="list-group-item">Inaktive Nutzer: {{ inactive_user_count }} <a
href="{{ url('realm-multiple-user-delete-inactive', args=[realm.id]) }}"
class="float-right">
Inaktive Nutzer löschen</a></li>
{% if realm.email %} {% if realm.email %}
<li class="list-group-item">Email: {{ realm.email }}</li> <li class="list-group-item">Email: {{ realm.email }}</li>
{% else %} {% else %}

View File

@ -26,55 +26,7 @@
</div> </div>
<form action="{{ url('realm-multiple-user-delete', args=[realm.id]) }}" method="post"> <form action="{{ url('realm-multiple-user-delete', args=[realm.id]) }}" method="post">
<input type="hidden" name="csrfmiddlewaretoken" value="{{ csrf_token }}"> <input type="hidden" name="csrfmiddlewaretoken" value="{{ csrf_token }}">
<table class="table table-hover table-striped table-inverse table-bordered data-table"> {{ mform.user_select_table_input(users=[], deletable_users=deletable_users, blocked_users=blocked_users, name="ldap_users",css_classes='',show_lastlogin=True, checkbox_label_classes='table-checkbox-control-label') }}
<thead>
<tr>
<th scope="col" class="text-center"></th>
<th scope="col">Nutzername</th>
<th scope="col">E-Mail</th>
<th scope="col">Vorname</th>
<th scope="col">Nachname</th>
</tr>
</thead>
<tbody>
{% for user in deletable_users %}
<tr>
<td class="text-center">
<input type="checkbox"
class="table-checkbox-control-input multiple-select-checkbox"
id="user_{{ loop.index }}"
value="{{ user.username }}"
name="ldap_users"
checked
disabled
><label class="table-checkbox-control-label" for="user_{{ loop.index }}"></label>
</td>
<td>{{ user.username }}</td>
<td>{{ user.email }}</td>
<td>{{ user.first_name }}</td>
<td>{{ user.last_name }}</td>
</tr>
<input type="checkbox" value="{{ user.username }}" name="ldap_users" checked hidden>
{% endfor %}
{% for user in blocked_users %}
<tr>
<td class="text-center">
<input type="checkbox"
class="table-checkbox-control-input delete-checkbox"
id="user_{{ loop.index }}"
value="{{ user.username }}"
name="ldap_users"
disabled
><label class="table-checkbox-control-label" for="user_{{ loop.index }}"></label>
</td>
<td>{{ user.username }}</td>
<td>{{ user.email }}</td>
<td>{{ user.first_name }}</td>
<td>{{ user.last_name }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="d-flex mt-4"> <div class="d-flex mt-4">
<button type="submit" class="btn btn-danger mr-auto p-2">Ausführen</button> <button type="submit" class="btn btn-danger mr-auto p-2">Ausführen</button>
<a href="{{ url('realm-user-list', args = [realm.id]) }}" <a href="{{ url('realm-user-list', args = [realm.id]) }}"

View File

@ -12,41 +12,7 @@
</div> </div>
<form action="{{ url('realm-multiple-user-delete-confirm', args=[realm.id]) }}" method="post"> <form action="{{ url('realm-multiple-user-delete-confirm', args=[realm.id]) }}" method="post">
<input type="hidden" name="csrfmiddlewaretoken" value="{{ csrf_token }}"> <input type="hidden" name="csrfmiddlewaretoken" value="{{ csrf_token }}">
{# {{ form.as_p() }}#} {{ mform.user_select_table_input(users, name="ldap_users",css_classes='',show_lastlogin=True, checkbox_label_classes='table-checkbox-control-label') }}
<table class="table table-hover table-striped table-inverse table-bordered data-table">
<thead>
<tr>
<th scope="col" class="text-center">
<input type="checkbox"
class="table-checkbox-control-input"
id="delete-all-checkbox"
><label class="table-checkbox-control-label" for="delete-all-checkbox"></label>
</th>
<th scope="col">Nutzername</th>
<th scope="col">E-Mail</th>
<th scope="col">Vorname</th>
<th scope="col">Nachname</th>
</tr>
</thead>
<tbody>
{% for user in users %}
<tr>
<td class="text-center">
<input type="checkbox"
class="table-checkbox-control-input multiple-select-checkbox"
id="user_{{ loop.index }}"
value="{{ user.username }}"
name="ldap_users"
><label class="table-checkbox-control-label" for="user_{{ loop.index }}"></label>
</td>
<td>{{ user.username }}</td>
<td>{{ user.email }}</td>
<td>{{ user.first_name }}</td>
<td>{{ user.last_name }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="d-flex mt-4"> <div class="d-flex mt-4">
<button type="submit" class="btn btn-danger mr-auto p-2">Ausführen</button> <button type="submit" class="btn btn-danger mr-auto p-2">Ausführen</button>
<a href="{{ url('realm-user-list', args = [realm.id]) }}" <a href="{{ url('realm-user-list', args = [realm.id]) }}"