add user settings for Sources

This commit is contained in:
Jens Langhammer 2019-03-13 16:49:30 +01:00
parent e98e5e4e3e
commit ae3c092238
17 changed files with 84 additions and 109 deletions

View File

@ -186,6 +186,12 @@ class Source(PolicyModel):
"""Return additional Info, such as a callback URL. Show in the administration interface.""" """Return additional Info, such as a callback URL. Show in the administration interface."""
return None return None
def has_user_settings(self):
"""Entrypoint to integrate with User settings. Can either return False if no
user settings are available, or a tuple or string, string, string where the first string
is the name the item has, the second string is the icon and the third is the view-name."""
return False
def __str__(self): def __str__(self):
return self.name return self.name

View File

@ -26,7 +26,7 @@
<li class="dropdown"> <li class="dropdown">
<button class="btn btn-link dropdown-toggle nav-item-iconic" id="dropdownMenu1" data-toggle="dropdown" <button class="btn btn-link dropdown-toggle nav-item-iconic" id="dropdownMenu1" data-toggle="dropdown"
aria-haspopup="true" aria-expanded="true"> aria-haspopup="true" aria-expanded="true">
<span title="Help" class="fa pficon-help dropdown-title"></span> <span title="Help" class="fa pficon-help"></span>
</button> </button>
<ul class="dropdown-menu" aria-labelledby="dropdownMenu1"> <ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
{% comment %} <li><a href="#0">Help</a></li> {% endcomment %} {% comment %} <li><a href="#0">Help</a></li> {% endcomment %}

View File

@ -2,6 +2,7 @@
{% load i18n %} {% load i18n %}
{% load is_active %} {% load is_active %}
{% load static %}
{% load passbook_user_settings %} {% load passbook_user_settings %}
{% block content %} {% block content %}
@ -24,6 +25,15 @@
</a> </a>
</li> </li>
{% endfor %} {% endfor %}
<li class="nav-divider"></li>
{% user_sources as us %}
{% for name, icon, link in us %}
<li class="{% if link == request.get_full_path %} active {% endif %}">
<a href="{{ link }}">
<img src="{% static icon %}" alt=""> {{ name }}
</a>
</li>
{% endfor %}
</ul> </ul>
</div> </div>
</div> </div>

View File

@ -2,7 +2,7 @@
from django import template from django import template
from passbook.core.models import Factor from passbook.core.models import Factor, Source
from passbook.core.policies import PolicyEngine from passbook.core.policies import PolicyEngine
register = template.Library() register = template.Library()
@ -20,3 +20,17 @@ def user_factors(context):
if policy_engine.passing and _link: if policy_engine.passing and _link:
matching_factors.append(_link) matching_factors.append(_link)
return matching_factors return matching_factors
@register.simple_tag(takes_context=True)
def user_sources(context):
"""Return a list of all sources which are enabled for the user"""
user = context.get('request').user
_all_sources = Source.objects.filter(enabled=True).select_subclasses()
matching_sources = []
for factor in _all_sources:
_link = factor.has_user_settings()
policy_engine = PolicyEngine(factor.policies.all())
policy_engine.for_user(user).with_request(context.get('request')).build()
if policy_engine.passing and _link:
matching_sources.append(_link)
return matching_sources

View File

@ -1,7 +1,7 @@
"""OAuth Client models""" """OAuth Client models"""
from django.db import models from django.db import models
from django.urls import reverse_lazy from django.urls import reverse, reverse_lazy
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
from passbook.core.models import Source, UserSourceConnection from passbook.core.models import Source, UserSourceConnection
@ -38,6 +38,16 @@ class OAuthSource(Source):
return "Callback URL: '%s'" % reverse_lazy('passbook_oauth_client:oauth-client-callback', return "Callback URL: '%s'" % reverse_lazy('passbook_oauth_client:oauth-client-callback',
kwargs={'source_slug': self.slug}) kwargs={'source_slug': self.slug})
def has_user_settings(self):
"""Entrypoint to integrate with User settings. Can either return False if no
user settings are available, or a tuple or string, string, string where the first string
is the name the item has, the second string is the icon and the third is the view-name."""
icon = 'img/%s.svg' % self.get_login_button[1]
view_name = 'passbook_oauth_client:oauth-client-user'
return self.name, icon, reverse((view_name), kwargs={
'source_slug': self.slug
})
class Meta: class Meta:
verbose_name = _('Generic OAuth Source') verbose_name = _('Generic OAuth Source')

View File

@ -1,6 +0,0 @@
{% load passbook_oauth_client %}
{% any_provider as enabled %}
{% if enabled %}
<div class="btn-group btn-primary btn-block">
{% endif %}

View File

@ -1,6 +0,0 @@
{% load passbook_oauth_client %}
{% provider_exists 'facebook' as facebook_enabled %}
{% if facebook_enabled %}
<a href="{% url 'passbook_oauth_client:oauth-client-login' provider='facebook' %}" class="btn" style="background-color:#4267b2;color:white;margin-top:10px;width:100%;"><i class="fa fa-facebook-official" aria-hidden="true"></i></a>
{% endif %}

View File

@ -1,6 +0,0 @@
{% load passbook_oauth_client %}
{% provider_exists 'twitter' as twitter_enabled %}
{% if twitter_enabled %}
<a href="{% url 'passbook_oauth_client:oauth-client-login' provider='twitter' %}" class="btn" style="background-color:#55ACEE;color:white;margin-top:10px;width:100%;"><i class="fa fa-twitter" aria-hidden="true"></i></a>
{% endif %}

View File

