admin: sort types, minor fixups
This commit is contained in:
parent
57fed2b92b
commit
c42ed6bc99
|
@ -34,7 +34,8 @@ class StageListView(LoginRequiredMixin, PermissionListMixin, ListView):
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
kwargs["types"] = {
|
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)
|
return super().get_context_data(**kwargs)
|
||||||
|
|
||||||
|
|
|
@ -86,13 +86,13 @@ router.register("stages/invitation", InvitationStageViewSet)
|
||||||
router.register("stages/invitation/invitations", InvitationViewSet)
|
router.register("stages/invitation/invitations", InvitationViewSet)
|
||||||
router.register("stages/otp", OTPStageViewSet)
|
router.register("stages/otp", OTPStageViewSet)
|
||||||
router.register("stages/password", PasswordStageViewSet)
|
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/prompt/prompts", PromptViewSet)
|
||||||
router.register("stages/user_login", UserLoginStageViewSet)
|
router.register("stages/user_login", UserLoginStageViewSet)
|
||||||
router.register("stages/user_logout", UserLogoutStageViewSet)
|
router.register("stages/user_logout", UserLogoutStageViewSet)
|
||||||
router.register("stages/user_write", UserWriteStageViewSet)
|
router.register("stages/user_write", UserWriteStageViewSet)
|
||||||
|
|
||||||
router.register("flows", FlowViewSet)
|
router.register("flows/instances", FlowViewSet)
|
||||||
router.register("flows/bindings", FlowStageBindingViewSet)
|
router.register("flows/bindings", FlowStageBindingViewSet)
|
||||||
|
|
||||||
if settings.DEBUG:
|
if settings.DEBUG:
|
||||||
|
|
|
@ -25,6 +25,11 @@
|
||||||
<div class="select col-sm-10">
|
<div class="select col-sm-10">
|
||||||
{{ field }}
|
{{ field }}
|
||||||
</div>
|
</div>
|
||||||
|
{% if field.help_text %}
|
||||||
|
<span>
|
||||||
|
{{ field.help_text }}
|
||||||
|
</span>
|
||||||
|
{% endif %}
|
||||||
{% elif field.field.widget|fieldtype == 'CheckboxInput' %}
|
{% elif field.field.widget|fieldtype == 'CheckboxInput' %}
|
||||||
<label class="checkbox-label">
|
<label class="checkbox-label">
|
||||||
{{ field }} {{ field.label }}
|
{{ field }} {{ field.label }}
|
||||||
|
|
|
@ -57,12 +57,8 @@
|
||||||
<main role="main" class="pf-c-page__main" tabindex="-1" id="main-content">
|
<main role="main" class="pf-c-page__main" tabindex="-1" id="main-content">
|
||||||
<section class="pf-c-page__main-section">
|
<section class="pf-c-page__main-section">
|
||||||
<div class="pf-l-split pf-m-gutter">
|
<div class="pf-l-split pf-m-gutter">
|
||||||
<div class="pf-l-split__item">
|
{% block page %}
|
||||||
<div class="pf-c-card">
|
{% endblock %}
|
||||||
{% block page %}
|
|
||||||
{% endblock %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</main>
|
</main>
|
||||||
|
|
|
@ -3,22 +3,55 @@
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
{% block page %}
|
{% block page %}
|
||||||
<div class="pf-c-card__header pf-c-title pf-m-md">
|
<div class="pf-l-split__item">
|
||||||
<h1>{% trans 'Update details' %}</h1>
|
<div class="pf-c-card">
|
||||||
</div>
|
<div class="pf-c-card__header pf-c-title pf-m-md">
|
||||||
<div class="pf-c-card__body">
|
<h1>{% trans 'Update details' %}</h1>
|
||||||
<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>
|
</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>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -6,6 +6,7 @@ from django.template.context import RequestContext
|
||||||
|
|
||||||
from passbook.core.models import Source
|
from passbook.core.models import Source
|
||||||
from passbook.core.types import UIUserSettings
|
from passbook.core.types import UIUserSettings
|
||||||
|
from passbook.flows.models import Stage
|
||||||
from passbook.policies.engine import PolicyEngine
|
from passbook.policies.engine import PolicyEngine
|
||||||
|
|
||||||
register = template.Library()
|
register = template.Library()
|
||||||
|
@ -15,20 +16,14 @@ register = template.Library()
|
||||||
# pylint: disable=unused-argument
|
# pylint: disable=unused-argument
|
||||||
def user_stages(context: RequestContext) -> List[UIUserSettings]:
|
def user_stages(context: RequestContext) -> List[UIUserSettings]:
|
||||||
"""Return list of all stages which apply to user"""
|
"""Return list of all stages which apply to user"""
|
||||||
# TODO: Rewrite this based on flows
|
_all_stages: Iterable[Stage] = Stage.objects.all().select_subclasses()
|
||||||
# user = context.get("request").user
|
|
||||||
# _all_stages: Iterable[Stage] = (Stage.objects.all().select_subclasses())
|
|
||||||
matching_stages: List[UIUserSettings] = []
|
matching_stages: List[UIUserSettings] = []
|
||||||
# for stage in _all_stages:
|
for stage in _all_stages:
|
||||||
# user_settings = stage.ui_user_settings
|
user_settings = stage.ui_user_settings
|
||||||
# if not user_settings:
|
if not user_settings:
|
||||||
# continue
|
continue
|
||||||
# policy_engine = PolicyEngine(
|
matching_stages.append(user_settings)
|
||||||
# stage.policies.all(), user, context.get("request")
|
print(matching_stages)
|
||||||
# )
|
|
||||||
# policy_engine.build()
|
|
||||||
# if policy_engine.passing:
|
|
||||||
# matching_stages.append(user_settings)
|
|
||||||
return matching_stages
|
return matching_stages
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -35,21 +35,27 @@ class FlowStageBindingViewSet(ModelViewSet):
|
||||||
|
|
||||||
queryset = FlowStageBinding.objects.all()
|
queryset = FlowStageBinding.objects.all()
|
||||||
serializer_class = FlowStageBindingSerializer
|
serializer_class = FlowStageBindingSerializer
|
||||||
|
filterset_fields = "__all__"
|
||||||
|
|
||||||
|
|
||||||
class StageSerializer(ModelSerializer):
|
class StageSerializer(ModelSerializer):
|
||||||
"""Stage Serializer"""
|
"""Stage Serializer"""
|
||||||
|
|
||||||
__type__ = SerializerMethodField(method_name="get_type")
|
__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"""
|
"""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", "")
|
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:
|
class Meta:
|
||||||
|
|
||||||
model = Stage
|
model = Stage
|
||||||
fields = ["pk", "name", "__type__"]
|
fields = ["pk", "name", "__type__", "verbose_name"]
|
||||||
|
|
||||||
|
|
||||||
class StageViewSet(ReadOnlyModelViewSet):
|
class StageViewSet(ReadOnlyModelViewSet):
|
||||||
|
|
|
@ -20,6 +20,16 @@ class FlowForm(forms.ModelForm):
|
||||||
"stages",
|
"stages",
|
||||||
"policies",
|
"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 = {
|
widgets = {
|
||||||
"name": forms.TextInput(),
|
"name": forms.TextInput(),
|
||||||
"stages": FilteredSelectMultiple(_("stages"), False),
|
"stages": FilteredSelectMultiple(_("stages"), False),
|
||||||
|
|
|
@ -77,6 +77,7 @@ INSTALLED_APPS = [
|
||||||
"django.contrib.postgres",
|
"django.contrib.postgres",
|
||||||
"django.contrib.humanize",
|
"django.contrib.humanize",
|
||||||
"rest_framework",
|
"rest_framework",
|
||||||
|
"django_filters",
|
||||||
"drf_yasg",
|
"drf_yasg",
|
||||||
"guardian",
|
"guardian",
|
||||||
"django_prometheus",
|
"django_prometheus",
|
||||||
|
|
|
@ -4,45 +4,39 @@
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
{% block page %}
|
{% block page %}
|
||||||
<div class="pf-c-card__header pf-c-title pf-m-md">
|
<div class="pf-c-card">
|
||||||
<h1>{% trans "One-Time Passwords" %}</h1>
|
<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>
|
||||||
<div class="pf-c-card__body">
|
|
||||||
<div class="row">
|
<div class="pf-c-card">
|
||||||
<div class="col-md-6">
|
<div class="pf-c-card__header pf-c-title pf-m-md">
|
||||||
<div class="card-footer">
|
{% trans "Your Backup tokens:" %}
|
||||||
<p>
|
</div>
|
||||||
{% blocktrans with state=state|yesno:"Enabled,Disabled" %}
|
<div class="pf-c-card__body">
|
||||||
Status: {{ state }}
|
<pre>{% for token in static_tokens %}{{ token.token }}
|
||||||
{% endblocktrans %}
|
{% empty %}{% trans 'N/A' %}{% endfor %}</pre>
|
||||||
{% 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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
|
@ -31,7 +31,7 @@ LOGGER = get_logger()
|
||||||
class UserSettingsView(LoginRequiredMixin, TemplateView):
|
class UserSettingsView(LoginRequiredMixin, TemplateView):
|
||||||
"""View for user settings to control OTP"""
|
"""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
|
# TODO: Check if OTP Stage exists and applies to user
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
|
|
Reference in New Issue