Merge branch 'develop' of dev.c-base.org:cbmi/cbmi into develop

Conflicts:
	.gitignore
	cbmi/settings.py
This commit is contained in:
smile 2013-10-24 21:35:25 +02:00
commit 376f0cb9be
19 changed files with 450 additions and 50 deletions

2
.gitignore vendored
View file

@ -1,3 +1,5 @@
*.pyc *.pyc
.idea .idea
local_settings.py local_settings.py
build
*.sqlite3

109
account/cbase_members.py Normal file
View file

@ -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]

View file

@ -1,6 +1,45 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import re
from django import forms from django import forms
from django.utils.translation import ugettext as _
class LoginForm(forms.Form): class LoginForm(forms.Form):
username = forms.CharField(max_length=255) username = forms.CharField(max_length=255)
password = forms.CharField(max_length=255, widget=forms.PasswordInput) 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'))

View file

@ -1,7 +1,6 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block body %} {% block container %}
<div class="container">
<div class="row"> <div class="row">
<div class="span12"> <div class="span12">
<h2>{{ request.user.username }}</h2> <h2>{{ request.user.username }}</h2>
@ -29,5 +28,4 @@
{% endfor %} {% endfor %}
</div> </div>
</div> </div>
</div> {% endblock container %}
{% endblock body %}

View file

@ -0,0 +1,18 @@
{% extends "base.html" %}
{% load i18n %}
{% block container %}
<div class="row">
<div class="span12">
<h2>{% block form_title %}{% endblock %}</h2>
{% block form_description %}{% endblock %}
{% if message %}
<div class="alert alert-success">{{ message }}</div>
{% endif %}
{% block form_fields %}{% endblock form_fields %}
</div>
</div>
{% endblock container %}

View file

@ -0,0 +1,20 @@
{% extends "base.html" %}
{% block body %}
<div class="container">
<div class="row">
<div class="span12">
<h2>Gastro-Pin</h2>
{% if message %}
<div class="alert alert-success">{{ message }}</div>
{% endif %}
<form action="/gastropin/" method="post">
{{ form.non_field_errors }}
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
</div>
</div>
{% endblock %}

View file

@ -0,0 +1,23 @@
{% extends "form_base.html" %}
{% load i18n %}
{% load crispy_forms_tags %}
{% block form_title %}{% trans "RFID"%}{% endblock %}
{% block form_description %}
<p>{% blocktrans %}Blabla testblab bla bla blub{% endblocktrans %}</p>
{% endblock %}
{% block form_fields %}
{{ form.non_field_errors }}
<form action="{% url account.views.rfid %}" method="post" class="form-horizontal well">
{% csrf_token %}
{{ form|crispy }}
<div class="control-group">
<div class="controls">
<button type="submit" class="btn btn-primary">Speichern</button>
</div>
</div>
</form>
{% endblock form_fields %}

View file

@ -0,0 +1,25 @@
{% extends "form_base.html" %}
{% load i18n %}
{% load crispy_forms_tags %}
{% block form_title %}{% trans "WiFi Presence"%}{% endblock %}
{% block form_description %}
<p>{% 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 %}</p>
{% endblock %}
{% block form_fields %}
{{ form.non_field_errors }}
<form action="{% url account.views.wlan_presence %}" method="post" class="form-horizontal well">
{% csrf_token %}
{{ form|crispy }}
<div class="control-group">
<div class="controls">
<button type="submit" class="btn btn-primary">Speichern</button>
</div>
</div>
</form>
{% endblock form_fields %}

View file

@ -3,6 +3,10 @@ from django.conf.urls import patterns, url
urlpatterns = patterns( urlpatterns = patterns(
'', '',
url(r'^login/$', 'account.views.auth_login'), url(r'^login/$', 'account.views.auth_login', name="auth_login"),
url(r'^logout/$', 'account.views.auth_logout'), 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<group_name>[^/]+)/', 'account.views.groups_list'),
) )

View file

