From 9eca98c1d4f44ee01cec5029d68bc33005646d12 Mon Sep 17 00:00:00 2001 From: Brian Wiborg Date: Sun, 20 Oct 2013 20:42:13 +0200 Subject: [PATCH 01/19] sample api app --- account/templates/dashboard.html | 35 ++++++++++++++++---------------- cbapi_ldap/__init__.py | 0 cbapi_ldap/urls.py | 9 ++++++++ cbapi_ldap/views.py | 22 ++++++++++++++++++++ cbmi/settings.py | 2 ++ cbmi/urls.py | 3 +++ 6 files changed, 54 insertions(+), 17 deletions(-) create mode 100644 cbapi_ldap/__init__.py create mode 100644 cbapi_ldap/urls.py create mode 100644 cbapi_ldap/views.py diff --git a/account/templates/dashboard.html b/account/templates/dashboard.html index a0cf778..ff65e1c 100644 --- a/account/templates/dashboard.html +++ b/account/templates/dashboard.html @@ -4,25 +4,26 @@
-

{{ request.user.username }}

+

{{ request.user.username }}

{% for g in request.user.groups.all %} - {% if g.name == "ceymaster" %} - - - - {% elif "cey" in g.name %} - - - - {% elif g.name == "ldap_admins" %} - - - - {% else %} - - - + {% if g.name == "ceymaster" %} + + {{ g }} + + {% elif "cey" in g.name %} + + {{ g }} + + {% elif g.name == "ldap_admins" %} + + {{ g }} + + {% else %} + + {{ g }} + {% endif %} +
{% empty %} no groups... {% endfor %} diff --git a/cbapi_ldap/__init__.py b/cbapi_ldap/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/cbapi_ldap/urls.py b/cbapi_ldap/urls.py new file mode 100644 index 0000000..bb83b0b --- /dev/null +++ b/cbapi_ldap/urls.py @@ -0,0 +1,9 @@ +from django.conf.urls import patterns, url +from jsonrpc import jsonrpc_site +from cbapi_ldap import views + +urlpatterns = patterns( + '', + url(r'^ldap/browse/$', 'jsonrpc.views.browse', name='jsonrpc_browser'), + url(r'^ldap/$', jsonrpc_site.dispatch, name='jsonrpc_mountpoint'), +) diff --git a/cbapi_ldap/views.py b/cbapi_ldap/views.py new file mode 100644 index 0000000..d417c14 --- /dev/null +++ b/cbapi_ldap/views.py @@ -0,0 +1,22 @@ +from jsonrpc import jsonrpc_method + +TODO = [ + '', +] + +@jsonrpc_method("ping", authenticated=True) +def ping(request, username, password): + """Ping - Echo Request + + :returns str: echo_response + """ + echo_response = "PONG" + return echo_response + +@jsonrpc_method("todo") +def todo(request): + """Todo - List ToDo Items + + :returns list: todolist + """ + return TODO diff --git a/cbmi/settings.py b/cbmi/settings.py index 7c9609b..94a050a 100644 --- a/cbmi/settings.py +++ b/cbmi/settings.py @@ -165,8 +165,10 @@ INSTALLED_APPS = ( 'django.contrib.staticfiles', 'django.contrib.admin', 'django.contrib.admindocs', + 'jsonrpc', 'cbmi', 'account', + 'cbapi_ldap', ) # A sample logging configuration. The only tangible logging diff --git a/cbmi/urls.py b/cbmi/urls.py index 5f24716..b0f696d 100644 --- a/cbmi/urls.py +++ b/cbmi/urls.py @@ -6,6 +6,9 @@ admin.autodiscover() urlpatterns = patterns('', url(r'^admin/doc/', include('django.contrib.admindocs.urls')), url(r'^admin/', include(admin.site.urls)), + + 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') From e0f53cd529deebd552d41a5d18bee95482fe77a7 Mon Sep 17 00:00:00 2001 From: Uwe Kamper Date: Tue, 22 Oct 2013 22:26:22 +0200 Subject: [PATCH 02/19] 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 83d7f19294fd5f56219383f65938a470eb49f274 Mon Sep 17 00:00:00 2001 From: smile Date: Tue, 22 Oct 2013 22:31:12 +0200 Subject: [PATCH 03/19] added local_settings.py --- .gitignore | 1 + cbmi/settings.py | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/.gitignore b/.gitignore index 99ec428..efc1dfb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ *.pyc .idea +local_settings.py 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 From afe60cadb9a32f98479bca4ae77a86ba0f93f94f Mon Sep 17 00:00:00 2001 From: smile Date: Tue, 22 Oct 2013 22:32:22 +0200 Subject: [PATCH 04/19] added smiles local_settings.py --- cbmi/local_settings.py.smile | 57 ++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 cbmi/local_settings.py.smile 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 From 032bc5acaa1c36acac7591d75553d47e01bc4528 Mon Sep 17 00:00:00 2001 From: Uwe Kamper Date: Wed, 23 Oct 2013 00:27:31 +0200 Subject: [PATCH 05/19] 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 06/19] 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 07/19] 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 From 623d5131b7118b0bd85850ccb4334c12ab1333d2 Mon Sep 17 00:00:00 2001 From: smile Date: Thu, 24 Oct 2013 21:28:17 +0200 Subject: [PATCH 08/19] moved c-base-bootstrap to its own directory and use submodule --- cbmi/templates/base.html | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cbmi/templates/base.html b/cbmi/templates/base.html index ce4d198..4f30d80 100644 --- a/cbmi/templates/base.html +++ b/cbmi/templates/base.html @@ -13,8 +13,8 @@ - - + + diff --git a/static/img/c-base_raumstation.gif b/static/img/c-base_raumstation.gif new file mode 100644 index 0000000000000000000000000000000000000000..dc80bf874f872d6e650a576f87b47b7caf5b5e8c GIT binary patch literal 1326 zcmV+}1=0FPNk%w1VMhTV0K^^uQ92m^nE)mm3lh7YZ{U0Pc?f5efh{ClDeO0GV6>-Gu-#BM!`Z06{Jj8xsgsGXN_e4Tw?z z5DW#XW&i*H00000A^8LW0015UEC2ui07n5J06+!*peK%GX`aX7oNVj9a4gSsZQppV z?|hF3fr4*HEEVWB_JP8{k3I2m*?WiVP$S4FV00BZ>_p1BwG4iHZm#42z$fjEf$nq9dIc zB&eQ|0wSG^lOmY{qp&BIn3^7;lCqk&rI)je2*-?+B+99zsL8GZj<=&Ex*pad*+W}+ z;Njxq=^pi;?LG)V%`P;vl) zlCoe4hzS7GO;AKH5I_kamaU^Aeiqf~)I-Ul0(w>e@DivAnl_tS1wa5n$*p3edeug= z6at+mQ?4|jlfa^w3D}Z#3zw-%M_B=EDk1fhR<4DKd=tsIvE#?y;z6EFxpFuO3k+DC zu{iUBg)9yj7=5n=X3a4~leWydwVi$zK;KwA!aWR18M2@ReIAyWg0n3!Hw8I_g?2o_a>j6jKKV^ukxI2Z|q1%^^hGZH9+ zfec7R4PMMJ0Oe3uRak)|VCf{7ic?kTQdJsq(4q%orby!miB-VVRSH}Z*d`6c)aEWk zU6sII{BLixBDHxMZ(j{nw7y`QHRWTmbq@!_p$)%7U#L3kqibZ`EA00DgK)vy?UwUUs5ap@FL8a}kXu&Z^y#%ioM z=mhY9X1UE44_P{jxt^qRr{0Sg%SK(itw`@jYVa2uYr*m^7OvFOqf(PlQJn#Mi` zY3cz4#%Tn^Jr0~ZLcCZ&AP2ob5SQ-2Mz~6yeb*V>PDS6v;SLqy><5qK_`ECR|Zb1ZWm@D(r`uO!1z^Udjy{2v9Q?K_&j z7#oo6$1mRobgnZuT|~C<6u|Biyaq9~1n}**-PKt;?e*6%Xz8T_L|#?X2rWM7!J1@? zP-k9c3ObgcgE6osgNOPA6atH06~T!;P5PCYF0O4hje&Vt)}ezk-gbzL=VeyjVpmD_ znCkp_Gr6_ zfl(+}=Q9zmHceX*z@v_O(fxVoqZ@i?ER{3*eC)bYN*GYV_e8v^RB?b8D;{8w(jp$R z@}(kDT>_R=DHf&-QM`-5(@u+^KFacXU9gBtLYiEKPOv@!v@cH{K#T2WR2RP7M0^n< k-;Ua%2>LY;8Q~kBgU(WlNxeyc5dvEe-f|5Q1}FpoI}G+MmjD0& literal 0 HcmV?d00001 diff --git a/static/img/logo.gif b/static/img/logo.gif new file mode 100644 index 0000000000000000000000000000000000000000..f17304da1d225a1fe4ec0b5425aae763ac660ef9 GIT binary patch literal 564 zcmV-40?YkJNk%w1VO;h7YZ{U0Pc?f5efh{ClDeO0GV6>-Gu-#BM!`Z06{Jj8xsgsGXN_e4Tw?z z5DW#XW&r>H|NsC0A^8LW3IHDfEC2ui09^nY000I4;3tk`X`aX7oNVj9a4efaP|SF) z?`3`Sz@TvC8yb(ZB67*>*_u$MGD;Ort61GN%Z+WjLdn8#;7!L1$m?KeuUuksjO}JY zCbfXU{1g@PdnXwbc|LC?cYrU0g*JyG5Eg}jT74gXc|Rlzjd>4`ACZ$ToSgxmB$B6O z5`3Bt2OD`CBpI0*2MdI!ts|-r8wb6Dx4FN)r50*IUk(p7!@CP5cmWe5$;&R%)HTTNr3UNg1XRdq%+8+-Hk1p6!ig*GGT#M@**RbRq24omH3YOo9lR6ALQ zoM#56rzM;fdZDXO0kb$tXF@$f!e7riS&MMp8HR)uYI)o~kefw{8L(vh216W32mm`z CgxVkg literal 0 HcmV?d00001 diff --git a/static/img/logo.xcf b/static/img/logo.xcf new file mode 100644 index 0000000000000000000000000000000000000000..df40600d7509566961ea5d7c80ae540e2a7d689a GIT binary patch literal 2274 zcmbVNO>ZMb5bd6s?sjJEnaS9hU`%SQ-3St`5+$s(2Nn(>1c&7U5;s2Ncx|txB#z=N z>~i6R#0{?d7dUa}4{+ej34Q=VidH~S$7JcJJH}$KQxWSKNIiyx9;>KN7!wCAM$*KYbzI+^o0il@ITT+c#=oe;~rD`mT@U zVi6+wsyd|d*0(~i;A=n}2$vEUI{Pib|0S&90L5<%_d0{##^7-H046S3ina04ligl> zJlY*TSa;X@gYIZ|bl6_YmW{)~PN%)Kxs`p_DBH!+Izo4@2`$gt|E_T8^JTmB3ras`TZ^Qb`E-w@oT>l4+@d7%w4o?Z zBPsE;7t#XFjFuYtU7ChN%{-~)H1Nr$ zlQ5=O%0QdwBIlWJTAZ~-7R{Q_{#H%nHQ*M(avDod$~dH@yiSKEejp{PrUX77vL>jq zj{PYdQJI+vVr|+R3t27&T{h!%q!VF9-NXa2oG7|2cb|rNK^HE zf0FIVM@)gp)ZC3$|t0G;|43 znN6itB(~=4`MJV{7X0$FT(^r@RjgOz_#Vz%D^|XT^Es%)hSZ9cYhphoyflDty=>EB zAr0{;g@^mX;PD1^II!8M-A1i4y)V9$C7Xfig1*JD!QO>AvRY&_O)D3ylr)h+3xqT| z`~G0|F-apL(9S)l*5c1_FgPf)G%|NyNg-#yczI3YZuqlAglc2zX{=g8}Sdm C^04** literal 0 HcmV?d00001 From c74b6565f9b5fc102ebf876fec8b4634941e679b Mon Sep 17 00:00:00 2001 From: Uwe Kamper Date: Fri, 25 Oct 2013 20:55:36 +0200 Subject: [PATCH 17/19] i18n --- account/conf/locale/de/LC_MESSAGES/django.mo | Bin 0 -> 1933 bytes account/conf/locale/de/LC_MESSAGES/django.po | 260 +++++++++++++++++++ {cbmi => account}/templates/base.html | 0 {cbmi => account}/templates/group_list.html | 0 cbmi/settings.py | 6 +- 5 files changed, 264 insertions(+), 2 deletions(-) create mode 100644 account/conf/locale/de/LC_MESSAGES/django.mo create mode 100644 account/conf/locale/de/LC_MESSAGES/django.po rename {cbmi => account}/templates/base.html (100%) rename {cbmi => account}/templates/group_list.html (100%) diff --git a/account/conf/locale/de/LC_MESSAGES/django.mo b/account/conf/locale/de/LC_MESSAGES/django.mo new file mode 100644 index 0000000000000000000000000000000000000000..4613a95e1609e947758d9f4641a7e93aaf9326a3 GIT binary patch literal 1933 zcmZ9M&u<$=6vr1RkeVNb^1GtqMFO=_v#yhdsJI2i#7=6(b}ZXTm59sO`?4Og-VHOe zH92qsae-sGa-jz#B(7W#mq`2rGjI%k1B&i{K+*je6u&di3*Ztcx-=-?eF=(eu`TzPCjP{S+*cYxmubgQ?>Tgdqcphk zaE&a7G8aFh38C;Vqf3+AWcSQw`H#e1n)vrt#wre(4wBT+$dA;Jy3G!`gw$xn){+}@ zv99B6GE|l)9J{jDh}AG+y02F??HjfnkJww)aX?Axa*MsyW}SuyG)|&G$Kjbpr$X@} z<_)WW4Hfp4Hc>L#D|>6oI+KVTuhUyySoE89uftQy*ZpiA(-YCz=DxCanwY@rq!TuJ zq#{b<=wOZ(#oH1EI@Hd3a>q$(9S!;XPTA}6J}Y^#b~7=>^we*$aN@eJ9M%ThSnb>RVsBi2L1|iCKmm=a$Kc_%KR;VzTz*uk74!J2RAAUl?o2}J$|6Y zcyVsKQS15b4ZmKadmGhu^Ty6br%`Gl(f+`w*hb1Frb?@utrm4^?FQX#v}?`Qa;;wP zHTwOJa5N566|z5IHK|go)>+#W$#+|=Gn{&QucxlAH{gMG3_4yY6w}S zoiv0%N+-u9Gof{kA~r}hwEEqmN{DrA;V^<0ub$GLieo&+0Lz@c02;GVsog~}aXcrb z5%7e9R6fKj(xb6M*@PMuqS?6oBY$1VP~os<>W{_|rg^6, YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2013-10-25 20:39+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: forms.py:20 +msgid "Sorry, that login was invalid. Please try again." +msgstr "" + +#: forms.py:39 +msgid "PIN must be 4 to 6 digits." +msgstr "Die PIN muss 4 - 6 Ziffern enthalten." + +#: forms.py:43 +msgid "New Gastro-PIN" +msgstr "Neue Gastro-PIN" + +#: forms.py:44 +msgid "Repeat Gastro-PIN" +msgstr "Gastro-PIN wiederholen" + +#: forms.py:52 forms.py:86 +msgid "The PINs entered were not identical." +msgstr "Die beiden eingegeben PINs waren nicht identisch." + +#: forms.py:60 +msgid "Enable WiFi presence" +msgstr "WLAN-Presence einschalten" + +#: forms.py:65 +msgid "New password" +msgstr "Neues Passwort" + +#: forms.py:67 +msgid "Repeat password" +msgstr "Passwort wiederholen" + +#: forms.py:71 +msgid "Your RFID" +msgstr "Deine RFID" + +#: forms.py:72 +msgid "" +"Find out your RFID by holding your RFID tag to the reader in the airlock." +msgstr "Du kannst deine RFID herausfinden, in dem du eine nicht registrierte RFID-Karte an die Schleuse hältst." + +#: forms.py:77 +msgid "Your SIP PIN" +msgstr "Deine SIP-PIN" + +#: forms.py:78 +msgid "Repeat SIP PIN" +msgstr "SIP-PIN wiederholen" + +#: forms.py:92 +msgid "NRF24-ID" +msgstr "NRF24-ID" + +#: forms.py:93 +msgid "Your r0ket's NRF24 identification" +msgstr "Die NRF24-ID deiner r0ket" + +#: forms.py:97 +msgid "New c-lab PIN" +msgstr "Neue c-lab-PIN" + +#: forms.py:98 +msgid "Repeat c-lab PIN" +msgstr "c-lab-PIN wiederholen" + +#: forms.py:99 +msgid "Numerical only, 4 to 6 digits" +msgstr "Nur Zahlen, 4 bis 6 Ziffern lang" + +#: views.py:119 +msgid "Your changes have been saved. Thank you!" +msgstr "Deine Änderungen wurden gespeichert. Vielen Dank!" + +#: templates/clabpin.html:5 +msgid "c-lab PIN" +msgstr "c-lab-PIN" + +#: templates/clabpin.html:8 +msgid "Change your c-lab PIN to access the c-lab in the basement." +msgstr "PIN ändern für den Zugang um c-lab im Keller." + +#: templates/clabpin.html:18 templates/gastropin.html:23 +#: templates/nrf24.html:19 templates/password.html:19 templates/sippin.html:18 +msgid "Save" +msgstr "Speichern" + +#: templates/gastropin.html:5 +msgid "Gastro PIN" +msgstr "Gastro-PIN" + +#: templates/gastropin.html:9 +msgid "" +"Change your Gastro PIN to access the vending machines.\n" +" To use unlock member prices, press the A button then " +"enter\n" +" your numeric user ID" +msgstr "" + +#: templates/gastropin.html:13 +msgid "and your Gastro PIN." +msgstr "" + +#: templates/login.html:20 +msgid "Login" +msgstr "" + +#: templates/member_base.html:9 +msgid "Home" +msgstr "" + +#: templates/member_base.html:13 templates/password.html:5 +msgid "Password" +msgstr "" + +#: templates/member_base.html:17 +msgid "Gastro-PIN" +msgstr "" + +#: templates/member_base.html:21 +msgid "WiFi presence" +msgstr "WLAN-Presence" + +#: templates/member_base.html:25 templates/rfid.html:5 +msgid "RFID" +msgstr "" + +#: templates/member_base.html:29 +msgid "c-lab-PIN" +msgstr "" + +#: templates/member_base.html:33 templates/nrf24.html:5 +msgid "NRF24" +msgstr "" + +#: templates/member_base.html:37 +msgid "SIP-PIN" +msgstr "" + +#: templates/nrf24.html:8 +msgid "" +"The NRF24 identification is used to interface with the\n" +" CCC's r0ket badge." +msgstr "" + +#: templates/password.html:8 +msgid "You can change your password here." +msgstr "" + +#: templates/rfid.html:8 +msgid "" +"A Radio Frequency Identification (RFID) tag can be used\n" +" to announce your presence to other c-base members when you arrive.\n" +" Place your RFID tag on the RFID reader in the airlock terminal.\n" +" If you configured your RFID correctly, the airlock terminal will greet\n" +" you and show additional information. If you place your RFID tag in the\n" +" reader again when leaving, you will be logged out." +msgstr "" + +#: templates/sippin.html:5 +msgid "SIP PIN" +msgstr "" + +#: templates/sippin.html:8 +msgid "" +"The SIP PIN is your access to the c-base SIP server for voice telephony." +msgstr "" + +#: templates/start.html:7 +msgid "Welcome to the c-base member interface" +msgstr "" + +#: templates/start.html:8 +msgid "" +"Here you can change\n" +" some parameters of your c-base member account." +msgstr "" + +#: templates/start.html:11 +msgid "Basic information about your account" +msgstr "" + +#: templates/start.html:15 +msgid "Your user ID:" +msgstr "" + +#: templates/start.html:17 +msgid "Numeric user ID:" +msgstr "" + +#: templates/start.html:19 +msgid "" +"The numeric user ID can be used to login with\n" +" the vending machines and network connected combination\n" +" locks." +msgstr "" + +#: templates/start.html:23 +msgid "Your c-base e-mail address:" +msgstr "" + +#: templates/start.html:28 +msgid "Management information" +msgstr "" + +#: templates/start.html:31 +msgid "Name:" +msgstr "" + +#: templates/start.html:35 +msgid "External e-mail address:" +msgstr "" + +#: templates/start.html:37 +msgid "" +"The external e-mail address is used by the\n" +" board of c-base to reach you in cases where your c-base\n" +" address (see above) is not working. To change your\n" +" externe e-mail address please contact the c-base board\n" +" (vorstand@c-base." +"org)." +msgstr "" + +#: templates/start.html:44 +msgid "Your c-base member account balance:" +msgstr "" + +#: templates/start.html:45 +msgid "Check balance" +msgstr "" + +#: templates/wlan_presence.html:5 +msgid "WiFi Presence" +msgstr "" + +#: templates/wlan_presence.html:8 +msgid "" +"The WiFi Presence automatically logs you in\n" +" to the c-base presence system when you connect a device to the Crew-" +"Wifi\n" +" (SSID: c-base-crew) with your username and password." +msgstr "" diff --git a/cbmi/templates/base.html b/account/templates/base.html similarity index 100% rename from cbmi/templates/base.html rename to account/templates/base.html diff --git a/cbmi/templates/group_list.html b/account/templates/group_list.html similarity index 100% rename from cbmi/templates/group_list.html rename to account/templates/group_list.html diff --git a/cbmi/settings.py b/cbmi/settings.py index 94431ba..112cce1 100644 --- a/cbmi/settings.py +++ b/cbmi/settings.py @@ -177,9 +177,9 @@ INSTALLED_APPS = ( 'django.contrib.admindocs', 'jsonrpc', 'crispy_forms', - 'cbmi', + # 'cbmi', 'account', - 'cbapi_ldap', + #'cbapi_ldap', ) # A sample logging configuration. The only tangible logging @@ -217,6 +217,8 @@ CRISPY_TEMPLATE_PACK = 'bootstrap' CBASE_LDAP_URL = 'ldap://lea.cbrp3.c-base.org:389/' CBASE_BASE_DN = 'ou=crew,dc=c-base,dc=org' +#LOCALE_PATHS = + try: from local_settings import * except ImportError, e: From 5691659fe104b07a8a7b04cb6ea54956493dbc8c Mon Sep 17 00:00:00 2001 From: Uwe Kamper Date: Fri, 25 Oct 2013 23:15:30 +0200 Subject: [PATCH 18/19] gastropin works --- account/forms.py | 2 +- account/views.py | 57 +++++++++++++++++++++++++++++++----- cbmi/local_settings.py.smile | 2 ++ cbmi/local_settings.py.uk | 2 ++ 4 files changed, 54 insertions(+), 9 deletions(-) diff --git a/account/forms.py b/account/forms.py index 5aa1664..f50d10f 100644 --- a/account/forms.py +++ b/account/forms.py @@ -51,7 +51,7 @@ class GastroPinForm(forms.Form): raise forms.ValidationError( _('The PINs entered were not identical.'), code='not_identical') - + return cleaned_data class WlanPresenceForm(forms.Form): diff --git a/account/views.py b/account/views.py index 5eede90..59df8bd 100644 --- a/account/views.py +++ b/account/views.py @@ -1,5 +1,7 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- +import hashlib +from django.conf import settings from django.http import HttpResponseRedirect from django.shortcuts import render_to_response @@ -89,16 +91,58 @@ def groups_list(request, group_name): is_admin = True return render_to_response("group_list.html", locals()) -@login_required -def gastropin(request): - return set_ldap_field(request, GastroPinForm, - [('gastropin', 'gastropin')], 'gastropin.html') + @login_required def sippin(request): return set_ldap_field(request, SIPPinForm, [('sippin', 'sippin')], 'sippin.html') + +def calculate_gastro_hash(pin): + key = settings.CBASE_GASTRO_KEY + bla = '%s%s' % (key, pin) + return hashlib.sha256(bla).hexdigest() + +def set_hash_field(request, form_type, in_field, out_field, hash_func, + template_name): + """ + Abstract view for each of the different forms. + """ + member = retrieve_member(request) + initial = {} + + if request.method == 'POST': + form = form_type(request.POST) + if form.is_valid(): + hashed_value = hash_func(form.cleaned_data[in_field]) + 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()}) + else: + 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()}) + +@login_required +def gastropin(request): + return set_hash_field(request, GastroPinForm, + 'gastropin1', 'gastroPIN', calculate_gastro_hash, 'gastropin.html') + +@login_required +def password(request): + def hash_password(password): + return password + + return set_ldap_field(request, PasswordForm, 'password1', 'password', + hash_password, 'password.html') + def set_ldap_field(request, form_type, field_names, template_name): """ Abstract view for each of the different forms. @@ -141,10 +185,7 @@ def rfid(request): def nrf24(request): return set_ldap_field(request, NRF24Form, [('nrf24', 'nrf24')], 'nrf24.html') -@login_required -def password(request): - return set_ldap_field(request, PasswordForm, [('password1', 'password')], - 'password.html') + @login_required def clabpin(request): diff --git a/cbmi/local_settings.py.smile b/cbmi/local_settings.py.smile index 1ea4e09..58cf7b0 100644 --- a/cbmi/local_settings.py.smile +++ b/cbmi/local_settings.py.smile @@ -55,3 +55,5 @@ TEMPLATE_DIRS = ( ) AUTH_LDAP_START_TLS = False + +CBASE_GASTRO_KEY = '12345690askdkadlasjdaj REPLACE ME' \ No newline at end of file diff --git a/cbmi/local_settings.py.uk b/cbmi/local_settings.py.uk index 1ea4e09..58cf7b0 100644 --- a/cbmi/local_settings.py.uk +++ b/cbmi/local_settings.py.uk @@ -55,3 +55,5 @@ TEMPLATE_DIRS = ( ) AUTH_LDAP_START_TLS = False + +CBASE_GASTRO_KEY = '12345690askdkadlasjdaj REPLACE ME' \ No newline at end of file From 5558882b9aabfbb0401add521c1eb84c7ed9d24e Mon Sep 17 00:00:00 2001 From: Uwe Kamper Date: Sat, 26 Oct 2013 20:06:42 +0200 Subject: [PATCH 19/19] everything except admin works --- account/cbase_members.py | 17 ++++- account/forms.py | 25 +++++++ account/templates/{start.html => home.html} | 8 +++ account/templates/password.html | 1 - account/views.py | 76 ++++++++++++++------- cbmi/settings.py | 3 + 6 files changed, 101 insertions(+), 29 deletions(-) rename account/templates/{start.html => home.html} (87%) diff --git a/account/cbase_members.py b/account/cbase_members.py index 5845382..47dcbfa 100644 --- a/account/cbase_members.py +++ b/account/cbase_members.py @@ -60,10 +60,8 @@ class MemberValues(object): 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 = ldap.initialize(settings.CBASE_LDAP_URL) l.simple_bind_s(dn, self._password) mod_attrs = [] @@ -83,6 +81,18 @@ class MemberValues(object): print "modattrs: ",mod_attrs result = l.modify_s(dn, mod_attrs) print "result is: ", result + l.unbind_s() + + 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) + 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() def to_dict(self): result = {} @@ -119,3 +129,4 @@ class MemberValues(object): print "result is: ", result # TODO: if len(result)==0 return result[0][1] + session.unbind_s() diff --git a/account/forms.py b/account/forms.py index f50d10f..01b5f24 100644 --- a/account/forms.py +++ b/account/forms.py @@ -61,11 +61,36 @@ class WlanPresenceForm(forms.Form): class PasswordForm(forms.Form): + 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')) + def __init__(self, *args, **kwargs): + self._request = kwargs.pop('request', None) + super(PasswordForm, self).__init__(*args, **kwargs) + + def clean(self): + cleaned_data = super(PasswordForm, self).clean() + old_password = cleaned_data.get('old_password') + username = self._request.user.username + 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') + + password1 = cleaned_data.get('password1') + password2 = cleaned_data.get('password2') + if password1 != password2: + raise forms.ValidationError( + _('The new passwords were not identical.'), + code='not_identical') + return cleaned_data + class RFIDForm(forms.Form): rfid = forms.CharField(max_length=255, label=_('Your RFID'), diff --git a/account/templates/start.html b/account/templates/home.html similarity index 87% rename from account/templates/start.html rename to account/templates/home.html index c2b7861..f8f2aaa 100644 --- a/account/templates/start.html +++ b/account/templates/home.html @@ -25,6 +25,14 @@ +

    {% trans "Your group memberships" %}

    + {% trans "You are part of the following LDAP groups:" %} +
      + {% for group in groups %} +
    • {{ group }}
    • + {% endfor %} +
    +

    {% trans "Management information" %}

      diff --git a/account/templates/password.html b/account/templates/password.html index f81d9a9..c1bb1e4 100644 --- a/account/templates/password.html +++ b/account/templates/password.html @@ -9,7 +9,6 @@ {% endblock %} {% block form_fields %} - {{ form.non_field_errors }}
      {% csrf_token %} {{ form|crispy }} diff --git a/account/views.py b/account/views.py index 59df8bd..f8b8f5e 100644 --- a/account/views.py +++ b/account/views.py @@ -1,8 +1,11 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -import hashlib -from django.conf import settings +import os +import base64 +import hashlib + +from django.conf import settings from django.http import HttpResponseRedirect from django.shortcuts import render_to_response from django.template.context import RequestContext @@ -16,8 +19,7 @@ from django.utils.translation import ugettext as _ from forms import GastroPinForm, WlanPresenceForm, LoginForm, PasswordForm, \ RFIDForm, NRF24Form, SIPPinForm, CLabPinForm -from cbase_members import MemberValues, retrieve_member - +from cbase_members import retrieve_member def landingpage(request): if request.user.is_authenticated(): @@ -69,9 +71,8 @@ def auth_login(request): @login_required def home(request): member = retrieve_member(request) - context = {'member': member.to_dict()} - print context - return render(request, 'start.html', context) + context = {'member': member.to_dict(), 'groups': request.user.groups.all()} + return render(request, 'home.html', context) @login_required def auth_logout(request): @@ -91,23 +92,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') - -def calculate_gastro_hash(pin): - key = settings.CBASE_GASTRO_KEY - bla = '%s%s' % (key, pin) - return hashlib.sha256(bla).hexdigest() - def set_hash_field(request, form_type, in_field, out_field, hash_func, template_name): """ - Abstract view for each of the different forms. + Abstract view for changing LDAP attributes that need to be hashed. + Takes a function that converts the value into the hashed_value. """ member = retrieve_member(request) initial = {} @@ -116,6 +110,7 @@ def set_hash_field(request, form_type, in_field, out_field, hash_func, form = form_type(request.POST) if form.is_valid(): hashed_value = hash_func(form.cleaned_data[in_field]) + print 'hashed value: ', hashed_value member.set(out_field, hashed_value) member.save() new_form = form_type(initial=initial) @@ -132,20 +127,55 @@ def set_hash_field(request, form_type, in_field, out_field, hash_func, @login_required def gastropin(request): + def calculate_gastro_hash(pin): + key = settings.CBASE_GASTRO_KEY + bla = '%s%s' % (key, pin) + return hashlib.sha256(bla).hexdigest() + return set_hash_field(request, GastroPinForm, 'gastropin1', 'gastroPIN', calculate_gastro_hash, 'gastropin.html') @login_required -def password(request): - def hash_password(password): - return password +def clabpin(request): + def calculate_clab_hash(pin): + salt = os.urandom(12) + digest = hashlib.sha1(bytearray(pin, 'UTF-8')+salt).digest() + return '{SSHA}' + base64.b64encode(digest + salt) - return set_ldap_field(request, PasswordForm, 'password1', 'password', - hash_password, 'password.html') + return set_hash_field(request, CLabPinForm, 'c_lab_pin1', 'c-labPIN', + calculate_clab_hash, 'clabpin.html') + +@login_required +def password(request): + """ + """ + member = retrieve_member(request) + + if request.method == 'POST': + form = PasswordForm(request.POST, request=request) + + if form.is_valid(): + new_password = form.cleaned_data['password1'] + member.change_password(new_password) + request.session['ldap_password'] = new_password + request.session.save() + new_form = PasswordForm() + return render(request, 'password.html', + {'message': _('Your password was changed. Thank you!'), + 'form': new_form, 'member': member.to_dict()}) + else: + return render(request, 'password.html', + {'form': form, 'member': member.to_dict()}) + else: + form = PasswordForm() + 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. + + field_names contains the mapping of the field name in the form to """ member = retrieve_member(request) initial = {} @@ -187,8 +217,4 @@ def nrf24(request): -@login_required -def clabpin(request): - return set_ldap_field(request, CLabPinForm, [('c_lab_pin1', 'c-labPIN')], - 'clabpin.html') diff --git a/cbmi/settings.py b/cbmi/settings.py index 112cce1..60fd668 100644 --- a/cbmi/settings.py +++ b/cbmi/settings.py @@ -217,6 +217,9 @@ CRISPY_TEMPLATE_PACK = 'bootstrap' CBASE_LDAP_URL = 'ldap://lea.cbrp3.c-base.org:389/' CBASE_BASE_DN = 'ou=crew,dc=c-base,dc=org' +# Set session cookie timeout to 10 minutes +SESSION_COOKIE_AGE = 600 +LOGIN_URL = '/account/login/' #LOCALE_PATHS = try: