From e0f53cd529deebd552d41a5d18bee95482fe77a7 Mon Sep 17 00:00:00 2001 From: Uwe Kamper Date: Tue, 22 Oct 2013 22:26:22 +0200 Subject: [PATCH 1/4] local_settings.py wird ignoriert --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 99ec428..efc1dfb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ *.pyc .idea +local_settings.py From 032bc5acaa1c36acac7591d75553d47e01bc4528 Mon Sep 17 00:00:00 2001 From: Uwe Kamper Date: Wed, 23 Oct 2013 00:27:31 +0200 Subject: [PATCH 2/4] added form and view for changing gastro-PINs --- .gitignore | 2 ++ account/forms.py | 2 ++ cbmi/forms.py | 21 +++++++++++++ cbmi/local_settings.py.smile | 57 +++++++++++++++++++++++++++++++++++ cbmi/local_settings.py.uk | 57 +++++++++++++++++++++++++++++++++++ cbmi/settings.py | 5 +++ cbmi/templates/gastropin.html | 20 ++++++++++++ cbmi/urls.py | 3 +- cbmi/views.py | 24 +++++++++++++++ manage.py | 0 requirements.txt | 2 +- 11 files changed, 191 insertions(+), 2 deletions(-) create mode 100644 cbmi/forms.py create mode 100644 cbmi/local_settings.py.smile create mode 100644 cbmi/local_settings.py.uk create mode 100644 cbmi/templates/gastropin.html mode change 100644 => 100755 manage.py diff --git a/.gitignore b/.gitignore index efc1dfb..db472e5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ *.pyc .idea local_settings.py +build +*.sqlite3 diff --git a/account/forms.py b/account/forms.py index 1eec70f..1f840d2 100644 --- a/account/forms.py +++ b/account/forms.py @@ -4,3 +4,5 @@ from django import forms class LoginForm(forms.Form): username = forms.CharField(max_length=255) password = forms.CharField(max_length=255, widget=forms.PasswordInput) + + diff --git a/cbmi/forms.py b/cbmi/forms.py new file mode 100644 index 0000000..93e4003 --- /dev/null +++ b/cbmi/forms.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import re + +from django import forms +from django.utils.translation import ugettext as _ + + +class GastroPinField(forms.CharField): + def validate(self, value): + """ + Check if the value is all numeric and 4 - 6 chars long. + """ + match = re.match(r'^\d{4,6}$', value) + if not match: + raise forms.ValidationError(_('PIN must be 4 to 6 digits.')) + + +class GastroPinForm(forms.Form): + gastropin = GastroPinField() \ No newline at end of file diff --git a/cbmi/local_settings.py.smile b/cbmi/local_settings.py.smile new file mode 100644 index 0000000..1ea4e09 --- /dev/null +++ b/cbmi/local_settings.py.smile @@ -0,0 +1,57 @@ +# Django settings for cbmi project. + +DEBUG = True +TEMPLATE_DEBUG = DEBUG + +ADMINS = ( + ('Brian Wiborg', 'baccenfutter@c-base.org') + # ('Your Name', 'your_email@example.com'), +) + +MANAGERS = ADMINS + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': 'cbmi.sqlite3', + 'USER': '', + 'PASSWORD': '', + 'HOST': '', + 'PORT': '', + } +} + +# Absolute filesystem path to the directory that will hold user-uploaded files. +# Example: "/home/media/media.lawrence.com/media/" +MEDIA_ROOT = '' + +# URL that handles the media served from MEDIA_ROOT. Make sure to use a +# trailing slash. +# Examples: "http://media.lawrence.com/media/", "http://example.com/media/" +MEDIA_URL = '' + +# Absolute path to the directory static files should be collected to. +# Don't put anything in this directory yourself; store your static files +# in apps' "static/" subdirectories and in STATICFILES_DIRS. +# Example: "/home/media/media.lawrence.com/static/" +STATIC_ROOT = '' + +# URL prefix for static files. +# Example: "http://media.lawrence.com/static/" +STATIC_URL = '/static/' + +# Additional locations of static files +STATICFILES_DIRS = ( + # Put strings here, like "/home/html/static" or "C:/www/django/static". + # Always use forward slashes, even on Windows. + # Don't forget to use absolute paths, not relative paths. + '/home/smile/projects/cbmi/src/static', +) + +TEMPLATE_DIRS = ( + # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". + # Always use forward slashes, even on Windows. + # Don't forget to use absolute paths, not relative paths. +) + +AUTH_LDAP_START_TLS = False diff --git a/cbmi/local_settings.py.uk b/cbmi/local_settings.py.uk new file mode 100644 index 0000000..1ea4e09 --- /dev/null +++ b/cbmi/local_settings.py.uk @@ -0,0 +1,57 @@ +# Django settings for cbmi project. + +DEBUG = True +TEMPLATE_DEBUG = DEBUG + +ADMINS = ( + ('Brian Wiborg', 'baccenfutter@c-base.org') + # ('Your Name', 'your_email@example.com'), +) + +MANAGERS = ADMINS + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': 'cbmi.sqlite3', + 'USER': '', + 'PASSWORD': '', + 'HOST': '', + 'PORT': '', + } +} + +# Absolute filesystem path to the directory that will hold user-uploaded files. +# Example: "/home/media/media.lawrence.com/media/" +MEDIA_ROOT = '' + +# URL that handles the media served from MEDIA_ROOT. Make sure to use a +# trailing slash. +# Examples: "http://media.lawrence.com/media/", "http://example.com/media/" +MEDIA_URL = '' + +# Absolute path to the directory static files should be collected to. +# Don't put anything in this directory yourself; store your static files +# in apps' "static/" subdirectories and in STATICFILES_DIRS. +# Example: "/home/media/media.lawrence.com/static/" +STATIC_ROOT = '' + +# URL prefix for static files. +# Example: "http://media.lawrence.com/static/" +STATIC_URL = '/static/' + +# Additional locations of static files +STATICFILES_DIRS = ( + # Put strings here, like "/home/html/static" or "C:/www/django/static". + # Always use forward slashes, even on Windows. + # Don't forget to use absolute paths, not relative paths. + '/home/smile/projects/cbmi/src/static', +) + +TEMPLATE_DIRS = ( + # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". + # Always use forward slashes, even on Windows. + # Don't forget to use absolute paths, not relative paths. +) + +AUTH_LDAP_START_TLS = False diff --git a/cbmi/settings.py b/cbmi/settings.py index 94a050a..f322292 100644 --- a/cbmi/settings.py +++ b/cbmi/settings.py @@ -199,3 +199,8 @@ LOGGING = { }, } } + +try: + from local_settings import * +except ImportError, e: + print 'Unable to load local_settings.py:', e diff --git a/cbmi/templates/gastropin.html b/cbmi/templates/gastropin.html new file mode 100644 index 0000000..b1480f1 --- /dev/null +++ b/cbmi/templates/gastropin.html @@ -0,0 +1,20 @@ +{% extends "base.html" %} + +{% block body %} +
+
+
+

