[FEAT] Enable django-allauth for enhanced user management & federation

This commit is contained in:
2023-02-24 19:42:07 +00:00
parent 05ca7433f1
commit 86e18c399d
58 changed files with 1248 additions and 30 deletions

View File

@@ -0,0 +1,16 @@
from allauth.account.adapter import DefaultAccountAdapter
from constance import config
class ControlSignupsAccountAdapter(DefaultAccountAdapter):
def is_open_for_signup(self, request):
"""
Checks whether or not the site is open for signups.
Next to simply returning True/False you can also intervene the
regular flow by raising an ImmediateHttpResponse
(Comment reproduced from the overridden method.)
"""
return config.ALLOW_SIGNUPS

View File

@@ -185,6 +185,7 @@ DJANGO_APPS = [
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.sites',
]
THIRD_PARTY_APPS = [
@@ -199,6 +200,12 @@ THIRD_PARTY_APPS = [
'bootstrap_datepicker_plus',
'hijack',
'pwa',
'allauth',
'allauth.account',
'allauth.socialaccount',
'allauth.socialaccount.providers.google',
'allauth.socialaccount.providers.microsoft',
'django_inlinecss',
]
FIRST_PARTY_APPS = [
@@ -219,6 +226,11 @@ MIDDLEWARE = [
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'hijack.middleware.HijackUserMiddleware',
'django.contrib.sites.middleware.CurrentSiteMiddleware',
]
FIXTURE_DIRS = [
BASE_DIR.joinpath('breccia_mapper', 'fixtures'),
]
ROOT_URLCONF = 'breccia_mapper.urls'
@@ -243,6 +255,33 @@ TEMPLATES = [
WSGI_APPLICATION = 'breccia_mapper.wsgi.application'
# allauth
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',
]
SITE_ID = 1
ACCOUNT_DEFAULT_HTTP_PROTOCOL = SITE_PROTOCOL
ACCOUNT_EMAIL_CONFIRMATION_EXPIRE_DAYS = 1
ACCOUNT_EMAIL_REQUIRED = True
ACCOUNT_EMAIL_VERIFICATION = "mandatory"
ACCOUNT_LOGIN_ATTEMPTS_LIMIT = 5
# 1 day
ACCOUNT_LOGIN_ATTEMPTS_TIMEOUT = 86400
# or any other page
ACCOUNT_LOGOUT_REDIRECT_URL = '/'
ACCOUNT_ADAPTER = 'breccia_mapper.account_adapter.ControlSignupsAccountAdapter'
PROJECT_LONG_NAME = config('PROJECT_LONG_NAME', 'Project Network Mapper')
PROJECT_SHORT_NAME = config('PROJECT_SHORT_NAME', 'Network Mapper')
PROJECT_DESCRIPTION = config('PROJECT_DESCRIPTION', 'Application to map network relationships in the organisation.')
THEME_COLOR = '#' + config('THEME_COLOR', '212121')
BACKGROUND_COLOR = '#' + config('BACKGROUND_COLOR', 'ffffff')
# Database
# https://docs.djangoproject.com/en/2.2/ref/settings/#databases
@@ -303,7 +342,7 @@ AUTH_USER_MODEL = 'people.User'
# Login flow
LOGIN_URL = reverse_lazy('login')
LOGIN_URL = reverse_lazy('account_login')
LOGIN_REDIRECT_URL = reverse_lazy('people:person.profile')
@@ -408,6 +447,15 @@ CONSTANCE_CONFIG = {
'PROJECT_TAGLINE': (
'Here is your project\'s tagline.',
'Project tagline'),
'ALLOW_SIGNUPS': (
False,
'Allow new users to sign up using the site\'s sign up form'),
'ENABLE_GOOGLE_LOGIN': (
False,
'Allow users to sign in using their Google accounts'),
'ENABLE_MICROSOFT_LOGIN': (
False,
'Allow users to sign in using their Microsoft accounts'),
'HOMEPAGE_HEADER_IMAGE': (
'800x500.png',
'Homepage header image',
@@ -459,6 +507,9 @@ CONSTANCE_CONFIG_FIELDSETS = {
'PARENT_PROJECT_NAME',
'PROJECT_LEAD',
'PROJECT_TAGLINE',
'ALLOW_SIGNUPS',
'ENABLE_GOOGLE_LOGIN',
'ENABLE_MICROSOFT_LOGIN',
),
'Homepage configuration': (
'HOMEPAGE_HEADER_IMAGE_SHRINK',
@@ -492,12 +543,6 @@ CONSTANCE_CONFIG_FIELDSETS = {
CONSTANCE_BACKEND = 'constance.backends.database.DatabaseBackend'
PROJECT_LONG_NAME = config('PROJECT_LONG_NAME', 'Project Network Mapper')
PROJECT_SHORT_NAME = config('PROJECT_SHORT_NAME', 'Network Mapper')
PROJECT_DESCRIPTION = config('PROJECT_DESCRIPTION', 'Application to map network relationships in the organisation.')
THEME_COLOR = '#' + config('THEME_COLOR', '212121')
BACKGROUND_COLOR = '#' + config('BACKGROUND_COLOR', 'ffffff')
# Django Hijack settings
# See https://django-hijack.readthedocs.io/en/stable/

View File

@@ -0,0 +1,303 @@
/* -------------------------------------
GLOBAL
A very basic CSS reset
------------------------------------- */
* {
margin: 0;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
box-sizing: border-box;
font-size: 14px;
}
img {
max-width: 100%;
}
body {
-webkit-font-smoothing: antialiased;
-webkit-text-size-adjust: none;
width: 100% !important;
height: 100%;
line-height: 1.6em;
/* 1.6em * 14px = 22.4px, use px to get airier line-height also in Thunderbird, and Yahoo!, Outlook.com, AOL webmail clients */
/*line-height: 22px;*/
}
/* Let's make sure all tables have defaults */
table td {
vertical-align: top;
}
/* -------------------------------------
BODY & CONTAINER
------------------------------------- */
body {
background-color: #f6f6f6;
}
.body-wrap {
background-color: #f6f6f6;
width: 100%;
}
.container {
display: block !important;
max-width: 600px !important;
margin: 0 auto !important;
/* makes it centered */
clear: both !important;
}
.content {
max-width: 600px;
margin: 0 auto;
display: block;
padding: 20px;
}
/* -------------------------------------
HEADER, FOOTER, MAIN
------------------------------------- */
.main {
background-color: #fff;
border: 1px solid #e9e9e9;
border-radius: 3px;
}
.content-wrap {
padding: 20px;
}
.content-block {
padding: 0 0 20px;
}
.header {
width: 100%;
margin-bottom: 20px;
}
.footer {
width: 100%;
clear: both;
color: #999;
padding: 20px;
}
.footer p,
.footer a,
.footer td {
color: #999;
font-size: 12px;
}
/* -------------------------------------
TYPOGRAPHY
------------------------------------- */
h1,
h2,
h3 {
font-family: "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
color: #000;
margin: 40px 0 0;
line-height: 1.2em;
font-weight: 400;
}
h1 {
font-size: 32px;
font-weight: 500;
/* 1.2em * 32px = 38.4px, use px to get airier line-height also in Thunderbird, and Yahoo!, Outlook.com, AOL webmail clients */
/*line-height: 38px;*/
}
h2 {
font-size: 24px;
/* 1.2em * 24px = 28.8px, use px to get airier line-height also in Thunderbird, and Yahoo!, Outlook.com, AOL webmail clients */
/*line-height: 29px;*/
}
h3 {
font-size: 18px;
/* 1.2em * 18px = 21.6px, use px to get airier line-height also in Thunderbird, and Yahoo!, Outlook.com, AOL webmail clients */
/*line-height: 22px;*/
}
h4 {
font-size: 14px;
font-weight: 600;
}
p,
ul,
ol {
margin-bottom: 10px;
font-weight: normal;
}
p li,
ul li,
ol li {
margin-left: 5px;
list-style-position: inside;
}
/* -------------------------------------
LINKS & BUTTONS
------------------------------------- */
a {
color: #348eda;
text-decoration: underline;
}
.btn-primary {
text-decoration: none;
color: #FFF;
background-color: #348eda;
border: solid #348eda;
border-width: 10px 20px;
line-height: 2em;
/* 2em * 14px = 28px, use px to get airier line-height also in Thunderbird, and Yahoo!, Outlook.com, AOL webmail clients */
/*line-height: 28px;*/
font-weight: bold;
text-align: center;
cursor: pointer;
display: inline-block;
border-radius: 5px;
text-transform: capitalize;
}
/* -------------------------------------
OTHER STYLES THAT MIGHT BE USEFUL
------------------------------------- */
.last {
margin-bottom: 0;
}
.first {
margin-top: 0;
}
.aligncenter {
text-align: center;
}
.alignright {
text-align: right;
}
.alignleft {
text-align: left;
}
.clear {
clear: both;
}
/* -------------------------------------
ALERTS
Change the class depending on warning email, good email or bad email
------------------------------------- */
.alert {
font-size: 16px;
color: #fff;
font-weight: 500;
padding: 20px;
text-align: center;
border-radius: 3px 3px 0 0;
}
.alert a {
color: #fff;
text-decoration: none;
font-weight: 500;
font-size: 16px;
}
.alert.alert-warning {
background-color: #FF9F00;
}
.alert.alert-bad {
background-color: #D0021B;
}
.alert.alert-good {
background-color: #68B90F;
}
/* -------------------------------------
INVOICE
Styles for the billing table
------------------------------------- */
.invoice {
margin: 40px auto;
text-align: left;
width: 80%;
}
.invoice td {
padding: 5px 0;
}
.invoice .invoice-items {
width: 100%;
}
.invoice .invoice-items td {
border-top: #eee 1px solid;
}
.invoice .invoice-items .total td {
border-top: 2px solid #333;
border-bottom: 2px solid #333;
font-weight: 700;
}
/* -------------------------------------
RESPONSIVE AND MOBILE FRIENDLY STYLES
------------------------------------- */
@media only screen and (max-width: 640px) {
body {
padding: 0 !important;
}
h1,
h2,
h3,
h4 {
font-weight: 800 !important;
margin: 20px 0 5px !important;
}
h1 {
font-size: 22px !important;
}
h2 {
font-size: 18px !important;
}
h3 {
font-size: 16px !important;
}
.container {
padding: 0 !important;
width: 100% !important;
}
.content {
padding: 0 !important;
}
.content-wrap {
padding: 10px !important;
}
.invoice {
width: 100% !important;
}
}
/*# sourceMappingURL=styles.css.map */

View File

@@ -12,6 +12,19 @@ body {
flex: 1 0 auto;
}
main {
padding-top: 12px;
}
form {
margin-bottom: 24px;
}
.social_providers_list > form {
display: inline-block;
margin-bottom: 8px;
}
.footer {
height: 60px;

View File

View File

@@ -0,0 +1,11 @@
{% extends "account/base.html" %}
{% load i18n %}
{% block head_title %}{% trans "Account Inactive" %}{% endblock %}
{% block content %}
<h1>{% trans "Account Inactive" %}</h1>
<p>{% trans "This account is inactive." %}</p>
{% endblock %}

View File

@@ -0,0 +1 @@
{% extends "base.html" %}

View File

@@ -0,0 +1,93 @@
{% extends "account/base.html" %}
{% load i18n %}
{% block head_title %}{% trans "Account Details" %}{% endblock %}
{% block content %}
<h1 class="h1" id="head_banner">Account Details</h1>
<h2 class="h2" id="head_banner">{% trans "Email Addresses" %}</h2>
{% if user.emailaddress_set.all %}
<p class="email_settings_info">{% trans 'The following email addresses are associated with your account:' %}</p>
<form action="{% url 'account_email' %}" method="post">
{% csrf_token %}
{% for emailaddress in user.emailaddress_set.all %}
<div class="ctrlHolder">
<label for="email_radio_{{forloop.counter}}" class="{% if emailaddress.primary %}primary_email{%endif%}">
{{ emailaddress.email }}
{% if emailaddress.primary %}
<span class="primary">(primary email)</span>
{% endif %}
{% if not emailaddress.verified %}
<span class="unverified">(not verified)</span>
{% 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}}"/>
</label>
</div>
{% endfor %}
<div>
<button class="btn btn-primary" type="submit" name="action_primary" >{% trans 'Make Primary' %}</button>
<button class="btn btn-info" type="submit" name="action_send" >{% trans 'Re-send Verification' %}</button>
<button class="btn btn-danger" type="submit" name="action_remove" >{% trans 'Remove' %}</button>
</div>
</form>
{% else %}
<p class="email_settings_info"><strong>{% trans 'Warning:'%}</strong> {% trans "You do not have any email addresses set up. Please add an email address to receive notifications, reset your password, and perform other account-related actions." %}</p>
{% endif %}
<h3 class="h3" id="head_banner">{% trans "Add Email Address" %}</h3>
<form method="post" id="email_form" action="{% url 'account_email' %}">
{% csrf_token %}
{% load bootstrap4 %}
{% bootstrap_form form %}
<button class="btn btn-primary" name="action_add" type="submit">{% trans "Add Email" %}</button>
</form>
<h2 class="h2" id="head_banner">{% trans "Change Password" %}</h2>
<a class="btn btn-primary mb-4" href="{% url 'account_change_password' %}">{% trans "Change password" %}</a>
<h2 class="h2" id="head_banner">{% trans "Federated Login" %}</h2>
<p>You can connect third-party accounts to log into this site with them.</p>
<a class="btn btn-primary" href="{% url 'socialaccount_connections' %}">{% trans "Manage" %}</a>
{% endblock %}
{% block extra_body %}
<script type="text/javascript">
(function() {
var message = "{% trans 'Are you sure you want to remove the selected email address?' %}";
var actions = document.getElementsByName('action_remove');
if (actions.length) {
actions[0].addEventListener("click", function(e) {
if (! confirm(message)) {
e.preventDefault();
}
});
}
})();
</script>
{% endblock %}

View File

@@ -0,0 +1,76 @@
{% load account %}
{% user_display user as user_display %}
{% load i18n %}
{% load inlinecss %}
{% inlinecss "css/emails.css" %}
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta name="viewport" content="width=device-width" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Your New {{ settings.PROJECT_LONG_NAME }} Account</title>
</head>
<body itemscope itemtype="http://schema.org/EmailMessage">
<table class="body-wrap">
<tr>
<td></td>
<td class="container" width="600">
<div class="content">
<table class="main" width="100%" cellpadding="0" cellspacing="0" itemprop="action" itemscope
itemtype="http://schema.org/ConfirmAction">
<tr>
<td class="content-wrap">
<meta itemprop="name" content="Confirm Email" />
<table width="100%" cellpadding="0" cellspacing="0">
<tr>
<td class="content-block">
<h2>{{ settings.PROJECT_LONG_NAME }}</h2>
</td>
</tr><tr>
<td class="content-block">
You have a new account on {{ settings.PROJECT_LONG_NAME }}. You can log in with the button below.
</td>
</tr>
<tr>
<td class="content-block">
Your username is <i>{{ user.username }}</i>.
</td>
</tr>
<tr>
<td class="content-block" itemprop="handler" itemscope
itemtype="http://schema.org/HttpActionHandler">
<a href="{{ settings.SITE_PROTOCOL }}://{{ settings.SITE_URL }}/accounts/login/" class="btn-primary" itemprop="url">Log in</a>
</td>
</tr>
<tr>
<td class="content-block">
The {{ settings.PROJECT_SHORT_NAME }} team
</td>
</tr>
</table>
</td>
</tr>
</table>
<div class="footer">
<table width="100%">
<tr>
</tr>
</table>
</div>
</div>
</td>
<td></td>
</tr>
</table>
</body>
</html>
{% endinlinecss %}

View File

@@ -0,0 +1,10 @@
Dear user,
You have a new account on {{ settings.PROJECT_LONG_NAME }}. You can log in at the link below.
Your username is {{ user.username }}.
Log in: {{ settings.SITE_PROTOCOL }}://{{ settings.SITE_URL }}/accounts/login/
Thanks,
The {{ settings.PROJECT_SHORT_NAME }} team

View File

@@ -0,0 +1,71 @@
{% load account %}
{% user_display user as user_display %}
{% load i18n %}
{% load inlinecss %}
{% inlinecss "css/emails.css" %}
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta name="viewport" content="width=device-width" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Registration confirmation email</title>
</head>
<body itemscope itemtype="http://schema.org/EmailMessage">
<table class="body-wrap">
<tr>
<td></td>
<td class="container" width="600">
<div class="content">
<table class="main" width="100%" cellpadding="0" cellspacing="0" itemprop="action" itemscope itemtype="http://schema.org/ConfirmAction">
<tr>
<td class="content-wrap">
<meta itemprop="name" content="Confirm Email"/>
<table width="100%" cellpadding="0" cellspacing="0">
<tr>
<td class="content-block">
<h2>{{ settings.PROJECT_LONG_NAME }}</h2>
</td>
</tr>
<tr>
<td class="content-block">
Please confirm your email address by clicking the link below.
</td>
</tr>
<tr>
<td class="content-block">
We may need to send you critical information about our service, so it is important that we have your correct email address.
</td>
</tr>
<tr>
<td class="content-block" itemprop="handler" itemscope itemtype="http://schema.org/HttpActionHandler">
<a href="{{ activate_url }}" class="btn-primary" itemprop="url">Confirm email address</a>
</td>
</tr>
<tr>
<td class="content-block">
The {{ settings.PROJECT_SHORT_NAME }} team
</td>
</tr>
</table>
</td>
</tr>
</table>
<div class="footer">
<table width="100%">
<tr>
</tr>
</table>
</div></div>
</td>
<td></td>
</tr>
</table>
</body>
</html>
{% endinlinecss %}

View File

@@ -0,0 +1 @@
{% include "account/email/email_confirmation_message.html" %}

View File

@@ -0,0 +1,4 @@
{% load i18n %}
{% autoescape off %}
{% blocktrans %}Confirm Your Registration - {{ settings.PROJECT_SHORT_NAME }}{% endblocktrans %}
{% endautoescape %}

View File

@@ -0,0 +1 @@
Confirm Your Email

View File

@@ -0,0 +1,69 @@
{% load i18n %}
{% load inlinecss %}
{% inlinecss "css/emails.css" %}
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta name="viewport" content="width=device-width" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Reset your Password</title>
</head>
<body itemscope itemtype="http://schema.org/EmailMessage">
<table class="body-wrap">
<tr>
<td></td>
<td class="container" width="600">
<div class="content">
<table class="main" width="100%" cellpadding="0" cellspacing="0" itemprop="action" itemscope itemtype="http://schema.org/ConfirmAction">
<tr>
<td class="content-wrap">
<meta itemprop="name" content="Confirm Email"/>
<table width="100%" cellpadding="0" cellspacing="0">
<tr>
<td class="content-block">
<h2>{{ settings.PROJECT_LONG_NAME }}</h2>
</td>
</tr>
<tr>
<td class="content-block">
Please reset your password by clicking the link below.
</td>
</tr>
<tr>
<td class="content-block">
We may need to send you critical information about our service, so it is important that we have your correct email address.
</td>
</tr>
<tr>
<td class="content-block" itemprop="handler" itemscope itemtype="http://schema.org/HttpActionHandler">
<a href="{{ password_reset_url }}" class="btn-primary" itemprop="url">Reset your password</a>
</td>
</tr>
<tr>
<td class="content-block">
The {{ settings.PROJECT_SHORT_NAME }} team
</td>
</tr>
</table>
</td>
</tr>
</table>
<div class="footer">
<table width="100%">
<tr>
</tr>
</table>
</div></div>
</td>
<td></td>
</tr>
</table>
</body>
</html>
{% endinlinecss %}

View File

@@ -0,0 +1,4 @@
{% load i18n %}
{% autoescape off %}
{% blocktrans %}Reset Password - {{ settings.PROJECT_SHORT_NAME }}{% endblocktrans %}
{% endautoescape %}

View File

@@ -0,0 +1,32 @@
{% extends "account/base.html" %}
{% load i18n %}
{% load account %}
{% block head_title %}{% trans "Confirm Email Address" %}{% endblock %}
{% block content %}
<h3 class="h3" id="head_banner">{% trans "Confirm Email Address" %}</h3>
{% if confirmation %}
<p class="verification_sent_info" >{% blocktrans with confirmation.email_address.email as email %} Please confirm ownership of <a href="mailto:{{ email }}">{{ email }}</a>.{% endblocktrans %}</p>
<form method="post"action="{% url 'account_confirm_email' confirmation.key %}">
{% csrf_token %}
<button class="btn btn-success" type="submit">{% trans 'Confirm' %}</button>
</form>
{% else %}
{% url 'account_email' as email_url %}
<p class="verification_sent_info" >{% blocktrans %}This email confirmation link expired or is invalid. Please <a href="{{ email_url }}">request a new email confirmation</a>. You will be redirected to the login page in 5 seconds.{% endblocktrans %}</p>
<script>
setTimeout("location.href = '{% url 'account_login' %}';",5000);
</script>
{% endif %}
{% endblock %}

View File

@@ -0,0 +1,59 @@
{% extends "account/base.html" %}
{% load i18n %}
{% block head_links %}
<title>Sign In</title>
{% endblock %}
{% block head_title %}{% trans "Sign In" %} {% endblock %}
{% block content %}
<h3 class="h3" id="head_banner">{% trans "Sign In" %}</h3>
<form id="login_form" method="POST" action="{% url 'account_login' %}">
{% csrf_token %}
{% load bootstrap4 %}
{% bootstrap_form form %}
{% if redirect_field_value %}
<input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}" />
{% endif %}
<button class="btn btn-primary " type="submit">{% trans "Log in" %}</button>
<a class="btn btn-outline-dark" href="{% url 'account_reset_password' %}">{% trans "Forgot password?" %}</a>
</form>
{% if config.ENABLE_GOOGLE_LOGIN or config.ENABLE_MICROSOFT_LOGIN %}
{% load account socialaccount %}
{% get_providers as socialaccount_providers %}
<h5>Federated Login</h5>
<div class="social_providers_list">
{% for provider in socialaccount_providers %}
{% if provider.name == "Google" and config.ENABLE_GOOGLE_LOGIN or provider.name == "Microsoft Graph" and config.ENABLE_MICROSOFT_LOGIN %}
<form action="{% provider_login_url provider.id process=process scope=scope auth_params=auth_params %}" method="post">
{% csrf_token %}
<button class="btn btn-outline-dark" type="submit">
{% if provider.name == "Microsoft Graph" %}
Microsoft
{% else %}
{{provider.name}}
{% endif %}
</button>
</form>
{% endif %}
{% endfor %}
</div>
{% endif %}
{% endblock %}

View File

@@ -0,0 +1,26 @@
{% extends "account/base.html" %}
{% load i18n %}
{% block head_title %}{% trans "Sign Out" %}{% endblock %}
{% block content %}
<h3 class="h3" id="head_banner">{% trans "Sign Out" %}</h3>
<p class="confirm_logout_info">{% trans 'Are you sure you want to sign out?' %}</p>
<form id="logout_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-success" type="submit">{% trans 'Sign Out' %}</button>
<a class="btn btn-danger" id="custom_logout_no" href="/accounts/profile/">{% trans 'No' %}</a>
</form>
{% endblock %}

View File

@@ -0,0 +1,2 @@
{% load i18n %}
{% blocktrans %}You cannot remove your primary email address ({{email}}).{% endblocktrans %}

View File

@@ -0,0 +1,2 @@
{% load i18n %}
{% blocktrans %}Confirmation email sent to {{email}}.{% endblocktrans %}

View File

@@ -0,0 +1,2 @@
{% load i18n %}
{% blocktrans %}You have confirmed {{email}}.{% endblocktrans %}

View File

@@ -0,0 +1,2 @@
{% load i18n %}
{% blocktrans %}Removed email address {{email}}.{% endblocktrans %}

View File

@@ -0,0 +1,4 @@
{% load account %}
{% load i18n %}
{% user_display user as name %}
{% blocktrans %}Successfully logged in as {{name}}.{% endblocktrans %}

View File

@@ -0,0 +1,2 @@
{% load i18n %}
{% blocktrans %}You have signed out.{% endblocktrans %}

View File

@@ -0,0 +1,2 @@
{% load i18n %}
{% blocktrans %}Password successfully changed.{% endblocktrans %}

View File

@@ -0,0 +1,2 @@
{% load i18n %}
{% blocktrans %}Password successfully set.{% endblocktrans %}

View File

@@ -0,0 +1,2 @@
{% load i18n %}
{% blocktrans %}Primary email address set.{% endblocktrans %}

View File

@@ -0,0 +1,2 @@
{% load i18n %}
{% blocktrans %}Your primary email address must be verified.{% endblocktrans %}

View File

@@ -0,0 +1,18 @@
{% extends "account/base.html" %}
{% load i18n %}
{% block head_title %}{% trans "Change Password" %}{% endblock %}
{% block content %}
<h3 class="h3" id="head_banner">{% trans "Change Password" %}</h3>
<form method="POST" action="{% url 'account_change_password' %}" id="change_password_form">
{% csrf_token %}
{% load bootstrap4 %}
{% bootstrap_form form %}
<button class="btn btn-info" type="submit" name="action">{% trans "Change Password" %}</button>
</form>
{% endblock %}

View File

@@ -0,0 +1,26 @@
{% extends "account/base.html" %}
{% load i18n %}
{% load account %}
{% block head_title %}{% trans "Password Reset" %}{% endblock %}
{% block content %}
{% if user.is_authenticated %}
{% include "account/snippets/already_logged_in.html" %}
{% endif %}
<h3 class="h3" id="head_banner">{% trans "Password Reset" %}</h3>
<p class="forgot_password_info" >{% trans "Forgotten your password? Enter your email address below to reset it." %}</p>
<form method="POST" id="forgot_password_form" action="{% url 'account_reset_password' %}">
{% csrf_token %}
{% load bootstrap4 %}
{% bootstrap_form form %}
<input class="btn btn-outline-primary " type="submit" value="{% trans 'Reset Password' %}" />
</form>
<p class="forgot_password_info">{% blocktrans %}Please contact us if you are unable to reset your password.{% endblocktrans %}</p>
{% endblock %}

View File

@@ -0,0 +1,20 @@
{% extends "account/base.html" %}
{% load i18n %}
{% load account %}
{% block head_title %}{% trans "Password Reset" %}{% endblock %}
{% block content %}
<h3 class="h3" id="head_banner">{% trans "Password Reset Email Sent." %}</h3>
{% if user.is_authenticated %}
{% include "account/snippets/already_logged_in.html" %}
{% block content_extra %} {% endblock %}
{% else %}
<p class="forgot_password_info">A password reset link has been sent to your email address. Please contact us if you do not receive it within a few minutes. <br> You will be redirected to <a href="{% url 'account_login' %}">sign in</a> in 5 seconds.</p>
<script>
setTimeout("location.href = '{% url 'account_login' %}';",5000);
</script>
{% endif %}
{% endblock %}

View File

@@ -0,0 +1,24 @@
{% extends "account/base.html" %}
{% load i18n %}
{% block head_title %}{% trans "Change Password" %}{% endblock %}
{% block content %}
<h1>{% if token_fail %}{% trans "Bad Token" %}{% else %}{% trans "Change Password" %}{% endif %}</h1>
{% if token_fail %}
{% url 'account_reset_password' as passwd_reset_url %}
<p>{% blocktrans %}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>.{% endblocktrans %}</p>
{% else %}
{% if form %}
<form method="POST" action="{{ action_url }}">
{% csrf_token %}
{% load bootstrap4 %}
{% bootstrap_form form %}
<input type="submit" name="action" value="{% trans 'change password' %}"/>
</form>
{% else %}
<p>{% trans 'Your password has been changed.' %}</p>
{% endif %}
{% endif %}
{% endblock %}

View File

@@ -0,0 +1,9 @@
{% extends "account/base.html" %}
{% load i18n %}
{% block head_title %}{% trans "Change Password" %}{% endblock %}
{% block content %}
<h1>{% trans "Change Password" %}</h1>
<p>{% trans 'Your password has been changed.' %}</p>
{% endblock %}

View File

@@ -0,0 +1,18 @@
{% extends "account/base.html" %}
{% load i18n %}
{% block head_title %}{% trans "Set Password" %}{% endblock %}
{% block content %}
<h3 class="h3" id="head_banner">{% trans "Set Password" %}</h3>
<form method="POST" action="{% url 'account_set_password' %}" class="password_set">
{% csrf_token %}
{% load bootstrap4 %}
{% bootstrap_form form %}
<input class="btn btn-outline-primary btn-lg" type="submit" name="action" value="{% trans 'Set Password' %}"/>
</form>
{% endblock %}

View File

@@ -0,0 +1,33 @@
{% extends "account/base.html" %}
{% load i18n %}
{% block head_title %}{% trans "Sign Up" %}{% endblock %}
{% block head_links %}
<title>Signup</title>
{% endblock %}
{% block content %}
<h3 class="h3" id="head_banner">{% trans "Sign Up" %}</h3>
<p class="exist_account_info">{% blocktrans %}Already have an account? Please <a href="{{ login_url }}">sign in</a>.{% endblocktrans %}</p>
<form id="signup_form" method="post" action="{% url 'account_signup' %}">
{% csrf_token %}
{% load bootstrap4 %}
{% bootstrap_form form %}
{% if redirect_field_value %}
<input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}" />
{% endif %}
<button class="btn btn-primary" type="submit">{% trans "Sign Up" %}</button>
</form>
{% endblock %}

View File

@@ -0,0 +1,11 @@
{% extends "account/base.html" %}
{% load i18n %}
{% block head_title %}{% trans "Sign Up Closed" %}{% endblock %}
{% block content %}
<h1>{% trans "Sign Up Closed" %}</h1>
<p>{% blocktrans with project_long_name=settings.PROJECT_LONG_NAME %}Signing up to {{ project_long_name }} is currently not permitted.{% endblocktrans %}</p>
{% endblock %}

View File

@@ -0,0 +1,11 @@
{% load i18n %}
{% load account %}
{% block content %}
{% user_display user as user_display %}
<h3 class="h3" id="head_banner">Already Logged In</h3>
<p class="forgot_password_info" >You are already logged in as {{ user_display }}.</p>
<a class="btn btn-primary mb-4" id="custom_logout_no" href="{% url 'account_email' %}">Account Details</a>
{% endblock %}

View File

@@ -0,0 +1,12 @@
{% extends "account/base.html" %}
{% load i18n %}
{% block head_title %}{% trans "Verify Your Email Address" %}{% endblock %}
{% block content %}
<h3 class="h3" id="head_banner">{% trans "Verify Your Email Address" %}</h3>
<p id="verification_sent_info">{% blocktrans %}A verification email has been sent to your email address. Follow the link provided to activate your account. Contact us if you do not receive it within a few minutes.{% endblocktrans %}</p>
{% endblock %}

View File

@@ -0,0 +1,22 @@
{% extends "account/base.html" %}
{% load i18n %}
{% block head_title %}{% trans "Verify Your Email Address" %}{% endblock %}
{% block content %}
<h1>{% trans "Verify Your Email Address" %}</h1>
{% url 'account_email' as email_url %}
<p>{% blocktrans %}This part of the site requires us to verify that
you are who you claim to be. We therefore require you to
verify ownership of your email address. {% endblocktrans %}</p>
<p>{% blocktrans %}A verification email has been sent to your email address. Follow the link provided to activate your account. Contact us
if you do not receive it within a few minutes.{% endblocktrans %}</p>
<p>{% blocktrans %}<strong>Note:</strong> you can still <a href="{{ email_url }}">change your email address</a>.{% endblocktrans %}</p>
{% endblock %}

View File

@@ -7,6 +7,7 @@
<html lang="{{ LANGUAGE_CODE|default:'en_us' }}">
{% load pwa %}
{% load socialaccount %}
<link rel="manifest" href="/manifest.json">
@@ -76,6 +77,12 @@
<div class="navbar-collapse collapse" id="navbarCollapse">
<ul class="navbar-nav mt-2 mt-lg-0">
<li class="nav-item">
<a href="{% if request.user.person %}{% url 'people:person.profile' %}{% else %}{% url 'people:person.create' %}?user{% endif %}" class="nav-link">
Profile
</a>
</li>
<li class="nav-item">
<a href="{% url 'people:person.list' %}" class="nav-link">People</a>
</li>
@@ -114,23 +121,18 @@
<ul class="navbar-nav mt-2 mt-lg-0 ml-auto">
{% if request.user.is_authenticated %}
<li class="nav-item">
{% if request.user.person %}
<a href="{% url 'people:person.profile' %}" class="nav-link">
<a href="{% url 'account_email' %}" class="nav-link">
<i class="fa-solid fa-circle-user"></i>
{{ request.user }}
</a>
{% if request.user.first_name != "" %}
{{ request.user.first_name }}
{% else %}
<a href="{% url 'people:person.create' %}?user" class="nav-link">
<i class="fa-solid fa-circle-user"></i>
{{ request.user }}
</a>
{% endif %}
</a>
</li>
<li class="nav-item">
<a href="{% url 'logout' %}" class="nav-link">
<a href="{% url 'account_logout' %}" class="nav-link">
<i class="fa-solid fa-right-from-bracket"></i>
Log Out
</a>
@@ -138,7 +140,7 @@
{% else %}
<li class="nav-item">
<a href="{% url 'login' %}" class="nav-link">
<a href="{% url 'account_login' %}" class="nav-link">
<i class="fa-solid fa-right-to-bracket"></i>
Log In
</a>

View File

@@ -4,5 +4,5 @@
{% block content %}
<h1>Password Reset Complete</h1>
<p>Your password has been successfully reset. You can now <a href="{% url 'login' %}">log in using it</a>.</p> If you haven't yet completed your profile, please do this now.
<p>Your password has been successfully reset. You can now <a href="{% url 'account_login' %}">log in using it</a>.</p> If you haven't yet completed your profile, please do this now.
{% endblock %}

View File

@@ -17,7 +17,7 @@
{% else %}
<p>That link isn't valid - has it already been used? You can request a new link <a href="{% url 'login' %}">here</a>.</p>
<p>That link isn't valid - has it already been used? You can request a new link <a href="{% url 'account_reset_password' %}">here</a>.</p>
{% endif %}

View File

@@ -0,0 +1,11 @@
{% extends "socialaccount/base.html" %}
{% load i18n %}
{% block head_title %}{% trans "Federated Login Failure" %}{% endblock %}
{% block content %}
<h1>{% trans "Federated Login Failure" %}</h1>
<p>{% trans "An error occurred while attempting to log in via your third party account." %}</p>
{% endblock %}

View File

@@ -0,0 +1 @@
{% extends "account/base.html" %}

View File

@@ -0,0 +1,70 @@
{% extends "socialaccount/base.html" %}
{% load i18n %}
{% block head_title %}{% trans "Account Connections" %}{% endblock %}
{% block content %}
{% load i18n %}
<a class="btn btn-primary mb-4" href="{% url 'account_email' %}">{% trans "Account Details" %}</a>
<h2 class="h2" id="head_banner">{% trans "Account Connections" %}</h2>
{% if form.accounts %}
<p>{% blocktrans %}You can sign in to your account using any of the following third party accounts:{% endblocktrans %}
</p>
<form method="post" action="{% url 'socialaccount_connections' %}">
{% csrf_token %}
<fieldset>
{% if form.non_field_errors %}
<div id="errorMsg">{{ form.non_field_errors }}</div>
{% endif %}
{% for base_account in form.accounts %}
{% with base_account.get_provider_account as account %}
<div>
<label for="id_account_{{ base_account.id }}">
<input id="id_account_{{ base_account.id }}" type="radio" name="account"
value="{{ base_account.id }}" />
<span class="socialaccount_provider {{ base_account.provider }} {{ account.get_brand.id }}">
{% if account.get_brand.name == "Microsoft Graph" %}
Microsoft
{% else %}
{{ account.get_brand.name }}
{% endif %}
-
</span>
{{ account }}
</label>
</div>
{% endwith %}
{% endfor %}
<div>
<button class="btn btn-danger" type="submit">{% trans 'Remove' %}</button>
</div>
</fieldset>
</form>
{% else %}
<p>{% trans 'You currently have no third party accounts connected to this account.' %}</p>
{% endif %}
<h3 class="h3" id="head_banner">{% trans 'Add Federated Login Account' %}</h3>
<p>Adding a third party account allows you to log in to this site with it.</p>
<div class="social_providers_list">
{% include "socialaccount/snippets/provider_list.html" with process="connect" %}
</div>
{% include "socialaccount/snippets/login_extra.html" %}
{% endblock %}

View File

@@ -0,0 +1,15 @@
{% extends "socialaccount/base.html" %}
{% load i18n %}
{% block head_title %}{% trans "Login Cancelled" %}{% endblock %}
{% block content %}
<h1>{% trans "Login Cancelled" %}</h1>
{% url 'account_login' as login_url %}
<p>{% blocktrans %}Login was cancelled. If this was a mistake, please proceed to <a href="{{login_url}}">sign in</a>.{% endblocktrans %}</p>
{% endblock %}

View File

@@ -0,0 +1,2 @@
{% load i18n %}
{% blocktrans %}Your third party account has been connected.{% endblocktrans %}

View File

@@ -0,0 +1,2 @@
{% load i18n %}
{% blocktrans %}Your third party account is already connected to a different account on this site.{% endblocktrans %}

View File

@@ -0,0 +1,2 @@
{% load i18n %}
{% blocktrans %}Your third party account has been disconnected.{% endblocktrans %}

View File

@@ -0,0 +1,24 @@
{% extends "socialaccount/base.html" %}
{% load i18n %}
{% block head_title %}{% trans "Signup" %}{% endblock %}
{% block content %}
<h1>{% trans "Sign Up" %}</h1>
<p>{% blocktrans with provider_name=account.get_provider.name site_name=site.name %}You are about to use your {% if provider_name == 'Microsoft Graph' %}Microsoft{% else %}{{provider_name}}{% endif %} account to sign up to
{{site_name}}.{% endblocktrans %}</p>
<form class="signup" id="signup_form" method="post" action="{% url 'socialaccount_signup' %}">
{% csrf_token %}
{% load bootstrap4 %}
{% bootstrap_form form %}
{% if redirect_field_value %}
<input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}" />
{% endif %}
<button type="submit">{% trans "Sign Up" %} &raquo;</button>
</form>
{% endblock %}

View File

@@ -0,0 +1,3 @@
{% load socialaccount %}
{% providers_media_js %}

View File

@@ -0,0 +1,22 @@
{% load socialaccount %}
{% get_providers as socialaccount_providers %}
{% for provider in socialaccount_providers %}
{% if provider.id == "openid" %}
{% for brand in provider.get_brands %}
<form action="{% provider_login_url provider.id openid=brand.openid_url process=process %}" method="post">
{% csrf_token %}
<button class="btn btn-outline-dark" type="submit">
{{ brand.name }}
</button>
</form>
{% endfor %}
{% endif %}
<form action="{% provider_login_url provider.id process=process scope=scope auth_params=auth_params %}" method="post">
{% csrf_token %}
<button class="btn btn-outline-dark" type="submit">
{% if provider.name == 'Microsoft Graph' %}Microsoft{% else %}{{provider.name}}{% endif %}
</button>
</form>
{% endfor %}

View File

@@ -33,9 +33,6 @@ urlpatterns = [
path('hijack/',
include('hijack.urls', namespace='hijack')),
path('',
include('django.contrib.auth.urls')),
path('',
views.IndexView.as_view(),
name='index'),
@@ -55,4 +52,7 @@ urlpatterns = [
path('',
include('pwa.urls')),
path('accounts/',
include('allauth.urls')),
] # yapf: disable

View File

@@ -3,6 +3,7 @@
set -eo pipefail
python manage.py migrate
echo "[{\"model\": \"sites.site\",\"pk\": 1,\"fields\": { \"domain\": \"${SITE_URL}\", \"name\": \"${PROJECT_SHORT_NAME}\" }}]" | python manage.py loaddata --format=json -
python manage.py collectstatic --no-input
exec "$@"

View File

@@ -7,8 +7,8 @@
"created": "2020-04-27T12:13:30.448Z",
"last_updated": "2020-04-27T14:45:27.152Z",
"subject": "Welcome to {{settings.PROJECT_LONG_NAME}}",
"content": "Dear user,\r\n\r\nWelcome to {{ settings.PROJECT_LONG_NAME }}. You can set your password at {{ settings.SITE_PROTOCOL }}://{{ settings.SITE_URL }}/password_reset/.\r\n\r\nYour username is {{ user.username }}.\r\nThanks,\r\n\r\nThe {{ settings.PROJECT_SHORT_NAME }} team",
"html_content": "<h1>{{ settings.PROJECT_LONG_NAME }}</h1><br/><p>Dear user,</p><br/><p>Welcome to {{ settings.PROJECT_LONG_NAME }}. You can set your password <a href='{{ settings.SITE_PROTOCOL }}://{{ settings.SITE_URL }}/password_reset/'>here</a>.</p><p>Your username is {{ user.username }}.</p><br/><p>Thanks,</p><p>The {{ settings.PROJECT_SHORT_NAME }} team</p>",
"content": "{% include 'account/email/email_account_creation_message.txt' %}",
"html_content": "{% include 'account/email/email_account_creation_message.html' %}",
"language": "",
"default_template": null
}

View File

@@ -67,7 +67,7 @@
{% load hijack %}
{% if person.user == request.user and not request.user.is_hijacked %}
<a class="btn btn-info"
href="{% url 'password_change' %}?next={{ person.get_absolute_url }}">Change Password</a>
href="{% url 'account_email' %}?next={{ person.get_absolute_url }}">Account Details</a>
{% endif %}
{% if request.user.is_superuser and person.user and person.user != request.user %}

View File

@@ -45,3 +45,5 @@ sqlparse==0.4.3
typed-ast
wrapt==1.14.1
Pillow==9.4.0
django-allauth
django-inlinecss-redux