コード例 #1
0
def move_confirm(request, page_to_move_id, destination_id):
    page_to_move = get_object_or_404(Page, id=page_to_move_id).specific
    # Needs .specific_deferred because the .get_admin_display_title method is called in template
    destination = get_object_or_404(Page, id=destination_id).specific_deferred

    if not Page._slug_is_available(
            page_to_move.slug, destination, page=page_to_move):
        messages.error(
            request,
            _("The slug '{0}' is already in use at the selected parent page. Make sure the slug is unique and try again"
              ).format(page_to_move.slug),
        )
        return redirect(
            "wagtailadmin_pages:move_choose_destination",
            page_to_move.id,
            destination.id,
        )

    for fn in hooks.get_hooks("before_move_page"):
        result = fn(request, page_to_move, destination)
        if hasattr(result, "status_code"):
            return result

    if request.method == "POST":
        # any invalid moves *should* be caught by the permission check in the action class,
        # so don't bother to catch InvalidMoveToDescendant
        action = MovePageAction(page_to_move,
                                destination,
                                pos="last-child",
                                user=request.user)
        action.execute()

        messages.success(
            request,
            _("Page '{0}' moved.").format(
                page_to_move.get_admin_display_title()),
            buttons=[
                messages.button(
                    reverse("wagtailadmin_pages:edit",
                            args=(page_to_move.id, )),
                    _("Edit"),
                )
            ],
        )

        for fn in hooks.get_hooks("after_move_page"):
            result = fn(request, page_to_move)
            if hasattr(result, "status_code"):
                return result

        return redirect("wagtailadmin_explore", destination.id)

    return TemplateResponse(
        request,
        "wagtailadmin/pages/confirm_move.html",
        {
            "page_to_move": page_to_move,
            "destination": destination,
        },
    )
コード例 #2
0
def delete(request, user_id):
    user = get_object_or_404(User, pk=user_id)

    if not user_can_delete_user(request.user, user):
        raise PermissionDenied

    for fn in hooks.get_hooks("before_delete_user"):
        result = fn(request, user)
        if hasattr(result, "status_code"):
            return result
    if request.method == "POST":
        with transaction.atomic():
            log(user, "wagtail.delete")
            user.delete()
        messages.success(request, _("User '{0}' deleted.").format(user))
        for fn in hooks.get_hooks("after_delete_user"):
            result = fn(request, user)
            if hasattr(result, "status_code"):
                return result
        return redirect("wagtailusers_users:index")

    return TemplateResponse(
        request,
        "wagtailusers/users/confirm_delete.html",
        {
            "user": user,
        },
    )
コード例 #3
0
def edit(request, user_id):
    user = get_object_or_404(User, pk=user_id)
    can_delete = user_can_delete_user(request.user, user)
    editing_self = request.user == user

    for fn in hooks.get_hooks("before_edit_user"):
        result = fn(request, user)
        if hasattr(result, "status_code"):
            return result
    if request.method == "POST":
        form = get_user_edit_form()(request.POST,
                                    request.FILES,
                                    instance=user,
                                    editing_self=editing_self)
        if form.is_valid():
            with transaction.atomic():
                user = form.save()
                log(user, "wagtail.edit")

            if user == request.user and "password1" in form.changed_data:
                # User is changing their own password; need to update their session hash
                update_session_auth_hash(request, user)

            messages.success(
                request,
                _("User '{0}' updated.").format(user),
                buttons=[
                    messages.button(
                        reverse("wagtailusers_users:edit", args=(user.pk, )),
                        _("Edit"))
                ],
            )
            for fn in hooks.get_hooks("after_edit_user"):
                result = fn(request, user)
                if hasattr(result, "status_code"):
                    return result
            return redirect("wagtailusers_users:index")
        else:
            messages.error(request,
                           _("The user could not be saved due to errors."))
    else:
        form = get_user_edit_form()(instance=user, editing_self=editing_self)

    return TemplateResponse(
        request,
        "wagtailusers/users/edit.html",
        {
            "user": user,
            "form": form,
            "can_delete": can_delete,
        },
    )
コード例 #4
0
def unpublish(request, page_id):
    page = get_object_or_404(Page, id=page_id).specific

    user_perms = UserPagePermissionsProxy(request.user)
    if not user_perms.for_page(page).can_unpublish():
        raise PermissionDenied

    next_url = get_valid_next_url_from_request(request)

    if request.method == "POST":
        include_descendants = request.POST.get("include_descendants", False)

        for fn in hooks.get_hooks("before_unpublish_page"):
            result = fn(request, page)
            if hasattr(result, "status_code"):
                return result

        action = UnpublishPageAction(page,
                                     user=request.user,
                                     include_descendants=include_descendants)
        action.execute(skip_permission_checks=True)

        for fn in hooks.get_hooks("after_unpublish_page"):
            result = fn(request, page)
            if hasattr(result, "status_code"):
                return result

        messages.success(
            request,
            _("Page '{0}' unpublished.").format(
                page.get_admin_display_title()),
            buttons=[
                messages.button(
                    reverse("wagtailadmin_pages:edit", args=(page.id, )),
                    _("Edit"))
            ],
        )

        if next_url:
            return redirect(next_url)
        return redirect("wagtailadmin_explore", page.get_parent().id)

    return TemplateResponse(
        request,
        "wagtailadmin/pages/confirm_unpublish.html",
        {
            "page": page,
            "next": next_url,
            "live_descendant_count": page.get_descendants().live().count(),
        },
    )
コード例 #5
0
ファイル: wagtailadmin_tags.py プロジェクト: tomkins/wagtail
def page_listing_buttons(context, page, page_perms, is_parent=False):
    next_url = context.request.path
    button_hooks = hooks.get_hooks("register_page_listing_buttons")

    buttons = []
    for hook in button_hooks:
        buttons.extend(hook(page, page_perms, is_parent, next_url))

    buttons.sort()

    for hook in hooks.get_hooks("construct_page_listing_buttons"):
        hook(buttons, page, page_perms, is_parent, context)

    return {"page": page, "buttons": buttons}
コード例 #6
0
def snippet_listing_buttons(context, snippet):
    next_url = context["request"].path
    button_hooks = hooks.get_hooks("register_snippet_listing_buttons")

    buttons = []
    for hook in button_hooks:
        buttons.extend(hook(snippet, context["request"].user, next_url))

    buttons.sort()

    for hook in hooks.get_hooks("construct_snippet_listing_buttons"):
        hook(buttons, snippet, context["request"].user, context)

    return {"snippet": snippet, "buttons": buttons}
コード例 #7
0
def _get_base_page_action_menu_items():
    """
    Retrieve the global list of menu items for the page action menu,
    which may then be customised on a per-request basis
    """
    global BASE_PAGE_ACTION_MENU_ITEMS

    if BASE_PAGE_ACTION_MENU_ITEMS is None:
        BASE_PAGE_ACTION_MENU_ITEMS = [
            SaveDraftMenuItem(order=0),
            DeleteMenuItem(order=10),
            LockMenuItem(order=15),
            UnlockMenuItem(order=15),
            UnpublishMenuItem(order=20),
            PublishMenuItem(order=30),
            CancelWorkflowMenuItem(order=40),
            RestartWorkflowMenuItem(order=50),
            SubmitForModerationMenuItem(order=60),
            PageLockedMenuItem(order=10000),
        ]
        for hook in hooks.get_hooks("register_page_action_menu_item"):
            action_menu_item = hook()
            if action_menu_item:
                BASE_PAGE_ACTION_MENU_ITEMS.append(action_menu_item)

    return BASE_PAGE_ACTION_MENU_ITEMS
