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
|
@ -45,6 +45,16 @@ AUTH_LDAP_USER_SEARCH = LDAPSearchUnion(
|
||||||
|
|
||||||
# LDAP config end
|
# 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, ...)
|
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
||||||
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
@ -71,6 +81,7 @@ INSTALLED_APPS = [
|
||||||
'django.contrib.sessions',
|
'django.contrib.sessions',
|
||||||
'django.contrib.messages',
|
'django.contrib.messages',
|
||||||
'django.contrib.staticfiles',
|
'django.contrib.staticfiles',
|
||||||
|
'dal',
|
||||||
]
|
]
|
||||||
|
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
|
|
|
@ -9,6 +9,6 @@
|
||||||
<li> Email: {{email}} </li>
|
<li> Email: {{email}} </li>
|
||||||
</ul>
|
</ul>
|
||||||
<br><br>
|
<br><br>
|
||||||
<form action={% url 'index' %} type="get">
|
<form action={% url 'index' %} method="get">
|
||||||
<input type="submit" value="Back to indexpage">
|
<input type="submit" value="Back to indexpage">
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -2,12 +2,12 @@
|
||||||
|
|
||||||
<h2> Changing the password for {{user}} </h2>
|
<h2> Changing the password for {{user}} </h2>
|
||||||
<br><br>
|
<br><br>
|
||||||
<form action={% url 'index' %} type="get">
|
<form action={% url 'index' %} method="get">
|
||||||
<input type="submit" value="Back to indexpage">
|
<input type="submit" value="Back to indexpage">
|
||||||
</form>
|
</form>
|
||||||
<br><br>
|
<br><br>
|
||||||
To change the password for {{user}}, please supply
|
To change the password for {{user}}, please supply
|
||||||
<form action={% url 'change_password' %} type="post">
|
<form action={% url 'change_password' %} method="post">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<br>The old password:<br>
|
<br>The old password:<br>
|
||||||
<input type="password" name="oldpassword" id="oldpassword">
|
<input type="password" name="oldpassword" id="oldpassword">
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
|
|
||||||
<h2> Changing user data for {{user}} </h2>
|
<h2> Changing user data for {{user}} </h2>
|
||||||
<br><br>
|
<br><br>
|
||||||
<form action={% url 'index' %} type="get">
|
<form action={% url 'index' %} method="get">
|
||||||
<input type="submit" value="Back to indexpage">
|
<input type="submit" value="Back to indexpage">
|
||||||
</form>
|
</form>
|
||||||
<br><br>
|
<br><br>
|
||||||
<form action={% url 'change_data' %} type="post">
|
<form action={% url 'change_data' %} method="post">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<br>Firstname:<br>
|
<br>Firstname:<br>
|
||||||
<input type="text" name="firstname" id="firstname" value="{{firstname}}">
|
<input type="text" name="firstname" id="firstname" value="{{firstname}}">
|
||||||
|
|
|
@ -2,12 +2,12 @@
|
||||||
|
|
||||||
<h2> Deleting an Account </h2>
|
<h2> Deleting an Account </h2>
|
||||||
<br><br>
|
<br><br>
|
||||||
<form action={% url 'index' %} type="get">
|
<form action={% url 'index' %} method="get">
|
||||||
<input type="submit" value="Back to indexpage">
|
<input type="submit" value="Back to indexpage">
|
||||||
</form>
|
</form>
|
||||||
<br><br>
|
<br><br>
|
||||||
To delete an account, please type the username and password below:
|
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>
|
<br><br>Username:<br>
|
||||||
<input type="text" name="username" id="username">
|
<input type="text" name="username" id="username">
|
||||||
<br><br>Password:<br>
|
<br><br>Password:<br>
|
||||||
|
|
|
@ -2,6 +2,6 @@
|
||||||
|
|
||||||
<h2> The user {{user}} was deleted from our system. </h2>
|
<h2> The user {{user}} was deleted from our system. </h2>
|
||||||
<br>
|
<br>
|
||||||
<form action={% url 'index' %} type="get">
|
<form action={% url 'index' %} method="get">
|
||||||
<input type="submit" value="Back to indexpage">
|
<input type="submit" value="Back to indexpage">
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -6,10 +6,10 @@ While trying to {{service}}, an error was encountered: {{error}}
|
||||||
<br><br>
|
<br><br>
|
||||||
You can try to:
|
You can try to:
|
||||||
<br>
|
<br>
|
||||||
<form action={% url urlname %} type="get">
|
<form action={% url urlname %} method="get">
|
||||||
<input type="submit" value="Go back and try again">
|
<input type="submit" value="Go back and try again">
|
||||||
</form>
|
</form>
|
||||||
<br>or<br>
|
<br>or<br>
|
||||||
<form action={% url 'index' %} type="get">
|
<form action={% url 'index' %} method="get">
|
||||||
<input type="submit" value="Go to the indexpage">
|
<input type="submit" value="Go to the indexpage">
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
<h2> Welcome to the ungleich user service </h2>
|
<h2> Welcome to the ungleich user service </h2>
|
||||||
<br><br>
|
<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:
|
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>
|
<br><br>Username:<br>
|
||||||
<input type="text" name="username" id="username">
|
<input type="text" name="username" id="username">
|
||||||
<br><br>Password:<br>
|
<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">
|
<input type="submit" value="Submit">
|
||||||
</form>
|
</form>
|
||||||
<br><br>If you have an account, but forgot your password, please visit our password reset page:
|
<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">
|
<input type="submit" value="Password reset">
|
||||||
</form>
|
</form>
|
||||||
<br><br>If you don't have an account, please register yourself with us:
|
<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">
|
<input type="submit" value="Register an user">
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
|
|
||||||
<h2> Sorry, but your login has failed </h2>
|
<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.
|
<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">
|
<input type="submit" value="Register an user">
|
||||||
</form>
|
</form>
|
||||||
<br><br>
|
<br><br>
|
||||||
<form action={% url 'index' %} type="get">
|
<form action={% url 'index' %} method="get">
|
||||||
<input type="submit" value="Back to indexpage">
|
<input type="submit" value="Back to indexpage">
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -2,6 +2,6 @@
|
||||||
|
|
||||||
<h2> You must be logged in to access this page </h2>
|
<h2> You must be logged in to access this page </h2>
|
||||||
<br><br>
|
<br><br>
|
||||||
<form action={% url 'index' %} type="get">
|
<form action={% url 'index' %} method="get">
|
||||||
<input type="submit" value="Back to indexpage">
|
<input type="submit" value="Back to indexpage">
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -2,13 +2,13 @@
|
||||||
|
|
||||||
<h2> Register an user at ungleich </h2>
|
<h2> Register an user at ungleich </h2>
|
||||||
<br><br>
|
<br><br>
|
||||||
<form action={% url 'index' %} type="get">
|
<form action={% url 'index' %} method="get">
|
||||||
<input type="submit" value="Back to indexpage">
|
<input type="submit" value="Back to indexpage">
|
||||||
</form>
|
</form>
|
||||||
<br><br>
|
<br><br>
|
||||||
To register yourself an user, please fill out the fields below:
|
To register yourself an user, please fill out the fields below:
|
||||||
<br>
|
<br>
|
||||||
<form action={% url 'register' %} type="post">
|
<form action={% url 'register' %} method="post">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<br>Username (alphanumeric):<br>
|
<br>Username (alphanumeric):<br>
|
||||||
<input type="text" name="username" id="username">
|
<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
|
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.
|
temporary password. Please remember to change it immediately after logging in.
|
||||||
<br>
|
<br>
|
||||||
<form action={% url 'reset_password' %} type="post">
|
<form action={% url 'reset_password' %} method="post">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
Username:<br>
|
Username:<br>
|
||||||
<input type="text" name="user" id="user">
|
<input type="text" name="user" id="user">
|
||||||
|
|
|
@ -4,6 +4,6 @@
|
||||||
<br><br>
|
<br><br>
|
||||||
You will shortly get the confirmation email at {{email}} to confirm that you wish to reset the password for {{user}}.
|
You will shortly get the confirmation email at {{email}} to confirm that you wish to reset the password for {{user}}.
|
||||||
<br><br>
|
<br><br>
|
||||||
<form action={% url 'index' %} type="get">
|
<form action={% url 'index' %} method="get">
|
||||||
<input type="submit" value="Back to indexpage">
|
<input type="submit" value="Back to indexpage">
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -4,18 +4,18 @@
|
||||||
<br><br>
|
<br><br>
|
||||||
You have the following options:
|
You have the following options:
|
||||||
<br>
|
<br>
|
||||||
<form action={% url 'change_data' %} type="get">
|
<form action={% url 'change_data' %} method="get">
|
||||||
<input type="submit" value="Change your userdata">
|
<input type="submit" value="Change your userdata">
|
||||||
</form>
|
</form>
|
||||||
<br>
|
<br>
|
||||||
<form action={% url 'change_password' %} type="get">
|
<form action={% url 'change_password' %} method="get">
|
||||||
<input type="submit" value="Change your password">
|
<input type="submit" value="Change your password">
|
||||||
</form>
|
</form>
|
||||||
<br>
|
<br>
|
||||||
<form action={% url 'reset_password' %} type="get">
|
<form action={% url 'reset_password' %} method="get">
|
||||||
<input type="submit" value="Reset your password">
|
<input type="submit" value="Reset your password">
|
||||||
</form>
|
</form>
|
||||||
<br>
|
<br>
|
||||||
<form action={% url 'account_delete' %} type="get">
|
<form action={% url 'account_delete' %} method="get">
|
||||||
<input type="submit" value="Delete your account">
|
<input type="submit" value="Delete your account">
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -18,14 +18,14 @@ from django.urls import path
|
||||||
from django.conf.urls import url
|
from django.conf.urls import url
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
|
||||||
from .views import Register, ChangeData, ResetPassword, DeleteAccount, Index
|
from .views import Register, ChangeData, ChangePassword, ResetPassword, DeleteAccount, Index
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('admin/', admin.site.urls),
|
# path('admin/', admin.site.urls),
|
||||||
path('register/', Register.as_view(), name="register"),
|
path('register/', Register.as_view(), name="register"),
|
||||||
path('changedata/', ChangeData.as_view(), name="change_data"),
|
path('changedata/', ChangeData.as_view(), name="change_data"),
|
||||||
path('resetpassword/', ResetPassword.as_view(), name="reset_password"),
|
path('resetpassword/', ResetPassword.as_view(), name="reset_password"),
|
||||||
path('changepassword/', ChangePassword.as_view(), name="change_password"),
|
path('changepassword/', ChangePassword.as_view(), name="change_password"),
|
||||||
path('deleteaccount/', DeleteAccount.as_view(), name="account_delete"),
|
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 import authenticate, login
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from django.http import HttpResponse, HttpResponseRedirect
|
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.urls import reverse_lazy
|
||||||
|
from django_nameko import get_pool
|
||||||
|
|
||||||
# Check to see if the username is already taken
|
# Check to see if the username is already taken
|
||||||
# Helper function, not to be set up as a view
|
# Helper function, not to be set up as a view
|
||||||
# First checks the DB, since ldap parks users there
|
# Check the LDAP if the user exists
|
||||||
# After that, check LDAP directly if the user just never
|
|
||||||
# logged in
|
|
||||||
def check_user_exists(username):
|
def check_user_exists(username):
|
||||||
if User.objects.filter(username=username).exists():
|
with get_pool().next() as rpc:
|
||||||
return True
|
return rpc.userlookup.lookup(username)
|
||||||
# TODO: Needs to look up the LDAP
|
|
||||||
else return False
|
|
||||||
|
|
||||||
|
|
||||||
# The index page
|
# The index page
|
||||||
# If there's a session open, it will give the user the options he/she/it can do, if not,
|
# 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
|
# check if the supplied passwords match
|
||||||
if password1 != password2:
|
if password1 != password2:
|
||||||
return render(request, 'registererror.html', { 'urlname': urlname, 'service': service,
|
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')
|
email = request.POST.get('email')
|
||||||
# Is the emailaddress valid?
|
# 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.' } )
|
return render(request, 'registererror.html', { 'urlname': urlname, 'service': service, 'error': 'The supplied email address is invalid.' } )
|
||||||
|
|
||||||
firstname = request.POST.get('firstname')
|
firstname = request.POST.get('firstname')
|
||||||
lastname = request.POST.get('lastname')
|
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.' } )
|
return render(request, 'registererror.html', { 'urlname': urlname, 'service': service, 'error': 'Please enter your firstname and lastname.' } )
|
||||||
# throw it to nameko to create the user
|
# throw it to nameko to create the user
|
||||||
if self.create_user(username, password1, firstname, lastname, email):
|
with get_pool().next() as rpc:
|
||||||
return render(request, 'usercreated.html', { 'user': username } )
|
result = rpc.createuser.create_user(username, password1, firstname, lastname, email)
|
||||||
return render(request, 'error.html', { 'urlname': urlname, 'service': service, 'error': 'Unknown error while creating the user.' } )
|
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
|
# Change user data for logged in users
|
||||||
|
|
||||||
class ChangeData(View):
|
class ChangeData(View):
|
||||||
|
|
||||||
|
|
||||||
# provide the form for the change request
|
# provide the form for the change request
|
||||||
def get(self, request):
|
def get(self, request):
|
||||||
|
urlname = 'change_data'
|
||||||
|
service = 'get default data for logged in user'
|
||||||
if not request.user.is_authenticated:
|
if not request.user.is_authenticated:
|
||||||
return render(request, 'mustbeloggedin.html')
|
return render(request, 'mustbeloggedin.html')
|
||||||
user = request.user
|
user = request.user
|
||||||
login(request, user)
|
login(request, user)
|
||||||
# get basic data (firstname, lastname, email)
|
# 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
|
# 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
|
# get the change request
|
||||||
def post(self, 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.' } )
|
return render(request, 'error.html', { 'urlname': urlname, 'service': service, 'error': 'Please enter a lastname.' } )
|
||||||
elif email == "":
|
elif email == "":
|
||||||
return render(request, 'error.html', { 'urlname': urlname, 'service': service, 'error': 'Please enter an 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.' } )
|
return render(request, 'error.html', { 'urlname': urlname, 'service': service, 'error': 'The supplied email address is invalid.' } )
|
||||||
# Trying to change the data
|
# 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, '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
|
# Resets the password for a user
|
||||||
# Will need to send a confirmation email to the user and we will need a backend
|
# 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:
|
if password1 != password2:
|
||||||
return render(request, 'error.html', { 'urlname': urlname, 'service': service,
|
return render(request, 'error.html', { 'urlname': urlname, 'service': service,
|
||||||
'error': 'Please check if you typed the same password both times for the new password' } )
|
'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
|
# 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 } )
|
return render(request, 'changedpassword.html', { 'user': user } )
|
||||||
|
# Password not changed, instead got some kind of error
|
||||||
else:
|
else:
|
||||||
return render(request, 'error.html', { 'urlname': urlname, 'service': service, 'error': 'Unknown error while changing the password!' } )
|
return render(request, 'error.html', { 'urlname': urlname, 'service': service, 'error': result } )
|
||||||
|
|
||||||
|
|
||||||
# Changes the password for the supplied user
|
|
||||||
def change_password(self, user, oldpassword, password):
|
|
||||||
#TODO: write nameko function to change a password
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Deletes an account
|
||||||
class DeleteAccount(View):
|
class DeleteAccount(View):
|
||||||
|
|
||||||
|
# Show the basic form for deleting an account
|
||||||
def get(self, request):
|
def get(self, request):
|
||||||
return render(request, 'deleteaccount.html')
|
return render(request, 'deleteaccount.html')
|
||||||
|
|
||||||
|
# Reads the filled out form
|
||||||
def post(self, request):
|
def post(self, request):
|
||||||
# Variables for error page
|
# Variables for error page
|
||||||
urlname = 'account_delete'
|
urlname = 'account_delete'
|
||||||
|
@ -242,11 +246,13 @@ class DeleteAccount(View):
|
||||||
return render(request, 'error.html', { 'urlname': urlname, 'service': service, 'error': 'Wrong password for user.' } )
|
return render(request, 'error.html', { 'urlname': urlname, 'service': service, 'error': 'Wrong password for user.' } )
|
||||||
|
|
||||||
# Try to delete the 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, '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.events import EventDispatcher, event_handler
|
||||||
from nameko.rpc import rpc
|
from nameko.rpc import rpc
|
||||||
from configparser import ConfigParser
|
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 = ConfigParser()
|
||||||
config.read('nameko.conf')
|
config.read('nameko.conf')
|
||||||
|
|
||||||
|
# Sanity check for config
|
||||||
try:
|
try:
|
||||||
mult_server = int(config['LDAP']['SERVERMULTIPLE'])
|
mult_server = int(config['LDAP']['SERVERMULTIPLE'])
|
||||||
|
# SERVERMULTIPLE is set to something not a number
|
||||||
except:
|
except:
|
||||||
exit("[LDAP] SERVERMULTIPLE has to be an integer >= 1")
|
exit("[LDAP] SERVERMULTIPLE has to be an integer >= 1")
|
||||||
|
# less than one server is not a sensible option
|
||||||
if mult_server < 1:
|
if mult_server < 1:
|
||||||
exit("[LDAP] SERVERMULTIPLE has to be an integer >= 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):
|
class UserLookUp(object):
|
||||||
name = "userlookup"
|
name = "userlookup"
|
||||||
dispatch = EventDispatcher()
|
dispatch = EventDispatcher()
|
||||||
|
|
||||||
@rpc
|
@rpc
|
||||||
def lookup(self, user):
|
def lookup(self, user):
|
||||||
|
# Setup the search parameter and connect to LDAP
|
||||||
LDAP_UID = 'uid=%s' % user
|
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):
|
class CreateUser(object):
|
||||||
name = "createuser"
|
name = "createuser"
|
||||||
dispatch = EventDispatcher()
|
dispatch = EventDispatcher()
|
||||||
|
|
||||||
@rpc
|
@rpc
|
||||||
def create_user(self, user, password, firstname, lastname, email):
|
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):
|
class GetUserData(object):
|
||||||
name = "getuserdata"
|
name = "getuserdata"
|
||||||
dispatch = EventDispatcher()
|
dispatch = EventDispatcher()
|
||||||
|
|
||||||
@rpc
|
@rpc
|
||||||
def get_data(self, user):
|
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):
|
class ChangeUserData(object):
|
||||||
name = "changeuserdata"
|
name = "changeuserdata"
|
||||||
dispatch = EventDispatcher()
|
dispatch = EventDispatcher()
|
||||||
|
|
||||||
@rpc
|
@rpc
|
||||||
def change_data(self, user, firstname, lastname, email):
|
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):
|
class PasswordResetRequest(object):
|
||||||
name = "passwordresetrequest"
|
name = "passwordresetrequest"
|
||||||
dispatch = EventDispatcher()
|
dispatch = EventDispatcher()
|
||||||
|
|
||||||
@rpc
|
@rpc
|
||||||
def send_request(self, user):
|
def send_request(self, user):
|
||||||
|
# TODO: Find a good system for that
|
||||||
return "To be done"
|
return "To be done"
|
||||||
|
|
||||||
|
|
||||||
|
# change the password for the user
|
||||||
class ChangePassword(object):
|
class ChangePassword(object):
|
||||||
name = "changepassword"
|
name = "changepassword"
|
||||||
dispatch = EventDispatcher()
|
dispatch = EventDispatcher()
|
||||||
|
|
||||||
@rpc
|
@rpc
|
||||||
def change_password(self, user, oldpassword, newpassword):
|
def change_password(self, user, newpassword):
|
||||||
return "To be done"
|
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):
|
class DeleteUser(object):
|
||||||
name = "deleteuser"
|
name = "deleteuser"
|
||||||
dispatch = EventDispatcher()
|
dispatch = EventDispatcher()
|
||||||
|
|
||||||
@rpc
|
@rpc
|
||||||
def delete_user(self, user):
|
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):
|
class Log(object):
|
||||||
name = "log"
|
name = "log"
|
||||||
ldaplog = config['System']['LOGDIR'] + '/ldap.log'
|
ldaplog = config['System']['LOGDIR'] + '/ldap.log'
|
||||||
|
|
|
@ -10,4 +10,5 @@ SERVERMULTIPLE = 1
|
||||||
|
|
||||||
LDAPSERVER1 = localhost
|
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
|
django-auth-ldap>=1.7.0
|
||||||
nameko>=2.11.0
|
nameko>=2.11.0
|
||||||
ldap3>=2.5.1
|
ldap3>=2.5.1
|
||||||
|
django-nameko>=0.1
|
||||||
|
|
Loading…
Reference in a new issue