Rules -> Policies, more things

This commit is contained in:
Jens Langhammer
2019-02-21 16:06:57 +01:00
parent d3d75737ed
commit c941107d42
31 changed files with 333 additions and 175 deletions

View File

@ -15,8 +15,9 @@ class AuthenticationFactor(TemplateView):
form = None
required = True
authenticator = None
pending_user = None
request = None
template_name = 'login/form.html'
template_name = 'login/factors/base.html'
def __init__(self, authenticator):
self.authenticator = authenticator
@ -26,4 +27,5 @@ class AuthenticationFactor(TemplateView):
kwargs['is_login'] = True
kwargs['title'] = _('Log in to your account')
kwargs['primary_action'] = _('Log in')
kwargs['pending_user'] = self.pending_user
return super().get_context_data(**kwargs)

View File

@ -67,6 +67,7 @@ class AuthenticationView(UserPassesTestMixin, View):
# Instantiate Next Factor and pass request
factor = path_to_class(factor_class)
self._current_factor = factor(self)
self._current_factor.pending_user = self.pending_user
self._current_factor.request = request
return super().dispatch(request, *args, **kwargs)
@ -93,7 +94,8 @@ class AuthenticationView(UserPassesTestMixin, View):
self.pending_factors
self.request.session[AuthenticationView.SESSION_FACTOR] = next_factor
LOGGER.debug("Rendering Factor is %s", next_factor)
return redirect(reverse('passbook_core:auth-process', kwargs={'factor': next_factor}))
# return redirect(reverse('passbook_core:auth-process', kwargs={'factor': next_factor}))
return redirect(reverse('passbook_core:auth-process'))
# User passed all factors
LOGGER.debug("User passed all factors, logging in")
return self._user_passed()
@ -102,6 +104,7 @@ class AuthenticationView(UserPassesTestMixin, View):
"""Show error message, user cannot login.
This should only be shown if user authenticated successfully, but is disabled/locked/etc"""
LOGGER.debug("User invalid")
self._cleanup()
return redirect(reverse('passbook_core:auth-denied'))
def _user_passed(self):

View File

@ -1,5 +1,6 @@
"""passbook Core Application forms"""
from django import forms
from django.utils.translation import gettext_lazy as _
from passbook.core.models import Application, Provider
@ -19,3 +20,7 @@ class ApplicationForm(forms.ModelForm):
'launch_url': forms.TextInput(),
'icon_url': forms.TextInput(),
}
labels = {
'launch_url': _('Launch URL'),
'icon_url': _('Icon URL'),
}

View File

@ -18,6 +18,11 @@ class LoginForm(forms.Form):
uid_field = forms.CharField(widget=forms.TextInput(attrs={'placeholder': _('UID')}))
remember_me = forms.BooleanField(required=False)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if CONFIG.y('passbook.uid_fields') == ['email']:
self.fields['uid_field'] = forms.EmailField()
def clean_uid_field(self):
"""Validate uid_field after EmailValidator if 'email' is the only selected uid_fields"""
if CONFIG.y('passbook.uid_fields') == ['email']:

View File

@ -17,7 +17,7 @@ class FactorForm(forms.ModelForm):
class Meta:
model = Factor
fields = ['name', 'slug', 'order', 'policies', 'type', 'enabled']
fields = ['name', 'slug', 'order', 'policies', 'type', 'enabled', 'arguments']
widgets = {
'type': forms.Select(choices=get_factors()),
'name': forms.TextInput(),

View File

@ -0,0 +1,28 @@
# Generated by Django 2.1.7 on 2019-02-21 12:01
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('passbook_core', '0004_auto_20190216_1013'),
]
operations = [
migrations.AlterField(
model_name='policy',
name='created',
field=models.DateTimeField(auto_now_add=True),
),
migrations.AlterField(
model_name='policymodel',
name='created',
field=models.DateTimeField(auto_now_add=True),
),
migrations.AlterField(
model_name='usersourceconnection',
name='created',
field=models.DateTimeField(auto_now_add=True),
),
]

