From 11966f37ee035ef9b8ed19e4416409f115cb98c0 Mon Sep 17 00:00:00 2001 From: Christian Elberfeld <christian.elberfeld@adesso.de> Date: Sun, 21 Apr 2019 19:21:27 +0200 Subject: [PATCH] Grundlegende Login / Logout Funktionen --- Dockerfile | 11 +++-- README.md | 1 + app/app/settings.py | 37 +++++++++++++++-- app/app/urls.py | 24 ++++------- app/app/views.py | 21 ++++++++++ app/static_files/warpzone.png | Bin 0 -> 24657 bytes app/templates/about.html | 19 +++++++++ app/templates/base.html | 75 ++++++++++++++++++++++++++++++++++ app/templates/login.html | 14 +++++++ app/templates/main.html | 24 +++++++++++ app/uwsgi.ini | 4 +- config.ini | 1 + docker-compose-dev.yml | 1 + 13 files changed, 208 insertions(+), 24 deletions(-) create mode 100644 app/app/views.py create mode 100644 app/static_files/warpzone.png create mode 100644 app/templates/about.html create mode 100644 app/templates/base.html create mode 100644 app/templates/login.html create mode 100644 app/templates/main.html diff --git a/Dockerfile b/Dockerfile index 1195139..fc83756 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ -FROM debian:stretch +FROM debian:buster # Python Packages RUN apt-get update && apt-get install -y \ @@ -13,16 +13,19 @@ RUN apt-get update && apt-get install -y \ libssl-dev \ netcat \ python3 \ - python3-pip + python3-pip \ + python3-pyasn1 # Upgrade pip RUN pip3 install --upgrade pip # pip Packages RUN pip3 install \ - django \ - django-mysql \ + django>=2.0.2 \ django-auth-ldap \ + django-bootstrap-static>=4.0 \ + django-mysql \ + django-settings-export \ ldap3 \ mysqlclient \ uwsgi \ diff --git a/README.md b/README.md index 0edccd0..e868497 100644 --- a/README.md +++ b/README.md @@ -57,3 +57,4 @@ Die Anwendung wird auf Port 5000 bereitgestellt. Alle Umgebungsspezifischen Konfigurationen erfolgen in der Datei config.ini. Diese Datei wird beim deployment der Anwendung angepasst. + diff --git a/app/app/settings.py b/app/app/settings.py index ecf95ff..1191644 100644 --- a/app/app/settings.py +++ b/app/app/settings.py @@ -24,6 +24,8 @@ ALLOWED_HOSTS = [] # Application definition +APP_NAME = config.get('common', 'APP_NAME') + INSTALLED_APPS = [ 'django.contrib.admin', @@ -32,6 +34,8 @@ INSTALLED_APPS = [ 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', + 'bootstrap', + 'fontawesome', ] MIDDLEWARE = [ @@ -49,7 +53,9 @@ ROOT_URLCONF = 'app.urls' TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'DIRS': [], + 'DIRS': [ + os.path.join(BASE_DIR, 'templates') + ], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ @@ -57,6 +63,7 @@ TEMPLATES = [ 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', + 'django_settings_export.settings_export', ], }, }, @@ -124,9 +131,22 @@ STATIC_URL = '/static/' STATIC_ROOT = os.path.join(BASE_DIR, 'static') -#LOGIN_URL = 'two_factor:login' -#LOGOUT_URL = 'logout' -#LOGIN_REDIRECT_URL = '/' +STATICFILES_FINDERS = [ + 'django.contrib.staticfiles.finders.FileSystemFinder', + 'django.contrib.staticfiles.finders.AppDirectoriesFinder', +] + +STATICFILES_DIRS = ( + os.path.join(BASE_DIR, 'static_files'), +) + +# +# Login and Auth Settings +# + +LOGIN_URL = '/login' +LOGOUT_URL = '/logout' +LOGIN_REDIRECT_URL = '/' AUTHENTICATION_BACKENDS = ( 'django_auth_ldap.backend.LDAPBackend', @@ -192,3 +212,12 @@ LOGGING = { }, }, } + +# +# Make Settings available in Templates +# + +SETTINGS_EXPORT = [ + 'DEBUG', + 'APP_NAME' +] diff --git a/app/app/urls.py b/app/app/urls.py index 3ba3d80..50fe1c4 100644 --- a/app/app/urls.py +++ b/app/app/urls.py @@ -1,21 +1,15 @@ -"""app URL Configuration - -The `urlpatterns` list routes URLs to views. For more information please see: - https://docs.djangoproject.com/en/1.11/topics/http/urls/ -Examples: -Function views - 1. Add an import: from my_app import views - 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') -Class-based views - 1. Add an import: from other_app.views import Home - 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') -Including another URLconf - 1. Import the include() function: from django.conf.urls import url, include - 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) -""" +from django.urls import include, path from django.conf.urls import url from django.contrib import admin +from app.views import * +from django.contrib.auth import views as auth_views urlpatterns = [ url(r'^admin/', admin.site.urls), + + url(r'^login/$',auth_views.LoginView.as_view(template_name="login.html"), name="login"), + url(r'^logout/$', logout_view, name='logout'), + + url(r'^$', main, name='Main'), + url(r'^about/$', about, name='About'), ] diff --git a/app/app/views.py b/app/app/views.py new file mode 100644 index 0000000..d7215fb --- /dev/null +++ b/app/app/views.py @@ -0,0 +1,21 @@ +from django.conf import settings +from django.http import HttpResponse +from django.shortcuts import render, redirect +from django.contrib.auth.decorators import login_required +from django.contrib.auth import logout +from django.utils.html import escape + + +@login_required(login_url=settings.LOGIN_URL, redirect_field_name=None) +def main(request): + return HttpResponse(render(request, 'main.html')) + + +def about(request): + return HttpResponse(render(request, 'about.html')) + +@login_required(login_url=settings.LOGIN_URL, redirect_field_name=None) +def logout_view(request): + logout(request) + return redirect('/') + diff --git a/app/static_files/warpzone.png b/app/static_files/warpzone.png new file mode 100644 index 0000000000000000000000000000000000000000..42c08b291d0540edd6f4df3be8fa367814f367bf GIT binary patch literal 24657 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 Vf54R6(Hb}axTCI%E>g7)`5!+g)(-#x literal 0 HcmV?d00001 diff --git a/app/templates/about.html b/app/templates/about.html new file mode 100644 index 0000000..81a9053 --- /dev/null +++ b/app/templates/about.html @@ -0,0 +1,19 @@ +{% extends 'base.html' %} + +{% block title %}About{% endblock %} + +{% block content %} + + <div class="jumbotron"> + <h1 class="display-4">About {{ settings.APP_NAME }}</h1> + <hr class="my-4"> + <p> + Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + </p> + <p class="lead"> + <a class="btn btn-primary btn-lg" href="#" role="button">More Info</a> + </p> + </div> + + +{% endblock %} \ No newline at end of file diff --git a/app/templates/base.html b/app/templates/base.html new file mode 100644 index 0000000..06fc850 --- /dev/null +++ b/app/templates/base.html @@ -0,0 +1,75 @@ +{% load static %} + +<html> +<head> + <meta charset="utf-8"> + <title>{% block title %}Django Auth Tutorial{% endblock %}</title> + <link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.min.css' %}"> + <script defer src="{% static 'fontawesome/js/fontawesome-all.min.js' %}"></script> +</head> +<body> + + <header> + + <nav class="navbar navbar-expand-lg navbar-light bg-light"> + + <div class="container"> + <div class="navbar-header"> + <a class="navbar-brand" href="/"> + <img style="display: inline; text-align:left" height="25" width="25" src="{% static 'warpzone.png' %}" /> {{ settings.APP_NAME }} + </a> + + <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"> + <span class="navbar-toggler-icon"></span> + </button> + + <div class="collapse navbar-collapse" id="navbarSupportedContent"> + <ul class="navbar-nav mr-auto"> + + {% if request.user.is_authenticated %} + <!-- + <li class="nav-item"> + <a class="nav-link" href="/sample">Sample Link</span></a> + </li> + --> + {% endif %} + + <li class="nav-item"> + <a class="nav-link" href="/about">About</span></a> + </li> + + {% if request.user.is_authenticated %} + <li class="nav-item"> + <a class="nav-link" href="/logout">Logout</span></a> + </li> + {% endif %} + + {% if user.is_superuser %} + <li class="nav-item"> + <a class="nav-link" href="/admin">Admin</span></a> + </li> + {% endif %} + + {% if settings.DEBUG %} + <li class="nav-item"> + <a class="nav-link disabled" href="#">DEBUG is ON</span></a> + </li> + {% endif %} + + </ul> + </div> + + </div> + </div> + </nav> + </header> + + <main> + {% block content %} + {% endblock %} + </main> + + <script src="{% static 'bootstrap/js/jquery.min.js' %}"></script> + <script src="{% static 'bootstrap/js/bootstrap.bundle.min.js' %}"></script> +</body> +</html> \ No newline at end of file diff --git a/app/templates/login.html b/app/templates/login.html new file mode 100644 index 0000000..0659617 --- /dev/null +++ b/app/templates/login.html @@ -0,0 +1,14 @@ +{% extends 'base.html' %} + +{% block title %}Login{% endblock %} + +{% block content %} +<h2>Login</h2> +<form method="post"> + <div class="form-group"> + {% csrf_token %} + {{ form.as_p }} + </div> + <button type="submit">Login</button> +</form> +{% endblock %} \ No newline at end of file diff --git a/app/templates/main.html b/app/templates/main.html new file mode 100644 index 0000000..508f1f3 --- /dev/null +++ b/app/templates/main.html @@ -0,0 +1,24 @@ +{% extends 'base.html' %} + +{% block title %}Home{% endblock %} + +{% block content %} + + <div class="jumbotron"> + <h1 class="display-4">Hi {{ user.username }}!</h1> + <hr class="my-4"> + <p> + Do some stuff + </p> + <p class="lead"> + <a class="btn btn-primary btn-lg" href="#" role="button">Do other Stuff</a> + </p> + </div> + +{% if user.is_authenticated %} + Hi {{ user.username }}! +{% else %} + <p>You are not logged in</p> + <a href="{% url 'login' %}">login</a> +{% endif %} +{% endblock %} \ No newline at end of file diff --git a/app/uwsgi.ini b/app/uwsgi.ini index 1ade1e8..95d64a5 100644 --- a/app/uwsgi.ini +++ b/app/uwsgi.ini @@ -7,4 +7,6 @@ vacuum = True http-socket = :5000 max-requests = 5000 processes = 5 -static-map = /static=/opt/app/static \ No newline at end of file +static-map = /static=/opt/app/static +uid = www-data +gid = www-data diff --git a/config.ini b/config.ini index 83b0154..ae96e71 100644 --- a/config.ini +++ b/config.ini @@ -1,5 +1,6 @@ [common] +APP_NAME = Django LDAP Sample DEBUG = True [database] diff --git a/docker-compose-dev.yml b/docker-compose-dev.yml index eeb6723..34edb56 100644 --- a/docker-compose-dev.yml +++ b/docker-compose-dev.yml @@ -41,6 +41,7 @@ services: build: . entrypoint: /opt/entrypoint_dev.sh + restart: always depends_on: - mariadb - openldap -- GitLab