ungleich-user/dal/views.py

695 lines
28 KiB
Python
Raw Normal View History

2019-01-26 13:02:37 +00:00
# Imports from django
2018-10-09 17:49:47 +00:00
from django.shortcuts import render
2019-02-19 22:16:05 +00:00
from django.views.generic import View, FormView
from django.contrib.auth import authenticate, login, logout
2019-04-23 05:19:45 +00:00
from django.contrib.auth.models import User
2019-02-24 19:16:10 +00:00
from django.http import HttpResponse
from django.core.validators import validate_email, ValidationError
2018-10-09 17:49:47 +00:00
from django.urls import reverse_lazy
2018-10-15 15:52:15 +00:00
from django.contrib.auth.tokens import PasswordResetTokenGenerator
from django.core.mail import EmailMessage
from django.views.decorators.cache import cache_control
2019-04-23 05:19:45 +00:00
from rest_framework.views import APIView
from rest_framework.response import Response
from .models import ResetToken
2019-02-19 22:16:05 +00:00
from .forms import LoginForm
2019-02-23 20:29:33 +00:00
from .ungleich_ldap import LdapManager
from decouple import config, Csv
from pyotp import TOTP
import logging
logger = logging.getLogger(__name__)
# Imports for the extra stuff not in django
2019-01-26 13:02:37 +00:00
2018-10-15 15:52:15 +00:00
from base64 import b64encode, b64decode
from datetime import datetime
2019-01-26 13:02:37 +00:00
from random import choice, randint
import string
import requests
import json
2018-11-07 12:08:46 +00:00
2019-01-26 16:46:06 +00:00
from django.conf import settings
from django.contrib.auth.mixins import LoginRequiredMixin
2018-10-09 17:49:47 +00:00
2019-05-26 20:15:07 +00:00
admin_seed = config('ADMIN_SEED')
admin_name = config('ADMIN_NAME')
admin_realm = config('ADMIN_REALM')
user_realm = config('USER_REALM')
otp_url = config('OTPSERVER')
2019-05-02 21:29:01 +00:00
def activate_account_link(base_url, user, pwd, firstname, lastname, email, epochutc):
tokengen = PasswordResetTokenGenerator()
pseudouser = PseudoUser()
token = tokengen.make_token(pseudouser)
buser = bytes(user, 'utf-8')
bpwd = bytes(pwd, 'utf-8')
bfirstname = bytes(firstname, 'utf-8')
blasttname = bytes(lastname, 'utf-8')
bemail = bytes(email, 'utf-8')
userpart = b64encode(buser)
pwdpart = b64encode(bpwd)
fnpart = b64encode(bfirstname)
lnpart = b64encode(blasttname)
mailpart = b64encode(bemail)
# create entry into the database
newdbentry = ResetToken(user=user, token=token, creation=epochutc)
newdbentry.save()
# set up the link
2019-05-02 21:36:31 +00:00
link = "{base_url}/activate/{user}/{pwd}/{fn}/{ln}/{mail}/{token}/".format(
2019-05-02 21:29:01 +00:00
base_url=base_url, user=userpart.decode('utf-8'),
pwd=pwdpart.decode('utf-8'),
fn=fnpart.decode('utf-8'),
ln=lnpart.decode('utf-8'),
mail=mailpart.decode('utf-8'),
token=token
)
return link
def clean_db():
"""Revoves outdated tokens"""
# cutoff time is set to 24h hours
# using utcnow() to have no headache with timezones
cutoff = int(datetime.utcnow().timestamp()) - (24*60*60)
# Get all tokens older than 24 hours
oldtokens = ResetToken.objects.all().filter(creation__lt=cutoff)
for token in oldtokens:
# delete all tokens older than 24 hours
token.delete()
return True
2019-02-19 22:16:05 +00:00
class Index(FormView):
template_name = "landing.html"
form_class = LoginForm
2019-02-23 08:20:58 +00:00
success_url = 'useroptions.html'
def form_valid(self, form):
username = form.cleaned_data.get('username')
2019-02-23 08:20:58 +00:00
password = form.cleaned_data.get('password')
user = authenticate(username=username, password=password)
2019-02-23 08:20:58 +00:00
if user is not None:
login(self.request, user)
return render(self.request, 'useroptions.html', { 'user': user } )
return render(self.request, 'loginfailed.html')
2018-10-09 17:49:47 +00:00
@cache_control(no_cache=True, must_revalidate=True, no_store=True)
def get(self, request, *args, **kwargs):
if self.request.user.is_authenticated:
return render(self.request, 'useroptions.html',
{ 'user': self.request.user.username } )
return super(Index, self).get(request, *args, **kwargs)
2018-10-09 17:49:47 +00:00
class Register(View):
def get(self, request):
return render(request, 'registeruser.html')
# Someone filled out the register page, do some basic checks and throw it at nameko
def post(self, request):
service = 'register an user'
2018-10-09 17:49:47 +00:00
urlname = 'register'
username = request.POST.get('username')
2019-01-26 16:46:06 +00:00
2018-10-14 16:17:59 +00:00
if username == "" or not username:
return render(request, 'error.html', { 'urlname': urlname, 'service': service, 'error': 'Please supply a username.' } )
2019-01-26 14:19:58 +00:00
2018-10-09 17:49:47 +00:00
password1 = request.POST.get('password1')
password2 = request.POST.get('password2')
if password1 != password2:
2019-01-26 14:19:58 +00:00
return render(request, 'error.html', { 'urlname': urlname,
'service': service,
2019-01-26 16:46:06 +00:00
'error': "Passwords don't match." } )
2018-10-23 16:13:25 +00:00
2018-10-09 17:49:47 +00:00
email = request.POST.get('email')
try:
validate_email(email)
except ValidationError:
2019-01-26 16:46:06 +00:00
return render(request, 'error.html', { 'urlname': urlname,
'service': service,
'error': 'The supplied email address is invalid.' } )
2018-10-09 17:49:47 +00:00
firstname = request.POST.get('firstname')
lastname = request.POST.get('lastname')
2019-01-26 16:46:06 +00:00
if not firstname or not lastname:
return render(request, 'error.html', { 'urlname': urlname,
'service': service,
'error': 'Please enter your firstname and lastname.' } )
2018-10-09 17:49:47 +00:00
2019-01-26 14:19:58 +00:00
# so nothing strange happens if there are escapable chars
pwd = r'%s' % password1
2018-10-09 17:49:47 +00:00
2019-01-26 14:19:58 +00:00
try:
2019-05-02 21:29:01 +00:00
creationtime = int(datetime.utcnow().timestamp())
base_url = "{0}://{1}".format(self.request.scheme,
self.request.get_host())
link = activate_account_link(base_url, username, pwd, firstname, lastname, email, creationtime)
email_from = settings.EMAIL_FROM_ADDRESS
to = ['%s <%s>' % (username, email)]
subject = 'Activate your ungleich account'.format(firstname)
body = 'You can activate your ungleich account account by clicking <a href="{link}">here</a>.' \
' You can also copy and paste the following link into the address bar of your browser and follow' \
' the link in order to activate your account.\n\n{link}'.format(link=link)
# Build the email
mail = EmailMessage(
subject=subject,
body=body,
from_email=email_from,
to=to
2019-02-23 20:29:33 +00:00
)
2019-05-02 21:29:01 +00:00
mail.send()
2019-01-26 14:19:58 +00:00
except Exception as e:
return render(request, 'error.html', { 'urlname': urlname,
'service': service,
'error': e } )
2019-05-02 21:29:01 +00:00
return render(request, 'confirm_email.html')
class ChangeData(LoginRequiredMixin, View):
login_url = reverse_lazy('login_index')
2018-10-09 17:49:47 +00:00
# provide the form for the change request
def get(self, request):
urlname = 'change_data'
service = 'get default data for logged in user'
2019-02-24 21:23:43 +00:00
user = request.user
ldap_manager = LdapManager()
user_exists, entries = ldap_manager.check_user_exists(
uid=user.username,
2019-02-24 21:23:43 +00:00
attributes=['uid', 'givenName', 'sn', 'mail'],
search_base=settings.ENTIRE_SEARCH_BASE
)
if user_exists:
return render(
request,
'changeuserdata.html',
{ 'user': user.username,
'firstname': entries[0].givenName
if entries[0].givenName.value is not None else '',
'lastname': entries[0].sn
if entries[0].sn.value is not None else '',
2019-02-24 16:25:13 +00:00
'email': entries[0].mail
if entries[0].mail.value is not None else ''}
)
else:
return render(request, 'error.html',
{'urlname': urlname, 'service': service,
'error': request.user.username})
2018-10-09 17:49:47 +00:00
# get the change request
def post(self, request):
# variables for the error page
service = 'change user data'
2018-10-09 17:49:47 +00:00
urlname = 'change_data'
firstname = request.POST.get('firstname')
lastname = request.POST.get('lastname')
email = request.POST.get('email')
2019-01-26 13:02:37 +00:00
2018-10-09 17:49:47 +00:00
# Some sanity checks for the supplied data
if firstname == "":
return render(request, 'error.html', { 'urlname': urlname, 'service': service, 'error': 'Please enter a firstname.' } )
elif lastname == "":
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.' } )
try:
validate_email(email)
except ValidationError:
2018-10-09 17:49:47 +00:00
return render(request, 'error.html', { 'urlname': urlname, 'service': service, 'error': 'The supplied email address is invalid.' } )
2019-02-24 16:25:13 +00:00
ldap_manager = LdapManager()
result, msg = ldap_manager.change_user_details(
uid=request.user.username,
details={"givenName": firstname, "sn": lastname, "mail": email}
)
# Data change worked
2019-02-24 16:25:13 +00:00
if result:
return render(request, 'changeddata.html', { 'user': request.user.username, 'firstname': firstname, 'lastname': lastname, 'email': email } )
# Data change did not work, display error
else:
2019-02-24 16:25:13 +00:00
return render(request, 'error.html', { 'urlname': urlname, 'service': service, 'error': msg } )
2018-10-09 17:49:47 +00:00
class ResetPassword(View):
2018-10-09 17:49:47 +00:00
def get(self, request):
return render(request, 'resetpassword.html')
def post(self, request):
urlname = 'reset_password'
service = 'send a password reset request'
2018-10-09 17:49:47 +00:00
user = request.POST.get('user')
2018-10-15 15:52:15 +00:00
# First, check if the user exists
2019-02-24 17:42:27 +00:00
ldap_manager = LdapManager()
user_exists, entries = ldap_manager.check_user_exists(
uid=user,
2019-02-24 22:25:12 +00:00
search_base=settings.ENTIRE_SEARCH_BASE,
2019-02-24 17:42:27 +00:00
attributes=['uid', 'givenName', 'sn', 'mail']
)
if user_exists:
2019-02-24 17:42:27 +00:00
# user exists, so try to get email
# with get_pool().next() as rpc:
# (state, tmp1, tmp2, email) = rpc.getuserdata.get_data(user)
# Either error with the datalookup or no email provided
email = entries[0].mail.value
if email is None:
return render(
request, 'error.html',
{'urlname': urlname, 'service': service,
'error': 'Unable to retrieve email address for user.'}
)
base_url = "{0}://{1}".format(self.request.scheme,
self.request.get_host())
# Try to send the email out
emailsend = self.email(user, email, base_url)
# Email got sent out
if emailsend == True:
return render(
request, 'send_resetrequest.html', {'user': user}
)
# Error while trying to send email
else:
return render(
request, 'error.html',
{'urlname': urlname, 'service': service,
'error': emailsend}
)
2018-10-15 15:52:15 +00:00
else:
2019-02-24 17:42:27 +00:00
return render(
request, 'error.html',
{ 'urlname': urlname, 'service': service,
'error': 'The user does not exist.' }
)
2018-10-15 15:52:15 +00:00
2018-10-15 19:24:53 +00:00
# Sends an email to the user with the 24h active link for a password reset
def email(self, user, email, base_url):
2018-10-15 19:24:53 +00:00
# getting epoch for the time now in UTC to spare us headache with timezones
creationtime = int(datetime.utcnow().timestamp())
# Construct the data for the email
2019-02-24 17:41:07 +00:00
email_from = settings.EMAIL_FROM_ADDRESS
to = ['%s <%s>' % (user, email)]
2018-10-15 15:52:15 +00:00
subject = 'Password reset request for %s' % user
link = self.build_reset_link(user, creationtime, base_url)
body = 'This is an automated email which was triggered by a reset request for the user %s. Please do not reply to this email.\n' % user
2018-10-15 15:52:15 +00:00
body += 'If you received this email in error, please disregard it. If you get multiple emails like this, please contact us to look into potential abuse.\n'
body += 'To reset your password, please follow the link below:\n'
body += '%s\n\n' % link
2018-10-15 19:24:53 +00:00
body += 'The link will remain active for 24 hours.\n'
# Build the email
mail = EmailMessage(
subject=subject,
body=body,
from_email=email_from,
to=to
)
try:
mail.send()
result = True
except:
result = "An error occurred while trying to send the mail."
return result
2018-10-15 15:52:15 +00:00
2018-10-15 19:24:53 +00:00
# Builds the reset link for the email and puts the token into the database
def build_reset_link(self, user, epochutc, base_url):
2019-01-26 13:02:37 +00:00
# set up the data
2018-10-15 19:24:53 +00:00
tokengen = PasswordResetTokenGenerator()
# create some noise for use in the tokengenerator
pseudouser = PseudoUser()
token = tokengen.make_token(pseudouser)
2018-10-15 19:24:53 +00:00
buser = bytes(user, 'utf-8')
userpart = b64encode(buser)
2019-01-26 13:02:37 +00:00
# create entry into the database
2018-10-15 19:24:53 +00:00
newdbentry = ResetToken(user=user, token=token, creation=epochutc)
newdbentry.save()
# set up the link
link = "{base_url}/reset/{user}/{token}/".format(
base_url=base_url,user=userpart.decode('utf-8'),token=token
)
logger.debug("User reset url is {}".format(link))
2018-10-15 15:52:15 +00:00
return link
2018-10-15 19:24:53 +00:00
# Catch the resetrequest URL and check it
2018-10-15 15:52:15 +00:00
class ResetRequest(View):
# Gets the URL with user in b64 and the token, and checks it
# Also cleans the database
def get(self, request, user=None, token=None):
# Cleans up outdated tokens
2018-10-15 19:24:53 +00:00
# If we expect quite a bit of old tokens, maybe somewhere else is better,
# but for now we don't really expect many unused tokens
2019-05-02 21:29:01 +00:00
clean_db()
2018-10-15 19:24:53 +00:00
# If user and token are not supplied by django, it was called from somewhere else, so it's
# invalid
2018-10-15 15:52:15 +00:00
if user == None or token == None:
return HttpResponse('Invalid URL.', status=404)
# extract user from b64 format
tmp_user = bytes(user, 'utf-8')
user = b64decode(tmp_user)
user_clean = user.decode('utf-8')
2018-10-15 19:24:53 +00:00
# set checks_out = True if token is found in database
checks_out = False
2018-10-15 19:24:53 +00:00
dbentries = ResetToken.objects.all().filter(user=user_clean)
for entry in dbentries:
if entry.token == token:
# found the token, now delete it since it's used
checks_out = True
entry.delete()
# No token was found
2018-10-15 15:52:15 +00:00
if not checks_out:
return HttpResponse('Invalid URL.', status=404)
2018-10-15 19:24:53 +00:00
# Token was found, supply the form
2018-10-15 15:52:15 +00:00
else:
return render(request, 'resetpasswordnew.html', { 'user': user_clean } )
# Gets the post form with the new password and sets it
def post(self, request):
service = 'reset the password'
2018-10-15 19:24:53 +00:00
# get the supplied passwords
2018-10-15 15:52:15 +00:00
password1 = request.POST.get("password1")
password2 = request.POST.get("password2")
2018-10-15 19:24:53 +00:00
# get the hidden value of user
2018-10-15 15:52:15 +00:00
user = request.POST.get("user")
2018-10-15 19:24:53 +00:00
# some checks over the supplied data
2019-05-01 21:48:24 +00:00
if user == "" or not user:
2018-10-15 19:24:53 +00:00
return render(request, 'error.html', { 'service': service, 'error': 'Something went wrong. Did you use the supplied form?' } )
2018-10-15 15:52:15 +00:00
if password1 == "" or not password1 or password2 == "" or not password2:
return render(request, 'error.html', { 'service': service, 'error': 'Please supply a password and confirm it.' } )
if password1 != password2:
2019-05-02 21:29:01 +00:00
return render(request, 'error.html', {'service': service, 'error': 'The supplied passwords do not match.'})
2018-10-23 17:41:49 +00:00
if len(password1) < 8:
2019-05-02 21:29:01 +00:00
return render(request, 'error.html', {'service': service,
'error': 'The password is too short, please use a longer one. At least 8 characters.'})
ldap_manager = LdapManager()
result = ldap_manager.change_password(
user,
password1
)
# password change successful
if result:
2018-10-15 15:52:15 +00:00
return render(request, 'changedpassword.html', { 'user': user } )
2018-10-15 19:24:53 +00:00
# Something went wrong while changing the password
2018-10-15 15:52:15 +00:00
else:
return render(request, 'error.html', { 'service': service, 'error': result } )
2019-05-02 21:29:01 +00:00
2018-10-09 17:49:47 +00:00
# The logged in user can change the password here
class ChangePassword(LoginRequiredMixin, View):
login_url = reverse_lazy('login_index')
2018-10-09 17:49:47 +00:00
# Presents the page for a logged in user
def get(self, request):
if not request.user.is_authenticated:
return render(request, 'mustbeloggedin.html')
return render(request, 'changepassword.html', { 'user': request.user } )
2019-01-26 13:02:37 +00:00
2018-10-09 17:49:47 +00:00
# Does some checks on the supplied data and changes the password
def post(self, request):
# Variables for the error page
urlname = 'change_password'
service = 'change the password'
if not request.user.is_authenticated:
return render(request, 'mustbeloggedin.html')
login(request, request.user)
user = str(request.user)
2018-10-09 17:49:47 +00:00
oldpassword = request.POST.get('oldpassword')
check = authenticate(request, username=user, password=oldpassword)
# Is the right password for the user supplied?
if check is None:
return render(request, 'error.html', { 'urlname': urlname, 'service': service, 'error': 'Wrong password for the user.' } )
password1 = request.POST.get('password1')
password2 = request.POST.get('password2')
# Are both passwords from the form the same?
if password1 != password2:
2019-01-26 13:02:37 +00:00
return render(request, 'error.html', { 'urlname': urlname, 'service': service,
2018-10-09 17:49:47 +00:00
'error': 'Please check if you typed the same password both times for the new password' } )
2018-10-23 17:41:49 +00:00
# Check for password length
if len(password1) < 8:
return render(request, 'error.html', { 'urlname': urlname, 'service': service,
'error': 'The password is too short, please use a longer one. At least 8 characters.' } )
2019-02-23 18:50:42 +00:00
from .ungleich_ldap import LdapManager
ldap_manager = LdapManager()
result = ldap_manager.change_password(
user,
2019-02-23 18:50:42 +00:00
password1
)
# Password was changed
2019-02-23 18:50:42 +00:00
if result:
2019-02-24 22:32:50 +00:00
logout(request)
2018-10-09 17:49:47 +00:00
return render(request, 'changedpassword.html', { 'user': user } )
# Password not changed, instead got some kind of error
2018-10-09 17:49:47 +00:00
else:
return render(request, 'error.html', { 'urlname': urlname, 'service': service, 'error': result } )
2018-10-09 17:49:47 +00:00
# Deletes an account
class DeleteAccount(LoginRequiredMixin, View):
login_url = reverse_lazy('login_index')
# Show the basic form for deleting an account
2018-10-09 17:49:47 +00:00
def get(self, request):
2018-10-10 12:13:49 +00:00
return render(request, 'deleteaccount.html')
2018-10-09 17:49:47 +00:00
# Reads the filled out form
2018-10-10 12:13:49 +00:00
def post(self, request):
# Variables for error page
urlname = 'account_delete'
service = 'delete an account'
# Does the user exist?
username = request.POST.get('username')
ldap_manager = LdapManager()
user_exists, user_details = ldap_manager.check_user_exists(username)
if user_exists and request.user.username == username:
# Do user and password match?
password = request.POST.get('password')
pwd = r'%s' % password
check = authenticate(request, username=username, password=pwd)
if check is None:
return render(request, 'error.html',
{'urlname': urlname, 'service': service,
'error': 'Wrong password for user.'})
result = ldap_manager.delete_user(username)
# User deleted
if result:
logout(request)
return render(request, 'deleteduser.html', {'user': username})
# User not deleted, got some kind of error
else:
return render(request, 'error.html',
{'urlname': urlname, 'service': service,
'error': result})
else:
2019-02-24 16:46:44 +00:00
return render(request, 'error.html', { 'urlname': urlname, 'service': service, 'error': 'Unknown user.' } )
2018-10-09 17:49:47 +00:00
2018-10-15 19:24:53 +00:00
# Log out the session
class LogOut(View):
def get(self, request):
logout(request)
return HttpResponse(
"You have been logged out. You will be redirected in 2 seconds."
"<script>"
"setTimeout(function (){document.location.href='/';}, 2000);"
"</script>",
status=200
)
2019-01-26 14:19:58 +00:00
# TO be clarified
# To trick the tokengenerator to work with us, because we don't really
# have the expected user Class since we are reading the user from a form
# We store the tokens and don't have to use the check function,
# some one time data works fine.
class LastLogin():
def replace(self, microsecond=0, tzinfo=None):
return randint(1,100000)
class PseudoUser():
# easiest way to handle the check for lastlogin
last_login = LastLogin()
# random alphanumeric strings for primary key and password, just used for token generation
pk = ''.join(choice(string.ascii_letters + string.digits) for _ in range(20))
password = ''.join(choice(string.ascii_letters + string.digits) for _ in range(30))
2019-04-23 05:19:45 +00:00
2019-05-02 21:29:01 +00:00
class ActivateAccount(View):
def get(self, request, user=None, pwd=None, firstname=None, lastname=None, email=None, token=None):
clean_db()
if token is None:
return HttpResponse('Invalid URL', status=404)
elem_list = [user, pwd, firstname, lastname, email]
clean_list = []
for value in elem_list:
try:
value_temp = bytes(value, 'utf-8')
value_decode = b64decode(value_temp)
value_clean = value_decode.decode('utf-8')
clean_list.append(value_clean)
except Exception as e:
return HttpResponse('Invalid URL', status=404)
checks_out = False
dbentries = ResetToken.objects.all().filter(user=clean_list[0])
for entry in dbentries:
if entry.token == token:
# found the token, now delete it since it's used
checks_out = True
entry.delete()
# No token was found
if not checks_out:
return HttpResponse('Invalid URL.', status=404)
# Token was found, create user
try:
ldap_manager = LdapManager()
ldap_manager.create_user(
clean_list[0], clean_list[1], clean_list[2], clean_list[3], clean_list[4]
)
2019-05-26 20:15:07 +00:00
req = requests.post(otp_url, data=json.dumps(
{
'auth_token': TOTP(admin_seed).now(),
'auth_name': admin_name,
'auth_realm': admin_realm,
'name': clean_list[0],
'realm': user_realm
}), headers={'Content-Type': 'application/json'})
if req.status_code != 201:
logger.error("User {} failed to create its otp seed".format(clean_list[0]))
2019-05-02 21:29:01 +00:00
#Send welcome email
except Exception as e:
return render(request, 'error.html', {'urlname': 'register',
'service': 'register an user',
'error': e})
return render(request, 'usercreated.html', { 'user': clean_list[0] } )
2019-04-23 05:19:45 +00:00
class UserCreateAPI(APIView):
def post(self, request):
2019-04-23 05:19:45 +00:00
username = request.POST.get('username')
email = request.POST.get('email')
firstname = request.POST.get('firstname')
lastname = request.POST.get('lastname')
if username == "" or not username:
return Response('Please supply a username.', 400)
try:
validate_email(email)
except ValidationError:
return Response('Email is not valid.', 400)
if not firstname or not lastname:
return Response('Please provide firstname and lastname', 400)
pwd = r'%s' % User.objects.make_random_password()
2019-05-02 21:29:01 +00:00
base_url = "{0}://{1}".format(self.request.scheme,
self.request.get_host())
2019-04-23 05:19:45 +00:00
creationtime = int(datetime.utcnow().timestamp())
2019-05-02 21:29:01 +00:00
link = activate_account_link(base_url, username, pwd, firstname, lastname, email. creationtime)
2019-04-23 05:19:45 +00:00
# Construct the data for the email
email_from = settings.EMAIL_FROM_ADDRESS
to = ['%s <%s>' % (username, email)]
2019-05-02 21:29:01 +00:00
subject = 'Ungleich account creation.'
body = 'A request has been sent to our servers to register you as a ungleich user.\n'
body += 'In order to complete the registration process you must ' \
'click <a href="{link}">here</a> or copy & paste the following link into the address bar of ' \
'your browser.\n{link}\n'.format(link=link)
2019-04-23 05:19:45 +00:00
body += 'Your credentials are:\n'
body += 'Username: %s\n\n' % username
body += 'Password: %s\n\n' % pwd
2019-05-02 21:29:01 +00:00
body += 'We strongly recommend after the activation to log in and change your password.\n'
body += 'This link will remain active for 24 hours.\n'
2019-04-23 05:19:45 +00:00
# Build the email
mail = EmailMessage(
subject=subject,
body=body,
from_email=email_from,
to=to
)
try:
mail.send()
except:
2019-05-02 21:29:01 +00:00
return Response('Failed to send the email', 201)
return Response('Email with activation link successfully sent', 200)
class SeedRetrieveCreate(APIView):
def post(self, request):
try:
username = request.data['username']
password = request.data[r'password']
realm = request.data['realm']
print(password)
except KeyError:
return Response('You need to specify username, password, and realm values', 400)
# authenticate the user against ldap
user = authenticate(username=username, password=password)
if user is not None:
req = requests.get(otp_url, data=json.dumps(
{
'auth_token': TOTP(admin_seed).now(),
'auth_name': admin_name,
2019-05-26 20:15:07 +00:00
'auth_realm': admin_realm}), headers={'Content-Type': 'application/json'})
response_data = json.loads(req.text)
for elem in response_data:
if elem['name'] == username and elem['realm'] == realm:
return Response(elem, 200)
# If doesn't find a match then check if the realm is allowed and create the user
allowed_realms = config('ALLOWED_REALMS', cast=Csv())
if realm not in allowed_realms:
return Response('Not allowed to perform this action.', 403)
else:
req = requests.post(otp_url, data=json.dumps(
{
'auth_token': TOTP(admin_seed).now(),
'auth_name': admin_name,
2019-05-26 20:15:07 +00:00
'auth_realm': admin_realm,
'name': username,
'realm': realm
}), headers={'Content-Type': 'application/json'})
if req.status_code == 201:
msg = json.loads(req.text)
return Response(msg, 201)
else:
return Response(json.loads(req.text), req.status_code)
else:
2019-05-26 20:15:07 +00:00
return Response('Invalid Credentials', 400)
class Seeds(LoginRequiredMixin, View):
login_url = reverse_lazy('login_index')
def get(self, request):
seedlist = []
response = requests.get(
otp_url,
headers={'Content-Type': 'application/json'},
data=json.dumps(
{'auth_name': admin_name, 'auth_realm': admin_realm, 'auth_token': TOTP(admin_seed).now()}))
response_data = json.loads(response.text)
for i in range(len(response_data)):
2019-05-26 20:59:52 +00:00
if response_data[i]['name'] == request.user.username:
2019-05-26 20:15:07 +00:00
value = {'realm': response_data[i]['realm'], 'seed': response_data[i]['seed']}
seedlist.append(value)
return render(request, 'seed_list.html', {'seed': seedlist})