admin: sort types, minor fixups
This commit is contained in:
		| @ -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,13 +57,9 @@ | |||||||
| <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"> |  | ||||||
|                 <div class="pf-c-card"> |  | ||||||
|             {% block page %} |             {% block page %} | ||||||
|             {% endblock %} |             {% endblock %} | ||||||
|         </div> |         </div> | ||||||
|             </div> |  | ||||||
|         </div> |  | ||||||
|     </section> |     </section> | ||||||
| </main> | </main> | ||||||
| {% endblock %} | {% endblock %} | ||||||
|  | |||||||
| @ -3,6 +3,8 @@ | |||||||
| {% load i18n %} | {% load i18n %} | ||||||
|  |  | ||||||
| {% block page %} | {% block page %} | ||||||
|  | <div class="pf-l-split__item"> | ||||||
|  |     <div class="pf-c-card"> | ||||||
|         <div class="pf-c-card__header pf-c-title pf-m-md"> |         <div class="pf-c-card__header pf-c-title pf-m-md"> | ||||||
|             <h1>{% trans 'Update details' %}</h1> |             <h1>{% trans 'Update details' %}</h1> | ||||||
|         </div> |         </div> | ||||||
| @ -21,4 +23,35 @@ | |||||||
|                 </div> |                 </div> | ||||||
|             </form> |             </form> | ||||||
|         </div> |         </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 %} | {% 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,13 +4,11 @@ | |||||||
| {% load i18n %} | {% load i18n %} | ||||||
|  |  | ||||||
| {% block page %} | {% block page %} | ||||||
|  | <div class="pf-c-card"> | ||||||
|     <div class="pf-c-card__header pf-c-title pf-m-md"> |     <div class="pf-c-card__header pf-c-title pf-m-md"> | ||||||
|     <h1>{% trans "One-Time Passwords" %}</h1> |         {% trans "One-Time Passwords" %} | ||||||
|     </div> |     </div> | ||||||
|     <div class="pf-c-card__body"> |     <div class="pf-c-card__body"> | ||||||
|     <div class="row"> |  | ||||||
|         <div class="col-md-6"> |  | ||||||
|             <div class="card-footer"> |  | ||||||
|         <p> |         <p> | ||||||
|             {% blocktrans with state=state|yesno:"Enabled,Disabled" %} |             {% blocktrans with state=state|yesno:"Enabled,Disabled" %} | ||||||
|             Status: {{ state }} |             Status: {{ state }} | ||||||
| @ -23,26 +21,22 @@ | |||||||
|         </p> |         </p> | ||||||
|         <p> |         <p> | ||||||
|             {% if not state %} |             {% if not state %} | ||||||
|                     <a href="{% url 'passbook_stages_otp:otp-enable' %}" |             <a href="{% url 'passbook_stages_otp:otp-enable' %}" class="btn btn-success btn-sm">{% trans "Enable OTP" %}</a> | ||||||
|                     class="btn btn-success btn-sm">{% trans "Enable OTP" %}</a> |  | ||||||
|             {% else %} |             {% else %} | ||||||
|                     <a href="{% url 'passbook_stages_otp:otp-disable' %}" |             <a href="{% url 'passbook_stages_otp:otp-disable' %}" class="btn btn-danger btn-sm">{% trans "Disable OTP" %}</a> | ||||||
|                     class="btn btn-danger btn-sm">{% trans "Disable OTP" %}</a> |  | ||||||
|             {% endif %} |             {% endif %} | ||||||
|         </p> |         </p> | ||||||
|     </div> |     </div> | ||||||
| </div> | </div> | ||||||
|         <div class="col-md-6"> |  | ||||||
|             <div class="card"> | <div class="pf-c-card"> | ||||||
|                 <div class="card-header"> |     <div class="pf-c-card__header pf-c-title pf-m-md"> | ||||||
|         {% trans "Your Backup tokens:" %} |         {% trans "Your Backup tokens:" %} | ||||||
|     </div> |     </div> | ||||||
|                 <div class="card-block"> |     <div class="pf-c-card__body"> | ||||||
|         <pre>{% for token in static_tokens %}{{ token.token }} |         <pre>{% for token in static_tokens %}{{ token.token }} | ||||||
|         {% empty %}{% trans 'N/A' %}{% endfor %}</pre> |         {% empty %}{% trans 'N/A' %}{% endfor %}</pre> | ||||||
|         </div> |         </div> | ||||||
|     </div> |     </div> | ||||||
| </div> | </div> | ||||||
|         </div> |  | ||||||
|     </div> |  | ||||||
| {% endblock %} | {% 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
	
	Block a user
	 Jens Langhammer
					Jens Langhammer