factors: -> stage

This commit is contained in:
Jens Langhammer
2020-05-08 19:46:39 +02:00
parent 08c0eb2ec6
commit 212e966dd4
99 changed files with 745 additions and 958 deletions

View File

@ -1,30 +0,0 @@
"""Factor API Views"""
from rest_framework.serializers import ModelSerializer, SerializerMethodField
from rest_framework.viewsets import ReadOnlyModelViewSet
from passbook.core.models import Factor
class FactorSerializer(ModelSerializer):
"""Factor Serializer"""
__type__ = SerializerMethodField(method_name="get_type")
def get_type(self, obj):
"""Get object type so that we know which API Endpoint to use to get the full object"""
return obj._meta.object_name.lower().replace("factor", "")
class Meta:
model = Factor
fields = ["pk", "name", "slug", "order", "enabled", "__type__"]
class FactorViewSet(ReadOnlyModelViewSet):
"""Factor Viewset"""
queryset = Factor.objects.all()
serializer_class = FactorSerializer
def get_queryset(self):
return Factor.objects.select_subclasses()

View File

@ -0,0 +1,14 @@
# Generated by Django 3.0.3 on 2020-05-08 17:58
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("passbook_core", "0011_auto_20200222_1822"),
]
operations = [
migrations.DeleteModel(name="Factor",),
]

View File

@ -103,30 +103,6 @@ class PolicyModel(UUIDModel, CreatedUpdatedModel):
policies = models.ManyToManyField("Policy", blank=True)
class Factor(ExportModelOperationsMixin("factor"), PolicyModel):
"""Authentication factor, multiple instances of the same Factor can be used"""
name = models.TextField(help_text=_("Factor's display Name."))
slug = models.SlugField(
unique=True, help_text=_("Internal factor name, used in URLs.")
)
order = models.IntegerField()
enabled = models.BooleanField(default=True)
objects = InheritanceManager()
type = ""
form = ""
@property
def ui_user_settings(self) -> Optional[UIUserSettings]:
"""Entrypoint to integrate with User settings. Can either return None if no
user settings are available, or an instanace of UIUserSettings."""
return None
def __str__(self):
return f"Factor {self.slug}"
class Application(ExportModelOperationsMixin("application"), PolicyModel):
"""Every Application which uses passbook for authentication/identification/authorization
needs an Application record. Other authentication types can subclass this Model to

View File

@ -18,16 +18,16 @@
</li>
</ul>
</section>
{% user_factors as user_factors_loc %}
{% if user_factors_loc %}
{% user_stages as user_stages_loc %}
{% if user_stages_loc %}
<section class="pf-c-nav__section">
<h2 class="pf-c-nav__section-title">{% trans 'Factors' %}</h2>
<ul class="pf-c-nav__list">
{% for factor in user_factors_loc %}
{% for stage in user_stages_loc %}
<li class="pf-c-nav__item">
<a href="{% url factor.view_name %}" class="pf-c-nav__link {% is_active factor.view_name %}">
<i class="{{ factor.icon }}"></i>
{{ factor.name }}
<a href="{% url stage.view_name %}" class="pf-c-nav__link {% is_active stage.view_name %}">
<i class="{{ stage.icon }}"></i>
{{ stage.name }}
</a>
</li>
{% endfor %}

View File

@ -4,7 +4,7 @@ from typing import Iterable, List
from django import template
from django.template.context import RequestContext
from passbook.core.models import Factor, Source
from passbook.core.models import Source
from passbook.core.types import UIUserSettings
from passbook.policies.engine import PolicyEngine
@ -12,24 +12,24 @@ register = template.Library()
@register.simple_tag(takes_context=True)
def user_factors(context: RequestContext) -> List[UIUserSettings]:
"""Return list of all factors which apply to user"""
user = context.get("request").user
_all_factors: Iterable[Factor] = (
Factor.objects.filter(enabled=True).order_by("order").select_subclasses()
)
matching_factors: List[UIUserSettings] = []
for factor in _all_factors:
user_settings = factor.ui_user_settings
if not user_settings:
continue
policy_engine = PolicyEngine(
factor.policies.all(), user, context.get("request")
)
policy_engine.build()
if policy_engine.passing:
matching_factors.append(user_settings)
return matching_factors
# pylint: disable=unused-argument
def user_stages(context: RequestContext) -> List[UIUserSettings]:
"""Return list of all stages which apply to user"""
# TODO: Rewrite this based on flows
# user = context.get("request").user
# _all_stages: Iterable[Stage] = (Stage.objects.all().select_subclasses())
matching_stages: List[UIUserSettings] = []
# for stage in _all_stages:
# user_settings = stage.ui_user_settings
# if not user_settings:
# continue
# policy_engine = PolicyEngine(
# stage.policies.all(), user, context.get("request")
# )
# policy_engine.build()
# if policy_engine.passing:
# matching_stages.append(user_settings)
return matching_stages
@register.simple_tag(takes_context=True)
@ -40,12 +40,12 @@ def user_sources(context: RequestContext) -> List[UIUserSettings]:
Source.objects.filter(enabled=True).select_subclasses()
)
matching_sources: List[UIUserSettings] = []
for factor in _all_sources:
user_settings = factor.ui_user_settings
for source in _all_sources:
user_settings = source.ui_user_settings
if not user_settings:
continue
policy_engine = PolicyEngine(
factor.policies.all(), user, context.get("request")
source.policies.all(), user, context.get("request")
)
policy_engine.build()
if policy_engine.passing:

View File

@ -5,7 +5,7 @@ from typing import Optional
@dataclass
class UIUserSettings:
"""Dataclass for Factor and Source's user_settings"""
"""Dataclass for Stage and Source's user_settings"""
name: str
icon: str

View File

@ -15,12 +15,12 @@ from structlog import get_logger
from passbook.core.forms.authentication import LoginForm, SignUpForm
from passbook.core.models import Invitation, Nonce, Source, User
from passbook.core.signals import invitation_used, user_signed_up
from passbook.factors.password.exceptions import PasswordPolicyInvalid
from passbook.flows.models import Flow, FlowDesignation
from passbook.flows.planner import PLAN_CONTEXT_PENDING_USER, FlowPlanner
from passbook.flows.views import SESSION_KEY_PLAN
from passbook.lib.config import CONFIG
from passbook.lib.utils.urls import redirect_with_qs
from passbook.stages.password.exceptions import PasswordPolicyInvalid
LOGGER = get_logger()

View File

@ -10,8 +10,8 @@ from django.utils.translation import gettext as _
from django.views.generic import DeleteView, FormView, UpdateView
from passbook.core.forms.users import PasswordChangeForm, UserDetailForm
from passbook.factors.password.exceptions import PasswordPolicyInvalid
from passbook.lib.config import CONFIG
from passbook.stages.password.exceptions import PasswordPolicyInvalid
class UserSettingsView(SuccessMessageMixin, LoginRequiredMixin, UpdateView):