@ -1,7 +0,0 @@
{% load passbook_oauth_client %}
{% load static %}
{% provider_exists 'google' as google_enabled %}
{% if google_enabled %}
<a href="{% url 'passbook_oauth_client:oauth-client-login' provider='google' %}" class="btn" style="background-color:white;color:black;margin-top:10px;width:100%;"><img src="{% static 'img/google.svg' %}" style="height:12px"></a>
{% endif %}

View File

@ -1,6 +0,0 @@
{% load passbook_oauth_client %}
{% provider_exists 'github' as github_enabled %}
{% if github_enabled %}
<a href="{% url 'passbook_oauth_client:oauth-client-login' provider='github' %}" class="btn" style="background-color:#444444;color:white;margin-top:10px;width:100%;"><i class="fa fa-github" aria-hidden="true"></i></a>
{% endif %}

View File

@ -1,7 +0,0 @@
{% load passbook_oauth_client %}
{% load static %}
{% provider_exists 'discord' as discord_enabled %}
{% if discord_enabled %}
<a href="{% url 'passbook_oauth_client:oauth-client-login' provider='discord' %}" class="btn" style="background-color:#2C2F33;color:white;margin-top:10px;width:100%;"><img src="{% static 'img/discord.svg' %}" style="height:12px"></a>
{% endif %}

View File

@ -1,7 +0,0 @@
{% load passbook_oauth_client %}
{% load static %}
{% provider_exists 'reddit' as reddit_enabled %}
{% if reddit_enabled %}
<a href="{% url 'passbook_oauth_client:oauth-client-login' provider='reddit' %}" class="btn" style="background-color:#ff4500;color:white;margin-top:10px;width:100%;"><img src="{% static 'img/reddit.svg' %}" style="height:20px;margin-top:-5px;"></a>
{% endif %}

View File

@ -1,6 +0,0 @@
{% load passbook_oauth_client %}
{% any_provider as enabled %}
{% if enabled %}
</div>
{% endif %}

View File

@ -1,54 +0,0 @@
{% extends "user/base.html" %}
{% load utils %}
{% load i18n %}
{% block title %}
{% title "Overview" %}
{% endblock %}
{% block content %}
<h1><clr-icon shape="connect" size="48"></clr-icon>{% trans "OAuth2" %}</h1>
<div class="row">
<div class="col-md-12">
<div class="card">
<div class="card-header">
{% trans "Connected Accounts" %}
</div>
<div class="card-footer">
{% if provider_state %}
<table class="table">
<thead>
<th>
<th>{% trans 'Provider' %}</th>
<th>{% trans 'Status' %}</th>
<th>{% trans 'Action' %}</th>
<th>{% trans 'ID' %}</th>
</th>
</thead>
<tbody>
{% for data in provider_state %}
<tr>
<td></td>
<td>{% trans data.provider.ui_name %}</td>
<td>{{ data.state|yesno:"Connected,Not Connected" }}</td>
<td>
{% if data.state == False %}
<a href="{% url 'passbook_oauth_client:oauth-client-login' provider=data.provider.name %}">Connect</a>
{% else %}
<a href="{% url 'passbook_oauth_client:oauth-client-disconnect' provider=data.provider.name %}">Disconnect</a>
{% endif %}
</td>
<td>{{ data.aas.first.identifier }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<p>{% trans "No Providers configured!" %}</p>
{% endif %}
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,18 @@
{% extends "user/base.html" %}
{% load i18n %}
{% block page %}
<h1>{{ source.name }}</h1>
{% if connections.exists %}
<p>{% trans 'Connected.' %}</p>
<a class="btn btn-danger" href="{% url 'passbook_oauth_client:oauth-client-disconnect' source_slug=source.slug %}">
{% trans 'Disconnect' %}
</a>
{% else %}
<p>Not connected.</p>
<a class="btn btn-primary" href="{% url 'passbook_oauth_client:oauth-client-login' source_slug=source.slug %}">
{% trans 'Connect' %}
</a>
{% endif %}
{% endblock %}

View File

@ -3,7 +3,7 @@
from django.urls import path from django.urls import path
from passbook.oauth_client.source_types.manager import RequestKind from passbook.oauth_client.source_types.manager import RequestKind
from passbook.oauth_client.views import core, dispatcher from passbook.oauth_client.views import core, dispatcher, user
urlpatterns = [ urlpatterns = [
path('login/<slug:source_slug>/', dispatcher.DispatcherView.as_view( path('login/<slug:source_slug>/', dispatcher.DispatcherView.as_view(
@ -12,4 +12,6 @@ urlpatterns = [
kind=RequestKind.callback), name='oauth-client-callback'), kind=RequestKind.callback), name='oauth-client-callback'),
path('disconnect/<slug:source_slug>/', core.DisconnectView.as_view(), path('disconnect/<slug:source_slug>/', core.DisconnectView.as_view(),
name='oauth-client-disconnect'), name='oauth-client-disconnect'),
path('user/<slug:source_slug>/', user.UserSettingsView.as_view(),
name='oauth-client-user'),
] ]

View File

@ -0,0 +1,20 @@
"""passbook oauth_client user views"""
from django.contrib.auth.mixins import LoginRequiredMixin
from django.shortcuts import get_object_or_404
from django.views.generic import TemplateView
from passbook.oauth_client.models import OAuthSource, UserOAuthSourceConnection
class UserSettingsView(LoginRequiredMixin, TemplateView):
"""Show user current connection state"""
template_name = 'oauth_client/user.html'
def get_context_data(self, **kwargs):
source = get_object_or_404(OAuthSource, slug=self.kwargs.get('source_slug'))
connections = UserOAuthSourceConnection.objects.filter(user=self.request.user,
source=source)
kwargs['source'] = source
kwargs['connections'] = connections
return super().get_context_data(**kwargs)