Merge branch 'master' of git.stuve-bamberg.de:mgoetz/ldap_account_manager

This commit is contained in:
Götz 2019-06-07 17:53:35 +02:00
commit 7b0bd4f17e
10 changed files with 85 additions and 27 deletions

View File

@ -30,3 +30,13 @@ DEFAULT_FROM_EMAIL=
SERVER_EMAIL= SERVER_EMAIL=
DELETION_WAIT_DAYS=14 DELETION_WAIT_DAYS=14
#EMAIL_BACKEND=smtp
#EMAIL_HOST=smtp.uni-bamberg.de
#EMAIL_PORT=587
#EMAIL_USE_TLS=False
#EMAIL_USE_SSL=False
#DEFAULT_FROM_EMAIL=vergesslich@uni-bamberg.de
##DEFAULT_FROM_EMAIL=fachschaft-wiai.stuve@uni-bamberg.de
#SERVER_EMAIL=fachschaft-wiai.stuve@uni-bamberg.de

View File

@ -1,6 +1,6 @@
from django import forms from django import forms
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.contrib.auth.forms import PasswordResetForm from django.contrib.auth.forms import PasswordResetForm, PasswordChangeForm
from account_manager.utils.django_user import update_dajngo_user from account_manager.utils.django_user import update_dajngo_user
from .models import LdapUser, LdapGroup from .models import LdapUser, LdapGroup
@ -95,3 +95,11 @@ class LdapPasswordResetForm(PasswordResetForm):
}) })
logger.debug((u for u in active_users)) logger.debug((u for u in active_users))
return (u for u in active_users) return (u for u in active_users)
class LdapPasswordChangeForm(PasswordChangeForm):
def clean_old_password(self):
"""
Validates that the old_password field is correct.
"""
return "ralf"

View File

@ -45,7 +45,7 @@ def realm_list(request):
try: try:
LdapUser.base_dn = LdapUser.ROOT_DN LdapUser.base_dn = LdapUser.ROOT_DN
user = LdapUser.objects.get(username=user.username) user = LdapUser.objects.get(username=user.username)
realm_base_dn = re.compile('(uid=[a-zA-Z0-9_]*),(ou=[a-zA-Z_]*),(.*)').match(user.dn).group(3) realm_base_dn = re.compile('(uid=[a-zA-Z0-9_-]*),(ou=[a-zA-Z_-]*),(.*)').match(user.dn).group(3)
realm = Realm.objects.get(ldap_base_dn=realm_base_dn) realm = Realm.objects.get(ldap_base_dn=realm_base_dn)
return redirect('user-detail', realm.id, user.dn) return redirect('user-detail', realm.id, user.dn)
@ -68,6 +68,7 @@ def _get_group_user_count_wrapper(realm):
@login_required @login_required
@is_realm_admin
def realm_add(request): def realm_add(request):
if request.user.is_superuser: if request.user.is_superuser:
realms = Realm.objects.all().order_by('name') realms = Realm.objects.all().order_by('name')
@ -111,6 +112,7 @@ def realm_detail(request, realm_id):
def get_realm_detail_rendered(request, realm_id, success_headline=None, success_text=None, error_headline=None, def get_realm_detail_rendered(request, realm_id, success_headline=None, success_text=None, error_headline=None,
error_text=None): error_text=None):
realm = Realm.objects.get(id=realm_id) realm = Realm.objects.get(id=realm_id)
ldap_admin_group, ldap_default_group = get_default_admin_group(realm)
LdapUser.base_dn = realm.ldap_base_dn LdapUser.base_dn = realm.ldap_base_dn
inactive_users = LdapUser.get_inactive_users().count() inactive_users = LdapUser.get_inactive_users().count()
ldap_admin_group, ldap_default_group = get_default_admin_group(realm) ldap_admin_group, ldap_default_group = get_default_admin_group(realm)

View File

@ -84,7 +84,7 @@ class LdapUser(Model):
LdapUser.base_dn = LdapUser.ROOT_DN LdapUser.base_dn = LdapUser.ROOT_DN
ldap_user = LdapUser.objects.get(username=user.username) ldap_user = LdapUser.objects.get(username=user.username)
ldap_user.password = raw_password ldap_user.password = raw_password
LdapUser.base_dn = re.compile('(uid=[a-zA-Z0-9_]*),(.*)').match(ldap_user.dn).group(2) LdapUser.base_dn = re.compile('(uid=[a-zA-Z0-9_-]*),(.*)').match(ldap_user.dn).group(2)
ldap_user.save() ldap_user.save()
@staticmethod @staticmethod

View File

@ -80,6 +80,8 @@ urlpatterns = [
name='user-delete'), name='user-delete'),
path('accounts/reset/<uidb64>/<token>/', user_views.LdapPasswordResetConfirmView.as_view(), path('accounts/reset/<uidb64>/<token>/', user_views.LdapPasswordResetConfirmView.as_view(),
name='ldap_password_reset_confirm'), name='ldap_password_reset_confirm'),
path('accounts/password_change/secure/', user_views.password_change_controller,
name='password_change_controller'),
path('accounts/password_change/', user_views.LdapPasswordChangeView.as_view(), path('accounts/password_change/', user_views.LdapPasswordChangeView.as_view(),
name='password_change'), name='password_change'),

