improve OAuth Source Setup process, fix login template, closes #3

This commit is contained in:
Jens Langhammer 2019-02-25 14:10:10 +01:00
parent b40ac6dc5d
commit 33431ae013
8 changed files with 93 additions and 179 deletions

View File

@ -27,6 +27,7 @@
<tr> <tr>
<th>{% trans 'Name' %}</th> <th>{% trans 'Name' %}</th>
<th>{% trans 'Class' %}</th> <th>{% trans 'Class' %}</th>
<th>{% trans 'Additional Info' %}</th>
<th></th> <th></th>
</tr> </tr>
</thead> </thead>
@ -35,6 +36,7 @@
<tr> <tr>
<td>{{ source.name }}</td> <td>{{ source.name }}</td>
<td>{{ source|fieldtype }}</td> <td>{{ source|fieldtype }}</td>
<td>{{ source.additional_info }}</td>
<td> <td>
<a class="btn btn-default btn-sm" <a class="btn btn-default btn-sm"
href="{% url 'passbook_admin:source-update' pk=source.uuid %}?back={{ request.get_full_path }}">{% trans 'Edit' %}</a> href="{% url 'passbook_admin:source-update' pk=source.uuid %}?back={{ request.get_full_path }}">{% trans 'Edit' %}</a>

View File

@ -155,10 +155,15 @@ class Source(PolicyModel):
return False return False
@property @property
def get_url(self): def get_login_button(self):
"""Return URL used for logging in""" """Return a tuple of URL, Icon name and Name"""
raise NotImplementedError raise NotImplementedError
@property
def additional_info(self):
"""Return additional Info, such as a callback URL. Show in the administration interface."""
return None
def __str__(self): def __str__(self):
return self.name return self.name

View File

@ -23,16 +23,16 @@
{% endblock %} {% endblock %}
{% block body %} {% block body %}
<div class="toast-notifications-list-pf">
{% include 'partials/messages.html' with toast=True %}
</div>
<div class="login-pf-page"> <div class="login-pf-page">
<div class="container-fluid"> <div class="container-fluid">
<div class="row"> <div class="row">
<div class="col-md-6 col-md-offset-3">
{% include 'partials/messages.html' %}
</div>
<div class="col-sm-6 col-sm-offset-3 col-md-6 col-md-offset-3 col-lg-4 col-lg-offset-4"> <div class="col-sm-6 col-sm-offset-3 col-md-6 col-md-offset-3 col-lg-4 col-lg-offset-4">
<header class="login-pf-page-header"> <header class="login-pf-page-header">
<img class="login-pf-brand" style="max-height: 10rem;" src="{% static 'img/logo.svg' %}" <img class="login-pf-brand" style="max-height: 10rem;" src="{% static 'img/logo.svg' %}"
alt="PatternFly logo" /> alt="passbook logo" />
{% if config.login.subtext %} {% if config.login.subtext %}
<p>{{ config.login.subtext }}</p> <p>{{ config.login.subtext }}</p>
{% endif %} {% endif %}

View File

@ -8,7 +8,6 @@
<h1>{% trans title %}</h1> <h1>{% trans title %}</h1>
</header> </header>
<form method="POST"> <form method="POST">
{% csrf_token %}
{% block above_form %} {% block above_form %}
{% endblock %} {% endblock %}
{% include 'partials/form_login.html' %} {% include 'partials/form_login.html' %}

View File