Gastro-Pin

+ {% if message %} +
{{ message }}
+ {% endif %} +
+ {{ form.non_field_errors }} + {% csrf_token %} + {{ form.as_p }} + +
+
+
+
+{% endblock %} diff --git a/cbmi/urls.py b/cbmi/urls.py index b0f696d..72d5a43 100644 --- a/cbmi/urls.py +++ b/cbmi/urls.py @@ -11,5 +11,6 @@ urlpatterns = patterns('', url(r'account/', include('account.urls')), url(r'^groups/(?P[^/]+)/', 'cbmi.views.groups_list'), - url(r'^$', 'cbmi.views.landingpage') + url(r'^$', 'cbmi.views.landingpage'), + url(r'^gastropin/$', 'cbmi.views.gastropin', name='gastropin'), ) diff --git a/cbmi/views.py b/cbmi/views.py index 8d9300d..e9d306b 100644 --- a/cbmi/views.py +++ b/cbmi/views.py @@ -1,8 +1,12 @@ from django.shortcuts import render_to_response, get_object_or_404 from django.contrib.auth.decorators import login_required from django.contrib.auth.models import Group +from django.shortcuts import render +from django.utils.translation import ugettext as _ +from forms import GastroPinForm + def landingpage(request): is_ceymaster = is_admin = False if 'ceymaster' in [g.name for g in request.user.groups.all()]: @@ -25,3 +29,23 @@ def groups_list(request, group_name): if 'ldap_admins' in [g.name for g in request.user.groups.all()]: is_admin = True return render_to_response("group_list.html", locals()) + +@login_required +def gastropin(request): + if request.method == 'POST': + form = GastroPinForm(request.POST) + if form.is_valid(): + user = request.user + user_profile = user.get_profile() + user_profile.gastropin = form.cleaned_data['gastropin'] + user_profile.save() + return render(request, 'gastropin.html', + {'message': _('Your Gastro-PIN was changed. Thank you!'), + 'form:': form}) + else: + return render(request, 'gastropin.html', {'form:': form}) + + else: + form = GastroPinForm() + + return render(request, 'gastropin.html', {'form': form}) diff --git a/manage.py b/manage.py old mode 100644 new mode 100755 diff --git a/requirements.txt b/requirements.txt index 8063f0b..5a224e6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ Django==1.4.2 MySQL-python==1.2.4 -django-auth-ldap==1.1.4 + django-auth-ldap==1.1.4 django-json-rpc==0.6.1 From 0aade5be9411caf31c9906aa9dfbab58ef785fac Mon Sep 17 00:00:00 2001 From: Uwe Kamper Date: Thu, 24 Oct 2013 01:49:46 +0200 Subject: [PATCH 3/4] setting wifi presence --- account/forms.py | 1 - account/templates/dashboard.html | 6 +- account/urls.py | 4 +- account/views.py | 26 ++++--- cbmi/forms.py | 7 +- cbmi/settings.py | 12 +++ cbmi/templates/base.html | 15 +++- cbmi/templates/group_list.html | 7 +- cbmi/templates/wlan_presence.html | 43 +++++++++++ cbmi/urls.py | 3 + cbmi/views.py | 120 +++++++++++++++++++++++++++++- 11 files changed, 220 insertions(+), 24 deletions(-) create mode 100644 cbmi/templates/wlan_presence.html diff --git a/account/forms.py b/account/forms.py index 1f840d2..b6a3650 100644 --- a/account/forms.py +++ b/account/forms.py @@ -1,6 +1,5 @@ from django import forms - class LoginForm(forms.Form): username = forms.CharField(max_length=255) password = forms.CharField(max_length=255, widget=forms.PasswordInput) diff --git a/account/templates/dashboard.html b/account/templates/dashboard.html index ff65e1c..87b9e79 100644 --- a/account/templates/dashboard.html +++ b/account/templates/dashboard.html @@ -1,7 +1,6 @@ {% extends "base.html" %} -{% block body %} -
+{% block container %}

{{ request.user.username }}

@@ -29,5 +28,4 @@ {% endfor %}
-
-{% endblock body %} +{% endblock container %} diff --git a/account/urls.py b/account/urls.py index 6e24af4..8370e0f 100644 --- a/account/urls.py +++ b/account/urls.py @@ -3,6 +3,6 @@ from django.conf.urls import patterns, url urlpatterns = patterns( '', - url(r'^login/$', 'account.views.auth_login'), - url(r'^logout/$', 'account.views.auth_logout'), + url(r'^login/$', 'account.views.auth_login', name="auth_login"), + url(r'^logout/$', 'account.views.auth_logout', name="auth_logout"), ) \ No newline at end of file diff --git a/account/views.py b/account/views.py index 9e36077..a13ebf8 100644 --- a/account/views.py +++ b/account/views.py @@ -1,3 +1,6 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + from django.http import HttpResponseRedirect from django.shortcuts import render_to_response from django.template.context import RequestContext @@ -6,9 +9,8 @@ from django.contrib.auth.models import User from account.forms import LoginForm - def auth_login(request): - redirect_to = request.REQUEST.get('next', '') or '/' + redirect_to = request.GET.get('next', '') or '/' if request.method == 'POST': form = LoginForm(request.POST) if form.is_valid(): @@ -18,20 +20,26 @@ def auth_login(request): if user is not None: if user.is_active: login(request, user) - member, created = User.objects.get_or_create( - username=username) + member, created = \ + User.objects.get_or_create(username=username) if created: member.save() - return HttpResponseRedirect(redirect_to) + # save password in the session for later use with LDAP + request.session['ldap_password'] = password + response = HttpResponseRedirect(redirect_to) + response.set_cookie('sessionkey', 'bla') + return response else: print 'user is none' else: form = LoginForm() - return render_to_response('login.html', - RequestContext(request, locals())) + return render_to_response('login.html', + RequestContext(request, locals())) def auth_logout(request): - redirect_to = request.REQUEST.get('next', '') or '/' + redirect_to = request.GET.get('next', '') or '/' logout(request) - return HttpResponseRedirect(redirect_to) + response = HttpResponseRedirect(redirect_to) + response.delete_cookie('sessionkey') + return response diff --git a/cbmi/forms.py b/cbmi/forms.py index 93e4003..d06bbe6 100644 --- a/cbmi/forms.py +++ b/cbmi/forms.py @@ -18,4 +18,9 @@ class GastroPinField(forms.CharField): class GastroPinForm(forms.Form): - gastropin = GastroPinField() \ No newline at end of file + gastropin = GastroPinField() + + +class WlanPresenceForm(forms.Form): + # Boolean fields must never be required. + presence = forms.BooleanField(required=False) \ No newline at end of file diff --git a/cbmi/settings.py b/cbmi/settings.py index f322292..8db3812 100644 --- a/cbmi/settings.py +++ b/cbmi/settings.py @@ -88,6 +88,16 @@ TEMPLATE_LOADERS = ( 'django.template.loaders.app_directories.Loader', # 'django.template.loaders.eggs.Loader', ) +TEMPLATE_CONTEXT_PROCESSORS = ( + "django.contrib.auth.context_processors.auth", + "django.core.context_processors.debug", + "django.core.context_processors.i18n", + "django.core.context_processors.media", + "django.core.context_processors.static", + "django.core.context_processors.tz", + "django.contrib.messages.context_processors.messages", + "django.core.context_processors.request" +) MIDDLEWARE_CLASSES = ( 'django.middleware.common.CommonMiddleware', @@ -200,6 +210,8 @@ LOGGING = { } } +# LOGIN_URL = '/account/login' + try: from local_settings import * except ImportError, e: diff --git a/cbmi/templates/base.html b/cbmi/templates/base.html index ce4d198..2d43373 100644 --- a/cbmi/templates/base.html +++ b/cbmi/templates/base.html @@ -1,3 +1,4 @@ +{% load i18n %} @@ -63,6 +64,17 @@
{% block body %}
+ + {% block container %}
@@ -79,7 +91,8 @@
-
+ {% endblock container %} + {% endblock body %} diff --git a/cbmi/templates/group_list.html b/cbmi/templates/group_list.html index 9356146..0548fb2 100644 --- a/cbmi/templates/group_list.html +++ b/cbmi/templates/group_list.html @@ -1,7 +1,7 @@ {% extends "base.html" %} -{% block body %} -
+{% block container %} + BLA

