Fixes IndexError on save with removed member forwarding email (#11)

* Fixed IndexError if a non existent field gets queried for a value. Using dict.get to either get a value or provide a reasonable default
* Removed list construction around new_key value
* Clean up source code with 80x25 terminal and vim (complies with PEP-8)
* Added some docstrings
This commit is contained in:
Matthias 2020-12-05 23:23:19 +01:00 committed by GitHub
parent 4f093c0899
commit 09af25761c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 409 additions and 194 deletions

View file

@ -1,12 +1,6 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import ldap
import copy
from django.conf import settings
from account.password_encryption import get_ldap_password
"""
Example configuration:
@ -14,12 +8,30 @@ CBASE_LDAP_URL = 'ldap://lea.cbrp3.c-base.org:389/'
CBASE_BASE_DN = 'ou=crew,dc=c-base,dc=org'
"""
import copy
import logging
from django.conf import settings
import ldap
from account.password_encryption import get_ldap_password
LOGGER = logging.getLogger(__name__)
def retrieve_member(request):
"""
Gets a MemberValues object by its user name bound to a request object.
:param request:
:return: A MemberValues object
"""
ldap_password = get_ldap_password(request)
session = dict(request.session)
print("session:", session)
print("cookies:", request.COOKIES)
request_session = dict(request.session)
LOGGER.info("session: %s", request_session)
LOGGER.info("cookies: %s", request.COOKIES)
return MemberValues(request.user.username, ldap_password)
@ -29,6 +41,13 @@ class MemberValues(object):
"""
def __init__(self, username, password):
"""
Initializes a MemberValues object with all necessary parameters to
synchronize with an LDAP server.
:param username:
:param password:
"""
self._username = username
self._password = password
self._old = self._get_user_values()
@ -38,6 +57,12 @@ class MemberValues(object):
self._new = copy.deepcopy(self._old)
def get(self, key, default=None):
"""
Gets a member attribute value by key.
:param key:
:param default:
:return:
"""
value_list = self._new.get(key, default)
if value_list:
value = value_list[0]
@ -56,13 +81,19 @@ class MemberValues(object):
return value
def set(self, key, value):
if value == None:
"""
Sets a member attribute value for a key replacing the old value
:param key:
:param value:
:return:
"""
if value is None:
self._new[key] = [None]
return
converted_value = value
if isinstance(value, bool):
if value == True:
if value:
converted_value = 'TRUE'
else:
converted_value = 'FALSE'
@ -73,12 +104,13 @@ class MemberValues(object):
"""
Save the values back to the LDAP server.
"""
dn = "uid=%s,ou=crew,dc=c-base,dc=org" % self._username
user_dn = "uid=%s,ou=crew,dc=c-base,dc=org" % self._username
l = ldap.initialize(settings.CBASE_LDAP_URL)
l.simple_bind_s(dn, self._password)
session = ldap.initialize(settings.CBASE_LDAP_URL)
session.simple_bind_s(user_dn, self._password)
mod_attrs = []
action = None
for new_key, new_value in self._new.items():
# Replace is the default.
action = ldap.MOD_REPLACE
@ -86,36 +118,41 @@ class MemberValues(object):
action = ldap.MOD_ADD
mod_attrs.append((action, '%s' % new_key, new_value))
continue
if self._old[new_key][0] != None and new_value == [None]:
if self._old.get(new_key, [None])[0] is not None \
and new_value == [None]:
action = ldap.MOD_DELETE
mod_attrs.append((action, '%s' % new_key, []))
continue
# Set the attribute and wait for the LDAP server to complete.
if self._old[new_key][0] != new_value[0]:
continue
if self._old.get(new_key, [None])[0] != new_value[0]:
action = ldap.MOD_REPLACE
mod_attrs.append((action, '%s' % new_key, new_value))
continue
print("modattrs: ", mod_attrs)
result = l.modify_s(dn, mod_attrs)
#
# print("result is: ", result)
l.unbind_s()
LOGGER.debug("action: %s modattrs: %s", action, mod_attrs)
result = session.modify_s(user_dn, mod_attrs)
LOGGER.debug("result is: %s", result)
session.unbind_s()
return result # does not harm any1
def change_password(self, new_password):
"""
Change the password of the member.
You do not need to call save() after calling change_password().
"""
l = ldap.initialize(settings.CBASE_LDAP_URL)
session = ldap.initialize(settings.CBASE_LDAP_URL)
user_dn = self._get_bind_dn()
l.simple_bind_s(user_dn, self._password)
l.passwd_s(user_dn, self._password, new_password)
l.unbind_s()
session.simple_bind_s(user_dn, self._password)
session.passwd_s(user_dn, self._password, new_password)
session.unbind_s()
def to_dict(self):
"""
Converts a MembersValue object to a dict representation.
:return:
"""
result = {}
for key, value in self._new.items():
for key, _ in self._new.items():
result[key] = self.get(key)
return result
@ -139,17 +176,22 @@ class MemberValues(object):
session.simple_bind_s(self._get_bind_dn(), self._password)
# Set the attribute and wait for the LDAP server to complete.
searchScope = ldap.SCOPE_SUBTREE
search_scope = ldap.SCOPE_SUBTREE
# retrieve all attributes
retrieveAttributes = None
searchFilter = "uid=%s" % self._username
retrieve_attributes = None
search_filter = "uid=%s" % self._username
dn = settings.CBASE_BASE_DN
base_dn = settings.CBASE_BASE_DN
result = session.search_s(
dn, searchScope, searchFilter, retrieveAttributes)
base_dn,
search_scope,
search_filter,
retrieve_attributes
)
# TODO: latin1
print("result is: ", result)
LOGGER.info("result is: %s", result)
# TODO: if len(result)==0
session.unbind_s()
return result[0][1]
@ -159,11 +201,11 @@ class MemberValues(object):
Change the password of the member.
You do not need to call save() after calling change_password().
"""
l = ldap.initialize(settings.CBASE_LDAP_URL)
session = ldap.initialize(settings.CBASE_LDAP_URL)
user_dn = self._get_bind_dn()
l.simple_bind_s(user_dn, self._password)
l.passwd_s(self._get_bind_dn(username), None, new_password)
l.unbind_s()
session.simple_bind_s(user_dn, self._password)
session.passwd_s(self._get_bind_dn(username), None, new_password)
session.unbind_s()
def get_number_of_members(self):
"""
@ -176,22 +218,26 @@ class MemberValues(object):
Returns a list of strings with all usernames in the group 'crew'.
The list is sorted alphabetically.
"""
l = ldap.initialize(settings.CBASE_LDAP_URL)
session = ldap.initialize(settings.CBASE_LDAP_URL)
user_dn = self._get_bind_dn()
l.simple_bind_s(user_dn, self._password)
session.simple_bind_s(user_dn, self._password)
try:
result_id = l.search(settings.CBASE_BASE_DN, ldap.SCOPE_SUBTREE,
"memberOf=cn=crew,ou=groups,dc=c-base,dc=org", None)
result_id = session.search(
settings.CBASE_BASE_DN,
ldap.SCOPE_SUBTREE,
"memberOf=cn=crew,ou=groups,dc=c-base,dc=org",
None
)
result_set = []
while True:
result_type, result_data = l.result(result_id, 0)
if (result_data == []):
result_type, result_data = session.result(result_id, 0)
if not result_data:
break
else:
if result_type == ldap.RES_SEARCH_ENTRY:
result_set.append(result_data)
# list comprehension to get a list of user tupels in the format ("nickname", "nickname (real name)")
# list comprehension to get a list of user tupels in the
# format ("nickname", "nickname (real name)")
userlist = [(
x[0][1]['uid'][0].decode(),
'%s (%s, %s)' % (
@ -202,4 +248,5 @@ class MemberValues(object):
) for x in result_set]
return sorted(userlist)
except Exception:
LOGGER.exception('list_users failed')
return []

View file

@ -7,13 +7,15 @@ from django import forms
from django.contrib.auth import authenticate
from django.utils.translation import ugettext as _
class UsernameField(forms.CharField):
"""
The username field makes sure that usernames are always entered in lower-case.
If we do not convert the username to lower-case, Django will create more than
one user object in the database. If we then try to login again, the Django auth
subsystem will do an query that looks like this: username__iexact="username". The
result is an error, because iexact returns the objects for "username" and "Username".
The username field makes sure that usernames are always entered in
lower-case. If we do not convert the username to lower-case, Django will
create more than one user object in the database. If we then try to login
again, the Django auth subsystem will do an query that looks like this:
username__iexact="username". The result is an error, because iexact returns
the objects for "username" and "Username".
"""
def to_python(self, value):
@ -24,7 +26,8 @@ class UsernameField(forms.CharField):
class LoginForm(forms.Form):
username = UsernameField(max_length=255)
password = forms.CharField(max_length=255, widget=forms.PasswordInput,
password = forms.CharField(
max_length=255, widget=forms.PasswordInput,
help_text=_('Cookies must be enabled.'))
def clean(self):
@ -32,8 +35,13 @@ class LoginForm(forms.Form):
password = self.cleaned_data.get('password')
user = authenticate(username=username, password=password)
if not user or not user.is_active:
raise forms.ValidationError(_('Sorry, that login was invalid. '
'Please try again.'), code='invalid_login')
raise forms.ValidationError(
_(
'Sorry, that login was invalid. '
'Please try again.'
),
code='invalid_login'
)
return self.cleaned_data
def login(self, request):
@ -45,6 +53,7 @@ class LoginForm(forms.Form):
class GastroPinField(forms.CharField):
widget = forms.PasswordInput
def validate(self, value):
"""
Check if the value is all numeric and 4 - 8 chars long.
@ -56,7 +65,8 @@ class GastroPinField(forms.CharField):
class GastroPinForm(forms.Form):
gastropin1 = GastroPinField(label=_('New Gastro-PIN'))
gastropin2 = GastroPinField(label=_('Repeat Gastro-PIN'),
gastropin2 = GastroPinField(
label=_('Repeat Gastro-PIN'),
help_text=_('Numerical only, 4 to 8 digits'))
def clean(self):
@ -67,24 +77,33 @@ class GastroPinForm(forms.Form):
if gastropin1 != gastropin2:
raise forms.ValidationError(
_('The PINs entered were not identical.'),
code='not_identical')
code='not_identical'
)
return cleaned_data
class WlanPresenceForm(forms.Form):
# Boolean fields must never be required.
presence = forms.BooleanField(required=False,
label=_('Enable WiFi presence'))
presence = forms.BooleanField(
required=False,
label=_('Enable WiFi presence')
)
class PasswordForm(forms.Form):
old_password = forms.CharField(max_length=255, widget=forms.PasswordInput,
old_password = forms.CharField(
max_length=255, widget=forms.PasswordInput,
label=_('Old password'),
help_text=_('Enter your current password here.'))
password1 = forms.CharField(max_length=255, widget=forms.PasswordInput,
label=_('New password'))
password2 = forms.CharField(max_length=255, widget=forms.PasswordInput,
label=_('Repeat password'))
help_text=_(
'Enter your current password here.'))
password1 = forms.CharField(
max_length=255, widget=forms.PasswordInput,
label=_('New password')
)
password2 = forms.CharField(
max_length=255, widget=forms.PasswordInput,
label=_('Repeat password')
)
def __init__(self, *args, **kwargs):
self._request = kwargs.pop('request', None)
@ -97,8 +116,12 @@ class PasswordForm(forms.Form):
user = authenticate(username=username, password=old_password)
if not user or not user.is_active:
raise forms.ValidationError(_('The old password was incorrect.'),
code='old_password_wrong')
raise forms.ValidationError(
_(
'The old password was incorrect.'
),
code='old_password_wrong'
)
password1 = cleaned_data.get('password1')
password2 = cleaned_data.get('password2')
@ -115,9 +138,14 @@ class PasswordForm(forms.Form):
class RFIDForm(forms.Form):
rfid = forms.CharField(max_length=255, label=_('Your RFID'),
help_text=_('Find out your RFID by holding your RFID tag to the '
'reader in the airlock.'))
rfid = forms.CharField(
max_length=255,
label=_('Your RFID'),
help_text=_(
'Find out your RFID by holding your RFID tag to the '
'reader in the airlock.'
)
)
class SIPPinForm(forms.Form):
@ -135,30 +163,44 @@ class SIPPinForm(forms.Form):
class NRF24Form(forms.Form):
nrf24 = forms.CharField(max_length=255,
label = _('NRF24-ID'),
help_text=_("Your r0ket's NRF24 identification"))
nrf24 = forms.CharField(
max_length=255,
label=_('NRF24-ID'),
help_text=_("Your r0ket's NRF24 identification")
)
class CLabPinForm(forms.Form):
c_lab_pin1 = GastroPinField(label=_('New indoor PIN'))
c_lab_pin2 = GastroPinField(label=_('Repeat indoor PIN'),
help_text=_('Numerical only, 4 to 8 digits'))
c_lab_pin2 = GastroPinField(
label=_('Repeat indoor PIN'),
help_text=_('Numerical only, 4 to 8 digits')
)
class PreferredEmailForm(forms.Form):
preferred_email = forms.EmailField(max_length=255, required=False,
label = _('Preferred e-mail'),
help_text=_("Forward my mail to this address. Leave empty to use the c-base IMAP and SMTP servers."))
preferred_email = forms.EmailField(
max_length=255, required=False,
label=_('Preferred e-mail'),
help_text=_(
"Forward my mail to this address. Leave empty to use the c-base "
"IMAP and SMTP servers."
)
)
class AdminForm(forms.Form):
username = forms.ChoiceField(choices=[])
password1 = forms.CharField(max_length=255, widget=forms.PasswordInput,
label=_('New password'))
password2 = forms.CharField(max_length=255, widget=forms.PasswordInput,
label=_('Repeat password'))
password1 = forms.CharField(
max_length=255,
widget=forms.PasswordInput,
label=_('New password')
)
password2 = forms.CharField(
max_length=255,
widget=forms.PasswordInput,
label=_('Repeat password')
)
def __init__(self, *args, **kwargs):
self._request = kwargs.pop('request', None)
@ -166,10 +208,23 @@ class AdminForm(forms.Form):
choices = [x for x in self._users]
choices.insert(0, ('', 'Select username ...'))
super(AdminForm, self).__init__(*args, **kwargs)
#self.fields.insert(0, 'username', forms.ChoiceField(choices=choices,
#help_text=_('Select the username for whom you want to reset the password.')))
self.fields['username'] = forms.ChoiceField(choices=choices,
help_text=_('Select the username for whom you want to reset the password.'))
# self.fields.insert(
# 0,
# 'username',
# forms.ChoiceField(
# choices=choices,
# help_text=_(
# 'Select the username for whom you want '
# 'to reset the password.'
# )
# )
# )
self.fields['username'] = forms.ChoiceField(
choices=choices,
help_text=_(
'Select the username for whom you want to reset the password.'
)
)
def clean(self):
cleaned_data = super(AdminForm, self).clean()
@ -179,11 +234,13 @@ class AdminForm(forms.Form):
if password1 != password2:
raise forms.ValidationError(
_('The new passwords were not identical.'),
code='not_identical')
code='not_identical'
)
if len(password1) < 6:
raise forms.ValidationError(
_('Password must be at least 6 characters long'),
code='to_short')
code='to_short'
)
return cleaned_data

View file

@ -1,43 +1,73 @@
from django.db import models
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Django models
"""
from django.contrib.auth.models import User
from django.db import models
from django.db.models import signals
from account.signals import create_profile, delete_profile
class UserProfile(models.Model):
user = models.OneToOneField(User, editable=False, on_delete=models.CASCADE)
uid = models.CharField(verbose_name="User-ID",
"""
UserProfile to be attached to a django User model.
"""
user = models.OneToOneField(
User,
editable=False,
on_delete=models.CASCADE
)
uid = models.CharField(
verbose_name="User-ID",
max_length=8,
null=True,
default=None)
sippin = models.CharField(verbose_name="SIP PIN",
default=None
)
sippin = models.CharField(
verbose_name="SIP PIN",
max_length=255,
null=True,
blank=True,
default=None)
gastropin = models.CharField(verbose_name="Gastro PIN",
default=None
)
gastropin = models.CharField(
verbose_name="Gastro PIN",
max_length=255,
null=True,
blank=True,
default=None)
rfid = models.CharField(verbose_name="RFID",
default=None
)
rfid = models.CharField(
verbose_name="RFID",
max_length=255,
null=True,
blank=True,
default=None)
macaddress = models.CharField(verbose_name="MAC-Address",
default=None
)
macaddress = models.CharField(
verbose_name="MAC-Address",
max_length=255,
null=True,
blank=True,
default=None)
clabpin = models.CharField(verbose_name="c-lab PIN",
default=None
)
clabpin = models.CharField(
verbose_name="c-lab PIN",
max_length=255,
null=True,
blank=True,
default=None)
preferred_email = models.CharField(verbose_name="preferred e-mail address",
default=None
)
preferred_email = models.CharField(
verbose_name="preferred e-mail address",
max_length=1024,
null=True,
default=None)
default=None
)
is_member = models.BooleanField(default=False, editable=False)
is_ldap_admin = models.BooleanField(default=False, editable=False)
is_circle_member = models.BooleanField(default=False, editable=False)
@ -49,6 +79,7 @@ class UserProfile(models.Model):
def __unicode__(self):
return 'Profile: %s' % self.user.username
User.profile = property(lambda u: UserProfile.objects.get_or_create(user=u)[0])
signals.post_save.connect(create_profile, sender=User)
signals.pre_delete.connect(delete_profile, sender=User)

View file

@ -8,6 +8,7 @@ from Crypto.Cipher import AES
ENCRYPTED_LDAP_PASSWORD = 'encrypted_ldap_password'
def encrypt_ldap_password(cleartext_pw):
"""
Encrypts the cleartext_pw with a randomly generated key.
@ -28,6 +29,7 @@ def encrypt_ldap_password(cleartext_pw):
message = iv + aes.encrypt(cleartext_pw)
return base64.b64encode(message).decode(), base64.b64encode(key).decode()
def decrypt_ldap_password(message, key):
"""
Takes an encrypted, base64 encoded password and the base64 encoded key.
@ -47,6 +49,7 @@ def decrypt_ldap_password(message, key):
cleartext_pw = aes.decrypt(ciphertext)
return cleartext_pw
def store_ldap_password(request, password):
"""
Stores the password in an encrypted session storage and returns the key.
@ -56,6 +59,7 @@ def store_ldap_password(request, password):
request.session.save()
return key
def get_ldap_password(request):
cookies = request.COOKIES
key = cookies.get('sessionkey', None)

View file

@ -4,6 +4,7 @@ def create_profile(sender, instance, signal, created, **kwargs):
if created:
UserProfile(user=instance).save()
def delete_profile(sender, instance, signal, **kwargs):
from account.models import UserProfile
UserProfile(user=instance).delete()

View file

@ -6,7 +6,9 @@ Replace this with more appropriate tests for your application.
"""
from django.test import TestCase
from password_encryption import encrypt_ldap_password, decrypt_ldap_password
from account.password_encryption import encrypt_ldap_password, \
decrypt_ldap_password
class PasswordEncryptionTest(TestCase):
"""
@ -22,7 +24,6 @@ class PasswordEncryptionTest(TestCase):
print('key:', key)
print('message:', message)
def test_decrypt_ldap_password(self):
message, key = self.encrypt_it()
decrypted = decrypt_ldap_password(message, key)

View file

@ -1,29 +1,30 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import hashlib
import smbpasswd
import requests
import collections
import hashlib
import os
import requests
from django.conf import settings
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render_to_response
from django.template.context import RequestContext
from django.contrib.auth import login, logout, authenticate
from django.contrib.auth.models import User
from django.shortcuts import get_object_or_404
from django.contrib.auth import login, logout
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import Group
from django.contrib.auth.models import User
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import get_object_or_404
from django.shortcuts import render
from django.shortcuts import render_to_response
from django.utils.translation import ugettext as _
from account.forms import GastroPinForm, WlanPresenceForm, LoginForm, PasswordForm, \
RFIDForm, NRF24Form, SIPPinForm, CLabPinForm, AdminForm, PreferredEmailForm
import smbpasswd
from account.cbase_members import retrieve_member, MemberValues
from account.forms import GastroPinForm, WlanPresenceForm, LoginForm, \
PasswordForm, RFIDForm, NRF24Form, SIPPinForm, CLabPinForm, AdminForm, \
PreferredEmailForm
from account.password_encryption import *
def landingpage(request):
if request.user.is_authenticated:
return HttpResponseRedirect('/account')
@ -31,7 +32,7 @@ def landingpage(request):
try:
# just in case the group hasn't yet been synced
admins = Group.objects.get(name="ldap_admins").user_set.all()
except:
except Exception:
# else provide an emtpy list
admins = []
@ -42,7 +43,7 @@ def landingpage(request):
try:
user = User.objects.get(username=check_nickname)
check_nickname = True
except:
except Exception:
check_nickname = False
# output as text if requested
@ -51,6 +52,7 @@ def landingpage(request):
return render(request, 'base.html', locals())
def auth_login(request):
redirect_to = request.GET.get('next', '') or '/'
if request.method == 'POST':
@ -76,6 +78,7 @@ def auth_login(request):
form = LoginForm()
return render(request, 'login.html', {'form': form})
@login_required
def home(request):
member = retrieve_member(request)
@ -85,17 +88,23 @@ def home(request):
url = "https://vorstand.c-base.org/cteward-api/legacy/member/%s" % username
cteward = None
try:
r = requests.get(url, verify=False, auth=(username, password))
r = requests.get(
url,
verify=False,
auth=(username, password)
)
cteward = r.json()
except Exception:
pass
context = {'member': member.to_dict(),
context = {
'member': member.to_dict(),
'groups': list(request.user.groups.all().order_by('name')),
'number_of_members': number_of_members,
'cteward': cteward,
}
return render(request, 'home.html', context)
@login_required
def auth_logout(request):
request.session.pop(ENCRYPTED_LDAP_PASSWORD)
@ -105,7 +114,8 @@ def auth_logout(request):
response.delete_cookie('sessionkey')
return response
@login_required(redirect_field_name="/" ,login_url="/account/login/")
@login_required(redirect_field_name="/", login_url="/account/login/")
def groups_list(request, group_name):
group = get_object_or_404(Group, name=group_name)
groups = Group.objects.all()
@ -115,10 +125,16 @@ def groups_list(request, group_name):
is_admin = True
return render_to_response("group_list.html", locals())
@login_required
def sippin(request):
return set_ldap_field(request, SIPPinForm, [('sippin', 'sippin')],
'sippin.html')
return set_ldap_field(
request,
SIPPinForm,
[('sippin', 'sippin')],
'sippin.html'
)
def set_hash_field(request, form_type, in_field, out_field, hash_func,
template_name):
@ -136,16 +152,35 @@ def set_hash_field(request, form_type, in_field, out_field, hash_func,
member.set(out_field, hashed_value)
member.save()
new_form = form_type(initial=initial)
return render(request, template_name,
{'message': _('Your changes have been saved. Thank you!'),
'form': new_form, 'member': member.to_dict()})
return render(
request,
template_name,
{
'message': _('Your changes have been saved. Thank you!'),
'form': new_form,
'member': member.to_dict()
}
)
else:
return render(request, template_name,
{'form': form, 'member': member.to_dict()})
return render(
request,
template_name,
{
'form': form,
'member': member.to_dict()
}
)
else:
form = form_type(initial=initial)
return render(request, template_name,
{'form': form, 'member': member.to_dict()})
return render(
request,
template_name,
{
'form': form,
'member': member.to_dict()
}
)
@login_required
def gastropin(request):
@ -154,23 +189,32 @@ def gastropin(request):
bla = '%s%s' % (key, pin)
return hashlib.sha256(bla.encode()).hexdigest()
return set_hash_field(request, GastroPinForm,
'gastropin1', 'gastroPIN', calculate_gastro_hash, 'gastropin.html')
return set_hash_field(
request,
GastroPinForm,
'gastropin1',
'gastroPIN',
calculate_gastro_hash,
'gastropin.html'
)
@login_required
def clabpin(request):
# if len(request.user.groups.filter(name__in=['cey-c-lab', 'cey-schleuse', 'cey-soundlab'])) < 1:
# names = ['cey-c-lab', 'cey-schleuse', 'cey-soundlab']
# if len(request.user.groups.filter(name__in=names)) < 1:
# return render(request, 'access_denied.html')
def calculate_clab_hash(pin):
salt = os.urandom(12)
digest = hashlib.sha1(bytearray(pin, 'UTF-8')+salt).digest()
digest = hashlib.sha1(bytearray(pin, 'UTF-8') + salt).digest()
pin_hash = '{SSHA}%s' % base64.b64encode(digest + salt).decode()
return pin_hash
return set_hash_field(request, CLabPinForm, 'c_lab_pin1', 'c-labPIN',
calculate_clab_hash, 'clabpin.html')
@login_required
def password(request):
"""
@ -196,7 +240,8 @@ def password(request):
request.session.save()
new_form = PasswordForm()
response = render(request, 'password.html',
{'message': _('Your password was changed. Thank you!'),
{'message': _(
'Your password was changed. Thank you!'),
'form': new_form, 'member': member.to_dict()})
response.set_cookie('sessionkey', key)
return response
@ -208,6 +253,7 @@ def password(request):
return render(request, 'password.html',
{'form': form, 'member': member.to_dict()})
def set_ldap_field(request, form_type, field_names, template_name):
"""
Abstract view for each of the different forms.
@ -230,7 +276,8 @@ def set_ldap_field(request, form_type, field_names, template_name):
member.save()
new_form = form_type(initial=initial)
return render(request, template_name,
{'message': _('Your changes have been saved. Thank you!'),
{'message': _(
'Your changes have been saved. Thank you!'),
'form': new_form, 'member': member.to_dict()})
else:
return render(request, template_name,
@ -242,24 +289,31 @@ def set_ldap_field(request, form_type, field_names, template_name):
return render(request, template_name,
{'form': form, 'member': member.to_dict()})
@login_required
def wlan_presence(request):
return set_ldap_field(request, WlanPresenceForm,
[('presence', 'wlanPresence')], 'wlan_presence.html')
@login_required
def rfid(request):
return set_ldap_field(request, RFIDForm, [('rfid', 'rfid')], 'rfid.html')
@login_required
def nrf24(request):
return set_ldap_field(request, NRF24Form, [('nrf24', 'nrf24')], 'nrf24.html')
return set_ldap_field(request, NRF24Form, [('nrf24', 'nrf24')],
'nrf24.html')
@login_required
def preferred_email(request):
return set_ldap_field(request, PreferredEmailForm, [('preferred_email', 'preferredEmail')],
return set_ldap_field(request, PreferredEmailForm,
[('preferred_email', 'preferredEmail')],
'preferred_email.html')
@login_required
def admin(request):
admin_member = retrieve_member(request)
@ -271,7 +325,8 @@ def admin(request):
if form.is_valid():
new_password = form.cleaned_data['password1']
admin_member.admin_change_password(form.cleaned_data['username'], new_password)
admin_member.admin_change_password(form.cleaned_data['username'],
new_password)
member = MemberValues(form.cleaned_data['username'], new_password)
member.set('sambaLMPassword', smbpasswd.lmhash(new_password))
@ -280,7 +335,9 @@ def admin(request):
new_form = AdminForm(request=request, users=users)
return render(request, 'admin.html',
{'message': _('The password for %s was changed. Thank you!' % form.cleaned_data['username']),
{'message': _(
'The password for %s was changed. Thank you!' %
form.cleaned_data['username']),
'form': new_form})
else:
return render(request, 'admin.html',
@ -290,32 +347,49 @@ def admin(request):
return render(request, 'admin.html',
{'form': form})
#username = cleaned_data.get('username')
#admin_username = self._request.user.username
#admin_password = self._request.session['ldap_password']
# username = cleaned_data.get('username')
# admin_username = self._request.user.username
# admin_password = self._request.session['ldap_password']
def hammertime(request):
return render(request, 'hammertime.html', {})
@login_required
def memberstatus(request):
#url = baseurl + route_operation_mapping['SessionCreate']['Route']
#data = json.dumps({'UserLogin': username, 'Password': password})
# url = baseurl + route_operation_mapping['SessionCreate']['Route']
# data = json.dumps({'UserLogin': username, 'Password': password})
password = get_ldap_password(request)
username = request.user.username
url = "https://vorstand.c-base.org/cteward-api/legacy/member/%s/contributions" % username
r = requests.get(url, verify=False, auth=(username, password))
url = "https://vorstand.c-base.org" \
"/cteward-api/legacy/member/%s/contributions" % username
r = requests.get(
url,
verify=False,
auth=(username, password)
)
contributions = r.json()
try:
years = collections.OrderedDict(sorted(contributions['years'].items(), reverse=True))
years = collections.OrderedDict(
sorted(contributions['years'].items(), reverse=True))
contributions['years'] = years.items()
except: pass
except:
pass
url = "https://vorstand.c-base.org/cteward-api/legacy/member/%s" % username
r = requests.get(url, verify=False, auth=(username, password))
r = requests.get(
url,
verify=False,
auth=(username, password)
)
cteward = r.json()
return render(request, 'memberstatus.html', {'contributions': contributions, 'cteward': cteward})
return render(
request, 'memberstatus.html',
{
'contributions': contributions,
'cteward': cteward
}
)