def test_unlock_link_only_present_for_draft_versions(self): draft_version = factories.PollVersionFactory( created_by=self.user_author) published_version = Version.objects.create( content=factories.PollContentFactory( poll=draft_version.content.poll), created_by=factories.UserFactory(), state=constants.PUBLISHED) draft_unlock_url = self.get_admin_url( self.versionable.version_model_proxy, 'unlock', draft_version.pk) draft_unlock_control = render_to_string( 'djangocms_version_locking/admin/unlock_icon.html', {'unlock_url': draft_unlock_url}) published_unlock_url = self.get_admin_url( self.versionable.version_model_proxy, 'unlock', published_version.pk) published_unlock_control = render_to_string( 'djangocms_version_locking/admin/unlock_icon.html', {'unlock_url': published_unlock_url}) changelist_url = version_list_url(draft_version.content) with self.login_user_context(self.superuser): response = self.client.post(changelist_url) # The draft version unlock control exists self.assertContains(response, draft_unlock_control, html=True) # The published version exists self.assertNotContains(response, published_unlock_control, html=True)
def add_view(self, request, menu_content_id=None, form_url="", extra_context=None): extra_context = extra_context or {} if menu_content_id: request.menu_content_id = menu_content_id if self._versioning_enabled: menu_content = get_object_or_404(MenuContent._base_manager, id=menu_content_id) version = Version.objects.get_for_content(menu_content) try: version.check_modify(request.user) except ConditionFailed as error: messages.error(request, str(error)) return HttpResponseRedirect(version_list_url(menu_content)) # purge menu cache purge_menu_cache(site_id=menu_content.menu.site_id) extra_context["list_url"] = reverse( "admin:djangocms_navigation_menuitem_list", kwargs={"menu_content_id": menu_content_id}, ) return super().add_view(request, form_url=form_url, extra_context=extra_context)
def preview_view(self, request, menu_content_id=None, form_url="", extra_context=None): extra_context = extra_context or {} if menu_content_id: request.menu_content_id = menu_content_id if self._versioning_enabled: menu_content = get_object_or_404( self.menu_content_model._base_manager, id=menu_content_id) version = Version.objects.get_for_content(menu_content) try: version.check_view(request.user) except ConditionFailed as error: messages.error(request, str(error)) return HttpResponseRedirect(version_list_url(menu_content)) # purge menu cache purge_menu_cache(site_id=menu_content.menu.site_id) extra_context["list_url"] = reverse( "admin:{}_menuitem_list".format(self.model._meta.app_label), kwargs={"menu_content_id": menu_content_id}, ) if request.GET.get("content_type_id"): return True else: return False
def delete_view(self, request, object_id, menu_content_id=None, form_url="", extra_context=None): extra_context = extra_context or {} if menu_content_id: request.menu_content_id = menu_content_id list_url = reverse_admin_name( self.model, 'list', kwargs={"menu_content_id": menu_content_id}, ) extra_context["list_url"] = list_url if self._versioning_enabled: menu_content = get_object_or_404( self.menu_content_model._base_manager, id=menu_content_id) delete_perm = self.has_delete_permission(request, menu_content) if not delete_perm: messages.error(request, LOCK_MESSAGE) return HttpResponseRedirect(version_list_url(menu_content)) menu_item = get_object_or_404(self.model, id=object_id) if menu_item.is_root(): messages.error( request, _("This item is the root of a menu, therefore it cannot be deleted." )) return HttpResponseRedirect(list_url) version = Version.objects.get_for_content(menu_content) try: version.check_modify(request.user) except ConditionFailed as error: messages.error(request, str(error)) return HttpResponseRedirect(version_list_url(menu_content)) extra_context["menu_name"] = menu_item extra_context[ "deleted_objects"] = self._get_to_be_deleted_objects( menu_item, request) return super().delete_view(request, object_id, extra_context)
def test_version_menu_and_url_for_version_content(self): # Versioned item should have versioning menu and url should be version list url version = PollVersionFactory() toolbar = get_toolbar(version.content, preview_mode=True) toolbar.post_template_populate() version_menu = toolbar.toolbar.get_menu('version') self.assertIsNotNone(version_menu) self.assertEqual(version_menu.get_items()[0].url, version_list_url(version.content))
def change_view(self, request, object_id, menu_content_id=None, form_url="", extra_context=None): extra_context = extra_context or {} if menu_content_id: request.menu_content_id = menu_content_id if self._versioning_enabled: menu_content = get_object_or_404( self.menu_content_model._base_manager, id=menu_content_id) change_perm = self.has_change_permission(request, menu_content) if not change_perm: messages.error(request, LOCK_MESSAGE) return HttpResponseRedirect(version_list_url(menu_content)) version = Version.objects.get_for_content(menu_content) try: version.check_modify(request.user) except ConditionFailed as error: messages.error(request, str(error)) return HttpResponseRedirect(version_list_url(menu_content)) # purge menu cache purge_menu_cache(site_id=menu_content.menu.site_id) extra_context["list_url"] = reverse_admin_name( self.model, 'list', kwargs={"menu_content_id": menu_content_id}, ) extra_context["delete_url"] = reverse( "admin:{}_menuitem_delete".format(self.model._meta.app_label), kwargs={ "menu_content_id": menu_content_id, "object_id": object_id }, ) return super().change_view(request, object_id, form_url="", extra_context=extra_context)
def test_menuitem_changelist_contains_version_list_url(self): menu_content = factories.MenuContentWithVersionFactory() factories.ChildMenuItemFactory.create_batch(5, parent=menu_content.root) list_url = reverse( "admin:djangocms_navigation_menuitem_list", args=(menu_content.id,) ) response = self.client.get(list_url) self.assertContains(response, version_list_url(menu_content))
def _get_manage_versions_link(self, obj, request, disabled=False): url = version_list_url(obj) return render_to_string( "djangocms_pageadmin/admin/icons/manage_versions.html", { "url": url, "disabled": disabled, "action": False }, )
def test_manage_versions_link(self): pagecontent = PageContentWithVersionFactory() func = self.modeladmin._list_actions(self.get_request("/")) response = func(pagecontent) soup = parse_html(response) element = soup.find("a", {"class": "cms-page-admin-action-manage-versions"}) self.assertIsNotNone( element, "Missing a.cms-page-admin-action-manage-versions element") self.assertEqual(element["title"], "Manage versions") self.assertEqual(element["href"], version_list_url(pagecontent))
def test_version_locking_css_media_loaded(self): """ The verison locking css media is loaded on the page """ poll_version = factories.PollVersionFactory(created_by=self.superuser) changelist_url = version_list_url(poll_version.content) css_file = "djangocms_version_locking/css/version-locking.css" with self.login_user_context(self.superuser): response = self.client.post(changelist_url) self.assertContains(response, css_file)
def test_unlock_link_present_for_user_with_privileges(self): poll_version = factories.PollVersionFactory( state=constants.DRAFT, created_by=self.user_author) changelist_url = version_list_url(poll_version.content) unlock_url = self.get_admin_url(self.versionable.version_model_proxy, 'unlock', poll_version.pk) unlock_control = render_to_string( 'djangocms_version_locking/admin/unlock_icon.html', {'unlock_url': unlock_url}) with self.login_user_context(self.user_has_unlock_perms): response = self.client.post(changelist_url) self.assertContains(response, unlock_control, html=True)
def test_version_list_url(self): pv = factories.PollVersionFactory(content__language="en") url = version_list_url(pv.content) parsed = urlparse(url) self.assertEqual(parsed.path, "/en/admin/djangocms_versioning/pollcontentversion/") self.assertEqual( {k: v[0] for k, v in parse_qs(parsed.query).items()}, { "poll": "1", "language": "en" }, )
def test_unlock_link_not_present_for_author(self): # FIXME: May be redundant now as this requirement was probably removed at a later date due # to the fact that an author may be asked to unlock their version for someone else to use! author = self.get_superuser() poll_version = factories.PollVersionFactory(state=constants.DRAFT, created_by=author) changelist_url = version_list_url(poll_version.content) unlock_url = self.get_admin_url(self.versionable.version_model_proxy, 'unlock', poll_version.pk) unlock_control = render_to_string( 'djangocms_version_locking/admin/unlock_icon.html', {'unlock_url': unlock_url}) with self.login_user_context(author): response = self.client.get(changelist_url) self.assertNotContains(response, unlock_control, html=True)
def _add_versioning_menu(self): """ Helper method to add version menu in the toolbar """ # Check if object is registred with versioning otherwise dont add if not self._is_versioned(): return version = Version.objects.get_for_content(self.toolbar.obj) if version is None: return version_menu_label = _("Version #{number} ({state})").format( number=version.number, state=version.state) versioning_menu = self.toolbar.get_or_create_menu( VERSIONING_MENU_IDENTIFIER, version_menu_label, disabled=False) version = version.convert_to_proxy() if self.request.user.has_perm("{app_label}.{codename}".format( app_label=version._meta.app_label, codename=get_permission_codename("change", version._meta), )): url = version_list_url(version.content) versioning_menu.add_sideframe_item(_("Manage Versions"), url=url)
def changelist_view(self, request, menu_content_id=None, extra_context=None): extra_context = extra_context or {} if menu_content_id: request.menu_content_id = menu_content_id menu_content = get_object_or_404( self.menu_content_model._base_manager, id=menu_content_id) if self._versioning_enabled: version = Version.objects.get_for_content(menu_content) try: version.check_modify(request.user) except ConditionFailed as error: messages.error(request, str(error)) return HttpResponseRedirect(version_list_url(menu_content)) extra_context["menu_content"] = menu_content extra_context[ "versioning_enabled_for_nav"] = self._versioning_enabled return super().changelist_view(request, extra_context)
def _unlock_view(self, request, object_id): """ Unlock a locked version """ # This view always changes data so only POST requests should work if request.method != 'POST': return HttpResponseNotAllowed( ['POST'], _('This view only supports POST method.')) # Check version exists version = self.get_object(request, unquote(object_id)) if version is None: return self._get_obj_does_not_exist_redirect(request, self.model._meta, object_id) # Raise 404 if not locked if version.state != constants.DRAFT: raise Http404 # Check that the user has unlock permission if not request.user.has_perm( 'djangocms_version_locking.delete_versionlock'): return HttpResponseForbidden( force_text( _("You do not have permission to remove the version lock"))) # Unlock the version remove_version_lock(version) # Display message messages.success(request, _("Version unlocked")) # Send an email notification notify_version_author_version_unlocked(version, request.user) # Redirect url = version_list_url(version.content) return redirect(url)
def _get_moderation_link(self, version, request): if not is_registered_for_moderation(version.content): return "" if version.state != DRAFT: return "" content_object = version.content moderation_request = get_active_moderation_request(content_object) if moderation_request: title, url = get_moderation_button_title_and_url(moderation_request) return format_html('<a href="{}">{}</a>', url, title) elif is_obj_version_unlocked(content_object, request.user): url = add_url_parameters( get_admin_url(name="cms_moderation_items_to_collection", language="en", args=()), version_ids=version.pk, return_to_url=version_list_url(version.content), ) # TODO use a fancy icon as for the rest of the actions? return format_html('<a href="{}">{}</a>', url, _("Submit for moderation")) return ""
def test_version_list_url(self): pv = factories.PollVersionFactory() self.assertEqual( version_list_url(pv.content), "/en/admin/djangocms_versioning/pollcontentversion/?grouper=1", )
def assertRedirectsToVersionList(self, response, menu_content): """Asserts the response redirects to the menu content version list""" endpoint = version_list_url(menu_content) self.assertRedirects(response, endpoint)