members of {{ group.name }}

@@ -13,5 +13,4 @@ {% endfor %}
-
-{% endblock %} +{% endblock container %} diff --git a/cbmi/templates/wlan_presence.html b/cbmi/templates/wlan_presence.html new file mode 100644 index 0000000..ea201db --- /dev/null +++ b/cbmi/templates/wlan_presence.html @@ -0,0 +1,43 @@ +{% extends "base.html" %} +{% load i18n %} +{% block container %} +
+
+

{% trans "WiFi Presence"%}

+

{% blocktrans %}The WiFi Presence automatically logs you in + to the c-base presence system when you connect a device to the Crew-Wifi + (SSID: c-base-crew) with your username and password.{% endblocktrans %}

+ + {% if message %} +
{{ message }}
+ {% endif %} + + {{ form.non_field_errors }} + +
+ + {% csrf_token %} +
+ +
+ {{ form.presence.errors }} +
+
+ + + +
+
+
+
+ +
+
+
+
+
+{% endblock container %} diff --git a/cbmi/urls.py b/cbmi/urls.py index 72d5a43..1b9e252 100644 --- a/cbmi/urls.py +++ b/cbmi/urls.py @@ -13,4 +13,7 @@ urlpatterns = patterns('', url(r'^groups/(?P[^/]+)/', 'cbmi.views.groups_list'), url(r'^$', 'cbmi.views.landingpage'), url(r'^gastropin/$', 'cbmi.views.gastropin', name='gastropin'), + + url(r'^wlan_presence/$', 'cbmi.views.wlan_presence', name='wlan_presence'), + ) diff --git a/cbmi/views.py b/cbmi/views.py index e9d306b..f187c8a 100644 --- a/cbmi/views.py +++ b/cbmi/views.py @@ -1,11 +1,16 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import ldap +import copy + from django.shortcuts import render_to_response, get_object_or_404 from django.contrib.auth.decorators import login_required from django.contrib.auth.models import Group from django.shortcuts import render from django.utils.translation import ugettext as _ - -from forms import GastroPinForm +from forms import GastroPinForm, WlanPresenceForm def landingpage(request): is_ceymaster = is_admin = False @@ -16,6 +21,7 @@ def landingpage(request): groups = Group.objects.all() admins = Group.objects.get(name="ldap_admins").user_set.all() if request.user.is_authenticated(): + # values = get_user_values(request.user.username, request.session['ldap_password']) return render_to_response("dashboard.html", locals()) return render_to_response("base.html", locals()) @@ -49,3 +55,113 @@ def gastropin(request): form = GastroPinForm() return render(request, 'gastropin.html', {'form': form}) + +@login_required +def wlan_presence(request): + uv = UserValues(request.user.username, request.session['ldap_password']) + print "presence ist: ", uv.get_bool("wlanPresence") + + if request.method == 'POST': + form = WlanPresenceForm(request.POST) + if form.is_valid(): + + p = 'FALSE' + if form.cleaned_data['presence'] == True: + p = 'TRUE' + uv.set('wlanPresence', p) + uv.save() + new_form = WlanPresenceForm(initial={'presence': uv.get_bool("wlanPresence")}) + return render(request, 'wlan_presence.html', + {'message': _('Your Wifi Presenc has been set. Thank you!'), + 'form': new_form}) + else: + return render(request, 'wlan_presence.html', {'form:': form}) + else: + form = WlanPresenceForm(initial={'presence': uv.get_bool("wlanPresence")}) + + return render(request, 'wlan_presence.html', {'form': form}) + + +#def set_wlan_presence(request, value): +# """ +# +# """ +# set_boolean_value('wlanPresence', value, +# request.user.username, request.session['ldap_password']) + + +class UserValues(object): + """ + + """ + + def __init__(self, username, password): + self._username = username + self._password = password + self._old = self.get_user_values() + self._new = copy.deepcopy(self._old) + + def get(self, key, default=None): + return self._new.get(key, default)[0] + + def set(self, key, value): + self._new[key] = [value] + + def get_bool(self, key): + return self.get(key) == 'TRUE' + + def save(self): + """ + + """ + dn = "uid=%s,ou=crew,dc=c-base,dc=org" % self._username + print 'setting dn=', dn + + # TODO: Use settings for url + l = ldap.initialize("ldap://lea.cbrp3.c-base.org:389/") + l.simple_bind_s(dn, self._password) + + mod_attrs = [] + for new_key, new_value in self._new.items(): + # Replace is the default. + action = ldap.MOD_REPLACE + if new_key not in self._old.keys(): + action = ldap.MOD_ADD + mod_attrs.append((action, '%s' % new_key, new_value )) + continue + # Set the attribute and wait for the LDAP server to complete. + if self._old[new_key][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 + + + def get_user_values(self): + """ + + """ + + dn = "ou=crew,dc=c-base,dc=org" + bind_dn = "uid=%s,ou=crew,dc=c-base,dc=org" % self._username + print('setting dn=', dn) + + # TODO: Use settings for url + l = ldap.initialize("ldap://lea.cbrp3.c-base.org:389/") + l.simple_bind_s(bind_dn, self._password) + + # Set the attribute and wait for the LDAP server to complete. + searchScope = ldap.SCOPE_SUBTREE + ## retrieve all attributes - again adjust to your needs - see documentation for more options + retrieveAttributes = None + searchFilter = "uid=%s" % self._username + + # get_attrs = [( ldap., 'wlanPresence', set_value )] + result = l.search_s(dn, searchScope, searchFilter, retrieveAttributes) + # TODO: latin1 + print "result is: ", result + # TODO: if len(result)==0 + return result[0][1] From 8fdc6064fa0954d39b9a9ca25f11b3848edd19d5 Mon Sep 17 00:00:00 2001 From: Uwe Kamper Date: Thu, 24 Oct 2013 21:27:15 +0200 Subject: [PATCH 4/4] forms work and are saved to ldap correctly, added RFID form --- account/cbase_members.py | 109 ++++++++++++++ account/forms.py | 38 +++++ account/templates/form_base.html | 18 +++ {cbmi => account}/templates/gastropin.html | 0 account/templates/rfid.html | 23 +++ account/templates/wlan_presence.html | 25 ++++ account/urls.py | 4 + account/views.py | 88 ++++++++++- cbmi/forms.py | 26 ---- cbmi/settings.py | 7 +- cbmi/templates/base.html | 6 +- cbmi/templates/wlan_presence.html | 43 ------ cbmi/urls.py | 5 +- cbmi/views.py | 165 +-------------------- 14 files changed, 317 insertions(+), 240 deletions(-) create mode 100644 account/cbase_members.py create mode 100644 account/templates/form_base.html rename {cbmi => account}/templates/gastropin.html (100%) create mode 100644 account/templates/rfid.html create mode 100644 account/templates/wlan_presence.html delete mode 100644 cbmi/templates/wlan_presence.html diff --git a/account/cbase_members.py b/account/cbase_members.py new file mode 100644 index 0000000..eddbebd --- /dev/null +++ b/account/cbase_members.py @@ -0,0 +1,109 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import ldap +import copy + +from django.conf import settings + +""" +Example configuration: + +CBASE_LDAP_URL = 'ldap://lea.cbrp3.c-base.org:389/' +CBASE_BASE_DN = 'ou=crew,dc=c-base,dc=org' +""" + +def retrieve_member(request): + # TODO: Put password in encrypted session storage + return MemberValues(request.user.username, request.session['ldap_password']) + + +class MemberValues(object): + """ + Dictionary-like abstraction of the c-base member attributes. + """ + def __init__(self, username, password): + self._username = username + self._password = password + self._old = self._get_user_values() + + # Make a complete copy of the old values so we can later check + # which + self._new = copy.deepcopy(self._old) + + def get(self, key, default=None): + value = self._new.get(key, default)[0] + if value == 'TRUE': + return True + elif value == 'FALSE': + return False + else: + return value + + def set(self, key, value): + converted_value = value + if isinstance(value, bool): + if value == True: + converted_value = 'TRUE' + else: + converted_value = 'FALSE' + self._new[key] = [converted_value.encode('latin-1')] + + def save(self): + """ + Save the values back to the LDAP server. + """ + dn = "uid=%s,ou=crew,dc=c-base,dc=org" % self._username + print 'setting dn=', dn + + # TODO: Use settings for url + l = ldap.initialize("ldap://lea.cbrp3.c-base.org:389/") + l.simple_bind_s(dn, self._password) + + mod_attrs = [] + for new_key, new_value in self._new.items(): + # Replace is the default. + action = ldap.MOD_REPLACE + if new_key not in self._old.keys(): + action = ldap.MOD_ADD + mod_attrs.append((action, '%s' % new_key, new_value )) + continue + # Set the attribute and wait for the LDAP server to complete. + if self._old[new_key][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 + + def _get_bind_dn(self): + """ + Adds the uid=userid, to the base dn and returns that. + """ + bind_dn = 'uid=%s,' % self._username + bind_dn += settings.CBASE_BASE_DN + return bind_dn + + def _get_user_values(self): + """ + Get an attribute from the ldap storage. + """ + # Create a new LDAP bind (aka connection or session) + session = ldap.initialize(settings.CBASE_LDAP_URL) + 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 + + # retrieve all attributes + retrieveAttributes = None + searchFilter = "uid=%s" % self._username + + dn = settings.CBASE_BASE_DN + result = session.search_s(dn, searchScope, searchFilter, retrieveAttributes) + # TODO: latin1 + print "result is: ", result + # TODO: if len(result)==0 + return result[0][1] diff --git a/account/forms.py b/account/forms.py index b6a3650..d51623d 100644 --- a/account/forms.py +++ b/account/forms.py @@ -1,7 +1,45 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import re + from django import forms +from django.utils.translation import ugettext as _ + class LoginForm(forms.Form): username = forms.CharField(max_length=255) password = forms.CharField(max_length=255, widget=forms.PasswordInput) +class GastroPinField(forms.CharField): + def validate(self, value): + """ + Check if the value is all numeric and 4 - 6 chars long. + """ + match = re.match(r'^\d{4,6}$', value) + if not match: + raise forms.ValidationError(_('PIN must be 4 to 6 digits.')) + + +class GastroPinForm(forms.Form): + gastropin = GastroPinField() + + +class WlanPresenceForm(forms.Form): + # Boolean fields must never be required. + presence = forms.BooleanField(required=False, + help_text=_('Enable WiFi presence?')) + + +class PaswordForm(forms.Form): + password1 = forms.CharField(max_length=255, widget=forms.PasswordInput, + help_text=_('New password')) + password2 = forms.CharField(max_length=255, widget=forms.PasswordInput, + help_text=_('Repeat password')) + + +class RFIDForm(forms.Form): + rfid = forms.CharField(max_length=255, help_text=_('Your RFID')) + + diff --git a/account/templates/form_base.html b/account/templates/form_base.html new file mode 100644 index 0000000..1000011 --- /dev/null +++ b/account/templates/form_base.html @@ -0,0 +1,18 @@ +{% extends "base.html" %} +{% load i18n %} + +{% block container %} +
+
+