@ -1,131 +0,0 @@
{% load static %}
<!DOCTYPE html>
<!--[if IE 9]><html lang="en-us" class="ie9 login-pf"><![endif]-->
<!--[if gt IE 9]><!-->
<html lang="en-us" class="login-pf">
<!--<![endif]-->
<head>
<title>Login Social Account (two column) - Red Hat&reg; Common User Experience</title>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="shortcut icon" href="{% static 'img/favicon.ico' %}">
<!-- iPad retina icon -->
<link rel="apple-touch-icon-precomposed" sizes="152x152" href="{% static 'img/apple-touch-icon-precomposed-152.png' %}">
<!-- iPad retina icon (iOS < 7) -->
<link rel="apple-touch-icon-precomposed" sizes="144x144" href="{% static 'img/apple-touch-icon-precomposed-144.png' %}">
<!-- iPad non-retina icon -->
<link rel="apple-touch-icon-precomposed" sizes="76x76" href="{% static 'img/apple-touch-icon-precomposed-76.png' %}">
<!-- iPad non-retina icon (iOS < 7) -->
<link rel="apple-touch-icon-precomposed" sizes="72x72" href="{% static 'img/apple-touch-icon-precomposed-72.png' %}">
<!-- iPhone 6 Plus icon -->
<link rel="apple-touch-icon-precomposed" sizes="120x120" href="{% static 'img/apple-touch-icon-precomposed-180.png' %}">
<!-- iPhone retina icon (iOS < 7) -->
<link rel="apple-touch-icon-precomposed" sizes="114x114" href="{% static 'img/apple-touch-icon-precomposed-114.png' %}">
<!-- iPhone non-retina icon (iOS < 7) -->
<link rel="apple-touch-icon-precomposed" sizes="57x57" href="{% static 'img/apple-touch-icon-precomposed-57.png' %}">
<link rel="stylesheet" type="text/css" href="{% static 'css/patternfly.min.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'css/patternfly-additions.min.css' %}">
<script src="{% static 'js/jquery.min.js' %}"></script>
<script src="{% static 'js/bootstrap.min.js' %}"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.12.2/js/bootstrap-select.min.js"></script>
<script src="{% static 'js/patternfly.min.js' %}"></script>
</head>
<div class="toast-notifications-list-pf">
<div class="toast-pf alert alert-warning alert-dismissable">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">
<span class="pficon pficon-close"></span>
</button>
<span class="pficon pficon-warning-triangle-o"></span>
These examples are included for development testing purposes. For official documentation, see <a href="https://www.patternfly.org" class="alert-link">https://www.patternfly.org</a> and <a href="http://getbootstrap.com" class="alert-link">http://getbootstrap.com</a>.
</div>
</div>
<body>
<div class="login-pf-page login-pf-page-accounts">
<header class="login-pf-page-header">
<img class="login-pf-brand" src="/" alt="Red Hat&reg; logo" />
</header>
<div class="card-pf login-pf-accounts">
<header class="login-pf-header">
<select class="selectpicker">
<option>English</option>
<option>French</option>
<option>Italian</option>
</select>
<h1>Log In to Your Account</h1>
</header>
<section class="login-pf-social-section" role="contentinfo" aria-label="Log in to your patternfly account">
<form>
<div class="form-group">
<label class="sr-only" for="exampleInputEmail1">Email address</label>
<input type="email" class="form-control input-lg" id="exampleInputEmail1" placeholder="Email address">
</div>
<div class="form-group">
<label class="sr-only" for="exampleInputPassword1">Password
</label>
<input type="password" class="form-control input-lg" id="exampleInputPassword1" placeholder="Password">
</div>
<div class="login-pf-settings">
<label class="checkbox-label">
<input type="checkbox"> Keep me logged in for 30 days
</label>
<a href="#">Forgot password?</a>
</div>
<button type="submit" class="btn btn-primary btn-block btn-lg">Log In</button>
</form>
</section><!--login-pf-section-->
<section class="login-pf-social-section" role="contentinfo" aria-label="Log in with third party account">
<ul class="login-pf-social login-pf-social-double-col list-unstyled">
<li class="login-pf-social-link"><a href="#"><img src="{% static 'img/google-logo.svg' %}" alt="Google account login">Google</a></li>
<li class="login-pf-social-link"><a href="#"><img src="{% static 'img/github-logo.svg' %}" alt="github account login">Github</a></li>
<li class="login-pf-social-link"><a href="#"><img src="{% static 'img/facebook-logo.svg' %}" alt="Facebook account login">Facebook</a></li>
<li class="login-pf-social-link"><a href="#"><img src="{% static 'img/twitter-logo.svg' %}" alt="Twitter account login">Twitter</a></li>
<li class="login-pf-social-link"><a href="#"><img src="{% static 'img/linkedin-logo.svg' %}" alt="LinkIn account login">LinkIn</a></li>
<li class="login-pf-social-link"><a href="#"><img src="{% static 'img/stack-exchange-logo.svg' %}" alt="Stack Exchange logo">Stack Exchange</a></li>
<li class="login-pf-social-link"><a href="#"><img src="{% static 'img/open-id-logo.svg' %}" alt="Open ID account login">Open ID</a></li>
<li class="login-pf-social-link"><a href="#"><img src="{% static 'img/instagram-logo.png' %}" alt="Instagram account login">Instagram</a></li>
<li class="login-pf-social-link login-pf-social-link-more"><a href="#"><img src="{% static 'img/git-logo.svg' %}" alt="Git account login">Git</a></li>
<li class="login-pf-social-link login-pf-social-link-more"><a href="#"><img src="{% static 'img/dropbox-logo.svg' %}" alt="dropbox account login">Dropbox</a></li>
<li class="login-pf-social-link login-pf-social-link-more"><a href="#"><img src="{% static 'img/fedora-logo.png' %}" alt="fedora account login">Fedora</a></li>
<li class="login-pf-social-link login-pf-social-link-more"><a href="#"><img src="{% static 'img/skype-logo.svg' %}" alt="skype account logingit ">Skype</a></li>
</ul>
<button type="button" id="socialAccountsToggle" class="btn btn-link login-pf-social-toggle">More<span class="caret"></span></button>
</section><!--login-pf-section-->
<p class="login-pf-signup">Need an account?<a href="#">Sign up</a></p>
</div><!-- card -->
<div class="row">
<div class="col-md-6 col-md-offset-3">
<footer class="login-pf-page-footer">
<ul class="login-pf-page-footer-links list-unstyled">
<li><a class="login-pf-page-footer-link" href="#">Terms of Use</a></li>
<li><a class="login-pf-page-footer-link" href="#">Help</a></li>
<li><a class="login-pf-page-footer-link" href="#">Privacy Policy</a></li>
</ul>
</footer>
</div>
</div>
</div><!-- login-pf-page -->
<script>
$("#socialAccountsToggle").on("click", function(e) {
var $toggle = $(e.target);
var text = $toggle.contents().first()[0];
var socialContainer = $('.login-pf-social-section > .login-pf-social');
if ($toggle.hasClass('login-pf-social-toggle-active')) {
$toggle.removeClass('login-pf-social-toggle-active');
text.textContent = 'More';
socialContainer.removeClass('login-pf-social-all');
} else {
$toggle.addClass('login-pf-social-toggle-active');
text.textContent = 'Less';
socialContainer.addClass('login-pf-social-all');
}
});
</script>
</body>
</html>