View File

@ -8,19 +8,22 @@ from django.contrib.auth.views import PasswordResetConfirmView, PasswordChangeVi
from django.contrib.sites.shortcuts import get_current_site from django.contrib.sites.shortcuts import get_current_site
from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ObjectDoesNotExist
from django.db import IntegrityError from django.db import IntegrityError
from django.http import HttpRequest from django.http import HttpRequest, HttpResponseRedirect
from django.shortcuts import render, redirect from django.shortcuts import render, redirect
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
from ldap import ALREADY_EXISTS, OBJECT_CLASS_VIOLATION from ldap import ALREADY_EXISTS, OBJECT_CLASS_VIOLATION
from django.urls import reverse
from urllib.parse import urlencode
from account_helper.models import Realm, DeletedUser from account_helper.models import Realm, DeletedUser
from account_manager.forms import AddLDAPUserForm, UserDeleteListForm, UpdateLDAPUserForm, AdminUpdateLDAPUserForm, \ from account_manager.forms import AddLDAPUserForm, UserDeleteListForm, UpdateLDAPUserForm, AdminUpdateLDAPUserForm, \
UserGroupListForm UserGroupListForm, LdapPasswordChangeForm
from account_manager.main_views import is_realm_admin from account_manager.main_views import is_realm_admin
from account_manager.models import LdapUser, LdapGroup from account_manager.models import LdapUser, LdapGroup
from account_manager.utils.django_user import update_dajngo_user from account_manager.utils.django_user import update_dajngo_user
from account_manager.utils.mail_utils import send_welcome_mail, send_deletion_mail from account_manager.utils.mail_utils import send_welcome_mail, send_deletion_mail
from django.contrib.auth import logout
from django.conf import settings from django.conf import settings
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -153,7 +156,7 @@ def realm_user_resend_password_reset(request, realm_id, user_dn):
ldap_user = LdapUser.objects.get(dn=user_dn) ldap_user = LdapUser.objects.get(dn=user_dn)
try: try:
if ldap_user.email: if ldap_user.email:
logger.info("Sending email for to this email:", ldap_user.email) logger.info(f"Sending email to {ldap_user.email}")
form = PasswordResetForm({'email': ldap_user.email}) form = PasswordResetForm({'email': ldap_user.email})
if form.is_valid(): if form.is_valid():
logger.info('CREATE REQUEST') logger.info('CREATE REQUEST')
@ -166,11 +169,11 @@ def realm_user_resend_password_reset(request, realm_id, user_dn):
form.save( form.save(
request=pw_reset_request, request=pw_reset_request,
use_https=True, use_https=True,
from_email=os.environ.get('DEFAULT_FROM_EMAIL', 'vergesslich@test.de'), from_email=settings.DEFAULT_FROM_EMAIL,
email_template_name='registration/password_reset_email.html') email_template_name='registration/password_reset_email.html')
except Exception as e: except Exception as e:
logger.info('Error') logger.error('Error')
return redirect('realm-user-detail', realm_id, user_dn) return redirect('realm-user-detail', realm_id, user_dn)
@ -496,19 +499,37 @@ def ldap_add_user_to_groups(ldap_user, user_groups):
group.save() group.save()
@login_required
def password_change_controller(request):
logout(request)
base_url = reverse('login')
next_param = reverse('password_change')
query_string = urlencode({'next': next_param})
url = '{}?{}'.format(base_url, query_string)
return redirect(url)
class LdapPasswordResetConfirmView(PasswordResetConfirmView): class LdapPasswordResetConfirmView(PasswordResetConfirmView):
def form_valid(self, form): def form_valid(self, form):
user = form.save() user = form.save()
password = form.cleaned_data['new_password1'] password = form.cleaned_data['new_password1']
LdapUser.base_dn = LdapUser.ROOT_DN LdapUser.base_dn = LdapUser.ROOT_DN
LdapUser.password_reset(user, password) LdapUser.password_reset(user, password)
return super().form_valid(form) cached_redirect = super().form_valid(form)
user.set_unusable_password()
user.save()
return cached_redirect
class LdapPasswordChangeView(PasswordChangeView): class LdapPasswordChangeView(PasswordChangeView):
form_class = LdapPasswordChangeForm
def form_valid(self, form): def form_valid(self, form):
user = form.save() user = form.save()
password = form.cleaned_data['new_password1'] password = form.cleaned_data['new_password1']
LdapUser.base_dn = LdapUser.ROOT_DN LdapUser.base_dn = LdapUser.ROOT_DN
LdapUser.password_reset(user, password) LdapUser.password_reset(user, password)
return super().form_valid(form) cached_request = super().form_valid(form)
user.set_unusable_password()
user.save()
return cached_request

View File