{% block form_title %}{% endblock %}

+ {% block form_description %}{% endblock %} + + {% if message %} +
{{ message }}
+ {% endif %} + + {% block form_fields %}{% endblock form_fields %} + +
+
+{% endblock container %} diff --git a/cbmi/templates/gastropin.html b/account/templates/gastropin.html similarity index 100% rename from cbmi/templates/gastropin.html rename to account/templates/gastropin.html diff --git a/account/templates/rfid.html b/account/templates/rfid.html new file mode 100644 index 0000000..40e4636 --- /dev/null +++ b/account/templates/rfid.html @@ -0,0 +1,23 @@ +{% extends "form_base.html" %} +{% load i18n %} +{% load crispy_forms_tags %} + +{% block form_title %}{% trans "RFID"%}{% endblock %} + +{% block form_description %} +

{% blocktrans %}Blabla testblab bla bla blub{% endblocktrans %}

+{% endblock %} + +{% block form_fields %} + {{ form.non_field_errors }} +
+ {% csrf_token %} + {{ form|crispy }} + +
+
+ +
+
+
+{% endblock form_fields %} \ No newline at end of file diff --git a/account/templates/wlan_presence.html b/account/templates/wlan_presence.html new file mode 100644 index 0000000..d26df1e --- /dev/null +++ b/account/templates/wlan_presence.html @@ -0,0 +1,25 @@ +{% extends "form_base.html" %} +{% load i18n %} +{% load crispy_forms_tags %} + +{% block form_title %}{% trans "WiFi Presence"%}{% endblock %} + +{% block form_description %} +