@ -1,14 +1,22 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from django.http import HttpResponseRedirect from django.http import HttpResponseRedirect
from django.shortcuts import render_to_response from django.shortcuts import render_to_response
from django.template.context import RequestContext from django.template.context import RequestContext
from django.contrib.auth import login, logout, authenticate from django.contrib.auth import login, logout, authenticate
from django.contrib.auth.models import User 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): def auth_login(request):
redirect_to = request.REQUEST.get('next', '') or '/' redirect_to = request.GET.get('next', '') or '/'
if request.method == 'POST': if request.method == 'POST':
form = LoginForm(request.POST) form = LoginForm(request.POST)
if form.is_valid(): if form.is_valid():
@ -18,20 +26,106 @@ def auth_login(request):
if user is not None: if user is not None:
if user.is_active: if user.is_active:
login(request, user) login(request, user)
member, created = User.objects.get_or_create( member, created = \
username=username) User.objects.get_or_create(username=username)
if created: if created:
member.save() 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: else:
print 'user is none' print 'user is none'
else: else:
form = LoginForm() form = LoginForm()
return render_to_response('login.html', return render_to_response('login.html',
RequestContext(request, locals())) RequestContext(request, locals()))
def auth_logout(request): def auth_logout(request):
redirect_to = request.REQUEST.get('next', '') or '/' redirect_to = request.GET.get('next', '') or '/'
logout(request) logout(request)
return HttpResponseRedirect(redirect_to) 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')

0
cbmi/forms.py Normal file
View file

57
cbmi/local_settings.py.uk Normal file
View file

@ -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

View file

@ -88,6 +88,16 @@ TEMPLATE_LOADERS = (
'django.template.loaders.app_directories.Loader', 'django.template.loaders.app_directories.Loader',
# 'django.template.loaders.eggs.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 = ( MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware', 'django.middleware.common.CommonMiddleware',
@ -166,6 +176,7 @@ INSTALLED_APPS = (
'django.contrib.admin', 'django.contrib.admin',
'django.contrib.admindocs', 'django.contrib.admindocs',
'jsonrpc', 'jsonrpc',
'crispy_forms',
'cbmi', 'cbmi',
'account', 'account',
'cbapi_ldap', 'cbapi_ldap',
@ -200,6 +211,12 @@ LOGGING = {
} }
} }
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: try:
from local_settings import * from local_settings import *
except ImportError, e: except ImportError, e:

View file

@ -1,3 +1,4 @@
{% load i18n %}
<!DOCTYPE html> <!DOCTYPE html>
<html lang="de"> <html lang="de">
<head> <head>
@ -63,6 +64,21 @@
<br/> <br/>
{% block body %} {% block body %}
<div class="container"> <div class="container">
<ul class="nav nav-tabs">
{% url cbmi.views.landingpage as landing_page_url %}
<li class="{% if request.path == landing_page_url %}active{% endif %}">
<a href="{{ landing_page_url }}">{% trans "Home" %}</a>
</li>
{% url account.views.wlan_presence as wlan_presence_url %}
<li class="{% if request.path == wlan_presence_url %}active{% endif %}">
<a href="{{ wlan_presence_url }}">{% trans "WLAN Presence" %}</a>
</li>
{% url account.views.rfid as rfid_url %}
<li class="{% if request.path == rfid_url %}active{% endif %}">
<a href="{{ rfid_url }}">{% trans "RFID" %}</a>
</li>
</ul>
{% block container %}
<div class="row"> <div class="row">
<div class="span12"> <div class="span12">
<div class="well"> <div class="well">
@ -79,7 +95,8 @@
</div> </div>
</div> </div>
</div> </div>
</div> {% endblock container %}
</div><!-- /.container -->
{% endblock body %} {% endblock body %}
<script src="/static/c-base-bootstrap/js/bootstrap.js"></script> <script src="/static/c-base-bootstrap/js/bootstrap.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>

View file

@ -1,7 +1,7 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block body %} {% block container %}
<div class="container"> BLA
<div class="row"> <div class="row">
<div class="span12"> <div class="span12">
<h2>members of {{ group.name }}</h2> <h2>members of {{ group.name }}</h2>
@ -13,5 +13,4 @@
{% endfor %} {% endfor %}
</div> </div>
</div> </div>
</div> {% endblock container %}
{% endblock %}

View file

@ -10,6 +10,7 @@ urlpatterns = patterns('',
url(r'^cbapi/', include("cbapi_ldap.urls")), url(r'^cbapi/', include("cbapi_ldap.urls")),
url(r'account/', include('account.urls')), url(r'account/', include('account.urls')),
url(r'^groups/(?P<group_name>[^/]+)/', 'cbmi.views.groups_list'),
url(r'^$', 'cbmi.views.landingpage') url(r'^$', 'cbmi.views.landingpage'),
) )

View file

@ -1,27 +1,4 @@
from django.shortcuts import render_to_response, get_object_or_404 #!/usr/bin/env python
from django.contrib.auth.decorators import login_required # -*- coding: utf-8 -*-
from django.contrib.auth.models import Group
# Create your views here
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():
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())

0
manage.py Normal file → Executable file
View file