コード例 #8
0
ファイル: userbar.py プロジェクト: tnir/wagtail
def for_moderation(request, revision_id):
    items = [
        EditPageItem(
            Revision.page_revisions.get(id=revision_id).content_object),
        AddPageItem(
            Revision.page_revisions.get(id=revision_id).content_object),
        ApproveModerationEditPageItem(
            Revision.page_revisions.get(id=revision_id)),
        RejectModerationEditPageItem(
            Revision.page_revisions.get(id=revision_id)),
    ]

    for fn in hooks.get_hooks("construct_wagtail_userbar"):
        fn(request, items)

    # Render the items
    rendered_items = [item.render(request) for item in items]

    # Remove any unrendered items
    rendered_items = [item for item in rendered_items if item]

    # Render the edit bird
    return TemplateResponse(
        request,
        "wagtailadmin/userbar/base.html",
        {
            "items": rendered_items,
        },
    )
コード例 #9
0
ファイル: wagtailadmin_tags.py プロジェクト: minusf/wagtail
def page_header_buttons(context, page, page_perms):
    next_url = context.request.path
    button_hooks = hooks.get_hooks("register_page_header_buttons")

    buttons = []
    for hook in button_hooks:
        buttons.extend(hook(page, page_perms, next_url))

    buttons.sort()
    return {
        "page": page,
        "buttons": buttons,
        "title": _("Actions"),
        "icon_name": "ellipsis-v",
        "classes": [
            "w-flex",
            "w-justify-center",
            "w-items-center",
            "w-h-full",
            "w-ml-1",
        ],
        "button_classes": [
            "w-p-0",
            "w-w-12",
            "w-h-12",
            "w-text-primary",
            "w-bg-transparent",
            "hover:w-scale-110",
            "w-transition",
            "w-outline-offset-inside",
            "w-relative",
            "w-z-30",
        ],
        "hide_title": True,
    }
コード例 #10
0
    def test_after_hook(self):
        def after_hook():
            pass

        with self.register_hook("test_hook_name", after_hook, order=1):
            hook_fns = hooks.get_hooks("test_hook_name")
            self.assertEqual(hook_fns, [test_hook, after_hook])
コード例 #11
0
    def get(self, request):
        self.image_model = get_image_model()

        images = permission_policy.instances_user_has_any_permission_for(
            request.user, ["choose"]).order_by("-created_at")

        # allow hooks to modify the queryset
        for hook in hooks.get_hooks("construct_image_chooser_queryset"):
            images = hook(images, request)

        collection_id = request.GET.get("collection_id")
        if collection_id:
            images = images.filter(collection=collection_id)

        self.is_searching = False
        self.q = None

        if "q" in request.GET:
            self.search_form = SearchForm(request.GET)
            if self.search_form.is_valid():
                self.q = self.search_form.cleaned_data["q"]
                self.is_searching = True
                images = images.search(self.q)
        else:
            self.search_form = SearchForm()

        if not self.is_searching:
            tag_name = request.GET.get("tag")
            if tag_name:
                images = images.filter(tags__name=tag_name)

        # Pagination
        paginator = Paginator(images, per_page=CHOOSER_PAGE_SIZE)
        self.images = paginator.get_page(request.GET.get("p"))
        return self.render_to_response()
コード例 #12
0
    def test_before_hook(self):
        def before_hook():
            pass

        with self.register_hook("test_hook_name", before_hook, order=-1):
            hook_fns = hooks.get_hooks("test_hook_name")
            self.assertEqual(hook_fns, [before_hook, test_hook])
コード例 #13
0
ファイル: action_menu.py プロジェクト: tnir/wagtail
    def __init__(self, request, **kwargs):
        self.request = request
        self.context = kwargs
        self.context["request"] = request

        if "instance" in self.context:
            self.context["model"] = self.context["instance"].__class__

        self.context["draftstate_enabled"] = issubclass(
            self.context["model"], DraftStateMixin)

        self.menu_items = [
            menu_item for menu_item in get_base_snippet_action_menu_items(
                self.context["model"]) if menu_item.is_shown(self.context)
        ]

        self.menu_items.sort(key=lambda item: item.order)

        for hook in hooks.get_hooks("construct_snippet_action_menu"):
            hook(self.menu_items, self.request, self.context)

        try:
            self.default_item = self.menu_items.pop(0)
        except IndexError:
            self.default_item = None
