diff --git a/.gitignore b/.gitignore index 442e57a..93c9300 100644 --- a/.gitignore +++ b/.gitignore @@ -284,6 +284,8 @@ fabric.properties # Test blog posts /markdownblog/mdfiles/* /envvars.env +<<<<<<< HEAD # ignore static files /markdownblog/static/ + diff --git a/docker-compose.yml b/docker-compose.yml index 3831d8c..0d341c3 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -6,15 +6,13 @@ services: depends_on: - db volumes: - - ./markdownblog:/markdownblog + - ./markdownblog:/markdownblog ports: - "8234:8234" env_file: - envvars.env command: gunicorn markdownblog.wsgi -b 0.0.0.0:8234 - - db: image: postgres:14.3-alpine ports: diff --git a/markdownblog/blog/views.py b/markdownblog/blog/views.py index 27ac043..c967c01 100644 --- a/markdownblog/blog/views.py +++ b/markdownblog/blog/views.py @@ -10,6 +10,7 @@ from django.shortcuts import render, redirect from blog.models import Topic, Tag, Blogpost from django.template import Template, Context from django.views.decorators.csrf import csrf_exempt +from django_2fa.decorators import mfa_login_required def render_md_file(path) -> Template: @@ -53,6 +54,7 @@ def index(request) -> HttpResponse: @login_required +@mfa_login_required def edit(request, id) -> HttpResponse: blogpost = Blogpost.objects.get(pk=id) mdfile_content = open(blogpost.mdfile, "r").read() @@ -94,6 +96,7 @@ def edit(request, id) -> HttpResponse: @login_required @csrf_exempt +@mfa_login_required def order(request) -> HttpResponse: if request.method == "POST": root_id = int(request.POST['rootID']) if request.POST['rootID'] != 'root_list' else None @@ -114,6 +117,7 @@ def order(request) -> HttpResponse: @login_required +@mfa_login_required def addpost(request) -> HttpResponse: context = {'alltopics': Topic.objects.all().order_by('name').values(), 'markdown': '', 'roottopics': Topic.objects.all().filter(rootTopic=None), @@ -154,6 +158,7 @@ def addpost(request) -> HttpResponse: # @login_required +# @mfa_login_required # def createmocks(request, objtype, n) -> HttpResponse: # topics = TopicFactory.create_batch(n) # @@ -171,6 +176,7 @@ def addpost(request) -> HttpResponse: @login_required +@mfa_login_required def addtopic(request): context = {'roottopics': Topic.objects.all().filter(rootTopic=None), 'allposts': Blogpost.objects.all()} diff --git a/markdownblog/markdownblog/settings.py b/markdownblog/markdownblog/settings.py index 0a9c71f..9491789 100644 --- a/markdownblog/markdownblog/settings.py +++ b/markdownblog/markdownblog/settings.py @@ -32,6 +32,8 @@ INSTALLED_APPS = [ 'blog', 'markdownblog', 'fontawesomefree', + 'django_2fa', + 'django_extensions', 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', @@ -48,6 +50,7 @@ MIDDLEWARE = [ 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', + 'django_2fa.middleware.MFAProctectMiddleware', ] ROOT_URLCONF = 'markdownblog.urls' @@ -129,9 +132,21 @@ STATIC_ROOT = '/markdownblog/static' DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' +LOGIN_URL = '/accounts/login' + LOGIN_REDIRECT_URL = "/" LOGOUT_REDIRECT_URL = "/" CSRF_HEADER_NAME = "X-CSRFToken" CSRF_TRUSTED_ORIGINS = ["https://cdaut.de", "http://cdaut.de"] + +# multifactor auth +MFA_URL = '/accounts/2fa/login' + +SALT_KEY = os.environ['SALT_KEY'] + +MFA_ISSUER_NAME = 'MDBlog' + +# Configure mail here +EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' diff --git a/markdownblog/markdownblog/static/base.css b/markdownblog/markdownblog/static/base.css index 3cfe968..705328e 100644 --- a/markdownblog/markdownblog/static/base.css +++ b/markdownblog/markdownblog/static/base.css @@ -24,4 +24,8 @@ header, main, footer { header, main, footer { padding-left: 0; } +} + +.mt-3 { + margin-top: 3em; } \ No newline at end of file diff --git a/markdownblog/markdownblog/templates/2fa/add-device.html b/markdownblog/markdownblog/templates/2fa/add-device.html new file mode 100644 index 0000000..87e930f --- /dev/null +++ b/markdownblog/markdownblog/templates/2fa/add-device.html @@ -0,0 +1,57 @@ +{% extends 'base/base.html' %} +{% load i18n static %} +{% block title %} + Add new 2FA device +{% endblock %} +{% block includehere %} +{% endblock %} +{% block content %} +
+

{% translate 'Add new 2FA device' %}

+
+ {% if form.errors and not form.non_field_errors %} +

