admin: sort types, minor fixups

This commit is contained in:
Jens Langhammer 2020-05-13 11:57:10 +02:00
parent 57fed2b92b
commit c42ed6bc99
11 changed files with 121 additions and 80 deletions

View File

@ -34,7 +34,8 @@ class StageListView(LoginRequiredMixin, PermissionListMixin, ListView):
def get_context_data(self, **kwargs):
kwargs["types"] = {
x.__name__: x._meta.verbose_name for x in all_subclasses(Stage)
x.__name__: x._meta.verbose_name
for x in sorted(all_subclasses(Stage), key=lambda x: x.__name__)
}
return super().get_context_data(**kwargs)

View File

@ -86,13 +86,13 @@ router.register("stages/invitation", InvitationStageViewSet)
router.register("stages/invitation/invitations", InvitationViewSet)
router.register("stages/otp", OTPStageViewSet)
router.register("stages/password", PasswordStageViewSet)
router.register("stages/prompt", PromptStageViewSet)
router.register("stages/prompt/stages", PromptStageViewSet)
router.register("stages/prompt/prompts", PromptViewSet)
router.register("stages/user_login", UserLoginStageViewSet)
router.register("stages/user_logout", UserLogoutStageViewSet)
router.register("stages/user_write", UserWriteStageViewSet)
router.register("flows", FlowViewSet)
router.register("flows/instances", FlowViewSet)
router.register("flows/bindings", FlowStageBindingViewSet)
if settings.DEBUG:

View File

@ -25,6 +25,11 @@
<div class="select col-sm-10">
{{ field }}
</div>
{% if field.help_text %}
<span>
{{ field.help_text }}
</span>
{% endif %}
{% elif field.field.widget|fieldtype == 'CheckboxInput' %}
<label class="checkbox-label">
{{ field }} {{ field.label }}

View File

@ -57,12 +57,8 @@
<main role="main" class="pf-c-page__main" tabindex="-1" id="main-content">
<section class="pf-c-page__main-section">
<div class="pf-l-split pf-m-gutter">
<div class="pf-l-split__item">
<div class="pf-c-card">
{% block page %}
{% endblock %}
</div>
</div>
{% block page %}
{% endblock %}
</div>
</section>
</main>

View File

@ -3,22 +3,55 @@
{% load i18n %}
{% block page %}
<div class="pf-c-card__header pf-c-title pf-m-md">
<h1>{% trans 'Update details' %}</h1>
</div>
<div class="pf-c-card__body">
<form action="" method="post" class="pf-c-form pf-m-horizontal">
{% include 'partials/form_horizontal.html' with form=form %}
{% block beneath_form %}
{% endblock %}
<div class="pf-c-form__group pf-m-action">
<div class="pf-c-form__horizontal-group">
<div class="pf-c-form__actions">
<input class="pf-c-button pf-m-primary" type="submit" value="{% trans 'Update' %}" />
<a class="pf-c-button pf-m-danger" href="{% url 'passbook_flows:default-unenrollment' %}?back={{ request.get_full_path }}">{% trans "Delete account" %}</a>
</div>
</div>
<div class="pf-l-split__item">
<div class="pf-c-card">
<div class="pf-c-card__header pf-c-title pf-m-md">
<h1>{% trans 'Update details' %}</h1>
</div>
</form>
<div class="pf-c-card__body">
<form action="" method="post" class="pf-c-form pf-m-horizontal">
{% include 'partials/form_horizontal.html' with form=form %}
{% block beneath_form %}
{% endblock %}
<div class="pf-c-form__group pf-m-action">
<div class="pf-c-form__horizontal-group">
<div class="pf-c-form__actions">
<input class="pf-c-button pf-m-primary" type="submit" value="{% trans 'Update' %}" />
<a class="pf-c-button pf-m-danger" href="{% url 'passbook_flows:default-unenrollment' %}?back={{ request.get_full_path }}">{% trans "Delete account" %}</a>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
<div class="pf-l-split__item">
<div class="pf-c-card">
<div class="pf-c-card__header pf-c-title pf-m-md">
<h1>{% trans 'Sessions' %}</h1>
</div>
<div class="pf-c-card__body">
<table class="pf-c-table pf-m-grid-md" role="grid" aria-label="This is a simple table example" id="table-basic">
<thead>
<tr role="row">
<th role="columnheader" scope="col">Repositories</th>
<th role="columnheader" scope="col">Branches</th>
<th role="columnheader" scope="col">Pull requests</th>
<th role="columnheader" scope="col">Workspaces</th>
<th role="columnheader" scope="col">Last commit</th>
</tr>
</thead>
<tbody role="rowgroup">
<tr role="row">
<td role="cell" data-label="Repository name">Repository 1</td>
<td role="cell" data-label="Branches">10</td>
<td role="cell" data-label="Pull requests">25</td>
<td role="cell" data-label="Workspaces">5</td>
<td role="cell" data-label="Last commit">2 days ago</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
{% endblock %}

View File

@ -6,6 +6,7 @@ from django.template.context import RequestContext
from passbook.core.models import Source
from passbook.core.types import UIUserSettings
from passbook.flows.models import Stage
from passbook.policies.engine import PolicyEngine
register = template.Library()
@ -15,20 +16,14 @@ register = template.Library()
# 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())
_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)
for stage in _all_stages:
user_settings = stage.ui_user_settings
if not user_settings:
continue
matching_stages.append(user_settings)
print(matching_stages)
return matching_stages

View File

@ -35,21 +35,27 @@ class FlowStageBindingViewSet(ModelViewSet):
queryset = FlowStageBinding.objects.all()
serializer_class = FlowStageBindingSerializer
filterset_fields = "__all__"
class StageSerializer(ModelSerializer):
"""Stage Serializer"""
__type__ = SerializerMethodField(method_name="get_type")
verbose_name = SerializerMethodField(method_name="get_verbose_name")
def get_type(self, obj):
def get_type(self, obj: Stage) -> str:
"""Get object type so that we know which API Endpoint to use to get the full object"""
return obj._meta.object_name.lower().replace("stage", "")
def get_verbose_name(self, obj: Stage) -> str:
"""Get verbose name for UI"""
return obj._meta.verbose_name
class Meta:
model = Stage
fields = ["pk", "name", "__type__"]
fields = ["pk", "name", "__type__", "verbose_name"]
class StageViewSet(ReadOnlyModelViewSet):

View File

@ -20,6 +20,16 @@ class FlowForm(forms.ModelForm):
"stages",
"policies",
]
help_texts = {
"name": _("Shown as the Title in Flow pages."),
"slug": _("Visible in the URL."),
"designation": _(
(
"Decides what this Flow is used for. For example, the Authentication flow "
"is redirect to when an un-authenticated user visits passbook."
)
),
}
widgets = {
"name": forms.TextInput(),
"stages": FilteredSelectMultiple(_("stages"), False),

View File

@ -77,6 +77,7 @@ INSTALLED_APPS = [
"django.contrib.postgres",
"django.contrib.humanize",
"rest_framework",
"django_filters",
"drf_yasg",
"guardian",
"django_prometheus",

View File

@ -4,45 +4,39 @@
{% load i18n %}
{% block page %}
<div class="pf-c-card__header pf-c-title pf-m-md">
<h1>{% trans "One-Time Passwords" %}</h1>
<div class="pf-c-card">
<div class="pf-c-card__header pf-c-title pf-m-md">
{% trans "One-Time Passwords" %}
</div>
<div class="pf-c-card__body">
<p>
{% blocktrans with state=state|yesno:"Enabled,Disabled" %}
Status: {{ state }}
{% endblocktrans %}
{% if state %}
<i class="pf-icon pf-icon-ok"></i>
{% else %}
<i class="pf-icon pf-icon-error-circle-o"></i>
{% endif %}
</p>
<p>
{% if not state %}
<a href="{% url 'passbook_stages_otp:otp-enable' %}" class="btn btn-success btn-sm">{% trans "Enable OTP" %}</a>
{% else %}
<a href="{% url 'passbook_stages_otp:otp-disable' %}" class="btn btn-danger btn-sm">{% trans "Disable OTP" %}</a>
{% endif %}
</p>
</div>
</div>
<div class="pf-c-card__body">
<div class="row">
<div class="col-md-6">
<div class="card-footer">
<p>
{% blocktrans with state=state|yesno:"Enabled,Disabled" %}
Status: {{ state }}
{% endblocktrans %}
{% if state %}
<i class="pf-icon pf-icon-ok"></i>
{% else %}
<i class="pf-icon pf-icon-error-circle-o"></i>
{% endif %}
</p>
<p>
{% if not state %}
<a href="{% url 'passbook_stages_otp:otp-enable' %}"
class="btn btn-success btn-sm">{% trans "Enable OTP" %}</a>
{% else %}
<a href="{% url 'passbook_stages_otp:otp-disable' %}"
class="btn btn-danger btn-sm">{% trans "Disable OTP" %}</a>
{% endif %}
</p>
</div>
</div>
<div class="col-md-6">
<div class="card">
<div class="card-header">
{% trans "Your Backup tokens:" %}
</div>
<div class="card-block">
<pre>{% for token in static_tokens %}{{ token.token }}
{% empty %}{% trans 'N/A' %}{% endfor %}</pre>
</div>
</div>
</div>
<div class="pf-c-card">
<div class="pf-c-card__header pf-c-title pf-m-md">
{% trans "Your Backup tokens:" %}
</div>
<div class="pf-c-card__body">
<pre>{% for token in static_tokens %}{{ token.token }}
{% empty %}{% trans 'N/A' %}{% endfor %}</pre>
</div>
</div>
{% endblock %}
</div>
{% endblock %}

View File

@ -31,7 +31,7 @@ LOGGER = get_logger()
class UserSettingsView(LoginRequiredMixin, TemplateView):
"""View for user settings to control OTP"""
template_name = "otp/user_settings.html"
template_name = "stages/otp/user_settings.html"
# TODO: Check if OTP Stage exists and applies to user
def get_context_data(self, **kwargs):