View File

@ -1,45 +1,71 @@
{% extends 'login/base.html' %} {% extends 'base/skeleton.html' %}
{% load static %} {% load static %}
{% load i18n %} {% load i18n %}
{% block row %} {% block head %}
{% include 'partials/messages.html' %} <style>
<div class="col-md-6"> .login-pf-page .login-pf-page-footer-links {
<div class="card-pf"> padding: 15px;
background-color: #fff;
border-top: 2px solid transparent;
box-shadow: 0 1px 1px rgba(3, 3, 3, .175);
}
.login-pf-page .login-pf-page-footer-link {
color: #72767b;
}
.login-pf-page .login-pf-page-footer-links li:not(:last-of-type):after {
color: #72767b;
}
</style>
{% endblock %}
{% block body %}
<div class="toast-notifications-list-pf">
{% include 'partials/messages.html' with toast=True %}
</div>
<div class="login-pf-page login-pf-page-accounts">
<header class="login-pf-page-header">
<img class="login-pf-brand" style="max-height: 10rem;" src="{% static 'img/logo.svg' %}" alt="passbook logo" />
{% if config.login.subtext %}
<p>{{ config.login.subtext }}</p>
{% endif %}
</header>
<div class="card-pf login-pf-accounts">
<header class="login-pf-header"> <header class="login-pf-header">
<h1>{% trans title %}</h1> <h1>{% trans title %}</h1>
</header> </header>
<section class="login-pf-social-section" role="contentinfo" aria-label="Log in to your patternfly account">
<form method="POST"> <form method="POST">
{% csrf_token %}
{% block above_form %} {% block above_form %}
{% endblock %} {% endblock %}
{% include 'partials/form_login.html' %} {% include 'partials/form_login.html' %}
<button type="submit" class="btn btn-primary btn-block btn-lg">{% trans primary_action %}</button> <button type="submit" class="btn btn-primary btn-block btn-lg">{% trans primary_action %}</button>
</form> </form>
</section>
<!--login-pf-section-->
<section class="login-pf-social-section" role="contentinfo" aria-label="Log in with third party account">
<ul class="login-pf-social login-pf-social-double-col list-unstyled">
{% for url, icon, name in sources %}
<li class="login-pf-social-link">
<a href="{{ url }}">
<img src="{% static 'img/' %}{{ icon }}.svg" alt="{{ name }}"> {{ name }}
</a>
</li>
{% endfor %}
</ul>
</section>
{% if show_sign_up_notice %} {% if show_sign_up_notice %}
<p class="login-pf-signup"> <p class="login-pf-signup">
{% trans 'Need an account?' %} {% trans 'Need an account?' %}
<a href="{% url 'passbook_core:auth-sign-up' %}">{% trans 'Sign up' %}</a> <a href="{% url 'passbook_core:auth-sign-up' %}">{% trans 'Sign up' %}</a>
</p> </p>
{% endif %} {% endif %}
</div> </div><!-- card -->
</div> <div class="row">
<div class="col-md-6"> <div class="col-md-6 col-md-offset-3">
<div class="card-pf">
<header class="login-pf-header">
<h1>{% trans title %}</h1>
<ul>
{% for source in sources %}
<li>
<a class="btn btn-block btn-primary" href="{{ source.get_url }}">{{ source }}</a>
</li>
{% endfor %}
</ul>
</header>
</div>
</div>
<div class="col-sm-10 col-sm-offset-1 col-md-8 col-md-offset-2 col-lg-8 col-lg-offset-2">
<footer class="login-pf-page-footer"> <footer class="login-pf-page-footer">
<ul class="login-pf-page-footer-links list-unstyled"> <ul class="login-pf-page-footer-links list-unstyled">
<li><a class="login-pf-page-footer-link" href="#">Terms of Use</a></li> <li><a class="login-pf-page-footer-link" href="#">Terms of Use</a></li>
@ -48,4 +74,6 @@
</ul> </ul>
</footer> </footer>
</div> </div>
</div>
</div>
{% endblock %} {% endblock %}

