From ace2fa6eb98935c373c4c794255b249ce09478c6 Mon Sep 17 00:00:00 2001 From: PCoder <purple.coder@yahoo.co.uk> Date: Sun, 17 Feb 2019 17:43:06 +0100 Subject: [PATCH 01/54] Move project files to root directory --- dal/{dal => }/__init__.py | 0 .../font-awesome/css/font-awesome.min.css | 4 ---- dal/{dal => }/env.sample | 0 dal/{dal => }/models.py | 0 dal/{dal => }/settings.py | 6 +++--- .../datacenterlight/css/bootstrap-3.3.7.min.css | 0 dal/{dal => }/static/datacenterlight/css/cms.css | 0 dal/{dal => }/static/datacenterlight/css/common.css | 0 .../static/datacenterlight/css/header-slider.css | 0 .../static/datacenterlight/css/hosting.css | 0 .../static/datacenterlight/css/landing-page.css | 0 .../font-awesome/css/font-awesome.min.css | 4 ++++ .../font-awesome/fonts/FontAwesome.otf | Bin .../font-awesome/fonts/fontawesome-webfont.eot | Bin .../font-awesome/fonts/fontawesome-webfont.svg | 0 .../font-awesome/fonts/fontawesome-webfont.ttf | Bin .../font-awesome/fonts/fontawesome-webfont.woff | Bin .../font-awesome/fonts/fontawesome-webfont.woff2 | Bin .../font-awesome/less/bordered-pulled.less | 0 .../datacenterlight/font-awesome/less/core.less | 0 .../font-awesome/less/fixed-width.less | 0 .../font-awesome/less/font-awesome.less | 0 .../datacenterlight/font-awesome/less/icons.less | 0 .../datacenterlight/font-awesome/less/larger.less | 0 .../datacenterlight/font-awesome/less/list.less | 0 .../datacenterlight/font-awesome/less/mixins.less | 0 .../datacenterlight/font-awesome/less/path.less | 0 .../font-awesome/less/rotated-flipped.less | 0 .../datacenterlight/font-awesome/less/spinning.less | 0 .../datacenterlight/font-awesome/less/stacked.less | 0 .../font-awesome/less/variables.less | 0 .../font-awesome/scss/_bordered-pulled.scss | 0 .../datacenterlight/font-awesome/scss/_core.scss | 0 .../font-awesome/scss/_fixed-width.scss | 0 .../datacenterlight/font-awesome/scss/_icons.scss | 0 .../datacenterlight/font-awesome/scss/_larger.scss | 0 .../datacenterlight/font-awesome/scss/_list.scss | 0 .../datacenterlight/font-awesome/scss/_mixins.scss | 0 .../datacenterlight/font-awesome/scss/_path.scss | 0 .../font-awesome/scss/_rotated-flipped.scss | 0 .../font-awesome/scss/_spinning.scss | 0 .../datacenterlight/font-awesome/scss/_stacked.scss | 0 .../font-awesome/scss/_variables.scss | 0 .../font-awesome/scss/font-awesome.scss | 0 .../fonts/Montserrat/Montserrat-Black.ttf | Bin .../fonts/Montserrat/Montserrat-BlackItalic.ttf | Bin .../fonts/Montserrat/Montserrat-Bold.ttf | Bin .../fonts/Montserrat/Montserrat-BoldItalic.ttf | Bin .../fonts/Montserrat/Montserrat-ExtraBold.ttf | Bin .../fonts/Montserrat/Montserrat-ExtraBoldItalic.ttf | Bin .../fonts/Montserrat/Montserrat-ExtraLight.ttf | Bin .../Montserrat/Montserrat-ExtraLightItalic.ttf | Bin .../fonts/Montserrat/Montserrat-Italic.ttf | Bin .../fonts/Montserrat/Montserrat-Light.ttf | Bin .../fonts/Montserrat/Montserrat-LightItalic.ttf | Bin .../fonts/Montserrat/Montserrat-Medium.ttf | Bin .../fonts/Montserrat/Montserrat-MediumItalic.ttf | Bin .../fonts/Montserrat/Montserrat-Regular.ttf | Bin .../fonts/Montserrat/Montserrat-SemiBold.ttf | Bin .../fonts/Montserrat/Montserrat-SemiBoldItalic.ttf | Bin .../fonts/Montserrat/Montserrat-Thin.ttf | Bin .../fonts/Montserrat/Montserrat-ThinItalic.ttf | Bin .../static/datacenterlight/fonts/Montserrat/OFL.txt | 0 .../fonts/glyphicons-halflings-regular.eot | Bin .../fonts/glyphicons-halflings-regular.svg | 0 .../fonts/glyphicons-halflings-regular.ttf | Bin .../fonts/glyphicons-halflings-regular.woff | Bin .../fonts/glyphicons-halflings-regular.woff2 | Bin .../static/datacenterlight/img/Ceph_Logo.png | Bin .../static/datacenterlight/img/banner-bg copy.jpg | Bin .../static/datacenterlight/img/banner-bg.jpg | Bin dal/{dal => }/static/datacenterlight/img/bg.png | Bin .../static/datacenterlight/img/cdistbyungleich.png | Bin .../static/datacenterlight/img/checkmark.png | Bin .../static/datacenterlight/img/configure.jpg | Bin .../static/datacenterlight/img/datacenterlight.png | Bin .../static/datacenterlight/img/dcl-email-bg.jpg | Bin .../static/datacenterlight/img/deluxeroom.jpg | Bin dal/{dal => }/static/datacenterlight/img/devuan.png | Bin dal/{dal => }/static/datacenterlight/img/django.png | Bin dal/{dal => }/static/datacenterlight/img/dog.png | Bin .../static/datacenterlight/img/economy.jpg | Bin .../static/datacenterlight/img/facebook_logo.svg | 0 .../static/datacenterlight/img/favicon.ico | Bin .../static/datacenterlight/img/header-bg.jpg | Bin dal/{dal => }/static/datacenterlight/img/home.png | Bin dal/{dal => }/static/datacenterlight/img/how.png | Bin dal/{dal => }/static/datacenterlight/img/how1.png | Bin dal/{dal => }/static/datacenterlight/img/how2.png | Bin dal/{dal => }/static/datacenterlight/img/how3.png | Bin dal/{dal => }/static/datacenterlight/img/how4.png | Bin .../static/datacenterlight/img/intro-bg.jpg | Bin dal/{dal => }/static/datacenterlight/img/ipad.png | Bin .../static/datacenterlight/img/loading.gif | Bin .../static/datacenterlight/img/logo_black.png | Bin .../static/datacenterlight/img/logo_black.svg | 0 .../static/datacenterlight/img/logo_white.svg | 0 .../static/datacenterlight/img/opennebula.png | Bin .../static/datacenterlight/img/pattern.jpg | Bin dal/{dal => }/static/datacenterlight/img/phones.png | Bin .../static/datacenterlight/img/presidentialroom.jpg | Bin .../static/datacenterlight/img/prometheus.png | Bin .../static/datacenterlight/img/python-logo.png | Bin dal/{dal => }/static/datacenterlight/img/ssd.jpg | Bin .../static/datacenterlight/img/standardroom.jpg | Bin dal/{dal => }/static/datacenterlight/img/tayga.png | Bin dal/{dal => }/static/datacenterlight/img/ubuntu.png | Bin .../datacenterlight/js/bootstrap-3.3.7.min.js | 0 dal/{dal => }/static/datacenterlight/js/form.js | 0 .../static/datacenterlight/js/jquery-2.2.4.min.js | 0 dal/{dal => }/static/datacenterlight/js/main.js | 0 dal/{dal => }/static/hosting/card-django.png | Bin dal/{dal => }/static/hosting/card-nodejs.png | Bin dal/{dal => }/static/hosting/card-rails.png | Bin dal/{dal => }/static/hosting/css/commons.css | 0 dal/{dal => }/static/hosting/css/dashboard.css | 0 dal/{dal => }/static/hosting/css/landing-page.css | 0 dal/{dal => }/static/hosting/css/nodejshosting.css | 0 dal/{dal => }/static/hosting/css/order.css | 0 dal/{dal => }/static/hosting/css/orders.css | 0 dal/{dal => }/static/hosting/css/payment.css | 0 .../static/hosting/css/price_calculator.css | 0 dal/{dal => }/static/hosting/css/pricing.css | 0 dal/{dal => }/static/hosting/css/user_keys.css | 0 .../static/hosting/css/virtual-machine.css | 0 dal/{dal => }/static/hosting/django-intro-bg.png | Bin .../static/hosting/img/24-hours-support.svg | 0 dal/{dal => }/static/hosting/img/CH_flag.png | Bin dal/{dal => }/static/hosting/img/DE_flag.png | Bin dal/{dal => }/static/hosting/img/ajax-loader.gif | Bin dal/{dal => }/static/hosting/img/auth-bg-sm.jpg | Bin dal/{dal => }/static/hosting/img/auth-bg.jpg | Bin dal/{dal => }/static/hosting/img/banner-bg copy.jpg | Bin dal/{dal => }/static/hosting/img/banner-bg.jpg | Bin dal/{dal => }/static/hosting/img/billing.svg | 0 dal/{dal => }/static/hosting/img/card-django.png | Bin dal/{dal => }/static/hosting/img/card-nodejs.png | Bin dal/{dal => }/static/hosting/img/card-rails.png | Bin dal/{dal => }/static/hosting/img/checkmark.png | Bin dal/{dal => }/static/hosting/img/configure.jpg | Bin dal/{dal => }/static/hosting/img/connected.svg | 0 dal/{dal => }/static/hosting/img/copy.svg | 0 .../static/hosting/img/dashboard_settings.svg | 0 dal/{dal => }/static/hosting/img/delete.svg | 0 dal/{dal => }/static/hosting/img/deluxeroom.jpg | Bin .../static/hosting/img/django-intro-bg.png | Bin dal/{dal => }/static/hosting/img/dog.png | Bin dal/{dal => }/static/hosting/img/economy.jpg | Bin dal/{dal => }/static/hosting/img/favicon.ico | Bin dal/{dal => }/static/hosting/img/g222.png | Bin dal/{dal => }/static/hosting/img/header-bg.jpg | Bin dal/{dal => }/static/hosting/img/home.png | Bin dal/{dal => }/static/hosting/img/how.png | Bin dal/{dal => }/static/hosting/img/how1.png | Bin dal/{dal => }/static/hosting/img/how2.png | Bin dal/{dal => }/static/hosting/img/how4.png | Bin dal/{dal => }/static/hosting/img/icon-pdf.svg | 0 dal/{dal => }/static/hosting/img/icon-print.svg | 0 dal/{dal => }/static/hosting/img/intro-bg.jpg | Bin dal/{dal => }/static/hosting/img/ipad.png | Bin dal/{dal => }/static/hosting/img/key.svg | 0 dal/{dal => }/static/hosting/img/login-bg.jpg | Bin dal/{dal => }/static/hosting/img/logo_black.png | Bin dal/{dal => }/static/hosting/img/logo_black.svg | 0 dal/{dal => }/static/hosting/img/logo_white.svg | 0 .../static/hosting/img/nodejs-intro-bg.png | Bin dal/{dal => }/static/hosting/img/pattern.jpg | Bin .../static/hosting/img/pattern_original.jpg | Bin dal/{dal => }/static/hosting/img/phones.png | Bin dal/{dal => }/static/hosting/img/plusVM.svg | 0 .../static/hosting/img/presidentialroom.jpg | Bin dal/{dal => }/static/hosting/img/rails-intro-bg.png | Bin dal/{dal => }/static/hosting/img/settings.svg | 0 dal/{dal => }/static/hosting/img/shopping-cart.svg | 0 dal/{dal => }/static/hosting/img/signup-bg.png | Bin dal/{dal => }/static/hosting/img/standardroom.jpg | Bin dal/{dal => }/static/hosting/img/ubuntu.png | Bin dal/{dal => }/static/hosting/img/vm.svg | 0 dal/{dal => }/static/hosting/js/createvm.js | 0 dal/{dal => }/static/hosting/js/gen-ssh-key.js | 0 dal/{dal => }/static/hosting/js/html2canvas.min.js | 0 dal/{dal => }/static/hosting/js/html2pdf.min.js | 0 dal/{dal => }/static/hosting/js/initial.js | 0 dal/{dal => }/static/hosting/js/order.js | 0 dal/{dal => }/static/hosting/js/payment.js | 0 dal/{dal => }/static/hosting/js/pricing.js | 0 .../static/hosting/js/virtual_machine_detail.js | 0 dal/{dal => }/static/hosting/nodejs-intro-bg.png | Bin dal/{dal => }/static/hosting/rails-intro-bg.png | Bin dal/{dal => }/templates/base.html | 0 dal/{dal => }/templates/base_short.html | 0 dal/{dal => }/templates/changeddata.html | 0 dal/{dal => }/templates/changedpassword.html | 0 dal/{dal => }/templates/changepassword.html | 0 dal/{dal => }/templates/changeuserdata.html | 0 dal/{dal => }/templates/deleteaccount.html | 0 dal/{dal => }/templates/deleteduser.html | 0 dal/{dal => }/templates/error.html | 0 dal/{dal => }/templates/hosting_login.html | 0 dal/{dal => }/templates/includes/_card_input.html | 0 dal/{dal => }/templates/includes/_contact.html | 0 dal/{dal => }/templates/includes/_footer.html | 0 dal/{dal => }/templates/includes/_header.html | 0 dal/{dal => }/templates/includes/_messages.html | 0 dal/{dal => }/templates/includes/_navbar.html | 0 .../templates/includes/_navbar_transparent.html | 0 dal/{dal => }/templates/includes/_navbar_user.html | 0 .../templates/includes/_our_infrastructure.html | 0 dal/{dal => }/templates/includes/_pricing.html | 0 .../templates/includes/_your_infrastructure.html | 0 dal/{dal => }/templates/landing.html | 0 dal/{dal => }/templates/loginfailed.html | 0 dal/{dal => }/templates/mustbeloggedin.html | 0 dal/{dal => }/templates/registeruser.html | 0 dal/{dal => }/templates/resetpassword.html | 0 dal/{dal => }/templates/resetpasswordnew.html | 0 dal/{dal => }/templates/send_resetrequest.html | 0 dal/{dal => }/templates/usercreated.html | 0 dal/{dal => }/templates/useroptions.html | 0 dal/{dal => }/urls.py | 0 dal/{dal => }/views.py | 0 dal/{dal => }/wsgi.py | 0 dal/manage.py => manage.py | 0 223 files changed, 7 insertions(+), 7 deletions(-) rename dal/{dal => }/__init__.py (100%) delete mode 100644 dal/dal/static/datacenterlight/font-awesome/css/font-awesome.min.css rename dal/{dal => }/env.sample (100%) rename dal/{dal => }/models.py (100%) rename dal/{dal => }/settings.py (95%) rename dal/{dal => }/static/datacenterlight/css/bootstrap-3.3.7.min.css (100%) rename dal/{dal => }/static/datacenterlight/css/cms.css (100%) rename dal/{dal => }/static/datacenterlight/css/common.css (100%) rename dal/{dal => }/static/datacenterlight/css/header-slider.css (100%) rename dal/{dal => }/static/datacenterlight/css/hosting.css (100%) rename dal/{dal => }/static/datacenterlight/css/landing-page.css (100%) create mode 100644 dal/static/datacenterlight/font-awesome/css/font-awesome.min.css rename dal/{dal => }/static/datacenterlight/font-awesome/fonts/FontAwesome.otf (100%) rename dal/{dal => }/static/datacenterlight/font-awesome/fonts/fontawesome-webfont.eot (100%) rename dal/{dal => }/static/datacenterlight/font-awesome/fonts/fontawesome-webfont.svg (100%) rename dal/{dal => }/static/datacenterlight/font-awesome/fonts/fontawesome-webfont.ttf (100%) rename dal/{dal => }/static/datacenterlight/font-awesome/fonts/fontawesome-webfont.woff (100%) rename dal/{dal => }/static/datacenterlight/font-awesome/fonts/fontawesome-webfont.woff2 (100%) rename dal/{dal => }/static/datacenterlight/font-awesome/less/bordered-pulled.less (100%) rename dal/{dal => }/static/datacenterlight/font-awesome/less/core.less (100%) rename dal/{dal => }/static/datacenterlight/font-awesome/less/fixed-width.less (100%) rename dal/{dal => }/static/datacenterlight/font-awesome/less/font-awesome.less (100%) rename dal/{dal => }/static/datacenterlight/font-awesome/less/icons.less (100%) rename dal/{dal => }/static/datacenterlight/font-awesome/less/larger.less (100%) rename dal/{dal => }/static/datacenterlight/font-awesome/less/list.less (100%) rename dal/{dal => }/static/datacenterlight/font-awesome/less/mixins.less (100%) rename dal/{dal => }/static/datacenterlight/font-awesome/less/path.less (100%) rename dal/{dal => }/static/datacenterlight/font-awesome/less/rotated-flipped.less (100%) rename dal/{dal => }/static/datacenterlight/font-awesome/less/spinning.less (100%) rename dal/{dal => }/static/datacenterlight/font-awesome/less/stacked.less (100%) rename dal/{dal => }/static/datacenterlight/font-awesome/less/variables.less (100%) rename dal/{dal => }/static/datacenterlight/font-awesome/scss/_bordered-pulled.scss (100%) rename dal/{dal => }/static/datacenterlight/font-awesome/scss/_core.scss (100%) rename dal/{dal => }/static/datacenterlight/font-awesome/scss/_fixed-width.scss (100%) rename dal/{dal => }/static/datacenterlight/font-awesome/scss/_icons.scss (100%) rename dal/{dal => }/static/datacenterlight/font-awesome/scss/_larger.scss (100%) rename dal/{dal => }/static/datacenterlight/font-awesome/scss/_list.scss (100%) rename dal/{dal => }/static/datacenterlight/font-awesome/scss/_mixins.scss (100%) rename dal/{dal => }/static/datacenterlight/font-awesome/scss/_path.scss (100%) rename dal/{dal => }/static/datacenterlight/font-awesome/scss/_rotated-flipped.scss (100%) rename dal/{dal => }/static/datacenterlight/font-awesome/scss/_spinning.scss (100%) rename dal/{dal => }/static/datacenterlight/font-awesome/scss/_stacked.scss (100%) rename dal/{dal => }/static/datacenterlight/font-awesome/scss/_variables.scss (100%) rename dal/{dal => }/static/datacenterlight/font-awesome/scss/font-awesome.scss (100%) rename dal/{dal => }/static/datacenterlight/fonts/Montserrat/Montserrat-Black.ttf (100%) rename dal/{dal => }/static/datacenterlight/fonts/Montserrat/Montserrat-BlackItalic.ttf (100%) rename dal/{dal => }/static/datacenterlight/fonts/Montserrat/Montserrat-Bold.ttf (100%) rename dal/{dal => }/static/datacenterlight/fonts/Montserrat/Montserrat-BoldItalic.ttf (100%) rename dal/{dal => }/static/datacenterlight/fonts/Montserrat/Montserrat-ExtraBold.ttf (100%) rename dal/{dal => }/static/datacenterlight/fonts/Montserrat/Montserrat-ExtraBoldItalic.ttf (100%) rename dal/{dal => }/static/datacenterlight/fonts/Montserrat/Montserrat-ExtraLight.ttf (100%) rename dal/{dal => }/static/datacenterlight/fonts/Montserrat/Montserrat-ExtraLightItalic.ttf (100%) rename dal/{dal => }/static/datacenterlight/fonts/Montserrat/Montserrat-Italic.ttf (100%) rename dal/{dal => }/static/datacenterlight/fonts/Montserrat/Montserrat-Light.ttf (100%) rename dal/{dal => }/static/datacenterlight/fonts/Montserrat/Montserrat-LightItalic.ttf (100%) rename dal/{dal => }/static/datacenterlight/fonts/Montserrat/Montserrat-Medium.ttf (100%) rename dal/{dal => }/static/datacenterlight/fonts/Montserrat/Montserrat-MediumItalic.ttf (100%) rename dal/{dal => }/static/datacenterlight/fonts/Montserrat/Montserrat-Regular.ttf (100%) rename dal/{dal => }/static/datacenterlight/fonts/Montserrat/Montserrat-SemiBold.ttf (100%) rename dal/{dal => }/static/datacenterlight/fonts/Montserrat/Montserrat-SemiBoldItalic.ttf (100%) rename dal/{dal => }/static/datacenterlight/fonts/Montserrat/Montserrat-Thin.ttf (100%) rename dal/{dal => }/static/datacenterlight/fonts/Montserrat/Montserrat-ThinItalic.ttf (100%) rename dal/{dal => }/static/datacenterlight/fonts/Montserrat/OFL.txt (100%) rename dal/{dal => }/static/datacenterlight/fonts/glyphicons-halflings-regular.eot (100%) rename dal/{dal => }/static/datacenterlight/fonts/glyphicons-halflings-regular.svg (100%) rename dal/{dal => }/static/datacenterlight/fonts/glyphicons-halflings-regular.ttf (100%) rename dal/{dal => }/static/datacenterlight/fonts/glyphicons-halflings-regular.woff (100%) rename dal/{dal => }/static/datacenterlight/fonts/glyphicons-halflings-regular.woff2 (100%) rename dal/{dal => }/static/datacenterlight/img/Ceph_Logo.png (100%) rename dal/{dal => }/static/datacenterlight/img/banner-bg copy.jpg (100%) rename dal/{dal => }/static/datacenterlight/img/banner-bg.jpg (100%) rename dal/{dal => }/static/datacenterlight/img/bg.png (100%) rename dal/{dal => }/static/datacenterlight/img/cdistbyungleich.png (100%) rename dal/{dal => }/static/datacenterlight/img/checkmark.png (100%) rename dal/{dal => }/static/datacenterlight/img/configure.jpg (100%) rename dal/{dal => }/static/datacenterlight/img/datacenterlight.png (100%) rename dal/{dal => }/static/datacenterlight/img/dcl-email-bg.jpg (100%) rename dal/{dal => }/static/datacenterlight/img/deluxeroom.jpg (100%) rename dal/{dal => }/static/datacenterlight/img/devuan.png (100%) rename dal/{dal => }/static/datacenterlight/img/django.png (100%) rename dal/{dal => }/static/datacenterlight/img/dog.png (100%) rename dal/{dal => }/static/datacenterlight/img/economy.jpg (100%) rename dal/{dal => }/static/datacenterlight/img/facebook_logo.svg (100%) rename dal/{dal => }/static/datacenterlight/img/favicon.ico (100%) rename dal/{dal => }/static/datacenterlight/img/header-bg.jpg (100%) rename dal/{dal => }/static/datacenterlight/img/home.png (100%) rename dal/{dal => }/static/datacenterlight/img/how.png (100%) rename dal/{dal => }/static/datacenterlight/img/how1.png (100%) rename dal/{dal => }/static/datacenterlight/img/how2.png (100%) rename dal/{dal => }/static/datacenterlight/img/how3.png (100%) rename dal/{dal => }/static/datacenterlight/img/how4.png (100%) rename dal/{dal => }/static/datacenterlight/img/intro-bg.jpg (100%) rename dal/{dal => }/static/datacenterlight/img/ipad.png (100%) rename dal/{dal => }/static/datacenterlight/img/loading.gif (100%) rename dal/{dal => }/static/datacenterlight/img/logo_black.png (100%) rename dal/{dal => }/static/datacenterlight/img/logo_black.svg (100%) rename dal/{dal => }/static/datacenterlight/img/logo_white.svg (100%) rename dal/{dal => }/static/datacenterlight/img/opennebula.png (100%) rename dal/{dal => }/static/datacenterlight/img/pattern.jpg (100%) rename dal/{dal => }/static/datacenterlight/img/phones.png (100%) rename dal/{dal => }/static/datacenterlight/img/presidentialroom.jpg (100%) rename dal/{dal => }/static/datacenterlight/img/prometheus.png (100%) rename dal/{dal => }/static/datacenterlight/img/python-logo.png (100%) rename dal/{dal => }/static/datacenterlight/img/ssd.jpg (100%) rename dal/{dal => }/static/datacenterlight/img/standardroom.jpg (100%) rename dal/{dal => }/static/datacenterlight/img/tayga.png (100%) rename dal/{dal => }/static/datacenterlight/img/ubuntu.png (100%) rename dal/{dal => }/static/datacenterlight/js/bootstrap-3.3.7.min.js (100%) rename dal/{dal => }/static/datacenterlight/js/form.js (100%) rename dal/{dal => }/static/datacenterlight/js/jquery-2.2.4.min.js (100%) rename dal/{dal => }/static/datacenterlight/js/main.js (100%) rename dal/{dal => }/static/hosting/card-django.png (100%) rename dal/{dal => }/static/hosting/card-nodejs.png (100%) rename dal/{dal => }/static/hosting/card-rails.png (100%) rename dal/{dal => }/static/hosting/css/commons.css (100%) rename dal/{dal => }/static/hosting/css/dashboard.css (100%) rename dal/{dal => }/static/hosting/css/landing-page.css (100%) rename dal/{dal => }/static/hosting/css/nodejshosting.css (100%) rename dal/{dal => }/static/hosting/css/order.css (100%) rename dal/{dal => }/static/hosting/css/orders.css (100%) rename dal/{dal => }/static/hosting/css/payment.css (100%) rename dal/{dal => }/static/hosting/css/price_calculator.css (100%) rename dal/{dal => }/static/hosting/css/pricing.css (100%) rename dal/{dal => }/static/hosting/css/user_keys.css (100%) rename dal/{dal => }/static/hosting/css/virtual-machine.css (100%) rename dal/{dal => }/static/hosting/django-intro-bg.png (100%) rename dal/{dal => }/static/hosting/img/24-hours-support.svg (100%) rename dal/{dal => }/static/hosting/img/CH_flag.png (100%) rename dal/{dal => }/static/hosting/img/DE_flag.png (100%) rename dal/{dal => }/static/hosting/img/ajax-loader.gif (100%) rename dal/{dal => }/static/hosting/img/auth-bg-sm.jpg (100%) rename dal/{dal => }/static/hosting/img/auth-bg.jpg (100%) rename dal/{dal => }/static/hosting/img/banner-bg copy.jpg (100%) rename dal/{dal => }/static/hosting/img/banner-bg.jpg (100%) rename dal/{dal => }/static/hosting/img/billing.svg (100%) rename dal/{dal => }/static/hosting/img/card-django.png (100%) rename dal/{dal => }/static/hosting/img/card-nodejs.png (100%) rename dal/{dal => }/static/hosting/img/card-rails.png (100%) rename dal/{dal => }/static/hosting/img/checkmark.png (100%) rename dal/{dal => }/static/hosting/img/configure.jpg (100%) rename dal/{dal => }/static/hosting/img/connected.svg (100%) rename dal/{dal => }/static/hosting/img/copy.svg (100%) rename dal/{dal => }/static/hosting/img/dashboard_settings.svg (100%) rename dal/{dal => }/static/hosting/img/delete.svg (100%) rename dal/{dal => }/static/hosting/img/deluxeroom.jpg (100%) rename dal/{dal => }/static/hosting/img/django-intro-bg.png (100%) rename dal/{dal => }/static/hosting/img/dog.png (100%) rename dal/{dal => }/static/hosting/img/economy.jpg (100%) rename dal/{dal => }/static/hosting/img/favicon.ico (100%) rename dal/{dal => }/static/hosting/img/g222.png (100%) rename dal/{dal => }/static/hosting/img/header-bg.jpg (100%) rename dal/{dal => }/static/hosting/img/home.png (100%) rename dal/{dal => }/static/hosting/img/how.png (100%) rename dal/{dal => }/static/hosting/img/how1.png (100%) rename dal/{dal => }/static/hosting/img/how2.png (100%) rename dal/{dal => }/static/hosting/img/how4.png (100%) rename dal/{dal => }/static/hosting/img/icon-pdf.svg (100%) rename dal/{dal => }/static/hosting/img/icon-print.svg (100%) rename dal/{dal => }/static/hosting/img/intro-bg.jpg (100%) rename dal/{dal => }/static/hosting/img/ipad.png (100%) rename dal/{dal => }/static/hosting/img/key.svg (100%) rename dal/{dal => }/static/hosting/img/login-bg.jpg (100%) rename dal/{dal => }/static/hosting/img/logo_black.png (100%) rename dal/{dal => }/static/hosting/img/logo_black.svg (100%) rename dal/{dal => }/static/hosting/img/logo_white.svg (100%) rename dal/{dal => }/static/hosting/img/nodejs-intro-bg.png (100%) rename dal/{dal => }/static/hosting/img/pattern.jpg (100%) rename dal/{dal => }/static/hosting/img/pattern_original.jpg (100%) rename dal/{dal => }/static/hosting/img/phones.png (100%) rename dal/{dal => }/static/hosting/img/plusVM.svg (100%) rename dal/{dal => }/static/hosting/img/presidentialroom.jpg (100%) rename dal/{dal => }/static/hosting/img/rails-intro-bg.png (100%) rename dal/{dal => }/static/hosting/img/settings.svg (100%) rename dal/{dal => }/static/hosting/img/shopping-cart.svg (100%) rename dal/{dal => }/static/hosting/img/signup-bg.png (100%) rename dal/{dal => }/static/hosting/img/standardroom.jpg (100%) rename dal/{dal => }/static/hosting/img/ubuntu.png (100%) rename dal/{dal => }/static/hosting/img/vm.svg (100%) rename dal/{dal => }/static/hosting/js/createvm.js (100%) rename dal/{dal => }/static/hosting/js/gen-ssh-key.js (100%) rename dal/{dal => }/static/hosting/js/html2canvas.min.js (100%) rename dal/{dal => }/static/hosting/js/html2pdf.min.js (100%) rename dal/{dal => }/static/hosting/js/initial.js (100%) rename dal/{dal => }/static/hosting/js/order.js (100%) rename dal/{dal => }/static/hosting/js/payment.js (100%) rename dal/{dal => }/static/hosting/js/pricing.js (100%) rename dal/{dal => }/static/hosting/js/virtual_machine_detail.js (100%) rename dal/{dal => }/static/hosting/nodejs-intro-bg.png (100%) rename dal/{dal => }/static/hosting/rails-intro-bg.png (100%) rename dal/{dal => }/templates/base.html (100%) rename dal/{dal => }/templates/base_short.html (100%) rename dal/{dal => }/templates/changeddata.html (100%) rename dal/{dal => }/templates/changedpassword.html (100%) rename dal/{dal => }/templates/changepassword.html (100%) rename dal/{dal => }/templates/changeuserdata.html (100%) rename dal/{dal => }/templates/deleteaccount.html (100%) rename dal/{dal => }/templates/deleteduser.html (100%) rename dal/{dal => }/templates/error.html (100%) rename dal/{dal => }/templates/hosting_login.html (100%) rename dal/{dal => }/templates/includes/_card_input.html (100%) rename dal/{dal => }/templates/includes/_contact.html (100%) rename dal/{dal => }/templates/includes/_footer.html (100%) rename dal/{dal => }/templates/includes/_header.html (100%) rename dal/{dal => }/templates/includes/_messages.html (100%) rename dal/{dal => }/templates/includes/_navbar.html (100%) rename dal/{dal => }/templates/includes/_navbar_transparent.html (100%) rename dal/{dal => }/templates/includes/_navbar_user.html (100%) rename dal/{dal => }/templates/includes/_our_infrastructure.html (100%) rename dal/{dal => }/templates/includes/_pricing.html (100%) rename dal/{dal => }/templates/includes/_your_infrastructure.html (100%) rename dal/{dal => }/templates/landing.html (100%) rename dal/{dal => }/templates/loginfailed.html (100%) rename dal/{dal => }/templates/mustbeloggedin.html (100%) rename dal/{dal => }/templates/registeruser.html (100%) rename dal/{dal => }/templates/resetpassword.html (100%) rename dal/{dal => }/templates/resetpasswordnew.html (100%) rename dal/{dal => }/templates/send_resetrequest.html (100%) rename dal/{dal => }/templates/usercreated.html (100%) rename dal/{dal => }/templates/useroptions.html (100%) rename dal/{dal => }/urls.py (100%) rename dal/{dal => }/views.py (100%) rename dal/{dal => }/wsgi.py (100%) rename dal/manage.py => manage.py (100%) diff --git a/dal/dal/__init__.py b/dal/__init__.py similarity index 100% rename from dal/dal/__init__.py rename to dal/__init__.py diff --git a/dal/dal/static/datacenterlight/font-awesome/css/font-awesome.min.css b/dal/dal/static/datacenterlight/font-awesome/css/font-awesome.min.css deleted file mode 100644 index 540440c..0000000 --- a/dal/dal/static/datacenterlight/font-awesome/css/font-awesome.min.css +++ /dev/null @@ -1,4 +0,0 @@ -/*! - * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome - * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) - */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.7.0');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.7.0') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff2?v=4.7.0') format('woff2'),url('../fonts/fontawesome-webfont.woff?v=4.7.0') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.7.0') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook-f:before,.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before,.fa-gratipay:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-resistance:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-y-combinator-square:before,.fa-yc-square:before,.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}.fa-buysellads:before{content:"\f20d"}.fa-connectdevelop:before{content:"\f20e"}.fa-dashcube:before{content:"\f210"}.fa-forumbee:before{content:"\f211"}.fa-leanpub:before{content:"\f212"}.fa-sellsy:before{content:"\f213"}.fa-shirtsinbulk:before{content:"\f214"}.fa-simplybuilt:before{content:"\f215"}.fa-skyatlas:before{content:"\f216"}.fa-cart-plus:before{content:"\f217"}.fa-cart-arrow-down:before{content:"\f218"}.fa-diamond:before{content:"\f219"}.fa-ship:before{content:"\f21a"}.fa-user-secret:before{content:"\f21b"}.fa-motorcycle:before{content:"\f21c"}.fa-street-view:before{content:"\f21d"}.fa-heartbeat:before{content:"\f21e"}.fa-venus:before{content:"\f221"}.fa-mars:before{content:"\f222"}.fa-mercury:before{content:"\f223"}.fa-intersex:before,.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-venus-double:before{content:"\f226"}.fa-mars-double:before{content:"\f227"}.fa-venus-mars:before{content:"\f228"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-neuter:before{content:"\f22c"}.fa-genderless:before{content:"\f22d"}.fa-facebook-official:before{content:"\f230"}.fa-pinterest-p:before{content:"\f231"}.fa-whatsapp:before{content:"\f232"}.fa-server:before{content:"\f233"}.fa-user-plus:before{content:"\f234"}.fa-user-times:before{content:"\f235"}.fa-hotel:before,.fa-bed:before{content:"\f236"}.fa-viacoin:before{content:"\f237"}.fa-train:before{content:"\f238"}.fa-subway:before{content:"\f239"}.fa-medium:before{content:"\f23a"}.fa-yc:before,.fa-y-combinator:before{content:"\f23b"}.fa-optin-monster:before{content:"\f23c"}.fa-opencart:before{content:"\f23d"}.fa-expeditedssl:before{content:"\f23e"}.fa-battery-4:before,.fa-battery:before,.fa-battery-full:before{content:"\f240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-battery-2:before,.fa-battery-half:before{content:"\f242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\f243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-mouse-pointer:before{content:"\f245"}.fa-i-cursor:before{content:"\f246"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-sticky-note:before{content:"\f249"}.fa-sticky-note-o:before{content:"\f24a"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-diners-club:before{content:"\f24c"}.fa-clone:before{content:"\f24d"}.fa-balance-scale:before{content:"\f24e"}.fa-hourglass-o:before{content:"\f250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-hourglass:before{content:"\f254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\f255"}.fa-hand-stop-o:before,.fa-hand-paper-o:before{content:"\f256"}.fa-hand-scissors-o:before{content:"\f257"}.fa-hand-lizard-o:before{content:"\f258"}.fa-hand-spock-o:before{content:"\f259"}.fa-hand-pointer-o:before{content:"\f25a"}.fa-hand-peace-o:before{content:"\f25b"}.fa-trademark:before{content:"\f25c"}.fa-registered:before{content:"\f25d"}.fa-creative-commons:before{content:"\f25e"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-tripadvisor:before{content:"\f262"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-get-pocket:before{content:"\f265"}.fa-wikipedia-w:before{content:"\f266"}.fa-safari:before{content:"\f267"}.fa-chrome:before{content:"\f268"}.fa-firefox:before{content:"\f269"}.fa-opera:before{content:"\f26a"}.fa-internet-explorer:before{content:"\f26b"}.fa-tv:before,.fa-television:before{content:"\f26c"}.fa-contao:before{content:"\f26d"}.fa-500px:before{content:"\f26e"}.fa-amazon:before{content:"\f270"}.fa-calendar-plus-o:before{content:"\f271"}.fa-calendar-minus-o:before{content:"\f272"}.fa-calendar-times-o:before{content:"\f273"}.fa-calendar-check-o:before{content:"\f274"}.fa-industry:before{content:"\f275"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-map-o:before{content:"\f278"}.fa-map:before{content:"\f279"}.fa-commenting:before{content:"\f27a"}.fa-commenting-o:before{content:"\f27b"}.fa-houzz:before{content:"\f27c"}.fa-vimeo:before{content:"\f27d"}.fa-black-tie:before{content:"\f27e"}.fa-fonticons:before{content:"\f280"}.fa-reddit-alien:before{content:"\f281"}.fa-edge:before{content:"\f282"}.fa-credit-card-alt:before{content:"\f283"}.fa-codiepie:before{content:"\f284"}.fa-modx:before{content:"\f285"}.fa-fort-awesome:before{content:"\f286"}.fa-usb:before{content:"\f287"}.fa-product-hunt:before{content:"\f288"}.fa-mixcloud:before{content:"\f289"}.fa-scribd:before{content:"\f28a"}.fa-pause-circle:before{content:"\f28b"}.fa-pause-circle-o:before{content:"\f28c"}.fa-stop-circle:before{content:"\f28d"}.fa-stop-circle-o:before{content:"\f28e"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-hashtag:before{content:"\f292"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-percent:before{content:"\f295"}.fa-gitlab:before{content:"\f296"}.fa-wpbeginner:before{content:"\f297"}.fa-wpforms:before{content:"\f298"}.fa-envira:before{content:"\f299"}.fa-universal-access:before{content:"\f29a"}.fa-wheelchair-alt:before{content:"\f29b"}.fa-question-circle-o:before{content:"\f29c"}.fa-blind:before{content:"\f29d"}.fa-audio-description:before{content:"\f29e"}.fa-volume-control-phone:before{content:"\f2a0"}.fa-braille:before{content:"\f2a1"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asl-interpreting:before,.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-deafness:before,.fa-hard-of-hearing:before,.fa-deaf:before{content:"\f2a4"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-signing:before,.fa-sign-language:before{content:"\f2a7"}.fa-low-vision:before{content:"\f2a8"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-pied-piper:before{content:"\f2ae"}.fa-first-order:before{content:"\f2b0"}.fa-yoast:before{content:"\f2b1"}.fa-themeisle:before{content:"\f2b2"}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:"\f2b3"}.fa-fa:before,.fa-font-awesome:before{content:"\f2b4"}.fa-handshake-o:before{content:"\f2b5"}.fa-envelope-open:before{content:"\f2b6"}.fa-envelope-open-o:before{content:"\f2b7"}.fa-linode:before{content:"\f2b8"}.fa-address-book:before{content:"\f2b9"}.fa-address-book-o:before{content:"\f2ba"}.fa-vcard:before,.fa-address-card:before{content:"\f2bb"}.fa-vcard-o:before,.fa-address-card-o:before{content:"\f2bc"}.fa-user-circle:before{content:"\f2bd"}.fa-user-circle-o:before{content:"\f2be"}.fa-user-o:before{content:"\f2c0"}.fa-id-badge:before{content:"\f2c1"}.fa-drivers-license:before,.fa-id-card:before{content:"\f2c2"}.fa-drivers-license-o:before,.fa-id-card-o:before{content:"\f2c3"}.fa-quora:before{content:"\f2c4"}.fa-free-code-camp:before{content:"\f2c5"}.fa-telegram:before{content:"\f2c6"}.fa-thermometer-4:before,.fa-thermometer:before,.fa-thermometer-full:before{content:"\f2c7"}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-thermometer-2:before,.fa-thermometer-half:before{content:"\f2c9"}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:"\f2ca"}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:"\f2cb"}.fa-shower:before{content:"\f2cc"}.fa-bathtub:before,.fa-s15:before,.fa-bath:before{content:"\f2cd"}.fa-podcast:before{content:"\f2ce"}.fa-window-maximize:before{content:"\f2d0"}.fa-window-minimize:before{content:"\f2d1"}.fa-window-restore:before{content:"\f2d2"}.fa-times-rectangle:before,.fa-window-close:before{content:"\f2d3"}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:"\f2d4"}.fa-bandcamp:before{content:"\f2d5"}.fa-grav:before{content:"\f2d6"}.fa-etsy:before{content:"\f2d7"}.fa-imdb:before{content:"\f2d8"}.fa-ravelry:before{content:"\f2d9"}.fa-eercast:before{content:"\f2da"}.fa-microchip:before{content:"\f2db"}.fa-snowflake-o:before{content:"\f2dc"}.fa-superpowers:before{content:"\f2dd"}.fa-wpexplorer:before{content:"\f2de"}.fa-meetup:before{content:"\f2e0"}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto} diff --git a/dal/dal/env.sample b/dal/env.sample similarity index 100% rename from dal/dal/env.sample rename to dal/env.sample diff --git a/dal/dal/models.py b/dal/models.py similarity index 100% rename from dal/dal/models.py rename to dal/models.py diff --git a/dal/dal/settings.py b/dal/settings.py similarity index 95% rename from dal/dal/settings.py rename to dal/settings.py index a284663..7c30a2a 100644 --- a/dal/dal/settings.py +++ b/dal/settings.py @@ -120,7 +120,7 @@ STATIC_URL = '/static/' ############################# To be fixed -STATIC_ROOT = os.path.dirname('/home/downhill/ungleich/vuejsuserservice/dal/dal/static/') +STATIC_ROOT= os.path.join(BASE_DIR, 'static/') # Database # https://docs.djangoproject.com/en/1.10/ref/settings/#databases @@ -131,7 +131,7 @@ DATABASES = { 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), } } -SECRET_KEY = 'rn=f&ecp#&#escxpk!0e%a$i3sbm$z@5+g4h9q+w7-83*f2f-i' +SECRET_KEY = os.environ.get('SECRET_KEY') # SECURITY WARNING: don't run with debug turned on in production! -DEBUG = True +DEBUG = os.environ.get('DEBUG', False) diff --git a/dal/dal/static/datacenterlight/css/bootstrap-3.3.7.min.css b/dal/static/datacenterlight/css/bootstrap-3.3.7.min.css similarity index 100% rename from dal/dal/static/datacenterlight/css/bootstrap-3.3.7.min.css rename to dal/static/datacenterlight/css/bootstrap-3.3.7.min.css diff --git a/dal/dal/static/datacenterlight/css/cms.css b/dal/static/datacenterlight/css/cms.css similarity index 100% rename from dal/dal/static/datacenterlight/css/cms.css rename to dal/static/datacenterlight/css/cms.css diff --git a/dal/dal/static/datacenterlight/css/common.css b/dal/static/datacenterlight/css/common.css similarity index 100% rename from dal/dal/static/datacenterlight/css/common.css rename to dal/static/datacenterlight/css/common.css diff --git a/dal/dal/static/datacenterlight/css/header-slider.css b/dal/static/datacenterlight/css/header-slider.css similarity index 100% rename from dal/dal/static/datacenterlight/css/header-slider.css rename to dal/static/datacenterlight/css/header-slider.css diff --git a/dal/dal/static/datacenterlight/css/hosting.css b/dal/static/datacenterlight/css/hosting.css similarity index 100% rename from dal/dal/static/datacenterlight/css/hosting.css rename to dal/static/datacenterlight/css/hosting.css diff --git a/dal/dal/static/datacenterlight/css/landing-page.css b/dal/static/datacenterlight/css/landing-page.css similarity index 100% rename from dal/dal/static/datacenterlight/css/landing-page.css rename to dal/static/datacenterlight/css/landing-page.css diff --git a/dal/static/datacenterlight/font-awesome/css/font-awesome.min.css b/dal/static/datacenterlight/font-awesome/css/font-awesome.min.css new file mode 100644 index 0000000..248ea7a --- /dev/null +++ b/dal/static/datacenterlight/font-awesome/css/font-awesome.min.css @@ -0,0 +1,4 @@ +/*! + * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.7.0');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.7.0') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff2?v=4.7.0') format('woff2'),url('../fonts/fontawesome-webfont.woff?v=4.7.0') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.7.0') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale} .fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%} .fa-2x{font-size:2em} .fa-3x{font-size:3em} .fa-4x{font-size:4em} .fa-5x{font-size:5em} .fa-fw{width:1.28571429em;text-align:center} .fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none} .fa-ul>li{position:relative} .fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center} .fa-li.fa-lg{left:-1.85714286em} .fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em} .fa-pull-left{float:left} .fa-pull-right{float:right} .fa.fa-pull-left{margin-right:.3em} .fa.fa-pull-right{margin-left:.3em} .pull-right{float:right} .pull-left{float:left} .fa.pull-left{margin-right:.3em} .fa.pull-right{margin-left:.3em} .fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear} .fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)} @-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}} @keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}} .fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)} .fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)} .fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)} .fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)} .fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)} :root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none} .fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle} .fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center} .fa-stack-1x{line-height:inherit} .fa-stack-2x{font-size:2em} .fa-inverse{color:#fff} .fa-glass:before{content:"\f000"} .fa-music:before{content:"\f001"} .fa-search:before{content:"\f002"} .fa-envelope-o:before{content:"\f003"} .fa-heart:before{content:"\f004"} .fa-star:before{content:"\f005"} .fa-star-o:before{content:"\f006"} .fa-user:before{content:"\f007"} .fa-film:before{content:"\f008"} .fa-th-large:before{content:"\f009"} .fa-th:before{content:"\f00a"} .fa-th-list:before{content:"\f00b"} .fa-check:before{content:"\f00c"} .fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"} .fa-search-plus:before{content:"\f00e"} .fa-search-minus:before{content:"\f010"} .fa-power-off:before{content:"\f011"} .fa-signal:before{content:"\f012"} .fa-gear:before,.fa-cog:before{content:"\f013"} .fa-trash-o:before{content:"\f014"} .fa-home:before{content:"\f015"} .fa-file-o:before{content:"\f016"} .fa-clock-o:before{content:"\f017"} .fa-road:before{content:"\f018"} .fa-download:before{content:"\f019"} .fa-arrow-circle-o-down:before{content:"\f01a"} .fa-arrow-circle-o-up:before{content:"\f01b"} .fa-inbox:before{content:"\f01c"} .fa-play-circle-o:before{content:"\f01d"} .fa-rotate-right:before,.fa-repeat:before{content:"\f01e"} .fa-refresh:before{content:"\f021"} .fa-list-alt:before{content:"\f022"} .fa-lock:before{content:"\f023"} .fa-flag:before{content:"\f024"} .fa-headphones:before{content:"\f025"} .fa-volume-off:before{content:"\f026"} .fa-volume-down:before{content:"\f027"} .fa-volume-up:before{content:"\f028"} .fa-qrcode:before{content:"\f029"} .fa-barcode:before{content:"\f02a"} .fa-tag:before{content:"\f02b"} .fa-tags:before{content:"\f02c"} .fa-book:before{content:"\f02d"} .fa-bookmark:before{content:"\f02e"} .fa-print:before{content:"\f02f"} .fa-camera:before{content:"\f030"} .fa-font:before{content:"\f031"} .fa-bold:before{content:"\f032"} .fa-italic:before{content:"\f033"} .fa-text-height:before{content:"\f034"} .fa-text-width:before{content:"\f035"} .fa-align-left:before{content:"\f036"} .fa-align-center:before{content:"\f037"} .fa-align-right:before{content:"\f038"} .fa-align-justify:before{content:"\f039"} .fa-list:before{content:"\f03a"} .fa-dedent:before,.fa-outdent:before{content:"\f03b"} .fa-indent:before{content:"\f03c"} .fa-video-camera:before{content:"\f03d"} .fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"} .fa-pencil:before{content:"\f040"} .fa-map-marker:before{content:"\f041"} .fa-adjust:before{content:"\f042"} .fa-tint:before{content:"\f043"} .fa-edit:before,.fa-pencil-square-o:before{content:"\f044"} .fa-share-square-o:before{content:"\f045"} .fa-check-square-o:before{content:"\f046"} .fa-arrows:before{content:"\f047"} .fa-step-backward:before{content:"\f048"} .fa-fast-backward:before{content:"\f049"} .fa-backward:before{content:"\f04a"} .fa-play:before{content:"\f04b"} .fa-pause:before{content:"\f04c"} .fa-stop:before{content:"\f04d"} .fa-forward:before{content:"\f04e"} .fa-fast-forward:before{content:"\f050"} .fa-step-forward:before{content:"\f051"} .fa-eject:before{content:"\f052"} .fa-chevron-left:before{content:"\f053"} .fa-chevron-right:before{content:"\f054"} .fa-plus-circle:before{content:"\f055"} .fa-minus-circle:before{content:"\f056"} .fa-times-circle:before{content:"\f057"} .fa-check-circle:before{content:"\f058"} .fa-question-circle:before{content:"\f059"} .fa-info-circle:before{content:"\f05a"} .fa-crosshairs:before{content:"\f05b"} .fa-times-circle-o:before{content:"\f05c"} .fa-check-circle-o:before{content:"\f05d"} .fa-ban:before{content:"\f05e"} .fa-arrow-left:before{content:"\f060"} .fa-arrow-right:before{content:"\f061"} .fa-arrow-up:before{content:"\f062"} .fa-arrow-down:before{content:"\f063"} .fa-mail-forward:before,.fa-share:before{content:"\f064"} .fa-expand:before{content:"\f065"} .fa-compress:before{content:"\f066"} .fa-plus:before{content:"\f067"} .fa-minus:before{content:"\f068"} .fa-asterisk:before{content:"\f069"} .fa-exclamation-circle:before{content:"\f06a"} .fa-gift:before{content:"\f06b"} .fa-leaf:before{content:"\f06c"} .fa-fire:before{content:"\f06d"} .fa-eye:before{content:"\f06e"} .fa-eye-slash:before{content:"\f070"} .fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"} .fa-plane:before{content:"\f072"} .fa-calendar:before{content:"\f073"} .fa-random:before{content:"\f074"} .fa-comment:before{content:"\f075"} .fa-magnet:before{content:"\f076"} .fa-chevron-up:before{content:"\f077"} .fa-chevron-down:before{content:"\f078"} .fa-retweet:before{content:"\f079"} .fa-shopping-cart:before{content:"\f07a"} .fa-folder:before{content:"\f07b"} .fa-folder-open:before{content:"\f07c"} .fa-arrows-v:before{content:"\f07d"} .fa-arrows-h:before{content:"\f07e"} .fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"} .fa-twitter-square:before{content:"\f081"} .fa-facebook-square:before{content:"\f082"} .fa-camera-retro:before{content:"\f083"} .fa-key:before{content:"\f084"} .fa-gears:before,.fa-cogs:before{content:"\f085"} .fa-comments:before{content:"\f086"} .fa-thumbs-o-up:before{content:"\f087"} .fa-thumbs-o-down:before{content:"\f088"} .fa-star-half:before{content:"\f089"} .fa-heart-o:before{content:"\f08a"} .fa-sign-out:before{content:"\f08b"} .fa-linkedin-square:before{content:"\f08c"} .fa-thumb-tack:before{content:"\f08d"} .fa-external-link:before{content:"\f08e"} .fa-sign-in:before{content:"\f090"} .fa-trophy:before{content:"\f091"} .fa-github-square:before{content:"\f092"} .fa-upload:before{content:"\f093"} .fa-lemon-o:before{content:"\f094"} .fa-phone:before{content:"\f095"} .fa-square-o:before{content:"\f096"} .fa-bookmark-o:before{content:"\f097"} .fa-phone-square:before{content:"\f098"} .fa-twitter:before{content:"\f099"} .fa-facebook-f:before,.fa-facebook:before{content:"\f09a"} .fa-github:before{content:"\f09b"} .fa-unlock:before{content:"\f09c"} .fa-credit-card:before{content:"\f09d"} .fa-feed:before,.fa-rss:before{content:"\f09e"} .fa-hdd-o:before{content:"\f0a0"} .fa-bullhorn:before{content:"\f0a1"} .fa-bell:before{content:"\f0f3"} .fa-certificate:before{content:"\f0a3"} .fa-hand-o-right:before{content:"\f0a4"} .fa-hand-o-left:before{content:"\f0a5"} .fa-hand-o-up:before{content:"\f0a6"} .fa-hand-o-down:before{content:"\f0a7"} .fa-arrow-circle-left:before{content:"\f0a8"} .fa-arrow-circle-right:before{content:"\f0a9"} .fa-arrow-circle-up:before{content:"\f0aa"} .fa-arrow-circle-down:before{content:"\f0ab"} .fa-globe:before{content:"\f0ac"} .fa-wrench:before{content:"\f0ad"} .fa-tasks:before{content:"\f0ae"} .fa-filter:before{content:"\f0b0"} .fa-briefcase:before{content:"\f0b1"} .fa-arrows-alt:before{content:"\f0b2"} .fa-group:before,.fa-users:before{content:"\f0c0"} .fa-chain:before,.fa-link:before{content:"\f0c1"} .fa-cloud:before{content:"\f0c2"} .fa-flask:before{content:"\f0c3"} .fa-cut:before,.fa-scissors:before{content:"\f0c4"} .fa-copy:before,.fa-files-o:before{content:"\f0c5"} .fa-paperclip:before{content:"\f0c6"} .fa-save:before,.fa-floppy-o:before{content:"\f0c7"} .fa-square:before{content:"\f0c8"} .fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"} .fa-list-ul:before{content:"\f0ca"} .fa-list-ol:before{content:"\f0cb"} .fa-strikethrough:before{content:"\f0cc"} .fa-underline:before{content:"\f0cd"} .fa-table:before{content:"\f0ce"} .fa-magic:before{content:"\f0d0"} .fa-truck:before{content:"\f0d1"} .fa-pinterest:before{content:"\f0d2"} .fa-pinterest-square:before{content:"\f0d3"} .fa-google-plus-square:before{content:"\f0d4"} .fa-google-plus:before{content:"\f0d5"} .fa-money:before{content:"\f0d6"} .fa-caret-down:before{content:"\f0d7"} .fa-caret-up:before{content:"\f0d8"} .fa-caret-left:before{content:"\f0d9"} .fa-caret-right:before{content:"\f0da"} .fa-columns:before{content:"\f0db"} .fa-unsorted:before,.fa-sort:before{content:"\f0dc"} .fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"} .fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"} .fa-envelope:before{content:"\f0e0"} .fa-linkedin:before{content:"\f0e1"} .fa-rotate-left:before,.fa-undo:before{content:"\f0e2"} .fa-legal:before,.fa-gavel:before{content:"\f0e3"} .fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"} .fa-comment-o:before{content:"\f0e5"} .fa-comments-o:before{content:"\f0e6"} .fa-flash:before,.fa-bolt:before{content:"\f0e7"} .fa-sitemap:before{content:"\f0e8"} .fa-umbrella:before{content:"\f0e9"} .fa-paste:before,.fa-clipboard:before{content:"\f0ea"} .fa-lightbulb-o:before{content:"\f0eb"} .fa-exchange:before{content:"\f0ec"} .fa-cloud-download:before{content:"\f0ed"} .fa-cloud-upload:before{content:"\f0ee"} .fa-user-md:before{content:"\f0f0"} .fa-stethoscope:before{content:"\f0f1"} .fa-suitcase:before{content:"\f0f2"} .fa-bell-o:before{content:"\f0a2"} .fa-coffee:before{content:"\f0f4"} .fa-cutlery:before{content:"\f0f5"} .fa-file-text-o:before{content:"\f0f6"} .fa-building-o:before{content:"\f0f7"} .fa-hospital-o:before{content:"\f0f8"} .fa-ambulance:before{content:"\f0f9"} .fa-medkit:before{content:"\f0fa"} .fa-fighter-jet:before{content:"\f0fb"} .fa-beer:before{content:"\f0fc"} .fa-h-square:before{content:"\f0fd"} .fa-plus-square:before{content:"\f0fe"} .fa-angle-double-left:before{content:"\f100"} .fa-angle-double-right:before{content:"\f101"} .fa-angle-double-up:before{content:"\f102"} .fa-angle-double-down:before{content:"\f103"} .fa-angle-left:before{content:"\f104"} .fa-angle-right:before{content:"\f105"} .fa-angle-up:before{content:"\f106"} .fa-angle-down:before{content:"\f107"} .fa-desktop:before{content:"\f108"} .fa-laptop:before{content:"\f109"} .fa-tablet:before{content:"\f10a"} .fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"} .fa-circle-o:before{content:"\f10c"} .fa-quote-left:before{content:"\f10d"} .fa-quote-right:before{content:"\f10e"} .fa-spinner:before{content:"\f110"} .fa-circle:before{content:"\f111"} .fa-mail-reply:before,.fa-reply:before{content:"\f112"} .fa-github-alt:before{content:"\f113"} .fa-folder-o:before{content:"\f114"} .fa-folder-open-o:before{content:"\f115"} .fa-smile-o:before{content:"\f118"} .fa-frown-o:before{content:"\f119"} .fa-meh-o:before{content:"\f11a"} .fa-gamepad:before{content:"\f11b"} .fa-keyboard-o:before{content:"\f11c"} .fa-flag-o:before{content:"\f11d"} .fa-flag-checkered:before{content:"\f11e"} .fa-terminal:before{content:"\f120"} .fa-code:before{content:"\f121"} .fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"} .fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"} .fa-location-arrow:before{content:"\f124"} .fa-crop:before{content:"\f125"} .fa-code-fork:before{content:"\f126"} .fa-unlink:before,.fa-chain-broken:before{content:"\f127"} .fa-question:before{content:"\f128"} .fa-info:before{content:"\f129"} .fa-exclamation:before{content:"\f12a"} .fa-superscript:before{content:"\f12b"} .fa-subscript:before{content:"\f12c"} .fa-eraser:before{content:"\f12d"} .fa-puzzle-piece:before{content:"\f12e"} .fa-microphone:before{content:"\f130"} .fa-microphone-slash:before{content:"\f131"} .fa-shield:before{content:"\f132"} .fa-calendar-o:before{content:"\f133"} .fa-fire-extinguisher:before{content:"\f134"} .fa-rocket:before{content:"\f135"} .fa-maxcdn:before{content:"\f136"} .fa-chevron-circle-left:before{content:"\f137"} .fa-chevron-circle-right:before{content:"\f138"} .fa-chevron-circle-up:before{content:"\f139"} .fa-chevron-circle-down:before{content:"\f13a"} .fa-html5:before{content:"\f13b"} .fa-css3:before{content:"\f13c"} .fa-anchor:before{content:"\f13d"} .fa-unlock-alt:before{content:"\f13e"} .fa-bullseye:before{content:"\f140"} .fa-ellipsis-h:before{content:"\f141"} .fa-ellipsis-v:before{content:"\f142"} .fa-rss-square:before{content:"\f143"} .fa-play-circle:before{content:"\f144"} .fa-ticket:before{content:"\f145"} .fa-minus-square:before{content:"\f146"} .fa-minus-square-o:before{content:"\f147"} .fa-level-up:before{content:"\f148"} .fa-level-down:before{content:"\f149"} .fa-check-square:before{content:"\f14a"} .fa-pencil-square:before{content:"\f14b"} .fa-external-link-square:before{content:"\f14c"} .fa-share-square:before{content:"\f14d"} .fa-compass:before{content:"\f14e"} .fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"} .fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"} .fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"} .fa-euro:before,.fa-eur:before{content:"\f153"} .fa-gbp:before{content:"\f154"} .fa-dollar:before,.fa-usd:before{content:"\f155"} .fa-rupee:before,.fa-inr:before{content:"\f156"} .fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"} .fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"} .fa-won:before,.fa-krw:before{content:"\f159"} .fa-bitcoin:before,.fa-btc:before{content:"\f15a"} .fa-file:before{content:"\f15b"} .fa-file-text:before{content:"\f15c"} .fa-sort-alpha-asc:before{content:"\f15d"} .fa-sort-alpha-desc:before{content:"\f15e"} .fa-sort-amount-asc:before{content:"\f160"} .fa-sort-amount-desc:before{content:"\f161"} .fa-sort-numeric-asc:before{content:"\f162"} .fa-sort-numeric-desc:before{content:"\f163"} .fa-thumbs-up:before{content:"\f164"} .fa-thumbs-down:before{content:"\f165"} .fa-youtube-square:before{content:"\f166"} .fa-youtube:before{content:"\f167"} .fa-xing:before{content:"\f168"} .fa-xing-square:before{content:"\f169"} .fa-youtube-play:before{content:"\f16a"} .fa-dropbox:before{content:"\f16b"} .fa-stack-overflow:before{content:"\f16c"} .fa-instagram:before{content:"\f16d"} .fa-flickr:before{content:"\f16e"} .fa-adn:before{content:"\f170"} .fa-bitbucket:before{content:"\f171"} .fa-bitbucket-square:before{content:"\f172"} .fa-tumblr:before{content:"\f173"} .fa-tumblr-square:before{content:"\f174"} .fa-long-arrow-down:before{content:"\f175"} .fa-long-arrow-up:before{content:"\f176"} .fa-long-arrow-left:before{content:"\f177"} .fa-long-arrow-right:before{content:"\f178"} .fa-apple:before{content:"\f179"} .fa-windows:before{content:"\f17a"} .fa-android:before{content:"\f17b"} .fa-linux:before{content:"\f17c"} .fa-dribbble:before{content:"\f17d"} .fa-skype:before{content:"\f17e"} .fa-foursquare:before{content:"\f180"} .fa-trello:before{content:"\f181"} .fa-female:before{content:"\f182"} .fa-male:before{content:"\f183"} .fa-gittip:before,.fa-gratipay:before{content:"\f184"} .fa-sun-o:before{content:"\f185"} .fa-moon-o:before{content:"\f186"} .fa-archive:before{content:"\f187"} .fa-bug:before{content:"\f188"} .fa-vk:before{content:"\f189"} .fa-weibo:before{content:"\f18a"} .fa-renren:before{content:"\f18b"} .fa-pagelines:before{content:"\f18c"} .fa-stack-exchange:before{content:"\f18d"} .fa-arrow-circle-o-right:before{content:"\f18e"} .fa-arrow-circle-o-left:before{content:"\f190"} .fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"} .fa-dot-circle-o:before{content:"\f192"} .fa-wheelchair:before{content:"\f193"} .fa-vimeo-square:before{content:"\f194"} .fa-turkish-lira:before,.fa-try:before{content:"\f195"} .fa-plus-square-o:before{content:"\f196"} .fa-space-shuttle:before{content:"\f197"} .fa-slack:before{content:"\f198"} .fa-envelope-square:before{content:"\f199"} .fa-wordpress:before{content:"\f19a"} .fa-openid:before{content:"\f19b"} .fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"} .fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"} .fa-yahoo:before{content:"\f19e"} .fa-google:before{content:"\f1a0"} .fa-reddit:before{content:"\f1a1"} .fa-reddit-square:before{content:"\f1a2"} .fa-stumbleupon-circle:before{content:"\f1a3"} .fa-stumbleupon:before{content:"\f1a4"} .fa-delicious:before{content:"\f1a5"} .fa-digg:before{content:"\f1a6"} .fa-pied-piper-pp:before{content:"\f1a7"} .fa-pied-piper-alt:before{content:"\f1a8"} .fa-drupal:before{content:"\f1a9"} .fa-joomla:before{content:"\f1aa"} .fa-language:before{content:"\f1ab"} .fa-fax:before{content:"\f1ac"} .fa-building:before{content:"\f1ad"} .fa-child:before{content:"\f1ae"} .fa-paw:before{content:"\f1b0"} .fa-spoon:before{content:"\f1b1"} .fa-cube:before{content:"\f1b2"} .fa-cubes:before{content:"\f1b3"} .fa-behance:before{content:"\f1b4"} .fa-behance-square:before{content:"\f1b5"} .fa-steam:before{content:"\f1b6"} .fa-steam-square:before{content:"\f1b7"} .fa-recycle:before{content:"\f1b8"} .fa-automobile:before,.fa-car:before{content:"\f1b9"} .fa-cab:before,.fa-taxi:before{content:"\f1ba"} .fa-tree:before{content:"\f1bb"} .fa-spotify:before{content:"\f1bc"} .fa-deviantart:before{content:"\f1bd"} .fa-soundcloud:before{content:"\f1be"} .fa-database:before{content:"\f1c0"} .fa-file-pdf-o:before{content:"\f1c1"} .fa-file-word-o:before{content:"\f1c2"} .fa-file-excel-o:before{content:"\f1c3"} .fa-file-powerpoint-o:before{content:"\f1c4"} .fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"} .fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"} .fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"} .fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"} .fa-file-code-o:before{content:"\f1c9"} .fa-vine:before{content:"\f1ca"} .fa-codepen:before{content:"\f1cb"} .fa-jsfiddle:before{content:"\f1cc"} .fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"} .fa-circle-o-notch:before{content:"\f1ce"} .fa-ra:before,.fa-resistance:before,.fa-rebel:before{content:"\f1d0"} .fa-ge:before,.fa-empire:before{content:"\f1d1"} .fa-git-square:before{content:"\f1d2"} .fa-git:before{content:"\f1d3"} .fa-y-combinator-square:before,.fa-yc-square:before,.fa-hacker-news:before{content:"\f1d4"} .fa-tencent-weibo:before{content:"\f1d5"} .fa-qq:before{content:"\f1d6"} .fa-wechat:before,.fa-weixin:before{content:"\f1d7"} .fa-send:before,.fa-paper-plane:before{content:"\f1d8"} .fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"} .fa-history:before{content:"\f1da"} .fa-circle-thin:before{content:"\f1db"} .fa-header:before{content:"\f1dc"} .fa-paragraph:before{content:"\f1dd"} .fa-sliders:before{content:"\f1de"} .fa-share-alt:before{content:"\f1e0"} .fa-share-alt-square:before{content:"\f1e1"} .fa-bomb:before{content:"\f1e2"} .fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"} .fa-tty:before{content:"\f1e4"} .fa-binoculars:before{content:"\f1e5"} .fa-plug:before{content:"\f1e6"} .fa-slideshare:before{content:"\f1e7"} .fa-twitch:before{content:"\f1e8"} .fa-yelp:before{content:"\f1e9"} .fa-newspaper-o:before{content:"\f1ea"} .fa-wifi:before{content:"\f1eb"} .fa-calculator:before{content:"\f1ec"} .fa-paypal:before{content:"\f1ed"} .fa-google-wallet:before{content:"\f1ee"} .fa-cc-visa:before{content:"\f1f0"} .fa-cc-mastercard:before{content:"\f1f1"} .fa-cc-discover:before{content:"\f1f2"} .fa-cc-amex:before{content:"\f1f3"} .fa-cc-paypal:before{content:"\f1f4"} .fa-cc-stripe:before{content:"\f1f5"} .fa-bell-slash:before{content:"\f1f6"} .fa-bell-slash-o:before{content:"\f1f7"} .fa-trash:before{content:"\f1f8"} .fa-copyright:before{content:"\f1f9"} .fa-at:before{content:"\f1fa"} .fa-eyedropper:before{content:"\f1fb"} .fa-paint-brush:before{content:"\f1fc"} .fa-birthday-cake:before{content:"\f1fd"} .fa-area-chart:before{content:"\f1fe"} .fa-pie-chart:before{content:"\f200"} .fa-line-chart:before{content:"\f201"} .fa-lastfm:before{content:"\f202"} .fa-lastfm-square:before{content:"\f203"} .fa-toggle-off:before{content:"\f204"} .fa-toggle-on:before{content:"\f205"} .fa-bicycle:before{content:"\f206"} .fa-bus:before{content:"\f207"} .fa-ioxhost:before{content:"\f208"} .fa-angellist:before{content:"\f209"} .fa-cc:before{content:"\f20a"} .fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"} .fa-meanpath:before{content:"\f20c"} .fa-buysellads:before{content:"\f20d"} .fa-connectdevelop:before{content:"\f20e"} .fa-dashcube:before{content:"\f210"} .fa-forumbee:before{content:"\f211"} .fa-leanpub:before{content:"\f212"} .fa-sellsy:before{content:"\f213"} .fa-shirtsinbulk:before{content:"\f214"} .fa-simplybuilt:before{content:"\f215"} .fa-skyatlas:before{content:"\f216"} .fa-cart-plus:before{content:"\f217"} .fa-cart-arrow-down:before{content:"\f218"} .fa-diamond:before{content:"\f219"} .fa-ship:before{content:"\f21a"} .fa-user-secret:before{content:"\f21b"} .fa-motorcycle:before{content:"\f21c"} .fa-street-view:before{content:"\f21d"} .fa-heartbeat:before{content:"\f21e"} .fa-venus:before{content:"\f221"} .fa-mars:before{content:"\f222"} .fa-mercury:before{content:"\f223"} .fa-intersex:before,.fa-transgender:before{content:"\f224"} .fa-transgender-alt:before{content:"\f225"} .fa-venus-double:before{content:"\f226"} .fa-mars-double:before{content:"\f227"} .fa-venus-mars:before{content:"\f228"} .fa-mars-stroke:before{content:"\f229"} .fa-mars-stroke-v:before{content:"\f22a"} .fa-mars-stroke-h:before{content:"\f22b"} .fa-neuter:before{content:"\f22c"} .fa-genderless:before{content:"\f22d"} .fa-facebook-official:before{content:"\f230"} .fa-pinterest-p:before{content:"\f231"} .fa-whatsapp:before{content:"\f232"} .fa-server:before{content:"\f233"} .fa-user-plus:before{content:"\f234"} .fa-user-times:before{content:"\f235"} .fa-hotel:before,.fa-bed:before{content:"\f236"} .fa-viacoin:before{content:"\f237"} .fa-train:before{content:"\f238"} .fa-subway:before{content:"\f239"} .fa-medium:before{content:"\f23a"} .fa-yc:before,.fa-y-combinator:before{content:"\f23b"} .fa-optin-monster:before{content:"\f23c"} .fa-opencart:before{content:"\f23d"} .fa-expeditedssl:before{content:"\f23e"} .fa-battery-4:before,.fa-battery:before,.fa-battery-full:before{content:"\f240"} .fa-battery-3:before,.fa-battery-three-quarters:before{content:"\f241"} .fa-battery-2:before,.fa-battery-half:before{content:"\f242"} .fa-battery-1:before,.fa-battery-quarter:before{content:"\f243"} .fa-battery-0:before,.fa-battery-empty:before{content:"\f244"} .fa-mouse-pointer:before{content:"\f245"} .fa-i-cursor:before{content:"\f246"} .fa-object-group:before{content:"\f247"} .fa-object-ungroup:before{content:"\f248"} .fa-sticky-note:before{content:"\f249"} .fa-sticky-note-o:before{content:"\f24a"} .fa-cc-jcb:before{content:"\f24b"} .fa-cc-diners-club:before{content:"\f24c"} .fa-clone:before{content:"\f24d"} .fa-balance-scale:before{content:"\f24e"} .fa-hourglass-o:before{content:"\f250"} .fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"} .fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"} .fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"} .fa-hourglass:before{content:"\f254"} .fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\f255"} .fa-hand-stop-o:before,.fa-hand-paper-o:before{content:"\f256"} .fa-hand-scissors-o:before{content:"\f257"} .fa-hand-lizard-o:before{content:"\f258"} .fa-hand-spock-o:before{content:"\f259"} .fa-hand-pointer-o:before{content:"\f25a"} .fa-hand-peace-o:before{content:"\f25b"} .fa-trademark:before{content:"\f25c"} .fa-registered:before{content:"\f25d"} .fa-creative-commons:before{content:"\f25e"} .fa-gg:before{content:"\f260"} .fa-gg-circle:before{content:"\f261"} .fa-tripadvisor:before{content:"\f262"} .fa-odnoklassniki:before{content:"\f263"} .fa-odnoklassniki-square:before{content:"\f264"} .fa-get-pocket:before{content:"\f265"} .fa-wikipedia-w:before{content:"\f266"} .fa-safari:before{content:"\f267"} .fa-chrome:before{content:"\f268"} .fa-firefox:before{content:"\f269"} .fa-opera:before{content:"\f26a"} .fa-internet-explorer:before{content:"\f26b"} .fa-tv:before,.fa-television:before{content:"\f26c"} .fa-contao:before{content:"\f26d"} .fa-500px:before{content:"\f26e"} .fa-amazon:before{content:"\f270"} .fa-calendar-plus-o:before{content:"\f271"} .fa-calendar-minus-o:before{content:"\f272"} .fa-calendar-times-o:before{content:"\f273"} .fa-calendar-check-o:before{content:"\f274"} .fa-industry:before{content:"\f275"} .fa-map-pin:before{content:"\f276"} .fa-map-signs:before{content:"\f277"} .fa-map-o:before{content:"\f278"} .fa-map:before{content:"\f279"} .fa-commenting:before{content:"\f27a"} .fa-commenting-o:before{content:"\f27b"} .fa-houzz:before{content:"\f27c"} .fa-vimeo:before{content:"\f27d"} .fa-black-tie:before{content:"\f27e"} .fa-fonticons:before{content:"\f280"} .fa-reddit-alien:before{content:"\f281"} .fa-edge:before{content:"\f282"} .fa-credit-card-alt:before{content:"\f283"} .fa-codiepie:before{content:"\f284"} .fa-modx:before{content:"\f285"} .fa-fort-awesome:before{content:"\f286"} .fa-usb:before{content:"\f287"} .fa-product-hunt:before{content:"\f288"} .fa-mixcloud:before{content:"\f289"} .fa-scribd:before{content:"\f28a"} .fa-pause-circle:before{content:"\f28b"} .fa-pause-circle-o:before{content:"\f28c"} .fa-stop-circle:before{content:"\f28d"} .fa-stop-circle-o:before{content:"\f28e"} .fa-shopping-bag:before{content:"\f290"} .fa-shopping-basket:before{content:"\f291"} .fa-hashtag:before{content:"\f292"} .fa-bluetooth:before{content:"\f293"} .fa-bluetooth-b:before{content:"\f294"} .fa-percent:before{content:"\f295"} .fa-gitlab:before{content:"\f296"} .fa-wpbeginner:before{content:"\f297"} .fa-wpforms:before{content:"\f298"} .fa-envira:before{content:"\f299"} .fa-universal-access:before{content:"\f29a"} .fa-wheelchair-alt:before{content:"\f29b"} .fa-question-circle-o:before{content:"\f29c"} .fa-blind:before{content:"\f29d"} .fa-audio-description:before{content:"\f29e"} .fa-volume-control-phone:before{content:"\f2a0"} .fa-braille:before{content:"\f2a1"} .fa-assistive-listening-systems:before{content:"\f2a2"} .fa-asl-interpreting:before,.fa-american-sign-language-interpreting:before{content:"\f2a3"} .fa-deafness:before,.fa-hard-of-hearing:before,.fa-deaf:before{content:"\f2a4"} .fa-glide:before{content:"\f2a5"} .fa-glide-g:before{content:"\f2a6"} .fa-signing:before,.fa-sign-language:before{content:"\f2a7"} .fa-low-vision:before{content:"\f2a8"} .fa-viadeo:before{content:"\f2a9"} .fa-viadeo-square:before{content:"\f2aa"} .fa-snapchat:before{content:"\f2ab"} .fa-snapchat-ghost:before{content:"\f2ac"} .fa-snapchat-square:before{content:"\f2ad"} .fa-pied-piper:before{content:"\f2ae"} .fa-first-order:before{content:"\f2b0"} .fa-yoast:before{content:"\f2b1"} .fa-themeisle:before{content:"\f2b2"} .fa-google-plus-circle:before,.fa-google-plus-official:before{content:"\f2b3"} .fa-fa:before,.fa-font-awesome:before{content:"\f2b4"} .fa-handshake-o:before{content:"\f2b5"} .fa-envelope-open:before{content:"\f2b6"} .fa-envelope-open-o:before{content:"\f2b7"} .fa-linode:before{content:"\f2b8"} .fa-address-book:before{content:"\f2b9"} .fa-address-book-o:before{content:"\f2ba"} .fa-vcard:before,.fa-address-card:before{content:"\f2bb"} .fa-vcard-o:before,.fa-address-card-o:before{content:"\f2bc"} .fa-user-circle:before{content:"\f2bd"} .fa-user-circle-o:before{content:"\f2be"} .fa-user-o:before{content:"\f2c0"} .fa-id-badge:before{content:"\f2c1"} .fa-drivers-license:before,.fa-id-card:before{content:"\f2c2"} .fa-drivers-license-o:before,.fa-id-card-o:before{content:"\f2c3"} .fa-quora:before{content:"\f2c4"} .fa-free-code-camp:before{content:"\f2c5"} .fa-telegram:before{content:"\f2c6"} .fa-thermometer-4:before,.fa-thermometer:before,.fa-thermometer-full:before{content:"\f2c7"} .fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:"\f2c8"} .fa-thermometer-2:before,.fa-thermometer-half:before{content:"\f2c9"} .fa-thermometer-1:before,.fa-thermometer-quarter:before{content:"\f2ca"} .fa-thermometer-0:before,.fa-thermometer-empty:before{content:"\f2cb"} .fa-shower:before{content:"\f2cc"} .fa-bathtub:before,.fa-s15:before,.fa-bath:before{content:"\f2cd"} .fa-podcast:before{content:"\f2ce"} .fa-window-maximize:before{content:"\f2d0"} .fa-window-minimize:before{content:"\f2d1"} .fa-window-restore:before{content:"\f2d2"} .fa-times-rectangle:before,.fa-window-close:before{content:"\f2d3"} .fa-times-rectangle-o:before,.fa-window-close-o:before{content:"\f2d4"} .fa-bandcamp:before{content:"\f2d5"} .fa-grav:before{content:"\f2d6"} .fa-etsy:before{content:"\f2d7"} .fa-imdb:before{content:"\f2d8"} .fa-ravelry:before{content:"\f2d9"} .fa-eercast:before{content:"\f2da"} .fa-microchip:before{content:"\f2db"} .fa-snowflake-o:before{content:"\f2dc"} .fa-superpowers:before{content:"\f2dd"} .fa-wpexplorer:before{content:"\f2de"} .fa-meetup:before{content:"\f2e0"} .sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);border:0} .sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto} diff --git a/dal/dal/static/datacenterlight/font-awesome/fonts/FontAwesome.otf b/dal/static/datacenterlight/font-awesome/fonts/FontAwesome.otf similarity index 100% rename from dal/dal/static/datacenterlight/font-awesome/fonts/FontAwesome.otf rename to dal/static/datacenterlight/font-awesome/fonts/FontAwesome.otf diff --git a/dal/dal/static/datacenterlight/font-awesome/fonts/fontawesome-webfont.eot b/dal/static/datacenterlight/font-awesome/fonts/fontawesome-webfont.eot similarity index 100% rename from dal/dal/static/datacenterlight/font-awesome/fonts/fontawesome-webfont.eot rename to dal/static/datacenterlight/font-awesome/fonts/fontawesome-webfont.eot diff --git a/dal/dal/static/datacenterlight/font-awesome/fonts/fontawesome-webfont.svg b/dal/static/datacenterlight/font-awesome/fonts/fontawesome-webfont.svg similarity index 100% rename from dal/dal/static/datacenterlight/font-awesome/fonts/fontawesome-webfont.svg rename to dal/static/datacenterlight/font-awesome/fonts/fontawesome-webfont.svg diff --git a/dal/dal/static/datacenterlight/font-awesome/fonts/fontawesome-webfont.ttf b/dal/static/datacenterlight/font-awesome/fonts/fontawesome-webfont.ttf similarity index 100% rename from dal/dal/static/datacenterlight/font-awesome/fonts/fontawesome-webfont.ttf rename to dal/static/datacenterlight/font-awesome/fonts/fontawesome-webfont.ttf diff --git a/dal/dal/static/datacenterlight/font-awesome/fonts/fontawesome-webfont.woff b/dal/static/datacenterlight/font-awesome/fonts/fontawesome-webfont.woff similarity index 100% rename from dal/dal/static/datacenterlight/font-awesome/fonts/fontawesome-webfont.woff rename to dal/static/datacenterlight/font-awesome/fonts/fontawesome-webfont.woff diff --git a/dal/dal/static/datacenterlight/font-awesome/fonts/fontawesome-webfont.woff2 b/dal/static/datacenterlight/font-awesome/fonts/fontawesome-webfont.woff2 similarity index 100% rename from dal/dal/static/datacenterlight/font-awesome/fonts/fontawesome-webfont.woff2 rename to dal/static/datacenterlight/font-awesome/fonts/fontawesome-webfont.woff2 diff --git a/dal/dal/static/datacenterlight/font-awesome/less/bordered-pulled.less b/dal/static/datacenterlight/font-awesome/less/bordered-pulled.less similarity index 100% rename from dal/dal/static/datacenterlight/font-awesome/less/bordered-pulled.less rename to dal/static/datacenterlight/font-awesome/less/bordered-pulled.less diff --git a/dal/dal/static/datacenterlight/font-awesome/less/core.less b/dal/static/datacenterlight/font-awesome/less/core.less similarity index 100% rename from dal/dal/static/datacenterlight/font-awesome/less/core.less rename to dal/static/datacenterlight/font-awesome/less/core.less diff --git a/dal/dal/static/datacenterlight/font-awesome/less/fixed-width.less b/dal/static/datacenterlight/font-awesome/less/fixed-width.less similarity index 100% rename from dal/dal/static/datacenterlight/font-awesome/less/fixed-width.less rename to dal/static/datacenterlight/font-awesome/less/fixed-width.less diff --git a/dal/dal/static/datacenterlight/font-awesome/less/font-awesome.less b/dal/static/datacenterlight/font-awesome/less/font-awesome.less similarity index 100% rename from dal/dal/static/datacenterlight/font-awesome/less/font-awesome.less rename to dal/static/datacenterlight/font-awesome/less/font-awesome.less diff --git a/dal/dal/static/datacenterlight/font-awesome/less/icons.less b/dal/static/datacenterlight/font-awesome/less/icons.less similarity index 100% rename from dal/dal/static/datacenterlight/font-awesome/less/icons.less rename to dal/static/datacenterlight/font-awesome/less/icons.less diff --git a/dal/dal/static/datacenterlight/font-awesome/less/larger.less b/dal/static/datacenterlight/font-awesome/less/larger.less similarity index 100% rename from dal/dal/static/datacenterlight/font-awesome/less/larger.less rename to dal/static/datacenterlight/font-awesome/less/larger.less diff --git a/dal/dal/static/datacenterlight/font-awesome/less/list.less b/dal/static/datacenterlight/font-awesome/less/list.less similarity index 100% rename from dal/dal/static/datacenterlight/font-awesome/less/list.less rename to dal/static/datacenterlight/font-awesome/less/list.less diff --git a/dal/dal/static/datacenterlight/font-awesome/less/mixins.less b/dal/static/datacenterlight/font-awesome/less/mixins.less similarity index 100% rename from dal/dal/static/datacenterlight/font-awesome/less/mixins.less rename to dal/static/datacenterlight/font-awesome/less/mixins.less diff --git a/dal/dal/static/datacenterlight/font-awesome/less/path.less b/dal/static/datacenterlight/font-awesome/less/path.less similarity index 100% rename from dal/dal/static/datacenterlight/font-awesome/less/path.less rename to dal/static/datacenterlight/font-awesome/less/path.less diff --git a/dal/dal/static/datacenterlight/font-awesome/less/rotated-flipped.less b/dal/static/datacenterlight/font-awesome/less/rotated-flipped.less similarity index 100% rename from dal/dal/static/datacenterlight/font-awesome/less/rotated-flipped.less rename to dal/static/datacenterlight/font-awesome/less/rotated-flipped.less diff --git a/dal/dal/static/datacenterlight/font-awesome/less/spinning.less b/dal/static/datacenterlight/font-awesome/less/spinning.less similarity index 100% rename from dal/dal/static/datacenterlight/font-awesome/less/spinning.less rename to dal/static/datacenterlight/font-awesome/less/spinning.less diff --git a/dal/dal/static/datacenterlight/font-awesome/less/stacked.less b/dal/static/datacenterlight/font-awesome/less/stacked.less similarity index 100% rename from dal/dal/static/datacenterlight/font-awesome/less/stacked.less rename to dal/static/datacenterlight/font-awesome/less/stacked.less diff --git a/dal/dal/static/datacenterlight/font-awesome/less/variables.less b/dal/static/datacenterlight/font-awesome/less/variables.less similarity index 100% rename from dal/dal/static/datacenterlight/font-awesome/less/variables.less rename to dal/static/datacenterlight/font-awesome/less/variables.less diff --git a/dal/dal/static/datacenterlight/font-awesome/scss/_bordered-pulled.scss b/dal/static/datacenterlight/font-awesome/scss/_bordered-pulled.scss similarity index 100% rename from dal/dal/static/datacenterlight/font-awesome/scss/_bordered-pulled.scss rename to dal/static/datacenterlight/font-awesome/scss/_bordered-pulled.scss diff --git a/dal/dal/static/datacenterlight/font-awesome/scss/_core.scss b/dal/static/datacenterlight/font-awesome/scss/_core.scss similarity index 100% rename from dal/dal/static/datacenterlight/font-awesome/scss/_core.scss rename to dal/static/datacenterlight/font-awesome/scss/_core.scss diff --git a/dal/dal/static/datacenterlight/font-awesome/scss/_fixed-width.scss b/dal/static/datacenterlight/font-awesome/scss/_fixed-width.scss similarity index 100% rename from dal/dal/static/datacenterlight/font-awesome/scss/_fixed-width.scss rename to dal/static/datacenterlight/font-awesome/scss/_fixed-width.scss diff --git a/dal/dal/static/datacenterlight/font-awesome/scss/_icons.scss b/dal/static/datacenterlight/font-awesome/scss/_icons.scss similarity index 100% rename from dal/dal/static/datacenterlight/font-awesome/scss/_icons.scss rename to dal/static/datacenterlight/font-awesome/scss/_icons.scss diff --git a/dal/dal/static/datacenterlight/font-awesome/scss/_larger.scss b/dal/static/datacenterlight/font-awesome/scss/_larger.scss similarity index 100% rename from dal/dal/static/datacenterlight/font-awesome/scss/_larger.scss rename to dal/static/datacenterlight/font-awesome/scss/_larger.scss diff --git a/dal/dal/static/datacenterlight/font-awesome/scss/_list.scss b/dal/static/datacenterlight/font-awesome/scss/_list.scss similarity index 100% rename from dal/dal/static/datacenterlight/font-awesome/scss/_list.scss rename to dal/static/datacenterlight/font-awesome/scss/_list.scss diff --git a/dal/dal/static/datacenterlight/font-awesome/scss/_mixins.scss b/dal/static/datacenterlight/font-awesome/scss/_mixins.scss similarity index 100% rename from dal/dal/static/datacenterlight/font-awesome/scss/_mixins.scss rename to dal/static/datacenterlight/font-awesome/scss/_mixins.scss diff --git a/dal/dal/static/datacenterlight/font-awesome/scss/_path.scss b/dal/static/datacenterlight/font-awesome/scss/_path.scss similarity index 100% rename from dal/dal/static/datacenterlight/font-awesome/scss/_path.scss rename to dal/static/datacenterlight/font-awesome/scss/_path.scss diff --git a/dal/dal/static/datacenterlight/font-awesome/scss/_rotated-flipped.scss b/dal/static/datacenterlight/font-awesome/scss/_rotated-flipped.scss similarity index 100% rename from dal/dal/static/datacenterlight/font-awesome/scss/_rotated-flipped.scss rename to dal/static/datacenterlight/font-awesome/scss/_rotated-flipped.scss diff --git a/dal/dal/static/datacenterlight/font-awesome/scss/_spinning.scss b/dal/static/datacenterlight/font-awesome/scss/_spinning.scss similarity index 100% rename from dal/dal/static/datacenterlight/font-awesome/scss/_spinning.scss rename to dal/static/datacenterlight/font-awesome/scss/_spinning.scss diff --git a/dal/dal/static/datacenterlight/font-awesome/scss/_stacked.scss b/dal/static/datacenterlight/font-awesome/scss/_stacked.scss similarity index 100% rename from dal/dal/static/datacenterlight/font-awesome/scss/_stacked.scss rename to dal/static/datacenterlight/font-awesome/scss/_stacked.scss diff --git a/dal/dal/static/datacenterlight/font-awesome/scss/_variables.scss b/dal/static/datacenterlight/font-awesome/scss/_variables.scss similarity index 100% rename from dal/dal/static/datacenterlight/font-awesome/scss/_variables.scss rename to dal/static/datacenterlight/font-awesome/scss/_variables.scss diff --git a/dal/dal/static/datacenterlight/font-awesome/scss/font-awesome.scss b/dal/static/datacenterlight/font-awesome/scss/font-awesome.scss similarity index 100% rename from dal/dal/static/datacenterlight/font-awesome/scss/font-awesome.scss rename to dal/static/datacenterlight/font-awesome/scss/font-awesome.scss diff --git a/dal/dal/static/datacenterlight/fonts/Montserrat/Montserrat-Black.ttf b/dal/static/datacenterlight/fonts/Montserrat/Montserrat-Black.ttf similarity index 100% rename from dal/dal/static/datacenterlight/fonts/Montserrat/Montserrat-Black.ttf rename to dal/static/datacenterlight/fonts/Montserrat/Montserrat-Black.ttf diff --git a/dal/dal/static/datacenterlight/fonts/Montserrat/Montserrat-BlackItalic.ttf b/dal/static/datacenterlight/fonts/Montserrat/Montserrat-BlackItalic.ttf similarity index 100% rename from dal/dal/static/datacenterlight/fonts/Montserrat/Montserrat-BlackItalic.ttf rename to dal/static/datacenterlight/fonts/Montserrat/Montserrat-BlackItalic.ttf diff --git a/dal/dal/static/datacenterlight/fonts/Montserrat/Montserrat-Bold.ttf b/dal/static/datacenterlight/fonts/Montserrat/Montserrat-Bold.ttf similarity index 100% rename from dal/dal/static/datacenterlight/fonts/Montserrat/Montserrat-Bold.ttf rename to dal/static/datacenterlight/fonts/Montserrat/Montserrat-Bold.ttf diff --git a/dal/dal/static/datacenterlight/fonts/Montserrat/Montserrat-BoldItalic.ttf b/dal/static/datacenterlight/fonts/Montserrat/Montserrat-BoldItalic.ttf similarity index 100% rename from dal/dal/static/datacenterlight/fonts/Montserrat/Montserrat-BoldItalic.ttf rename to dal/static/datacenterlight/fonts/Montserrat/Montserrat-BoldItalic.ttf diff --git a/dal/dal/static/datacenterlight/fonts/Montserrat/Montserrat-ExtraBold.ttf b/dal/static/datacenterlight/fonts/Montserrat/Montserrat-ExtraBold.ttf similarity index 100% rename from dal/dal/static/datacenterlight/fonts/Montserrat/Montserrat-ExtraBold.ttf rename to dal/static/datacenterlight/fonts/Montserrat/Montserrat-ExtraBold.ttf diff --git a/dal/dal/static/datacenterlight/fonts/Montserrat/Montserrat-ExtraBoldItalic.ttf b/dal/static/datacenterlight/fonts/Montserrat/Montserrat-ExtraBoldItalic.ttf similarity index 100% rename from dal/dal/static/datacenterlight/fonts/Montserrat/Montserrat-ExtraBoldItalic.ttf rename to dal/static/datacenterlight/fonts/Montserrat/Montserrat-ExtraBoldItalic.ttf diff --git a/dal/dal/static/datacenterlight/fonts/Montserrat/Montserrat-ExtraLight.ttf b/dal/static/datacenterlight/fonts/Montserrat/Montserrat-ExtraLight.ttf similarity index 100% rename from dal/dal/static/datacenterlight/fonts/Montserrat/Montserrat-ExtraLight.ttf rename to dal/static/datacenterlight/fonts/Montserrat/Montserrat-ExtraLight.ttf diff --git a/dal/dal/static/datacenterlight/fonts/Montserrat/Montserrat-ExtraLightItalic.ttf b/dal/static/datacenterlight/fonts/Montserrat/Montserrat-ExtraLightItalic.ttf similarity index 100% rename from dal/dal/static/datacenterlight/fonts/Montserrat/Montserrat-ExtraLightItalic.ttf rename to dal/static/datacenterlight/fonts/Montserrat/Montserrat-ExtraLightItalic.ttf diff --git a/dal/dal/static/datacenterlight/fonts/Montserrat/Montserrat-Italic.ttf b/dal/static/datacenterlight/fonts/Montserrat/Montserrat-Italic.ttf similarity index 100% rename from dal/dal/static/datacenterlight/fonts/Montserrat/Montserrat-Italic.ttf rename to dal/static/datacenterlight/fonts/Montserrat/Montserrat-Italic.ttf diff --git a/dal/dal/static/datacenterlight/fonts/Montserrat/Montserrat-Light.ttf b/dal/static/datacenterlight/fonts/Montserrat/Montserrat-Light.ttf similarity index 100% rename from dal/dal/static/datacenterlight/fonts/Montserrat/Montserrat-Light.ttf rename to dal/static/datacenterlight/fonts/Montserrat/Montserrat-Light.ttf diff --git a/dal/dal/static/datacenterlight/fonts/Montserrat/Montserrat-LightItalic.ttf b/dal/static/datacenterlight/fonts/Montserrat/Montserrat-LightItalic.ttf similarity index 100% rename from dal/dal/static/datacenterlight/fonts/Montserrat/Montserrat-LightItalic.ttf rename to dal/static/datacenterlight/fonts/Montserrat/Montserrat-LightItalic.ttf diff --git a/dal/dal/static/datacenterlight/fonts/Montserrat/Montserrat-Medium.ttf b/dal/static/datacenterlight/fonts/Montserrat/Montserrat-Medium.ttf similarity index 100% rename from dal/dal/static/datacenterlight/fonts/Montserrat/Montserrat-Medium.ttf rename to dal/static/datacenterlight/fonts/Montserrat/Montserrat-Medium.ttf diff --git a/dal/dal/static/datacenterlight/fonts/Montserrat/Montserrat-MediumItalic.ttf b/dal/static/datacenterlight/fonts/Montserrat/Montserrat-MediumItalic.ttf similarity index 100% rename from dal/dal/static/datacenterlight/fonts/Montserrat/Montserrat-MediumItalic.ttf rename to dal/static/datacenterlight/fonts/Montserrat/Montserrat-MediumItalic.ttf diff --git a/dal/dal/static/datacenterlight/fonts/Montserrat/Montserrat-Regular.ttf b/dal/static/datacenterlight/fonts/Montserrat/Montserrat-Regular.ttf similarity index 100% rename from dal/dal/static/datacenterlight/fonts/Montserrat/Montserrat-Regular.ttf rename to dal/static/datacenterlight/fonts/Montserrat/Montserrat-Regular.ttf diff --git a/dal/dal/static/datacenterlight/fonts/Montserrat/Montserrat-SemiBold.ttf b/dal/static/datacenterlight/fonts/Montserrat/Montserrat-SemiBold.ttf similarity index 100% rename from dal/dal/static/datacenterlight/fonts/Montserrat/Montserrat-SemiBold.ttf rename to dal/static/datacenterlight/fonts/Montserrat/Montserrat-SemiBold.ttf diff --git a/dal/dal/static/datacenterlight/fonts/Montserrat/Montserrat-SemiBoldItalic.ttf b/dal/static/datacenterlight/fonts/Montserrat/Montserrat-SemiBoldItalic.ttf similarity index 100% rename from dal/dal/static/datacenterlight/fonts/Montserrat/Montserrat-SemiBoldItalic.ttf rename to dal/static/datacenterlight/fonts/Montserrat/Montserrat-SemiBoldItalic.ttf diff --git a/dal/dal/static/datacenterlight/fonts/Montserrat/Montserrat-Thin.ttf b/dal/static/datacenterlight/fonts/Montserrat/Montserrat-Thin.ttf similarity index 100% rename from dal/dal/static/datacenterlight/fonts/Montserrat/Montserrat-Thin.ttf rename to dal/static/datacenterlight/fonts/Montserrat/Montserrat-Thin.ttf diff --git a/dal/dal/static/datacenterlight/fonts/Montserrat/Montserrat-ThinItalic.ttf b/dal/static/datacenterlight/fonts/Montserrat/Montserrat-ThinItalic.ttf similarity index 100% rename from dal/dal/static/datacenterlight/fonts/Montserrat/Montserrat-ThinItalic.ttf rename to dal/static/datacenterlight/fonts/Montserrat/Montserrat-ThinItalic.ttf diff --git a/dal/dal/static/datacenterlight/fonts/Montserrat/OFL.txt b/dal/static/datacenterlight/fonts/Montserrat/OFL.txt similarity index 100% rename from dal/dal/static/datacenterlight/fonts/Montserrat/OFL.txt rename to dal/static/datacenterlight/fonts/Montserrat/OFL.txt diff --git a/dal/dal/static/datacenterlight/fonts/glyphicons-halflings-regular.eot b/dal/static/datacenterlight/fonts/glyphicons-halflings-regular.eot similarity index 100% rename from dal/dal/static/datacenterlight/fonts/glyphicons-halflings-regular.eot rename to dal/static/datacenterlight/fonts/glyphicons-halflings-regular.eot diff --git a/dal/dal/static/datacenterlight/fonts/glyphicons-halflings-regular.svg b/dal/static/datacenterlight/fonts/glyphicons-halflings-regular.svg similarity index 100% rename from dal/dal/static/datacenterlight/fonts/glyphicons-halflings-regular.svg rename to dal/static/datacenterlight/fonts/glyphicons-halflings-regular.svg diff --git a/dal/dal/static/datacenterlight/fonts/glyphicons-halflings-regular.ttf b/dal/static/datacenterlight/fonts/glyphicons-halflings-regular.ttf similarity index 100% rename from dal/dal/static/datacenterlight/fonts/glyphicons-halflings-regular.ttf rename to dal/static/datacenterlight/fonts/glyphicons-halflings-regular.ttf diff --git a/dal/dal/static/datacenterlight/fonts/glyphicons-halflings-regular.woff b/dal/static/datacenterlight/fonts/glyphicons-halflings-regular.woff similarity index 100% rename from dal/dal/static/datacenterlight/fonts/glyphicons-halflings-regular.woff rename to dal/static/datacenterlight/fonts/glyphicons-halflings-regular.woff diff --git a/dal/dal/static/datacenterlight/fonts/glyphicons-halflings-regular.woff2 b/dal/static/datacenterlight/fonts/glyphicons-halflings-regular.woff2 similarity index 100% rename from dal/dal/static/datacenterlight/fonts/glyphicons-halflings-regular.woff2 rename to dal/static/datacenterlight/fonts/glyphicons-halflings-regular.woff2 diff --git a/dal/dal/static/datacenterlight/img/Ceph_Logo.png b/dal/static/datacenterlight/img/Ceph_Logo.png similarity index 100% rename from dal/dal/static/datacenterlight/img/Ceph_Logo.png rename to dal/static/datacenterlight/img/Ceph_Logo.png diff --git a/dal/dal/static/datacenterlight/img/banner-bg copy.jpg b/dal/static/datacenterlight/img/banner-bg copy.jpg similarity index 100% rename from dal/dal/static/datacenterlight/img/banner-bg copy.jpg rename to dal/static/datacenterlight/img/banner-bg copy.jpg diff --git a/dal/dal/static/datacenterlight/img/banner-bg.jpg b/dal/static/datacenterlight/img/banner-bg.jpg similarity index 100% rename from dal/dal/static/datacenterlight/img/banner-bg.jpg rename to dal/static/datacenterlight/img/banner-bg.jpg diff --git a/dal/dal/static/datacenterlight/img/bg.png b/dal/static/datacenterlight/img/bg.png similarity index 100% rename from dal/dal/static/datacenterlight/img/bg.png rename to dal/static/datacenterlight/img/bg.png diff --git a/dal/dal/static/datacenterlight/img/cdistbyungleich.png b/dal/static/datacenterlight/img/cdistbyungleich.png similarity index 100% rename from dal/dal/static/datacenterlight/img/cdistbyungleich.png rename to dal/static/datacenterlight/img/cdistbyungleich.png diff --git a/dal/dal/static/datacenterlight/img/checkmark.png b/dal/static/datacenterlight/img/checkmark.png similarity index 100% rename from dal/dal/static/datacenterlight/img/checkmark.png rename to dal/static/datacenterlight/img/checkmark.png diff --git a/dal/dal/static/datacenterlight/img/configure.jpg b/dal/static/datacenterlight/img/configure.jpg similarity index 100% rename from dal/dal/static/datacenterlight/img/configure.jpg rename to dal/static/datacenterlight/img/configure.jpg diff --git a/dal/dal/static/datacenterlight/img/datacenterlight.png b/dal/static/datacenterlight/img/datacenterlight.png similarity index 100% rename from dal/dal/static/datacenterlight/img/datacenterlight.png rename to dal/static/datacenterlight/img/datacenterlight.png diff --git a/dal/dal/static/datacenterlight/img/dcl-email-bg.jpg b/dal/static/datacenterlight/img/dcl-email-bg.jpg similarity index 100% rename from dal/dal/static/datacenterlight/img/dcl-email-bg.jpg rename to dal/static/datacenterlight/img/dcl-email-bg.jpg diff --git a/dal/dal/static/datacenterlight/img/deluxeroom.jpg b/dal/static/datacenterlight/img/deluxeroom.jpg similarity index 100% rename from dal/dal/static/datacenterlight/img/deluxeroom.jpg rename to dal/static/datacenterlight/img/deluxeroom.jpg diff --git a/dal/dal/static/datacenterlight/img/devuan.png b/dal/static/datacenterlight/img/devuan.png similarity index 100% rename from dal/dal/static/datacenterlight/img/devuan.png rename to dal/static/datacenterlight/img/devuan.png diff --git a/dal/dal/static/datacenterlight/img/django.png b/dal/static/datacenterlight/img/django.png similarity index 100% rename from dal/dal/static/datacenterlight/img/django.png rename to dal/static/datacenterlight/img/django.png diff --git a/dal/dal/static/datacenterlight/img/dog.png b/dal/static/datacenterlight/img/dog.png similarity index 100% rename from dal/dal/static/datacenterlight/img/dog.png rename to dal/static/datacenterlight/img/dog.png diff --git a/dal/dal/static/datacenterlight/img/economy.jpg b/dal/static/datacenterlight/img/economy.jpg similarity index 100% rename from dal/dal/static/datacenterlight/img/economy.jpg rename to dal/static/datacenterlight/img/economy.jpg diff --git a/dal/dal/static/datacenterlight/img/facebook_logo.svg b/dal/static/datacenterlight/img/facebook_logo.svg similarity index 100% rename from dal/dal/static/datacenterlight/img/facebook_logo.svg rename to dal/static/datacenterlight/img/facebook_logo.svg diff --git a/dal/dal/static/datacenterlight/img/favicon.ico b/dal/static/datacenterlight/img/favicon.ico similarity index 100% rename from dal/dal/static/datacenterlight/img/favicon.ico rename to dal/static/datacenterlight/img/favicon.ico diff --git a/dal/dal/static/datacenterlight/img/header-bg.jpg b/dal/static/datacenterlight/img/header-bg.jpg similarity index 100% rename from dal/dal/static/datacenterlight/img/header-bg.jpg rename to dal/static/datacenterlight/img/header-bg.jpg diff --git a/dal/dal/static/datacenterlight/img/home.png b/dal/static/datacenterlight/img/home.png similarity index 100% rename from dal/dal/static/datacenterlight/img/home.png rename to dal/static/datacenterlight/img/home.png diff --git a/dal/dal/static/datacenterlight/img/how.png b/dal/static/datacenterlight/img/how.png similarity index 100% rename from dal/dal/static/datacenterlight/img/how.png rename to dal/static/datacenterlight/img/how.png diff --git a/dal/dal/static/datacenterlight/img/how1.png b/dal/static/datacenterlight/img/how1.png similarity index 100% rename from dal/dal/static/datacenterlight/img/how1.png rename to dal/static/datacenterlight/img/how1.png diff --git a/dal/dal/static/datacenterlight/img/how2.png b/dal/static/datacenterlight/img/how2.png similarity index 100% rename from dal/dal/static/datacenterlight/img/how2.png rename to dal/static/datacenterlight/img/how2.png diff --git a/dal/dal/static/datacenterlight/img/how3.png b/dal/static/datacenterlight/img/how3.png similarity index 100% rename from dal/dal/static/datacenterlight/img/how3.png rename to dal/static/datacenterlight/img/how3.png diff --git a/dal/dal/static/datacenterlight/img/how4.png b/dal/static/datacenterlight/img/how4.png similarity index 100% rename from dal/dal/static/datacenterlight/img/how4.png rename to dal/static/datacenterlight/img/how4.png diff --git a/dal/dal/static/datacenterlight/img/intro-bg.jpg b/dal/static/datacenterlight/img/intro-bg.jpg similarity index 100% rename from dal/dal/static/datacenterlight/img/intro-bg.jpg rename to dal/static/datacenterlight/img/intro-bg.jpg diff --git a/dal/dal/static/datacenterlight/img/ipad.png b/dal/static/datacenterlight/img/ipad.png similarity index 100% rename from dal/dal/static/datacenterlight/img/ipad.png rename to dal/static/datacenterlight/img/ipad.png diff --git a/dal/dal/static/datacenterlight/img/loading.gif b/dal/static/datacenterlight/img/loading.gif similarity index 100% rename from dal/dal/static/datacenterlight/img/loading.gif rename to dal/static/datacenterlight/img/loading.gif diff --git a/dal/dal/static/datacenterlight/img/logo_black.png b/dal/static/datacenterlight/img/logo_black.png similarity index 100% rename from dal/dal/static/datacenterlight/img/logo_black.png rename to dal/static/datacenterlight/img/logo_black.png diff --git a/dal/dal/static/datacenterlight/img/logo_black.svg b/dal/static/datacenterlight/img/logo_black.svg similarity index 100% rename from dal/dal/static/datacenterlight/img/logo_black.svg rename to dal/static/datacenterlight/img/logo_black.svg diff --git a/dal/dal/static/datacenterlight/img/logo_white.svg b/dal/static/datacenterlight/img/logo_white.svg similarity index 100% rename from dal/dal/static/datacenterlight/img/logo_white.svg rename to dal/static/datacenterlight/img/logo_white.svg diff --git a/dal/dal/static/datacenterlight/img/opennebula.png b/dal/static/datacenterlight/img/opennebula.png similarity index 100% rename from dal/dal/static/datacenterlight/img/opennebula.png rename to dal/static/datacenterlight/img/opennebula.png diff --git a/dal/dal/static/datacenterlight/img/pattern.jpg b/dal/static/datacenterlight/img/pattern.jpg similarity index 100% rename from dal/dal/static/datacenterlight/img/pattern.jpg rename to dal/static/datacenterlight/img/pattern.jpg diff --git a/dal/dal/static/datacenterlight/img/phones.png b/dal/static/datacenterlight/img/phones.png similarity index 100% rename from dal/dal/static/datacenterlight/img/phones.png rename to dal/static/datacenterlight/img/phones.png diff --git a/dal/dal/static/datacenterlight/img/presidentialroom.jpg b/dal/static/datacenterlight/img/presidentialroom.jpg similarity index 100% rename from dal/dal/static/datacenterlight/img/presidentialroom.jpg rename to dal/static/datacenterlight/img/presidentialroom.jpg diff --git a/dal/dal/static/datacenterlight/img/prometheus.png b/dal/static/datacenterlight/img/prometheus.png similarity index 100% rename from dal/dal/static/datacenterlight/img/prometheus.png rename to dal/static/datacenterlight/img/prometheus.png diff --git a/dal/dal/static/datacenterlight/img/python-logo.png b/dal/static/datacenterlight/img/python-logo.png similarity index 100% rename from dal/dal/static/datacenterlight/img/python-logo.png rename to dal/static/datacenterlight/img/python-logo.png diff --git a/dal/dal/static/datacenterlight/img/ssd.jpg b/dal/static/datacenterlight/img/ssd.jpg similarity index 100% rename from dal/dal/static/datacenterlight/img/ssd.jpg rename to dal/static/datacenterlight/img/ssd.jpg diff --git a/dal/dal/static/datacenterlight/img/standardroom.jpg b/dal/static/datacenterlight/img/standardroom.jpg similarity index 100% rename from dal/dal/static/datacenterlight/img/standardroom.jpg rename to dal/static/datacenterlight/img/standardroom.jpg diff --git a/dal/dal/static/datacenterlight/img/tayga.png b/dal/static/datacenterlight/img/tayga.png similarity index 100% rename from dal/dal/static/datacenterlight/img/tayga.png rename to dal/static/datacenterlight/img/tayga.png diff --git a/dal/dal/static/datacenterlight/img/ubuntu.png b/dal/static/datacenterlight/img/ubuntu.png similarity index 100% rename from dal/dal/static/datacenterlight/img/ubuntu.png rename to dal/static/datacenterlight/img/ubuntu.png diff --git a/dal/dal/static/datacenterlight/js/bootstrap-3.3.7.min.js b/dal/static/datacenterlight/js/bootstrap-3.3.7.min.js similarity index 100% rename from dal/dal/static/datacenterlight/js/bootstrap-3.3.7.min.js rename to dal/static/datacenterlight/js/bootstrap-3.3.7.min.js diff --git a/dal/dal/static/datacenterlight/js/form.js b/dal/static/datacenterlight/js/form.js similarity index 100% rename from dal/dal/static/datacenterlight/js/form.js rename to dal/static/datacenterlight/js/form.js diff --git a/dal/dal/static/datacenterlight/js/jquery-2.2.4.min.js b/dal/static/datacenterlight/js/jquery-2.2.4.min.js similarity index 100% rename from dal/dal/static/datacenterlight/js/jquery-2.2.4.min.js rename to dal/static/datacenterlight/js/jquery-2.2.4.min.js diff --git a/dal/dal/static/datacenterlight/js/main.js b/dal/static/datacenterlight/js/main.js similarity index 100% rename from dal/dal/static/datacenterlight/js/main.js rename to dal/static/datacenterlight/js/main.js diff --git a/dal/dal/static/hosting/card-django.png b/dal/static/hosting/card-django.png similarity index 100% rename from dal/dal/static/hosting/card-django.png rename to dal/static/hosting/card-django.png diff --git a/dal/dal/static/hosting/card-nodejs.png b/dal/static/hosting/card-nodejs.png similarity index 100% rename from dal/dal/static/hosting/card-nodejs.png rename to dal/static/hosting/card-nodejs.png diff --git a/dal/dal/static/hosting/card-rails.png b/dal/static/hosting/card-rails.png similarity index 100% rename from dal/dal/static/hosting/card-rails.png rename to dal/static/hosting/card-rails.png diff --git a/dal/dal/static/hosting/css/commons.css b/dal/static/hosting/css/commons.css similarity index 100% rename from dal/dal/static/hosting/css/commons.css rename to dal/static/hosting/css/commons.css diff --git a/dal/dal/static/hosting/css/dashboard.css b/dal/static/hosting/css/dashboard.css similarity index 100% rename from dal/dal/static/hosting/css/dashboard.css rename to dal/static/hosting/css/dashboard.css diff --git a/dal/dal/static/hosting/css/landing-page.css b/dal/static/hosting/css/landing-page.css similarity index 100% rename from dal/dal/static/hosting/css/landing-page.css rename to dal/static/hosting/css/landing-page.css diff --git a/dal/dal/static/hosting/css/nodejshosting.css b/dal/static/hosting/css/nodejshosting.css similarity index 100% rename from dal/dal/static/hosting/css/nodejshosting.css rename to dal/static/hosting/css/nodejshosting.css diff --git a/dal/dal/static/hosting/css/order.css b/dal/static/hosting/css/order.css similarity index 100% rename from dal/dal/static/hosting/css/order.css rename to dal/static/hosting/css/order.css diff --git a/dal/dal/static/hosting/css/orders.css b/dal/static/hosting/css/orders.css similarity index 100% rename from dal/dal/static/hosting/css/orders.css rename to dal/static/hosting/css/orders.css diff --git a/dal/dal/static/hosting/css/payment.css b/dal/static/hosting/css/payment.css similarity index 100% rename from dal/dal/static/hosting/css/payment.css rename to dal/static/hosting/css/payment.css diff --git a/dal/dal/static/hosting/css/price_calculator.css b/dal/static/hosting/css/price_calculator.css similarity index 100% rename from dal/dal/static/hosting/css/price_calculator.css rename to dal/static/hosting/css/price_calculator.css diff --git a/dal/dal/static/hosting/css/pricing.css b/dal/static/hosting/css/pricing.css similarity index 100% rename from dal/dal/static/hosting/css/pricing.css rename to dal/static/hosting/css/pricing.css diff --git a/dal/dal/static/hosting/css/user_keys.css b/dal/static/hosting/css/user_keys.css similarity index 100% rename from dal/dal/static/hosting/css/user_keys.css rename to dal/static/hosting/css/user_keys.css diff --git a/dal/dal/static/hosting/css/virtual-machine.css b/dal/static/hosting/css/virtual-machine.css similarity index 100% rename from dal/dal/static/hosting/css/virtual-machine.css rename to dal/static/hosting/css/virtual-machine.css diff --git a/dal/dal/static/hosting/django-intro-bg.png b/dal/static/hosting/django-intro-bg.png similarity index 100% rename from dal/dal/static/hosting/django-intro-bg.png rename to dal/static/hosting/django-intro-bg.png diff --git a/dal/dal/static/hosting/img/24-hours-support.svg b/dal/static/hosting/img/24-hours-support.svg similarity index 100% rename from dal/dal/static/hosting/img/24-hours-support.svg rename to dal/static/hosting/img/24-hours-support.svg diff --git a/dal/dal/static/hosting/img/CH_flag.png b/dal/static/hosting/img/CH_flag.png similarity index 100% rename from dal/dal/static/hosting/img/CH_flag.png rename to dal/static/hosting/img/CH_flag.png diff --git a/dal/dal/static/hosting/img/DE_flag.png b/dal/static/hosting/img/DE_flag.png similarity index 100% rename from dal/dal/static/hosting/img/DE_flag.png rename to dal/static/hosting/img/DE_flag.png diff --git a/dal/dal/static/hosting/img/ajax-loader.gif b/dal/static/hosting/img/ajax-loader.gif similarity index 100% rename from dal/dal/static/hosting/img/ajax-loader.gif rename to dal/static/hosting/img/ajax-loader.gif diff --git a/dal/dal/static/hosting/img/auth-bg-sm.jpg b/dal/static/hosting/img/auth-bg-sm.jpg similarity index 100% rename from dal/dal/static/hosting/img/auth-bg-sm.jpg rename to dal/static/hosting/img/auth-bg-sm.jpg diff --git a/dal/dal/static/hosting/img/auth-bg.jpg b/dal/static/hosting/img/auth-bg.jpg similarity index 100% rename from dal/dal/static/hosting/img/auth-bg.jpg rename to dal/static/hosting/img/auth-bg.jpg diff --git a/dal/dal/static/hosting/img/banner-bg copy.jpg b/dal/static/hosting/img/banner-bg copy.jpg similarity index 100% rename from dal/dal/static/hosting/img/banner-bg copy.jpg rename to dal/static/hosting/img/banner-bg copy.jpg diff --git a/dal/dal/static/hosting/img/banner-bg.jpg b/dal/static/hosting/img/banner-bg.jpg similarity index 100% rename from dal/dal/static/hosting/img/banner-bg.jpg rename to dal/static/hosting/img/banner-bg.jpg diff --git a/dal/dal/static/hosting/img/billing.svg b/dal/static/hosting/img/billing.svg similarity index 100% rename from dal/dal/static/hosting/img/billing.svg rename to dal/static/hosting/img/billing.svg diff --git a/dal/dal/static/hosting/img/card-django.png b/dal/static/hosting/img/card-django.png similarity index 100% rename from dal/dal/static/hosting/img/card-django.png rename to dal/static/hosting/img/card-django.png diff --git a/dal/dal/static/hosting/img/card-nodejs.png b/dal/static/hosting/img/card-nodejs.png similarity index 100% rename from dal/dal/static/hosting/img/card-nodejs.png rename to dal/static/hosting/img/card-nodejs.png diff --git a/dal/dal/static/hosting/img/card-rails.png b/dal/static/hosting/img/card-rails.png similarity index 100% rename from dal/dal/static/hosting/img/card-rails.png rename to dal/static/hosting/img/card-rails.png diff --git a/dal/dal/static/hosting/img/checkmark.png b/dal/static/hosting/img/checkmark.png similarity index 100% rename from dal/dal/static/hosting/img/checkmark.png rename to dal/static/hosting/img/checkmark.png diff --git a/dal/dal/static/hosting/img/configure.jpg b/dal/static/hosting/img/configure.jpg similarity index 100% rename from dal/dal/static/hosting/img/configure.jpg rename to dal/static/hosting/img/configure.jpg diff --git a/dal/dal/static/hosting/img/connected.svg b/dal/static/hosting/img/connected.svg similarity index 100% rename from dal/dal/static/hosting/img/connected.svg rename to dal/static/hosting/img/connected.svg diff --git a/dal/dal/static/hosting/img/copy.svg b/dal/static/hosting/img/copy.svg similarity index 100% rename from dal/dal/static/hosting/img/copy.svg rename to dal/static/hosting/img/copy.svg diff --git a/dal/dal/static/hosting/img/dashboard_settings.svg b/dal/static/hosting/img/dashboard_settings.svg similarity index 100% rename from dal/dal/static/hosting/img/dashboard_settings.svg rename to dal/static/hosting/img/dashboard_settings.svg diff --git a/dal/dal/static/hosting/img/delete.svg b/dal/static/hosting/img/delete.svg similarity index 100% rename from dal/dal/static/hosting/img/delete.svg rename to dal/static/hosting/img/delete.svg diff --git a/dal/dal/static/hosting/img/deluxeroom.jpg b/dal/static/hosting/img/deluxeroom.jpg similarity index 100% rename from dal/dal/static/hosting/img/deluxeroom.jpg rename to dal/static/hosting/img/deluxeroom.jpg diff --git a/dal/dal/static/hosting/img/django-intro-bg.png b/dal/static/hosting/img/django-intro-bg.png similarity index 100% rename from dal/dal/static/hosting/img/django-intro-bg.png rename to dal/static/hosting/img/django-intro-bg.png diff --git a/dal/dal/static/hosting/img/dog.png b/dal/static/hosting/img/dog.png similarity index 100% rename from dal/dal/static/hosting/img/dog.png rename to dal/static/hosting/img/dog.png diff --git a/dal/dal/static/hosting/img/economy.jpg b/dal/static/hosting/img/economy.jpg similarity index 100% rename from dal/dal/static/hosting/img/economy.jpg rename to dal/static/hosting/img/economy.jpg diff --git a/dal/dal/static/hosting/img/favicon.ico b/dal/static/hosting/img/favicon.ico similarity index 100% rename from dal/dal/static/hosting/img/favicon.ico rename to dal/static/hosting/img/favicon.ico diff --git a/dal/dal/static/hosting/img/g222.png b/dal/static/hosting/img/g222.png similarity index 100% rename from dal/dal/static/hosting/img/g222.png rename to dal/static/hosting/img/g222.png diff --git a/dal/dal/static/hosting/img/header-bg.jpg b/dal/static/hosting/img/header-bg.jpg similarity index 100% rename from dal/dal/static/hosting/img/header-bg.jpg rename to dal/static/hosting/img/header-bg.jpg diff --git a/dal/dal/static/hosting/img/home.png b/dal/static/hosting/img/home.png similarity index 100% rename from dal/dal/static/hosting/img/home.png rename to dal/static/hosting/img/home.png diff --git a/dal/dal/static/hosting/img/how.png b/dal/static/hosting/img/how.png similarity index 100% rename from dal/dal/static/hosting/img/how.png rename to dal/static/hosting/img/how.png diff --git a/dal/dal/static/hosting/img/how1.png b/dal/static/hosting/img/how1.png similarity index 100% rename from dal/dal/static/hosting/img/how1.png rename to dal/static/hosting/img/how1.png diff --git a/dal/dal/static/hosting/img/how2.png b/dal/static/hosting/img/how2.png similarity index 100% rename from dal/dal/static/hosting/img/how2.png rename to dal/static/hosting/img/how2.png diff --git a/dal/dal/static/hosting/img/how4.png b/dal/static/hosting/img/how4.png similarity index 100% rename from dal/dal/static/hosting/img/how4.png rename to dal/static/hosting/img/how4.png diff --git a/dal/dal/static/hosting/img/icon-pdf.svg b/dal/static/hosting/img/icon-pdf.svg similarity index 100% rename from dal/dal/static/hosting/img/icon-pdf.svg rename to dal/static/hosting/img/icon-pdf.svg diff --git a/dal/dal/static/hosting/img/icon-print.svg b/dal/static/hosting/img/icon-print.svg similarity index 100% rename from dal/dal/static/hosting/img/icon-print.svg rename to dal/static/hosting/img/icon-print.svg diff --git a/dal/dal/static/hosting/img/intro-bg.jpg b/dal/static/hosting/img/intro-bg.jpg similarity index 100% rename from dal/dal/static/hosting/img/intro-bg.jpg rename to dal/static/hosting/img/intro-bg.jpg diff --git a/dal/dal/static/hosting/img/ipad.png b/dal/static/hosting/img/ipad.png similarity index 100% rename from dal/dal/static/hosting/img/ipad.png rename to dal/static/hosting/img/ipad.png diff --git a/dal/dal/static/hosting/img/key.svg b/dal/static/hosting/img/key.svg similarity index 100% rename from dal/dal/static/hosting/img/key.svg rename to dal/static/hosting/img/key.svg diff --git a/dal/dal/static/hosting/img/login-bg.jpg b/dal/static/hosting/img/login-bg.jpg similarity index 100% rename from dal/dal/static/hosting/img/login-bg.jpg rename to dal/static/hosting/img/login-bg.jpg diff --git a/dal/dal/static/hosting/img/logo_black.png b/dal/static/hosting/img/logo_black.png similarity index 100% rename from dal/dal/static/hosting/img/logo_black.png rename to dal/static/hosting/img/logo_black.png diff --git a/dal/dal/static/hosting/img/logo_black.svg b/dal/static/hosting/img/logo_black.svg similarity index 100% rename from dal/dal/static/hosting/img/logo_black.svg rename to dal/static/hosting/img/logo_black.svg diff --git a/dal/dal/static/hosting/img/logo_white.svg b/dal/static/hosting/img/logo_white.svg similarity index 100% rename from dal/dal/static/hosting/img/logo_white.svg rename to dal/static/hosting/img/logo_white.svg diff --git a/dal/dal/static/hosting/img/nodejs-intro-bg.png b/dal/static/hosting/img/nodejs-intro-bg.png similarity index 100% rename from dal/dal/static/hosting/img/nodejs-intro-bg.png rename to dal/static/hosting/img/nodejs-intro-bg.png diff --git a/dal/dal/static/hosting/img/pattern.jpg b/dal/static/hosting/img/pattern.jpg similarity index 100% rename from dal/dal/static/hosting/img/pattern.jpg rename to dal/static/hosting/img/pattern.jpg diff --git a/dal/dal/static/hosting/img/pattern_original.jpg b/dal/static/hosting/img/pattern_original.jpg similarity index 100% rename from dal/dal/static/hosting/img/pattern_original.jpg rename to dal/static/hosting/img/pattern_original.jpg diff --git a/dal/dal/static/hosting/img/phones.png b/dal/static/hosting/img/phones.png similarity index 100% rename from dal/dal/static/hosting/img/phones.png rename to dal/static/hosting/img/phones.png diff --git a/dal/dal/static/hosting/img/plusVM.svg b/dal/static/hosting/img/plusVM.svg similarity index 100% rename from dal/dal/static/hosting/img/plusVM.svg rename to dal/static/hosting/img/plusVM.svg diff --git a/dal/dal/static/hosting/img/presidentialroom.jpg b/dal/static/hosting/img/presidentialroom.jpg similarity index 100% rename from dal/dal/static/hosting/img/presidentialroom.jpg rename to dal/static/hosting/img/presidentialroom.jpg diff --git a/dal/dal/static/hosting/img/rails-intro-bg.png b/dal/static/hosting/img/rails-intro-bg.png similarity index 100% rename from dal/dal/static/hosting/img/rails-intro-bg.png rename to dal/static/hosting/img/rails-intro-bg.png diff --git a/dal/dal/static/hosting/img/settings.svg b/dal/static/hosting/img/settings.svg similarity index 100% rename from dal/dal/static/hosting/img/settings.svg rename to dal/static/hosting/img/settings.svg diff --git a/dal/dal/static/hosting/img/shopping-cart.svg b/dal/static/hosting/img/shopping-cart.svg similarity index 100% rename from dal/dal/static/hosting/img/shopping-cart.svg rename to dal/static/hosting/img/shopping-cart.svg diff --git a/dal/dal/static/hosting/img/signup-bg.png b/dal/static/hosting/img/signup-bg.png similarity index 100% rename from dal/dal/static/hosting/img/signup-bg.png rename to dal/static/hosting/img/signup-bg.png diff --git a/dal/dal/static/hosting/img/standardroom.jpg b/dal/static/hosting/img/standardroom.jpg similarity index 100% rename from dal/dal/static/hosting/img/standardroom.jpg rename to dal/static/hosting/img/standardroom.jpg diff --git a/dal/dal/static/hosting/img/ubuntu.png b/dal/static/hosting/img/ubuntu.png similarity index 100% rename from dal/dal/static/hosting/img/ubuntu.png rename to dal/static/hosting/img/ubuntu.png diff --git a/dal/dal/static/hosting/img/vm.svg b/dal/static/hosting/img/vm.svg similarity index 100% rename from dal/dal/static/hosting/img/vm.svg rename to dal/static/hosting/img/vm.svg diff --git a/dal/dal/static/hosting/js/createvm.js b/dal/static/hosting/js/createvm.js similarity index 100% rename from dal/dal/static/hosting/js/createvm.js rename to dal/static/hosting/js/createvm.js diff --git a/dal/dal/static/hosting/js/gen-ssh-key.js b/dal/static/hosting/js/gen-ssh-key.js similarity index 100% rename from dal/dal/static/hosting/js/gen-ssh-key.js rename to dal/static/hosting/js/gen-ssh-key.js diff --git a/dal/dal/static/hosting/js/html2canvas.min.js b/dal/static/hosting/js/html2canvas.min.js similarity index 100% rename from dal/dal/static/hosting/js/html2canvas.min.js rename to dal/static/hosting/js/html2canvas.min.js diff --git a/dal/dal/static/hosting/js/html2pdf.min.js b/dal/static/hosting/js/html2pdf.min.js similarity index 100% rename from dal/dal/static/hosting/js/html2pdf.min.js rename to dal/static/hosting/js/html2pdf.min.js diff --git a/dal/dal/static/hosting/js/initial.js b/dal/static/hosting/js/initial.js similarity index 100% rename from dal/dal/static/hosting/js/initial.js rename to dal/static/hosting/js/initial.js diff --git a/dal/dal/static/hosting/js/order.js b/dal/static/hosting/js/order.js similarity index 100% rename from dal/dal/static/hosting/js/order.js rename to dal/static/hosting/js/order.js diff --git a/dal/dal/static/hosting/js/payment.js b/dal/static/hosting/js/payment.js similarity index 100% rename from dal/dal/static/hosting/js/payment.js rename to dal/static/hosting/js/payment.js diff --git a/dal/dal/static/hosting/js/pricing.js b/dal/static/hosting/js/pricing.js similarity index 100% rename from dal/dal/static/hosting/js/pricing.js rename to dal/static/hosting/js/pricing.js diff --git a/dal/dal/static/hosting/js/virtual_machine_detail.js b/dal/static/hosting/js/virtual_machine_detail.js similarity index 100% rename from dal/dal/static/hosting/js/virtual_machine_detail.js rename to dal/static/hosting/js/virtual_machine_detail.js diff --git a/dal/dal/static/hosting/nodejs-intro-bg.png b/dal/static/hosting/nodejs-intro-bg.png similarity index 100% rename from dal/dal/static/hosting/nodejs-intro-bg.png rename to dal/static/hosting/nodejs-intro-bg.png diff --git a/dal/dal/static/hosting/rails-intro-bg.png b/dal/static/hosting/rails-intro-bg.png similarity index 100% rename from dal/dal/static/hosting/rails-intro-bg.png rename to dal/static/hosting/rails-intro-bg.png diff --git a/dal/dal/templates/base.html b/dal/templates/base.html similarity index 100% rename from dal/dal/templates/base.html rename to dal/templates/base.html diff --git a/dal/dal/templates/base_short.html b/dal/templates/base_short.html similarity index 100% rename from dal/dal/templates/base_short.html rename to dal/templates/base_short.html diff --git a/dal/dal/templates/changeddata.html b/dal/templates/changeddata.html similarity index 100% rename from dal/dal/templates/changeddata.html rename to dal/templates/changeddata.html diff --git a/dal/dal/templates/changedpassword.html b/dal/templates/changedpassword.html similarity index 100% rename from dal/dal/templates/changedpassword.html rename to dal/templates/changedpassword.html diff --git a/dal/dal/templates/changepassword.html b/dal/templates/changepassword.html similarity index 100% rename from dal/dal/templates/changepassword.html rename to dal/templates/changepassword.html diff --git a/dal/dal/templates/changeuserdata.html b/dal/templates/changeuserdata.html similarity index 100% rename from dal/dal/templates/changeuserdata.html rename to dal/templates/changeuserdata.html diff --git a/dal/dal/templates/deleteaccount.html b/dal/templates/deleteaccount.html similarity index 100% rename from dal/dal/templates/deleteaccount.html rename to dal/templates/deleteaccount.html diff --git a/dal/dal/templates/deleteduser.html b/dal/templates/deleteduser.html similarity index 100% rename from dal/dal/templates/deleteduser.html rename to dal/templates/deleteduser.html diff --git a/dal/dal/templates/error.html b/dal/templates/error.html similarity index 100% rename from dal/dal/templates/error.html rename to dal/templates/error.html diff --git a/dal/dal/templates/hosting_login.html b/dal/templates/hosting_login.html similarity index 100% rename from dal/dal/templates/hosting_login.html rename to dal/templates/hosting_login.html diff --git a/dal/dal/templates/includes/_card_input.html b/dal/templates/includes/_card_input.html similarity index 100% rename from dal/dal/templates/includes/_card_input.html rename to dal/templates/includes/_card_input.html diff --git a/dal/dal/templates/includes/_contact.html b/dal/templates/includes/_contact.html similarity index 100% rename from dal/dal/templates/includes/_contact.html rename to dal/templates/includes/_contact.html diff --git a/dal/dal/templates/includes/_footer.html b/dal/templates/includes/_footer.html similarity index 100% rename from dal/dal/templates/includes/_footer.html rename to dal/templates/includes/_footer.html diff --git a/dal/dal/templates/includes/_header.html b/dal/templates/includes/_header.html similarity index 100% rename from dal/dal/templates/includes/_header.html rename to dal/templates/includes/_header.html diff --git a/dal/dal/templates/includes/_messages.html b/dal/templates/includes/_messages.html similarity index 100% rename from dal/dal/templates/includes/_messages.html rename to dal/templates/includes/_messages.html diff --git a/dal/dal/templates/includes/_navbar.html b/dal/templates/includes/_navbar.html similarity index 100% rename from dal/dal/templates/includes/_navbar.html rename to dal/templates/includes/_navbar.html diff --git a/dal/dal/templates/includes/_navbar_transparent.html b/dal/templates/includes/_navbar_transparent.html similarity index 100% rename from dal/dal/templates/includes/_navbar_transparent.html rename to dal/templates/includes/_navbar_transparent.html diff --git a/dal/dal/templates/includes/_navbar_user.html b/dal/templates/includes/_navbar_user.html similarity index 100% rename from dal/dal/templates/includes/_navbar_user.html rename to dal/templates/includes/_navbar_user.html diff --git a/dal/dal/templates/includes/_our_infrastructure.html b/dal/templates/includes/_our_infrastructure.html similarity index 100% rename from dal/dal/templates/includes/_our_infrastructure.html rename to dal/templates/includes/_our_infrastructure.html diff --git a/dal/dal/templates/includes/_pricing.html b/dal/templates/includes/_pricing.html similarity index 100% rename from dal/dal/templates/includes/_pricing.html rename to dal/templates/includes/_pricing.html diff --git a/dal/dal/templates/includes/_your_infrastructure.html b/dal/templates/includes/_your_infrastructure.html similarity index 100% rename from dal/dal/templates/includes/_your_infrastructure.html rename to dal/templates/includes/_your_infrastructure.html diff --git a/dal/dal/templates/landing.html b/dal/templates/landing.html similarity index 100% rename from dal/dal/templates/landing.html rename to dal/templates/landing.html diff --git a/dal/dal/templates/loginfailed.html b/dal/templates/loginfailed.html similarity index 100% rename from dal/dal/templates/loginfailed.html rename to dal/templates/loginfailed.html diff --git a/dal/dal/templates/mustbeloggedin.html b/dal/templates/mustbeloggedin.html similarity index 100% rename from dal/dal/templates/mustbeloggedin.html rename to dal/templates/mustbeloggedin.html diff --git a/dal/dal/templates/registeruser.html b/dal/templates/registeruser.html similarity index 100% rename from dal/dal/templates/registeruser.html rename to dal/templates/registeruser.html diff --git a/dal/dal/templates/resetpassword.html b/dal/templates/resetpassword.html similarity index 100% rename from dal/dal/templates/resetpassword.html rename to dal/templates/resetpassword.html diff --git a/dal/dal/templates/resetpasswordnew.html b/dal/templates/resetpasswordnew.html similarity index 100% rename from dal/dal/templates/resetpasswordnew.html rename to dal/templates/resetpasswordnew.html diff --git a/dal/dal/templates/send_resetrequest.html b/dal/templates/send_resetrequest.html similarity index 100% rename from dal/dal/templates/send_resetrequest.html rename to dal/templates/send_resetrequest.html diff --git a/dal/dal/templates/usercreated.html b/dal/templates/usercreated.html similarity index 100% rename from dal/dal/templates/usercreated.html rename to dal/templates/usercreated.html diff --git a/dal/dal/templates/useroptions.html b/dal/templates/useroptions.html similarity index 100% rename from dal/dal/templates/useroptions.html rename to dal/templates/useroptions.html diff --git a/dal/dal/urls.py b/dal/urls.py similarity index 100% rename from dal/dal/urls.py rename to dal/urls.py diff --git a/dal/dal/views.py b/dal/views.py similarity index 100% rename from dal/dal/views.py rename to dal/views.py diff --git a/dal/dal/wsgi.py b/dal/wsgi.py similarity index 100% rename from dal/dal/wsgi.py rename to dal/wsgi.py diff --git a/dal/manage.py b/manage.py similarity index 100% rename from dal/manage.py rename to manage.py From 1673d6e03ba37396e946f037acb23b65ee591c48 Mon Sep 17 00:00:00 2001 From: PCoder <purple.coder@yahoo.co.uk> Date: Sun, 17 Feb 2019 17:44:17 +0100 Subject: [PATCH 02/54] Update .gitignore --- .gitignore | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/.gitignore b/.gitignore index f7275bb..712a31c 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,41 @@ +*.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/ From 8b61db8dee1902ae116954bf505ae5da7156aef2 Mon Sep 17 00:00:00 2001 From: PCoder <purple.coder@yahoo.co.uk> Date: Sun, 17 Feb 2019 17:57:48 +0100 Subject: [PATCH 03/54] Simplify getting LDAP_USE_TLS --- dal/settings.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/dal/settings.py b/dal/settings.py index 7c30a2a..ee96962 100644 --- a/dal/settings.py +++ b/dal/settings.py @@ -28,8 +28,7 @@ search_base = os.environ['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) -if os.environ['LDAP_USE_TLS']: - AUTH_LDAP_START_TLS=True +AUTH_LDAP_START_TLS = os.environ.get('LDAP_USE_TLS', False) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) From 5ec63d8536d2c0786d9a4558b62f1aa7636fd4d2 Mon Sep 17 00:00:00 2001 From: PCoder <purple.coder@yahoo.co.uk> Date: Sun, 17 Feb 2019 18:08:36 +0100 Subject: [PATCH 04/54] Get ALLOWED_HOSTS and DEBUG from .env --- dal/settings.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/dal/settings.py b/dal/settings.py index ee96962..9fd3169 100644 --- a/dal/settings.py +++ b/dal/settings.py @@ -32,7 +32,9 @@ AUTH_LDAP_START_TLS = os.environ.get('LDAP_USE_TLS', False) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) -ALLOWED_HOSTS = [] +ALLOWED_HOSTS = os.environ.get('ALLOWED_HOSTS', 'localhost') + +DEBUG = os.environ.get('DEBUG', False) INSTALLED_APPS = [ 'django.contrib.admin', @@ -131,6 +133,3 @@ DATABASES = { } } SECRET_KEY = os.environ.get('SECRET_KEY') - -# SECURITY WARNING: don't run with debug turned on in production! -DEBUG = os.environ.get('DEBUG', False) From 876567f9337fd476d3b9d8e0163b8b88eb1735d5 Mon Sep 17 00:00:00 2001 From: PCoder <purple.coder@yahoo.co.uk> Date: Sun, 17 Feb 2019 18:20:56 +0100 Subject: [PATCH 05/54] Correct the way we get ALLOWED_HOSTS --- dal/settings.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dal/settings.py b/dal/settings.py index 9fd3169..8b467c2 100644 --- a/dal/settings.py +++ b/dal/settings.py @@ -32,10 +32,10 @@ AUTH_LDAP_START_TLS = os.environ.get('LDAP_USE_TLS', False) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) -ALLOWED_HOSTS = os.environ.get('ALLOWED_HOSTS', 'localhost') - DEBUG = os.environ.get('DEBUG', False) +ALLOWED_HOSTS = os.environ.get('ALLOWED_HOSTS', 'localhost').split(",") + INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', From c4c990a98d80ccdbf6b67bcedfdbae3770e4d0e5 Mon Sep 17 00:00:00 2001 From: PCoder <purple.coder@yahoo.co.uk> Date: Sun, 17 Feb 2019 18:25:12 +0100 Subject: [PATCH 06/54] More correction --- dal/settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dal/settings.py b/dal/settings.py index 8b467c2..2aa808d 100644 --- a/dal/settings.py +++ b/dal/settings.py @@ -34,7 +34,7 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) DEBUG = os.environ.get('DEBUG', False) -ALLOWED_HOSTS = os.environ.get('ALLOWED_HOSTS', 'localhost').split(",") +ALLOWED_HOSTS = (os.environ.get('ALLOWED_HOSTS', 'localhost')).split(",") INSTALLED_APPS = [ 'django.contrib.admin', From 467af3422c4a003018e98ece457c1bc5addda77a Mon Sep 17 00:00:00 2001 From: PCoder <purple.coder@yahoo.co.uk> Date: Mon, 18 Feb 2019 22:01:07 +0100 Subject: [PATCH 07/54] Update django bootstrap and filter requirements --- requirements.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/requirements.txt b/requirements.txt index 0767c8c..f6d34b1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,3 +2,5 @@ django django-auth-ldap python-ldap django-dotenv +django-bootstrap3 +django-filter==2.1.0 \ No newline at end of file From c571cf5c1d6cfb05e819afcf71a5f91a7492350b Mon Sep 17 00:00:00 2001 From: PCoder <purple.coder@yahoo.co.uk> Date: Mon, 18 Feb 2019 22:01:42 +0100 Subject: [PATCH 08/54] Add bootstrap3 to INSTALLED_APPS --- dal/settings.py | 1 + 1 file changed, 1 insertion(+) diff --git a/dal/settings.py b/dal/settings.py index 2aa808d..1cc50c3 100644 --- a/dal/settings.py +++ b/dal/settings.py @@ -43,6 +43,7 @@ INSTALLED_APPS = [ 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', + 'bootstrap3', 'dal', ] From dab31aa8537c476f908be92e2ddffedaf01ed8eb Mon Sep 17 00:00:00 2001 From: PCoder <purple.coder@yahoo.co.uk> Date: Mon, 18 Feb 2019 22:03:51 +0100 Subject: [PATCH 09/54] Remove unwanted code / refactor code --- dal/templates/includes/_footer.html | 32 -------- .../includes/_navbar_transparent.html | 1 - dal/templates/landing.html | 73 +++++++++---------- 3 files changed, 35 insertions(+), 71 deletions(-) diff --git a/dal/templates/includes/_footer.html b/dal/templates/includes/_footer.html index e61ed59..800f7dc 100644 --- a/dal/templates/includes/_footer.html +++ b/dal/templates/includes/_footer.html @@ -1,41 +1,9 @@ {% 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> diff --git a/dal/templates/includes/_navbar_transparent.html b/dal/templates/includes/_navbar_transparent.html index e413ace..1af4bcb 100644 --- a/dal/templates/includes/_navbar_transparent.html +++ b/dal/templates/includes/_navbar_transparent.html @@ -2,7 +2,6 @@ <style> .container { - background-color: lightgrey; color: black; } </style> diff --git a/dal/templates/landing.html b/dal/templates/landing.html index f56d2bb..6f31087 100644 --- a/dal/templates/landing.html +++ b/dal/templates/landing.html @@ -1,43 +1,40 @@ {% extends "base_short.html" %} -{% load staticfiles %} +{% load i18n 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> - + <div class="auth-container"> + <div class="auth-bg"></div> + <div class="auth-center"> + <div class="auth-content"> + <div class="auth-box"> + <h1 class="section-heading allcaps">{% trans "Log in" %}</h1> + {% include 'includes/_messages.html' %} + <form action="{% url 'index' %}" method="post" class="form" novalidated> + {% csrf_token %} + {% for field in form %} + {% bootstrap_field field show_label=False type='fields'%} + {% endfor %} + <p class="red">{{form.non_field_errors|striptags}}</p> + <div class="text-center"> + <button type="submit" class="btn choice-btn"> + {% trans "Log in" %} + </button> + </div> + <input type='hidden' name='next' value='{{request.GET.next}}'/> + </form> + <div class="auth-footer"> + <div> + {% trans "Don't have an account yet ?" %} +{# <a href="{% url 'signup' %}">{% trans "Sign up" %}</a>#} + </div> + <div> + or <a href="{% url 'reset_password' %}">{% trans "Forgot your password ?" %}</a><br> +{# or <a href="{% url 'resend_activation_link' %}">{% trans "Resend activation link" %}</a>#} + </div> + </div> + </div> + </div> + </div> + </div> {% endblock %} From eb4dc68b3298b71899ff411aa3fdc7082afa982f Mon Sep 17 00:00:00 2001 From: PCoder <purple.coder@yahoo.co.uk> Date: Tue, 19 Feb 2019 21:21:30 +0100 Subject: [PATCH 10/54] Create logs dir --- logs/.keep | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 logs/.keep diff --git a/logs/.keep b/logs/.keep new file mode 100644 index 0000000..e69de29 From b60ffe6b5883bb326f6d00b680b94364ba86ba90 Mon Sep 17 00:00:00 2001 From: PCoder <purple.coder@yahoo.co.uk> Date: Tue, 19 Feb 2019 23:15:07 +0100 Subject: [PATCH 11/54] Use python-decouple instead of django-dotenv + add logging --- dal/settings.py | 58 +++++++++++++++++++++++++++++++++++++++--------- requirements.txt | 4 ++-- 2 files changed, 49 insertions(+), 13 deletions(-) diff --git a/dal/settings.py b/dal/settings.py index 1cc50c3..db939af 100644 --- a/dal/settings.py +++ b/dal/settings.py @@ -11,28 +11,25 @@ https://docs.djangoproject.com/en/1.10/ref/settings/ """ import os -import dotenv +from decouple import config, Csv import ldap from django_auth_ldap.config import LDAPSearch, LDAPSearchUnion -# get config -dotenv.read_dotenv() - # LDAP setup -AUTH_LDAP_SERVER_URI = os.environ['LDAPSERVER'] -AUTH_LDAP_BIND_DN = os.environ['LDAPSEARCHUSER'] -AUTH_LDAP_BIND_PASSWORD = os.environ['LDAPSEARCHUSERPASSWORD'] +AUTH_LDAP_SERVER_URI = config('LDAPSERVER') +AUTH_LDAP_BIND_DN = config('LDAPSEARCHUSER') +AUTH_LDAP_BIND_PASSWORD = config('LDAPSEARCHUSERPASSWORD') # Search union over OUs -search_base = os.environ['LDAPSEARCH'].split() +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 = os.environ.get('LDAP_USE_TLS', False) +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 = os.environ.get('DEBUG', False) +DEBUG = config('DEBUG', default=False, cast=bool) ALLOWED_HOSTS = (os.environ.get('ALLOWED_HOSTS', 'localhost')).split(",") @@ -133,4 +130,43 @@ DATABASES = { 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), } } -SECRET_KEY = os.environ.get('SECRET_KEY') +SECRET_KEY = config('SECRET_KEY') + + +LOGGING = { + 'disable_existing_loggers': False, + 'version': 1, + 'formatters': { + 'standard': { + 'format': '%(asctime)s %(levelname)s %(name)s: %(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 os.environ.get('ENABLE_DEBUG_LOG', '').strip().lower() == "true": + loggers_dict = {} + modules_to_log_list = os.environ.get('MODULES_TO_LOG', 'django').split(',') + 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 diff --git a/requirements.txt b/requirements.txt index f6d34b1..3f3ab68 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ django django-auth-ldap python-ldap -django-dotenv django-bootstrap3 -django-filter==2.1.0 \ No newline at end of file +django-filter==2.1.0 +python-decouple From a6a6f8213b7d872d333152d8494367709435cd92 Mon Sep 17 00:00:00 2001 From: PCoder <purple.coder@yahoo.co.uk> Date: Tue, 19 Feb 2019 23:16:05 +0100 Subject: [PATCH 12/54] Add LoginForm --- dal/forms.py | 40 ++++++++++++++++++++++++++++++++++++++++ dal/views.py | 21 +++++---------------- 2 files changed, 45 insertions(+), 16 deletions(-) create mode 100644 dal/forms.py diff --git a/dal/forms.py b/dal/forms.py new file mode 100644 index 0000000..ecbf9bc --- /dev/null +++ b/dal/forms.py @@ -0,0 +1,40 @@ +from django import forms +from django.contrib.auth import authenticate +from django.shortcuts import render +from django.utils.translation import ugettext_lazy as _ + + +class LoginForm(forms.Form): + email = forms.CharField(widget=forms.TextInput()) + password = forms.CharField(widget=forms.PasswordInput()) + + class Meta: + fields = ['email', 'password'] + + def clean(self): + email = self.cleaned_data.get('email') + password = self.cleaned_data.get('password') + if self.errors: + return self.cleaned_data + is_auth = authenticate(username=email, 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_email(self): + email = self.cleaned_data.get('email') + return email + # try: + # CustomUser.objects.get(email=email) + # return email + # except CustomUser.DoesNotExist: + # raise forms.ValidationError(_("User does not exist")) + + def form_valid(self, form): + form.save() + return render(self.request, 'useroptions.html', {'user': self.get_context_data()}) + diff --git a/dal/views.py b/dal/views.py index 0e8cd19..5ef21ad 100644 --- a/dal/views.py +++ b/dal/views.py @@ -1,6 +1,6 @@ # Imports from django from django.shortcuts import render -from django.views.generic import View +from django.views.generic import View, FormView from django.contrib.auth import authenticate, login, logout from django.contrib.auth.models import User from django.http import HttpResponse, HttpResponseRedirect @@ -9,6 +9,7 @@ from django.urls import reverse_lazy from django.contrib.auth.tokens import PasswordResetTokenGenerator from django.core.mail import EmailMessage from .models import ResetToken +from .forms import LoginForm # Imports for the extra stuff not in django @@ -96,21 +97,9 @@ class LDAP(object): return sorted(uidlist)[-1] + 1 -class Index(View): - def get(self, request): - if request.user.is_authenticated: - return render(request, 'useroptions.html', { 'user': request.user } ) - return render(request, 'landing.html') - - 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') +class Index(FormView): + template_name = "landing.html" + form_class = LoginForm class Register(View): def get(self, request): From 47b714101b3570294c08c08ff7891e8643e235f0 Mon Sep 17 00:00:00 2001 From: PCoder <purple.coder@yahoo.co.uk> Date: Tue, 19 Feb 2019 23:39:47 +0100 Subject: [PATCH 13/54] Reformat code --- dal/forms.py | 6 ++++-- dal/urls.py | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/dal/forms.py b/dal/forms.py index ecbf9bc..3a0e7e9 100644 --- a/dal/forms.py +++ b/dal/forms.py @@ -19,10 +19,12 @@ class LoginForm(forms.Form): is_auth = authenticate(username=email, password=password) if not is_auth: raise forms.ValidationError( - _("Your username and/or password were incorrect.")) + _("Your username and/or password were incorrect.") + ) elif is_auth.validated == 0: raise forms.ValidationError( - _("Your account is not activated yet.")) + _("Your account is not activated yet.") + ) return self.cleaned_data def clean_email(self): diff --git a/dal/urls.py b/dal/urls.py index 10875b6..f977499 100644 --- a/dal/urls.py +++ b/dal/urls.py @@ -17,4 +17,4 @@ urlpatterns = [ path('reset/<str:user>/<str:token>/', ResetRequest.as_view()), path('reset/', ResetRequest.as_view(), name="reset"), path('', Index.as_view(), name="index"), -] +] \ No newline at end of file From 00bc02541d04d7740ebf408b126b82ea8de7c6e4 Mon Sep 17 00:00:00 2001 From: PCoder <purple.coder@yahoo.co.uk> Date: Tue, 19 Feb 2019 23:40:09 +0100 Subject: [PATCH 14/54] Add basic AUTH_LDAP_USER_ATTR_MAP --- dal/settings.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dal/settings.py b/dal/settings.py index db939af..81872b2 100644 --- a/dal/settings.py +++ b/dal/settings.py @@ -132,6 +132,11 @@ DATABASES = { } SECRET_KEY = config('SECRET_KEY') +AUTH_LDAP_USER_ATTR_MAP = { + "first_name": "givenName", + "last_name": "sn", + "email": "mail" +} LOGGING = { 'disable_existing_loggers': False, From 4d2ee8cf7710aefeb425c066a828124fbf1b76e4 Mon Sep 17 00:00:00 2001 From: PCoder <purple.coder@yahoo.co.uk> Date: Wed, 20 Feb 2019 00:25:51 +0100 Subject: [PATCH 15/54] Add UserAccountValidationDetail model --- dal/models.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/dal/models.py b/dal/models.py index 7dee319..676b103 100644 --- a/dal/models.py +++ b/dal/models.py @@ -1,4 +1,6 @@ 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 @@ -13,3 +15,18 @@ class ResetToken(models.Model): # 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) From e8f12e18d2ad6229340c18c97890b14fe0001343 Mon Sep 17 00:00:00 2001 From: PCoder <purple.coder@yahoo.co.uk> Date: Fri, 22 Feb 2019 06:06:36 +0100 Subject: [PATCH 16/54] Obtain ALLOWED_HOSTS from config --- dal/settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dal/settings.py b/dal/settings.py index 81872b2..867c8db 100644 --- a/dal/settings.py +++ b/dal/settings.py @@ -31,7 +31,7 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) DEBUG = config('DEBUG', default=False, cast=bool) -ALLOWED_HOSTS = (os.environ.get('ALLOWED_HOSTS', 'localhost')).split(",") +ALLOWED_HOSTS = config('ALLOWED_HOSTS', cast=Csv()) INSTALLED_APPS = [ 'django.contrib.admin', From 76c585cdf47d269c41b9025e2e4b5f85a618f824 Mon Sep 17 00:00:00 2001 From: PCoder <purple.coder@yahoo.co.uk> Date: Sat, 23 Feb 2019 09:19:20 +0100 Subject: [PATCH 17/54] Comment/clean unused code --- dal/forms.py | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/dal/forms.py b/dal/forms.py index 3a0e7e9..d4bc028 100644 --- a/dal/forms.py +++ b/dal/forms.py @@ -1,6 +1,5 @@ from django import forms from django.contrib.auth import authenticate -from django.shortcuts import render from django.utils.translation import ugettext_lazy as _ @@ -21,22 +20,12 @@ class LoginForm(forms.Form): raise forms.ValidationError( _("Your username and/or password were incorrect.") ) - elif is_auth.validated == 0: - raise forms.ValidationError( - _("Your account is not activated yet.") - ) + # elif is_auth.validated == 0: + # raise forms.ValidationError( + # _("Your account is not activated yet.") + # ) return self.cleaned_data def clean_email(self): email = self.cleaned_data.get('email') return email - # try: - # CustomUser.objects.get(email=email) - # return email - # except CustomUser.DoesNotExist: - # raise forms.ValidationError(_("User does not exist")) - - def form_valid(self, form): - form.save() - return render(self.request, 'useroptions.html', {'user': self.get_context_data()}) - From 5c96f5c186d3f2615cec44402b515410689422e3 Mon Sep 17 00:00:00 2001 From: PCoder <purple.coder@yahoo.co.uk> Date: Sat, 23 Feb 2019 09:20:58 +0100 Subject: [PATCH 18/54] Add form_valid to the index form --- dal/views.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/dal/views.py b/dal/views.py index 5ef21ad..afd0241 100644 --- a/dal/views.py +++ b/dal/views.py @@ -100,6 +100,16 @@ class LDAP(object): class Index(FormView): template_name = "landing.html" form_class = LoginForm + success_url = 'useroptions.html' + + def form_valid(self, form): + email = form.cleaned_data.get('email') + password = form.cleaned_data.get('password') + user = authenticate(username=email, password=password) + if user is not None: + login(self.request, user) + return render(self.request, 'useroptions.html', { 'user': user } ) + return render(self.request, 'loginfailed.html') class Register(View): def get(self, request): From a3dca06c35ec5364597e3995dbbc6d88b091e917 Mon Sep 17 00:00:00 2001 From: PCoder <purple.coder@yahoo.co.uk> Date: Sat, 23 Feb 2019 09:28:56 +0100 Subject: [PATCH 19/54] Use config instead of os.environ --- dal/settings.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/dal/settings.py b/dal/settings.py index 867c8db..6523348 100644 --- a/dal/settings.py +++ b/dal/settings.py @@ -161,9 +161,11 @@ LOGGING = { }, } -if os.environ.get('ENABLE_DEBUG_LOG', '').strip().lower() == "true": +if config('ENABLE_DEBUG_LOG', default=False, cast=bool): loggers_dict = {} - modules_to_log_list = os.environ.get('MODULES_TO_LOG', 'django').split(',') + modules_to_log_list = config( + 'MODULES_TO_LOG', default='django', cast=Csv() + ) for custom_module in modules_to_log_list: logger_item = { custom_module: { From 113fa2c454a6b2458b0d062fd068ba67c3336c09 Mon Sep 17 00:00:00 2001 From: PCoder <purple.coder@yahoo.co.uk> Date: Sat, 23 Feb 2019 18:45:21 +0100 Subject: [PATCH 20/54] Pickup env variables and use them --- dal/settings.py | 17 +++++++++++++++-- dal/views.py | 6 +++--- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/dal/settings.py b/dal/settings.py index 6523348..a716182 100644 --- a/dal/settings.py +++ b/dal/settings.py @@ -16,9 +16,16 @@ import ldap from django_auth_ldap.config import LDAPSearch, LDAPSearchUnion # LDAP setup +LDAP_SERVER = config('LDAP_SERVER') AUTH_LDAP_SERVER_URI = config('LDAPSERVER') -AUTH_LDAP_BIND_DN = config('LDAPSEARCHUSER') -AUTH_LDAP_BIND_PASSWORD = config('LDAPSEARCHUSERPASSWORD') + +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 + +LDAP_CUSTOMER_DN = config('LDAP_CUSTOMER_DN') +LDAP_USERS_DN = config('LDAP_USERS_DN') # Search union over OUs search_base = config('LDAPSEARCH').split() @@ -177,3 +184,9 @@ if config('ENABLE_DEBUG_LOG', default=False, cast=bool): 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) diff --git a/dal/views.py b/dal/views.py index afd0241..d8443df 100644 --- a/dal/views.py +++ b/dal/views.py @@ -32,8 +32,8 @@ from django.conf import settings class LDAP(object): def __init__(self): self.uri = settings.AUTH_LDAP_SERVER_URI - self.user = settings.AUTH_LDAP_BIND_DN - self.password = settings.AUTH_LDAP_BIND_PASSWORD + self.user = settings.LDAP_ADMIN_DN + self.password = settings.LDAP_ADMIN_PASSWORD # FIXME: take from settings self.search_base = os.environ['LDAPSEARCH'] @@ -41,7 +41,7 @@ class LDAP(object): self.search_filter = "objectClass=inetOrgPerson" # FIXME: hard coded - self.dn = "uid={{}},{}".format(os.environ['LDAPCREATE']) + self.dn = "uid={{}},{}".format(settings.LDAP_CUSTOMER_DN) self.gid = "10004" self.conn = ldap.initialize(self.uri) From 6a28b5135400ea3889e0348c22eba2b33712c88d Mon Sep 17 00:00:00 2001 From: PCoder <purple.coder@yahoo.co.uk> Date: Sat, 23 Feb 2019 18:45:53 +0100 Subject: [PATCH 21/54] Fix bug: check the posted username also with logged in user's username --- dal/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dal/views.py b/dal/views.py index d8443df..26f82f9 100644 --- a/dal/views.py +++ b/dal/views.py @@ -333,7 +333,7 @@ class ResetRequest(View): # get the hidden value of user user = request.POST.get("user") # some checks over the supplied data - if user == "" or not user: + if user == "" or not user or user != self.request.user.username: 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.' } ) From f6f688dcb59c920d1bbaeb7a4152d8dcb3afdf82 Mon Sep 17 00:00:00 2001 From: PCoder <purple.coder@yahoo.co.uk> Date: Sat, 23 Feb 2019 18:47:01 +0100 Subject: [PATCH 22/54] WIP: Add ungleich_ldap and use it to reset password --- dal/ungleich_ldap.py | 144 +++++++++++++++++++++++++++++++++++++++++++ dal/views.py | 14 +++-- 2 files changed, 153 insertions(+), 5 deletions(-) create mode 100644 dal/ungleich_ldap.py diff --git a/dal/ungleich_ldap.py b/dal/ungleich_ldap.py new file mode 100644 index 0000000..7b8bb7a --- /dev/null +++ b/dal/ungleich_ldap.py @@ -0,0 +1,144 @@ +import base64 +import hashlib +import random + +import ldap3 +from django.conf import settings + + +class LdapManager: + __instance = None + def __new__(cls): + if LdapManager.__instance is None: + LdapManager.__instance = object.__new__(cls) + return LdapManager.__instance + + def __init__(self): + """ + Initialize the LDAP subsystem. + """ + self.rng = random.SystemRandom() + self.server = ldap3.Server(settings.AUTH_LDAP_SERVER) + + + def get_admin_conn(self): + """ + Return a bound :class:`ldap3.Connection` instance which has write + permissions on the dn in which the user accounts reside. + """ + conn = self.get_conn(user=settings.LDAP_ADMIN_DN, + password=settings.LDAP_ADMIN_PASSWORD, + raise_exceptions=True) + conn.bind() + return conn + + + def get_conn(self, **kwargs): + """ + Return an unbound :class:`ldap3.Connection` which talks to the configured + LDAP server. + + The *kwargs* are passed to the constructor of :class:`ldap3.Connection` and + can be used to set *user*, *password* and other useful arguments. + """ + return ldap3.Connection(self.server, **kwargs) + + + def _ssha_password(self, password): + """ + Apply the SSHA password hashing scheme to the given *password*. + *password* must be a :class:`bytes` object, containing the utf-8 + encoded password. + + Return a :class:`bytes` object containing ``ascii``-compatible data + which can be used as LDAP value, e.g. after armoring it once more using + base64 or decoding it to unicode from ``ascii``. + """ + SALT_BYTES = 15 + + sha1 = hashlib.sha1() + salt = self.rng.getrandbits(SALT_BYTES * 8).to_bytes(SALT_BYTES, + "little") + sha1.update(password) + sha1.update(salt) + + digest = sha1.digest() + passwd = b"{SSHA}" + base64.b64encode(digest + salt) + return passwd + + + def create_user(self, loginname, displayname, mail, password): + """ + Create a new user in the LDAP storage. + + *loginname* must be a unique, valid user id. It is generally safe to + pass lower-case ascii letters here. The *loginname* of an account + cannot be changed. + + *displayname* is the name which is shown to other users. This can be + changed in the future. + + *mail* is a valid mail address of the user. + + *password* is the initial plain text password for the user. + """ + + conn = self.get_admin_conn() + try: + conn.add( + ("uid={uid}," + settings.LDAP_CUSTOMER_DN).format(uid=loginname), + ["inetOrgPerson"], + { + "uid": [loginname], + "cn": [displayname], + "sn": ["XXX"], + "givenName": ["XXX"], + "mail": [mail], + "userpassword": [self._ssha_password( + password.encode("utf-8") + )] + } + ) + finally: + conn.unbind() + + + def change_password(self, user_dn, new_password): + """ + Changes the password of the user identified by user_dn + + :param user_dn: str The distinguished name for identifying the user + :param new_password: str The new password string + :return: True if password was changed successfully False otherwise + """ + conn = self.get_admin_conn() + return_val = conn.modify( + user_dn, + { + "userpassword": ( + ldap3.MODIFY_REPLACE, + [self._ssha_password(new_password.encode("utf-8"))] + ) + } + ) + conn.unbind() + return return_val + + def check_user_exists(self, uid, is_customer=True): + """ + Check if the user with the given uid exists in the customer group. + + :param uid: str representing the user + :param is_customer: bool representing whether the current user is a + customer. By default, the user is a customer (assume) + :return: True if the user exists otherwise return False + """ + conn = self.get_admin_conn() + try: + result = conn.search( + settings.LDAP_CUSTOMER_DN if is_customer else settings.LDAP_USERS_DN, + search_filter='(uid={uid})'.format(uid=uid) + ) + finally: + conn.unbind() + return result diff --git a/dal/views.py b/dal/views.py index 26f82f9..8020e44 100644 --- a/dal/views.py +++ b/dal/views.py @@ -342,11 +342,15 @@ class ResetRequest(View): 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: + + from .ungleich_ldap import LdapManager + ldap_manager = LdapManager() + result = ldap_manager.change_password( + ("uid={uid}," + settings.LDAP_CUSTOMER_DN).format(uid=user), + password1 + ) + # password change successful + if result: return render(request, 'changedpassword.html', { 'user': user } ) # Something went wrong while changing the password else: From 122ee37e48fc759cd425c510dcaf02da03321a28 Mon Sep 17 00:00:00 2001 From: PCoder <purple.coder@yahoo.co.uk> Date: Sat, 23 Feb 2019 19:50:42 +0100 Subject: [PATCH 23/54] Use LdapManager to change password --- dal/settings.py | 1 + dal/views.py | 12 +++++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/dal/settings.py b/dal/settings.py index a716182..8ba5c15 100644 --- a/dal/settings.py +++ b/dal/settings.py @@ -23,6 +23,7 @@ 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') diff --git a/dal/views.py b/dal/views.py index 8020e44..419e3b0 100644 --- a/dal/views.py +++ b/dal/views.py @@ -405,12 +405,14 @@ class ChangePassword(View): 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) + from .ungleich_ldap import LdapManager + ldap_manager = LdapManager() + result = ldap_manager.change_password( + ("uid={uid}," + settings.LDAP_CUSTOMER_DN).format(uid=user), + password1 + ) # Password was changed - if result == True: + if result: return render(request, 'changedpassword.html', { 'user': user } ) # Password not changed, instead got some kind of error else: From fc139296fb3e557ef262afb8d262f86fae55b477 Mon Sep 17 00:00:00 2001 From: PCoder <purple.coder@yahoo.co.uk> Date: Sat, 23 Feb 2019 21:25:15 +0100 Subject: [PATCH 24/54] Add dal/ldap_max_uid_file to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 712a31c..38b9c32 100644 --- a/.gitignore +++ b/.gitignore @@ -39,3 +39,4 @@ secret-key *.mo venv/ +dal/ldap_max_uid_file From 0976d0dbcb478f4ab079d63846dd608d3423bb17 Mon Sep 17 00:00:00 2001 From: PCoder <purple.coder@yahoo.co.uk> Date: Sat, 23 Feb 2019 21:25:58 +0100 Subject: [PATCH 25/54] Obtain some LDAP configs from env --- dal/settings.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/dal/settings.py b/dal/settings.py index 8ba5c15..95c1b56 100644 --- a/dal/settings.py +++ b/dal/settings.py @@ -27,6 +27,15 @@ 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() From ac89df9254528fe235172a6dbcda7cbb10ac2b56 Mon Sep 17 00:00:00 2001 From: PCoder <purple.coder@yahoo.co.uk> Date: Sat, 23 Feb 2019 21:27:23 +0100 Subject: [PATCH 26/54] Add complete implementation of create_user --- dal/ungleich_ldap.py | 112 +++++++++++++++++++++++++++++++++---------- 1 file changed, 86 insertions(+), 26 deletions(-) diff --git a/dal/ungleich_ldap.py b/dal/ungleich_ldap.py index 7b8bb7a..54e8eee 100644 --- a/dal/ungleich_ldap.py +++ b/dal/ungleich_ldap.py @@ -4,6 +4,9 @@ import random import ldap3 from django.conf import settings +import logging + +logger = logging.getLogger(__name__) class LdapManager: @@ -67,38 +70,53 @@ class LdapManager: return passwd - def create_user(self, loginname, displayname, mail, password): - """ - Create a new user in the LDAP storage. - - *loginname* must be a unique, valid user id. It is generally safe to - pass lower-case ascii letters here. The *loginname* of an account - cannot be changed. - - *displayname* is the name which is shown to other users. This can be - changed in the future. - - *mail* is a valid mail address of the user. - - *password* is the initial plain text password for the user. - """ - + def create_user(self, user, password, firstname, lastname, email): conn = self.get_admin_conn() + uidNumber = self._get_max_uid() + 1 + logger.debug("uidNumber={uidNumber}".format(uidNumber=uidNumber)) + results = True + while results: + results = self.check_user_exists( + "", + True, + '(&(objectClass=inetOrgPerson)(objectClass=posixAccount)' + '(objectClass=top)(uidNumber={uidNumber}))'.format( + uidNumber=uidNumber + ) + ) + if results: + logger.debug( + "{uid} exists. Trying next.".format(uid=uidNumber) + ) + uidNumber += 1 + logger.debug("{uid} does not exist. Using it".format(uid=uidNumber)) + self._set_max_uid(uidNumber) try: conn.add( - ("uid={uid}," + settings.LDAP_CUSTOMER_DN).format(uid=loginname), - ["inetOrgPerson"], + ("uid={uid}," + settings.LDAP_CUSTOMER_DN).format(uid=user), + ["inetOrgPerson", "posixAccount", "ldapPublickey"], { - "uid": [loginname], - "cn": [displayname], - "sn": ["XXX"], - "givenName": ["XXX"], - "mail": [mail], - "userpassword": [self._ssha_password( + "uid": [user.encode("utf-8")], + "sn": [lastname.encode("utf-8")], + "givenName": [firstname.encode("utf-8")], + "cn": ["{} {}".format(firstname, lastname).encode("utf-8")], + "displayName": ["{} {}".format(firstname, lastname).encode("utf-8")], + "uidNumber": [str(uidNumber)], + "gidNumber": [str(settings.LDAP_CUSTOMER_GROUP_ID)], + "loginShell": ["/bin/bash"], + "homeDirectory": ["/home/{}".format(user).encode("utf-8")], + "mail": email.encode("utf-8"), + "userPassword": [self._ssha_password( password.encode("utf-8") )] } ) + logger.debug('Created user %s %s' % (user.encode('utf-8'), + uidNumber)) + except Exception as ex: + logger.debug('Could not create user %s' % user.encode('utf-8')) + logger.error("Exception: " + str(ex)) + raise Exception(ex) finally: conn.unbind() @@ -124,21 +142,63 @@ class LdapManager: conn.unbind() return return_val - def check_user_exists(self, uid, is_customer=True): + def check_user_exists(self, uid, is_customer=True, search_filter=""): """ Check if the user with the given uid exists in the customer group. :param uid: str representing the user :param is_customer: bool representing whether the current user is a customer. By default, the user is a customer (assume) + :param search_filter: str representing the filter condition to find + users. If its empty, the search finds the user with + the given uid. :return: True if the user exists otherwise return False """ conn = self.get_admin_conn() try: result = conn.search( settings.LDAP_CUSTOMER_DN if is_customer else settings.LDAP_USERS_DN, - search_filter='(uid={uid})'.format(uid=uid) + search_filter=search_filter if len(search_filter)> 0 else + '(uid={uid})'.format(uid=uid) ) finally: conn.unbind() return result + + def _set_max_uid(self, max_uid): + """ + a utility function to save max_uid value to a file + + :param max_uid: an integer representing the max uid + :return: + """ + with open(settings.LDAP_MAX_UID_FILE_PATH, 'w+') as handler: + handler.write(str(max_uid)) + + def _get_max_uid(self): + """ + A utility function to read the max uid value that was previously set + + :return: An integer representing the max uid value that was previously + set + """ + try: + with open(settings.LDAP_MAX_UID_FILE_PATH, 'r+') as handler: + try: + return_value = int(handler.read()) + except ValueError as ve: + logger.error( + "Error reading int value from {}. {}" + "Returning default value {} instead".format( + settings.LDAP_MAX_UID_PATH, + str(ve), + settings.LDAP_DEFAULT_START_UID + ) + ) + return_value = settings.LDAP_DEFAULT_START_UID + return return_value + except FileNotFoundError as fnfe: + logger.error("File not found : " + str(fnfe)) + return_value = settings.LDAP_DEFAULT_START_UID + logger.error("So, returning UID={}".format(return_value)) + return return_value From 57fe6a01432d95c257671efe16f24a1f436dad63 Mon Sep 17 00:00:00 2001 From: PCoder <purple.coder@yahoo.co.uk> Date: Sat, 23 Feb 2019 21:29:33 +0100 Subject: [PATCH 27/54] Call create_user code --- dal/views.py | 81 ++++------------------------------------------------ 1 file changed, 5 insertions(+), 76 deletions(-) diff --git a/dal/views.py b/dal/views.py index 419e3b0..a1ff4a2 100644 --- a/dal/views.py +++ b/dal/views.py @@ -10,6 +10,7 @@ from django.contrib.auth.tokens import PasswordResetTokenGenerator from django.core.mail import EmailMessage from .models import ResetToken from .forms import LoginForm +from .ungleich_ldap import LdapManager # Imports for the extra stuff not in django @@ -28,75 +29,6 @@ import ldap.modlist as modlist from django.conf import settings - -class LDAP(object): - def __init__(self): - self.uri = settings.AUTH_LDAP_SERVER_URI - self.user = settings.LDAP_ADMIN_DN - self.password = settings.LDAP_ADMIN_PASSWORD - - # FIXME: take from settings - self.search_base = os.environ['LDAPSEARCH'] - self.search_scope = ldap.SCOPE_SUBTREE - self.search_filter = "objectClass=inetOrgPerson" - - # FIXME: hard coded - self.dn = "uid={{}},{}".format(settings.LDAP_CUSTOMER_DN) - self.gid = "10004" - - self.conn = ldap.initialize(self.uri) - if settings.AUTH_LDAP_START_TLS: - self.conn.start_tls_s() - - self.conn.bind_s(self.user, self.password) - - - def check_user_exists(self, username): - exists = False - - result = self.conn.search_s(self.search_base, - self.search_scope, - self.dn.format(username)) - if len(result) > 0: - exists = True - - return exists - - def create_user(self, user, password, firstname, lastname, email): - dn = self.dn.format(user) - attr = { - "objectClass": ["inetOrgPerson".encode("utf-8"), - "posixAccount".encode("utf-8"), - "ldapPublickey".encode("utf-8")], - "uid": [user.encode("utf-8")], - "sn": [lastname.encode("utf-8")], - "givenName": [firstname.encode("utf-8")], - "cn": ["{} {}".format(firstname, lastname).encode("utf-8")], - "displayName": ["{} {}".format(firstname, lastname).encode("utf-8")], - "uidNumber": ["{}".format(self.get_new_uid_number()).encode("utf-8")], - "gidNumber": [self.gid.encode("utf-8")], - "loginShell": ["/bin/bash".encode("utf-8")], - "homeDirectory": ["/home/{}".format(user).encode("utf-8")], - "mail": email.encode("utf-8"), - "userPassword": password.encode("utf-8") - } - - ldif = modlist.addModlist(attr) - - print("just before: {} {}".format(dn, ldif)) - return self.conn.add_s(dn, ldif) - - def get_new_uid_number(self): - uidlist = [0] - - for result in self.conn.search_s(self.search_base, - self.search_scope, - self.search_filter): - if 'uidNumber' in result[1]: - uidlist.append(int(result[1]['uidNumber'][0])) - - return sorted(uidlist)[-1] + 1 - class Index(FormView): template_name = "landing.html" form_class = LoginForm @@ -117,8 +49,6 @@ class Register(View): # Someone filled out the register page, do some basic checks and throw it at nameko def post(self, request): - l = LDAP() - service = 'register an user' urlname = 'register' username = request.POST.get('username') @@ -126,9 +56,6 @@ class Register(View): if username == "" or not username: return render(request, 'error.html', { 'urlname': urlname, 'service': service, 'error': 'Please supply a username.' } ) - if l.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') if password1 != password2: @@ -155,7 +82,10 @@ class Register(View): pwd = r'%s' % password1 try: - l.create_user(username, pwd, firstname, lastname, email) + ldap_manager = LdapManager() + ldap_manager.create_user( + username, pwd, firstname, lastname, email + ) except Exception as e: return render(request, 'error.html', { 'urlname': urlname, 'service': service, @@ -343,7 +273,6 @@ class ResetRequest(View): 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 - from .ungleich_ldap import LdapManager ldap_manager = LdapManager() result = ldap_manager.change_password( ("uid={uid}," + settings.LDAP_CUSTOMER_DN).format(uid=user), From 89b535c3d60828330b6b1a6081012aaacebc9b27 Mon Sep 17 00:00:00 2001 From: PCoder <purple.coder@yahoo.co.uk> Date: Sat, 23 Feb 2019 21:37:27 +0100 Subject: [PATCH 28/54] Add ldap3 requirement --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index 3f3ab68..c68b636 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,3 +4,4 @@ python-ldap django-bootstrap3 django-filter==2.1.0 python-decouple +ldap3 From 017ca767bee2cf3aafca1398b0de1303b04c4ced Mon Sep 17 00:00:00 2001 From: PCoder <purple.coder@yahoo.co.uk> Date: Sun, 24 Feb 2019 14:43:24 +0100 Subject: [PATCH 29/54] Also return entries in the ldap search result --- dal/ungleich_ldap.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/dal/ungleich_ldap.py b/dal/ungleich_ldap.py index 54e8eee..24566fa 100644 --- a/dal/ungleich_ldap.py +++ b/dal/ungleich_ldap.py @@ -74,9 +74,9 @@ class LdapManager: conn = self.get_admin_conn() uidNumber = self._get_max_uid() + 1 logger.debug("uidNumber={uidNumber}".format(uidNumber=uidNumber)) - results = True - while results: - results = self.check_user_exists( + user_exists = True + while user_exists: + user_exists, _ = self.check_user_exists( "", True, '(&(objectClass=inetOrgPerson)(objectClass=posixAccount)' @@ -84,7 +84,7 @@ class LdapManager: uidNumber=uidNumber ) ) - if results: + if user_exists: logger.debug( "{uid} exists. Trying next.".format(uid=uidNumber) ) @@ -155,15 +155,17 @@ class LdapManager: :return: True if the user exists otherwise return False """ conn = self.get_admin_conn() + entries = [] try: result = conn.search( settings.LDAP_CUSTOMER_DN if is_customer else settings.LDAP_USERS_DN, search_filter=search_filter if len(search_filter)> 0 else '(uid={uid})'.format(uid=uid) ) + entries = conn.entries finally: conn.unbind() - return result + return result, entries def _set_max_uid(self, max_uid): """ From 3a867a4cd1b603e0a562ad07676f7fa32bb67202 Mon Sep 17 00:00:00 2001 From: PCoder <purple.coder@yahoo.co.uk> Date: Sun, 24 Feb 2019 15:25:59 +0100 Subject: [PATCH 30/54] Update check_user_exists to accept attributes and add doc --- dal/ungleich_ldap.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/dal/ungleich_ldap.py b/dal/ungleich_ldap.py index 24566fa..5e31b38 100644 --- a/dal/ungleich_ldap.py +++ b/dal/ungleich_ldap.py @@ -142,7 +142,8 @@ class LdapManager: conn.unbind() return return_val - def check_user_exists(self, uid, is_customer=True, search_filter=""): + def check_user_exists(self, uid, is_customer=True, search_filter="", + attributes=None): """ Check if the user with the given uid exists in the customer group. @@ -152,7 +153,11 @@ class LdapManager: :param search_filter: str representing the filter condition to find users. If its empty, the search finds the user with the given uid. - :return: True if the user exists otherwise return False + :param attributes: list A list of str representing all the attributes + to be obtained in the result entries + :return: tuple (bool, [ldap3.abstract.entry.Entry ..]) + A bool indicating if the user exists + A list of all entries obtained in the search """ conn = self.get_admin_conn() entries = [] @@ -160,7 +165,8 @@ class LdapManager: result = conn.search( settings.LDAP_CUSTOMER_DN if is_customer else settings.LDAP_USERS_DN, search_filter=search_filter if len(search_filter)> 0 else - '(uid={uid})'.format(uid=uid) + '(uid={uid})'.format(uid=uid), + attributes=attributes ) entries = conn.entries finally: From 3f7ab047a50e69aa3c520c74fc9eb628812a0e78 Mon Sep 17 00:00:00 2001 From: PCoder <purple.coder@yahoo.co.uk> Date: Sun, 24 Feb 2019 15:29:40 +0100 Subject: [PATCH 31/54] Use LdapManager call in change user details page --- dal/views.py | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/dal/views.py b/dal/views.py index a1ff4a2..a4e02f0 100644 --- a/dal/views.py +++ b/dal/views.py @@ -101,16 +101,30 @@ class ChangeData(View): 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 + + ldap_manager = LdapManager() + user_exists, entries = ldap_manager.check_user_exists( + uid=user.username, + is_customer=True, + attributes=['uid', 'givenName', 'sn', 'email'] + ) + + 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 '', + 'email': entries[0].email + if entries[0].email.value is not None else ''} + ) else: - return render(request, 'changeuserdata.html', { 'user': str(request.user), 'firstname': firstname, 'lastname': lastname, 'email': email } ) + return render(request, 'error.html', + {'urlname': urlname, 'service': service, + 'error': request.user.username}) # get the change request def post(self, request): From 7d09819ccbe07f72acf868c951024e7e0d879721 Mon Sep 17 00:00:00 2001 From: PCoder <purple.coder@yahoo.co.uk> Date: Sun, 24 Feb 2019 17:23:41 +0100 Subject: [PATCH 32/54] Improve logging --- dal/settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dal/settings.py b/dal/settings.py index 95c1b56..137c914 100644 --- a/dal/settings.py +++ b/dal/settings.py @@ -160,7 +160,7 @@ LOGGING = { 'version': 1, 'formatters': { 'standard': { - 'format': '%(asctime)s %(levelname)s %(name)s: %(message)s' + 'format': '%(asctime)s %(levelname)s %(name)s %(funcName)s %(lineno)d: %(message)s' } }, 'handlers': { From 3bc2e0a7e519b88813dbef2c173ca1e530cd2417 Mon Sep 17 00:00:00 2001 From: PCoder <purple.coder@yahoo.co.uk> Date: Sun, 24 Feb 2019 17:24:44 +0100 Subject: [PATCH 33/54] Take uid as parameter for change_password instead of user_dn --- dal/ungleich_ldap.py | 6 +++--- dal/views.py | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/dal/ungleich_ldap.py b/dal/ungleich_ldap.py index 5e31b38..c85ba48 100644 --- a/dal/ungleich_ldap.py +++ b/dal/ungleich_ldap.py @@ -121,17 +121,17 @@ class LdapManager: conn.unbind() - def change_password(self, user_dn, new_password): + def change_password(self, uid, new_password): """ Changes the password of the user identified by user_dn - :param user_dn: str The distinguished name for identifying the user + :param uid: str The uid that identifies the user :param new_password: str The new password string :return: True if password was changed successfully False otherwise """ conn = self.get_admin_conn() return_val = conn.modify( - user_dn, + ("uid={uid}," + settings.LDAP_CUSTOMER_DN).format(uid=uid), { "userpassword": ( ldap3.MODIFY_REPLACE, diff --git a/dal/views.py b/dal/views.py index a4e02f0..e9793b8 100644 --- a/dal/views.py +++ b/dal/views.py @@ -289,7 +289,7 @@ class ResetRequest(View): ldap_manager = LdapManager() result = ldap_manager.change_password( - ("uid={uid}," + settings.LDAP_CUSTOMER_DN).format(uid=user), + user, password1 ) # password change successful @@ -351,7 +351,7 @@ class ChangePassword(View): from .ungleich_ldap import LdapManager ldap_manager = LdapManager() result = ldap_manager.change_password( - ("uid={uid}," + settings.LDAP_CUSTOMER_DN).format(uid=user), + user, password1 ) # Password was changed From a909a9b5c5f14761f57973a334fac28013369564 Mon Sep 17 00:00:00 2001 From: PCoder <purple.coder@yahoo.co.uk> Date: Sun, 24 Feb 2019 17:25:13 +0100 Subject: [PATCH 34/54] Add change_user_details --- dal/ungleich_ldap.py | 27 +++++++++++++++++++++++++++ dal/views.py | 23 +++++++++++++---------- 2 files changed, 40 insertions(+), 10 deletions(-) diff --git a/dal/ungleich_ldap.py b/dal/ungleich_ldap.py index c85ba48..2ee70c5 100644 --- a/dal/ungleich_ldap.py +++ b/dal/ungleich_ldap.py @@ -142,6 +142,33 @@ class LdapManager: conn.unbind() return return_val + def change_user_details(self, uid, details): + """ + Updates the user details as per given values in kwargs of the user + identified by user_dn. + + Assumes that all attributes passed in kwargs are valid. + + :param uid: str The uid that identifies the user + :param details: dict A dictionary containing the new values + :return: True if user details were updated successfully False otherwise + """ + conn = self.get_admin_conn() + details_dict = {k: (ldap3.MODIFY_REPLACE, [v.encode("utf-8")]) for k, v in details.items()} + try: + return_val = conn.modify( + ("uid={uid}," + settings.LDAP_CUSTOMER_DN).format(uid=uid), + details_dict + ) + msg = "success" + except Exception as ex: + msg = str(ex) + logger.error("Exception: " + msg) + return_val = False + finally: + conn.unbind() + return return_val, msg + def check_user_exists(self, uid, is_customer=True, search_filter="", attributes=None): """ diff --git a/dal/views.py b/dal/views.py index e9793b8..e03a634 100644 --- a/dal/views.py +++ b/dal/views.py @@ -106,7 +106,7 @@ class ChangeData(View): user_exists, entries = ldap_manager.check_user_exists( uid=user.username, is_customer=True, - attributes=['uid', 'givenName', 'sn', 'email'] + attributes=['uid', 'givenName', 'sn', 'mail'] ) if user_exists: @@ -118,8 +118,8 @@ class ChangeData(View): if entries[0].givenName.value is not None else '', 'lastname': entries[0].sn if entries[0].sn.value is not None else '', - 'email': entries[0].email - if entries[0].email.value is not None else ''} + 'email': entries[0].mail + if entries[0].mail.value is not None else ''} ) else: return render(request, 'error.html', @@ -136,7 +136,6 @@ class ChangeData(View): 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') @@ -152,15 +151,19 @@ class ChangeData(View): 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) + + ldap_manager = LdapManager() + result, msg = ldap_manager.change_user_details( + uid=request.user.username, + details={"givenName": firstname, "sn": lastname, "mail": email} + ) + # Data change worked - if result == True: - return render(request, 'changeddata.html', { 'user': user, 'firstname': firstname, 'lastname': lastname, 'email': email } ) + 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: - return render(request, 'error.html', { 'urlname': urlname, 'service': service, 'error': result } ) + return render(request, 'error.html', { 'urlname': urlname, 'service': service, 'error': msg } ) class ResetPassword(View): From 4e9493f1980336c9e87bcaf68757413d4270717a Mon Sep 17 00:00:00 2001 From: PCoder <purple.coder@yahoo.co.uk> Date: Sun, 24 Feb 2019 17:44:48 +0100 Subject: [PATCH 35/54] Add delete_user --- dal/ungleich_ldap.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/dal/ungleich_ldap.py b/dal/ungleich_ldap.py index 2ee70c5..5d56d2a 100644 --- a/dal/ungleich_ldap.py +++ b/dal/ungleich_ldap.py @@ -200,6 +200,27 @@ class LdapManager: conn.unbind() return result, entries + def delete_user(self, uid): + """ + Deletes the user with the given uid from ldap + + :param uid: str representing the user + :return: True if the delete was successful False otherwise + """ + conn = self.get_admin_conn() + try: + return_val = conn.delete( + ("uid={uid}," + settings.LDAP_CUSTOMER_DN).format(uid=uid), + ) + msg = "success" + except Exception as ex: + msg = str(ex) + logger.error("Exception: " + msg) + return_val = False + finally: + conn.unbind() + return return_val, msg + def _set_max_uid(self, max_uid): """ a utility function to save max_uid value to a file From db4ffe79798ff292d35445466a8f04c0d6b5e7e0 Mon Sep 17 00:00:00 2001 From: PCoder <purple.coder@yahoo.co.uk> Date: Sun, 24 Feb 2019 17:45:39 +0100 Subject: [PATCH 36/54] Use LdapManager delete_user to delete the user's account --- dal/views.py | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/dal/views.py b/dal/views.py index e03a634..4c76c13 100644 --- a/dal/views.py +++ b/dal/views.py @@ -379,24 +379,27 @@ class DeleteAccount(View): # 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 + 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: return render(request, 'error.html', { 'urlname': urlname, 'service': service, 'error': result } ) From 6e0788097f44a7e9e3f0ba739eeb1ed39e44f0a5 Mon Sep 17 00:00:00 2001 From: PCoder <purple.coder@yahoo.co.uk> Date: Sun, 24 Feb 2019 17:46:44 +0100 Subject: [PATCH 37/54] Update message --- dal/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dal/views.py b/dal/views.py index 4c76c13..f697c90 100644 --- a/dal/views.py +++ b/dal/views.py @@ -401,7 +401,7 @@ class DeleteAccount(View): {'urlname': urlname, 'service': service, 'error': result}) else: - return render(request, 'error.html', { 'urlname': urlname, 'service': service, 'error': result } ) + return render(request, 'error.html', { 'urlname': urlname, 'service': service, 'error': 'Unknown user.' } ) # Log out the session class LogOut(View): From ccf600b6208ee1c1c18c2f2ab805dfdf5b3a090e Mon Sep 17 00:00:00 2001 From: PCoder <purple.coder@yahoo.co.uk> Date: Sun, 24 Feb 2019 18:37:40 +0100 Subject: [PATCH 38/54] Add initial migration for dal --- dal/migrations/0001_initial.py | 37 ++++++++++++++++++++++++++++++++++ dal/migrations/__init__.py | 0 2 files changed, 37 insertions(+) create mode 100644 dal/migrations/0001_initial.py create mode 100644 dal/migrations/__init__.py diff --git a/dal/migrations/0001_initial.py b/dal/migrations/0001_initial.py new file mode 100644 index 0000000..936a832 --- /dev/null +++ b/dal/migrations/0001_initial.py @@ -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)), + ], + ), + ] diff --git a/dal/migrations/__init__.py b/dal/migrations/__init__.py new file mode 100644 index 0000000..e69de29 From 9ce45e6f56b645fdb440ebb3c22c950a5ec65dd1 Mon Sep 17 00:00:00 2001 From: PCoder <purple.coder@yahoo.co.uk> Date: Sun, 24 Feb 2019 18:41:07 +0100 Subject: [PATCH 39/54] Set EMAIL_FROM_ADDRESS from env --- dal/settings.py | 2 ++ dal/views.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/dal/settings.py b/dal/settings.py index 137c914..b1210b1 100644 --- a/dal/settings.py +++ b/dal/settings.py @@ -48,6 +48,8 @@ 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') + ALLOWED_HOSTS = config('ALLOWED_HOSTS', cast=Csv()) INSTALLED_APPS = [ diff --git a/dal/views.py b/dal/views.py index f697c90..2ea6dfb 100644 --- a/dal/views.py +++ b/dal/views.py @@ -197,7 +197,7 @@ class ResetPassword(View): # 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'] + email_from = settings.EMAIL_FROM_ADDRESS to = ['%s <%s>' % (user, email)] subject = 'Password reset request for %s' % user link = self.build_reset_link(user, creationtime) From 16b02cfe3f81f26714e41f63cb93213285ec9d73 Mon Sep 17 00:00:00 2001 From: PCoder <purple.coder@yahoo.co.uk> Date: Sun, 24 Feb 2019 18:42:02 +0100 Subject: [PATCH 40/54] Create base_url from request rather than hard code --- dal/views.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/dal/views.py b/dal/views.py index 2ea6dfb..18ff70d 100644 --- a/dal/views.py +++ b/dal/views.py @@ -193,14 +193,14 @@ class ResetPassword(View): 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): + def email(self, user, email, base_url): # 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 = settings.EMAIL_FROM_ADDRESS to = ['%s <%s>' % (user, email)] subject = 'Password reset request for %s' % user - link = self.build_reset_link(user, creationtime) + 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 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' @@ -221,9 +221,8 @@ class ResetPassword(View): return result # Builds the reset link for the email and puts the token into the database - def build_reset_link(self, user, epochutc): + def build_reset_link(self, user, epochutc, base_url): # set up the data - host = 'account-staging.ungleich.ch' tokengen = PasswordResetTokenGenerator() # create some noise for use in the tokengenerator pseudouser = PseudoUser() @@ -234,7 +233,7 @@ class ResetPassword(View): 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) + link = (base_url + '/reset/%s/%s/') % (userpart.decode('utf-8'), token) return link From acff3fc59213239cb4abf54db74d6810bbdf87bd Mon Sep 17 00:00:00 2001 From: PCoder <purple.coder@yahoo.co.uk> Date: Sun, 24 Feb 2019 18:42:27 +0100 Subject: [PATCH 41/54] Use LdapManager in password reset too --- dal/views.py | 54 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 15 deletions(-) diff --git a/dal/views.py b/dal/views.py index 18ff70d..334a197 100644 --- a/dal/views.py +++ b/dal/views.py @@ -175,22 +175,46 @@ class ResetPassword(View): 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 + ldap_manager = LdapManager() + user_exists, entries = ldap_manager.check_user_exists( + uid=user, + attributes=['uid', 'givenName', 'sn', 'mail'] + ) + if user_exists and request.user.username == user: + # 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} + ) else: - return render(request, 'error.html', { 'urlname': urlname, 'service': service, 'error': emailsend } ) + return render( + request, 'error.html', + { 'urlname': urlname, 'service': service, + 'error': 'The user does not exist.' } + ) # Sends an email to the user with the 24h active link for a password reset def email(self, user, email, base_url): From 0591a186d8e9a49183decf08496f0c9b6d7f5869 Mon Sep 17 00:00:00 2001 From: PCoder <purple.coder@yahoo.co.uk> Date: Sun, 24 Feb 2019 19:28:09 +0100 Subject: [PATCH 42/54] Add EMAIL settings --- dal/settings.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dal/settings.py b/dal/settings.py index b1210b1..9779679 100644 --- a/dal/settings.py +++ b/dal/settings.py @@ -50,6 +50,10 @@ 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 = [ From c3b8f7b553314e28ee76efe580cacf74010eeb6c Mon Sep 17 00:00:00 2001 From: PCoder <purple.coder@yahoo.co.uk> Date: Sun, 24 Feb 2019 20:13:09 +0100 Subject: [PATCH 43/54] Add LoginRequiredMixin mixin for various views --- dal/urls.py | 2 +- dal/views.py | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/dal/urls.py b/dal/urls.py index f977499..b5f4a3a 100644 --- a/dal/urls.py +++ b/dal/urls.py @@ -16,5 +16,5 @@ urlpatterns = [ path('logout/', LogOut.as_view(), name="logout"), path('reset/<str:user>/<str:token>/', ResetRequest.as_view()), path('reset/', ResetRequest.as_view(), name="reset"), - path('', Index.as_view(), name="index"), + path('', Index.as_view(), name="login_index"), ] \ No newline at end of file diff --git a/dal/views.py b/dal/views.py index 334a197..1b055fa 100644 --- a/dal/views.py +++ b/dal/views.py @@ -27,6 +27,7 @@ import ldap import ldap.modlist as modlist from django.conf import settings +from django.contrib.auth.mixins import LoginRequiredMixin class Index(FormView): @@ -93,7 +94,7 @@ class Register(View): return render(request, 'usercreated.html', { 'user': username } ) -class ChangeData(View): +class ChangeData(LoginRequiredMixin, View): # provide the form for the change request def get(self, request): urlname = 'change_data' @@ -166,7 +167,8 @@ class ChangeData(View): return render(request, 'error.html', { 'urlname': urlname, 'service': service, 'error': msg } ) -class ResetPassword(View): +class ResetPassword(LoginRequiredMixin, View): + login_url = reverse_lazy('login_index') def get(self, request): return render(request, 'resetpassword.html') @@ -339,7 +341,7 @@ class ResetRequest(View): # The logged in user can change the password here -class ChangePassword(View): +class ChangePassword(LoginRequiredMixin, View): # Presents the page for a logged in user def get(self, request): @@ -389,7 +391,7 @@ class ChangePassword(View): # Deletes an account -class DeleteAccount(View): +class DeleteAccount(LoginRequiredMixin, View): # Show the basic form for deleting an account def get(self, request): return render(request, 'deleteaccount.html') From f61023d01aa342253627c9d61f5bacb81c3b4fb9 Mon Sep 17 00:00:00 2001 From: PCoder <purple.coder@yahoo.co.uk> Date: Sun, 24 Feb 2019 20:14:49 +0100 Subject: [PATCH 44/54] Take user to logged in page when already authenticated --- dal/views.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/dal/views.py b/dal/views.py index 1b055fa..0dcaeea 100644 --- a/dal/views.py +++ b/dal/views.py @@ -8,6 +8,7 @@ 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 django.views.decorators.cache import cache_control from .models import ResetToken from .forms import LoginForm from .ungleich_ldap import LdapManager @@ -44,6 +45,14 @@ class Index(FormView): return render(self.request, 'useroptions.html', { 'user': user } ) return render(self.request, 'loginfailed.html') + @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) + + class Register(View): def get(self, request): return render(request, 'registeruser.html') From 5903e10d8743145af3035c707389664c93be746c Mon Sep 17 00:00:00 2001 From: PCoder <purple.coder@yahoo.co.uk> Date: Sun, 24 Feb 2019 20:15:52 +0100 Subject: [PATCH 45/54] Redirect user to login page after logout --- dal/views.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/dal/views.py b/dal/views.py index 0dcaeea..fb28dd3 100644 --- a/dal/views.py +++ b/dal/views.py @@ -441,7 +441,13 @@ class DeleteAccount(LoginRequiredMixin, View): class LogOut(View): def get(self, request): logout(request) - return HttpResponse("You have been logged out.", status=200) + return HttpResponse( + "You have been logged out. You will be redirected in 2 seconds." + "<script>" + "setTimeout(function (){document.location.href='/';}, 2000);" + "</script>", + status=200 + ) From d4a02dc57109697ad101cbee0e5bd55d82f6ec74 Mon Sep 17 00:00:00 2001 From: PCoder <purple.coder@yahoo.co.uk> Date: Sun, 24 Feb 2019 20:16:10 +0100 Subject: [PATCH 46/54] Remove unused imports --- dal/views.py | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/dal/views.py b/dal/views.py index fb28dd3..6f73602 100644 --- a/dal/views.py +++ b/dal/views.py @@ -2,8 +2,7 @@ from django.shortcuts import render from django.views.generic import View, FormView from django.contrib.auth import authenticate, login, logout -from django.contrib.auth.models import User -from django.http import HttpResponse, HttpResponseRedirect +from django.http import HttpResponse from django.core.validators import validate_email, ValidationError from django.urls import reverse_lazy from django.contrib.auth.tokens import PasswordResetTokenGenerator @@ -21,12 +20,6 @@ from datetime import datetime from random import choice, randint import string -import os - -# Use ldap, like django_auth_backend -import ldap -import ldap.modlist as modlist - from django.conf import settings from django.contrib.auth.mixins import LoginRequiredMixin From 14949cedb7ce42581f39e351aefaa37db88d2a79 Mon Sep 17 00:00:00 2001 From: PCoder <purple.coder@yahoo.co.uk> Date: Sun, 24 Feb 2019 20:34:08 +0100 Subject: [PATCH 47/54] Add register link to landing.html --- dal/templates/landing.html | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/dal/templates/landing.html b/dal/templates/landing.html index 6f31087..741fd74 100644 --- a/dal/templates/landing.html +++ b/dal/templates/landing.html @@ -25,12 +25,10 @@ </form> <div class="auth-footer"> <div> - {% trans "Don't have an account yet ?" %} -{# <a href="{% url 'signup' %}">{% trans "Sign up" %}</a>#} + {% trans "Don't have an account yet ?" %} <a href="/register">{% trans "Sign up" %}</a> </div> <div> or <a href="{% url 'reset_password' %}">{% trans "Forgot your password ?" %}</a><br> -{# or <a href="{% url 'resend_activation_link' %}">{% trans "Resend activation link" %}</a>#} </div> </div> </div> From a20e9479c8b5c43597a17296423a20528921a5fb Mon Sep 17 00:00:00 2001 From: PCoder <purple.coder@yahoo.co.uk> Date: Sun, 24 Feb 2019 20:34:53 +0100 Subject: [PATCH 48/54] Add login_url for all LoginRequiredMixin views --- dal/views.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dal/views.py b/dal/views.py index 6f73602..a3f33c5 100644 --- a/dal/views.py +++ b/dal/views.py @@ -97,6 +97,7 @@ class Register(View): return render(request, 'usercreated.html', { 'user': username } ) class ChangeData(LoginRequiredMixin, View): + login_url = reverse_lazy('login_index') # provide the form for the change request def get(self, request): urlname = 'change_data' @@ -344,7 +345,7 @@ class ResetRequest(View): # The logged in user can change the password here class ChangePassword(LoginRequiredMixin, View): - + login_url = reverse_lazy('login_index') # Presents the page for a logged in user def get(self, request): if not request.user.is_authenticated: @@ -394,6 +395,7 @@ class ChangePassword(LoginRequiredMixin, View): # Deletes an account class DeleteAccount(LoginRequiredMixin, View): + login_url = reverse_lazy('login_index') # Show the basic form for deleting an account def get(self, request): return render(request, 'deleteaccount.html') From c0264e5dda090c724dad109e744fb2656eb48e18 Mon Sep 17 00:00:00 2001 From: PCoder <purple.coder@yahoo.co.uk> Date: Sun, 24 Feb 2019 20:35:25 +0100 Subject: [PATCH 49/54] Remove LoginRequiredMixin for ResetPassword view As this can be done even when the user is logged out --- dal/views.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/dal/views.py b/dal/views.py index a3f33c5..35fa4d1 100644 --- a/dal/views.py +++ b/dal/views.py @@ -170,8 +170,7 @@ class ChangeData(LoginRequiredMixin, View): return render(request, 'error.html', { 'urlname': urlname, 'service': service, 'error': msg } ) -class ResetPassword(LoginRequiredMixin, View): - login_url = reverse_lazy('login_index') +class ResetPassword(View): def get(self, request): return render(request, 'resetpassword.html') @@ -185,7 +184,7 @@ class ResetPassword(LoginRequiredMixin, View): uid=user, attributes=['uid', 'givenName', 'sn', 'mail'] ) - if user_exists and request.user.username == user: + if user_exists: # user exists, so try to get email # with get_pool().next() as rpc: # (state, tmp1, tmp2, email) = rpc.getuserdata.get_data(user) From bf3b3b364faa0866a7ab8335a3ce303590835e9a Mon Sep 17 00:00:00 2001 From: PCoder <purple.coder@yahoo.co.uk> Date: Sun, 24 Feb 2019 22:21:55 +0100 Subject: [PATCH 50/54] Get ENTIRE_SEARCH_BASE from env --- dal/settings.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dal/settings.py b/dal/settings.py index 9779679..a302eac 100644 --- a/dal/settings.py +++ b/dal/settings.py @@ -161,6 +161,8 @@ AUTH_LDAP_USER_ATTR_MAP = { "email": "mail" } +ENTIRE_SEARCH_BASE = config("ENTIRE_SEARCH_BASE") + LOGGING = { 'disable_existing_loggers': False, 'version': 1, From a5e91ffda286eb79542cf4ef3b1015bbb064cc78 Mon Sep 17 00:00:00 2001 From: PCoder <purple.coder@yahoo.co.uk> Date: Sun, 24 Feb 2019 22:23:43 +0100 Subject: [PATCH 51/54] Simplify search_base logic --- dal/ungleich_ldap.py | 54 ++++++++++++++++++++++++++++---------------- dal/views.py | 12 +++------- 2 files changed, 38 insertions(+), 28 deletions(-) diff --git a/dal/ungleich_ldap.py b/dal/ungleich_ldap.py index 5d56d2a..373e927 100644 --- a/dal/ungleich_ldap.py +++ b/dal/ungleich_ldap.py @@ -78,7 +78,6 @@ class LdapManager: while user_exists: user_exists, _ = self.check_user_exists( "", - True, '(&(objectClass=inetOrgPerson)(objectClass=posixAccount)' '(objectClass=top)(uidNumber={uidNumber}))'.format( uidNumber=uidNumber @@ -154,34 +153,51 @@ class LdapManager: :return: True if user details were updated successfully False otherwise """ conn = self.get_admin_conn() - details_dict = {k: (ldap3.MODIFY_REPLACE, [v.encode("utf-8")]) for k, v in details.items()} - try: - return_val = conn.modify( - ("uid={uid}," + settings.LDAP_CUSTOMER_DN).format(uid=uid), - details_dict - ) - msg = "success" - except Exception as ex: - msg = str(ex) - logger.error("Exception: " + msg) - return_val = False - finally: - conn.unbind() + + # Make sure the user exists first to change his/her details + user_exists, entries = self.check_user_exists( + uid=uid, + attributes=['uid', 'givenName', 'sn', 'mail', 'gidNumber'], + search_base=settings.ENTIRE_SEARCH_BASE + ) + + + if user_exists: + details_dict = {k: (ldap3.MODIFY_REPLACE, [v.encode("utf-8")]) for + k, v in details.items()} + try: + return_val = conn.modify( + ("uid={uid}," + settings.LDAP_CUSTOMER_DN + if entries[0].gidNumber.value == settings.LDAP_CUSTOMER_GROUP_ID + else settings.LDAP_USERS_DN).format(uid=uid), + details_dict + ) + msg = "success" + except Exception as ex: + msg = str(ex) + logger.error("Exception: " + msg) + return_val = False + finally: + conn.unbind() + else: + msg = "User {} not found".format(uid) + logger.error(msg) + raise Exception(msg) + return return_val, msg - def check_user_exists(self, uid, is_customer=True, search_filter="", - attributes=None): + def check_user_exists(self, uid, search_filter="", attributes=None, + search_base=settings.LDAP_CUSTOMER_DN): """ Check if the user with the given uid exists in the customer group. :param uid: str representing the user - :param is_customer: bool representing whether the current user is a - customer. By default, the user is a customer (assume) :param search_filter: str representing the filter condition to find users. If its empty, the search finds the user with the given uid. :param attributes: list A list of str representing all the attributes to be obtained in the result entries + :param search_base: str :return: tuple (bool, [ldap3.abstract.entry.Entry ..]) A bool indicating if the user exists A list of all entries obtained in the search @@ -190,7 +206,7 @@ class LdapManager: entries = [] try: result = conn.search( - settings.LDAP_CUSTOMER_DN if is_customer else settings.LDAP_USERS_DN, + search_base=search_base, search_filter=search_filter if len(search_filter)> 0 else '(uid={uid})'.format(uid=uid), attributes=attributes diff --git a/dal/views.py b/dal/views.py index 35fa4d1..ea8917a 100644 --- a/dal/views.py +++ b/dal/views.py @@ -102,15 +102,13 @@ class ChangeData(LoginRequiredMixin, View): 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 + user = request.user ldap_manager = LdapManager() user_exists, entries = ldap_manager.check_user_exists( uid=user.username, - is_customer=True, - attributes=['uid', 'givenName', 'sn', 'mail'] + attributes=['uid', 'givenName', 'sn', 'mail'], + search_base=settings.ENTIRE_SEARCH_BASE ) if user_exists: @@ -136,10 +134,6 @@ class ChangeData(LoginRequiredMixin, View): 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') - firstname = request.POST.get('firstname') lastname = request.POST.get('lastname') email = request.POST.get('email') From bdb57221e5844006e4ecbfd828ea684acea859da Mon Sep 17 00:00:00 2001 From: PCoder <purple.coder@yahoo.co.uk> Date: Sun, 24 Feb 2019 23:25:12 +0100 Subject: [PATCH 52/54] Also check user before password reset --- dal/ungleich_ldap.py | 44 +++++++++++++++++++++++++------------------- dal/views.py | 1 + 2 files changed, 26 insertions(+), 19 deletions(-) diff --git a/dal/ungleich_ldap.py b/dal/ungleich_ldap.py index 373e927..74f102f 100644 --- a/dal/ungleich_ldap.py +++ b/dal/ungleich_ldap.py @@ -129,15 +129,29 @@ class LdapManager: :return: True if password was changed successfully False otherwise """ conn = self.get_admin_conn() - return_val = conn.modify( - ("uid={uid}," + settings.LDAP_CUSTOMER_DN).format(uid=uid), - { - "userpassword": ( - ldap3.MODIFY_REPLACE, - [self._ssha_password(new_password.encode("utf-8"))] - ) - } + + # Make sure the user exists first to change his/her details + user_exists, entries = self.check_user_exists( + uid=uid, + search_base=settings.ENTIRE_SEARCH_BASE ) + return_val = False + if user_exists: + try: + return_val = conn.modify( + entries[0].entry_dn, + { + "userpassword": ( + ldap3.MODIFY_REPLACE, + [self._ssha_password(new_password.encode("utf-8"))] + ) + } + ) + except Exception as ex: + logger.error("Exception: " + str(ex)) + else: + logger.error("User {} not found".format(uid)) + conn.unbind() return return_val @@ -157,33 +171,25 @@ class LdapManager: # Make sure the user exists first to change his/her details user_exists, entries = self.check_user_exists( uid=uid, - attributes=['uid', 'givenName', 'sn', 'mail', 'gidNumber'], search_base=settings.ENTIRE_SEARCH_BASE ) - + return_val = False if user_exists: details_dict = {k: (ldap3.MODIFY_REPLACE, [v.encode("utf-8")]) for k, v in details.items()} try: - return_val = conn.modify( - ("uid={uid}," + settings.LDAP_CUSTOMER_DN - if entries[0].gidNumber.value == settings.LDAP_CUSTOMER_GROUP_ID - else settings.LDAP_USERS_DN).format(uid=uid), - details_dict - ) + return_val = conn.modify(entries[0].entry_dn, details_dict) msg = "success" except Exception as ex: msg = str(ex) logger.error("Exception: " + msg) - return_val = False finally: conn.unbind() else: msg = "User {} not found".format(uid) logger.error(msg) - raise Exception(msg) - + conn.unbind() return return_val, msg def check_user_exists(self, uid, search_filter="", attributes=None, diff --git a/dal/views.py b/dal/views.py index ea8917a..0bcd174 100644 --- a/dal/views.py +++ b/dal/views.py @@ -176,6 +176,7 @@ class ResetPassword(View): ldap_manager = LdapManager() user_exists, entries = ldap_manager.check_user_exists( uid=user, + search_base=settings.ENTIRE_SEARCH_BASE, attributes=['uid', 'givenName', 'sn', 'mail'] ) if user_exists: From bcb3d6165db9269784327f6494b171ba9207edc6 Mon Sep 17 00:00:00 2001 From: PCoder <purple.coder@yahoo.co.uk> Date: Sun, 24 Feb 2019 23:32:50 +0100 Subject: [PATCH 53/54] Logout user after password reset --- dal/views.py | 1 + 1 file changed, 1 insertion(+) diff --git a/dal/views.py b/dal/views.py index 0bcd174..5002eaa 100644 --- a/dal/views.py +++ b/dal/views.py @@ -381,6 +381,7 @@ class ChangePassword(LoginRequiredMixin, View): ) # Password was changed if result: + logout(request) return render(request, 'changedpassword.html', { 'user': user } ) # Password not changed, instead got some kind of error else: From 7191eb0997af50d0a6537d4e393f164d25dfb9bf Mon Sep 17 00:00:00 2001 From: PCoder <purple.coder@yahoo.co.uk> Date: Sun, 24 Feb 2019 23:51:32 +0100 Subject: [PATCH 54/54] Initialize checks_out variable to False (missing before) --- dal/views.py | 1 + 1 file changed, 1 insertion(+) diff --git a/dal/views.py b/dal/views.py index 5002eaa..5d643d2 100644 --- a/dal/views.py +++ b/dal/views.py @@ -279,6 +279,7 @@ class ResetRequest(View): user = b64decode(tmp_user) user_clean = user.decode('utf-8') # set checks_out = True if token is found in database + checks_out = False dbentries = ResetToken.objects.all().filter(user=user_clean) for entry in dbentries: if entry.token == token: