From bd017079d5ad9a48c0edffb8d8e02498a10fa34b Mon Sep 17 00:00:00 2001 From: Daoud Clarke Date: Tue, 24 Oct 2023 10:32:06 +0100 Subject: [PATCH] Add login using allauth --- mwmbl/settings_bg_prod.py | 2 +- mwmbl/settings_common.py | 16 +++ mwmbl/settings_dev.py | 4 +- mwmbl/templates/base.html | 22 ++++ mwmbl/templates/home.html | 5 + mwmbl/templates/profile.html | 8 ++ mwmbl/templates/registration/login.html | 26 ++++ mwmbl/templates/signup.html | 10 ++ mwmbl/urls.py | 14 ++- mwmbl/views.py | 24 ++++ poetry.lock | 158 +++++++++++++++++++++++- pyproject.toml | 1 + 12 files changed, 285 insertions(+), 5 deletions(-) create mode 100644 mwmbl/templates/base.html create mode 100644 mwmbl/templates/home.html create mode 100644 mwmbl/templates/profile.html create mode 100644 mwmbl/templates/registration/login.html create mode 100644 mwmbl/templates/signup.html create mode 100644 mwmbl/views.py diff --git a/mwmbl/settings_bg_prod.py b/mwmbl/settings_bg_prod.py index 070bbf9..51d035e 100644 --- a/mwmbl/settings_bg_prod.py +++ b/mwmbl/settings_bg_prod.py @@ -5,4 +5,4 @@ ALLOWED_HOSTS = ["api.mwmbl.org", "mwmbl.org"] DATA_PATH = "/app/storage" RUN_BACKGROUND_PROCESSES = True -NUM_PAGES = 10240000 +NUM_PAGES = 10240000 \ No newline at end of file diff --git a/mwmbl/settings_common.py b/mwmbl/settings_common.py index 645ebd4..14a1e5a 100644 --- a/mwmbl/settings_common.py +++ b/mwmbl/settings_common.py @@ -33,6 +33,10 @@ INSTALLED_APPS = [ 'django.contrib.messages', 'django.contrib.staticfiles', 'mwmbl', + + 'allauth', + 'allauth.account', + 'allauth.socialaccount', ] MIDDLEWARE = [ @@ -43,6 +47,8 @@ MIDDLEWARE = [ 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', + + "allauth.account.middleware.AccountMiddleware", ] ROOT_URLCONF = 'mwmbl.urls' @@ -120,3 +126,13 @@ print("Static files", STATICFILES_DIRS) DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' +AUTHENTICATION_BACKENDS = [ + # Needed to login by username in Django admin, regardless of `allauth` + 'django.contrib.auth.backends.ModelBackend', + + # `allauth` specific authentication methods, such as login by email + 'allauth.account.auth_backends.AuthenticationBackend', +] + +ACCOUNT_EMAIL_REQUIRED = True +ACCOUNT_EMAIL_VERIFICATION = "mandatory" diff --git a/mwmbl/settings_dev.py b/mwmbl/settings_dev.py index ee82351..c7cd281 100644 --- a/mwmbl/settings_dev.py +++ b/mwmbl/settings_dev.py @@ -3,7 +3,9 @@ from mwmbl.settings_common import * DEBUG = True ALLOWED_HOSTS = ["localhost", "127.0.0.1"] +EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' + DATA_PATH = "./devdata" -RUN_BACKGROUND_PROCESSES = True +RUN_BACKGROUND_PROCESSES = False NUM_PAGES = 2560 diff --git a/mwmbl/templates/base.html b/mwmbl/templates/base.html new file mode 100644 index 0000000..b397195 --- /dev/null +++ b/mwmbl/templates/base.html @@ -0,0 +1,22 @@ + + + + + {% block title %}Simple is Better Than Complex{% endblock %} + + +
+

My Site

+ {% if user.is_authenticated %} + logout + {% else %} + login / signup + {% endif %} +
+
+
+ {% block content %} + {% endblock %} +
+ + diff --git a/mwmbl/templates/home.html b/mwmbl/templates/home.html new file mode 100644 index 0000000..ed59579 --- /dev/null +++ b/mwmbl/templates/home.html @@ -0,0 +1,5 @@ +{% extends 'base.html' %} + +{% block content %} +

Welcome, {{ user.username }}!

+{% endblock %} diff --git a/mwmbl/templates/profile.html b/mwmbl/templates/profile.html new file mode 100644 index 0000000..2923d40 --- /dev/null +++ b/mwmbl/templates/profile.html @@ -0,0 +1,8 @@ +{% extends "base.html" %} +{% block title %}Profile Page{% endblock title %} +{% block content %} +
+

This is the profile page for {{user.username}}

+
+ +{% endblock content %} diff --git a/mwmbl/templates/registration/login.html b/mwmbl/templates/registration/login.html new file mode 100644 index 0000000..a5f87a3 --- /dev/null +++ b/mwmbl/templates/registration/login.html @@ -0,0 +1,26 @@ +{% extends 'base.html' %} + +{% block content %} +

Log in to My Site

+ {% if form.errors %} +

Your username and password didn't match. Please try again.

+ {% endif %} +
+ {% csrf_token %} + + {% for field in form %} +

+ {{ field.label_tag }}
+ {{ field }}
+ {% for error in field.errors %} +

{{ error }}

+ {% endfor %} + {% if field.help_text %} +

{{ field.help_text }}

+ {% endif %} +

+ {% endfor %} + + New to My Site? Sign up +
+{% endblock %} diff --git a/mwmbl/templates/signup.html b/mwmbl/templates/signup.html new file mode 100644 index 0000000..b858ff6 --- /dev/null +++ b/mwmbl/templates/signup.html @@ -0,0 +1,10 @@ +{% extends 'base.html' %} + +{% block content %} +

Sign up

+
+ {% csrf_token %} + {{ form.as_p }} + +
+{% endblock %} diff --git a/mwmbl/urls.py b/mwmbl/urls.py index 7d8bff6..b416085 100644 --- a/mwmbl/urls.py +++ b/mwmbl/urls.py @@ -15,12 +15,22 @@ Including another URLconf 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) """ from django.contrib import admin -from django.urls import path +from django.contrib.auth import login, logout +from django.template.defaulttags import url +from django.urls import path, include from mwmbl.api import api_original as api, api_v1 +from mwmbl.views import signup, profile urlpatterns = [ path('admin/', admin.site.urls), path('', api.urls), - path('api/v1/', api_v1.urls) + path('api/v1/', api_v1.urls), + path('accounts/', include('allauth.urls')), + + # path("accounts/", include("django.contrib.auth.urls")), + # path('accounts/new/', signup, name='signup'), + path('accounts/profile/', profile, name='profile'), + # path('login/', login, {'template_name': 'login.html'}, name='login'), + # path('logout/', logout, {'next_page': 'login'}, name='logout'), ] diff --git a/mwmbl/views.py b/mwmbl/views.py new file mode 100644 index 0000000..0ae3ba8 --- /dev/null +++ b/mwmbl/views.py @@ -0,0 +1,24 @@ +from django.contrib.auth import authenticate, login +from django.contrib.auth.decorators import login_required +from django.contrib.auth.forms import UserCreationForm +from django.shortcuts import redirect, render + + +def signup(request): + if request.method == 'POST': + form = UserCreationForm(request.POST) + if form.is_valid(): + form.save() + username = form.cleaned_data.get('username') + raw_password = form.cleaned_data.get('password1') + user = authenticate(username=username, password=raw_password) + login(request, user) + return redirect('/') + else: + form = UserCreationForm() + return render(request, 'signup.html', {'form': form}) + + +@login_required +def profile(request): + return render(request, 'profile.html') diff --git a/poetry.lock b/poetry.lock index d7a0647..f4395b2 100644 --- a/poetry.lock +++ b/poetry.lock @@ -419,6 +419,52 @@ files = [ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] +[[package]] +name = "cryptography" +version = "41.0.4" +description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "cryptography-41.0.4-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:80907d3faa55dc5434a16579952ac6da800935cd98d14dbd62f6f042c7f5e839"}, + {file = "cryptography-41.0.4-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:35c00f637cd0b9d5b6c6bd11b6c3359194a8eba9c46d4e875a3660e3b400005f"}, + {file = "cryptography-41.0.4-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cecfefa17042941f94ab54f769c8ce0fe14beff2694e9ac684176a2535bf9714"}, + {file = "cryptography-41.0.4-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e40211b4923ba5a6dc9769eab704bdb3fbb58d56c5b336d30996c24fcf12aadb"}, + {file = "cryptography-41.0.4-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:23a25c09dfd0d9f28da2352503b23e086f8e78096b9fd585d1d14eca01613e13"}, + {file = "cryptography-41.0.4-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:2ed09183922d66c4ec5fdaa59b4d14e105c084dd0febd27452de8f6f74704143"}, + {file = "cryptography-41.0.4-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:5a0f09cefded00e648a127048119f77bc2b2ec61e736660b5789e638f43cc397"}, + {file = "cryptography-41.0.4-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:9eeb77214afae972a00dee47382d2591abe77bdae166bda672fb1e24702a3860"}, + {file = "cryptography-41.0.4-cp37-abi3-win32.whl", hash = "sha256:3b224890962a2d7b57cf5eeb16ccaafba6083f7b811829f00476309bce2fe0fd"}, + {file = "cryptography-41.0.4-cp37-abi3-win_amd64.whl", hash = "sha256:c880eba5175f4307129784eca96f4e70b88e57aa3f680aeba3bab0e980b0f37d"}, + {file = "cryptography-41.0.4-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:004b6ccc95943f6a9ad3142cfabcc769d7ee38a3f60fb0dddbfb431f818c3a67"}, + {file = "cryptography-41.0.4-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:86defa8d248c3fa029da68ce61fe735432b047e32179883bdb1e79ed9bb8195e"}, + {file = "cryptography-41.0.4-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:37480760ae08065437e6573d14be973112c9e6dcaf5f11d00147ee74f37a3829"}, + {file = "cryptography-41.0.4-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:b5f4dfe950ff0479f1f00eda09c18798d4f49b98f4e2006d644b3301682ebdca"}, + {file = "cryptography-41.0.4-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:7e53db173370dea832190870e975a1e09c86a879b613948f09eb49324218c14d"}, + {file = "cryptography-41.0.4-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:5b72205a360f3b6176485a333256b9bcd48700fc755fef51c8e7e67c4b63e3ac"}, + {file = "cryptography-41.0.4-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:93530900d14c37a46ce3d6c9e6fd35dbe5f5601bf6b3a5c325c7bffc030344d9"}, + {file = "cryptography-41.0.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:efc8ad4e6fc4f1752ebfb58aefece8b4e3c4cae940b0994d43649bdfce8d0d4f"}, + {file = "cryptography-41.0.4-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:c3391bd8e6de35f6f1140e50aaeb3e2b3d6a9012536ca23ab0d9c35ec18c8a91"}, + {file = "cryptography-41.0.4-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:0d9409894f495d465fe6fda92cb70e8323e9648af912d5b9141d616df40a87b8"}, + {file = "cryptography-41.0.4-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:8ac4f9ead4bbd0bc8ab2d318f97d85147167a488be0e08814a37eb2f439d5cf6"}, + {file = "cryptography-41.0.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:047c4603aeb4bbd8db2756e38f5b8bd7e94318c047cfe4efeb5d715e08b49311"}, + {file = "cryptography-41.0.4.tar.gz", hash = "sha256:7febc3094125fc126a7f6fb1f420d0da639f3f32cb15c8ff0dc3997c4549f51a"}, +] + +[package.dependencies] +cffi = ">=1.12" + +[package.extras] +docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=1.1.1)"] +docstest = ["pyenchant (>=1.6.11)", "sphinxcontrib-spelling (>=4.0.1)", "twine (>=1.12.0)"] +nox = ["nox"] +pep8test = ["black", "check-sdist", "mypy", "ruff"] +sdist = ["build"] +ssh = ["bcrypt (>=3.1.5)"] +test = ["pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"] +test-randomorder = ["pytest-randomly"] + [[package]] name = "cymem" version = "2.0.8" @@ -462,6 +508,18 @@ files = [ {file = "cymem-2.0.8.tar.gz", hash = "sha256:8fb09d222e21dcf1c7e907dc85cf74501d4cea6c4ed4ac6c9e016f98fb59cbbf"}, ] +[[package]] +name = "defusedxml" +version = "0.7.1" +description = "XML bomb protection for Python stdlib modules" +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61"}, + {file = "defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69"}, +] + [[package]] name = "django" version = "4.2.6" @@ -483,6 +541,28 @@ tzdata = {version = "*", markers = "sys_platform == \"win32\""} argon2 = ["argon2-cffi (>=19.1.0)"] bcrypt = ["bcrypt"] +[[package]] +name = "django-allauth" +version = "0.57.0" +description = "Integrated set of Django applications addressing authentication, registration, account management as well as 3rd party (social) account authentication." +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "django-allauth-0.57.0.tar.gz", hash = "sha256:a095ef0db7de305d9175772c78e765ebd5fceb004ae61c1383d7fc1af0f7c5b1"}, +] + +[package.dependencies] +Django = ">=3.2" +pyjwt = {version = ">=1.7", extras = ["crypto"]} +python3-openid = ">=3.0.8" +requests = ">=2.0.0" +requests-oauthlib = ">=0.3.0" + +[package.extras] +mfa = ["qrcode (>=7.0.0)"] +saml = ["python3-saml (>=1.15.0,<2.0.0)"] + [[package]] name = "django-ninja" version = "0.22.2" @@ -1104,6 +1184,23 @@ files = [ {file = "numpy-1.26.0.tar.gz", hash = "sha256:f93fc78fe8bf15afe2b8d6b6499f1c73953169fad1e9a8dd086cdff3190e7fdf"}, ] +[[package]] +name = "oauthlib" +version = "3.2.2" +description = "A generic, spec-compliant, thorough implementation of the OAuth request-signing logic" +category = "main" +optional = false +python-versions = ">=3.6" +files = [ + {file = "oauthlib-3.2.2-py3-none-any.whl", hash = "sha256:8139f29aac13e25d502680e9e19963e83f16838d48a0d71c287fe40e7067fbca"}, + {file = "oauthlib-3.2.2.tar.gz", hash = "sha256:9859c40929662bec5d64f34d01c99e093149682a3f38915dc0655d5a633dd918"}, +] + +[package.extras] +rsa = ["cryptography (>=3.0.0)"] +signals = ["blinker (>=1.4.0)"] +signedtoken = ["cryptography (>=3.0.0)", "pyjwt (>=2.0.0,<3)"] + [[package]] name = "packaging" version = "23.2" @@ -1454,6 +1551,27 @@ typing-extensions = ">=3.7.4.3" dotenv = ["python-dotenv (>=0.10.4)"] email = ["email-validator (>=1.0.3)"] +[[package]] +name = "pyjwt" +version = "2.8.0" +description = "JSON Web Token implementation in Python" +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "PyJWT-2.8.0-py3-none-any.whl", hash = "sha256:59127c392cc44c2da5bb3192169a91f429924e17aff6534d70fdc02ab3e04320"}, + {file = "PyJWT-2.8.0.tar.gz", hash = "sha256:57e28d156e3d5c10088e0c68abb90bfac3df82b40a71bd0daa20c65ccd5c23de"}, +] + +[package.dependencies] +cryptography = {version = ">=3.4.0", optional = true, markers = "extra == \"crypto\""} + +[package.extras] +crypto = ["cryptography (>=3.4.0)"] +dev = ["coverage[toml] (==5.0.4)", "cryptography (>=3.4.0)", "pre-commit", "pytest (>=6.0.0,<7.0.0)", "sphinx (>=4.5.0,<5.0.0)", "sphinx-rtd-theme", "zope.interface"] +docs = ["sphinx (>=4.5.0,<5.0.0)", "sphinx-rtd-theme", "zope.interface"] +tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"] + [[package]] name = "pyspark" version = "3.2.0" @@ -1530,6 +1648,25 @@ files = [ [package.dependencies] six = ">=1.5" +[[package]] +name = "python3-openid" +version = "3.2.0" +description = "OpenID support for modern servers and consumers." +category = "main" +optional = false +python-versions = "*" +files = [ + {file = "python3-openid-3.2.0.tar.gz", hash = "sha256:33fbf6928f401e0b790151ed2b5290b02545e8775f982485205a066f874aaeaf"}, + {file = "python3_openid-3.2.0-py3-none-any.whl", hash = "sha256:6626f771e0417486701e0b4daff762e7212e820ca5b29fcc0d05f6f8736dfa6b"}, +] + +[package.dependencies] +defusedxml = "*" + +[package.extras] +mysql = ["mysql-connector-python"] +postgresql = ["psycopg2"] + [[package]] name = "pytz" version = "2023.3.post1" @@ -1732,6 +1869,25 @@ redis = ["redis (>=3)"] security = ["itsdangerous (>=2.0)"] yaml = ["pyyaml (>=5.4)"] +[[package]] +name = "requests-oauthlib" +version = "1.3.1" +description = "OAuthlib authentication support for Requests." +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "requests-oauthlib-1.3.1.tar.gz", hash = "sha256:75beac4a47881eeb94d5ea5d6ad31ef88856affe2332b9aafb52c6452ccf0d7a"}, + {file = "requests_oauthlib-1.3.1-py2.py3-none-any.whl", hash = "sha256:2577c501a2fb8d05a304c09d090d6e47c306fef15809d102b327cf8364bddab5"}, +] + +[package.dependencies] +oauthlib = ">=3.0.0" +requests = ">=2.0.0" + +[package.extras] +rsa = ["oauthlib[signedtoken] (>=3.0.0)"] + [[package]] name = "s3transfer" version = "0.7.0" @@ -2443,4 +2599,4 @@ indexer = ["ujson", "warcio", "idna", "beautifulsoup4", "lxml", "langdetect", "p [metadata] lock-version = "2.0" python-versions = ">=3.10,<3.11" -content-hash = "fe5f238c57ec2d09acb6bdf8f46f33c7bbe499f68a7e34ab7bca1336e0ae881c" +content-hash = "13572a7df206102ce30a6deb1eecd22b5b217a96f864a7dd6c558a7ca263d520" diff --git a/pyproject.toml b/pyproject.toml index 4a4a725..a0de7fd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -37,6 +37,7 @@ django = "^4.2.4" django-ninja = "^0.22.2" requests-cache = "^1.1.0" redis = {extras = ["hiredis"], version = "^5.0.1"} +django-allauth = "^0.57.0" [tool.poetry.extras] indexer = [