View File

@ -42,9 +42,12 @@ class LoginView(UserPassesTestMixin, FormView):
kwargs['primary_action'] = _('Log in') kwargs['primary_action'] = _('Log in')
kwargs['show_sign_up_notice'] = CONFIG.y('passbook.sign_up.enabled') kwargs['show_sign_up_notice'] = CONFIG.y('passbook.sign_up.enabled')
kwargs['show_password_forget_notice'] = CONFIG.y('passbook.password_reset.enabled') kwargs['show_password_forget_notice'] = CONFIG.y('passbook.password_reset.enabled')
kwargs['sources'] = Source.objects.filter(enabled=True).select_subclasses() kwargs['sources'] = []
if any(source.is_link for source in kwargs['sources']): sources = Source.objects.filter(enabled=True).select_subclasses()
self.template_name = 'login/test.html' if any(source.is_link for source in sources):
for source in sources:
kwargs['sources'].append(source.get_login_button)
self.template_name = 'login/with_sources.html'
return super().get_context_data(**kwargs) return super().get_context_data(**kwargs)
def get_user(self, uid_value) -> User: def get_user(self, uid_value) -> User:

View File

@ -26,8 +26,16 @@ class OAuthSource(Source):
return True return True
@property @property
def get_url(self): def get_login_button(self):
return reverse_lazy('passbook_oauth_client:oauth-client-login', url = reverse_lazy('passbook_oauth_client:oauth-client-login',
kwargs={'source_slug': self.slug})
if self.provider_type == 'github':
return url, 'github-logo', _('GitHub')
return url, 'generic', _('Generic')
@property
def additional_info(self):
return "Callback URL: '%s'" % reverse_lazy('passbook_oauth_client:oauth-client-callback',
kwargs={'source_slug': self.slug}) kwargs={'source_slug': self.slug})
class Meta: class Meta: