Fixed typos, especially the wrong attribute in <form>
This commit is contained in:
		
					parent
					
						
							
								06249d530d
							
						
					
				
			
			
				commit
				
					
						2b566aeb8e
					
				
			
		
					 19 changed files with 327 additions and 85 deletions
				
			
		dal/dal
settings.py
nameko-func.pynameko.confrequirements.txttemplates
changeddata.htmlchangepassword.htmlchangeuserdata.htmldeleteaccount.htmldeleteduser.htmlerror.htmllanding.htmlloginfailed.htmlmustbeloggedin.htmlregisteruser.htmlresetpassword.htmlsend_resetrequest.htmluseroptions.html
urls.pyviews.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 = [ | ||||
|  |  | |||
|  | @ -9,6 +9,6 @@ | |||
| 	<li> Email: {{email}} </li> | ||||
| </ul> | ||||
| <br><br> | ||||
| <form action={% url 'index' %} type="get"> | ||||
| <form action={% url 'index' %} method="get"> | ||||
| 	<input type="submit" value="Back to indexpage"> | ||||
| </form> | ||||
|  |  | |||
|  | @ -2,12 +2,12 @@ | |||
| 
 | ||||
| <h2> Changing the password for {{user}} </h2> | ||||
| <br><br> | ||||
| <form action={% url 'index' %} type="get"> | ||||
| <form action={% url 'index' %} method="get"> | ||||
| 	<input type="submit" value="Back to indexpage"> | ||||
| </form> | ||||
| <br><br> | ||||
| To change the password for {{user}}, please supply  | ||||
| <form action={% url 'change_password' %} type="post"> | ||||
| <form action={% url 'change_password' %} method="post"> | ||||
| 	{% csrf_token %} | ||||
| 	<br>The old password:<br>   | ||||
| 	<input type="password" name="oldpassword" id="oldpassword"> | ||||
|  |  | |||
|  | @ -2,11 +2,11 @@ | |||
| 
 | ||||
| <h2> Changing user data for {{user}} </h2> | ||||
| <br><br> | ||||
| <form action={% url 'index' %} type="get"> | ||||
| <form action={% url 'index' %} method="get"> | ||||
| 	<input type="submit" value="Back to indexpage"> | ||||
| </form> | ||||
| <br><br> | ||||
| <form action={% url 'change_data' %} type="post"> | ||||
| <form action={% url 'change_data' %} method="post"> | ||||
| 	{% csrf_token %} | ||||
| 	<br>Firstname:<br> | ||||
| 	<input type="text" name="firstname" id="firstname" value="{{firstname}}"> | ||||
|  |  | |||
|  | @ -2,12 +2,12 @@ | |||
| 
 | ||||
| <h2> Deleting an Account </h2> | ||||
| <br><br> | ||||
| <form action={% url 'index' %} type="get"> | ||||
| <form action={% url 'index' %} method="get"> | ||||
| 	<input type="submit" value="Back to indexpage"> | ||||
| </form> | ||||
| <br><br> | ||||
| To delete an account, please type the username and password below: | ||||
| <form action={% url 'account_delete' %} type="post"> | ||||
| <form action={% url 'account_delete' %} method="post"> | ||||
| 	<br><br>Username:<br> | ||||
| 	<input type="text" name="username" id="username"> | ||||
| 	<br><br>Password:<br> | ||||
|  |  | |||
|  | @ -2,6 +2,6 @@ | |||
| 
 | ||||
| <h2> The user {{user}} was deleted from our system. </h2> | ||||
| <br> | ||||
| <form action={% url 'index' %} type="get"> | ||||
| <form action={% url 'index' %} method="get"> | ||||
| 	<input type="submit" value="Back to indexpage"> | ||||
| </form> | ||||
|  |  | |||
|  | @ -6,10 +6,10 @@ While trying to {{service}}, an error was encountered: {{error}} | |||
| <br><br> | ||||
| You can try to: | ||||
| <br> | ||||
| <form action={% url urlname %} type="get"> | ||||
| <form action={% url urlname %} method="get"> | ||||
| 	<input type="submit" value="Go back and try again"> | ||||
| </form> | ||||
| <br>or<br> | ||||
| <form action={% url 'index' %} type="get"> | ||||
| <form action={% url 'index' %} method="get"> | ||||
| 	<input type="submit" value="Go to the indexpage"> | ||||
| </form> | ||||
|  |  | |||
|  | @ -3,7 +3,8 @@ | |||
| <h2> Welcome to the ungleich user service </h2> | ||||
| <br><br> | ||||
| If you want to use the user service, you will need an account on our system. If you already have one, please login below: | ||||
| <form action={% url 'index' %} type="post"> | ||||
| <form action={% url 'index' %} method="post"> | ||||
| 	{% csrf_token %} | ||||
| 	<br><br>Username:<br> | ||||
| 	<input type="text" name="username" id="username"> | ||||
| 	<br><br>Password:<br> | ||||
|  | @ -12,10 +13,10 @@ If you want to use the user service, you will need an account on our system. If | |||
| 	<input type="submit" value="Submit"> | ||||
| </form> | ||||
| <br><br>If you have an account, but forgot your password, please visit our password reset page: | ||||
| <form action={% url 'reset_password' %} type="get"> | ||||
| <form action={% url 'reset_password' %} method="get"> | ||||
| 	<input type="submit" value="Password reset"> | ||||
| </form> | ||||
| <br><br>If you don't have an account, please register yourself with us: | ||||
| <form action={% url 'register' %} type="get"> | ||||
| <form action={% url 'register' %} method="get"> | ||||
| 	<input type="submit" value="Register an user"> | ||||
| </form> | ||||
|  |  | |||
|  | @ -2,10 +2,10 @@ | |||
| 
 | ||||
| <h2> Sorry, but your login has failed </h2> | ||||
| <br><br>This service runs for our LDAP users, so maybe you don't already have an LDAP account with us? If so, please register one. | ||||
| <form action={% url 'register' %} type="get"> | ||||
| <form action={% url 'register' %} method="get"> | ||||
| 	<input type="submit" value="Register an user"> | ||||
| </form> | ||||
| <br><br> | ||||
| <form action={% url 'index' %} type="get"> | ||||
| <form action={% url 'index' %} method="get"> | ||||
| 	<input type="submit" value="Back to indexpage"> | ||||
| </form> | ||||
|  |  | |||
|  | @ -2,6 +2,6 @@ | |||
| 
 | ||||
| <h2> You must be logged in to access this page </h2> | ||||
| <br><br> | ||||
| <form action={% url 'index' %} type="get"> | ||||
| <form action={% url 'index' %} method="get"> | ||||
| 	<input type="submit" value="Back to indexpage"> | ||||
| </form> | ||||
|  |  | |||
|  | @ -2,13 +2,13 @@ | |||
| 
 | ||||
| <h2> Register an user at ungleich </h2> | ||||
| <br><br> | ||||
| <form action={% url 'index' %} type="get"> | ||||
| <form action={% url 'index' %} method="get"> | ||||
| 	<input type="submit" value="Back to indexpage"> | ||||
| </form> | ||||
| <br><br> | ||||
| To register yourself an user, please fill out the fields below: | ||||
| <br> | ||||
| <form action={% url 'register' %} type="post"> | ||||
| <form action={% url 'register' %} method="post"> | ||||
| 	{% csrf_token %} | ||||
| 	<br>Username (alphanumeric):<br> | ||||
| 	<input type="text" name="username" id="username"> | ||||
|  |  | |||
|  | @ -5,7 +5,7 @@ | |||
| To reset your password, please enter your username below. You will get an email asking you to confirm this and after confirmation an email with your | ||||
| temporary password. Please remember to change it immediately after logging in. | ||||
| <br> | ||||
| <form action={% url 'reset_password' %} type="post"> | ||||
| <form action={% url 'reset_password' %} method="post"> | ||||
| 	{% csrf_token %} | ||||
| 	Username:<br> | ||||
| 	<input type="text" name="user" id="user"> | ||||
|  |  | |||
|  | @ -4,6 +4,6 @@ | |||
| <br><br> | ||||
| You will shortly get the confirmation email at {{email}} to confirm that you wish to reset the password for {{user}}. | ||||
| <br><br> | ||||
| <form action={% url 'index' %} type="get"> | ||||
| <form action={% url 'index' %} method="get"> | ||||
| 	<input type="submit" value="Back to indexpage"> | ||||
| </form> | ||||
|  |  | |||
|  | @ -4,18 +4,18 @@ | |||
| <br><br> | ||||
| You have the following options: | ||||
| <br> | ||||
| <form action={% url 'change_data' %} type="get"> | ||||
| <form action={% url 'change_data' %} method="get"> | ||||
| 	<input type="submit" value="Change your userdata"> | ||||
| </form> | ||||
| <br> | ||||
| <form action={% url 'change_password' %} type="get"> | ||||
| <form action={% url 'change_password' %} method="get"> | ||||
| 	<input type="submit" value="Change your password"> | ||||
| </form> | ||||
| <br> | ||||
| <form action={% url 'reset_password' %} type="get"> | ||||
| <form action={% url 'reset_password' %} method="get"> | ||||
| 	<input type="submit" value="Reset your password"> | ||||
| </form> | ||||
| <br> | ||||
| <form action={% url 'account_delete' %} type="get"> | ||||
| <form action={% url 'account_delete' %} method="get"> | ||||
| 	<input type="submit" value="Delete your account"> | ||||
| </form> | ||||
|  |  | |||
|  | @ -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"), | ||||
| ] | ||||
|  |  | |||
							
								
								
									
										102
									
								
								dal/dal/views.py
									
										
									
									
									
								
							
							
						
						
									
										102
									
								
								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 | ||||
|  |  | |||
							
								
								
									
										240
									
								
								nameko-func.py
									
										
									
									
									
								
							
							
						
						
									
										240
									
								
								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' | ||||
|  |  | |||
|  | @ -10,4 +10,5 @@ SERVERMULTIPLE = 1 | |||
| 
 | ||||
| LDAPSERVER1 = localhost | ||||
| 
 | ||||
| LDAPDATA = ,ou=customers,dc=foo,dc=bar | ||||
| LDAPMANAGER = cn=manager,dc=ungleich,dc=ch | ||||
| LDAPMANAGERPASSWORD = foobar | ||||
|  |  | |||
|  | @ -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 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue