Initial commit
This commit is contained in:
0
env/lib/python3.10/site-packages/wagtail/users/views/__init__.py
vendored
Normal file
0
env/lib/python3.10/site-packages/wagtail/users/views/__init__.py
vendored
Normal file
BIN
env/lib/python3.10/site-packages/wagtail/users/views/__pycache__/__init__.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/wagtail/users/views/__pycache__/__init__.cpython-310.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/wagtail/users/views/__pycache__/groups.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/wagtail/users/views/__pycache__/groups.cpython-310.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/wagtail/users/views/__pycache__/users.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/wagtail/users/views/__pycache__/users.cpython-310.pyc
vendored
Normal file
Binary file not shown.
5
env/lib/python3.10/site-packages/wagtail/users/views/bulk_actions/__init__.py
vendored
Normal file
5
env/lib/python3.10/site-packages/wagtail/users/views/bulk_actions/__init__.py
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
from .assign_role import AssignRoleBulkAction
|
||||
from .delete import DeleteBulkAction
|
||||
from .set_active_state import SetActiveStateBulkAction
|
||||
|
||||
__all__ = ["AssignRoleBulkAction", "DeleteBulkAction", "SetActiveStateBulkAction"]
|
||||
Binary file not shown.
Binary file not shown.
BIN
env/lib/python3.10/site-packages/wagtail/users/views/bulk_actions/__pycache__/delete.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/wagtail/users/views/bulk_actions/__pycache__/delete.cpython-310.pyc
vendored
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
46
env/lib/python3.10/site-packages/wagtail/users/views/bulk_actions/assign_role.py
vendored
Normal file
46
env/lib/python3.10/site-packages/wagtail/users/views/bulk_actions/assign_role.py
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
from django import forms
|
||||
from django.contrib.auth.models import Group
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.utils.translation import ngettext
|
||||
|
||||
from wagtail.users.views.bulk_actions.user_bulk_action import UserBulkAction
|
||||
from wagtail.users.views.users import change_user_perm
|
||||
|
||||
|
||||
class RoleForm(forms.Form):
|
||||
role = forms.ModelChoiceField(queryset=Group.objects.all())
|
||||
|
||||
|
||||
class AssignRoleBulkAction(UserBulkAction):
|
||||
display_name = _("Assign role")
|
||||
action_type = "assign_role"
|
||||
aria_label = _("Assign role to selected users")
|
||||
template_name = "wagtailusers/bulk_actions/confirm_bulk_assign_role.html"
|
||||
action_priority = 30
|
||||
form_class = RoleForm
|
||||
|
||||
def check_perm(self, obj):
|
||||
return self.request.user.has_perm(change_user_perm)
|
||||
|
||||
def get_execution_context(self):
|
||||
return {
|
||||
"role": self.cleaned_form.cleaned_data["role"],
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def execute_action(cls, objects, role=None, **kwargs):
|
||||
if role is None:
|
||||
return
|
||||
role.user_set.add(*objects)
|
||||
num_parent_objects = len(objects)
|
||||
return num_parent_objects, 0
|
||||
|
||||
def get_success_message(self, num_parent_objects, num_child_objects):
|
||||
return ngettext(
|
||||
"%(num_parent_objects)d user has been assigned as %(role)s",
|
||||
"%(num_parent_objects)d users have been assigned as %(role)s",
|
||||
num_parent_objects,
|
||||
) % {
|
||||
"num_parent_objects": num_parent_objects,
|
||||
"role": self.cleaned_form.cleaned_data["role"].name,
|
||||
}
|
||||
34
env/lib/python3.10/site-packages/wagtail/users/views/bulk_actions/delete.py
vendored
Normal file
34
env/lib/python3.10/site-packages/wagtail/users/views/bulk_actions/delete.py
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.utils.translation import ngettext
|
||||
|
||||
from wagtail.users.utils import user_can_delete_user
|
||||
from wagtail.users.views.bulk_actions.user_bulk_action import UserBulkAction
|
||||
|
||||
|
||||
class DeleteBulkAction(UserBulkAction):
|
||||
display_name = _("Delete")
|
||||
action_type = "delete"
|
||||
aria_label = _("Delete selected users")
|
||||
template_name = "wagtailusers/bulk_actions/confirm_bulk_delete.html"
|
||||
action_priority = 10
|
||||
classes = {"serious"}
|
||||
|
||||
def check_perm(self, obj):
|
||||
return user_can_delete_user(self.request.user, obj)
|
||||
|
||||
def get_execution_context(self):
|
||||
return {**super().get_execution_context(), "model": self.model}
|
||||
|
||||
@classmethod
|
||||
def execute_action(cls, objects, model=None, **kwargs):
|
||||
if model is None:
|
||||
model = cls.get_default_model()
|
||||
model.objects.filter(pk__in=[obj.pk for obj in objects]).delete()
|
||||
return len(objects), 0
|
||||
|
||||
def get_success_message(self, num_parent_objects, num_child_objects):
|
||||
return ngettext(
|
||||
"%(num_parent_objects)d user has been deleted",
|
||||
"%(num_parent_objects)d users have been deleted",
|
||||
num_parent_objects,
|
||||
) % {"num_parent_objects": num_parent_objects}
|
||||
72
env/lib/python3.10/site-packages/wagtail/users/views/bulk_actions/set_active_state.py
vendored
Normal file
72
env/lib/python3.10/site-packages/wagtail/users/views/bulk_actions/set_active_state.py
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
from django import forms
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.utils.translation import ngettext
|
||||
|
||||
from wagtail.users.views.bulk_actions.user_bulk_action import UserBulkAction
|
||||
from wagtail.users.views.users import change_user_perm
|
||||
|
||||
|
||||
class ActivityForm(forms.Form):
|
||||
mark_as_active = forms.TypedChoiceField(
|
||||
choices=((True, _("Active")), (False, _("Inactive"))),
|
||||
label=_("Mark as active"),
|
||||
widget=forms.RadioSelect,
|
||||
coerce=lambda x: x == "True",
|
||||
)
|
||||
|
||||
|
||||
class SetActiveStateBulkAction(UserBulkAction):
|
||||
display_name = _("Set active state")
|
||||
action_type = "set_active_state"
|
||||
aria_label = _("Change the active state for selected users")
|
||||
template_name = "wagtailusers/bulk_actions/confirm_bulk_set_active_state.html"
|
||||
action_priority = 20
|
||||
form_class = ActivityForm
|
||||
|
||||
def check_perm(self, obj):
|
||||
return self.request.user.has_perm(change_user_perm)
|
||||
|
||||
def get_execution_context(self):
|
||||
return {
|
||||
"mark_as_active": self.cleaned_form.cleaned_data["mark_as_active"],
|
||||
"user": self.request.user,
|
||||
"model": self.model,
|
||||
}
|
||||
|
||||
def get_actionable_objects(self):
|
||||
objects, objects_without_access = super().get_actionable_objects()
|
||||
user = self.request.user
|
||||
users = list(filter(lambda x: x.pk != user.pk, objects))
|
||||
if len(objects) != len(users):
|
||||
objects_without_access["mark_self_as_inactive"] = [user]
|
||||
return users, objects_without_access
|
||||
|
||||
@classmethod
|
||||
def execute_action(cls, objects, mark_as_active=False, model=None, **kwargs):
|
||||
if model is None:
|
||||
model = cls.get_default_model()
|
||||
user = kwargs.get("user", None)
|
||||
if user is not None:
|
||||
objects = list(filter(lambda x: x.pk != user.pk, objects))
|
||||
num_parent_objects = model.objects.filter(
|
||||
pk__in=[obj.pk for obj in objects]
|
||||
).update(is_active=mark_as_active)
|
||||
return num_parent_objects, 0
|
||||
|
||||
def get_success_message(self, num_parent_objects, num_child_objects):
|
||||
if self.cleaned_form.cleaned_data["mark_as_active"]:
|
||||
return ngettext(
|
||||
"%(num_parent_objects)d user has been marked as active",
|
||||
"%(num_parent_objects)d users have been marked as active",
|
||||
num_parent_objects,
|
||||
) % {
|
||||
"num_parent_objects": num_parent_objects,
|
||||
}
|
||||
else:
|
||||
return ngettext(
|
||||
"%(num_parent_objects)d user has been marked as inactive",
|
||||
"%(num_parent_objects)d users have been marked as inactive",
|
||||
num_parent_objects,
|
||||
) % {
|
||||
"num_parent_objects": num_parent_objects,
|
||||
}
|
||||
25
env/lib/python3.10/site-packages/wagtail/users/views/bulk_actions/user_bulk_action.py
vendored
Normal file
25
env/lib/python3.10/site-packages/wagtail/users/views/bulk_actions/user_bulk_action.py
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
from django.contrib.auth import get_user_model
|
||||
|
||||
from wagtail.admin.views.bulk_action import BulkAction
|
||||
from wagtail.admin.views.generic.permissions import PermissionCheckedMixin
|
||||
from wagtail.permission_policies import ModelPermissionPolicy
|
||||
from wagtail.users.views.users import get_users_filter_query
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
|
||||
class UserBulkAction(PermissionCheckedMixin, BulkAction):
|
||||
models = [User]
|
||||
permission_policy = ModelPermissionPolicy(User)
|
||||
any_permission_required = ["add", "change", "delete"]
|
||||
|
||||
def get_all_objects_in_listing_query(self, parent_id):
|
||||
listing_objects = self.model.objects.all().values_list("pk", flat=True)
|
||||
if "q" in self.request.GET:
|
||||
q = self.request.GET.get("q")
|
||||
model_fields = {f.name for f in self.model._meta.get_fields()}
|
||||
conditions = get_users_filter_query(q, model_fields)
|
||||
|
||||
listing_objects = listing_objects.filter(conditions)
|
||||
|
||||
return listing_objects
|
||||
196
env/lib/python3.10/site-packages/wagtail/users/views/groups.py
vendored
Normal file
196
env/lib/python3.10/site-packages/wagtail/users/views/groups.py
vendored
Normal file
@@ -0,0 +1,196 @@
|
||||
from warnings import warn
|
||||
|
||||
from django.contrib.auth.models import Group
|
||||
from django.shortcuts import get_object_or_404, redirect
|
||||
from django.urls import re_path, reverse
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.translation import gettext
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from wagtail import hooks
|
||||
from wagtail.admin.ui.tables import TitleColumn
|
||||
from wagtail.admin.utils import set_query_params
|
||||
from wagtail.admin.views import generic
|
||||
from wagtail.admin.viewsets.model import ModelViewSet
|
||||
from wagtail.admin.widgets.button import HeaderButton
|
||||
from wagtail.users.forms import GroupForm, GroupPagePermissionFormSet
|
||||
from wagtail.utils.deprecation import RemovedInWagtail70Warning
|
||||
|
||||
_permission_panel_classes = None
|
||||
|
||||
|
||||
def get_permission_panel_classes():
|
||||
global _permission_panel_classes
|
||||
if _permission_panel_classes is None:
|
||||
_permission_panel_classes = [GroupPagePermissionFormSet]
|
||||
for fn in hooks.get_hooks("register_group_permission_panel"):
|
||||
_permission_panel_classes.append(fn())
|
||||
|
||||
return _permission_panel_classes
|
||||
|
||||
|
||||
class PermissionPanelFormsMixin:
|
||||
def get_permission_panel_form_kwargs(self, cls):
|
||||
kwargs = {}
|
||||
|
||||
if self.request.method in ("POST", "PUT"):
|
||||
kwargs.update(
|
||||
{
|
||||
"data": self.request.POST,
|
||||
"files": self.request.FILES,
|
||||
}
|
||||
)
|
||||
|
||||
if hasattr(self, "object"):
|
||||
kwargs.update({"instance": self.object})
|
||||
|
||||
return kwargs
|
||||
|
||||
def get_permission_panel_forms(self):
|
||||
return [
|
||||
cls(**self.get_permission_panel_form_kwargs(cls))
|
||||
for cls in get_permission_panel_classes()
|
||||
]
|
||||
|
||||
def process_form(self):
|
||||
form = self.get_form()
|
||||
permission_panels = self.get_permission_panel_forms()
|
||||
if form.is_valid() and all(panel.is_valid() for panel in permission_panels):
|
||||
response = self.form_valid(form)
|
||||
|
||||
for panel in permission_panels:
|
||||
panel.save()
|
||||
|
||||
return response
|
||||
else:
|
||||
return self.form_invalid(form)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
if "permission_panels" not in kwargs:
|
||||
kwargs["permission_panels"] = self.get_permission_panel_forms()
|
||||
|
||||
context = super().get_context_data(**kwargs)
|
||||
|
||||
# Add js/css media from the formsets to the existing media
|
||||
for panel in context["permission_panels"]:
|
||||
context["media"] += panel.media
|
||||
|
||||
return context
|
||||
|
||||
|
||||
class IndexView(generic.IndexView):
|
||||
page_title = _("Groups")
|
||||
add_item_label = _("Add a group")
|
||||
search_box_placeholder = _("Search groups")
|
||||
search_fields = ["name"]
|
||||
context_object_name = "groups"
|
||||
paginate_by = 20
|
||||
|
||||
columns = [
|
||||
TitleColumn(
|
||||
"name",
|
||||
label=_("Name"),
|
||||
sort_key="name",
|
||||
url_name="wagtailusers_groups:edit",
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
class CreateView(PermissionPanelFormsMixin, generic.CreateView):
|
||||
page_title = _("Add group")
|
||||
success_message = _("Group '%(object)s' created.")
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
"""
|
||||
Handle POST requests: instantiate a form instance with the passed
|
||||
POST variables and then check if it's valid.
|
||||
"""
|
||||
# Create an object now so that the permission panel forms have something to link them against
|
||||
self.object = Group()
|
||||
return self.process_form()
|
||||
|
||||
|
||||
class EditView(PermissionPanelFormsMixin, generic.EditView):
|
||||
success_message = _("Group '%(object)s' updated.")
|
||||
error_message = _("The group could not be saved due to errors.")
|
||||
delete_item_label = _("Delete group")
|
||||
context_object_name = "group"
|
||||
|
||||
@cached_property
|
||||
def header_buttons(self):
|
||||
return [
|
||||
HeaderButton(
|
||||
gettext("View users in this group"),
|
||||
url=set_query_params(
|
||||
reverse("wagtailusers_users:index"),
|
||||
{"group": self.object.pk},
|
||||
),
|
||||
icon_name="user",
|
||||
)
|
||||
]
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
"""
|
||||
Handle POST requests: instantiate a form instance with the passed
|
||||
POST variables and then check if it's valid.
|
||||
"""
|
||||
self.object = self.get_object()
|
||||
return self.process_form()
|
||||
|
||||
|
||||
class DeleteView(generic.DeleteView):
|
||||
success_message = _("Group '%(object)s' deleted.")
|
||||
page_title = _("Delete group")
|
||||
confirmation_message = _("Are you sure you want to delete this group?")
|
||||
|
||||
|
||||
class GroupViewSet(ModelViewSet):
|
||||
icon = "group"
|
||||
model = Group
|
||||
ordering = ["name"]
|
||||
add_to_reference_index = False
|
||||
menu_name = "groups"
|
||||
menu_label = _("Groups")
|
||||
menu_order = 601
|
||||
add_to_settings_menu = True
|
||||
|
||||
index_view_class = IndexView
|
||||
add_view_class = CreateView
|
||||
edit_view_class = EditView
|
||||
delete_view_class = DeleteView
|
||||
|
||||
template_prefix = "wagtailusers/groups/"
|
||||
|
||||
@property
|
||||
def users_view(self):
|
||||
def view(request, pk):
|
||||
legacy_url = reverse(self.get_url_name("users"), args=(pk,))
|
||||
new_url = set_query_params(
|
||||
reverse("wagtailusers_users:index"),
|
||||
{"group": get_object_or_404(Group, pk=pk).pk},
|
||||
)
|
||||
|
||||
warn(
|
||||
f"Accessing the list of users in a group via {legacy_url} is "
|
||||
f"deprecated, use {new_url} instead.",
|
||||
RemovedInWagtail70Warning,
|
||||
)
|
||||
return redirect(new_url)
|
||||
|
||||
return view
|
||||
|
||||
def get_common_view_kwargs(self, **kwargs):
|
||||
return super().get_common_view_kwargs(
|
||||
**{
|
||||
"usage_url_name": None,
|
||||
**kwargs,
|
||||
}
|
||||
)
|
||||
|
||||
def get_form_class(self, for_update=False):
|
||||
return GroupForm
|
||||
|
||||
def get_urlpatterns(self):
|
||||
return super().get_urlpatterns() + [
|
||||
re_path(r"(\d+)/users/$", self.users_view, name="users"),
|
||||
]
|
||||
441
env/lib/python3.10/site-packages/wagtail/users/views/users.py
vendored
Normal file
441
env/lib/python3.10/site-packages/wagtail/users/views/users.py
vendored
Normal file
@@ -0,0 +1,441 @@
|
||||
from warnings import warn
|
||||
|
||||
import django_filters
|
||||
from django.conf import settings
|
||||
from django.contrib.auth import (
|
||||
get_user_model,
|
||||
update_session_auth_hash,
|
||||
)
|
||||
from django.contrib.auth.models import Group
|
||||
from django.core.exceptions import FieldDoesNotExist, PermissionDenied
|
||||
from django.db.models import Q
|
||||
from django.forms import CheckboxSelectMultiple
|
||||
from django.template import RequestContext
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.translation import gettext as _
|
||||
from django.utils.translation import gettext_lazy
|
||||
|
||||
from wagtail import hooks
|
||||
from wagtail.admin.filters import DateRangePickerWidget, WagtailFilterSet
|
||||
from wagtail.admin.search import SearchArea
|
||||
from wagtail.admin.ui.tables import (
|
||||
BulkActionsCheckboxColumn,
|
||||
Column,
|
||||
DateColumn,
|
||||
StatusTagColumn,
|
||||
TitleColumn,
|
||||
)
|
||||
from wagtail.admin.utils import get_user_display_name
|
||||
from wagtail.admin.views import generic
|
||||
from wagtail.admin.viewsets.model import ModelViewSet
|
||||
from wagtail.admin.widgets.boolean_radio_select import BooleanRadioSelect
|
||||
from wagtail.admin.widgets.button import (
|
||||
BaseDropdownMenuButton,
|
||||
ButtonWithDropdown,
|
||||
)
|
||||
from wagtail.compat import AUTH_USER_APP_LABEL, AUTH_USER_MODEL_NAME
|
||||
from wagtail.coreutils import accepts_kwarg
|
||||
from wagtail.users.forms import UserCreationForm, UserEditForm
|
||||
from wagtail.users.utils import user_can_delete_user
|
||||
from wagtail.utils.deprecation import RemovedInWagtail70Warning
|
||||
from wagtail.utils.loading import get_custom_form
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
# Typically we would check the permission 'auth.change_user' (and 'auth.add_user' /
|
||||
# 'auth.delete_user') for user management actions, but this may vary according to
|
||||
# the AUTH_USER_MODEL setting. These are no longer used in the codebase in favour
|
||||
# of ModelPermissionPolicy, but are kept here for backwards compatibility.
|
||||
add_user_perm = f"{AUTH_USER_APP_LABEL}.add_{AUTH_USER_MODEL_NAME.lower()}"
|
||||
change_user_perm = "{}.change_{}".format(
|
||||
AUTH_USER_APP_LABEL, AUTH_USER_MODEL_NAME.lower()
|
||||
)
|
||||
delete_user_perm = "{}.delete_{}".format(
|
||||
AUTH_USER_APP_LABEL, AUTH_USER_MODEL_NAME.lower()
|
||||
)
|
||||
|
||||
|
||||
def get_user_creation_form():
|
||||
form_setting = "WAGTAIL_USER_CREATION_FORM"
|
||||
if hasattr(settings, form_setting):
|
||||
warn(
|
||||
"The `WAGTAIL_USER_CREATION_FORM` setting is deprecated. Use a custom "
|
||||
"`UserViewSet` subclass and override `get_form_class()` instead.",
|
||||
RemovedInWagtail70Warning,
|
||||
)
|
||||
return get_custom_form(form_setting)
|
||||
else:
|
||||
return UserCreationForm
|
||||
|
||||
|
||||
def get_user_edit_form():
|
||||
form_setting = "WAGTAIL_USER_EDIT_FORM"
|
||||
if hasattr(settings, form_setting):
|
||||
warn(
|
||||
"The `WAGTAIL_USER_EDIT_FORM` setting is deprecated. Use a custom "
|
||||
"`UserViewSet` subclass and override `get_form_class()` instead.",
|
||||
RemovedInWagtail70Warning,
|
||||
)
|
||||
return get_custom_form(form_setting)
|
||||
else:
|
||||
return UserEditForm
|
||||
|
||||
|
||||
def get_users_filter_query(q, model_fields):
|
||||
conditions = Q()
|
||||
|
||||
for term in q.split():
|
||||
if "username" in model_fields:
|
||||
conditions |= Q(username__icontains=term)
|
||||
|
||||
if "first_name" in model_fields:
|
||||
conditions |= Q(first_name__icontains=term)
|
||||
|
||||
if "last_name" in model_fields:
|
||||
conditions |= Q(last_name__icontains=term)
|
||||
|
||||
if "email" in model_fields:
|
||||
conditions |= Q(email__icontains=term)
|
||||
|
||||
return conditions
|
||||
|
||||
|
||||
class UserColumn(TitleColumn):
|
||||
cell_template_name = "wagtailusers/users/user_cell.html"
|
||||
|
||||
|
||||
class UserFilterSet(WagtailFilterSet):
|
||||
is_superuser = django_filters.BooleanFilter(
|
||||
label=gettext_lazy("Administrator"),
|
||||
widget=BooleanRadioSelect,
|
||||
)
|
||||
last_login = django_filters.DateFromToRangeFilter(
|
||||
label=gettext_lazy("Last login"),
|
||||
widget=DateRangePickerWidget,
|
||||
)
|
||||
group = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name="groups",
|
||||
queryset=Group.objects.all(),
|
||||
label=gettext_lazy("Group"),
|
||||
widget=CheckboxSelectMultiple,
|
||||
)
|
||||
|
||||
def __init__(self, data=None, queryset=None, *, request=None, prefix=None):
|
||||
super().__init__(data, queryset, request=request, prefix=prefix)
|
||||
try:
|
||||
self._meta.model._meta.get_field("is_active")
|
||||
except FieldDoesNotExist:
|
||||
pass
|
||||
else:
|
||||
self.filters["is_active"] = django_filters.BooleanFilter(
|
||||
field_name="is_active",
|
||||
label=gettext_lazy("Active"),
|
||||
widget=BooleanRadioSelect,
|
||||
)
|
||||
self.filters.move_to_end("is_active", last=False)
|
||||
|
||||
class Meta:
|
||||
model = User
|
||||
fields = []
|
||||
|
||||
|
||||
class IndexView(generic.IndexView):
|
||||
"""
|
||||
Lists the users for management within the admin.
|
||||
"""
|
||||
|
||||
template_name = "wagtailusers/users/index.html"
|
||||
results_template_name = "wagtailusers/users/index_results.html"
|
||||
add_item_label = gettext_lazy("Add a user")
|
||||
context_object_name = "users"
|
||||
is_searchable = True
|
||||
page_title = gettext_lazy("Users")
|
||||
show_other_searches = True
|
||||
|
||||
@cached_property
|
||||
def columns(self):
|
||||
_UserColumn = self._get_title_column_class(UserColumn)
|
||||
return [
|
||||
BulkActionsCheckboxColumn("bulk_actions", obj_type="user"),
|
||||
_UserColumn(
|
||||
"name",
|
||||
accessor=lambda u: get_user_display_name(u),
|
||||
label=gettext_lazy("Name"),
|
||||
sort_key="name"
|
||||
if self.model_fields.issuperset({"first_name", "last_name"})
|
||||
else None,
|
||||
get_url=self.get_edit_url,
|
||||
classname="name",
|
||||
),
|
||||
Column(
|
||||
self.model.USERNAME_FIELD,
|
||||
accessor="get_username",
|
||||
label=gettext_lazy("Username"),
|
||||
sort_key=self.model.USERNAME_FIELD,
|
||||
classname="username",
|
||||
width="20%",
|
||||
),
|
||||
Column(
|
||||
"is_superuser",
|
||||
accessor=lambda u: gettext_lazy("Admin") if u.is_superuser else None,
|
||||
label=gettext_lazy("Access level"),
|
||||
sort_key="is_superuser",
|
||||
classname="level",
|
||||
width="10%",
|
||||
),
|
||||
StatusTagColumn(
|
||||
"is_active",
|
||||
accessor=lambda u: gettext_lazy("Active")
|
||||
if u.is_active
|
||||
else gettext_lazy("Inactive"),
|
||||
primary=lambda u: u.is_active,
|
||||
label=gettext_lazy("Status"),
|
||||
sort_key="is_active" if "is_active" in self.model_fields else None,
|
||||
classname="status",
|
||||
width="10%",
|
||||
),
|
||||
DateColumn(
|
||||
"last_login",
|
||||
label=gettext_lazy("Last login"),
|
||||
sort_key="last_login",
|
||||
classname="last-login",
|
||||
width="15%",
|
||||
),
|
||||
]
|
||||
|
||||
@cached_property
|
||||
def model_fields(self):
|
||||
return {f.name for f in User._meta.get_fields()}
|
||||
|
||||
def get_delete_url(self, instance):
|
||||
if user_can_delete_user(self.request.user, instance):
|
||||
return super().get_delete_url(instance)
|
||||
|
||||
def get_list_buttons(self, instance):
|
||||
more_buttons = self.get_list_more_buttons(instance)
|
||||
list_buttons = []
|
||||
|
||||
for hook in hooks.get_hooks("register_user_listing_buttons"):
|
||||
if accepts_kwarg(hook, "request_user"):
|
||||
hook_buttons = hook(user=instance, request_user=self.request.user)
|
||||
else:
|
||||
# old-style hook that accepts a context argument instead of request_user
|
||||
hook_buttons = hook(RequestContext(self.request), instance)
|
||||
warn(
|
||||
"`register_user_listing_buttons` hook functions should accept a `request_user` argument instead of `context` -"
|
||||
f" {hook.__module__}.{hook.__name__} needs to be updated",
|
||||
category=RemovedInWagtail70Warning,
|
||||
)
|
||||
|
||||
for button in hook_buttons:
|
||||
if isinstance(button, BaseDropdownMenuButton):
|
||||
# If the button is a dropdown menu, add it to the top-level
|
||||
# because we do not support nested dropdowns
|
||||
list_buttons.append(button)
|
||||
else:
|
||||
# Otherwise, add it to the default "More" dropdown
|
||||
more_buttons.append(button)
|
||||
|
||||
list_buttons.append(
|
||||
ButtonWithDropdown(
|
||||
buttons=sorted(more_buttons),
|
||||
icon_name="dots-horizontal",
|
||||
attrs={
|
||||
"aria-label": _("More options for '%(title)s'")
|
||||
% {"title": str(instance)},
|
||||
},
|
||||
)
|
||||
)
|
||||
|
||||
return sorted(list_buttons)
|
||||
|
||||
def get_base_queryset(self):
|
||||
users = User._default_manager.all()
|
||||
|
||||
if "wagtail_userprofile" in self.model_fields:
|
||||
users = users.select_related("wagtail_userprofile")
|
||||
|
||||
return users
|
||||
|
||||
def order_queryset(self, queryset):
|
||||
if self.ordering == "name":
|
||||
return queryset.order_by("last_name", "first_name")
|
||||
if self.ordering == "-name":
|
||||
return queryset.order_by("-last_name", "-first_name")
|
||||
return super().order_queryset(queryset)
|
||||
|
||||
def search_queryset(self, queryset):
|
||||
if self.is_searching:
|
||||
conditions = get_users_filter_query(self.search_query, self.model_fields)
|
||||
return queryset.filter(conditions)
|
||||
return queryset
|
||||
|
||||
|
||||
class CreateView(generic.CreateView):
|
||||
"""
|
||||
Provide the ability to create a user within the admin.
|
||||
"""
|
||||
|
||||
success_message = gettext_lazy("User '%(object)s' created.")
|
||||
page_title = gettext_lazy("Add user")
|
||||
|
||||
def run_before_hook(self):
|
||||
return self.run_hook(
|
||||
"before_create_user",
|
||||
self.request,
|
||||
)
|
||||
|
||||
def run_after_hook(self):
|
||||
return self.run_hook(
|
||||
"after_create_user",
|
||||
self.request,
|
||||
self.object,
|
||||
)
|
||||
|
||||
|
||||
class EditView(generic.EditView):
|
||||
"""
|
||||
Provide the ability to edit a user within the admin.
|
||||
"""
|
||||
|
||||
success_message = gettext_lazy("User '%(object)s' updated.")
|
||||
error_message = gettext_lazy("The user could not be saved due to errors.")
|
||||
context_object_name = "user"
|
||||
|
||||
def setup(self, request, *args, **kwargs):
|
||||
super().setup(request, *args, **kwargs)
|
||||
self.object = self.get_object()
|
||||
self.can_delete = user_can_delete_user(request.user, self.object)
|
||||
self.editing_self = request.user == self.object
|
||||
|
||||
def save_instance(self):
|
||||
instance = super().save_instance()
|
||||
if self.object == self.request.user and "password1" in self.form.changed_data:
|
||||
# User is changing their own password; need to update their session hash
|
||||
update_session_auth_hash(self.request, self.object)
|
||||
return instance
|
||||
|
||||
def get_form_kwargs(self):
|
||||
kwargs = super().get_form_kwargs()
|
||||
kwargs.update(
|
||||
{
|
||||
"editing_self": self.editing_self,
|
||||
}
|
||||
)
|
||||
return kwargs
|
||||
|
||||
def run_before_hook(self):
|
||||
return self.run_hook(
|
||||
"before_edit_user",
|
||||
self.request,
|
||||
self.object,
|
||||
)
|
||||
|
||||
def run_after_hook(self):
|
||||
return self.run_hook(
|
||||
"after_edit_user",
|
||||
self.request,
|
||||
self.object,
|
||||
)
|
||||
|
||||
def get_page_subtitle(self):
|
||||
return get_user_display_name(self.object)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context["can_delete"] = self.can_delete
|
||||
return context
|
||||
|
||||
|
||||
class DeleteView(generic.DeleteView):
|
||||
"""
|
||||
Provide the ability to delete a user within the admin.
|
||||
"""
|
||||
|
||||
page_title = gettext_lazy("Delete user")
|
||||
success_message = gettext_lazy("User '%(object)s' deleted.")
|
||||
context_object_name = "user"
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
self.object = self.get_object()
|
||||
if not user_can_delete_user(self.request.user, self.object):
|
||||
raise PermissionDenied
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
def run_before_hook(self):
|
||||
return self.run_hook(
|
||||
"before_delete_user",
|
||||
self.request,
|
||||
self.object,
|
||||
)
|
||||
|
||||
def run_after_hook(self):
|
||||
return self.run_hook(
|
||||
"after_delete_user",
|
||||
self.request,
|
||||
self.object,
|
||||
)
|
||||
|
||||
|
||||
class HistoryView(generic.HistoryView):
|
||||
def get_page_subtitle(self):
|
||||
return get_user_display_name(self.object)
|
||||
|
||||
|
||||
class UserViewSet(ModelViewSet):
|
||||
icon = "user"
|
||||
model = User
|
||||
ordering = "name"
|
||||
add_to_reference_index = False
|
||||
filterset_class = UserFilterSet
|
||||
menu_name = "users"
|
||||
menu_label = gettext_lazy("Users")
|
||||
menu_order = 600
|
||||
add_to_settings_menu = True
|
||||
|
||||
index_view_class = IndexView
|
||||
add_view_class = CreateView
|
||||
edit_view_class = EditView
|
||||
delete_view_class = DeleteView
|
||||
history_view_class = HistoryView
|
||||
|
||||
template_prefix = "wagtailusers/users/"
|
||||
|
||||
def get_common_view_kwargs(self, **kwargs):
|
||||
return super().get_common_view_kwargs(
|
||||
**{
|
||||
"usage_url_name": None,
|
||||
**kwargs,
|
||||
}
|
||||
)
|
||||
|
||||
def get_form_class(self, for_update=False):
|
||||
if for_update:
|
||||
return get_user_edit_form()
|
||||
return get_user_creation_form()
|
||||
|
||||
@cached_property
|
||||
def search_area_class(self):
|
||||
class UsersSearchArea(SearchArea):
|
||||
def is_shown(search_area, request):
|
||||
return self.permission_policy.user_has_any_permission(
|
||||
request.user, {"add", "change", "delete"}
|
||||
)
|
||||
|
||||
return UsersSearchArea
|
||||
|
||||
def get_search_area(self):
|
||||
return self.search_area_class(
|
||||
gettext_lazy("Users"),
|
||||
self.get_url_name("index"),
|
||||
name="users",
|
||||
icon_name="user",
|
||||
order=600,
|
||||
)
|
||||
|
||||
def register_search_area(self):
|
||||
hooks.register("register_admin_search_area", self.get_search_area)
|
||||
|
||||
def on_register(self):
|
||||
super().on_register()
|
||||
self.register_search_area()
|
||||
Reference in New Issue
Block a user