def test_unauthed(self): request = self.get_request() page = Page() page.pk = 1 page.level = 0 page.tree_id = 1 self.assertTrue(page.has_view_permission(request))
def test_public_for_all(self): user = User.objects.create_user('user', '*****@*****.**', 'user') request = self.get_request(user) page = Page() page.pk = 1 page.level = 0 page.tree_id = 1 self.assertTrue(page.has_view_permission(request))
def test_unauthed_no_access(self): with SettingsOverride(CMS_PUBLIC_FOR='staff'): request = self.get_request() page = Page() page.pk = 1 page.level = 0 page.tree_id = 1 self.assertFalse(page.has_view_permission(request))
def test_authed_no_access(self): with SettingsOverride(CMS_PUBLIC_FOR='staff'): user = User.objects.create_user('user', '*****@*****.**', 'user') request = self.get_request(user) page = Page() page.pk = 1 page.level = 0 page.tree_id = 1 self.assertFalse(page.has_view_permission(request))
def test_unauthed(self): request = self.get_request() page = Page() page.pk = 1 page.level = 0 page.tree_id = 1 pages = [page] result = get_visible_pages(request, pages) self.assertEqual(result, [1])
def test_unauthed_no_access_num_queries(self): site = Site() site.pk = 1 request = self.get_request() page = Page() page.pk = 1 page.level = 0 page.tree_id = 1 with self.assertNumQueries(1): page.has_view_permission(request)
def test_global_permission(self): with SettingsOverride(CMS_PUBLIC_FOR='staff'): user = User.objects.create_user('user', '*****@*****.**', 'user') GlobalPagePermission.objects.create(can_view=True, user=user) request = self.get_request(user) page = Page() page.pk = 1 page.level = 0 page.tree_id = 1 self.assertTrue(page.has_view_permission(request))
def test_public_for_all_staff(self): request = self.get_request() request.user.is_staff = True page = Page() page.pk = 1 page.level = 0 page.tree_id = 1 pages = [page] result = get_visible_pages(request, pages) self.assertEqual(result, [1])
def test_public_for_all(self): user = User.objects.create_user('user', '*****@*****.**', 'user') request = self.get_request(user) page = Page() page.pk = 1 page.level = 0 page.tree_id = 1 pages = [page] result = get_visible_pages(request, pages) self.assertEqual(result, [1])
def test_authed_basic_perm(self): with SettingsOverride(CMS_PUBLIC_FOR='staff'): user = User.objects.create_user('user', '*****@*****.**', 'user') user.user_permissions.add(Permission.objects.get(codename='view_page')) request = self.get_request(user) page = Page() page.pk = 1 page.level = 0 page.tree_id = 1 self.assertTrue(page.has_view_permission(request))
def test_unauthed_no_access(self): with SettingsOverride(CMS_PUBLIC_FOR='staff'): request = self.get_request() page = Page() page.pk = 1 page.level = 0 page.tree_id = 1 pages = [page] result = get_visible_pages(request, pages) self.assertEqual(result, [])
def test_unauthed_no_access_num_queries(self): current_site = Site() current_site.pk = 1 request = self.get_request() page = Page() page.pk = 1 page.level = 0 page.tree_id = 1 fake_mptt_attrs(page) with self.assertNumQueries(1): page.has_view_permission(request)
def test_unauthed_no_access_num_queries(self): site = Site() site.pk = 1 request = self.get_request() page = Page() page.pk = 1 page.level = 0 page.tree_id = 1 pages = [page] with self.assertNumQueries(1): get_visible_pages(request, pages, site)
def test_authed_no_access(self): with SettingsOverride(CMS_PUBLIC_FOR='staff'): user = User.objects.create_user('user', '*****@*****.**', 'user') request = self.get_request(user) page = Page() page.pk = 1 page.level = 0 page.tree_id = 1 pages = [page] result = get_visible_pages(request, pages) self.assertEqual(result, [])
def copy_pages(): pages = PagesPage.objects.order_by('tree_id', 'lft', ) # remove all the previous pages CMSPage.objects.all().delete() parents = {} for page in pages: cmspage = CMSPage() # replicate the language independent structure information # thanks to the common ancestor we can reuse exactly the same tree # information cmspage.pk = page.pk cmspage.creation_date = page.creation_date cmspage.publication_date = page.publication_date cmspage.publication_end_date = page.publication_end_date cmspage.changed_date = page.last_modification_date cmspage.template = 'django_' + page.template cmspage.level = page.level cmspage.lft = page.lft cmspage.rght = page.rght cmspage.tree_id = page.tree_id cmspage.site_id = 1 if page.parent_id in parents: cmspage.parent = parents[page.parent_id] cmspage.save(no_signals=True) cmspage.rescan_placeholders() parents[cmspage.pk] = cmspage # replicate the language dependent data for language in page.get_languages(): cmstitle = Title() cmstitle.language = language cmstitle.title = page.title(language) cmstitle.slug = page.slug(language) cmstitle.page = cmspage cmstitle.update_path() cmstitle.save() contents = page.content_by_language(language) for content in contents: if content.type in ('subtitle', 'text', 'right-column'): placeholder = cmspage.placeholders.get(slot=content.type) # For the main placeholders we need to scan whether content # is markdown or plain HTML # This is a very naif check, but does the trick in this # context if content.body.find('<p>') > -1: add_plugin(placeholder, plugin_type='TextPlugin', language=language, body=content.body) else: add_plugin(placeholder, plugin_type='MarkItUpPlugin', language=language, body=content.body) elif content.type not in ('slug', 'title'): # Fallback import placeholder = cmspage.placeholders.get(slot=content.type) add_plugin(placeholder, plugin_type='TextPlugin', language=language, body=content.body)
def test_global_permission(self): with SettingsOverride(CMS_PUBLIC_FOR='staff'): user = User.objects.create_user('user', '*****@*****.**', 'user') GlobalPagePermission.objects.create(can_view=True, user=user) request = self.get_request(user) page = Page() page.pk = 1 page.level = 0 page.tree_id = 1 pages = [page] result = get_visible_pages(request, pages) self.assertEqual(result, [1])
def test_authed_basic_perm(self): with SettingsOverride(CMS_PUBLIC_FOR='staff'): user = User.objects.create_user('user', '*****@*****.**', 'user') user.user_permissions.add(Permission.objects.get(codename='view_page')) request = self.get_request(user) page = Page() page.pk = 1 page.level = 0 page.tree_id = 1 pages = [page] result = get_visible_pages(request, pages) self.assertEqual(result, [1])
def test_unauthed_num_queries(self): request = self.get_request() site = Site() site.pk = 1 page = Page() page.pk = 1 page.level = 0 page.tree_id = 1 with self.assertNumQueries(1): """ The query is: PagePermission query for affected pages """ page.has_view_permission(request)
def test_public_for_all_staff_assert_num_queries(self): request = self.get_request() request.user.is_staff = True page = Page() page.pk = 1 page.level = 0 page.tree_id = 1 pages = [page] with self.assertNumQueries(1): """ The queries are: PagePermission count query """ get_visible_pages(request, pages)
def test_public_for_all_num_queries(self): user = User.objects.create_user('user', '*****@*****.**', 'user') request = self.get_request(user) site = Site() site.pk = 1 page = Page() page.pk = 1 page.level = 0 page.tree_id = 1 with self.assertNumQueries(3): """ The queries are: The current Site PagePermission query for affected pages GlobalpagePermission query for user """ page.has_view_permission(request)
def test_unauthed_num_queries(self): request = self.get_request() site = Site() site.pk = 1 page = Page() page.pk = 1 page.level = 0 page.tree_id = 1 pages = [page] with self.assertNumQueries(1): """ The query is: PagePermission query for affected pages global is not executed because it's lazy """ get_visible_pages(request, pages, site)
def test_public_for_all_num_queries(self): user = User.objects.create_user('user', '*****@*****.**', 'user') request = self.get_request(user) site = Site() site.pk = 1 page = Page() page.pk = 1 page.level = 0 page.tree_id = 1 pages = [page] with self.assertNumQueries(2): """ The queries are: PagePermission query for affected pages GlobalpagePermission query for user """ get_visible_pages(request, pages, site)
def test_authed_no_access_num_queries(self): site = Site() site.pk = 1 with SettingsOverride(CMS_PUBLIC_FOR='staff'): user = User.objects.create_user('user', '*****@*****.**', 'user') request = self.get_request(user) page = Page() page.pk = 1 page.level = 0 page.tree_id = 1 pages = [page] with self.assertNumQueries(2): """ The queries are: View Permission Calculation Query globalpagepermissino calculation """ get_visible_pages(request, pages, site)
def test_authed_no_access_num_queries(self): site = Site() site.pk = 1 with SettingsOverride(CMS_PUBLIC_FOR='staff'): user = User.objects.create_user('user', '*****@*****.**', 'user') request = self.get_request(user) page = Page() page.pk = 1 page.level = 0 page.tree_id = 1 pages = [page] with self.assertNumQueries(4): """ The queries are: PagePermission query for affected pages GlobalpagePermission query for user Generic django permission lookup content type lookup by permission lookup """ get_visible_pages(request, pages, site)
def test_authed_basic_perm_num_queries(self): site = Site() site.pk = 1 with SettingsOverride(CMS_PUBLIC_FOR='staff'): user = User.objects.create_user('user', '*****@*****.**', 'user') user.user_permissions.add(Permission.objects.get(codename='view_page')) request = self.get_request(user) page = Page() page.pk = 1 page.level = 0 page.tree_id = 1 with self.assertNumQueries(5): """ The queries are: The site PagePermission query for affected pages GlobalpagePermission query for user Generic django permission lookup content type lookup by permission lookup """ page.has_view_permission(request)
def test_authed_basic_perm_num_queries(self): site = Site() site.pk = 1 with SettingsOverride(CMS_PUBLIC_FOR='staff'): user = User() user.username="******" user.is_staff = True user.save() user.user_permissions.add(Permission.objects.get(codename='view_page')) request = self.get_request(user) page = Page() page.pk = 1 page.level = 0 page.tree_id = 1 pages = [page] with self.assertNumQueries(2): """ The queries are: PagePermission count query GlobalpagePermission count query """ get_visible_pages(request, pages, site)
def create(request): if not request.user.is_admin_in_forening(request.active_forening): return render(request, 'central/admin/sites/create_disallowed.html') available_site_types = [] for t in Site.TYPE_CHOICES: if t[0] == 'mal': if not request.user.has_perm('sherpa/admin'): continue available_site_types.append(t) site_templates = Site.objects.filter( forening=Forening.DNT_CENTRAL_ID, type='mal', ).order_by('title') context = { 'available_site_types': available_site_types, 'site_templates': site_templates, 'template_types': Site.TEMPLATE_TYPE_CHOICES, } if request.method == 'GET': context['form'] = CreateSiteForm(request.user, auto_id='%s') return render(request, 'central/admin/sites/create.html', context) elif request.method == 'POST': form = CreateSiteForm(request.user, request.POST, auto_id='%s') context['form'] = form if not form.is_valid(): return render(request, 'central/admin/sites/create.html', context) if not request.POST['domain-type'] in ['fqdn', 'subdomain']: raise PermissionDenied site_forening = form.cleaned_data['forening'] type = form.cleaned_data['type'] title = form.cleaned_data['title'] template_main = form.cleaned_data['template_main'] template_type = form.cleaned_data['template_type'] template_description = form.cleaned_data['template_description'] domain = form.cleaned_data['domain'] site = Site( domain=domain, type=type, forening=site_forening, title=title, template_main=template_main, template_type=template_type, template_description=template_description, ) site.save() # If this is a main template, clear other templates of this type in case any of them were previous main if site.type == 'mal' and site.template_main: Site.objects.filter( type=site.type, template_type=site.template_type, ).exclude( id=site.id, ).update( template_main=False ) # Invalidate the forening's homepage site cache cache.delete('forening.homepage_site.%s' % site_forening.id) if 'use-template' not in request.POST: # User explicitly requested not to clone any template, just create a front page page = Page( site=site, title='Forside', published=True, created_by=request.user, created_date=datetime.now(), ) page.save() version = Version( page=page, version=1, owner=request.user, ) version.save() elif request.POST.get('template', '').strip() == '': # Sherpa-admin error; a site-template for the chosen site type doesn't exist! # This needs to be fixed. logger.error( "Sherpa-bruker opprettet en site med en mal som ikke finnes", extra={ 'request': request, 'missing_template_type': request.POST.get('missing-template-type', '<unknown>'), } ) site.delete() messages.error(request, 'invalid_template') return render(request, 'central/admin/sites/create.html', context) else: # All right, let's clone the entire template site # Note that for most objects, we'll just set the primary key to None, change the site field to the # new site, and save it, which will insert a new object. # For related fields, we'll need to save the related set in memory before saving the new object, so # that we can iterate it, clone them and re-relate them to the new object # Additionally, replace domain name references in content from the template-domain to the new one template_site = Site.get_cached_by_id(request.POST['template']) assert template_site.type == 'mal' # Menus for menu in Menu.objects.filter(site=template_site): menu.id = None menu.site = site # Replace domain references with the new site domain menu.url = re.sub(template_site.domain, site.domain, menu.url) menu.save() # Pages # Used to map old IDs to their new corresponding pages. This is needed because the parent reference can't # be duplicated, it needs to be updated with its corresponding new parent page_id_mapping = {} # Order by the left value in order to insert new nodes in a consistent way for page in Page.objects.filter(site=template_site).order_by('lft'): versions = page.versions.all() old_id = page.id page.id = None page.site = site # Reset MPTT state and let our library recreate them page.tree_id = None page.lft = None page.rght = None page.level = None # Set parent to the corresponding clone; use the old parent id to retrieve it if page.parent is not None: page.parent = page_id_mapping[page.parent.id] # Change creation to the user creating the new site and reset modification page.created_by = request.user page.created_date = datetime.now() page.modified_by = None page.modified_date = None # Insert the new node appropriately if page.parent is None: Page.objects.insert_node(page, target=None, save=True) else: Page.objects.insert_node(page, target=page.parent, position='last-child', save=True) page.save() # Remember which old id maps to this page page_id_mapping[old_id] = page for version in versions: rows = version.rows.all() version.id = None version.page = page version.save() for row in rows: columns = row.columns.all() row.id = None row.version = version row.save() for column in columns: contents = column.contents.all() column.id = None column.row = row column.save() for content in contents: content.id = None content.column = column # Replace domain references with the new site domain # Use a json dump with prepended/trailing quotes stripped to ensure the # replacement string is properly escaped if inserted into json-formatted content json_safe_domain = json.dumps(site.domain)[1:-1] content.content = re.sub(template_site.domain, json_safe_domain, content.content) # For aktiviteteslisting-widgets, force arranger-filter to the new site's related # forening if content.type == 'widget': parsed_content = json.loads(content.content) if parsed_content['widget'] == 'aktivitet_listing': # Note that the list of ids contains strings, because we forgot to convert # it to int in the widget-editor save logic, but that's not a problem since # the filter lookup will implicitly convert it. So force it to str to be # consistent parsed_content['foreninger'] = [str(site.forening.id)] content.content = json.dumps(parsed_content) content.save() # Articles for article in Article.objects.filter(site=template_site): versions = article.versions.all() article.id = None article.site = site # Change creation to the user creating the new site and reset modification article.created_by = request.user article.created_date = datetime.now() article.modified_by = None article.modified_date = None article.save() for version in versions: rows = version.rows.all() version.id = None version.article = article version.save() for row in rows: columns = row.columns.all() row.id = None row.version = version row.save() for column in columns: contents = column.contents.all() column.id = None column.row = row column.save() for content in contents: content.id = None content.column = column # Replace domain references with the new site domain # Use a json dump with prepended/trailing quotes stripped to ensure the # replacement string is properly escaped if inserted into json-formatted content json_safe_domain = json.dumps(site.domain)[1:-1] content.content = re.sub(template_site.domain, json_safe_domain, content.content) # For aktiviteteslisting-widgets, force arranger-filter to the new site's related # forening if content.type == 'widget': parsed_content = json.loads(content.content) if parsed_content['widget'] == 'aktivitet_listing': # Note that the list of ids contains strings, because we forgot to convert # it to int in the widget-editor save logic, but that's not a problem since # the filter lookup will implicitly convert it. So force it to str to be # consistent parsed_content['foreninger'] = [str(site.forening.id)] content.content = json.dumps(parsed_content) content.save() # Campaigns for campaign in Campaign.objects.filter(site=template_site): campaign_texts = campaign.text.all() campaign.id = None campaign.site = site # Replace domain references with the new site domain campaign.button_anchor = re.sub(template_site.domain, site.domain, campaign.button_anchor) campaign.save() for campaign_text in campaign_texts: campaign_text.id = None campaign_text.campaign = campaign campaign_text.save() # Add default language menu options LanguageMenuOption.objects.create( site=site, label="English", destination="https://english.dnt.no/", sort=1 ) LanguageMenuOption.objects.create( site=site, label="Deutsch", destination="https://deutsch.dnt.no/", sort=2 ) LanguageMenuOption.objects.create( site=site, label="Français", destination="https://www.dnt.no/francais/", sort=3 ) request.session.modified = True messages.info(request, 'site_created') return redirect('admin:sites.show', site.id)
def copy_pages(): pages = PagesPage.objects.order_by( 'tree_id', 'lft', ) # remove all the previous pages CMSPage.objects.all().delete() parents = {} for page in pages: cmspage = CMSPage() # replicate the language independent structure information # thanks to the common ancestor we can reuse exactly the same tree # information cmspage.pk = page.pk cmspage.creation_date = page.creation_date cmspage.publication_date = page.publication_date cmspage.publication_end_date = page.publication_end_date cmspage.changed_date = page.last_modification_date cmspage.template = 'django_' + page.template cmspage.level = page.level cmspage.lft = page.lft cmspage.rght = page.rght cmspage.tree_id = page.tree_id cmspage.site_id = 1 if page.parent_id in parents: cmspage.parent = parents[page.parent_id] cmspage.save(no_signals=True) cmspage.rescan_placeholders() parents[cmspage.pk] = cmspage # replicate the language dependent data for language in page.get_languages(): cmstitle = Title() cmstitle.language = language cmstitle.title = page.title(language) cmstitle.slug = page.slug(language) cmstitle.page = cmspage cmstitle.update_path() cmstitle.save() contents = page.content_by_language(language) for content in contents: if content.type in ('subtitle', 'text', 'right-column'): placeholder = cmspage.placeholders.get(slot=content.type) # For the main placeholders we need to scan whether content # is markdown or plain HTML # This is a very naif check, but does the trick in this # context if content.body.find('<p>') > -1: add_plugin(placeholder, plugin_type='TextPlugin', language=language, body=content.body) else: add_plugin(placeholder, plugin_type='MarkItUpPlugin', language=language, body=content.body) elif content.type not in ('slug', 'title'): # Fallback import placeholder = cmspage.placeholders.get(slot=content.type) add_plugin(placeholder, plugin_type='TextPlugin', language=language, body=content.body)