Merge pull request #4843 from foarsitter/allauth

Allauth elements & MFA
This commit is contained in:
Jelmer 2024-02-26 08:39:17 +01:00 committed by GitHub
commit daacdd078b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
30 changed files with 188 additions and 429 deletions

View File

@ -84,6 +84,7 @@ THIRD_PARTY_APPS = [
"crispy_bootstrap5",
"allauth",
"allauth.account",
"allauth.mfa",
"allauth.socialaccount",
{%- if cookiecutter.use_celery == 'y' %}
"django_celery_beat",

View File

@ -31,7 +31,7 @@ uvicorn[standard]==0.27.1 # https://github.com/encode/uvicorn
django==4.2.10 # pyup: < 5.0 # https://www.djangoproject.com/
django-environ==0.11.2 # https://github.com/joke2k/django-environ
django-model-utils==4.4.0 # https://github.com/jazzband/django-model-utils
django-allauth==0.61.1 # https://github.com/pennersr/django-allauth
django-allauth[mfa]==0.61.1 # https://github.com/pennersr/django-allauth
django-crispy-forms==2.1 # https://github.com/django-crispy-forms/django-crispy-forms
crispy-bootstrap5==2023.10 # https://github.com/django-crispy-forms/crispy-bootstrap5
{%- if cookiecutter.frontend_pipeline == 'Django Compressor' %}

View File

@ -1,12 +0,0 @@
{% raw %}{% extends "account/base.html" %}
{% load i18n %}
{% block head_title %}
{% translate "Account Inactive" %}
{% endblock head_title %}
{% block inner %}
<h1>{% translate "Account Inactive" %}</h1>
<p>{% translate "This account is inactive." %}</p>
{% endblock inner %}
{%- endraw %}

View File

@ -1,14 +0,0 @@
{% raw %}{% extends "base.html" %}
{% block title %}
{% block head_title %}
{% endblock head_title %}
{% endblock title %}
{% block content %}
<div class="row">
<div class="col-md-6 offset-md-3">
{% block inner %}{% endblock inner %}
</div>
</div>
{% endblock content %}
{%- endraw %}

View File

@ -0,0 +1,11 @@
{% raw %}{% extends "account/base_manage.html" %}
{% block main %}
<div class="card">
<div class="card-body">
{% block content %}
{% endblock content %}
</div>
</div>
{% endblock main %}{% endraw %}

View File

@ -1,80 +0,0 @@
{% raw %}
{% extends "account/base.html" %}
{% load i18n %}
{% load crispy_forms_tags %}
{% block head_title %}
{% translate "Account" %}
{% endblock head_title %}
{% block inner %}
<h1>{% translate "E-mail Addresses" %}</h1>
{% if user.emailaddress_set.all %}
<p>{% translate "The following e-mail addresses are associated with your account:" %}</p>
<form action="{% url 'account_email' %}" class="email_list" method="post">
{% csrf_token %}
<fieldset class="blockLabels">
{% for emailaddress in user.emailaddress_set.all %}
<div class="radio">
<label for="email_radio_{{ forloop.counter }}"
class="{% if emailaddress.primary %}primary_email{% endif %}">
<input id="email_radio_{{ forloop.counter }}"
type="radio"
name="email"
{% if emailaddress.primary or user.emailaddress_set.count == 1 %}checked="checked"{% endif %}
value="{{ emailaddress.email }}" />
{{ emailaddress.email }}
{% if emailaddress.verified %}
<span class="verified">{% translate "Verified" %}</span>
{% else %}
<span class="unverified">{% translate "Unverified" %}</span>
{% endif %}
{% if emailaddress.primary %}
<span class="primary">{% translate "Primary" %}</span>
{% endif %}
</label>
</div>
{% endfor %}
<div class="form-group">
<button class="secondaryAction btn btn-primary"
type="submit"
name="action_primary">{% translate "Make Primary" %}</button>
<button class="secondaryAction btn btn-primary"
type="submit"
name="action_send">{% translate "Re-send Verification" %}</button>
<button class="primaryAction btn btn-primary"
type="submit"
name="action_remove">{% translate "Remove" %}</button>
</div>
</fieldset>
</form>
{% else %}
<p>
<strong>{% translate "Warning:" %}</strong> {% translate "You currently do not have any e-mail address set up. You should really add an e-mail address so you can receive notifications, reset your password, etc." %}
</p>
{% endif %}
<h2>{% translate "Add E-mail Address" %}</h2>
<form method="post" action="{% url 'account_email' %}" class="add_email">
{% csrf_token %}
{{ form|crispy }}
<button class="btn btn-primary" name="action_add" type="submit">{% translate "Add E-mail" %}</button>
</form>
{% endblock inner %}
{% block inline_javascript %}
{{ block.super }}
<script type="text/javascript">
window.addEventListener('DOMContentLoaded', function() {
const message = "{% translate 'Do you really want to remove the selected e-mail address?' %}";
const actions = document.getElementsByName('action_remove');
if (actions.length) {
actions[0].addEventListener("click", function(e) {
if (!confirm(message)) {
e.preventDefault();
}
});
}
Array.from(document.getElementsByClassName('form-group')).forEach(x => x.classList.remove('row'));
});
</script>
{% endblock inline_javascript %}
{%- endraw %}

View File

@ -1,28 +0,0 @@
{% raw %}{% extends "account/base.html" %}
{% load i18n %}
{% load account %}
{% block head_title %}
{% translate "Confirm E-mail Address" %}
{% endblock head_title %}
{% block inner %}
<h1>{% translate "Confirm E-mail Address" %}</h1>
{% if confirmation %}
{% user_display confirmation.email_address.user as user_display %}
<p>
{% blocktranslate with confirmation.email_address.email as email %}Please confirm that <a href="mailto:{{ email }}">{{ email }}</a> is an e-mail address for user {{ user_display }}.{% endblocktranslate %}
</p>
<form method="post"
action="{% url 'account_confirm_email' confirmation.key %}">
{% csrf_token %}
<button class="btn btn-primary" type="submit">{% translate "Confirm" %}</button>
</form>
{% else %}
{% url 'account_email' as email_url %}
<p>
{% blocktranslate %}This e-mail confirmation link expired or is invalid. Please <a href="{{ email_url }}">issue a new e-mail confirmation request</a>.{% endblocktranslate %}
</p>
{% endif %}
{% endblock inner %}
{%- endraw %}

View File

@ -1,53 +0,0 @@
{% raw %}{% extends "account/base.html" %}
{% load i18n %}
{% load account socialaccount %}
{% load crispy_forms_tags %}
{% block head_title %}
{% translate "Sign In" %}
{% endblock head_title %}
{% block inner %}
<h1>{% translate "Sign In" %}</h1>
{% get_providers as socialaccount_providers %}
{% if socialaccount_providers %}
<p>
{% translate "Please sign in with one of your existing third party accounts:" %}
{% if ACCOUNT_ALLOW_REGISTRATION %}
{% blocktranslate trimmed %}
Or, <a href="{{ signup_url }}">sign up</a>
for a {{ site_name }} account and sign in below:
{% endblocktranslate %}
{% endif %}
</p>
<div class="socialaccount_ballot">
<ul class="socialaccount_providers">
{% include "socialaccount/snippets/provider_list.html" with process="login" %}
</ul>
<div class="login-or">{% translate "or" %}</div>
</div>
{% include "socialaccount/snippets/login_extra.html" %}
{% else %}
{% if ACCOUNT_ALLOW_REGISTRATION %}
<p>
{% blocktranslate trimmed %}
If you have not created an account yet, then please
<a href="{{ signup_url }}">sign up</a> first.
{% endblocktranslate %}
</p>
{% endif %}
{% endif %}
<form class="login" method="post" action="{% url 'account_login' %}">
{% csrf_token %}
{{ form|crispy }}
{% if redirect_field_value %}
<input type="hidden"
name="{{ redirect_field_name }}"
value="{{ redirect_field_value }}" />
{% endif %}
<a class="button secondaryAction"
href="{% url 'account_reset_password' %}">{% translate "Forgot Password?" %}</a>
<button class="primaryAction btn btn-primary" type="submit">{% translate "Sign In" %}</button>
</form>
{% endblock inner %}
{%- endraw %}

View File

@ -1,21 +0,0 @@
{% raw %}{% extends "account/base.html" %}
{% load i18n %}
{% block head_title %}
{% translate "Sign Out" %}
{% endblock head_title %}
{% block inner %}
<h1>{% translate "Sign Out" %}</h1>
<p>{% translate "Are you sure you want to sign out?" %}</p>
<form method="post" action="{% url 'account_logout' %}">
{% csrf_token %}
{% if redirect_field_value %}
<input type="hidden"
name="{{ redirect_field_name }}"
value="{{ redirect_field_value }}" />
{% endif %}
<button class="btn btn-danger" type="submit">{% translate "Sign Out" %}</button>
</form>
{% endblock inner %}
{%- endraw %}

View File

@ -1,19 +0,0 @@
{% raw %}{% extends "account/base.html" %}
{% load i18n %}
{% load crispy_forms_tags %}
{% block head_title %}
{% translate "Change Password" %}
{% endblock head_title %}
{% block inner %}
<h1>{% translate "Change Password" %}</h1>
<form method="post"
action="{% url 'account_change_password' %}"
class="password_change">
{% csrf_token %}
{{ form|crispy }}
<button class="btn btn-primary" type="submit" name="action">{% translate "Change Password" %}</button>
</form>
{% endblock inner %}
{%- endraw %}

View File

@ -1,29 +0,0 @@
{% raw %}{% extends "account/base.html" %}
{% load i18n %}
{% load account %}
{% load crispy_forms_tags %}
{% block head_title %}
{% translate "Password Reset" %}
{% endblock head_title %}
{% block inner %}
<h1>{% translate "Password Reset" %}</h1>
{% if user.is_authenticated %}
{% include "account/snippets/already_logged_in.html" %}
{% endif %}
<p>
{% translate "Forgotten your password? Enter your e-mail address below, and we'll send you an e-mail allowing you to reset it." %}
</p>
<form method="post"
action="{% url 'account_reset_password' %}"
class="password_reset">
{% csrf_token %}
{{ form|crispy }}
<input class="btn btn-primary"
type="submit"
value="{% translate 'Reset My Password' %}" />
</form>
<p>{% blocktranslate %}Please contact us if you have any trouble resetting your password.{% endblocktranslate %}</p>
{% endblock inner %}
{%- endraw %}

View File

@ -1,18 +0,0 @@
{% raw %}{% extends "account/base.html" %}
{% load i18n %}
{% load account %}
{% block head_title %}
{% translate "Password Reset" %}
{% endblock head_title %}
{% block inner %}
<h1>{% translate "Password Reset" %}</h1>
{% if user.is_authenticated %}
{% include "account/snippets/already_logged_in.html" %}
{% endif %}
<p>
{% blocktranslate %}We have sent you an e-mail. Please contact us if you do not receive it within a few minutes.{% endblocktranslate %}
</p>
{% endblock inner %}
{%- endraw %}

View File

@ -1,37 +0,0 @@
{% raw %}{% extends "account/base.html" %}
{% load i18n %}
{% load crispy_forms_tags %}
{% block head_title %}
{% translate "Change Password" %}
{% endblock head_title %}
{% block inner %}
<h1>
{% if token_fail %}
{% translate "Bad Token" %}
{% else %}
{% translate "Change Password" %}
{% endif %}
</h1>
{% if token_fail %}
{% url 'account_reset_password' as passwd_reset_url %}
<p>
{% blocktranslate %}The password reset link was invalid, possibly because it has already been used. Please request a <a href="{{ passwd_reset_url }}">new password reset</a>.{% endblocktranslate %}
</p>
{% else %}
{% if form %}
<form method="post" action=".">
{% csrf_token %}
{{ form|crispy }}
<input class="btn btn-primary"
type="submit"
name="action"
value="{% translate 'change password' %}" />
</form>
{% else %}
<p>{% translate "Your password is now changed." %}</p>
{% endif %}
{% endif %}
{% endblock inner %}
{%- endraw %}

View File

@ -1,12 +0,0 @@
{% raw %}{% extends "account/base.html" %}
{% load i18n %}
{% block head_title %}
{% translate "Change Password" %}
{% endblock head_title %}
{% block inner %}
<h1>{% translate "Change Password" %}</h1>
<p>{% translate "Your password is now changed." %}</p>
{% endblock inner %}
{%- endraw %}

View File

@ -1,22 +0,0 @@
{% raw %}{% extends "account/base.html" %}
{% load i18n %}
{% load crispy_forms_tags %}
{% block head_title %}
{% translate "Set Password" %}
{% endblock head_title %}
{% block inner %}
<h1>{% translate "Set Password" %}</h1>
<form method="post"
action="{% url 'account_set_password' %}"
class="password_set">
{% csrf_token %}
{{ form|crispy }}
<input class="btn btn-primary"
type="submit"
name="action"
value="{% translate 'Set Password' %}" />
</form>
{% endblock inner %}
{%- endraw %}

View File

@ -1,28 +0,0 @@
{% raw %}{% extends "account/base.html" %}
{% load i18n %}
{% load crispy_forms_tags %}
{% block head_title %}
{% translate "Signup" %}
{% endblock head_title %}
{% block inner %}
<h1>{% translate "Sign Up" %}</h1>
<p>
{% blocktranslate %}Already have an account? Then please <a href="{{ login_url }}">sign in</a>.{% endblocktranslate %}
</p>
<form class="signup"
id="signup_form"
method="post"
action="{% url 'account_signup' %}">
{% csrf_token %}
{{ form|crispy }}
{% if redirect_field_value %}
<input type="hidden"
name="{{ redirect_field_name }}"
value="{{ redirect_field_value }}" />
{% endif %}
<button class="btn btn-primary" type="submit">{% translate "Sign Up" %} »</button>
</form>
{% endblock inner %}
{%- endraw %}

View File

@ -1,12 +0,0 @@
{% raw %}{% extends "account/base.html" %}
{% load i18n %}
{% block head_title %}
{% translate "Sign Up Closed" %}
{% endblock head_title %}
{% block inner %}
<h1>{% translate "Sign Up Closed" %}</h1>
<p>{% translate "We are sorry, but the sign up is currently closed." %}</p>
{% endblock inner %}
{%- endraw %}

View File

@ -1,14 +0,0 @@
{% raw %}{% extends "account/base.html" %}
{% load i18n %}
{% block head_title %}
{% translate "Verify Your E-mail Address" %}
{% endblock head_title %}
{% block inner %}
<h1>{% translate "Verify Your E-mail Address" %}</h1>
<p>
{% blocktranslate %}We have sent an e-mail to you for verification. Follow the link provided to finalize the signup process. Please contact us if you do not receive it within a few minutes.{% endblocktranslate %}
</p>
{% endblock inner %}
{%- endraw %}

View File

@ -1,25 +0,0 @@
{% raw %}{% extends "account/base.html" %}
{% load i18n %}
{% block head_title %}
{% translate "Verify Your E-mail Address" %}
{% endblock head_title %}
{% block inner %}
<h1>{% translate "Verify Your E-mail Address" %}</h1>
{% url 'account_email' as email_url %}
<p>
{% blocktranslate %}This part of the site requires us to verify that
you are who you claim to be. For this purpose, we require that you
verify ownership of your e-mail address. {% endblocktranslate %}
</p>
<p>
{% blocktranslate %}We have sent an e-mail to you for
verification. Please click on the link inside this e-mail. Please
contact us if you do not receive it within a few minutes.{% endblocktranslate %}
</p>
<p>
{% blocktranslate %}<strong>Note:</strong> you can still <a href="{{ email_url }}">change your e-mail address</a>.{% endblocktranslate %}
</p>
{% endblock inner %}
{%- endraw %}

View File

@ -0,0 +1,7 @@
{% raw %}{% load i18n %}
{% load allauth %}
<div class="alert alert-error">
{% slot message %}
{% endslot %}
</div>{% endraw %}

View File

@ -0,0 +1,6 @@
{% raw %}{% load allauth %}
<span class="badge {% if 'success' in attrs.tags %}bg-success{% endif %} {% if 'warning' in attrs.tags %}bg-warning{% endif %} {% if 'secondary' in attrs.tags %}bg-secondary{% endif %} {% if 'danger' in attrs.tags %}bg-danger{% endif %} {% if 'primary' in attrs.tags %}bg-primary{% endif %}">
{% slot %}
{% endslot %}
</span>{% endraw %}

View File

@ -0,0 +1,20 @@
{% raw %}{% load allauth %}
{% comment %} djlint:off {% endcomment %}
<{% if attrs.href %}a href="{{ attrs.href }}"{% else %}button{% endif %}
{% if attrs.form %}form="{{ attrs.form }}"{% endif %}
{% if attrs.id %}id="{{ attrs.id }}"{% endif %}
{% if attrs.name %}name="{{ attrs.name }}"{% endif %}
{% if attrs.type %}type="{{ attrs.type }}"{% endif %}
class="btn
{% if 'success' in attrs.tags %}btn-success
{% elif 'warning' in attrs.tags %}btn-warning
{% elif 'secondary' in attrs.tags %}btn-secondary
{% elif 'danger' in attrs.tags %}btn-danger
{% elif 'primary' in attrs.tags %}btn-primary
{% else %}btn-primary
{% endif %}"
>
{% slot %}
{% endslot %}
</{% if attrs.href %}a{% else %}button{% endif %}>{% endraw %}

View File

@ -0,0 +1,67 @@
{% raw %}{% load allauth %}
{% load crispy_forms_tags %}
{% if attrs.type == "textarea" %}
<div class="row mb-3">
<div class="col-sm-10">
<label for="{{ attrs.id }}">
{% slot label %}
{% endslot %}
</label>
</div>
<textarea {% if attrs.required %}required{% endif %}
{% if attrs.rows %}rows="{{ attrs.rows }}"{% endif %}
{% if attrs.disabled %}disabled{% endif %}
{% if attrs.readonly %}readonly{% endif %}
{% if attrs.checked %}checked{% endif %}
{% if attrs.name %}name="{{ attrs.name }}"{% endif %}
{% if attrs.id %}id="{{ attrs.id }}"{% endif %}
{% if attrs.placeholder %}placeholder="{{ attrs.placeholder }}"{% endif %}
class="form-control">{% slot value %}{% endslot %}</textarea>
</div>
{% elif attrs.type == "radio" %}
<div class="row mb-3">
<div class="col-sm-10">
<div class="form-check">
<input {% if attrs.required %}required{% endif %}
{% if attrs.disabled %}disabled{% endif %}
{% if attrs.readonly %}readonly{% endif %}
{% if attrs.checked %}checked{% endif %}
{% if attrs.name %}name="{{ attrs.name }}"{% endif %}
{% if attrs.id %}id="{{ attrs.id }}"{% endif %}
{% if attrs.placeholder %}placeholder="{{ attrs.placeholder }}"{% endif %}
{% if attrs.autocomplete %}autocomplete="{{ attrs.autocomplete }}"{% endif %}
value="{{ attrs.value|default_if_none:"" }}"
type="{{ attrs.type }}" />
<label class="form-check-label" for="gridRadios1">
{% slot label %}
{% endslot %}
</label>
</div>
</div>
</div>
{% else %}
<div class="col-sm-10">
<label for="{{ attrs.id }}">
{% slot label %}
{% endslot %}
</label>
</div>
<div class="col-sm-10">
<input {% if attrs.required %}required{% endif %}
{% if attrs.disabled %}disabled{% endif %}
{% if attrs.readonly %}readonly{% endif %}
{% if attrs.checked %}checked{% endif %}
{% if attrs.name %}name="{{ attrs.name }}"{% endif %}
{% if attrs.id %}id="{{ attrs.id }}"{% endif %}
{% if attrs.placeholder %}placeholder="{{ attrs.placeholder }}"{% endif %}
{% if attrs.autocomplete %}autocomplete="{{ attrs.autocomplete }}"{% endif %}
value="{{ attrs.value|default_if_none:"" }}"
type="{{ attrs.type }}"
class="form-control" />
</div>
{% endif %}
{% if slots.help_text %}
<div class="form-text">{% slot help_text %}</div>
{% endslot %}
{% endif %}{% endraw %}

View File

@ -0,0 +1,3 @@
{% raw %}{% load crispy_forms_tags %}
{{ attrs.form|crispy }}{% endraw %}

View File

@ -0,0 +1,19 @@
{% raw %}{% load allauth %}
<section>
<div class="card mb-4">
<div class="card-body">
<h2 class="card-title">
{% slot title %}
{% endslot %}
</h2>
{% slot body %}
{% endslot %}
{% if slots.actions %}
<ul>
{% for action in slots.actions %}<li>{{ action }}</li>{% endfor %}
</ul>
{% endif %}
</div>
</div>
</section>{% endraw %}

View File

@ -0,0 +1,6 @@
{% raw %}{% load allauth %}
<table class="table">
{% slot %}
{% endslot %}
</table>{% endraw %}

View File

@ -0,0 +1,29 @@
{% raw %}{% extends "base.html" %}
{% load i18n %}
{% block bodyclass %}bg-light{% endblock bodyclass %}
{% block css %}{{ block.super }}{% endblock css %}
{% block title %}
{% block head_title %}
{% trans "Sign In" %}
{% endblock head_title %}
{% endblock title %}
{% block body %}
<div class="d-flex justify-content-center h-100 py-4">
<div class="col-md-4 py-4 my-4 px-4">
{% if messages %}
{% for message in messages %}
<div class="alert alert-dismissible {% if message.tags %}alert-{{ message.tags }}{% endif %}">
{{ message }}
<button type="button"
class="btn-close"
data-bs-dismiss="alert"
aria-label="Close"></button>
</div>
{% endfor %}
{% endif %}
{% block content %}
{% endblock content %}
</div>
</div>
{% endblock body %}{% endraw %}

View File

@ -0,0 +1,6 @@
{% raw %}{% extends "base.html" %}
{% block main %}
{% block content %}
{% endblock content %}
{% endblock main %}{% endraw %}

View File

@ -111,7 +111,8 @@
{% raw %}
{% endblock javascript %}
</head>
<body>
<body class="{% block bodyclass %}{% endblock bodyclass %}">
{% block body %}
<div class="mb-1">
<nav class="navbar navbar-expand-md navbar-light bg-light">
<div class="container-fluid">
@ -171,10 +172,14 @@
</div>
{% endfor %}
{% endif %}
{% block content %}
<p>Use this document as a way to quick start any new project.</p>
{% endblock content %}
{% block main %}
{% block content %}
<p>Use this document as a way to quick start any new project.</p>
{% endblock content %}
{% endblock main %}
</div>
{% endblock body %}
<!-- /container -->
{% block modal %}
{% endblock modal %}

View File

@ -41,6 +41,9 @@
<a class="btn btn-primary"
href="{% url 'account_email' %}"
role="button">E-Mail</a>
<a class="btn btn-primary"
href="{% url 'mfa_index' %}"
role="button">MFA</a>
<!-- Your Stuff: Custom user template urls -->
</div>
</div>