Merge branch 'william' into 'master'
William See merge request downhill/vuejs-userservice!2
							
								
								
									
										42
									
								
								.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
					@ -0,0 +1,42 @@
 | 
				
			||||||
 | 
					*.log
 | 
				
			||||||
 | 
					db.sqlite3
 | 
				
			||||||
 | 
					*.pyc
 | 
				
			||||||
 | 
					*.DS_Store
 | 
				
			||||||
 | 
					build/
 | 
				
			||||||
 | 
					*.egg_info
 | 
				
			||||||
 | 
					#editors && utilites.
 | 
				
			||||||
 | 
					*.swp
 | 
				
			||||||
 | 
					*~
 | 
				
			||||||
 | 
					__pycache__/
 | 
				
			||||||
 | 
					.ropeproject/
 | 
				
			||||||
 | 
					#django
 | 
				
			||||||
 | 
					local_settings.py
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					!.keep
 | 
				
			||||||
 | 
					media/
 | 
				
			||||||
 | 
					!media/keep
 | 
				
			||||||
 | 
					/CACHE/
 | 
				
			||||||
 | 
					/static/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					\#*#
 | 
				
			||||||
 | 
					.\#*
 | 
				
			||||||
 | 
					*~
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					secret-key
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					node_modules/
 | 
				
			||||||
 | 
					*.db
 | 
				
			||||||
 | 
					ungleich.db
 | 
				
			||||||
 | 
					*~*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					secret-key
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*.psd
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.idea/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.env
 | 
				
			||||||
 | 
					*.mo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					venv/
 | 
				
			||||||
 | 
					dal/ldap_max_uid_file
 | 
				
			||||||
| 
						 | 
					@ -1,15 +0,0 @@
 | 
				
			||||||
from django.db import models
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Basic DB to correlate tokens, users and creation time
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class ResetToken(models.Model):
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # users wouldn't use usernames >100 chars
 | 
					 | 
				
			||||||
    user = models.CharField(max_length=100)
 | 
					 | 
				
			||||||
    # Not so sure about tokens, better make it big
 | 
					 | 
				
			||||||
    # should be <100, but big usernames make bigger tokens
 | 
					 | 
				
			||||||
    # if I read that correctly
 | 
					 | 
				
			||||||
    token = models.CharField(max_length=255)
 | 
					 | 
				
			||||||
    # creation time in epoch (UTC)
 | 
					 | 
				
			||||||
    # BigInt just so we are save for the next few decades ;)
 | 
					 | 
				
			||||||
    creation = models.BigIntegerField()
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,254 +0,0 @@
 | 
				
			||||||
"""
 | 
					 | 
				
			||||||
Django settings for dal project.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Generated by 'django-admin startproject' using Django 1.10.7.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
For more information on this file, see
 | 
					 | 
				
			||||||
https://docs.djangoproject.com/en/1.10/topics/settings/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
For the full list of settings and their values, see
 | 
					 | 
				
			||||||
https://docs.djangoproject.com/en/1.10/ref/settings/
 | 
					 | 
				
			||||||
"""
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import os
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import ldap
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
from django_auth_ldap.config import LDAPSearch, LDAPSearchUnion
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
from configparser import ConfigParser
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
config = ConfigParser()
 | 
					 | 
				
			||||||
config.read('userservice.conf')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# LDAP config
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
AUTH_LDAP_SERVER_URI = config['LDAP']['LDAPSERVER']
 | 
					 | 
				
			||||||
# The search user
 | 
					 | 
				
			||||||
AUTH_LDAP_BIND_DN = config['LDAP']['SEARCHUSER']
 | 
					 | 
				
			||||||
# The password for the search user
 | 
					 | 
				
			||||||
AUTH_LDAP_BIND_PASSWORD = config.get('LDAP','SEARCHUSERPASSWORD', raw=True)
 | 
					 | 
				
			||||||
# Search union over two ou
 | 
					 | 
				
			||||||
