aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichał Górny <mgorny@gentoo.org>2013-07-11 11:41:17 +0200
committerMichał Górny <mgorny@gentoo.org>2013-07-12 11:09:05 +0200
commit7c33de9705fd2bd1f8e606274c7b001c924e1f6c (patch)
treeb64fa1343c242bf7365ca7a96ef940d487e0cf02
parentSReg: initial support for choosing fields to send. (diff)
parentMerge pull request #24 from tampakrap/ldapdb (diff)
downloadidentity.gentoo.org-7c33de9705fd2bd1f8e606274c7b001c924e1f6c.tar.gz
identity.gentoo.org-7c33de9705fd2bd1f8e606274c7b001c924e1f6c.tar.bz2
identity.gentoo.org-7c33de9705fd2bd1f8e606274c7b001c924e1f6c.zip
Merge branch 'master' into openid-week4
And fix the PEP8 conflicts.
-rw-r--r--.gitignore2
-rw-r--r--okupy/__init__.py2
-rw-r--r--okupy/accounts/forms.py40
-rw-r--r--okupy/accounts/models.py78
-rw-r--r--okupy/accounts/openid_store.py51
-rw-r--r--okupy/accounts/urls.py6
-rw-r--r--okupy/accounts/views.py203
-rw-r--r--okupy/common/exceptions.py1
-rw-r--r--okupy/common/log.py7
-rw-r--r--okupy/common/testcase.py18
-rw-r--r--okupy/settings/__init__.py13
-rw-r--r--okupy/settings/local.py.sample24
-rw-r--r--okupy/templates/base.html42
-rw-r--r--okupy/templates/devlist.html46
-rw-r--r--okupy/templates/index.html80
-rw-r--r--okupy/tests/__init__.py2
-rw-r--r--okupy/tests/integration/index.py3
-rw-r--r--okupy/tests/integration/login.py17
-rw-r--r--okupy/tests/integration/signup.py5
-rw-r--r--okupy/tests/settings.py121
-rw-r--r--okupy/tests/tests.py33
-rw-r--r--requirements.txt1
-rwxr-xr-xsetup.py5
23 files changed, 505 insertions, 295 deletions
diff --git a/.gitignore b/.gitignore
index 100af90..bb6b5cd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,3 +13,5 @@ okupy/settings/development.py
.coverage
.coveralls.yml
/htmlcov
+.ropeproject
+.virtualenv
diff --git a/okupy/__init__.py b/okupy/__init__.py
index 52234b5..7e9bacb 100644
--- a/okupy/__init__.py
+++ b/okupy/__init__.py
@@ -1,4 +1,6 @@
# vim:fileencoding=utf8:et:ts=4:sts=4:sw=4:ft=python
+
+
def get_package_version():
return '0.0.1-dev'
diff --git a/okupy/accounts/forms.py b/okupy/accounts/forms.py
index ac59684..358670e 100644
--- a/okupy/accounts/forms.py
+++ b/okupy/accounts/forms.py
@@ -4,17 +4,23 @@ from django import forms
from .models import OpenID_Attributes
+
class LoginForm(forms.Form):
- username = forms.CharField(max_length = 100, label = 'Username:')
- password = forms.CharField(max_length = 30, widget = forms.PasswordInput(), label = 'Password:')
+ username = forms.CharField(max_length=100, label='Username:')
+ password = forms.CharField(max_length=30, widget=forms.PasswordInput(),
+ label='Password:')
+
class SignupForm(forms.Form):
- first_name = forms.CharField(max_length = 100, label = 'First Name:')
- last_name = forms.CharField(max_length = 100, label = 'Last Name:')
- email = forms.EmailField(max_length = 254, label = 'Email: ')
- username = forms.CharField(max_length = 100, label = 'Username:')
- password_origin = forms.CharField(max_length = 30, widget = forms.PasswordInput(), label = 'Password:')
- password_verify = forms.CharField(max_length = 30, widget = forms.PasswordInput(), label = 'Verify Password:')
+ first_name = forms.CharField(max_length=100, label='First Name:')
+ last_name = forms.CharField(max_length=100, label='Last Name:')
+ email = forms.EmailField(max_length=254, label='Email: ')
+ username = forms.CharField(max_length=100, label='Username:')
+ password_origin = forms.CharField(
+ max_length=30, widget=forms.PasswordInput(), label='Password:')
+ password_verify = forms.CharField(
+ max_length=30, widget=forms.PasswordInput(), label='Verify Password:')
+
# OpenID forms.
@@ -22,13 +28,13 @@ class SiteAuthForm(forms.ModelForm):
class Meta:
model = OpenID_Attributes
widgets = {
- 'nickname': forms.CheckboxInput,
- 'email': forms.CheckboxInput,
- 'fullname': forms.CheckboxInput,
- 'dob': forms.CheckboxInput,
- 'gender': forms.CheckboxInput,
- 'postcode': forms.CheckboxInput,
- 'country': forms.CheckboxInput,
- 'language': forms.CheckboxInput,
- 'timezone': forms.CheckboxInput,
+ 'nickname': forms.CheckboxInput,
+ 'email': forms.CheckboxInput,
+ 'fullname': forms.CheckboxInput,
+ 'dob': forms.CheckboxInput,
+ 'gender': forms.CheckboxInput,
+ 'postcode': forms.CheckboxInput,
+ 'country': forms.CheckboxInput,
+ 'language': forms.CheckboxInput,
+ 'timezone': forms.CheckboxInput,
}
diff --git a/okupy/accounts/models.py b/okupy/accounts/models.py
index 7527b48..e3abfdf 100644
--- a/okupy/accounts/models.py
+++ b/okupy/accounts/models.py
@@ -1,6 +1,10 @@
# vim:fileencoding=utf8:et:ts=4:sts=4:sw=4:ft=python
+from django.conf import settings
from django.db import models
+from ldapdb.models.fields import CharField, IntegerField, ListField
+import ldapdb.models
+
class Queue(models.Model):
username = models.CharField(max_length=100, unique=True)
@@ -10,27 +14,81 @@ class Queue(models.Model):
email = models.EmailField(max_length=254, unique=True)
token = models.CharField(max_length=40)
+
+class LDAPUser(ldapdb.models.Model):
+ """ Class representing an LDAP user entry """
+ # LDAP metadata
+ base_dn = settings.AUTH_LDAP_USER_BASE_DN
+ object_classes = settings.AUTH_LDAP_USER_OBJECTCLASS + \
+ settings.AUTH_LDAP_DEV_OBJECTCLASS
+ # top
+ object_class = ListField(db_column='objectClass')
+ # person
+ last_name = CharField(db_column='sn')
+ full_name = CharField(db_column='cn')
+ description = CharField(db_column='description')
+ phone = CharField(db_column='telephoneNumber', blank=True)
+ password = ListField(db_column='userPassword')
+ # inetOrgPerson
+ first_name = CharField(db_column='givenName')
+ email = ListField(db_column='mail')
+ username = CharField(db_column='uid', primary_key=True)
+ # posixAccount
+ uid = IntegerField(db_column='uidNumber', unique=True)
+ gid = IntegerField(db_column='gidNumber')
+ gecos = CharField(db_column='gecos')
+ home_directory = CharField(db_column='homeDirectory')
+ login_shell = CharField(db_column='loginShell', default='/bin/bash')
+ # ldapPublicKey
+ ssh_key = ListField(db_column='sshPublicKey')
+ # gentooGroup
+ ACL = ListField(db_column='gentooACL')
+ birthday = CharField(db_column='birthday')
+ gentoo_join_date = ListField(db_column='gentooJoin')
+ gentoo_retire_date = ListField(db_column='gentooRetire')
+ developer_bug = ListField(db_column='gentooDevBug')
+ gpg_fingerprint = ListField(db_column='gentooGPGFingerprint')
+ gpg_key = ListField(db_column='gentooGPGKey')
+ latitude = IntegerField(db_column='gentooLatitude')
+ longitude = IntegerField(db_column='gentooLongitude')
+ location = CharField(db_column='gentooLocation')
+ mentor = ListField(db_column='gentooMentor')
+ im = ListField(db_column='gentooIM')
+ # gentooDevGroup
+ roles = CharField(db_column='gentooRoles')
+ alias = ListField(db_column='gentooAlias')
+ spf = ListField(db_column='gentooSPF')
+
+ def __str__(self):
+ return self.username
+
+ def __unicode__(self):
+ return self.username
+
+
# Models for OpenID data store
class OpenID_Nonce(models.Model):
+ server_uri = models.URLField(max_length=2048)
+ ts = models.DateTimeField()
+ salt = models.CharField(max_length=40)
+
class Meta:
unique_together = ('server_uri', 'ts', 'salt')
- server_uri = models.URLField(max_length = 2048)
- ts = models.DateTimeField()
- salt = models.CharField(max_length = 40)
class OpenID_Association(models.Model):
+ server_uri = models.URLField(max_length=2048)
+ handle = models.CharField(max_length=255)
+ # TODO: BinaryField in newer versions of django
+ secret = models.CharField(max_length=128)
+ issued = models.DateTimeField()
+ expires = models.DateTimeField()
+ assoc_type = models.CharField(max_length=64)
+
class Meta:
unique_together = ('server_uri', 'handle')
- server_uri = models.URLField(max_length = 2048)
- handle = models.CharField(max_length = 255)
- # XXX: BinaryField in newer versions of django
- secret = models.CharField(max_length = 128)
- issued = models.DateTimeField()
- expires = models.DateTimeField()
- assoc_type = models.CharField(max_length = 64)
class OpenID_Attributes(models.Model):
""" An attribute choice for submission to the site requesting auth.
diff --git a/okupy/accounts/openid_store.py b/okupy/accounts/openid_store.py
index d2c1446..45cd715 100644
--- a/okupy/accounts/openid_store.py
+++ b/okupy/accounts/openid_store.py
@@ -1,6 +1,9 @@
# vim:fileencoding=utf8:et:ts=4:sts=4:sw=4:ft=python
-import base64, calendar, datetime, time
+import base64
+import calendar
+import datetime
+import time
from django.utils import timezone
@@ -10,30 +13,32 @@ from openid.store import nonce
from . import models as db_models
+
class DjangoDBOpenIDStore(OpenIDStore):
+
def storeAssociation(self, server_uri, assoc):
issued_dt = datetime.datetime.utcfromtimestamp(assoc.issued)
issued_dt = timezone.make_aware(issued_dt, timezone.utc)
- expire_delta = datetime.timedelta(seconds = assoc.lifetime)
+ expire_delta = datetime.timedelta(seconds=assoc.lifetime)
a = db_models.OpenID_Association(
- server_uri = server_uri,
- handle = assoc.handle,
- secret = base64.b64encode(assoc.secret),
- issued = issued_dt,
- expires = issued_dt + expire_delta,
- assoc_type = assoc.assoc_type)
+ server_uri=server_uri,
+ handle=assoc.handle,
+ secret=base64.b64encode(assoc.secret),
+ issued=issued_dt,
+ expires=issued_dt + expire_delta,
+ assoc_type=assoc.assoc_type)
a.save()
- def _db_getAssocs(self, server_uri, handle = None):
+ def _db_getAssocs(self, server_uri, handle=None):
objs = db_models.OpenID_Association.objects
- objs = objs.filter(server_uri = server_uri)
+ objs = objs.filter(server_uri=server_uri)
if handle is not None:
- objs = objs.filter(handle = handle)
+ objs = objs.filter(handle=handle)
return objs
- def getAssociation(self, server_uri, handle = None):
+ def getAssociation(self, server_uri, handle=None):
assert(server_uri is not None)
objs = self._db_getAssocs(server_uri, handle)
@@ -50,11 +55,11 @@ class DjangoDBOpenIDStore(OpenIDStore):
return None
return Association(
- a.handle,
- base64.b64decode(a.secret),
- calendar.timegm(a.issued.utctimetuple()),
- int((a.expires - a.issued).total_seconds()),
- a.assoc_type)
+ a.handle,
+ base64.b64decode(a.secret),
+ calendar.timegm(a.issued.utctimetuple()),
+ int((a.expires - a.issued).total_seconds()),
+ a.assoc_type)
def removeAssociation(self, server_uri, handle):
assert(server_uri is not None)
@@ -75,22 +80,22 @@ class DjangoDBOpenIDStore(OpenIDStore):
objs = db_models.OpenID_Nonce.objects
n, created = objs.get_or_create(
- server_uri = server_uri,
- ts = nonce_dt,
- salt = salt)
+ server_uri=server_uri,
+ ts=nonce_dt,
+ salt=salt)
# if it was created, it is unique and everything's fine.
# if we found one existing, it is duplicate and we return False.
return created
def cleanupNonces(self):
- skew_td = datetime.timedelta(seconds = nonce.SKEW)
+ skew_td = datetime.timedelta(seconds=nonce.SKEW)
expire_dt = timezone.now() - skew_td
- db_models.OpenID_Nonce.objects.filter(ts__lt = expire_dt).delete()
+ db_models.OpenID_Nonce.objects.filter(ts__lt=expire_dt).delete()
return 0
def cleanupAssociations(self):
db_models.OpenID_Association.objects.filter(
- expires__lt = timezone.now()).delete()
+ expires__lt=timezone.now()).delete()
return 0
diff --git a/okupy/accounts/urls.py b/okupy/accounts/urls.py
index e5a0d41..f9eb2dd 100644
--- a/okupy/accounts/urls.py
+++ b/okupy/accounts/urls.py
@@ -1,13 +1,15 @@
# vim:fileencoding=utf8:et:ts=4:sts=4:sw=4:ft=python
from django.conf.urls import patterns, url
-from .views import (login, logout, index, signup, activate, formerdevlist,
- foundationlist, openid_endpoint, user_page, openid_auth_site)
+from .views import (login, logout, index, signup, activate, devlist,
+ formerdevlist, foundationlist, openid_endpoint, user_page,
+ openid_auth_site)
accounts_urlpatterns = patterns('',
url(r'^$', index),
url(r'^login/$', login),
url(r'^logout/$', logout),
+ url(r'^devlist/$', devlist),
url(r'^former-devlist/$', formerdevlist),
url(r'^foundation-members/$', foundationlist),
url(r'^signup/$', signup),
diff --git a/okupy/accounts/views.py b/okupy/accounts/views.py
index 249309f..06294b9 100644
--- a/okupy/accounts/views.py
+++ b/okupy/accounts/views.py
@@ -2,41 +2,80 @@
from django.conf import settings
from django.contrib import messages
-from django.contrib.auth import login as _login, logout as _logout, authenticate
+from django.contrib.auth import (login as _login, logout as _logout,
+ authenticate)
from django.contrib.auth.decorators import login_required
from django.core.mail import send_mail
from django.core.urlresolvers import reverse
from django.db import IntegrityError
from django.http import HttpResponse
from django.shortcuts import redirect, render
-from django.template import RequestContext
from django.views.decorators.csrf import csrf_exempt
+from edpwd import random_string
+from openid.extensions.sreg import SRegRequest
+from openid.server.server import (Server, ProtocolError, EncodingError,
+ CheckIDRequest, ENCODE_URL,
+ ENCODE_KVFORM, ENCODE_HTML_FORM)
+from passlib.hash import ldap_md5_crypt
+
from .forms import LoginForm, SignupForm, SiteAuthForm
from .models import Queue
from .openid_store import DjangoDBOpenIDStore
-
from ..common.exceptions import OkupyError
from ..common.log import log_extra_data
-from edpwd import random_string
-from passlib.hash import ldap_md5_crypt
+# the following two are for exceptions
+import openid.yadis.discover
+import openid.fetchers
import ldap
import ldap.modlist as modlist
import logging
-from openid.extensions.sreg import SRegRequest
-from openid.server.server import (Server, ProtocolError, EncodingError,
- CheckIDRequest, ENCODE_URL, ENCODE_KVFORM, ENCODE_HTML_FORM)
-# for exceptions
-import openid.yadis.discover, openid.fetchers
-
logger = logging.getLogger('okupy')
logger_mail = logging.getLogger('mail_okupy')
+
@login_required
def index(request):
- return render(request, 'index.html', {})
+ anon_ldap_user = ldap.initialize(settings.AUTH_LDAP_SERVER_URI)
+ results = anon_ldap_user.search_s(settings.AUTH_LDAP_USER_DN_TEMPLATE % {
+ 'user': request.user}, ldap.SCOPE_SUBTREE, '(uid=%s)' % (request.user))
+ attrs = results[0][1]
+ personal_attributes = {
+ 'cn': 'Real Name', 'uid': 'Nickname', 'gentooLocation': 'Location'}
+ contact_attributes = {'mail': 'Email', 'gentooIM': 'IM Nickname'}
+ gentoo_attributes = {
+ 'herd': 'Herds', 'gentooRoles': 'Roles', 'gentooJoin': 'Date Joined',
+ 'gentooMentor': 'Mentor', 'gentooDevBug': 'Recruitment Bug',
+ 'gentooRetired': 'Retired'}
+ ldap_personal_info = {}
+ ldap_contact_info = {}
+ ldap_gentoo_info = {}
+
+ for k, v in personal_attributes.items():
+ attrs[k] = attrs.get(k, ['Empty, when it should be'])
+ ldap_personal_info[v] = attrs[k][0]
+
+ for k, v in contact_attributes.items():
+ attrs[k] = attrs.get(k, [''])
+ ldap_contact_info[v] = attrs[k][0]
+
+ for k, v in gentoo_attributes.items():
+ if k == 'gentooRetired' and k not in attrs:
+ continue
+ else:
+ attrs[k] = attrs.get(k, [''])
+ ldap_gentoo_info[v] = attrs[k][0]
+
+ anon_ldap_user.unbind_s()
+
+ return render(request, 'index.html', {
+ 'ldap_personal_info': ldap_personal_info,
+ 'ldap_contact_info': ldap_contact_info,
+ 'ldap_gentoo_info': ldap_gentoo_info
+ })
+
def login(request):
""" The login page """
@@ -72,18 +111,19 @@ def login(request):
it was successful. If it retrieves None then it failed to login
"""
try:
- user = authenticate(username = username, password = password)
+ user = authenticate(username=username, password=password)
except Exception as error:
logger.critical(error, extra=log_extra_data(request))
logger_mail.exception(error)
- raise OkupyError("Can't contact the LDAP server or the database")
+ raise OkupyError(
+ "Can't contact the LDAP server or the database")
if not user:
raise OkupyError('Login failed')
if user.is_active:
_login(request, user)
request.session.set_expiry(900)
return redirect(request.GET.get('next', index))
- except OkupyError, error:
+ except OkupyError as error:
messages.error(request, str(error))
else:
if request.user.is_authenticated():
@@ -96,11 +136,13 @@ def login(request):
'openid_request': oreq,
})
+
def logout(request):
""" The logout page """
_logout(request)
return redirect(login)
+
def signup(request):
""" The signup page """
signup_form = None
@@ -108,31 +150,37 @@ def signup(request):
signup_form = SignupForm(request.POST)
if signup_form.is_valid():
try:
- if signup_form.cleaned_data['password_origin'] != signup_form.cleaned_data['password_verify']:
+ if signup_form.cleaned_data['password_origin'] != \
+ signup_form.cleaned_data['password_verify']:
raise OkupyError("Passwords don't match")
try:
- anon_ldap_user = ldap.initialize(settings.AUTH_LDAP_SERVER_URI)
- anon_ldap_user.simple_bind_s(settings.AUTH_LDAP_BIND_DN, settings.AUTH_LDAP_BIND_PASSWORD)
+ anon_ldap_user = ldap.initialize(
+ settings.AUTH_LDAP_SERVER_URI)
+ anon_ldap_user.simple_bind_s(
+ settings.AUTH_LDAP_BIND_DN,
+ settings.AUTH_LDAP_BIND_PASSWORD)
except Exception as error:
logger.critical(error, extra=log_extra_data(request))
logger_mail.exception(error)
raise OkupyError("Can't contact LDAP server")
if anon_ldap_user.search_s(
settings.AUTH_LDAP_USER_BASE_DN, ldap.SCOPE_ONELEVEL,
- filterstr = '(uid=%s)' % signup_form.cleaned_data['username']):
+ filterstr='(uid=%s)' %
+ signup_form.cleaned_data['username']):
raise OkupyError('Username already exists')
if anon_ldap_user.search_s(
settings.AUTH_LDAP_USER_BASE_DN, ldap.SCOPE_ONELEVEL,
- filterstr = '(mail=%s)' % signup_form.cleaned_data['email']):
+ filterstr='(mail=%s)' %
+ signup_form.cleaned_data['email']):
raise OkupyError('Email already exists')
anon_ldap_user.unbind_s()
queued_user = Queue(
- username = signup_form.cleaned_data['username'],
- first_name = signup_form.cleaned_data['first_name'],
- last_name = signup_form.cleaned_data['last_name'],
- email = signup_form.cleaned_data['email'],
- password = signup_form.cleaned_data['password_origin'],
- token = random_string(40),
+ username=signup_form.cleaned_data['username'],
+ first_name=signup_form.cleaned_data['first_name'],
+ last_name=signup_form.cleaned_data['last_name'],
+ email=signup_form.cleaned_data['email'],
+ password=signup_form.cleaned_data['password_origin'],
+ token=random_string(40),
)
try:
queued_user.save()
@@ -144,13 +192,15 @@ def signup(request):
raise OkupyError("Can't contact the database")
send_mail(
'%sAccount Activation' % settings.EMAIL_SUBJECT_PREFIX,
- 'To confirm your email address, please click the following link:\n%s' % queued_user.token,
+ 'To confirm your email address, please click the \
+ following link:\n%s' % queued_user.token,
'%s' % settings.SERVER_EMAIL,
[signup_form.cleaned_data['email']]
)
- messages.info(request, "You will shortly receive an activation mail")
+ messages.info(
+ request, "You will shortly receive an activation mail")
return redirect(login)
- except OkupyError, error:
+ except OkupyError as error:
messages.error(request, str(error))
else:
signup_form = SignupForm()
@@ -158,6 +208,7 @@ def signup(request):
'signup_form': signup_form,
})
+
def activate(request, token):
"""
The page that users get to activate their accounts
@@ -177,7 +228,9 @@ def activate(request, token):
# add account to ldap
try:
admin_ldap_user = ldap.initialize(settings.AUTH_LDAP_SERVER_URI)
- admin_ldap_user.simple_bind_s(settings.AUTH_LDAP_ADMIN_BIND_DN, settings.AUTH_LDAP_ADMIN_BIND_PASSWORD)
+ admin_ldap_user.simple_bind_s(
+ settings.AUTH_LDAP_ADMIN_BIND_DN,
+ settings.AUTH_LDAP_ADMIN_BIND_PASSWORD)
except Exception as error:
logger.critical(error, extra=log_extra_data(request))
logger_mail.exception(error)
@@ -188,11 +241,13 @@ def activate(request, token):
'mail': [str(queued_user.email)],
'givenName': [str(queued_user.first_name)],
'sn': [str(queued_user.last_name)],
- 'gecos': ['%s %s' % (queued_user.first_name, queued_user.last_name)],
+ 'gecos': ['%s %s' % (queued_user.first_name,
+ queued_user.last_name)],
'objectClass': settings.AUTH_LDAP_USER_OBJECTCLASS,
}
if 'person' in new_user['objectClass']:
- new_user['cn'] = ['%s %s' % (queued_user.first_name, queued_user.last_name)]
+ new_user['cn'] = ['%s %s' % (
+ queued_user.first_name, queued_user.last_name)]
if 'posixAccount' in new_user['objectClass']:
try:
max_uidnumber = admin_ldap_user.search_s(
@@ -203,51 +258,63 @@ def activate(request, token):
max_uidnumber = 0
new_user['uidNumber'] = [str(int(max_uidnumber) + 1)]
new_user['gidNumber'] = ['100']
- new_user['homeDirectory'] = ['/home/%s' % str(queued_user.username)]
+ new_user['homeDirectory'] = [
+ '/home/%s' % str(queued_user.username)]
ldif = modlist.addModlist(new_user)
- admin_ldap_user.add_s('uid=%s,%s' % (queued_user.username, settings.AUTH_LDAP_USER_BASE_DN), ldif)
+ admin_ldap_user.add_s('uid=%s,%s' % (
+ queued_user.username, settings.AUTH_LDAP_USER_BASE_DN), ldif)
admin_ldap_user.unbind_s()
# remove queued account from DB
queued_user.delete()
- messages.success(request, "Your account has been activated successfully")
- except OkupyError, error:
+ messages.success(
+ request, "Your account has been activated successfully")
+ except OkupyError as error:
messages.error(request, str(error))
return redirect(login)
+
+def devlist(request):
+ return render(request, 'devlist.html', {})
+
+
def formerdevlist(request):
return render(request, 'former-devlist.html', {})
+
def foundationlist(request):
return render(request, 'foundation-members.html', {})
# OpenID-specific
+
def endpoint_url(request):
return request.build_absolute_uri(reverse(openid_endpoint))
+
def get_openid_server(request):
store = DjangoDBOpenIDStore()
return Server(store, endpoint_url(request))
-def render_openid_response(request, oresp, srv = None):
+
+def render_openid_response(request, oresp, srv=None):
if srv is None:
srv = get_openid_server(request)
try:
eresp = srv.encodeResponse(oresp)
except EncodingError as e:
- # XXX: do we want some different heading for it?
- return render(request, 'openid_endpoint.html',
- {
- 'error': str(e)
- }, status = 500)
+ # TODO: do we want some different heading for it?
+ return render(request, 'openid_endpoint.html', {
+ 'error': str(e),
+ }, status=500)
- dresp = HttpResponse(eresp.body, status = eresp.code)
+ dresp = HttpResponse(eresp.body, status=eresp.code)
for h, v in eresp.headers.items():
dresp[h] = v
return dresp
+
@csrf_exempt
def openid_endpoint(request):
if request.method == 'POST':
@@ -265,12 +332,11 @@ def openid_endpoint(request):
elif e.whichEncoding() == ENCODE_HTML_FORM:
return HttpResponse(e.toHTML())
elif e.whichEncoding() == ENCODE_KVFORM:
- return HttpResponse(e.encodeToKVForm(), status = 400)
+ return HttpResponse(e.encodeToKVForm(), status=400)
else:
- return render(request, 'openid_endpoint.html',
- {
- 'error': str(e)
- }, status = 400)
+ return render(request, 'openid_endpoint.html', {
+ 'error': str(e)
+ }, status=400)
if oreq is None:
return render(request, 'openid_endpoint.html')
@@ -288,20 +354,22 @@ def openid_endpoint(request):
return render_openid_response(request, oresp, srv)
+
def user_page(request, username):
return render(request, 'user-page.html', {
- 'endpoint_uri': endpoint_url(request)
+ 'endpoint_uri': endpoint_url(request),
})
+
@login_required
def openid_auth_site(request):
try:
oreq = request.session['openid_request']
except KeyError:
- return render(request, 'openid-auth-site.html',
- {
- 'error': 'No OpenID request associated. The request may have expired.'
- }, status = 400)
+ return render(request, 'openid-auth-site.html', {
+ 'error': 'No OpenID request associated. The request may have \
+ expired.',
+ }, status=400)
sreg = SRegRequest.fromOpenIDRequest(oreq)
@@ -310,7 +378,7 @@ def openid_auth_site(request):
# can it be invalid somehow?
assert(form.is_valid())
- attrs = form.save(commit = False)
+ attrs = form.save(commit=False)
# nullify fields that were not requested
for fn in form.cleaned_data:
@@ -320,22 +388,20 @@ def openid_auth_site(request):
# TODO: actually send the data
if 'accept' in request.POST:
- oresp = oreq.answer(True,
- identity=request.build_absolute_uri(
- reverse(user_page, args=(request.user.username,))))
+ oresp = oreq.answer(True, identity=request.build_absolute_uri(
+ reverse(user_page, args=(request.user.username,))))
elif 'reject' in request.POST:
oresp = oreq.answer(False)
else:
- return render(request, 'openid-auth-site.html',
- {
- 'error': 'Invalid request submitted.'
- }, status = 400)
+ return render(request, 'openid-auth-site.html', {
+ 'error': 'Invalid request submitted.',
+ }, status=400)
del request.session['openid_request']
return render_openid_response(request, oresp)
try:
- # XXX: cache it
+ # TODO: cache it
if oreq.returnToVerified():
tr_valid = 'Return-To valid and trusted'
else:
@@ -346,10 +412,9 @@ def openid_auth_site(request):
tr_valid = 'Unable to verify trust (HTTP error)'
form = SiteAuthForm()
- return render(request, 'openid-auth-site.html',
- {
- 'openid_request': oreq,
- 'return_to_valid': tr_valid,
- 'form': form,
- 'sreg': sreg,
- })
+ return render(request, 'openid-auth-site.html', {
+ 'openid_request': oreq,
+ 'return_to_valid': tr_valid,
+ 'form': form,
+ 'sreg': sreg,
+ })
diff --git a/okupy/common/exceptions.py b/okupy/common/exceptions.py
index fc04ea3..a979503 100644
--- a/okupy/common/exceptions.py
+++ b/okupy/common/exceptions.py
@@ -1,4 +1,5 @@
# vim:fileencoding=utf8:et:ts=4:sts=4:sw=4:ft=python
+
class OkupyError(Exception):
pass
diff --git a/okupy/common/log.py b/okupy/common/log.py
index 4f016c8..c8994cc 100644
--- a/okupy/common/log.py
+++ b/okupy/common/log.py
@@ -2,11 +2,12 @@
from django.conf import settings
-def log_extra_data(additional = None):
+
+def log_extra_data(additional=None):
'''
Extra data needed by the custom formatter
- * If the additional argument is a string or unicode, then its value is printed
- in the log.
+ * If the additional argument is a string or unicode, then its value is
+ printed in the log.
* If the additional argument is the request, then from the request it
prints the client IP and username if applicable.
'''
diff --git a/okupy/common/testcase.py b/okupy/common/testcase.py
index 3dd7d40..251b361 100644
--- a/okupy/common/testcase.py
+++ b/okupy/common/testcase.py
@@ -3,7 +3,9 @@
from django.test import TestCase
from django.contrib.messages.storage.cookie import CookieStorage
+
class OkupyTestCase(TestCase):
+
def _get_matches(self, response, text):
""" Get messages that match the given text """
messages = self._get_messages(response)
@@ -19,7 +21,8 @@ class OkupyTestCase(TestCase):
messages = response.context['messages']
except (TypeError, KeyError):
try:
- messages = CookieStorage(response)._decode(response.cookies['messages'].value)
+ messages = CookieStorage(response)._decode(
+ response.cookies['messages'].value)
except KeyError:
return
return messages
@@ -35,7 +38,7 @@ class OkupyTestCase(TestCase):
actual_num = 0
if actual_num != expect_num:
self.fail('Message count was %d, expected %d' %
- (actual_num, expect_num))
+ (actual_num, expect_num))
def assertMessage(self, response, text, level=None):
"""
@@ -46,18 +49,19 @@ class OkupyTestCase(TestCase):
msg = matches[0]
if level is not None and msg.level != level:
self.fail('There was one matching message but with different '
- 'level: %s != %s' % (msg.level, level))
+ 'level: %s != %s' % (msg.level, level))
elif len(matches) == 0:
- messages_str = ", ".join('"%s"' % m for m in self._get_messages(response))
+ messages_str = ", ".join(
+ '"%s"' % m for m in self._get_messages(response))
self.fail('No message contained text "%s", messages were: %s' %
- (text, messages_str))
+ (text, messages_str))
else:
self.fail('Multiple messages contained text "%s": %s' %
- (text, ", ".join(('"%s"' % m) for m in matches)))
+ (text, ", ".join(('"%s"' % m) for m in matches)))
def assertNotMessage(self, response, text):
""" Assert that no message contains the given text. """
matches = self._get_matches(response, text)
if len(matches) > 0:
self.fail('Message(s) contained text "%s": %s' %
- (text, ", ".join(('"%s"' % m) for m in matches)))
+ (text, ", ".join(('"%s"' % m) for m in matches)))
diff --git a/okupy/settings/__init__.py b/okupy/settings/__init__.py
index e811e89..9daa78e 100644
--- a/okupy/settings/__init__.py
+++ b/okupy/settings/__init__.py
@@ -80,7 +80,6 @@ LOGGING = {
'formatter': 'simple',
'address': '/dev/log',
},
-
},
'loggers': {
'mail_okupy': {
@@ -123,3 +122,15 @@ EMAIL_SUBJECT_PREFIX = '[%s]: ' % INSTANCE_NAME
TEMPLATE_CONTEXT_PROCESSORS += (
'django.core.context_processors.request',
)
+
+# django-ldapdb settings
+DATABASES['ldap'] = {
+ 'ENGINE': 'ldapdb.backends.ldap',
+ 'NAME': AUTH_LDAP_SERVER_URI,
+ 'USER': AUTH_LDAP_BIND_DN,
+ 'PASSWORD': AUTH_LDAP_BIND_PASSWORD,
+ 'CONNECTION_OPTIONS': AUTH_LDAP_CONNECTION_OPTIONS,
+ 'TLS': AUTH_LDAP_START_TLS,
+}
+
+DATABASE_ROUTERS = ['ldapdb.router.Router']
diff --git a/okupy/settings/local.py.sample b/okupy/settings/local.py.sample
index 79fd533..454906c 100644
--- a/okupy/settings/local.py.sample
+++ b/okupy/settings/local.py.sample
@@ -60,26 +60,14 @@ AUTH_LDAP_ADMIN_BIND_DN = ''
AUTH_LDAP_ADMIN_BIND_PASSWORD = ''
AUTH_LDAP_USER_ATTR = 'uid'
-AUTH_LDAP_USER_BASE_DN = 'ou=people,o=test'
+AUTH_LDAP_USER_BASE_DN = 'ou=people,dc=example,dc=com'
AUTH_LDAP_PERMIT_EMPTY_PASSWORD = False
AUTH_LDAP_START_TLS = False
-#AUTH_LDAP_GROUP_SEARCH
-#AUTH_LDAP_GROUP_TYPE
-#AUTH_LDAP_REQUIRE_GROUP
-#AUTH_LDAP_DENY_GROUP
-#AUTH_LDAP_CACHE_GROUPS
-#AUTH_LDAP_GROUP_CACHE_TIMEOUT
-#AUTH_LDAP_FIND_GROUP_PERMS
-
-#AUTH_LDAP_USER_FLAGS_BY_GROUP = {
- #'is_active': '',
- #'is_staff': '',
- #'is_superuser': '',
-#}
-
-#AUTH_LDAP_PROFILE_FLAGS_BY_GROUP = {}
-
-AUTH_LDAP_USER_OBJECTCLASS = ["person", "organizationalPerson", "inetOrgPerson", "posixAccount"]
+# objectClasses that are used by any user
+AUTH_LDAP_USER_OBJECTCLASS = ['top', 'person', 'organizationalPerson',
+ 'inetOrgPerson', 'posixAccount', 'shadowAccount']
+# additional objectClasses that are used by developers
+AUTH_LDAP_DEV_OBJECTCLASS = ['developerAccount']
diff --git a/okupy/templates/base.html b/okupy/templates/base.html
index e63c55c..f96a6a2 100644
--- a/okupy/templates/base.html
+++ b/okupy/templates/base.html
@@ -25,7 +25,7 @@
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</a>
- <a class="brand" href="#">
+ <a class="brand" href="/">
<img src="{%static "img/site-logo.png"%}" alt="Gentoo Logo" />
</a>
<div class="nav-collapse">
@@ -36,7 +36,7 @@
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Lists<b class="caret"></b></a>
<ul class="dropdown-menu">
- <li><a href="/">Developer List</a></li>
+ <li><a href="/devlist/">Developer List</a></li>
<li><a href="/foundation-members/">Foundation Members</a></li>
<li><a href="/former-devlist/">Former Developer List</a></li>
</ul>
@@ -45,21 +45,33 @@
<ul class="nav pull-right">
<li class="divider-vertical"></li>
<li class="dropdown">
- <a href="#" class="dropdown-toggle" data-toggle="dropdown">gentoo.org Sites <b class="caret"></b></a>
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">gentoo.org Sites <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+ <li><a href="http://www.gentoo.org/">gentoo.org</a></li>
+ <li><a href="http://wiki.gentoo.org/" title="Find and contribute documentation">Wiki</a></li>
+ <li><a href="https://bugs.gentoo.org/" title="Report issues and find common issues">Bugs</a></li>
+ <li><a href="http://forums.gentoo.org/" title="Discuss with the community">Forums</a></li>
+ <li><a href="http://packages.gentoo.org/" title="Find software for your Gentoo">Packages</a></li>
+ <li class="divider"></li>
+ <li><a href="http://archives.gentoo.org/" title="Read up on past discussions">Archives</a></li>
+ <li><a href="http://overlays.gentoo.org/" title="Collaborate on maintaining packages">Overlays</a></li>
+ <li><a href="http://planet.gentoo.org/" title="Find out what's going on in the developer community">Planet</a></li>
+ <li><a href="http://sources.gentoo.org/" title="Browse our source code">Sources</a></li>
+ </ul>
+ </li>
+ {% if user.is_authenticated %}
+ <li class="divider-vertical"></li>
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">{{ user }}<b class="caret"></b></a>
<ul class="dropdown-menu">
- <li><a href="http://www.gentoo.org/">gentoo.org</a></li>
- <li><a href="http://wiki.gentoo.org/" title="Find and contribute documentation">Wiki</a></li>
- <li><a href="https://bugs.gentoo.org/" title="Report issues and find common issues">Bugs</a></li>
- <li><a href="http://forums.gentoo.org/" title="Discuss with the community">Forums</a></li>
- <li><a href="http://packages.gentoo.org/" title="Find software for your Gentoo">Packages</a></li>
- <li class="divider"></li>
- <li><a href="http://archives.gentoo.org/" title="Read up on past discussions">Archives</a></li>
- <li><a href="http://overlays.gentoo.org/" title="Collaborate on maintaining packages">Overlays</a></li>
- <li><a href="http://planet.gentoo.org/" title="Find out what's going on in the developer community">Planet</a></li>
- <li><a href="http://sources.gentoo.org/" title="Browse our source code">Sources</a></li>
+ <li><a href="/" title="View Profile">View Profile</a></li>
+ <li><a href="#" title="Edit Profile">Edit Profile</a></li>
+ <li><a href="#" title="Invite others">Invite</a></li>
+ <li><a href="/logout/" title="Logout">Logout</a></li>
</ul>
- </li>
- </ul>
+ </li>
+ {% endif %}
+ </ul>
</div>
</div>
</div>
diff --git a/okupy/templates/devlist.html b/okupy/templates/devlist.html
new file mode 100644
index 0000000..93cee67
--- /dev/null
+++ b/okupy/templates/devlist.html
@@ -0,0 +1,46 @@
+{% extends "base.html" %}
+{% block content %}
+<div class="hero-unit">
+ <h1>Developers List</h1>
+ <p>List of active Gentoo developers.</p>
+</div>
+<p>
+<div class="row">
+ <div class="span12">
+ <h2>Developer List</h2><br />
+ <table class="table table-striped sortable" >
+ <tr>
+ <td class="infohead"><b>Username</b></td>
+ <td class="infohead"><b>Name</b></td>
+ <td class="infohead"><b>GPG key</b></td>
+ <td class="infohead"><b>Location</b></td>
+ <td class="infohead"><b>Areas of responsibility</b></td>
+ </tr>
+ <tr>
+ <td style="color:#5c4f85;"><b>mgorny</b></td>
+ <td>Michał Górny</td>
+ <td>0xDF84256885283521</td>
+ <td><a href="devmap.xml?dev=mgorny">near Poznan, Poland</a></td>
+ <td class="tableinfo">-</td>
+ </tr>
+ <tr>
+ <td class="infohead" style="color:#5c4f85;"><b>tampakrap</b></td>
+ <td class="tableinfo">Theo Chatzimichos</td>
+ <td class="tableinfo">0x57DC0078</td>
+ <td class="tableinfo"><a href="devmap.xml?dev=tampakrap">Larissa, Greece</a></td>
+ <td class="tableinfo">Infrastructure</td>
+ </tr>
+ <tr>
+ <td class="infohead" style="color:#5c4f85;"><b>dastergon</b></td>
+ <td class="tableinfo">Pavlos Ratis</td>
+ <td class="tableinfo">0x3A051746</td>
+ <td class="tableinfo">Serres, Greece</td>
+ <td class="tableinfo">kde</td>
+ </tr>
+ </table>
+ </div>
+</div>
+</p>
+{% endblock %}
+
+{# vim:se fileencoding=utf8 et ts=4 sts=4 sw=4 ft=htmldjango : #}
diff --git a/okupy/templates/index.html b/okupy/templates/index.html
index 93cee67..eec6d06 100644
--- a/okupy/templates/index.html
+++ b/okupy/templates/index.html
@@ -1,46 +1,48 @@
{% extends "base.html" %}
+
{% block content %}
-<div class="hero-unit">
- <h1>Developers List</h1>
- <p>List of active Gentoo developers.</p>
-</div>
-<p>
-<div class="row">
- <div class="span12">
- <h2>Developer List</h2><br />
- <table class="table table-striped sortable" >
- <tr>
- <td class="infohead"><b>Username</b></td>
- <td class="infohead"><b>Name</b></td>
- <td class="infohead"><b>GPG key</b></td>
- <td class="infohead"><b>Location</b></td>
- <td class="infohead"><b>Areas of responsibility</b></td>
- </tr>
- <tr>
- <td style="color:#5c4f85;"><b>mgorny</b></td>
- <td>Michał Górny</td>
- <td>0xDF84256885283521</td>
- <td><a href="devmap.xml?dev=mgorny">near Poznan, Poland</a></td>
- <td class="tableinfo">-</td>
- </tr>
- <tr>
- <td class="infohead" style="color:#5c4f85;"><b>tampakrap</b></td>
- <td class="tableinfo">Theo Chatzimichos</td>
- <td class="tableinfo">0x57DC0078</td>
- <td class="tableinfo"><a href="devmap.xml?dev=tampakrap">Larissa, Greece</a></td>
- <td class="tableinfo">Infrastructure</td>
- </tr>
- <tr>
- <td class="infohead" style="color:#5c4f85;"><b>dastergon</b></td>
- <td class="tableinfo">Pavlos Ratis</td>
- <td class="tableinfo">0x3A051746</td>
- <td class="tableinfo">Serres, Greece</td>
- <td class="tableinfo">kde</td>
- </tr>
- </table>
+<div id="pageRow" class="container">
+ <div class="row">
+ <div id="page" class="span10">
+ <div class="row-fluid">
+ <p>
+ <div class="span9">
+ <h3>Personal Information</h3><br />
+ <table class="table table-bordered table-striped table-condensed fixed-cell" id="yw0">
+ {% for key,attr in ldap_personal_info.items %}
+ <tr class={% cycle 'odd' 'even' %}><th>{{ key }}</th><td>{{ attr }}</td></tr>
+ {% endfor %}
+ </table>
+ </p>
+ </div>
+ </div>
+ <div class="row-fluid">
+ <p>
+ <div class="span9">
+ <h3>Contact Information</h3><br />
+ <table class="table table-bordered table-striped table-condensed fixed-cell" id="yw1">
+ {% for key,attr in ldap_contact_info.items %}
+ <tr class={% cycle 'odd' 'even' %}><th>{{ key }}</th><td>{{ attr }}</td></tr>
+ {% endfor %}
+ </table>
+ </div>
+ </p>
+ </div>
+ <div class="row-fluid">
+ <p>
+ <div class="span9">
+ <h3>Gentoo related Information</h3><br />
+ <table class="table table-bordered table-striped table-condensed fixed-cell" id="yw1">
+ {% for key,attr in ldap_gentoo_info.items %}
+ <tr class={% cycle 'odd' 'even' %}><th>{{ key }}</th><td>{{ attr }}</td></tr>
+ {% endfor %}
+ </table>
+ </div>
+ </p>
+ </div>
+ </div>
</div>
</div>
-</p>
{% endblock %}
{# vim:se fileencoding=utf8 et ts=4 sts=4 sw=4 ft=htmldjango : #}
diff --git a/okupy/tests/__init__.py b/okupy/tests/__init__.py
index f52534a..e69de29 100644
--- a/okupy/tests/__init__.py
+++ b/okupy/tests/__init__.py
@@ -1,2 +0,0 @@
-# vim:fileencoding=utf8:et:ts=4:sts=4:sw=4:ft=python
-
diff --git a/okupy/tests/integration/index.py b/okupy/tests/integration/index.py
index ebec9ba..7de50ef 100644
--- a/okupy/tests/integration/index.py
+++ b/okupy/tests/integration/index.py
@@ -5,12 +5,11 @@ from django.test.client import Client
from mockldap import MockLdap
from ...common.testcase import OkupyTestCase
-from ..tests import example_directory
class IndexTests(OkupyTestCase):
@classmethod
def setUpClass(cls):
- cls.mockldap = MockLdap(example_directory)
+ cls.mockldap = MockLdap(settings.DIRECTORY)
def setUp(self):
self.client = Client()
diff --git a/okupy/tests/integration/login.py b/okupy/tests/integration/login.py
index 9c209d6..98e7a58 100644
--- a/okupy/tests/integration/login.py
+++ b/okupy/tests/integration/login.py
@@ -8,7 +8,6 @@ from django.test.client import Client
from mockldap import MockLdap
from ...common.testcase import OkupyTestCase
-from ..tests import example_directory
import mock
@@ -18,7 +17,7 @@ class LoginTestsEmptyDB(OkupyTestCase):
@classmethod
def setUpClass(cls):
- cls.mockldap = MockLdap(example_directory)
+ cls.mockldap = MockLdap(settings.DIRECTORY)
def setUp(self):
self.client = Client()
@@ -85,18 +84,6 @@ class LoginTestsEmptyDB(OkupyTestCase):
self.assertEqual(User.objects.count(), 0)
self.mockldap.start()
- def test_weird_account(self):
- account = {'username': 'dreßler', 'password': 'password'}
- response = self.client.post('/login/', account)
- self.assertRedirects(response, '/')
- user = User.objects.get(pk=1)
- self.assertEqual(User.objects.count(), 1)
- self.assertEqual(user.username, u'dreßler')
- self.assert_(not user.has_usable_password())
- self.assertEqual(user.first_name, '')
- self.assertEqual(user.last_name, '')
- self.assertEqual(user.email, '')
-
@mock.patch("django.db.backends.util.CursorWrapper", cursor_wrapper)
def test_no_database(self):
response = self.client.post('/login/', self.account)
@@ -123,7 +110,7 @@ class LoginTestsOneAccountInDB(OkupyTestCase):
@classmethod
def setUpClass(cls):
- cls.mockldap = MockLdap(example_directory)
+ cls.mockldap = MockLdap(settings.DIRECTORY)
def setUp(self):
self.client = Client()
diff --git a/okupy/tests/integration/signup.py b/okupy/tests/integration/signup.py
index 010bc4e..f5b5140 100644
--- a/okupy/tests/integration/signup.py
+++ b/okupy/tests/integration/signup.py
@@ -9,7 +9,6 @@ from mockldap import MockLdap
from ...accounts.models import Queue
from ...common.testcase import OkupyTestCase
-from ..tests import example_directory
import mock
@@ -62,7 +61,7 @@ class SignupTestsOneAccountInQueue(OkupyTestCase):
@classmethod
def setUpClass(cls):
- cls.mockldap = MockLdap(example_directory)
+ cls.mockldap = MockLdap(settings.DIRECTORY)
def setUp(self):
self.client = Client()
@@ -92,7 +91,7 @@ class SignupTestsOneAccountInQueue(OkupyTestCase):
self.assertEqual(ldap_account['givenName'][0], self.queued_account.first_name)
self.assertEqual(ldap_account['sn'][0], self.queued_account.last_name)
self.assertEqual(ldap_account['objectClass'], settings.AUTH_LDAP_USER_OBJECTCLASS)
- self.assertEqual(ldap_account['uidNumber'][0], '1003')
+ self.assertEqual(ldap_account['uidNumber'][0], '1002')
self.assertEqual(ldap_account['mail'][0], self.queued_account.email)
data={'username': self.queued_account.username, 'password': 'queuedpass'}
response = self.client.post('/login/', data)
diff --git a/okupy/tests/settings.py b/okupy/tests/settings.py
index 0081d53..fefbdab 100644
--- a/okupy/tests/settings.py
+++ b/okupy/tests/settings.py
@@ -12,6 +12,15 @@ ADMINS = (
('admin', 'admin@example.com'),
)
+# Instance name, used in:
+# * log dir name: /var/log/okupy/${INSTANCE_NAME}
+# * console logs: ${INSTANCE_NAME} ${IP} ${ERROR}
+# * prefix of the notification mails: "[${INSTANCE_NAME}] ${TITLE}"
+# * (production only): {MEDIA,STATIC}_ROOT:
+# /var/www/${INSTANCE_NAME}/htdocs/{media,static}
+# Examples: okupy, okupy-dev, identity.gentoo.org
+INSTANCE_NAME = 'okupy-test'
+
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
@@ -41,40 +50,21 @@ AUTH_LDAP_ADMIN_BIND_PASSWORD = ''
AUTH_LDAP_USER_ATTR = 'uid'
AUTH_LDAP_USER_BASE_DN = 'ou=people,o=test'
-AUTH_LDAP_USER_DN_TEMPLATE = AUTH_LDAP_USER_ATTR + '=%(user)s,' + AUTH_LDAP_USER_BASE_DN
AUTH_LDAP_PERMIT_EMPTY_PASSWORD = False
AUTH_LDAP_START_TLS = False
-#AUTH_LDAP_GROUP_SEARCH
-#AUTH_LDAP_GROUP_TYPE
-#AUTH_LDAP_REQUIRE_GROUP
-#AUTH_LDAP_DENY_GROUP
-#AUTH_LDAP_CACHE_GROUPS
-#AUTH_LDAP_GROUP_CACHE_TIMEOUT
-#AUTH_LDAP_FIND_GROUP_PERMS
-
-#AUTH_LDAP_USER_FLAGS_BY_GROUP = {
- #'is_active': '',
- #'is_staff': '',
- #'is_superuser': '',
-#}
-
-#AUTH_LDAP_PROFILE_FLAGS_BY_GROUP = {}
-
-AUTH_LDAP_USER_OBJECTCLASS = ["person", "organizationalPerson", "inetOrgPerson", "posixAccount"]
+# objectClasses that are used by any user
+AUTH_LDAP_USER_OBJECTCLASS = ['top', 'person', 'organizationalPerson',
+ 'inetOrgPerson', 'posixAccount', 'shadowAccount']
+# additional objectClasses that are used by developers
+AUTH_LDAP_DEV_OBJECTCLASS = ['developerAccount']
# DEBUG Options: Select "True" for development use, "False" for production use
DEBUG = False
TEMPLATE_DEBUG = DEBUG
-# Instance name, used in:
-# * prefix of the notification mails: "[${INSTANCE_NAME}] ${TITLE}"
-# * log dir name: /var/log/${INSTANCE_NAME}
-# * console logs: ${INSTANCE_NAME} ${IP} ${ERROR}
-INSTANCE_NAME = 'okupy-test'
-
# Hosts/domain names that are valid for this site; required if DEBUG is False
# See https://docs.djangoproject.com/en/1.5/ref/settings/#allowed-hosts
ALLOWED_HOSTS = []
@@ -173,6 +163,10 @@ INSTALLED_APPS = (
'okupy.tests'
)
+#Compressor settings
+COMPRESS_ENABLED = False
+COMPRESS_PARSER = 'compressor.parser.HtmlParser'
+
MANAGERS = ADMINS
SITE_ID = 1
@@ -191,11 +185,11 @@ LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
- 'okupy': {
+ 'verbose': {
'format': '%(instance_name)s: %(levelname)s %(id_name)s %(client_ip)s Message: %(message)s File: %(module)s Function: %(funcName)s Line: %(lineno)d',
},
- 'django_auth_ldap': {
- 'format': 'django-auth-ldap: %(levelname)s Message: %(message)s',
+ 'simple': {
+ 'format': '$(instance_name)s: %(levelname)s Message: %(message)s File: %(module)s Function: %(funcName)s Line: %(lineno)d',
},
},
'filters': {
@@ -210,18 +204,28 @@ LOGGING = {
'class': 'django.utils.log.AdminEmailHandler',
'include_html': True,
},
+ 'console_v': {
+ 'level': 'DEBUG',
+ 'class': 'logging.StreamHandler',
+ 'formatter': 'verbose',
+ },
+ 'syslog_v': {
+ 'level': 'INFO',
+ 'class': 'logging.handlers.SysLogHandler',
+ 'formatter': 'verbose',
+ 'address': '/dev/log',
+ },
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
- 'formatter': 'okupy',
+ 'formatter': 'simple',
},
'syslog': {
'level': 'INFO',
'class': 'logging.handlers.SysLogHandler',
- 'formatter': 'okupy',
+ 'formatter': 'simple',
'address': '/dev/log',
},
-
},
'loggers': {
'mail_okupy': {
@@ -230,6 +234,14 @@ LOGGING = {
'propagate': True,
},
'okupy': {
+ 'handlers': ['console_v' if DEBUG else 'syslog_v'],
+ 'level': 'DEBUG' if DEBUG else 'INFO',
+ },
+ 'okupy_simple': {
+ 'handlers': ['console' if DEBUG else 'syslog'],
+ 'level': 'DEBUG' if DEBUG else 'INFO',
+ },
+ 'django_auth_ldap': {
'handlers': ['console' if DEBUG else 'syslog'],
'level': 'DEBUG' if DEBUG else 'INFO',
},
@@ -241,15 +253,56 @@ LOGIN_REDIRECT_URL = '/'
LOGOUT_URL = '/logout/'
SESSION_EXPIRE_AT_BROWSER_CLOSE = True
+AUTH_LDAP_USER_DN_TEMPLATE = AUTH_LDAP_USER_ATTR + '=%(user)s,' + AUTH_LDAP_USER_BASE_DN
+
# Custom authentication backend
AUTHENTICATION_BACKENDS = (
'django_auth_ldap.backend.LDAPBackend',
'django.contrib.auth.backends.ModelBackend',
)
+# email sending variables regarding server authentication
+# and configuration should be specified in settings/local.py
EMAIL_SUBJECT_PREFIX = '[%s]: ' % INSTANCE_NAME
-SERVER_EMAIL = 'no-reply@example.com'
-#Compressor Settings
-COMPRESS_ENABLED = False
-COMPRESS_PARSER = 'compressor.parser.HtmlParser'
+TEMPLATE_CONTEXT_PROCESSORS += (
+ 'django.core.context_processors.request',
+)
+
+# django-ldapdb settings
+# they break the existing tests for unknown reason
+# disabling them temporarily since they are not actually used yet
+# needs to be fixed though asap
+#DATABASES['ldap'] = {
+# 'ENGINE': 'ldapdb.backends.ldap',
+# 'NAME': AUTH_LDAP_SERVER_URI,
+# 'USER': AUTH_LDAP_BIND_DN,
+# 'PASSWORD': AUTH_LDAP_BIND_PASSWORD,
+# 'CONNECTION_OPTIONS': AUTH_LDAP_CONNECTION_OPTIONS,
+# 'TLS': AUTH_LDAP_START_TLS,
+#}
+
+DATABASE_ROUTERS = ['ldapdb.router.Router']
+
+DIRECTORY = {
+ "uid=alice,ou=people,o=test": {
+ "uid": ["alice"],
+ "userPassword": ['{CRYPT}$1$lO/RU6zz$2fJCOwurxBtCqdImkoLQo1'],
+ "objectClass": AUTH_LDAP_USER_OBJECTCLASS + AUTH_LDAP_DEV_OBJECTCLASS,
+ "uidNumber": ["1000"],
+ "gidNumber": ["1000"],
+ "givenName": ["Alice"],
+ "sn": ["Adams"],
+ "mail": ["alice@test.com"],
+ },
+ "uid=bob,ou=people,o=test": {
+ "uid": ["bob"],
+ "userPassword": ['{CRYPT}$1$eFSQMJY6$8y.WUL/ONeEarVXqeCIbH.'],
+ "objectClass": AUTH_LDAP_USER_OBJECTCLASS,
+ "uidNumber": ["1001"],
+ "gidNumber": ["50"],
+ "givenName": ["Robert"],
+ "sn": ["Barker"],
+ "mail": ["bob@test.com"],
+ }
+}
diff --git a/okupy/tests/tests.py b/okupy/tests/tests.py
index 4bf6de7..38d660f 100644
--- a/okupy/tests/tests.py
+++ b/okupy/tests/tests.py
@@ -1,38 +1,5 @@
# vim:fileencoding=utf8:et:ts=4:sts=4:sw=4:ft=python
-example_directory = {
- "uid=alice,ou=people,o=test": {
- "uid": ["alice"],
- "userPassword": ['{CRYPT}$1$lO/RU6zz$2fJCOwurxBtCqdImkoLQo1'],
- "objectClass": ["person", "organizationalPerson", "inetOrgPerson", "posixAccount"],
- "uidNumber": ["1000"],
- "gidNumber": ["1000"],
- "givenName": ["Alice"],
- "sn": ["Adams"],
- "mail": ["alice@test.com"],
- },
- "uid=bob,ou=people,o=test": {
- "uid": ["bob"],
- "objectClass": ["person", "organizationalPerson", "inetOrgPerson", "posixAccount"],
- "userPassword": ['{CRYPT}$1$eFSQMJY6$8y.WUL/ONeEarVXqeCIbH.'],
- "uidNumber": ["1001"],
- "gidNumber": ["50"],
- "givenName": ["Robert"],
- "sn": ["Barker"],
- "mail": ["bob@test.com"],
- },
- u"uid=dreßler,ou=people,o=test".encode('utf-8'): {
- "uid": [u"dreßler".encode('utf-8')],
- "objectClass": ["person", "organizationalPerson", "inetOrgPerson", "posixAccount"],
- "userPassword": ['{CRYPT}$1$kQ3GmP3k$oKSdmDpdepvrni/JQQ4Ri.'],
- "uidNumber": ["1002"],
- "gidNumber": ["50"],
- "givenName": ["Wolfgang"],
- "sn": [u"Dreßler".encode('utf-8')],
- "mail": ["dressler@test.com"],
- }
-}
-
# run tests modules
from .integration.index import *
from .integration.login import *
diff --git a/requirements.txt b/requirements.txt
index b966c1c..e6d20ae 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,6 +1,7 @@
django>=1.5
django-auth-ldap>=1.1.4
django-compressor>=1.3
+git+https://github.com/tampakrap/django-ldapdb@okupy#egg=django-ldapdb
edpwd>=0.0.7
mock>=1.0.1
hg+https://bitbucket.org/psagers/mockldap#egg=mockldap
diff --git a/setup.py b/setup.py
index bbb1c22..a7ed559 100755
--- a/setup.py
+++ b/setup.py
@@ -3,7 +3,6 @@
from setuptools import setup, find_packages
import okupy
-import os
setup(
name='okupy',
@@ -13,7 +12,7 @@ setup(
author_email='identity@gentoo.org',
url='http://github.com/gentoo/identity.gentoo.org',
description='Django LDAP webUI and OpenID provider for the Gentoo Linux project',
- long_description=open(os.path.join(os.path.dirname(__file__), 'README.md')).read(),
+ long_description=open('README.md').read(),
keywords='django, ldap, gentoo',
packages=find_packages(),
include_package_data=True,
@@ -31,11 +30,13 @@ setup(
],
dependency_links=[
'https://bitbucket.org/psagers/mockldap/get/default.tar.gz#egg=mockldap',
+ 'https://github.com/tampakrap/django-ldapdb/archive/okupy.tar.gz#egg=django-ldapdb',
],
install_requires=[
'django>=1.5',
'django-auth-ldap>=1.1.4',
'django-compressor>=1.3',
+ 'django-ldapdb',
'edpwd>=0.0.7',
'passlib>=1.6.1',
'python-ldap>=2.4.10',