This repository has been archived on 2024-05-31. You can view files and clone it, but cannot push or open issues or pull requests.
authentik/passbook/admin/views/utils.py

125 lines
4.2 KiB
Python

"""passbook admin util views"""
from typing import Any, Dict, List, Optional
from urllib.parse import urlparse
from django.contrib import messages
from django.contrib.messages.views import SuccessMessageMixin
from django.contrib.postgres.search import SearchQuery, SearchVector
from django.db.models import QuerySet
from django.http import Http404
from django.http.request import HttpRequest
from django.views.generic import DeleteView, ListView, UpdateView
from django.views.generic.list import MultipleObjectMixin
from passbook.lib.utils.reflection import all_subclasses
from passbook.lib.views import CreateAssignPermView
class DeleteMessageView(SuccessMessageMixin, DeleteView):
"""DeleteView which shows `self.success_message` on successful deletion"""
def delete(self, request, *args, **kwargs):
messages.success(self.request, self.success_message)
return super().delete(request, *args, **kwargs)
class InheritanceListView(ListView):
"""ListView for objects using InheritanceManager"""
def get_context_data(self, **kwargs):
kwargs["types"] = {x.__name__: x for x in all_subclasses(self.model)}
return super().get_context_data(**kwargs)
def get_queryset(self):
return super().get_queryset().select_subclasses()
class SearchListMixin(MultipleObjectMixin):
"""Accept search query using `search` querystring parameter. Requires self.search_fields,
a list of all fields to search. Can contain special lookups like __icontains"""
search_fields: List[str]
def get_queryset(self) -> QuerySet:
queryset = super().get_queryset()
if "search" in self.request.GET:
raw_query = self.request.GET["search"]
if raw_query == "":
# Empty query, don't search at all
return queryset
search = SearchQuery(raw_query, search_type="websearch")
return queryset.annotate(search=SearchVector(*self.search_fields)).filter(
search=search
)
return queryset
class InheritanceCreateView(CreateAssignPermView):
"""CreateView for objects using InheritanceManager"""
def get_form_class(self):
provider_type = self.request.GET.get("type")
try:
model = next(
x for x in all_subclasses(self.model) if x.__name__ == provider_type
)
except StopIteration as exc:
raise Http404 from exc
return model().form
def get_context_data(self, **kwargs: Any) -> Dict[str, Any]:
kwargs = super().get_context_data(**kwargs)
form_cls = self.get_form_class()
if hasattr(form_cls, "template_name"):
kwargs["base_template"] = form_cls.template_name
return kwargs
class InheritanceUpdateView(UpdateView):
"""UpdateView for objects using InheritanceManager"""
def get_context_data(self, **kwargs: Any) -> Dict[str, Any]:
kwargs = super().get_context_data(**kwargs)
form_cls = self.get_form_class()
if hasattr(form_cls, "template_name"):
kwargs["base_template"] = form_cls.template_name
return kwargs
def get_form_class(self):
return self.get_object().form
def get_object(self, queryset=None):
return (
self.model.objects.filter(pk=self.kwargs.get("pk"))
.select_subclasses()
.first()
)
class BackSuccessUrlMixin:
"""Checks if a relative URL has been given as ?back param, and redirect to it. Otherwise
default to self.success_url."""
request: HttpRequest
success_url: Optional[str]
def get_success_url(self) -> str:
"""get_success_url from FormMixin"""
back_param = self.request.GET.get("back")
if back_param:
if not bool(urlparse(back_param).netloc):
return back_param
return str(self.success_url)
class UserPaginateListMixin:
"""Get paginate_by value from user's attributes, defaulting to 15"""
request: HttpRequest
# pylint: disable=unused-argument
def get_paginate_by(self, queryset: QuerySet) -> int:
"""get_paginate_by Function of ListView"""
return self.request.user.attributes.get("paginate_by", 15)