Rules -> Policies, more things
This commit is contained in:
@ -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)
|
||||
|
||||
@ -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):
|
||||
|
||||
@ -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'),
|
||||
}
|
||||
|
||||
@ -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']:
|
||||
|
||||
@ -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(),
|
||||
|
||||
28
passbook/core/migrations/0005_auto_20190221_1201.py
Normal file
28
passbook/core/migrations/0005_auto_20190221_1201.py
Normal 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),
|
||||
),
|
||||
]
|
||||
19
passbook/core/migrations/0006_factor_arguments.py
Normal file
19
passbook/core/migrations/0006_factor_arguments.py
Normal 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),
|
||||
),
|
||||
]
|
||||
19
passbook/core/migrations/0007_auto_20190221_1233.py
Normal file
19
passbook/core/migrations/0007_auto_20190221_1233.py
Normal 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),
|
||||
),
|
||||
]
|
||||
@ -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
|
||||
|
||||
@ -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))
|
||||
|
||||
@ -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',
|
||||
|
||||
@ -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 %}
|
||||
|
||||
@ -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 %}
|
||||
|
||||
31
passbook/core/templates/login/factors/base.html
Normal file
31
passbook/core/templates/login/factors/base.html
Normal 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 %}
|
||||
@ -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 %}
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
14
passbook/core/templates/user/change_password.html
Normal file
14
passbook/core/templates/user/change_password.html
Normal 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 %}
|
||||
@ -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()
|
||||
|
||||
Reference in New Issue
Block a user