mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
SSO tweaks (#4169)
* Slight tweaks to login settings page * Cleanup login screen * Custom socialaccount connect page - Better rendering, just looks nicer etc * Add custom account templates - signup_closed - social signup * Catch potential email errors when signing up new user * Add custom template for authentication error * Bug fix for account base.html
This commit is contained in:
parent
82bdd7780d
commit
41318e4056
@ -3,11 +3,13 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import logging
|
||||
import sys
|
||||
import traceback
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import ValidationError as DjangoValidationError
|
||||
from django.db.utils import IntegrityError, OperationalError
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
import rest_framework.views as drfviews
|
||||
@ -16,6 +18,8 @@ from rest_framework import serializers
|
||||
from rest_framework.exceptions import ValidationError as DRFValidationError
|
||||
from rest_framework.response import Response
|
||||
|
||||
logger = logging.getLogger('inventree')
|
||||
|
||||
|
||||
def log_error(path):
|
||||
"""Log an error to the database.
|
||||
@ -32,12 +36,19 @@ def log_error(path):
|
||||
if kind in settings.IGNORED_ERRORS:
|
||||
return
|
||||
|
||||
Error.objects.create(
|
||||
kind=kind.__name__,
|
||||
info=info,
|
||||
data='\n'.join(traceback.format_exception(kind, info, data)),
|
||||
path=path,
|
||||
)
|
||||
# Log error to stderr
|
||||
logger.error(info)
|
||||
|
||||
try:
|
||||
Error.objects.create(
|
||||
kind=kind.__name__,
|
||||
info=info,
|
||||
data='\n'.join(traceback.format_exception(kind, info, data)),
|
||||
path=path,
|
||||
)
|
||||
except (OperationalError, IntegrityError):
|
||||
# Not much we can do if logging the error throws a db exception
|
||||
pass
|
||||
|
||||
|
||||
def exception_handler(exc, context):
|
||||
|
@ -23,6 +23,7 @@ from crispy_forms.helper import FormHelper
|
||||
from crispy_forms.layout import Field, Layout
|
||||
|
||||
from common.models import InvenTreeSetting
|
||||
from InvenTree.exceptions import log_error
|
||||
|
||||
logger = logging.getLogger('inventree')
|
||||
|
||||
@ -239,10 +240,20 @@ class CustomUrlMixin:
|
||||
|
||||
class CustomAccountAdapter(CustomUrlMixin, RegistratonMixin, OTPAdapter, DefaultAccountAdapter):
|
||||
"""Override of adapter to use dynamic settings."""
|
||||
|
||||
def send_mail(self, template_prefix, email, context):
|
||||
"""Only send mail if backend configured."""
|
||||
if settings.EMAIL_HOST:
|
||||
return super().send_mail(template_prefix, email, context)
|
||||
try:
|
||||
result = super().send_mail(template_prefix, email, context)
|
||||
except Exception:
|
||||
# An exception ocurred while attempting to send email
|
||||
# Log it (for admin users) and return silently
|
||||
log_error('account email')
|
||||
result = False
|
||||
|
||||
return result
|
||||
|
||||
return False
|
||||
|
||||
|
||||
|
@ -1070,3 +1070,24 @@ a {
|
||||
margin-left: 0.25rem;
|
||||
margin-right: 0.25rem;
|
||||
}
|
||||
|
||||
.sso-header {
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.sso-provider-list {
|
||||
width: 100%;
|
||||
list-style-type: none;
|
||||
padding-left: 0px;
|
||||
}
|
||||
|
||||
.sso-provider-link {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.sso-provider-link a {
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
}
|
@ -11,9 +11,14 @@
|
||||
|
||||
{% block content %}
|
||||
|
||||
{% if not email_configured %}
|
||||
<div class='alert alert-block alert-danger'>
|
||||
{% trans "Outgoing email has not been configured. Some login and sign-up features may not work correctly!" %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<table class='table table-striped table-condensed'>
|
||||
<tbody>
|
||||
{% include "InvenTree/settings/setting.html" with key="LOGIN_ENABLE_SSO" icon="fa-user-shield" %}
|
||||
{% include "InvenTree/settings/setting.html" with key="LOGIN_ENABLE_PWD_FORGOT" icon="fa-user-lock" %}
|
||||
{% include "InvenTree/settings/setting.html" with key="LOGIN_MAIL_REQUIRED" icon="fa-at" %}
|
||||
{% include "InvenTree/settings/setting.html" with key="LOGIN_ENFORCE_MFA" icon='fa-key' %}
|
||||
@ -24,8 +29,13 @@
|
||||
{% include "InvenTree/settings/setting.html" with key="LOGIN_ENABLE_REG" icon="fa-user-plus" %}
|
||||
{% include "InvenTree/settings/setting.html" with key="LOGIN_SIGNUP_MAIL_TWICE" icon="fa-at" %}
|
||||
{% include "InvenTree/settings/setting.html" with key="LOGIN_SIGNUP_PWD_TWICE" icon="fa-user-lock" %}
|
||||
{% include "InvenTree/settings/setting.html" with key="LOGIN_SIGNUP_SSO_AUTO" icon="fa-key" %}
|
||||
{% include "InvenTree/settings/setting.html" with key="SIGNUP_GROUP" icon="fa-users" %}
|
||||
<tr>
|
||||
<th><h5>{% trans 'Single Sign On' %}</h5></th>
|
||||
<td colspan='4'></td>
|
||||
</tr>
|
||||
{% include "InvenTree/settings/setting.html" with key="LOGIN_ENABLE_SSO" icon="fa-user-shield" %}
|
||||
{% include "InvenTree/settings/setting.html" with key="LOGIN_SIGNUP_SSO_AUTO" icon="fa-key" %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
@ -76,6 +76,7 @@
|
||||
{% endblock %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{% block extra_body %}
|
||||
@ -87,6 +88,7 @@
|
||||
<!-- general JS -->
|
||||
{% include "third_party_js.html" %}
|
||||
|
||||
<script type='text/javascript' src='{% static "script/inventree/inventree.js" %}'></script>
|
||||
<script type='text/javascript' src='{% static "script/inventree/message.js" %}'></script>
|
||||
|
||||
<script type='text/javascript'>
|
||||
@ -95,7 +97,7 @@ $(document).ready(function () {
|
||||
|
||||
{% if messages %}
|
||||
{% for message in messages %}
|
||||
showMessage(messsage);
|
||||
showMessage("{{ messsage }}");
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
@ -109,7 +111,7 @@ $(document).ready(function () {
|
||||
var icon = window.FontAwesome.icon({prefix: 'fab', iconName: tag});
|
||||
|
||||
if (icon) {
|
||||
el.append(` <span class='fab fa-${tag}'></span>`);
|
||||
el.prepend(`<span class='fab fa-${tag}'></span> `);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -13,19 +13,18 @@
|
||||
{% inventree_customize 'login_message' as login_message %}
|
||||
{% mail_configured as mail_conf %}
|
||||
|
||||
<h1>{% trans "Sign In" %}</h1>
|
||||
|
||||
{% if enable_reg %}
|
||||
{% get_providers as socialaccount_providers %}
|
||||
{% if socialaccount_providers %}
|
||||
<p>{% blocktrans with site.name as site_name %}Please sign in with one
|
||||
of your existing third party accounts or <a class="btn btn-primary btn-small" href="{{ signup_url }}">sign up</a>
|
||||
for a account and sign in below:{% endblocktrans %}</p>
|
||||
{% else %}
|
||||
<p>{% blocktrans %}If you have not created an account yet, then please
|
||||
<a href="{{ signup_url }}">sign up</a> first.{% endblocktrans %}</p>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<div class='d-flex flex-wrap'>
|
||||
<h3>{% trans "Sign In" %}</h3>
|
||||
{% include "spacer.html" %}
|
||||
{% if enable_reg %}
|
||||
<div class='float-right'>
|
||||
{% trans "Not a member?" %}
|
||||
<a class="btn btn-primary btn-small" href="{{ signup_url }}">
|
||||
<span class='fas fa-user-plus'></span> {% trans "Sign Up" %}
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<form class="login" method="POST" action="{% url 'account_login' %}">
|
||||
{% csrf_token %}
|
||||
@ -34,15 +33,14 @@ for a account and sign in below:{% endblocktrans %}</p>
|
||||
<input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}" />
|
||||
{% endif %}
|
||||
|
||||
<hr>
|
||||
{% if login_message %}
|
||||
<div>{{ login_message | safe }}<hr></div>
|
||||
{% endif %}
|
||||
<div class="btn-group" role="group">
|
||||
<div class="btn-group" role="group" style='width: 100%;'>
|
||||
<button class="btn btn-success" type="submit">
|
||||
<span class='fas fa-sign-in-alt'></span> {% trans "Sign In" %}
|
||||
</button>
|
||||
</div>
|
||||
{% if login_message %}
|
||||
<div>{{ login_message | safe }}<hr></div>
|
||||
{% endif %}
|
||||
{% if mail_conf and enable_pwd_forgot %}
|
||||
<a class="" href="{% url 'account_reset_password' %}"><small>{% trans "Forgot Password?" %}</small></a>
|
||||
{% endif %}
|
||||
@ -50,10 +48,15 @@ for a account and sign in below:{% endblocktrans %}</p>
|
||||
|
||||
{% if enable_sso %}
|
||||
<hr>
|
||||
<span class='float-right'>{% trans "Sign in using third-party SSO" %}</span>
|
||||
|
||||
<div class='sso-header'>
|
||||
<em>{% trans "or log in with" %}</em>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{% include "socialaccount/snippets/provider_list.html" with process="login" %}
|
||||
</div>
|
||||
|
||||
{% include "socialaccount/snippets/login_extra.html" %}
|
||||
{% endif %}
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
{% settings_value 'LOGIN_ENABLE_REG' as enable_reg %}
|
||||
{% settings_value 'LOGIN_ENABLE_SSO' as enable_sso %}
|
||||
|
||||
<h1>{% trans "Sign Up" %}</h1>
|
||||
<h3>{% trans "Sign Up" %}</h3>
|
||||
|
||||
<p>{% blocktrans %}Already have an account? Then please <a href="{{ login_url }}">sign in</a>.{% endblocktrans %}</p>
|
||||
|
||||
|
19
InvenTree/templates/account/signup_closed.html
Normal file
19
InvenTree/templates/account/signup_closed.html
Normal file
@ -0,0 +1,19 @@
|
||||
{% extends "account/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
{% block head_title %}{% trans "Sign Up Closed" %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h3>{% trans "Sign Up Closed" %}</h3>
|
||||
|
||||
<p>{% trans "Sign up is currently closed." %}</p>
|
||||
|
||||
<hr>
|
||||
<div>
|
||||
<a href='{% url "account_login" %}'>
|
||||
{% trans "Return to login page" %}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
23
InvenTree/templates/socialaccount/authentication_error.html
Normal file
23
InvenTree/templates/socialaccount/authentication_error.html
Normal file
@ -0,0 +1,23 @@
|
||||
{% extends "socialaccount/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
{% block head_title %}{% trans "Social Network Login Failure" %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h3>{% trans "Account Login Failure" %}</h3>
|
||||
|
||||
<p>
|
||||
{% trans "An error occurred while attempting to login via your social network account." %}
|
||||
<br>
|
||||
{% trans "Contact your system administrator for further information." %}
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
<div>
|
||||
<a href='{% url "account_login" %}'>
|
||||
{% trans "Return to login page" %}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
28
InvenTree/templates/socialaccount/login.html
Normal file
28
InvenTree/templates/socialaccount/login.html
Normal file
@ -0,0 +1,28 @@
|
||||
{% extends "socialaccount/base.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block head_title %}{% trans "Sign In" %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% if process == "connect" %}
|
||||
<h3>{% blocktrans with provider.name as provider %}Connect {{ provider }}{% endblocktrans %}</h3>
|
||||
|
||||
<p>{% blocktrans with provider.name as provider %}You are about to connect a new third party account from {{ provider }}.{% endblocktrans %}</p>
|
||||
{% else %}
|
||||
<h3>{% blocktrans with provider.name as provider %}Sign In Via {{ provider }}{% endblocktrans %}</h3>
|
||||
|
||||
<p>{% blocktrans with provider.name as provider %}You are about to sign in using a third party account from {{ provider }}.{% endblocktrans %}</p>
|
||||
{% endif %}
|
||||
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
<button class='btn btn-success sso-provider-link' type="submit"><span class='fas fa-sign-in-alt'></span> {% trans "Continue" %}</button>
|
||||
</form>
|
||||
|
||||
<hr>
|
||||
<div>
|
||||
<a href='{% url "account_login" %}'>
|
||||
{% trans "Return to login page" %}
|
||||
</a>
|
||||
</div>
|
||||
{% endblock %}
|
31
InvenTree/templates/socialaccount/signup.html
Normal file
31
InvenTree/templates/socialaccount/signup.html
Normal file
@ -0,0 +1,31 @@
|
||||
{% extends "socialaccount/base.html" %}
|
||||
|
||||
{% load i18n crispy_forms_tags inventree_extras %}
|
||||
|
||||
{% block head_title %}{% trans "Signup" %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h3>{% trans "Sign Up" %}</h3>
|
||||
|
||||
<p>{% blocktrans with provider_name=account.get_provider.name site_name=site.name %}You are about to use your {{provider_name}} account to login to
|
||||
{{site_name}}.<br>As a final step, please complete the following form:{% endblocktrans %}</p>
|
||||
|
||||
<form class="signup" id="signup_form" method="post" action="{% url 'socialaccount_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-success sso-provider-link' type="submit">
|
||||
<span class='fas fa-user-plus'></span> {% trans "Sign Up" %} »
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<hr>
|
||||
<div>
|
||||
<a href='{% url "account_login" %}'>
|
||||
{% trans "Return to login page" %}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
@ -2,17 +2,21 @@
|
||||
|
||||
{% get_providers as socialaccount_providers %}
|
||||
|
||||
<ul class='sso-provider-list'>
|
||||
{% for provider in socialaccount_providers %}
|
||||
<li class='sso-provider-link'>
|
||||
{% if provider.id == "openid" %}
|
||||
{% for brand in provider.get_brands %}
|
||||
<a title="{{brand.name}}" brand_name='{{ provider.id }}'
|
||||
class="btn btn-primary socialaccount_provider {{provider.id}} {{brand.id}}"
|
||||
class="btn btn-light socialaccount_provider {{provider.id}} {{brand.id}}"
|
||||
href="{% provider_login_url provider.id openid=brand.openid_url process=process %}">
|
||||
<span class='brand-icon' brand_name='{{provider.id}}'></span> {{brand.name}}</a>
|
||||
<span class='brand-icon' brand_name='{{provider.id}}'></span> {{ brand.name }}</a>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
<a title="{{provider.name}}" brand_name='{{ provider.id }}'
|
||||
class="btn btn-primary socialaccount_provider {{provider.id}}"
|
||||
class="btn btn-light socialaccount_provider {{provider.id}}"
|
||||
href="{% provider_login_url provider.id process=process scope=scope auth_params=auth_params %}"
|
||||
><span class='brand-icon' brand_name='{{provider.id}}'></span> {{provider.name}}</a>
|
||||
><span class='brand-icon' brand_name='{{provider.id}}'></span> {{ provider.name }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
Loading…
Reference in New Issue
Block a user