View File

@ -0,0 +1,19 @@
# Generated by Django 2.1.7 on 2019-02-21 12:32
import django.contrib.postgres.fields.jsonb
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('passbook_core', '0005_auto_20190221_1201'),
]
operations = [
migrations.AddField(
model_name='factor',
name='arguments',
field=django.contrib.postgres.fields.jsonb.JSONField(default=dict),
),
]

View File

@ -0,0 +1,19 @@
# Generated by Django 2.1.7 on 2019-02-21 12:33
import django.contrib.postgres.fields.jsonb
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('passbook_core', '0006_factor_arguments'),
]
operations = [
migrations.AlterField(
model_name='factor',
name='arguments',
field=django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=dict),
),
]

View File

@ -6,6 +6,7 @@ from time import sleep
from uuid import uuid4
from django.contrib.auth.models import AbstractUser
from django.contrib.postgres.fields import JSONField
from django.db import models
from django.urls import reverse_lazy
from django.utils.translation import gettext as _
@ -69,6 +70,7 @@ class Factor(PolicyModel):
order = models.IntegerField()
type = models.TextField(unique=True)
enabled = models.BooleanField(default=True)
arguments = JSONField(default=dict, blank=True)
def __str__(self):
return "Factor %s" % self.slug

View File

@ -32,7 +32,7 @@ class PolicyEngine:
"""Check policies for user"""
signatures = []
kwargs = {
'__password__': getattr(user, '__password__')
'__password__': getattr(user, '__password__', None)
}
for policy in self.policies:
signatures.append(_policy_engine_task.s(user.pk, policy.pk.hex, **kwargs))

View File