{% blocktrans %}The WiFi Presence automatically logs you in + to the c-base presence system when you connect a device to the Crew-Wifi + (SSID: c-base-crew) with your username and password.{% endblocktrans %}

+{% endblock %} + +{% block form_fields %} + {{ form.non_field_errors }} +
+ {% csrf_token %} + {{ form|crispy }} + +
+
+ +
+
+
+{% endblock form_fields %} diff --git a/account/urls.py b/account/urls.py index 8370e0f..0f3d722 100644 --- a/account/urls.py +++ b/account/urls.py @@ -5,4 +5,8 @@ urlpatterns = patterns( '', url(r'^login/$', 'account.views.auth_login', name="auth_login"), url(r'^logout/$', 'account.views.auth_logout', name="auth_logout"), + url(r'^gastropin/$', 'account.views.gastropin', name='gastropin'), + url(r'^wlan_presence/$', 'account.views.wlan_presence', name='wlan_presence'), + url(r'^rfid/$', 'account.views.rfid', name='rfid'), + url(r'^groups/(?P[^/]+)/', 'account.views.groups_list'), ) \ No newline at end of file diff --git a/account/views.py b/account/views.py index a13ebf8..90f8c64 100644 --- a/account/views.py +++ b/account/views.py @@ -6,8 +6,14 @@ 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.decorators import login_required +from django.contrib.auth.models import Group +from django.shortcuts import render +from django.utils.translation import ugettext as _ -from account.forms import LoginForm +from forms import GastroPinForm, WlanPresenceForm, LoginForm, PaswordForm, RFIDForm +from cbase_members import MemberValues, retrieve_member def auth_login(request): redirect_to = request.GET.get('next', '') or '/' @@ -43,3 +49,83 @@ def auth_logout(request): response = HttpResponseRedirect(redirect_to) response.delete_cookie('sessionkey') return response + +def landingpage(request): + is_ceymaster = is_admin = False + if 'ceymaster' in [g.name for g in request.user.groups.all()]: + is_ceymaster = True + if 'ldap_admins' in [g.name for g in request.user.groups.all()]: + is_admin = True + groups = Group.objects.all() + admins = Group.objects.get(name="ldap_admins").user_set.all() + if request.user.is_authenticated(): + # values = get_user_values(request.user.username, request.session['ldap_password']) + return render_to_response("dashboard.html", locals()) + return render_to_response("base.html", locals()) + +@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() + if 'ceymaster' in [g.name for g in request.user.groups.all()]: + is_ceymaster = True + if 'ldap_admins' in [g.name for g in request.user.groups.all()]: + is_admin = True + return render_to_response("group_list.html", locals()) + +@login_required +def gastropin(request): + if request.method == 'POST': + form = GastroPinForm(request.POST) + if form.is_valid(): + user = request.user + user_profile = user.get_profile() + user_profile.gastropin = form.cleaned_data['gastropin'] + user_profile.save() + return render(request, 'gastropin.html', + {'message': _('Your Gastro-PIN was changed. Thank you!'), + 'form:': form}) + else: + return render(request, 'gastropin.html', {'form:': form}) + + else: + form = GastroPinForm() + + return render(request, 'gastropin.html', {'form': form}) + + +def set_ldap_field(request, form_type, field_names, template_name): + member = retrieve_member(request) + initial = {} + + if request.method == 'POST': + form = form_type(request.POST) + if form.is_valid(): + + for form_field, ldap_field in field_names: + member.set(ldap_field, form.cleaned_data[form_field]) + initial[form_field] = member.get(ldap_field) + member.save() + new_form = form_type(initial=initial) + return render(request, template_name, + {'message': _('Your changes have been saved. Thank you!'), + 'form': new_form}) + else: + return render(request, template_name, {'form:': form}) + else: + for form_field, ldap_field in field_names: + initial[form_field] = member.get(ldap_field) + form = form_type(initial=initial) + return render(request, template_name, {'form': form}) + + +@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') + + diff --git a/cbmi/forms.py b/cbmi/forms.py index d06bbe6..e69de29 100644 --- a/cbmi/forms.py +++ b/cbmi/forms.py @@ -1,26 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -import re - -from django import forms -from django.utils.translation import ugettext as _ - - -class GastroPinField(forms.CharField): - def validate(self, value): - """ - Check if the value is all numeric and 4 - 6 chars long. - """ - match = re.match(r'^\d{4,6}$', value) - if not match: - raise forms.ValidationError(_('PIN must be 4 to 6 digits.')) - - -class GastroPinForm(forms.Form): - gastropin = GastroPinField() - - -class WlanPresenceForm(forms.Form): - # Boolean fields must never be required. - presence = forms.BooleanField(required=False) \ No newline at end of file diff --git a/cbmi/settings.py b/cbmi/settings.py index 8db3812..94431ba 100644 --- a/cbmi/settings.py +++ b/cbmi/settings.py @@ -176,6 +176,7 @@ INSTALLED_APPS = ( 'django.contrib.admin', 'django.contrib.admindocs', 'jsonrpc', + 'crispy_forms', 'cbmi', 'account', 'cbapi_ldap', @@ -210,7 +211,11 @@ LOGGING = { } } -# LOGIN_URL = '/account/login' +CRISPY_TEMPLATE_PACK = 'bootstrap' + +# c-base specific settings +CBASE_LDAP_URL = 'ldap://lea.cbrp3.c-base.org:389/' +CBASE_BASE_DN = 'ou=crew,dc=c-base,dc=org' try: from local_settings import * diff --git a/cbmi/templates/base.html b/cbmi/templates/base.html index 2d43373..25e2e0d 100644 --- a/cbmi/templates/base.html +++ b/cbmi/templates/base.html @@ -69,10 +69,14 @@
  • {% trans "Home" %}
  • - {% url cbmi.views.wlan_presence as wlan_presence_url %} + {% url account.views.wlan_presence as wlan_presence_url %}
  • {% trans "WLAN Presence" %}
  • + {% url account.views.rfid as rfid_url %} +
  • + {% trans "RFID" %} +
  • {% block container %}
    diff --git a/cbmi/templates/wlan_presence.html b/cbmi/templates/wlan_presence.html deleted file mode 100644 index ea201db..0000000 --- a/cbmi/templates/wlan_presence.html +++ /dev/null @@ -1,43 +0,0 @@ -{% extends "base.html" %} -{% load i18n %} -{% block container %} -
    -
    -

    {% trans "WiFi Presence"%}

    -

    {% blocktrans %}The WiFi Presence automatically logs you in - to the c-base presence system when you connect a device to the Crew-Wifi - (SSID: c-base-crew) with your username and password.{% endblocktrans %}

    - - {% if message %} -
    {{ message }}
    - {% endif %} - - {{ form.non_field_errors }} - -
    - - {% csrf_token %} -
    - -
    - {{ form.presence.errors }} -
    -
    - - - -
    -
    -
    -
    - -
    -
    -
    -
    -
    -{% endblock container %} diff --git a/cbmi/urls.py b/cbmi/urls.py index 1b9e252..b6efca6 100644 --- a/cbmi/urls.py +++ b/cbmi/urls.py @@ -10,10 +10,7 @@ urlpatterns = patterns('', url(r'^cbapi/', include("cbapi_ldap.urls")), url(r'account/', include('account.urls')), - url(r'^groups/(?P[^/]+)/', 'cbmi.views.groups_list'), - url(r'^$', 'cbmi.views.landingpage'), - url(r'^gastropin/$', 'cbmi.views.gastropin', name='gastropin'), - url(r'^wlan_presence/$', 'cbmi.views.wlan_presence', name='wlan_presence'), + url(r'^$', 'cbmi.views.landingpage'), ) diff --git a/cbmi/views.py b/cbmi/views.py index f187c8a..2360549 100644 --- a/cbmi/views.py +++ b/cbmi/views.py @@ -1,167 +1,4 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -import ldap -import copy - -from django.shortcuts import render_to_response, get_object_or_404 -from django.contrib.auth.decorators import login_required -from django.contrib.auth.models import Group -from django.shortcuts import render -from django.utils.translation import ugettext as _ - -from forms import GastroPinForm, WlanPresenceForm - -def landingpage(request): - is_ceymaster = is_admin = False - if 'ceymaster' in [g.name for g in request.user.groups.all()]: - is_ceymaster = True - if 'ldap_admins' in [g.name for g in request.user.groups.all()]: - is_admin = True - groups = Group.objects.all() - admins = Group.objects.get(name="ldap_admins").user_set.all() - if request.user.is_authenticated(): - # values = get_user_values(request.user.username, request.session['ldap_password']) - return render_to_response("dashboard.html", locals()) - return render_to_response("base.html", locals()) - - -@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() - if 'ceymaster' in [g.name for g in request.user.groups.all()]: - is_ceymaster = True - if 'ldap_admins' in [g.name for g in request.user.groups.all()]: - is_admin = True - return render_to_response("group_list.html", locals()) - -@login_required -def gastropin(request): - if request.method == 'POST': - form = GastroPinForm(request.POST) - if form.is_valid(): - user = request.user - user_profile = user.get_profile() - user_profile.gastropin = form.cleaned_data['gastropin'] - user_profile.save() - return render(request, 'gastropin.html', - {'message': _('Your Gastro-PIN was changed. Thank you!'), - 'form:': form}) - else: - return render(request, 'gastropin.html', {'form:': form}) - - else: - form = GastroPinForm() - - return render(request, 'gastropin.html', {'form': form}) - -@login_required -def wlan_presence(request): - uv = UserValues(request.user.username, request.session['ldap_password']) - print "presence ist: ", uv.get_bool("wlanPresence") - - if request.method == 'POST': - form = WlanPresenceForm(request.POST) - if form.is_valid(): - - p = 'FALSE' - if form.cleaned_data['presence'] == True: - p = 'TRUE' - uv.set('wlanPresence', p) - uv.save() - new_form = WlanPresenceForm(initial={'presence': uv.get_bool("wlanPresence")}) - return render(request, 'wlan_presence.html', - {'message': _('Your Wifi Presenc has been set. Thank you!'), - 'form': new_form}) - else: - return render(request, 'wlan_presence.html', {'form:': form}) - else: - form = WlanPresenceForm(initial={'presence': uv.get_bool("wlanPresence")}) - - return render(request, 'wlan_presence.html', {'form': form}) - - -#def set_wlan_presence(request, value): -# """ -# -# """ -# set_boolean_value('wlanPresence', value, -# request.user.username, request.session['ldap_password']) - - -class UserValues(object): - """ - - """ - - def __init__(self, username, password): - self._username = username - self._password = password - self._old = self.get_user_values() - self._new = copy.deepcopy(self._old) - - def get(self, key, default=None): - return self._new.get(key, default)[0] - - def set(self, key, value): - self._new[key] = [value] - - def get_bool(self, key): - return self.get(key) == 'TRUE' - - def save(self): - """ - - """ - dn = "uid=%s,ou=crew,dc=c-base,dc=org" % self._username - print 'setting dn=', dn - - # TODO: Use settings for url - l = ldap.initialize("ldap://lea.cbrp3.c-base.org:389/") - l.simple_bind_s(dn, self._password) - - mod_attrs = [] - for new_key, new_value in self._new.items(): - # Replace is the default. - action = ldap.MOD_REPLACE - if new_key not in self._old.keys(): - action = ldap.MOD_ADD - mod_attrs.append((action, '%s' % new_key, new_value )) - continue - # Set the attribute and wait for the LDAP server to complete. - if self._old[new_key][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 - - - def get_user_values(self): - """ - - """ - - dn = "ou=crew,dc=c-base,dc=org" - bind_dn = "uid=%s,ou=crew,dc=c-base,dc=org" % self._username - print('setting dn=', dn) - - # TODO: Use settings for url - l = ldap.initialize("ldap://lea.cbrp3.c-base.org:389/") - l.simple_bind_s(bind_dn, self._password) - - # Set the attribute and wait for the LDAP server to complete. - searchScope = ldap.SCOPE_SUBTREE - ## retrieve all attributes - again adjust to your needs - see documentation for more options - retrieveAttributes = None - searchFilter = "uid=%s" % self._username - - # get_attrs = [( ldap., 'wlanPresence', set_value )] - result = l.search_s(dn, searchScope, searchFilter, retrieveAttributes) - # TODO: latin1 - print "result is: ", result - # TODO: if len(result)==0 - return result[0][1] +# Create your views here \ No newline at end of file