AUTH_LDAP_USER_SEARCH = LDAPSearchUnion(
 | 
					 | 
				
			||||||
        LDAPSearch("ou=users,dc=ungleich,dc=ch", ldap.SCOPE_SUBTREE, "(uid=%(user)s)"),
 | 
					 | 
				
			||||||
        LDAPSearch("ou=customers,dc=ungleich,dc=ch", ldap.SCOPE_SUBTREE, "(uid=%(user)s)"),
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Basic User
 | 
					 | 
				
			||||||
#AUTH_LDAP_USER_DN_TEMPLATE = "uid=%(user)s,ou=users,dc=ungleich,dc=ch"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Search over just one ou
 | 
					 | 
				
			||||||
#AUTH_LDAP_USER_SEARCH = LDAPSearch( LDAPSearch("ou=users,dc=ungleich,dc=ch",
 | 
					 | 
				
			||||||
#                                        ldap.SCOPE_SUBTREE, "(uid=%(user)s)")
 | 
					 | 
				
			||||||
#                                )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Maps some user keys since ldap has extensive infos
 | 
					 | 
				
			||||||
#AUTH_LDAP_USER_ATTR_MAP = {"first_name": "givenName", "last_name": "sn"}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Maps some profile keys since ldap has extensive infos
 | 
					 | 
				
			||||||
#AUTH_LDAP_PROFILE_ATTR_MAP = {"home_directory": "homeDirectory"}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# LDAP config end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Django nameko config
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Where's the Rabbitmq at
 | 
					 | 
				
			||||||
NAMEKO_CONFIG = { 
 | 
					 | 
				
			||||||
        'AMQP_URI': 'amqp://%s' % config['System']['RABBITMQ']
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Standard pool size
 | 
					 | 
				
			||||||
NAMEKO_POOL_SIZE = 4
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Django nameko config end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
 | 
					 | 
				
			||||||
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
STATIC_ROOT = os.path.dirname('/home/downhill/ungleich/vuejsuserservice/dal/dal/static/')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Quick-start development settings - unsuitable for production
 | 
					 | 
				
			||||||
# See https://docs.djangoproject.com/en/1.10/howto/deployment/checklist/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# SECURITY WARNING: keep the secret key used in production secret!
 | 
					 | 
				
			||||||
SECRET_KEY = 'rn=f&ecp#&#escxpk!0e%a$i3sbm$z@5+g4h9q+w7-83*f2f-i'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# SECURITY WARNING: don't run with debug turned on in production!
 | 
					 | 
				
			||||||
DEBUG = True
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ALLOWED_HOSTS = []
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Application definition
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
INSTALLED_APPS = [
 | 
					 | 
				
			||||||
    'django.contrib.admin',
 | 
					 | 
				
			||||||
    'django.contrib.auth',
 | 
					 | 
				
			||||||
    'django.contrib.contenttypes',
 | 
					 | 
				
			||||||
    'django.contrib.sessions',
 | 
					 | 
				
			||||||
    'django.contrib.messages',
 | 
					 | 
				
			||||||
    'django.contrib.staticfiles',
 | 
					 | 
				
			||||||
    'bootstrap3',
 | 
					 | 
				
			||||||
    'sekizai',
 | 
					 | 
				
			||||||
    'dal',
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
MIDDLEWARE = [
 | 
					 | 
				
			||||||
    'django.middleware.security.SecurityMiddleware',
 | 
					 | 
				
			||||||
    'django.contrib.sessions.middleware.SessionMiddleware',
 | 
					 | 
				
			||||||
    'django.middleware.common.CommonMiddleware',
 | 
					 | 
				
			||||||
    'django.middleware.csrf.CsrfViewMiddleware',
 | 
					 | 
				
			||||||
    'django.contrib.auth.middleware.AuthenticationMiddleware',
 | 
					 | 
				
			||||||
    'django.contrib.messages.middleware.MessageMiddleware',
 | 
					 | 
				
			||||||
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Backend for auth
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
AUTHENTICATION_BACKENDS = (
 | 
					 | 
				
			||||||
    'django_auth_ldap.backend.LDAPBackend',
 | 
					 | 
				
			||||||
# we only use LDAP for this service, so no auth against the standard DB
 | 
					 | 
				
			||||||
#    'django.contrib.auth.backends.ModelBackend',
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ROOT_URLCONF = 'dal.urls'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TEMPLATES = [
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
 | 
					 | 
				
			||||||
        'DIRS': [],
 | 
					 | 
				
			||||||
        'APP_DIRS': True,
 | 
					 | 
				
			||||||
        'OPTIONS': {
 | 
					 | 
				
			||||||
            'context_processors': [
 | 
					 | 
				
			||||||
                'django.template.context_processors.debug',
 | 
					 | 
				
			||||||
                'django.template.context_processors.request',
 | 
					 | 
				
			||||||
                'django.contrib.auth.context_processors.auth',
 | 
					 | 
				
			||||||
                'django.contrib.messages.context_processors.messages',
 | 
					 | 
				
			||||||
                'sekizai.context_processors.sekizai',
 | 
					 | 
				
			||||||
            ],
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
WSGI_APPLICATION = 'dal.wsgi.application'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Django Bootstrap - Settings
 | 
					 | 
				
			||||||
# Added Configuration for bootstrap static files to load over https.
 | 
					 | 
				
			||||||
BOOTSTRAP3 = {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # The URL to the jQuery JavaScript file
 | 
					 | 
				
			||||||
    'jquery_url': '//code.jquery.com/jquery.min.js',
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # The Bootstrap base URL
 | 
					 | 
				
			||||||
    'base_url': '//maxcdn.bootstrapcdn.com/bootstrap/3.3.4/',
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # The complete URL to the Bootstrap CSS file
 | 
					 | 
				
			||||||
    # (None means derive it from base_url)
 | 
					 | 
				
			||||||
    'css_url': None,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # The complete URL to the Bootstrap CSS file (None means no theme)
 | 
					 | 
				
			||||||
    'theme_url': None,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # The complete URL to the Bootstrap JavaScript file
 | 
					 | 
				
			||||||
    # (None means derive it from base_url)
 | 
					 | 
				
			||||||
    'javascript_url': None,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Put JavaScript in the HEAD section of the HTML document
 | 
					 | 
				
			||||||
    # (only relevant if you use bootstrap3.html)
 | 
					 | 
				
			||||||
    'javascript_in_head': False,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Include jQuery with Bootstrap JavaScript
 | 
					 | 
				
			||||||
    # (affects django-bootstrap3 template tags)
 | 
					 | 
				
			||||||
    'include_jquery': False,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Label class to use in horizontal forms
 | 
					 | 
				
			||||||
    'horizontal_label_class': 'col-md-3',
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Field class to use in horizontal forms
 | 
					 | 
				
			||||||
    'horizontal_field_class': 'col-md-9',
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Set HTML required attribute on required fields
 | 
					 | 
				
			||||||
    'set_required': True,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Set HTML disabled attribute on disabled fields
 | 
					 | 
				
			||||||
    'set_disabled': False,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Set placeholder attributes to label if no placeholder is provided
 | 
					 | 
				
			||||||
    'set_placeholder': True,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Class to indicate required (better to set this in your Django form)
 | 
					 | 
				
			||||||
    'required_css_class': '',
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Class to indicate error (better to set this in your Django form)
 | 
					 | 
				
			||||||
    'error_css_class': 'has-error',
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Class to indicate success, meaning the field has valid input
 | 
					 | 
				
			||||||
    # (better to set this in your Django form)
 | 
					 | 
				
			||||||
    'success_css_class': 'has-success',
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Renderers (only set these if you have studied the source and understand
 | 
					 | 
				
			||||||
    # the inner workings)
 | 
					 | 
				
			||||||
    'formset_renderers': {
 | 
					 | 
				
			||||||
        'default': 'bootstrap3.renderers.FormsetRenderer',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    'form_renderers': {
 | 
					 | 
				
			||||||
        'default': 'bootstrap3.renderers.FormRenderer',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    'field_renderers': {
 | 
					 | 
				
			||||||
        'default': 'bootstrap3.renderers.FieldRenderer',
 | 
					 | 
				
			||||||
        'inline': 'bootstrap3.renderers.InlineFieldRenderer',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Database
 | 
					 | 
				
			||||||
# https://docs.djangoproject.com/en/1.10/ref/settings/#databases
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
DATABASES = {
 | 
					 | 
				
			||||||
    'default': {
 | 
					 | 
				
			||||||
        'ENGINE': 'django.db.backends.sqlite3',
 | 
					 | 
				
			||||||
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Password validation
 | 
					 | 
				
			||||||
# https://docs.djangoproject.com/en/1.10/ref/settings/#auth-password-validators
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
AUTH_PASSWORD_VALIDATORS = [
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Internationalization
 | 
					 | 
				
			||||||
# https://docs.djangoproject.com/en/1.10/topics/i18n/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
LANGUAGE_CODE = 'en-us'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TIME_ZONE = 'UTC'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
USE_I18N = True
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
USE_L10N = True
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
USE_TZ = True
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Static files (CSS, JavaScript, Images)
 | 
					 | 
				
			||||||
# https://docs.djangoproject.com/en/1.10/howto/static-files/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
STATIC_URL = '/static/'
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,14 +0,0 @@
 | 
				
			||||||
<title> Userdata changed. </title>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<h2> The data for {{user}} has been changed. </h2>
 | 
					 | 
				
			||||||
<br><br>
 | 
					 | 
				
			||||||
<ul>
 | 
					 | 
				
			||||||
	<li> Username: {{user}} </li>
 | 
					 | 
				
			||||||
	<li> Firstname: {{firstname}} </li>
 | 
					 | 
				
			||||||
	<li> Lastname: {{lastname}} </li>
 | 
					 | 
				
			||||||
	<li> Email: {{email}} </li>
 | 
					 | 
				
			||||||
</ul>
 | 
					 | 
				
			||||||
<br><br>
 | 
					 | 
				
			||||||
<form action={% url 'index' %} method="get">
 | 
					 | 
				
			||||||
	<input type="submit" value="Back to indexpage">
 | 
					 | 
				
			||||||
</form>
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,7 +0,0 @@
 | 
				
			||||||
<title> Password for {{user}}  changed. </title>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<h2> The password for {{user}} has been changed. </h2>
 | 
					 | 
				
			||||||
<br><br>
 | 
					 | 
				
			||||||
<form action={% url 'index' %} method="get">
 | 
					 | 
				
			||||||
	<input type="submit" value="Back to indexpage">
 | 
					 | 
				
			||||||
</form>
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,20 +0,0 @@
 | 
				
			||||||
<title> Changing the password for {{user}} </title>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<h2> Changing the password for {{user}} </h2>
 | 
					 | 
				
			||||||
<br><br>
 | 
					 | 
				
			||||||
<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' %} method="post">
 | 
					 | 
				
			||||||
	{% csrf_token %}
 | 
					 | 
				
			||||||
	<br>The old password:<br>  
 | 
					 | 
				
			||||||
	<input type="password" name="oldpassword" id="oldpassword">
 | 
					 | 
				
			||||||
	<br><br>The new password (at least 8 characters):<br>
 | 
					 | 
				
			||||||
	<input type="password" name="password1" id="password1">
 | 
					 | 
				
			||||||
	<br>Please repeat the new Password:<br>
 | 
					 | 
				
			||||||
	<input type="password" name="password2" id="password2">
 | 
					 | 
				
			||||||
	<br><br>
 | 
					 | 
				
			||||||
	<input type="submit" value="Submit">
 | 
					 | 
				
			||||||
</form>
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,19 +0,0 @@
 | 
				
			||||||
<title> Changing user data for {{user}} </title>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<h2> Changing user data for {{user}} </h2>
 | 
					 | 
				
			||||||
<br><br>
 | 
					 | 
				
			||||||
<form action={% url 'index' %} method="get">
 | 
					 | 
				
			||||||
	<input type="submit" value="Back to indexpage">
 | 
					 | 
				
			||||||
</form>
 | 
					 | 
				
			||||||
<br><br>
 | 
					 | 
				
			||||||
<form action={% url 'change_data' %} method="post">
 | 
					 | 
				
			||||||
	{% csrf_token %}
 | 
					 | 
				
			||||||
	<br>Firstname:<br>
 | 
					 | 
				
			||||||
	<input type="text" name="firstname" id="firstname" value="{{firstname}}">
 | 
					 | 
				
			||||||
	<br><br>Lastname:<br>
 | 
					 | 
				
			||||||
	<input type="text" name="lastname" id="lastname" value="{{lastname}}">
 | 
					 | 
				
			||||||
	<br><br>Email:<br>
 | 
					 | 
				
			||||||
	<input type="text" name="email" id="email" value="{{email}}">
 | 
					 | 
				
			||||||
	<br><br>
 | 
					 | 
				
			||||||
	<input type="submit" value="Submit">
 | 
					 | 
				
			||||||
</form>
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,18 +0,0 @@
 | 
				
			||||||
<title> Deleting an Account </title>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<h2> Deleting an Account </h2>
 | 
					 | 
				
			||||||
<br><br>
 | 
					 | 
				
			||||||
<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' %} method="post">
 | 
					 | 
				
			||||||
	{% csrf_token %} 
 | 
					 | 
				
			||||||
	<br><br>Username:<br>
 | 
					 | 
				
			||||||
	<input type="text" name="username" id="username">
 | 
					 | 
				
			||||||
	<br><br>Password:<br>
 | 
					 | 
				
			||||||
	<input type="password" name="password" id="password">
 | 
					 | 
				
			||||||
	<br><br>
 | 
					 | 
				
			||||||
	<input type="submit" value="Submit">
 | 
					 | 
				
			||||||
</form>
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,7 +0,0 @@
 | 
				
			||||||
<title> Deleted user {{user}} </title>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<h2> The user {{user}} was deleted from our system. </h2>
 | 
					 | 
				
			||||||
<br>
 | 
					 | 
				
			||||||
<form action={% url 'index' %} method="get">
 | 
					 | 
				
			||||||
	<input type="submit" value="Back to indexpage">
 | 
					 | 
				
			||||||
</form>
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,17 +0,0 @@
 | 
				
			||||||
<title> An error has occurred! </title>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<h2> We are sorry, an error has occured while handling your request. </h2>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
While trying to {{service}}, an error was encountered: {{error}}
 | 
					 | 
				
			||||||
<br><br>
 | 
					 | 
				
			||||||
You can try to:
 | 
					 | 
				
			||||||
<br>
 | 
					 | 
				
			||||||
{% if urlname %}
 | 
					 | 
				
			||||||
<form action={% url urlname %} method="get">
 | 
					 | 
				
			||||||
	<input type="submit" value="Go back and try again">
 | 
					 | 
				
			||||||
</form>
 | 
					 | 
				
			||||||
<br>or<br>
 | 
					 | 
				
			||||||
{% endif %}
 | 
					 | 
				
			||||||
<form action={% url 'index' %} method="get">
 | 
					 | 
				
			||||||
	<input type="submit" value="Go to the indexpage">
 | 
					 | 
				
			||||||
</form>
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,44 +0,0 @@
 | 
				
			||||||
{% load i18n %}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<style>
 | 
					 | 
				
			||||||
.col-lg-12 {
 | 
					 | 
				
			||||||
	background-color: grey;
 | 
					 | 
				
			||||||
	color: white;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.list-inline {
 | 
					 | 
				
			||||||
	background-color: grey;
 | 
					 | 
				
			||||||
	color: white;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
</style>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<footer>
 | 
					 | 
				
			||||||
    <div class="container">
 | 
					 | 
				
			||||||
        <div class="row">
 | 
					 | 
				
			||||||
            <div class="col-lg-12">
 | 
					 | 
				
			||||||
                <ul class="list-inline">
 | 
					 | 
				
			||||||
                    <li class="col-lg-12">
 | 
					 | 
				
			||||||
                        <a href="#">Home</a>
 | 
					 | 
				
			||||||
                    </li>
 | 
					 | 
				
			||||||
                    <li class="footer-menu-divider">⋅</li>
 | 
					 | 
				
			||||||
                    <li>
 | 
					 | 
				
			||||||
                        <a href="#about">How it works</a></li>
 | 
					 | 
				
			||||||
                    <li class="footer-menu-divider">⋅</li>
 | 
					 | 
				
			||||||
                    <li>
 | 
					 | 
				
			||||||
                        <a href="#about">Your infrastructure</a></li>
 | 
					 | 
				
			||||||
                    <li>⋅</li>
 | 
					 | 
				
			||||||
                    <li>
 | 
					 | 
				
			||||||
                        <a href="#about">Our infrastructure</a></li>
 | 
					 | 
				
			||||||
                    <li class="footer-menu-divider">⋅</li>
 | 
					 | 
				
			||||||
                    <li>
 | 
					 | 
				
			||||||
                        <a href="#services">Pricing</a>
 | 
					 | 
				
			||||||
                    </li>
 | 
					 | 
				
			||||||
                    <li class="footer-menu-divider">⋅</li>
 | 
					 | 
				
			||||||
                    <li>
 | 
					 | 
				
			||||||
                        <a href="#contact">Contact</a>
 | 
					 | 
				
			||||||
                    </li>
 | 
					 | 
				
			||||||
                </ul>
 | 
					 | 
				
			||||||
                <p class="copyright text-muted small">Copyright © ungleich glarus ag {% now "Y" %}. {% trans "All Rights Reserved" %}</p>
 | 
					 | 
				
			||||||
            </div>
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
</footer>
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,45 +0,0 @@
 | 
				
			||||||
{% extends "base_short.html" %}
 | 
					 | 
				
			||||||
{% load staticfiles bootstrap3 %}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
{% block content %}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<style>
 | 
					 | 
				
			||||||
.auth-footer { 
 | 
					 | 
				
			||||||
	color: black;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
a:link { color: #000000 } 
 | 
					 | 
				
			||||||
</style>
 | 
					 | 
				
			||||||
<div class="auth_container">
 | 
					 | 
				
			||||||
   <div class="auth_bg"></div>
 | 
					 | 
				
			||||||
   <div class="auth_center">
 | 
					 | 
				
			||||||
	<div class="auth_content">
 | 
					 | 
				
			||||||
	    <div class="auth-box">
 | 
					 | 
				
			||||||
		<h2 class="section-heading allcaps"> Login </h2>
 | 
					 | 
				
			||||||
		{% include 'includes/_messages.html' %}
 | 
					 | 
				
			||||||
		<form action={% url 'index' %} method="post" class="form" nonvalidated>
 | 
					 | 
				
			||||||
			{% csrf_token %}
 | 
					 | 
				
			||||||
			<div class="text-center">
 | 
					 | 
				
			||||||
				<div class="form-group"><label class="sr-only control-label" for="username">Username</label><input class="form-control" type="text" name="username" id="username" placeholder="Username"></div>
 | 
					 | 
				
			||||||
				<div class="form-group"><label class="sr-only control-label" for="password">Password</label><input class="form-control" type="password" name="password" id="password" placeholder="Password"></div>
 | 
					 | 
				
			||||||
			   <br><br>
 | 
					 | 
				
			||||||
			   <button type="submit" class="btn choice-btn"> Log in </button>
 | 
					 | 
				
			||||||
			</div>
 | 
					 | 
				
			||||||
		</form>
 | 
					 | 
				
			||||||
		<div class="auth-footer">
 | 
					 | 
				
			||||||
		   <div>
 | 
					 | 
				
			||||||
		       Don't have an account yet? 
 | 
					 | 
				
			||||||
		       <a href={% url 'register' %}> Sign up </a>
 | 
					 | 
				
			||||||
		   </div>
 | 
					 | 
				
			||||||
		   <div>
 | 
					 | 
				
			||||||
		       or <a href={% url 'reset_password' %}> Reset your password </a>
 | 
					 | 
				
			||||||
		   </div>
 | 
					 | 
				
			||||||
		</div>
 | 
					 | 
				
			||||||
	     </div>
 | 
					 | 
				
			||||||
	 </div>
 | 
					 | 
				
			||||||
   </div>
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
{% endblock %}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,11 +0,0 @@
 | 
				
			||||||
<title> Login failed! </title>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<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' %} method="get">
 | 
					 | 
				
			||||||
	<input type="submit" value="Register an user">
 | 
					 | 
				
			||||||
</form>
 | 
					 | 
				
			||||||
<br><br>
 | 
					 | 
				
			||||||
<form action={% url 'index' %} method="get">
 | 
					 | 
				
			||||||
	<input type="submit" value="Back to indexpage">
 | 
					 | 
				
			||||||
</form>
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,7 +0,0 @@
 | 
				
			||||||
<title> You must be logged in to access this page </title>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<h2> You must be logged in to access this page </h2>
 | 
					 | 
				
			||||||
<br><br>
 | 
					 | 
				
			||||||
<form action={% url 'index' %} method="get">
 | 
					 | 
				
			||||||
	<input type="submit" value="Back to indexpage">
 | 
					 | 
				
			||||||
</form>
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,27 +0,0 @@
 | 
				
			||||||
<title> Register an user at ungleich </title>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<h2> Register an user at ungleich </h2>
 | 
					 | 
				
			||||||
<br><br>
 | 
					 | 
				
			||||||
<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' %} method="post">
 | 
					 | 
				
			||||||
	{% csrf_token %}
 | 
					 | 
				
			||||||
	<br>Username (alphanumeric):<br>
 | 
					 | 
				
			||||||
	<input type="text" name="username" id="username">
 | 
					 | 
				
			||||||
	<br>Password (at least 8 characters):<br>
 | 
					 | 
				
			||||||
	<input type="password" name="password1" id="password1">
 | 
					 | 
				
			||||||
	<br>Please confirm your Password:<br>
 | 
					 | 
				
			||||||
	<input type="password" name="password2" id="password2">
 | 
					 | 
				
			||||||
	<br>Firstname:<br>
 | 
					 | 
				
			||||||
	<input type="text" name="firstname" id="firstname">
 | 
					 | 
				
			||||||
	<br>Lastname:<br>
 | 
					 | 
				
			||||||
	<input type="text" name="lastname" id="lastname">
 | 
					 | 
				
			||||||
	<br>Emailaddress:<br>
 | 
					 | 
				
			||||||
	<input type="text" name="email" id="email">
 | 
					 | 
				
			||||||
	<br>
 | 
					 | 
				
			||||||
	<input type="submit" value="Submit">
 | 
					 | 
				
			||||||
</form>
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,13 +0,0 @@
 | 
				
			||||||
<title> Password reset </title>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<h2> Password reset </h2>
 | 
					 | 
				
			||||||
<br><br>
 | 
					 | 
				
			||||||
To reset your password, please enter your username below. You will get an email with a link to change your password. 
 | 
					 | 
				
			||||||
<br><br>
 | 
					 | 
				
			||||||
<form action={% url 'reset_password' %} method="post">
 | 
					 | 
				
			||||||
	{% csrf_token %}
 | 
					 | 
				
			||||||
	Username:<br>
 | 
					 | 
				
			||||||
	<input type="text" name="user" id="user">
 | 
					 | 
				
			||||||
	<br>
 | 
					 | 
				
			||||||
	<input type="submit" value="Submit">
 | 
					 | 
				
			||||||
</form>
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,14 +0,0 @@
 | 
				
			||||||
<title> Set new password for {{user}} </title>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<h2> Please set new password for {{user}} </h2>
 | 
					 | 
				
			||||||
<br><br>
 | 
					 | 
				
			||||||
<form action={% url 'reset' %} method="post">
 | 
					 | 
				
			||||||
	{% csrf_token %}
 | 
					 | 
				
			||||||
	New Password:<br>
 | 
					 | 
				
			||||||
	<input type="password" name="password1" id="password1">
 | 
					 | 
				
			||||||
	<br>Please confirm new password:<br>
 | 
					 | 
				
			||||||
	<input type="password" name="password2" id="password2">
 | 
					 | 
				
			||||||
	<br>
 | 
					 | 
				
			||||||
	<input type="hidden" name="user" id="user" value="{{user}}">
 | 
					 | 
				
			||||||
	<input type="submit" value="Submit">
 | 
					 | 
				
			||||||
</form>
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,10 +0,0 @@
 | 
				
			||||||
<title> Reset request processed and confirmation email sent </title>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<h2> Reset request processed and confirmation email sent </h2>
 | 
					 | 
				
			||||||
<br><br>
 | 
					 | 
				
			||||||
You will shortly get the confirmation email to confirm that you wish to reset the password for {{user}}.<br>
 | 
					 | 
				
			||||||
Please follow the link in the email to reset your password.
 | 
					 | 
				
			||||||
<br><br>
 | 
					 | 
				
			||||||
<form action={% url 'index' %} method="get">
 | 
					 | 
				
			||||||
	<input type="submit" value="Back to indexpage">
 | 
					 | 
				
			||||||
</form>
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,7 +0,0 @@
 | 
				
			||||||
<title> User {{ user }} created. </title>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<h2> User {{ user }} was successfully created. </h2>
 | 
					 | 
				
			||||||
<br><br>
 | 
					 | 
				
			||||||
<form action={% url 'index' %} method="get">
 | 
					 | 
				
			||||||
	<input type="submit" value="Back to Indexpage">
 | 
					 | 
				
			||||||
</form>
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,24 +0,0 @@
 | 
				
			||||||
<title> Options for {{user}} </title>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<h2> Welcome, {{user}} </h2>
 | 
					 | 
				
			||||||
<br><br>
 | 
					 | 
				
			||||||
You have the following options:
 | 
					 | 
				
			||||||
<br>
 | 
					 | 
				
			||||||
<form action={% url 'change_data' %} method="get">
 | 
					 | 
				
			||||||
	<input type="submit" value="Change your userdata">
 | 
					 | 
				
			||||||
</form>
 | 
					 | 
				
			||||||
<br>
 | 
					 | 
				
			||||||
<form action={% url 'change_password' %} method="get">
 | 
					 | 
				
			||||||
	<input type="submit" value="Change your password">
 | 
					 | 
				
			||||||
</form>
 | 
					 | 
				
			||||||
<br>
 | 
					 | 
				
			||||||
<form action={% url 'reset_password' %} method="get">
 | 
					 | 
				
			||||||
	<input type="submit" value="Reset your password">
 | 
					 | 
				
			||||||
</form>
 | 
					 | 
				
			||||||
<br>
 | 
					 | 
				
			||||||
<form action={% url 'account_delete' %} method="get">
 | 
					 | 
				
			||||||
	<input type="submit" value="Delete your account">
 | 
					 | 
				
			||||||
</form>
 | 
					 | 
				
			||||||
<form action={% url 'logout' %} method="get">
 | 
					 | 
				
			||||||
	<input type="submit" value="Logout">
 | 
					 | 
				
			||||||
</form>
 | 
					 | 
				
			||||||
							
								
								
									
										437
									
								
								dal/dal/views.py
									
										
									
									
									
								
							
							
						
						| 
						 | 
					@ -1,437 +0,0 @@
 | 
				
			||||||
# Imports from django 
 | 
					 | 
				
			||||||
from django.shortcuts import render
 | 
					 | 
				
			||||||
from django.views.generic import View
 | 
					 | 
				
			||||||
from django.contrib.auth import authenticate, login, logout
 | 
					 | 
				
			||||||
from django.contrib.auth.models import User
 | 
					 | 
				
			||||||
from django.http import HttpResponse, HttpResponseRedirect
 | 
					 | 
				
			||||||
from django.core.validators import validate_email, ValidationError
 | 
					 | 
				
			||||||
from django.urls import reverse_lazy
 | 
					 | 
				
			||||||
from django.contrib.auth.tokens import PasswordResetTokenGenerator
 | 
					 | 
				
			||||||
from django.core.mail import EmailMessage
 | 
					 | 
				
			||||||
from .models import ResetToken
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Imports for the extra stuff not in django
 | 
					 | 
				
			||||||
# django_nameko is an extra module, so gets put in here
 | 
					 | 
				
			||||||
from base64 import b64encode, b64decode
 | 
					 | 
				
			||||||
from datetime import datetime
 | 
					 | 
				
			||||||
from django_nameko import get_pool
 | 
					 | 
				
			||||||
from random import choice, randint
 | 
					 | 
				
			||||||
import string
 | 
					 | 
				
			||||||
from configparser import ConfigParser
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
config = ConfigParser()
 | 
					 | 
				
			||||||
config.read('userservice.conf')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Check to see if the username is already taken
 | 
					 | 
				
			||||||
# Helper function, not to be set up as a view
 | 
					 | 
				
			||||||
# Check the LDAP if the user exists
 | 
					 | 
				
			||||||
def check_user_exists(username):
 | 
					 | 
				
			||||||
    with get_pool().next() as rpc:
 | 
					 | 
				
			||||||
        return rpc.userlookup.lookup(username)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# 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))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# The index page 
 | 
					 | 
				
			||||||
# If there's a session open, it will give the user the options he/she/it can do, if not,
 | 
					 | 
				
			||||||
# it will show a landing page explaining what this is and prompt them to login
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class Index(View):
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    # Basic binary choice, if it is an authenticated user, go straight to the options page,
 | 
					 | 
				
			||||||
    # if not, then show the landing page
 | 
					 | 
				
			||||||
    def get(self, request):
 | 
					 | 
				
			||||||
        if request.user.is_authenticated:
 | 
					 | 
				
			||||||
            return render(request, 'useroptions.html', { 'user': request.user } )
 | 
					 | 
				
			||||||
        return render(request, 'landing.html')
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    # Basically does the same as the GET request, just with trying to login the user beforehand
 | 
					 | 
				
			||||||
    # Shows an errorpage if authentication fails, since just looping to the landing page
 | 
					 | 
				
			||||||
    # would be frustrating
 | 
					 | 
				
			||||||
    def post(self, request):
 | 
					 | 
				
			||||||
        username = request.POST.get('username')
 | 
					 | 
				
			||||||
        password = request.POST.get('password')
 | 
					 | 
				
			||||||
        pwd = r'%s' % password
 | 
					 | 
				
			||||||
        user = authenticate(request, username=username, password=pwd)
 | 
					 | 
				
			||||||
        if user is not None:
 | 
					 | 
				
			||||||
            login(request, user)
 | 
					 | 
				
			||||||
            return render(request, 'useroptions.html', { 'user': user } )
 | 
					 | 
				
			||||||
        return render(request, 'loginfailed.html')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Registering a user 
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class Register(View):
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Someone wants to register, throw up the page for that
 | 
					 | 
				
			||||||
    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):
 | 
					 | 
				
			||||||
        # message for the error template
 | 
					 | 
				
			||||||
        service = 'register an user'
 | 
					 | 
				
			||||||
        # urlname for 'go back' on the errorpage
 | 
					 | 
				
			||||||
        urlname = 'register'
 | 
					 | 
				
			||||||
        username = request.POST.get('username')
 | 
					 | 
				
			||||||
        if username == "" or not username:
 | 
					 | 
				
			||||||
            return render(request, 'error.html', { 'urlname': urlname, 'service': service, 'error': 'Please supply a username.' } )
 | 
					 | 
				
			||||||
        # Check to see if username is already taken
 | 
					 | 
				
			||||||
        # isalnum() may be a bit harsh, but is the most logical choice to make sure it's a username we
 | 
					 | 
				
			||||||
        # can use
 | 
					 | 
				
			||||||
        if not username.isalnum():
 | 
					 | 
				
			||||||
            return render(request, 'error.html', { 'urlname': urlname, 'service': service, 'error': 'Username has to be alphanumeric.' } )
 | 
					 | 
				
			||||||
        elif check_user_exists(username):
 | 
					 | 
				
			||||||
            return render(request, 'error.html', { 'urlname': urlname, 'service': service, 'error': 'User already exists.' } )
 | 
					 | 
				
			||||||
        password1 = request.POST.get('password1')
 | 
					 | 
				
			||||||
        password2 = request.POST.get('password2')
 | 
					 | 
				
			||||||
        # check if the supplied passwords match
 | 
					 | 
				
			||||||
        if password1 != password2:
 | 
					 | 
				
			||||||
            return render(request, 'error.html', { 'urlname': urlname, 'service': service, 
 | 
					 | 
				
			||||||
                'error': 'Your passwords did not match. Please supply the same password twice.' } )
 | 
					 | 
				
			||||||
        # check for at least a bit of length on the password
 | 
					 | 
				
			||||||
        if len(password1) < 8:
 | 
					 | 
				
			||||||
            return render(request, 'error.html', { 'urlname': urlname, 'service': service, 
 | 
					 | 
				
			||||||
                'error': 'Your password is too short, please use a longer one. At least 8 characters.' } )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        email = request.POST.get('email')
 | 
					 | 
				
			||||||
        # Is the emailaddress valid?
 | 
					 | 
				
			||||||
        try:
 | 
					 | 
				
			||||||
            validate_email(email)
 | 
					 | 
				
			||||||
        except ValidationError:
 | 
					 | 
				
			||||||
            return render(request, 'error.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:
 | 
					 | 
				
			||||||
            return render(request, 'error.html', { 'urlname': urlname, 'service': service, 'error': 'Please enter your firstname and lastname.' } )
 | 
					 | 
				
			||||||
        # throw it to nameko to create the user
 | 
					 | 
				
			||||||
        with get_pool().next() as rpc:
 | 
					 | 
				
			||||||
            # so nothing strange happens if there are escapable chars
 | 
					 | 
				
			||||||
            pwd = r'%s' % password1
 | 
					 | 
				
			||||||
            result = rpc.createuser.create_user(username, pwd, 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 } )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# 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)
 | 
					 | 
				
			||||||
        with get_pool().next() as rpc:
 | 
					 | 
				
			||||||
            (state, firstname, lastname, email) = rpc.getuserdata.get_data(str(request.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
 | 
					 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
            return render(request, 'changeuserdata.html', { 'user': str(request.user), 'firstname': firstname, 'lastname': lastname, 'email': email } )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # get the change request
 | 
					 | 
				
			||||||
    def post(self, request):
 | 
					 | 
				
			||||||
        # variables for the error page
 | 
					 | 
				
			||||||
        service = 'change user data'
 | 
					 | 
				
			||||||
        urlname = 'change_data'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        # Only logged in users may change data
 | 
					 | 
				
			||||||
        if not request.user.is_authenticated:
 | 
					 | 
				
			||||||
            return render(request, 'mustbeloggedin.html')
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        user = str(request.user)
 | 
					 | 
				
			||||||
        firstname = request.POST.get('firstname')
 | 
					 | 
				
			||||||
        lastname = request.POST.get('lastname')
 | 
					 | 
				
			||||||
        email = request.POST.get('email')
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        # 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:
 | 
					 | 
				
			||||||
            return render(request, 'error.html', { 'urlname': urlname, 'service': service, 'error': 'The supplied email address is invalid.' } )
 | 
					 | 
				
			||||||
        # Trying to change the data
 | 
					 | 
				
			||||||
        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 } )
 | 
					 | 
				
			||||||
        # Data change did not work, display error
 | 
					 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
            return render(request, 'error.html', { 'urlname': urlname, 'service': service, 'error': result } )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Resets the password for a user
 | 
					 | 
				
			||||||
# Sends email to the user with a link to reset the password
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class ResetPassword(View):
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Presents the form with some information
 | 
					 | 
				
			||||||
    def get(self, request):
 | 
					 | 
				
			||||||
        return render(request, 'resetpassword.html')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # gets the data from confirming the reset request and checks if it was not a misclick
 | 
					 | 
				
			||||||
    # (by having the user type in his username)
 | 
					 | 
				
			||||||
    def post(self, request):
 | 
					 | 
				
			||||||
        urlname = 'reset_password'
 | 
					 | 
				
			||||||
        service = 'send a password reset request'
 | 
					 | 
				
			||||||
        user = request.POST.get('user')
 | 
					 | 
				
			||||||
        # First, check if the user exists
 | 
					 | 
				
			||||||
        if not check_user_exists(user):
 | 
					 | 
				
			||||||
            return render(request, 'error.html', { 'urlname': urlname, 'service': service, 'error': 'The user does not exist.' } )
 | 
					 | 
				
			||||||
        # 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
 | 
					 | 
				
			||||||
        if state == "error" or email == 'No email given' or not email:
 | 
					 | 
				
			||||||
            return render(request, 'error.html', { 'urlname': urlname, 'service': service, 'error': 'Unable to retrieve email address for user.' } )
 | 
					 | 
				
			||||||
        # Try to send the email out
 | 
					 | 
				
			||||||
        emailsend = self.email(user, email)
 | 
					 | 
				
			||||||
        # 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 } )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Sends an email to the user with the 24h active link for a password reset
 | 
					 | 
				
			||||||
    def email(self, user, email):
 | 
					 | 
				
			||||||
        # 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
 | 
					 | 
				
			||||||
        email_from = 'Userservice at ungleich <%s>' % config['EMAIL']['EMAILFROM']
 | 
					 | 
				
			||||||
        to = ['%s <%s>' % (user, email)]
 | 
					 | 
				
			||||||
        subject = 'Password reset request for %s' % user
 | 
					 | 
				
			||||||
        link = self.build_reset_link(user, creationtime)
 | 
					 | 
				
			||||||
        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
 | 
					 | 
				
			||||||
        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
 | 
					 | 
				
			||||||
        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
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Builds the reset link for the email and puts the token into the database
 | 
					 | 
				
			||||||
    def build_reset_link(self, user, epochutc):
 | 
					 | 
				
			||||||
        # set up the data 
 | 
					 | 
				
			||||||
        host = 'account-staging.ungleich.ch'
 | 
					 | 
				
			||||||
        tokengen = PasswordResetTokenGenerator()
 | 
					 | 
				
			||||||
        # create some noise for use in the tokengenerator
 | 
					 | 
				
			||||||
        pseudouser = PseudoUser()
 | 
					 | 
				
			||||||
        token = tokengen.make_token(pseudouser)
 | 
					 | 
				
			||||||
        buser = bytes(user, 'utf-8')
 | 
					 | 
				
			||||||
        userpart = b64encode(buser)
 | 
					 | 
				
			||||||
        # create entry into the database 
 | 
					 | 
				
			||||||
        newdbentry = ResetToken(user=user, token=token, creation=epochutc)
 | 
					 | 
				
			||||||
        newdbentry.save()
 | 
					 | 
				
			||||||
        # set up the link
 | 
					 | 
				
			||||||
        link = 'https://%s/reset/%s/%s/' % (host, userpart.decode('utf-8'), token)
 | 
					 | 
				
			||||||
        return link
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Catch the resetrequest URL and check it
 | 
					 | 
				
			||||||
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
 | 
					 | 
				
			||||||
        # 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
 | 
					 | 
				
			||||||
        self.clean_db()
 | 
					 | 
				
			||||||
        # If user and token are not supplied by django, it was called from somewhere else, so it's
 | 
					 | 
				
			||||||
        # invalid
 | 
					 | 
				
			||||||
        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')
 | 
					 | 
				
			||||||
        # set checks_out = True if token is found in database
 | 
					 | 
				
			||||||
        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
 | 
					 | 
				
			||||||
        if not checks_out:
 | 
					 | 
				
			||||||
            return HttpResponse('Invalid URL.', status=404)
 | 
					 | 
				
			||||||
        # Token was found, supply the form
 | 
					 | 
				
			||||||
        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'
 | 
					 | 
				
			||||||
        # get the supplied passwords
 | 
					 | 
				
			||||||
        password1 = request.POST.get("password1")
 | 
					 | 
				
			||||||
        password2 = request.POST.get("password2")
 | 
					 | 
				
			||||||
        # get the hidden value of user
 | 
					 | 
				
			||||||
        user = request.POST.get("user")
 | 
					 | 
				
			||||||
        # some checks over the supplied data
 | 
					 | 
				
			||||||
        if user == "" or not user:
 | 
					 | 
				
			||||||
            return render(request, 'error.html', { 'service': service, 'error': 'Something went wrong. Did you use the supplied form?' } )
 | 
					 | 
				
			||||||
        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:
 | 
					 | 
				
			||||||
            return render(request, 'error.html', { 'service': service, 'error': 'The supplied passwords do not match.' } )
 | 
					 | 
				
			||||||
        if len(password1) < 8:
 | 
					 | 
				
			||||||
            return render(request, 'error.html', { 'service': service, 'error': 'The password is too short, please use a longer one. At least 8 characters.' } )
 | 
					 | 
				
			||||||
        # everything checks out, now change the password
 | 
					 | 
				
			||||||
        with get_pool().next() as rpc:
 | 
					 | 
				
			||||||
            pwd = r'%s' % password1
 | 
					 | 
				
			||||||
            result = rpc.changepassword.change_password(user, pwd)
 | 
					 | 
				
			||||||
        # password change successfull
 | 
					 | 
				
			||||||
        if result == True:
 | 
					 | 
				
			||||||
            return render(request, 'changedpassword.html', { 'user': user } )
 | 
					 | 
				
			||||||
        # Something went wrong while changing the password
 | 
					 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
            return render(request, 'error.html', { 'service': service, 'error': result } )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Cleans up outdated tokens
 | 
					 | 
				
			||||||
    def clean_db(self):
 | 
					 | 
				
			||||||
        # 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
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# The logged in user can change the password here
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class ChangePassword(View):
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # 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 } )
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    # 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)
 | 
					 | 
				
			||||||
        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:
 | 
					 | 
				
			||||||
            return render(request, 'error.html', { 'urlname': urlname, 'service': service, 
 | 
					 | 
				
			||||||
                'error': 'Please check if you typed the same password both times for the new password' } )
 | 
					 | 
				
			||||||
        # 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.' } )
 | 
					 | 
				
			||||||
        with get_pool().next() as rpc:
 | 
					 | 
				
			||||||
            # Trying to change the password
 | 
					 | 
				
			||||||
            pwd = r'%s' % password1
 | 
					 | 
				
			||||||
            result = rpc.changepassword.change_password(user, pwd)
 | 
					 | 
				
			||||||
        # 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': 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'
 | 
					 | 
				
			||||||
        service = 'delete an account'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        # Does the user exist?
 | 
					 | 
				
			||||||
        username = request.POST.get('username')
 | 
					 | 
				
			||||||
        if not check_user_exists(username):
 | 
					 | 
				
			||||||
            return render(request, 'error.html', { 'urlname': urlname, 'service': service, 'error': 'Unknown user.' } )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        # 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.' } )
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
        # Try to delete the user
 | 
					 | 
				
			||||||
        with get_pool().next() as rpc:
 | 
					 | 
				
			||||||
            result = rpc.deleteuser.delete_user(username)
 | 
					 | 
				
			||||||
        # User deleted
 | 
					 | 
				
			||||||
        if result == True:
 | 
					 | 
				
			||||||
            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 } )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Log out the session
 | 
					 | 
				
			||||||
class LogOut(View):
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def get(self, request):
 | 
					 | 
				
			||||||
        logout(request)
 | 
					 | 
				
			||||||
        return HttpResponse("You have been logged out.", status=200)
 | 
					 | 
				
			||||||
							
								
								
									
										10
									
								
								dal/env.sample
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
					@ -0,0 +1,10 @@
 | 
				
			||||||
 | 
					# Create .env to be loaded automatically
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					LDAPSERVER="ldap://ldap1.ungleich.ch ldap://ldap2.ungleich.ch"
 | 
				
			||||||
 | 
					LDAPSEARCHUSER="user here"
 | 
				
			||||||
 | 
					LDAPSEARCHUSERPASSWORD="password here"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Space separated list of search bases for users
 | 
				
			||||||
 | 
					LDAPSEARCH="ou=users,dc=ungleich,dc=ch ou=customers,dc=ungleich,dc=ch"
 | 
				
			||||||
 | 
					LDAPCREATE="ou=customers,dc=ungleich,dc=ch"
 | 
				
			||||||
							
								
								
									
										31
									
								
								dal/forms.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
					@ -0,0 +1,31 @@
 | 
				
			||||||
 | 
					from django import forms
 | 
				
			||||||
 | 
					from django.contrib.auth import authenticate
 | 
				
			||||||
 | 
					from django.utils.translation import ugettext_lazy as _
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class LoginForm(forms.Form):
 | 
				
			||||||
 | 
					    username = forms.CharField(widget=forms.TextInput())
 | 
				
			||||||
 | 
					    password = forms.CharField(widget=forms.PasswordInput())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class Meta:
 | 
				
			||||||
 | 
					        fields = ['username', 'password']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def clean(self):
 | 
				
			||||||
 | 
					        username = self.cleaned_data.get('username')
 | 
				
			||||||
 | 
					        password = self.cleaned_data.get('password')
 | 
				
			||||||
 | 
					        if self.errors:
 | 
				
			||||||
 | 
					            return self.cleaned_data
 | 
				
			||||||
 | 
					        is_auth = authenticate(username=username, password=password)
 | 
				
			||||||
 | 
					        if not is_auth:
 | 
				
			||||||
 | 
					            raise forms.ValidationError(
 | 
				
			||||||
 | 
					                _("Your username and/or password were incorrect.")
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					        # elif is_auth.validated == 0:
 | 
				
			||||||
 | 
					        #     raise forms.ValidationError(
 | 
				
			||||||
 | 
					        #         _("Your account is not activated yet.")
 | 
				
			||||||
 | 
					        #     )
 | 
				
			||||||
 | 
					        return self.cleaned_data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def clean_username(self):
 | 
				
			||||||
 | 
					        username = self.cleaned_data.get('username')
 | 
				
			||||||
 | 
					        return username
 | 
				
			||||||
							
								
								
									
										37
									
								
								dal/migrations/0001_initial.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
					@ -0,0 +1,37 @@
 | 
				
			||||||
 | 
					# Generated by Django 2.1.7 on 2019-02-24 17:35
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import dal.models
 | 
				
			||||||
 | 
					from django.conf import settings
 | 
				
			||||||
 | 
					from django.db import migrations, models
 | 
				
			||||||
 | 
					import django.db.models.deletion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Migration(migrations.Migration):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    initial = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    dependencies = [
 | 
				
			||||||
 | 
					        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    operations = [
 | 
				
			||||||
 | 
					        migrations.CreateModel(
 | 
				
			||||||
 | 
					            name='ResetToken',
 | 
				
			||||||
 | 
					            fields=[
 | 
				
			||||||
 | 
					                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
 | 
				
			||||||
 | 
					                ('user', models.CharField(max_length=100)),
 | 
				
			||||||
 | 
					                ('token', models.CharField(max_length=255)),
 | 
				
			||||||
 | 
					                ('creation', models.BigIntegerField()),
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					        migrations.CreateModel(
 | 
				
			||||||
 | 
					            name='UserAccountValidationDetail',
 | 
				
			||||||
 | 
					            fields=[
 | 
				
			||||||
 | 
					                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
 | 
				
			||||||
 | 
					                ('validated', models.IntegerField(choices=[(0, 'Not validated'), (1, 'Validated')], default=0)),
 | 
				
			||||||
 | 
					                ('validation_slug', models.CharField(db_index=True, default=dal.models.get_validation_slug, max_length=50, unique=True)),
 | 
				
			||||||
 | 
					                ('date_validation_started', models.DateTimeField(auto_now_add=True)),
 | 
				
			||||||
 | 
					                ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
							
								
								
									
										0
									
								
								dal/migrations/__init__.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										32
									
								
								dal/models.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
					@ -0,0 +1,32 @@
 | 
				
			||||||
 | 
					from django.db import models
 | 
				
			||||||
 | 
					from django.contrib.auth.hashers import make_password
 | 
				
			||||||
 | 
					from django.contrib.auth.models import User
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Basic DB to correlate tokens, users and creation time
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ResetToken(models.Model):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # users wouldn't use usernames >100 chars
 | 
				
			||||||
 | 
					    user = models.CharField(max_length=100)
 | 
				
			||||||
 | 
					    # Not so sure about tokens, better make it big
 | 
				
			||||||
 | 
					    # should be <100, but big usernames make bigger tokens
 | 
				
			||||||
 | 
					    # if I read that correctly
 | 
				
			||||||
 | 
					    token = models.CharField(max_length=255)
 | 
				
			||||||
 | 
					    # creation time in epoch (UTC)
 | 
				
			||||||
 | 
					    # BigInt just so we are save for the next few decades ;)
 | 
				
			||||||
 | 
					    creation = models.BigIntegerField()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def get_validation_slug():
 | 
				
			||||||
 | 
					    return make_password(None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class UserAccountValidationDetail(models.Model):
 | 
				
			||||||
 | 
					    user = models.OneToOneField(User, on_delete=models.CASCADE)
 | 
				
			||||||
 | 
					    VALIDATED_CHOICES = ((0, 'Not validated'), (1, 'Validated'))
 | 
				
			||||||
 | 
					    validated = models.IntegerField(choices=VALIDATED_CHOICES, default=0)
 | 
				
			||||||
 | 
					    validation_slug = models.CharField(
 | 
				
			||||||
 | 
					        db_index=True, unique=True, max_length=50,
 | 
				
			||||||
 | 
					        default=get_validation_slug
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    date_validation_started = models.DateTimeField(auto_now_add=True)
 | 
				
			||||||
							
								
								
									
										218
									
								
								dal/settings.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
					@ -0,0 +1,218 @@
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					Django settings for dal project.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Generated by 'django-admin startproject' using Django 1.10.7.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					For more information on this file, see
 | 
				
			||||||
 | 
					https://docs.djangoproject.com/en/1.10/topics/settings/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					For the full list of settings and their values, see
 | 
				
			||||||
 | 
					https://docs.djangoproject.com/en/1.10/ref/settings/
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import os
 | 
				
			||||||
 | 
					from decouple import config, Csv
 | 
				
			||||||
 | 
					import ldap
 | 
				
			||||||
 | 
					from django_auth_ldap.config import LDAPSearch, LDAPSearchUnion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# LDAP setup
 | 
				
			||||||
 | 
					LDAP_SERVER = config('LDAP_SERVER')
 | 
				
			||||||
 | 
					AUTH_LDAP_SERVER_URI = config('LDAPSERVER')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					LDAP_ADMIN_DN = config('LDAP_ADMIN_DN')
 | 
				
			||||||
 | 
					LDAP_ADMIN_PASSWORD = config('LDAP_ADMIN_PASSWORD')
 | 
				
			||||||
 | 
					AUTH_LDAP_BIND_DN = LDAP_ADMIN_DN
 | 
				
			||||||
 | 
					AUTH_LDAP_BIND_PASSWORD = LDAP_ADMIN_PASSWORD
 | 
				
			||||||
 | 
					AUTH_LDAP_SERVER = AUTH_LDAP_SERVER_URI
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					LDAP_CUSTOMER_DN = config('LDAP_CUSTOMER_DN')
 | 
				
			||||||
 | 
					LDAP_USERS_DN = config('LDAP_USERS_DN')
 | 
				
			||||||
 | 
					LDAP_CUSTOMER_GROUP_ID = config('LDAP_CUSTOMER_GROUP_ID', cast=int)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					LDAP_MAX_UID_FILE_PATH = config(
 | 
				
			||||||
 | 
					    'LDAP_MAX_UID_FILE_PATH',
 | 
				
			||||||
 | 
					    default=os.path.join(os.path.abspath(
 | 
				
			||||||
 | 
					        os.path.dirname(__file__)), 'ldap_max_uid_file'
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					LDAP_DEFAULT_START_UID = config('LDAP_DEFAULT_START_UID', cast=int)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Search union over OUs
 | 
				
			||||||
 | 
					search_base = config('LDAPSEARCH').split()
 | 
				
			||||||
 | 
					search_base_ldap = [ LDAPSearch(x, ldap.SCOPE_SUBTREE, "(uid=%(user)s)") for x in search_base ]
 | 
				
			||||||
 | 
					AUTH_LDAP_USER_SEARCH = LDAPSearchUnion(*search_base_ldap)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					AUTH_LDAP_START_TLS = config('LDAP_USE_TLS', default=False, cast=bool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DEBUG = config('DEBUG', default=False, cast=bool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					EMAIL_FROM_ADDRESS = config('EMAIL_FROM_ADDRESS')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					EMAIL_HOST = config("EMAIL_HOST", default="localhost")
 | 
				
			||||||
 | 
					EMAIL_PORT = config("EMAIL_PORT", default=25, cast=int)
 | 
				
			||||||
 | 
					EMAIL_USE_TLS = config("EMAIL_USE_TLS", default=True, cast=bool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ALLOWED_HOSTS = config('ALLOWED_HOSTS', cast=Csv())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					INSTALLED_APPS = [
 | 
				
			||||||
 | 
					    'django.contrib.admin',
 | 
				
			||||||
 | 
					    'django.contrib.auth',
 | 
				
			||||||
 | 
					    'django.contrib.contenttypes',
 | 
				
			||||||
 | 
					    'django.contrib.sessions',
 | 
				
			||||||
 | 
					    'django.contrib.messages',
 | 
				
			||||||
 | 
					    'django.contrib.staticfiles',
 | 
				
			||||||
 | 
					    'bootstrap3',
 | 
				
			||||||
 | 
					    'dal',
 | 
				
			||||||
 | 
					    'rest_framework'
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MIDDLEWARE = [
 | 
				
			||||||
 | 
					    'django.middleware.security.SecurityMiddleware',
 | 
				
			||||||
 | 
					    'django.contrib.sessions.middleware.SessionMiddleware',
 | 
				
			||||||
 | 
					    'django.middleware.common.CommonMiddleware',
 | 
				
			||||||
 | 
					    'django.middleware.csrf.CsrfViewMiddleware',
 | 
				
			||||||
 | 
					    'django.contrib.auth.middleware.AuthenticationMiddleware',
 | 
				
			||||||
 | 
					    'django.contrib.messages.middleware.MessageMiddleware',
 | 
				
			||||||
 | 
					    'django.middleware.clickjacking.XFrameOptionsMiddleware',
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					AUTHENTICATION_BACKENDS = (
 | 
				
			||||||
 | 
					    'django_auth_ldap.backend.LDAPBackend',
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ROOT_URLCONF = 'dal.urls'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEMPLATES = [
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        'BACKEND': 'django.template.backends.django.DjangoTemplates',
 | 
				
			||||||
 | 
					        'DIRS': [],
 | 
				
			||||||
 | 
					        'APP_DIRS': True,
 | 
				
			||||||
 | 
					        'OPTIONS': {
 | 
				
			||||||
 | 
					            'context_processors': [
 | 
				
			||||||
 | 
					                'django.template.context_processors.debug',
 | 
				
			||||||
 | 
					                'django.template.context_processors.request',
 | 
				
			||||||
 | 
					                'django.contrib.auth.context_processors.auth',
 | 
				
			||||||
 | 
					                'django.contrib.messages.context_processors.messages',
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					WSGI_APPLICATION = 'dal.wsgi.application'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Password validation
 | 
				
			||||||
 | 
					# https://docs.djangoproject.com/en/1.10/ref/settings/#auth-password-validators
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					AUTH_PASSWORD_VALIDATORS = [
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Internationalization
 | 
				
			||||||
 | 
					# https://docs.djangoproject.com/en/1.10/topics/i18n/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					LANGUAGE_CODE = 'en-us'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TIME_ZONE = 'UTC'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					USE_I18N = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					USE_L10N = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					USE_TZ = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Static files (CSS, JavaScript, Images)
 | 
				
			||||||
 | 
					# https://docs.djangoproject.com/en/1.10/howto/static-files/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					STATIC_URL = '/static/'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					############################# To be fixed
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					STATIC_ROOT= os.path.join(BASE_DIR, 'static/')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Database
 | 
				
			||||||
 | 
					# https://docs.djangoproject.com/en/1.10/ref/settings/#databases
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DATABASES = {
 | 
				
			||||||
 | 
					    'default': {
 | 
				
			||||||
 | 
					        'ENGINE': 'django.db.backends.sqlite3',
 | 
				
			||||||
 | 
					        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					SECRET_KEY = config('SECRET_KEY')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					AUTH_LDAP_USER_ATTR_MAP = {
 | 
				
			||||||
 | 
					    "first_name": "givenName",
 | 
				
			||||||
 | 
					    "last_name": "sn",
 | 
				
			||||||
 | 
					    "email": "mail"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ENTIRE_SEARCH_BASE = config("ENTIRE_SEARCH_BASE")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					LOGGING = {
 | 
				
			||||||
 | 
					    'disable_existing_loggers': False,
 | 
				
			||||||
 | 
					    'version': 1,
 | 
				
			||||||
 | 
					    'formatters': {
 | 
				
			||||||
 | 
					        'standard': {
 | 
				
			||||||
 | 
					            'format': '%(asctime)s %(levelname)s %(name)s %(funcName)s %(lineno)d: %(message)s'
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    'handlers': {
 | 
				
			||||||
 | 
					        'default': {
 | 
				
			||||||
 | 
					            'level': 'DEBUG',
 | 
				
			||||||
 | 
					            'class': 'logging.handlers.RotatingFileHandler',
 | 
				
			||||||
 | 
					            'filename': 'logs/debug.log',
 | 
				
			||||||
 | 
					            'maxBytes': 1024*1024*5,
 | 
				
			||||||
 | 
					            'backupCount': 10,
 | 
				
			||||||
 | 
					            'formatter': 'standard',
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        'console': {
 | 
				
			||||||
 | 
					            'class': 'logging.StreamHandler',
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if config('ENABLE_DEBUG_LOG', default=False, cast=bool):
 | 
				
			||||||
 | 
					    loggers_dict = {}
 | 
				
			||||||
 | 
					    modules_to_log_list = config(
 | 
				
			||||||
 | 
					        'MODULES_TO_LOG', default='django', cast=Csv()
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    for custom_module in modules_to_log_list:
 | 
				
			||||||
 | 
					        logger_item = {
 | 
				
			||||||
 | 
					            custom_module: {
 | 
				
			||||||
 | 
					                'handlers': ['default'],
 | 
				
			||||||
 | 
					                'level': 'INFO',
 | 
				
			||||||
 | 
					                'propagate': True
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        loggers_dict.update(logger_item)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    LOGGING['loggers'] = loggers_dict
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if 'ldap3' in modules_to_log_list:
 | 
				
			||||||
 | 
					        from ldap3.utils.log import (
 | 
				
			||||||
 | 
					            set_library_log_detail_level, OFF, BASIC, NETWORK, EXTENDED
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        set_library_log_detail_level(BASIC)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					REST_FRAMEWORK = {
 | 
				
			||||||
 | 
					    'DEFAULT_RENDERER_CLASSES': (
 | 
				
			||||||
 | 
					        'rest_framework.renderers.JSONRenderer',
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										4
									
								
								dal/static/datacenterlight/font-awesome/css/font-awesome.min.css
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| 
		 Before Width: | Height: | Size: 434 KiB After Width: | Height: | Size: 434 KiB  | 
| 
		 Before Width: | Height: | Size: 106 KiB After Width: | Height: | Size: 106 KiB  | 
| 
		 Before Width: | Height: | Size: 9.7 KiB After Width: | Height: | Size: 9.7 KiB  | 
| 
		 Before Width: | Height: | Size: 394 KiB After Width: | Height: | Size: 394 KiB  | 
| 
		 Before Width: | Height: | Size: 298 KiB After Width: | Height: | Size: 298 KiB  | 
| 
		 Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 50 KiB  | 
| 
		 Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB  | 
| 
		 Before Width: | Height: | Size: 8.9 KiB After Width: | Height: | Size: 8.9 KiB  | 
| 
		 Before Width: | Height: | Size: 685 KiB After Width: | Height: | Size: 685 KiB  | 
| 
		 Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 5.8 KiB  |