@ -180,6 +180,8 @@ else:
EMAIL_TIMEOUT = 15 EMAIL_TIMEOUT = 15
EMAIL_HOST = os.environ['EMAIL_HOST'] EMAIL_HOST = os.environ['EMAIL_HOST']
EMAIL_PORT = int(os.environ['EMAIL_PORT']) EMAIL_PORT = int(os.environ['EMAIL_PORT'])
EMAIL_HOST_USER = os.environ.get('EMAIL_HOST_USER','')
EMAIL_HOST_PASSWORD = os.environ.get('EMAIL_HOST_PASSWORD','')
EMAIL_USE_TLS = os.environ.get('EMAIL_USE_TLS', 'False') == 'True' EMAIL_USE_TLS = os.environ.get('EMAIL_USE_TLS', 'False') == 'True'
EMAIL_USE_SSL = os.environ.get('EMAIL_USE_SSL', 'False') == 'True' EMAIL_USE_SSL = os.environ.get('EMAIL_USE_SSL', 'False') == 'True'

View File

@ -18,6 +18,7 @@ from django.urls import path, include
from django.contrib.auth import views as auth_views from django.contrib.auth import views as auth_views
from django.contrib.auth.decorators import user_passes_test from django.contrib.auth.decorators import user_passes_test
from account_manager.forms import LdapPasswordResetForm from account_manager.forms import LdapPasswordResetForm
from account_manager.views.user_views import LdapPasswordChangeView
from .views import about from .views import about
login_forbidden = user_passes_test(lambda u: u.is_anonymous(), '/') login_forbidden = user_passes_test(lambda u: u.is_anonymous(), '/')
@ -31,5 +32,6 @@ urlpatterns = [
auth_views.PasswordResetView.as_view(html_email_template_name='registration/password_reset_email.html', auth_views.PasswordResetView.as_view(html_email_template_name='registration/password_reset_email.html',
form_class=LdapPasswordResetForm), form_class=LdapPasswordResetForm),
name='password_reset'), name='password_reset'),
path('accounts/', include('django.contrib.auth.urls')), path('accounts/', include('django.contrib.auth.urls')),
] ]

View File

@ -1,22 +1,33 @@
{% extends 'base.jinja2' %} {% extends 'base.jinja2' %}
{% import 'macros/form_macros.jinja2' as mform %} {% import 'macros/form_macros.jinja2' as mform %}
{% block content %} {% block content %}
<div class="col-12 "> <div class="col-12 ">
<div class="row justify-content-center justify-content-sm-center"> <div class="row justify-content-center justify-content-sm-center">
<div class="col-12 col-sm-8 col-md-7 col-lg-5 col-xl-4 bg-white text-dark p-3 mt-5 border"> <div class="col-12 col-sm-8 col-md-7 col-lg-5 col-xl-4 bg-white text-dark p-3 mt-5 border">
<h1 class="mb-4">Passwort ändern</h1> <h1 class="mb-4">Passwort ändern</h1>
<form method="post" class="floating-label-form"> <form method="post" class="floating-label-form">
<input type="hidden" name="csrfmiddlewaretoken" value="{{ csrf_token }}"> <input type="hidden" name="csrfmiddlewaretoken" value="{{ csrf_token }}">
{{ mform.password_input(form.old_password) }} <!-- {{form.errors}}-->
{{ mform.password_input(form.new_password1) }} <input type="password"
{{ mform.password_input(form.new_password2) }} class="form-control"
<div class="d-flex mt-4"> placeholder="Old password"
<button type="submit" class="btn btn-primary mr-auto p-2">Speichern</button> aria-describedby="id_old_password_help"
<a href="{{ url('realm-home')}}" name="old_password"
class="btn btn-secondary p-2">Abbrechen</a> id="id_old_password"
</div> maxlength="None"
</form> value="ralf"
</div> hidden>
<!-- {{ mform.password_input(form.old_password) }}-->
{{ mform.password_input(form.new_password1) }}
{{ mform.password_input(form.new_password2) }}
<div class="d-flex mt-4">
<button type="submit" class="btn btn-primary mr-auto p-2">Speichern</button>
<a href="{{ url('realm-home')}}"
class="btn btn-secondary p-2">Abbrechen</a>
</div>
</form>
</div> </div>
</div> </div>
</div>
{% endblock %} {% endblock %}

View File

@ -32,7 +32,7 @@
class="font-weight-bold">Email:</span> {{ user.user.email }}</li> class="font-weight-bold">Email:</span> {{ user.user.email }}</li>
<li class="list-group-item"><span <li class="list-group-item"><span
class="font-weight-bold">Passwort:</span> <a class="font-weight-bold">Passwort:</span> <a
href="{{ url('password_change') }}">Passwort ändern</a> href="{{ url('password_change_controller') }}">Passwort ändern</a>
</li> </li>
<li class="list-group-item"><span <li class="list-group-item"><span
class="font-weight-bold">Telefon:</span> {{ user.user.phone }}</li> class="font-weight-bold">Telefon:</span> {{ user.user.phone }}</li>