diff --git a/dal/dal/settings.py b/dal/dal/settings.py
index d3cf036..0dfd7c7 100644
--- a/dal/dal/settings.py
+++ b/dal/dal/settings.py
@@ -45,6 +45,16 @@ AUTH_LDAP_USER_SEARCH = LDAPSearchUnion(
# LDAP config end
+# Django nameko config
+
+# Where's the Rabbitmq at
+NAMEKO_CONFIG = {
+ 'AMQP_URI': 'amqp://guest:guest@127.0.0.1'
+ }
+
+# Standard pool size
+NAMEKO_POOL_SIZE = 4
+
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
@@ -71,6 +81,7 @@ INSTALLED_APPS = [
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
+ 'dal',
]
MIDDLEWARE = [
diff --git a/dal/dal/templates/changeddata.html b/dal/dal/templates/changeddata.html
index 864b1b1..4fbbff4 100644
--- a/dal/dal/templates/changeddata.html
+++ b/dal/dal/templates/changeddata.html
@@ -9,6 +9,6 @@
Email: {{email}}
-
diff --git a/dal/dal/templates/changepassword.html b/dal/dal/templates/changepassword.html
index b8afd14..ea21d5e 100644
--- a/dal/dal/templates/changepassword.html
+++ b/dal/dal/templates/changepassword.html
@@ -2,12 +2,12 @@
Changing the password for {{user}}
-
To change the password for {{user}}, please supply
-
-
To delete an account, please type the username and password below:
-
diff --git a/dal/dal/templates/error.html b/dal/dal/templates/error.html
index b13c1c8..0001244 100644
--- a/dal/dal/templates/error.html
+++ b/dal/dal/templates/error.html
@@ -6,10 +6,10 @@ While trying to {{service}}, an error was encountered: {{error}}
You can try to:
-
or
-
diff --git a/dal/dal/templates/landing.html b/dal/dal/templates/landing.html
index f6dfb0d..ce4108b 100644
--- a/dal/dal/templates/landing.html
+++ b/dal/dal/templates/landing.html
@@ -3,7 +3,8 @@
Welcome to the ungleich user service
If you want to use the user service, you will need an account on our system. If you already have one, please login below:
-
If you have an account, but forgot your password, please visit our password reset page:
-
If you don't have an account, please register yourself with us:
-
diff --git a/dal/dal/templates/loginfailed.html b/dal/dal/templates/loginfailed.html
index 5bd0e4a..9dcf74f 100644
--- a/dal/dal/templates/loginfailed.html
+++ b/dal/dal/templates/loginfailed.html
@@ -2,10 +2,10 @@
Sorry, but your login has failed
This service runs for our LDAP users, so maybe you don't already have an LDAP account with us? If so, please register one.
-
-
diff --git a/dal/dal/templates/mustbeloggedin.html b/dal/dal/templates/mustbeloggedin.html
index 031fbf3..d70cd21 100644
--- a/dal/dal/templates/mustbeloggedin.html
+++ b/dal/dal/templates/mustbeloggedin.html
@@ -2,6 +2,6 @@
You must be logged in to access this page
-
diff --git a/dal/dal/templates/registeruser.html b/dal/dal/templates/registeruser.html
index 6412db1..17d1683 100644
--- a/dal/dal/templates/registeruser.html
+++ b/dal/dal/templates/registeruser.html
@@ -2,13 +2,13 @@
Register an user at ungleich
-
To register yourself an user, please fill out the fields below:
-
diff --git a/dal/dal/templates/useroptions.html b/dal/dal/templates/useroptions.html
index 4ce5597..ec60fc6 100644
--- a/dal/dal/templates/useroptions.html
+++ b/dal/dal/templates/useroptions.html
@@ -4,18 +4,18 @@
You have the following options:
-
-
-
-
diff --git a/dal/dal/urls.py b/dal/dal/urls.py
index c6d57da..efdb67c 100644
--- a/dal/dal/urls.py
+++ b/dal/dal/urls.py
@@ -18,14 +18,14 @@ from django.urls import path
from django.conf.urls import url
from django.contrib import admin
-from .views import Register, ChangeData, ResetPassword, DeleteAccount, Index
+from .views import Register, ChangeData, ChangePassword, ResetPassword, DeleteAccount, Index
urlpatterns = [
- path('admin/', admin.site.urls),
+# path('admin/', admin.site.urls),
path('register/', Register.as_view(), name="register"),
path('changedata/', ChangeData.as_view(), name="change_data"),
path('resetpassword/', ResetPassword.as_view(), name="reset_password"),
path('changepassword/', ChangePassword.as_view(), name="change_password"),
path('deleteaccount/', DeleteAccount.as_view(), name="account_delete"),
- path('/', Index.as_view(), name="index")
+ path('index/', Index.as_view(), name="index"),
]
diff --git a/dal/dal/views.py b/dal/dal/views.py
index 45e74e4..1c1edf2 100644
--- a/dal/dal/views.py
+++ b/dal/dal/views.py
@@ -3,21 +3,16 @@ from django.views.generic import View
from django.contrib.auth import authenticate, login
from django.contrib.auth.models import User
from django.http import HttpResponse, HttpResponseRedirect
-from django.core.validators import email_re
+from django.core.validators import validate_email, ValidationError
from django.urls import reverse_lazy
-
+from django_nameko import get_pool
# Check to see if the username is already taken
# Helper function, not to be set up as a view
-# First checks the DB, since ldap parks users there
-# After that, check LDAP directly if the user just never
-# logged in
+# Check the LDAP if the user exists
def check_user_exists(username):
- if User.objects.filter(username=username).exists():
- return True
- # TODO: Needs to look up the LDAP
- else return False
-
+ with get_pool().next() as rpc:
+ return rpc.userlookup.lookup(username)
# The index page
# If there's a session open, it will give the user the options he/she/it can do, if not,
@@ -72,40 +67,50 @@ class Register(View):
# check if the supplied passwords match
if password1 != password2:
return render(request, 'registererror.html', { 'urlname': urlname, 'service': service,
- 'error': 'Your passwords didn\'t match. Please supply the same password twice.' } )
+ 'error': 'Your passwords did not match. Please supply the same password twice.' } )
email = request.POST.get('email')
# Is the emailaddress valid?
- if not email_re.match(email):
+ try:
+ validate_email(email)
+ except ValidationError:
return render(request, 'registererror.html', { 'urlname': urlname, 'service': service, 'error': 'The supplied email address is invalid.' } )
+
firstname = request.POST.get('firstname')
lastname = request.POST.get('lastname')
- if firstname == "" or not firstname or lastname == "" or not lastname
+ if firstname == "" or not firstname or lastname == "" or not lastname:
return render(request, 'registererror.html', { 'urlname': urlname, 'service': service, 'error': 'Please enter your firstname and lastname.' } )
# throw it to nameko to create the user
- if self.create_user(username, password1, firstname, lastname, email):
- return render(request, 'usercreated.html', { 'user': username } )
- return render(request, 'error.html', { 'urlname': urlname, 'service': service, 'error': 'Unknown error while creating the user.' } )
+ with get_pool().next() as rpc:
+ result = rpc.createuser.create_user(username, password1, firstname, lastname, email)
+ if result == True:
+ return render(request, 'usercreated.html', { 'user': username } )
+ else:
+ return render(request, 'error.html', { 'urlname': urlname, 'service': service, 'error': result } )
- def create_user(self, username, password, firstname, lastname, email):
- #TODO: write nameko function to create a user
- return True
-
# Change user data for logged in users
class ChangeData(View):
-
+
+
# provide the form for the change request
def get(self, request):
+ urlname = 'change_data'
+ service = 'get default data for logged in user'
if not request.user.is_authenticated:
return render(request, 'mustbeloggedin.html')
user = request.user
login(request, user)
# get basic data (firstname, lastname, email)
- (firstname, lastname, email) = self.get_data(user)
+ with get_pool().next() as rpc:
+ (state, firstname, lastname, email) = rpc.getuserdata.get_data(user)
+ # If it throws an error, the errormessage gets put into firstname.. not great naming, but works best this way
+ if state == "error":
+ return render(request, 'error.html', { 'urlname': urlname, 'service': service, 'error': firstname } )
# The template puts the old data as standard in the fields
- return render(request, 'changeuserdata.html', { 'user': user, 'firstname': firstname, 'lastname': lastname, 'email': email } )
+ else:
+ return render(request, 'changeuserdata.html', { 'user': user, 'firstname': firstname, 'lastname': lastname, 'email': email } )
# get the change request
def post(self, request):
@@ -128,20 +133,20 @@ class ChangeData(View):
return render(request, 'error.html', { 'urlname': urlname, 'service': service, 'error': 'Please enter a lastname.' } )
elif email == "":
return render(request, 'error.html', { 'urlname': urlname, 'service': service, 'error': 'Please enter an email.' } )
- elif not email_re.match(email):
+ try:
+ validate_email(email)
+ except ValidationError:
return render(request, 'error.html', { 'urlname': urlname, 'service': service, 'error': 'The supplied email address is invalid.' } )
# Trying to change the data
- if self.change_data(firstname, lastname, email):
+ with get_pool().next() as rpc:
+ result = rpc.changeuserdata.change_data(user, firstname, lastname, email)
+ # Data change worked
+ if result == True:
return render(request, 'changeddata.html', { 'user': user, 'firstname': firstname, 'lastname': lastname, 'email': email } )
- return render(request, 'error.html', { 'urlname': urlname, 'service': service, 'error': 'An unknown error occurred.' } )
+ # Data change did not work, display error
+ else:
+ return render(request, 'error.html', { 'urlname': urlname, 'service': service, 'error': result } )
- # TODO: call nameko to get basic data from user
- def get_data(self, user):
- return ("a", "b", "c")
-
- # TODO: call nameko to change user data and think about return value
- def change_data(self, firstname, lastname, email):
- return True
# Resets the password for a user
# Will need to send a confirmation email to the user and we will need a backend
@@ -205,26 +210,25 @@ class ChangePassword(View):
if password1 != password2:
return render(request, 'error.html', { 'urlname': urlname, 'service': service,
'error': 'Please check if you typed the same password both times for the new password' } )
-
+ with get_pool().next() as rpc:
# Trying to change the password
- if self.change_password(user, oldpassword, password1):
+ result = rpc.changepassword.change_password(user, password1)
+ # Password was changed
+ if result == True:
return render(request, 'changedpassword.html', { 'user': user } )
+ # Password not changed, instead got some kind of error
else:
- return render(request, 'error.html', { 'urlname': urlname, 'service': service, 'error': 'Unknown error while changing the password!' } )
-
-
- # Changes the password for the supplied user
- def change_password(self, user, oldpassword, password):
- #TODO: write nameko function to change a password
- return True
-
+ return render(request, 'error.html', { 'urlname': urlname, 'service': service, 'error': result } )
+# Deletes an account
class DeleteAccount(View):
+ # Show the basic form for deleting an account
def get(self, request):
return render(request, 'deleteaccount.html')
+ # Reads the filled out form
def post(self, request):
# Variables for error page
urlname = 'account_delete'
@@ -242,11 +246,13 @@ class DeleteAccount(View):
return render(request, 'error.html', { 'urlname': urlname, 'service': service, 'error': 'Wrong password for user.' } )
# Try to delete the user
- if self.delete_user(username):
+ with get_pool().next() as rpc:
+ result = rpc.deleteuser.delete_user(user)
+ # User deleted
+ if result == True:
return render(request, 'deleteduser.html', { 'user': username } )
- return render(request, 'error.html', { 'urlname': urlname, 'service': service, 'error': 'Unknown error while trying to delete the user.' } )
+ # User not deleted, got some kind of error
+ else:
+ return render(request, 'error.html', { 'urlname': urlname, 'service': service, 'error': result } )
- def delete_user(self, username):
- #TODO: nameko call to delete the user
- return True
diff --git a/nameko-func.py b/nameko-func.py
index 6a4925b..da1e445 100644
--- a/nameko-func.py
+++ b/nameko-func.py
@@ -1,81 +1,303 @@
from nameko.events import EventDispatcher, event_handler
from nameko.rpc import rpc
from configparser import ConfigParser
-import ldap3
+from ldap3 import Server, ServerPool, Connection, ObjectDef, AttrDef, Reader, Writer
+from datetime import datetime
+# For testing
+from random import randint
+
+# Read the config in the nameko.conf
config = ConfigParser()
config.read('nameko.conf')
+# Sanity check for config
try:
mult_server = int(config['LDAP']['SERVERMULTIPLE'])
+# SERVERMULTIPLE is set to something not a number
except:
exit("[LDAP] SERVERMULTIPLE has to be an integer >= 1")
+# less than one server is not a sensible option
if mult_server < 1:
exit("[LDAP] SERVERMULTIPLE has to be an integer >= 1")
+
+# Function to setup the server or serverpool
+def ldapservers():
+ # Just one server, no need for a pool
+ if mult_server == 1:
+ ldapserver = Server(config['LDAP']['LDAPSERVER1'])
+ return ldapserver
+ # Multiple servers, set up a pool
+ else:
+ ldapserver = ServerPool(None)
+ for x in range(1, (mult_server+1)):
+ ins = Server(config['LDAP']['LDAPSERVER' + str(x)])
+ ldapserver.add(ins)
+ return ldapserver
+
+
+# Since there's no reason why someone in ou=users shouldn't use the service,
+# here's the helper function to check whether an uid is in ou=customers or
+# ou=users
+# returns the full dn
+def user_or_customer(uid):
+ server = ldapservers()
+ conn = Connection(server)
+ if conn.search('ou=customers,dc=ungleich,dc=ch', '(%s)' % uid):
+ return '%s,ou=customers,dc=ungleich,dc=ch' % uid
+ elif conn.search('ou=customers,dc=ungleich,dc=ch', '(%s)' % uid):
+ return '%s,ou=customers,dc=ungleich,dc=ch' % uid
+ else:
+ return False
+
+
+# checks if a user already exists in the LDAP
class UserLookUp(object):
name = "userlookup"
dispatch = EventDispatcher()
@rpc
def lookup(self, user):
+ # Setup the search parameter and connect to LDAP
LDAP_UID = 'uid=%s' % user
- LDAP_USER_SEARCH = LDAP_UID + config['LDAP']['LDAPDATA']
+ server = ldapservers()
+ conn = Connection(server)
+ conn.bind()
+ # Search ou=users and ou=customers
+ if conn.search('ou=customers,dc=ungleich,dc=ch', '(%s)' % LDAP_UID) or conn.search('ou=users,dc=ungleich,dc=ch', '(%s)' % LPAD_UID):
+ # return conn.entries[0] for first search result since we can assume uid is unique
+ self.dispatch('ldap', '%s [Info: UserLookUp] Searched for %s and found it: %s' % (datetime.now(), LDAP_UID, str(conn.entries[0])) )
+ conn.unbind()
+ # return True since the user is already in LDAP
+ return True
+ # User not in LDAP, so just close it down, write the log and return False
+ else:
+ conn.unbind()
+ self.dispatch('ldap', '%s [Info: UserLookUp] Searched for %s and not found it.' % (datetime.now(), LDAP_UID) )
+ return False
+# Create a user in the LDAP. Assumes the checks are already in place for existing users
class CreateUser(object):
name = "createuser"
dispatch = EventDispatcher()
@rpc
def create_user(self, user, password, firstname, lastname, email):
- return "To be done"
-
+ # Creates a user with some basic data
+ server = ldapservers()
+ conn = Connection(server, conf['LDAP']['LDAPMANAGER'], conf['LDAP']['LDAPMANAGERPASSWORD'])
+ if not conn.bind():
+ self.dispatch('ldap', '%s [Error CreateUser] Could not connect to LDAPserver' % datetime.now() )
+ return "Could not connect to LDAP Server."
+ # set objectClasses for the new user
+ obj_new_user = ObjectDef(['inetOrgPerson', 'posixAccount', 'shadowAccount'], conn)
+ w = Writer(conn, obj_new_user)
+ # newly created users get put into ou=customers
+ dn = 'uid=%s,ou=customers,dc=ungleich,dc=ch' % user
+ w.new(dn)
+ # Filling in some of the data
+ # required attributes are sn, cn, homeDirectory, uid (already handled by dn), uidNumber, gidNumber
+ w[0].givenName = firstname
+ w[0].sn = lastname
+ w[0].cn = firstname + " " + lastname
+ w[0].mail = email
+ w[0].userPassword = password
+ w[0].homeDirectory = '/home/%s' % user
+ # TODO: Learn how to get the last uidNumber and what gidNumber to use
+ w[0].uidNumber = randint(1200,50000)
+ w[0].gidNumber = randint(1200,50000)
+ if not w.commit():
+ conn.unbind()
+ self.dispatch('ldap', '%s [Error CreateUser] Could not write new user %s to LDAP DB' % (datetime.now(), dn) )
+ return "Couldn't write data to the LDAP Server."
+ conn.unbind()
+ self.dispatch('ldap', '%s [Info CreateUser] %s created.' % (datetime.now(), dn) )
+ return True
+# Returns some basic data from an user
class GetUserData(object):
name = "getuserdata"
dispatch = EventDispatcher()
@rpc
def get_data(self, user):
- return "To be done"
+ # Setup the search parameter and connect to LDAP
+ LDAP_UID = 'uid=%s' % user
+ server = ldapservers()
+ conn = Connection(server)
+ if not conn.bind():
+ self.dispatch('ldap', '%s [Error GetUserData] Could not connect to LDAP server.' % datetime.now() )
+ return ("error", "Could not connect to LDAP server.", "", "")
+ rdn = user_or_customer(LDAP_UID)
+ if rdn == False:
+ conn.unbind()
+ self.dispatch('ldap', '%s [Info GetUserData] Could not find user %s' % (datetime.now(), LDAP_UID) )
+ return ("error", "Could not find the user.", "", "")
+ obj = ObjectDef(['inetOrgPerson', 'posixAccount', 'shadowAccount'], conn)
+ # The Reader gets the data for the user
+ r = Reader(conn, obj, rdn)
+ r.search()
+ # Since the DN is basically confirmed by user_or_customer() it shouldn't throw an exception, but better check
+ try:
+ x = r[0].sn
+ except:
+ conn.unbind()
+ self.dispatch('ldap', '%s [Error GetUserData] Could not open Reader for %s' % (datetime.now(), rdn) )
+ return ("error", "Could not read data for user.", "", "")
+ # Putting the results into strings and then clean it up a bit if some attribute is not set in LDAP
+ (firstname, lastname, email) = (str(r[0].givenName), str(r[0].sn), str(r[0].mail))
+ if firstname == '[]':
+ firstname = 'No firstname given'
+ if lastname == '[]':
+ lastname = 'No lastname given'
+ if email == '[]':
+ email = 'No email given'
+ conn.unbind()
+ self.dispatch('ldap', '%s [Info GetUserData] Got data for %s Firstname: %s Lastname: %s Email: %s' % (datetime.now(), rdn, firstname, lastname, email) )
+ return ("OK", firstname, lastname, email)
+
+
+# change some (firstname, lastname, email) data for the user
class ChangeUserData(object):
name = "changeuserdata"
dispatch = EventDispatcher()
@rpc
def change_data(self, user, firstname, lastname, email):
- return "To be done"
+ LDAP_UID = 'uid=%s' % user
+ server = ldapservers()
+ # Establish connection with a user who can change the data
+ conn = Connection(server, conf['LDAP']['LDAPMANAGER'], conf['LDAP']['LDAPMANAGERPASSWORD'])
+ if not conn.bind():
+ self.dispatch('ldap', '%s [Error ChangeUserData] Could not connect to LDAP server.' % datetime.now() )
+ return "Could not connect to LDAP server."
+ # get the DN of the user
+ rdn = user_or_customer(LDAP_UID)
+ if rdn == False:
+ conn.unbind()
+ self.dispatch('ldap', '%s [Info ChangeUserData] User with %s not found.' % (datetime.now(), LDAP_UID) )
+ return "Could not find user."
+ # Set up a reader for the user
+ obj = ObjectDef(['inetOrgPerson', 'posixAccount', 'shadowAccount'], conn)
+ r = Reader(conn, obj, rdn)
+ r.search()
+ # Again, user_or_customer() should prevent it from throwing an exception because it's a confirmed user
+ try:
+ x = r[0].sn
+ except:
+ conn.unbind()
+ self.dispatch('ldap', '%s [Error ChangeUserData] Could not open Reader for %s' % (datetime.now(), rdn) )
+ return "Could not open the data of user."
+ # Opens a Writer instance prefilled with the old data
+ # We could check if something has changed, but since the form takes the old data as standard values, let's
+ # just update the relevant attributes
+ w = Writer.from_cursor(r)
+ w[0].sn = lastname
+ w[0].cn = firstname + " " + lastname
+ w[0].givenName = firstname
+ w[0].mail = email
+ # check if the data is written
+ if not w.commit():
+ conn.unbind()
+ self.dispatch('ldap', '%s [Error ChangeUserData] Could not write changes for %s' % (datetime.now(), rdn) )
+ return "Could not write changes for user."
+ conn.unbind()
+ self.dispatch('ldap', '%s [Info ChangeUserData] Changed data for %s Firstname: %s Lastname: %s Email: %s' % (datetime.now(), rdn, firstname, lastname, email) )
+ return True
+# Request a password reset
+# TODO: Set up a system for it
+# Basic idea: send email to customer with a confirmation request, set reply-to for something that handles it,
class PasswordResetRequest(object):
name = "passwordresetrequest"
dispatch = EventDispatcher()
@rpc
def send_request(self, user):
+ # TODO: Find a good system for that
return "To be done"
+# change the password for the user
class ChangePassword(object):
name = "changepassword"
dispatch = EventDispatcher()
@rpc
- def change_password(self, user, oldpassword, newpassword):
- return "To be done"
+ def change_password(self, user, newpassword):
+ LDAP_UID = 'uid=%s'
+ server = ldapservers()
+ conn = Connection(server, conf['LDAP']['LDAPMANAGER'], conf['LDAP']['LDAPMANAGERPASSWORD'])
+ if not conn.bind():
+ self.dispatch('ldap', '%s [Error ChangePassword] Could not connect to LDAP server.' % datetime.now() )
+ return "Could not connect to LDAP server."
+ # check if uid=user is in either ou=customers or ou=users
+ rdn = user_or_customer(LDAP_UID)
+ if rdn == False:
+ conn.unbind()
+ self.dispatch('ldap', '%s [Error ChangePassword] Could not find user %s' % (datetime.now(), LDAP_UID) )
+ return "Could not find the user."
+ # Set up a Reader for the DN
+ obj = ObjectDef(['inetOrgPerson', 'posixAccount', 'shadowAccount'], conn)
+ r = Reader(conn, obj, rdn)
+ r.search()
+ # Shouldn't throw an exception, since the user is confirmed to be there
+ try:
+ x = r[0].sn
+ except:
+ conn.unbind()
+ self.dispatch('ldap', '%s [Error ChangePassword] Could not open Reader for %s' % (datetime.now(), rdn) )
+ return "Could not open the data for the user."
+ # Set up the writer and overwrite the attribute with the new password
+ w = Writer.from_cursor(r)
+ w[0].userPassword = newpassword
+ # Check to see if the change has gone through
+ if not w.commit():
+ conn.unbind()
+ self.dispatch('ldap', '%s [Error ChangePassword] Could not write data for %s' % (datetime.now(), rdn) )
+ return "Could not write data for the user."
+ conn.unbind()
+ self.dispatch('ldap', '%s [Info ChangePassword] Password changed for %s' % (datetime.now(), rdn) )
+ return True
+# Deletes a user from LDAP
class DeleteUser(object):
name = "deleteuser"
dispatch = EventDispatcher()
@rpc
def delete_user(self, user):
- return "To be done"
+ LDAP_UID = user
+ server = ldapservers()
+ conn = Connection(server, conf['LDAP']['LDAPMANAGER'], conf['LDAP']['LDAPMANAGERPASSWORD'])
+ if not conn.bind():
+ self.dispatch('ldap', '%s [Error DeleteUser] Could not connect to LDAP server.' % datetime.now() )
+ return "Could not connect to LDAP server."
+ # again, check whether the uid= is in ou=users or ou=customers
+ dn = user_or_customer(LDAP_UID)
+ if dn == False:
+ conn.unbind()
+ self.dispatch('ldap', '%s [Error DeleteUser] Could not find the user %s' % (datetime.now(), LDAP_UID) )
+ return "Could not find the user."
+ # Check if the delete was successfull
+ if not conn.delete(dn):
+ conn.unbind()
+ self.dispatch('ldap', '%s [Error DeleteUser] Could not delete %s' % (datetime.now(), dn) )
+ return "Could not delete the user."
+ conn.unbind()
+ self.dispatch('ldap', '%s [Info DeleteUser] Deleted %s' % (datetime.now(), dn) )
+ return True
+# the class to log all the dispatches
+# for now everything gets logged into the same logfile, but
+# I don't forsee that much traffic plus with timestamps and the class name
+# in the log should be readable
class Log(object):
name = "log"
ldaplog = config['System']['LOGDIR'] + '/ldap.log'
diff --git a/nameko.conf b/nameko.conf
index f35b263..67c7576 100644
--- a/nameko.conf
+++ b/nameko.conf
@@ -10,4 +10,5 @@ SERVERMULTIPLE = 1
LDAPSERVER1 = localhost
-LDAPDATA = ,ou=customers,dc=foo,dc=bar
+LDAPMANAGER = cn=manager,dc=ungleich,dc=ch
+LDAPMANAGERPASSWORD = foobar
diff --git a/requirements.txt b/requirements.txt
index be5535b..6c3c085 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -2,3 +2,4 @@ django>=2.1.2
django-auth-ldap>=1.7.0
nameko>=2.11.0
ldap3>=2.5.1
+django-nameko>=0.1