stages/prompt: add static and separator elements

This commit is contained in:
Jens Langhammer 2020-07-08 23:49:59 +02:00
parent e58ac7ae90
commit ef2cdf27b3
3 changed files with 65 additions and 9 deletions

View file

@ -1,12 +1,15 @@
"""Prompt forms"""
from typing import Callable
from django import forms
from django.contrib.admin.widgets import FilteredSelectMultiple
from django.utils.translation import gettext_lazy as _
from guardian.shortcuts import get_anonymous_user
from passbook.core.models import User
from passbook.flows.planner import PLAN_CONTEXT_PENDING_USER, FlowPlan
from passbook.policies.engine import PolicyEngine
from passbook.stages.prompt.models import Prompt, PromptStage
from passbook.stages.prompt.models import FieldTypes, Prompt, PromptStage
class PromptStageForm(forms.ModelForm):
@ -57,6 +60,14 @@ class PromptForm(forms.Form):
for field in fields:
field: Prompt
self.fields[field.field_key] = field.field
# Special handling for fields with username type
# these check for existing users with the same username
if field.type == FieldTypes.USERNAME:
setattr(
self,
f"clean_{field.field_key}",
username_field_cleaner_generator(field),
)
self.field_order = sorted(fields, key=lambda x: x.order)
def clean(self):
@ -68,3 +79,15 @@ class PromptForm(forms.Form):
result = engine.result
if not result.passing:
raise forms.ValidationError(list(result.messages))
def username_field_cleaner_generator(field: Prompt) -> Callable:
"""Return a `clean_` method for `field`. Clean method checks if username is taken already."""
def username_field_cleaner(self: PromptForm):
"""Check for duplicate usernames"""
username = self.cleaned_data.get(field.field_key)
if User.objects.filter(username=username).exists():
raise forms.ValidationError("Username is already taken.")
return username_field_cleaner

View file

@ -7,25 +7,34 @@ from django.utils.translation import gettext_lazy as _
from passbook.flows.models import Stage
from passbook.policies.models import PolicyBindingModel
from passbook.stages.prompt.widgets import HorizontalRuleWidget, StaticTextWidget
class FieldTypes(models.TextChoices):
"""Field types an Prompt can be"""
# Simple text field
TEXT = "text"
TEXT = "text", _("Text: Simple Text input")
# Same as text, but has autocomplete for password managers
USERNAME = "username"
EMAIL = "email"
USERNAME = (
"username",
_(
(
"Username: Same as Text input, but checks for "
"duplicate and prevents duplicate usernames."
)
),
)
EMAIL = "email", _("Email: Text field with Email type.")
PASSWORD = "password" # noqa # nosec
NUMBER = "number"
CHECKBOX = "checkbox"
DATE = "data"
DATE_TIME = "data-time"
SEPARATOR = "separator"
HIDDEN = "hidden"
STATIC = "static"
SEPARATOR = "separator", _("Separator: Static Separator Line")
HIDDEN = "hidden", _("Hidden: Hidden field, can be used to insert data into form.")
STATIC = "static", _("Static: Static value, displayed as-is.")
class Prompt(models.Model):
@ -74,9 +83,16 @@ class Prompt(models.Model):
field_class = forms.DateInput
if self.type == FieldTypes.DATE_TIME:
field_class = forms.DateTimeInput
if self.type == FieldTypes.STATIC:
widget = StaticTextWidget(attrs=attrs)
kwargs["initial"] = self.placeholder
kwargs["required"] = False
kwargs["label"] = ""
if self.type == FieldTypes.SEPARATOR:
widget = HorizontalRuleWidget(attrs=attrs)
kwargs["required"] = False
kwargs["label"] = ""
# TODO: Implement static
# TODO: Implement separator
kwargs["widget"] = widget
return field_class(**kwargs)

View file

@ -0,0 +1,17 @@
"""Prompt Widgets"""
from django import forms
from django.utils.safestring import mark_safe
class StaticTextWidget(forms.widgets.Widget):
"""Widget to render static text"""
def render(self, name, value, attrs=None, renderer=None):
return mark_safe(f"<p>{value}</p>") # nosec
class HorizontalRuleWidget(forms.widgets.Widget):
"""Widget, which renders an <hr> element"""
def render(self, name, value, attrs=None, renderer=None):
return mark_safe("<hr>") # nosec