+ {% if form.errors.items|length == 1 %}{% translate "Please correct the error below." %}{% else %} + {% translate "Please correct the errors below." %}{% endif %} +

+ {% endif %} +
+ {% csrf_token %} + + {% if form.non_field_errors %} +
+ {{ form.non_field_errors }} +
+ {% endif %} +
+
+ {{ form.name.errors }} + {{ form.name }} + {{ form.name.label_tag }} +
+
+
+
+ {{ form.device_type.errors }} + {{ form.device_type }} + {{ form.device_type.label_tag }} +
+
+ {% for hidden in form.hidden_fields %}{{ hidden }}{% endfor %} +
+
+ +
+
+
+
+ +{% endblock %} + diff --git a/markdownblog/markdownblog/templates/2fa/complete-fido.html b/markdownblog/markdownblog/templates/2fa/complete-fido.html new file mode 100644 index 0000000..a123371 --- /dev/null +++ b/markdownblog/markdownblog/templates/2fa/complete-fido.html @@ -0,0 +1,41 @@ +{% extends "base/base.html" %} +{% load i18n static %} +{% block title %}{% translate "Complete setup for 2FA Device" %}{% endblock %} +{% block content %} +
+

{% translate 'Hardware Key Setup' %}

+
+

{% translate 'Insert your hardware key to complete setup for:' %} {{ device.name }}

+
+ + + +{% endblock %} \ No newline at end of file diff --git a/markdownblog/markdownblog/templates/2fa/devices.html b/markdownblog/markdownblog/templates/2fa/devices.html new file mode 100644 index 0000000..51a98ce --- /dev/null +++ b/markdownblog/markdownblog/templates/2fa/devices.html @@ -0,0 +1,39 @@ +{% extends 'base/base.html' %} +{% load i18n static %} +{% block title %} + Manage 2FA devices +{% endblock %} +{% block includehere %} +{% endblock %} +{% block content %} +
+

{% translate 'Manage 2FA devices' %}

+
+ + Add Device + + +
+ +{% endblock %} \ No newline at end of file diff --git a/markdownblog/markdownblog/templates/2fa/verify.html b/markdownblog/markdownblog/templates/2fa/verify.html new file mode 100644 index 0000000..3570279 --- /dev/null +++ b/markdownblog/markdownblog/templates/2fa/verify.html @@ -0,0 +1,76 @@ +{% extends "base/base.html" %} +{% load i18n static %} +{% block title %}{% translate "Verify authenticator app" %}{% endblock %} +{% block content %} +
+ {% if complete_setup %} +

{% translate 'Verify your authorization device.' %}

+ {% else %} +

{% translate 'Please authenticate with your 2FA token' %}

+ {% endif %} +
+ {% if form.errors and not form.non_field_errors %} +

+ {% if form.errors.items|length == 1 %}{% translate "Please correct the error below." %}{% else %} + {% translate "Please correct the errors below." %}{% endif %} +

+ {% endif %} +
+
+ {% csrf_token %} + + {% if form.non_field_errors %} +
+ {{ form.non_field_errors }} +
+ {% endif %} +
+

{% translate '2FA Factor:' %} {{ device.name }}

+

+ {% if device.device_type == 'email' %} + {% translate 'Check your e-mail for your authorization code.' %} + {% elif device.device_type == 'app' %} + {% if not complete_setup %} + {% translate 'Enter code from your authenicator application.' %}{% endif %} + {% else %} + {% translate 'Use your hardware token to complete sign in.' %} + {% endif %} +

+
+
+ {% if complete_setup and device.device_type == 'app' %} +

+ {% translate 'Scan QR below in your authenicator app, then enter a code to verify your device.' %} +
+ +

{% translate 'Provision URL:' %}
+

{{ device.provision_url }}
+

+ {% endif %} +
+ {{ form.mfa_code.errors }} + {{ form.mfa_code }} + {{ form.mfa_code.label_tag }} +
+
+
+
+ +
+
+
+
+
+ {% if complete_setup and device.device_type == 'app' %} + + + {% endif %} +{% endblock %} diff --git a/markdownblog/markdownblog/templates/base/base.html b/markdownblog/markdownblog/templates/base/base.html index dd49ed4..10dce4c 100644 --- a/markdownblog/markdownblog/templates/base/base.html +++ b/markdownblog/markdownblog/templates/base/base.html @@ -61,6 +61,8 @@
  • admin_panel_settingsAdmin panel
  • +
  • + vpn_keyManage 2FA
  • logoutLogout
  • {% if debug %} diff --git a/markdownblog/markdownblog/templates/blog/addpost.html b/markdownblog/markdownblog/templates/blog/addpost.html index 53dd3b8..5abdf71 100644 --- a/markdownblog/markdownblog/templates/blog/addpost.html +++ b/markdownblog/markdownblog/templates/blog/addpost.html @@ -6,6 +6,7 @@ {% block includehere %} + {% endblock %} {% block content %} @@ -13,8 +14,7 @@
    {% csrf_token %} - +