@ -61,7 +61,7 @@ INSTALLED_APPS = [
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'rest_framework_swagger',
'drf_yasg',
'passbook.core.apps.PassbookCoreConfig',
'passbook.admin.apps.PassbookAdminConfig',
'passbook.api.apps.PassbookAPIConfig',

View File

@ -26,7 +26,7 @@
<div class="login-pf-page">
<div class="container-fluid">
<div class="row">
<div class="col-sm-8 col-sm-offset-2 col-md-6 col-md-offset-3 col-lg-6 col-lg-offset-3">
<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">
<img class="login-pf-brand" style="max-height: 10rem;" src="{% static 'img/logo.svg' %}" alt="PatternFly logo" />
{% if config.login.subtext %}

View File

@ -1,8 +1,4 @@
{% extends 'login/form.html' %}
{% extends 'login/factors/base.html' %}
{% load i18n %}
{% block above_form %}
<span class="pficon pficon-unlocked"></span>
{% trans "This is a text" %}
{% endblock %}

View File

@ -0,0 +1,31 @@
{% extends 'login/form.html' %}
{% load i18n %}
{% load utils %}
{% block head %}
{{ block.super }}
<style>
.login-pf-settings img {
max-height: 32px;
border-radius: 100%;
border-width: 1px;
border-color: #000;
}
.login-pf-settings a {
padding-top: 3px;
padding-bottom: 3px;
line-height: 32px;
}
</style>
{% endblock %}
{% block above_form %}
<div class="form-group login-pf-settings">
<p class="form-control-static">
<img src="{% gravatar pending_user.email %}" alt="">
{{ pending_user.username }}
</p>
<a href="{% url 'passbook_core:auth-login' %}">{% trans 'Not you?' %}</a>
</div>
{% endblock %}

View File

@ -1,68 +0,0 @@
{% extends "base/skeleton.html" %}
{% load static %}
{% block body %}
<div class="login-pf-page">
<div class="container-fluid">
<div class="row">
<div class="col-sm-8 col-sm-offset-2 col-md-6 col-md-offset-3 col-lg-6 col-lg-offset-3">
<header class="login-pf-page-header">
<img class="login-pf-brand" src="{% static 'img/Logo_Horizontal_Reversed.svg' %}" alt=" logo" />
</header>
<div class="row">
<div class="col-sm-10 col-sm-offset-1 col-md-8 col-md-offset-2 col-lg-8 col-lg-offset-2">
<div class="card-pf">
<header class="login-pf-header">
<select class="selectpicker">
<option>English</option>
<option>French</option>
<option>Italian</option>
</select>
<h1>Single Sign-On</h1>
<p class="text-center">Log in to <strong>Application</strong></p>
</header>
<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="form-group 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>
<p class="login-pf-signup">Need an account?<a href="#">Sign up</a></p>
</div><!-- card -->
<footer class="login-pf-page-footer">
<div class="login-pf-page-footer-sso-services">
<p>One account for all your company services</p>
<ul class="login-pf-page-footer-sso-services-logos">
<li><img src="{% static 'img/google-drive.svg' %}" alt="google drive icon" /></li>
<li><img src="{% static 'img/gmail.svg' %}" alt="gmail icon" /></li>
<li><img src="{% static 'img/google-calendar.svg' %}" alt="google calendar icon" /></li>
</ul>
</div>
<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><!-- col -->
</div><!-- row -->
</div><!-- col -->
</div><!-- login-pf-page -->
</div>
<!--row-->
</div>
<!--container-->
{% endblock %}

View File

@ -14,7 +14,7 @@
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/">
<img src="{% static 'img/brand.svg' %}" alt="PatternFly Enterprise Application" />
<img src="{% static 'img/brand.svg' %}" alt="passbook" />
</a>
</div>
<div class="collapse navbar-collapse navbar-collapse-1">
@ -63,7 +63,9 @@
</div>
</nav>
<div class="container-fluid container-cards-pf">
{% include 'partials/messages.html' %}
<div class="container">
{% include 'partials/messages.html' %}
</div>
{% block content %}
{% endblock %}
</div>

View File

@ -9,10 +9,18 @@
<div class="nav-category">
<h2>{% trans 'User Profile'%}</h2>
<ul class="nav nav-pills nav-stacked">
<li class="{% is_active 'passbook_core:user-settings' %}"><a href="{% url 'passbook_core:user-settings' %}"><i class="fa fa-desktop"></i>{% trans 'Details' %}</a></li>
<li><a href="#"><i class="fa fa-cog"></i>System Services</a></li>
<li><a href="#"><i class="fa fa-file-text-o"></i>Journal</a></li>
<li><a href="#"><i class="fa fa-cloud"></i>Storage</a></li>
<li class="{% is_active 'passbook_core:user-settings' %}">
<a href="{% url 'passbook_core:user-settings' %}">
<i class="fa fa-desktop"></i> {% trans 'Details' %}
</a>
</li>
<li class="{% is_active 'passbook_core:user-settings' %}">
<a href="{% url 'passbook_core:user-settings' %}">
<i class="pficon pficon-locked"></i> {% trans 'Change Password' %}
</a>
</li>
<li><a href="#"><i class="fa fa-file-text-o"></i> Journal</a></li>
<li><a href="#"><i class="fa fa-cloud"></i> Storage</a></li>
</ul>
</div>
</div>

View File

@ -0,0 +1,14 @@
{% extends "user/base.html" %}
{% load i18n %}
{% block page %}
<h1>{% trans 'Change Password' %}</h1>
<form action="" method="post" class="form-horizontal">
{% csrf_token %}
{% include 'partials/form.html' %}
<input class="btn btn-primary" type="submit" value="{% trans 'Update' %}">
<a class="btn btn-danger"
href="{% url 'passbook_core:user-delete' %}?back={{ request.get_full_path }}">{% trans 'Delete user' %}</a>
</form>
{% endblock %}

View File

@ -13,6 +13,7 @@ class OverviewView(LoginRequiredMixin, TemplateView):
template_name = 'overview/index.html'
def get_context_data(self, **kwargs):
print(self.request.session.keys())
kwargs['applications'] = self.request.user.applications.all()
if self.request.user.is_superuser:
kwargs['applications'] = Application.objects.all()