コード例 #14
0
ファイル: home.py プロジェクト: tomkins/wagtail
def home(request):

    panels = [
        SiteSummaryPanel(request),
        UpgradeNotificationPanel(),
        WorkflowPagesToModeratePanel(),
        PagesForModerationPanel(),
        UserPagesInWorkflowModerationPanel(),
        RecentEditsPanel(),
        LockedPagesPanel(),
    ]

    for fn in hooks.get_hooks("construct_homepage_panels"):
        fn(request, panels)

    media = Media()

    for panel in panels:
        media += panel.media

    site_details = get_site_for_user(request.user)

    return TemplateResponse(
        request,
        "wagtailadmin/home.html",
        {
            "root_page": site_details["root_page"],
            "root_site": site_details["root_site"],
            "site_name": site_details["site_name"],
            "panels": sorted(panels, key=lambda p: p.order),
            "user": request.user,
            "media": media,
        },
    )
コード例 #15
0
ファイル: site_summary.py プロジェクト: tnir/wagtail
 def __init__(self, request):
     self.request = request
     summary_items = []
     for fn in hooks.get_hooks("construct_homepage_summary_items"):
         fn(request, summary_items)
     self.summary_items = [s for s in summary_items if s.is_shown()]
     self.summary_items.sort(key=lambda p: p.order)
コード例 #16
0
 def __init__(self, *args, **kwargs):
     super().__init__(*args, **kwargs)
     self.registered_permissions = Permission.objects.none()
     for fn in hooks.get_hooks("register_permissions"):
         self.registered_permissions = self.registered_permissions | fn()
     self.fields[
         "permissions"].queryset = self.registered_permissions.select_related(
             "content_type")
コード例 #17
0
ファイル: test_wagtail_hooks.py プロジェクト: tnir/wagtail
 def test_page_tree_sync_off(self):
     with hooks.register_temporarily(
             "construct_translated_pages_to_cascade_actions",
             self.unpublish_hook):
         for fn in hooks.get_hooks(
                 "construct_translated_pages_to_cascade_actions"):
             response = fn([self.en_homepage], "unpublish")
             self.assertIsNone(response)
コード例 #18
0
ファイル: chooser.py プロジェクト: thibaudcolas/wagtail
    def get_object_list(self):
        documents = self.permission_policy.instances_user_has_any_permission_for(
            self.request.user, ["choose"])
        # allow hooks to modify the queryset
        for hook in hooks.get_hooks("construct_document_chooser_queryset"):
            documents = hook(documents, self.request)

        return documents
コード例 #19
0
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
コード例 #20
0
    def _scan_for_serializers(self):
        serializers = dict(self.BASE_SERIALIZERS_BY_MODEL_CLASS)

        for fn in hooks.get_hooks('register_custom_serializers'):
            serializers.update(fn())

        self.serializers_by_model_class = serializers
        self._scanned_for_serializers = True
コード例 #21
0
 def populate(self):
     for fn in hooks.get_hooks("register_admin_viewset"):
         viewset = fn()
         if isinstance(viewset, (list, tuple)):
             for vs in viewset:
                 self.register(vs)
         else:
             self.register(viewset)
コード例 #22
0
    def _scan_for_adapters(self):
        adapters = dict(self.BASE_ADAPTERS_BY_FIELD_CLASS)

        for fn in hooks.get_hooks('register_field_adapters'):
            adapters.update(fn())

        self.adapters_by_field_class = adapters
        self._scanned_for_adapters = True
コード例 #23
0
ファイル: test_wagtail_hooks.py プロジェクト: tnir/wagtail
 def test_missing_hook_action(self):
     with hooks.register_temporarily(
             "construct_translated_pages_to_cascade_actions",
             self.missing_hook_action):
         for fn in hooks.get_hooks(
                 "construct_translated_pages_to_cascade_actions"):
             response = fn([self.en_homepage], "")
             if response is not None:
                 self.assertIsInstance(response, dict)
コード例 #24
0
ファイル: test_admin.py プロジェクト: tomkins/wagtail
 def test_registered_permission(self):
     permission = Permission.objects.get_by_natural_key(
         app_label="tests", model="testsetting", codename="change_testsetting"
     )
     for fn in hooks.get_hooks("register_permissions"):
         if permission in fn():
             break
     else:
         self.fail("Change permission for tests.TestSetting not registered")
コード例 #25
0
 def run_hook(self, hook_name, *args, **kwargs):
     """
     Run the named hook, passing args and kwargs to each function registered under that hook name.
     If any return an HttpResponse, stop processing and return that response
     """
     for fn in hooks.get_hooks(hook_name):
         result = fn(*args, **kwargs)
         if hasattr(result, "status_code"):
             return result
コード例 #26
0
ファイル: button.py プロジェクト: tnir/wagtail
    def dropdown_buttons(self):
        button_hooks = hooks.get_hooks(self.hook_name)

        buttons = []
        for hook in button_hooks:
            buttons.extend(hook(self.page, self.page_perms, self.next_url))

        buttons.sort()
        return buttons
コード例 #27
0
    def filter_object_list(self, objects):
        if self.construct_queryset_hook_name:
            # allow hooks to modify the queryset
            for hook in hooks.get_hooks(self.construct_queryset_hook_name):
                objects = hook(objects, self.request)

        if self.filter_form.is_valid():
            objects = self.filter_form.filter(objects)
        return objects
コード例 #28
0
ファイル: action_menu.py プロジェクト: tnir/wagtail
    def __init__(self, request, **kwargs):
        self.request = request
        self.context = kwargs
        self.context["request"] = request
        page = self.context.get("page")
        user_page_permissions = UserPagePermissionsProxy(self.request.user)
        self.context["user_page_permissions"] = user_page_permissions
        if page:
            self.context[
                "user_page_permissions_tester"] = user_page_permissions.for_page(
                    page)

        self.menu_items = []

        if page:
            task = page.current_workflow_task
            current_workflow_state = page.current_workflow_state
            is_final_task = (current_workflow_state
                             and current_workflow_state.is_at_final_task)
            if task:
                actions = task.get_actions(page, request.user)
                workflow_menu_items = []
                for name, label, launch_modal in actions:
                    icon_name = "edit"
                    if name == "approve":
                        if is_final_task and not getattr(
                                settings,
                                "WAGTAIL_WORKFLOW_REQUIRE_REAPPROVAL_ON_EDIT",
                                False,
                        ):
                            label = _("%(label)s and Publish") % {
                                "label": label
                            }
                        icon_name = "success"

                    item = WorkflowMenuItem(name,
                                            label,
                                            launch_modal,
                                            icon_name=icon_name)

                    if item.is_shown(self.context):
                        workflow_menu_items.append(item)
                self.menu_items.extend(workflow_menu_items)

        for menu_item in _get_base_page_action_menu_items():
            if menu_item.is_shown(self.context):
                self.menu_items.append(menu_item)

        self.menu_items.sort(key=lambda item: item.order)

        for hook in hooks.get_hooks("construct_page_action_menu"):
            hook(self.menu_items, self.request, self.context)

        try:
            self.default_item = self.menu_items.pop(0)
        except IndexError:
            self.default_item = None
コード例 #29
0
ファイル: wagtailadmin_tags.py プロジェクト: tomkins/wagtail
def hook_output(hook_name):
    """
    Example: {% hook_output 'insert_editor_css' %}
    Whenever we have a hook whose functions take no parameters and return a string, this tag can be used
    to output the concatenation of all of those return values onto the page.
    Note that the output is not escaped - it is the hook function's responsibility to escape unsafe content.
    """
    snippets = [fn() for fn in hooks.get_hooks(hook_name)]
    return mark_safe("".join(snippets))
コード例 #30
0
    def filter_queryset(self, request, queryset, view):
        if not hasattr(queryset, '_filtered_by_child_of'):
            raise BadRequestError(
                "filtering without child_of is not supported")

        parent_page = queryset._filtered_by_child_of
        for hook in hooks.get_hooks('construct_explorer_page_queryset'):
            queryset = hook(parent_page, queryset, request)

        return queryset