Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[#1799] Implement CMS plugin for mijn aanvragen #815

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions src/open_inwoner/cms/cases/cms_plugins.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
from django.utils.translation import ugettext_lazy as _

from cms.plugin_base import CMSPluginBase
from cms.plugin_pool import plugin_pool

# TODO: import `preprocess_data` after merge of PR 804
from open_inwoner.openzaak.cases import fetch_cases
from open_inwoner.openzaak.formapi import fetch_open_submissions

from ..utils.auth import check_user_access_rights, check_user_auth
from ..utils.plugin_mixins import CMSActiveAppMixin


# TODO: refactor after merge of PR 804
@plugin_pool.register_plugin
class CasesPlugin(CMSActiveAppMixin, CMSPluginBase):
module = _("Openzaak")
name = _("Cases Plugin")
render_template = "cms/cases/cases_plugin.html"
app_hook = "CasesApphook"
cache = False

limit = 4

def render(self, context, instance, placeholder):
request = context["request"]
user = request.user

if not check_user_auth(user, digid_required=True):
context["cases"] = None
return context

raw_cases = [case for case in fetch_cases(user.bsn) if not case.einddatum]

if not all(check_user_access_rights(user, case.url) for case in raw_cases):
context["cases"] = None
return context

# TODO
# preprocessed_cases = preprocess_data(raw_cases)

subs = fetch_open_submissions(request.user.bsn)

# replce raw_cases with preprocessed_cases
all_cases = raw_cases + subs

# processed_cases = [case.preprocess_data() for case in all_cases]

context["cases"] = all_cases[: self.limit]

return context
86 changes: 86 additions & 0 deletions src/open_inwoner/cms/cases/tests/test_plugin_cases.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
from unittest.mock import patch

from django.test import TestCase, override_settings

import lxml
import requests_mock
from pyquery import PyQuery as pq

from open_inwoner.accounts.choices import LoginTypeChoices
from open_inwoner.accounts.tests.factories import UserFactory
from open_inwoner.openzaak.tests.mixins import ZakenTestMixin
from open_inwoner.utils.test import ClearCachesMixin

from ...tests import cms_tools
from ..cms_apps import CasesApphook
from ..cms_plugins import CasesPlugin


@requests_mock.Mocker()
@patch.object(CasesPlugin, "limit", 2)
@override_settings(ROOT_URLCONF="open_inwoner.cms.tests.urls")
class CasesPluginTest(ZakenTestMixin, ClearCachesMixin, TestCase):
@classmethod
def setUpTestData(cls):
super().setUpTestData()
cms_tools.create_apphook_page(CasesApphook)

def test_cms_plugin_cases_not_rendered_for_anonymous_user(self, m):
self.setUpMocks(m)

# anonymous user
html, context = cms_tools.render_plugin(CasesPlugin)

self.assertIsNone(context["cases"])

# check that html empty
with self.assertRaises(lxml.etree.ParserError) as ctx:
pq(html)

self.assertEqual(str(ctx.exception), "Document is empty")

def test_cms_plugin_cases_not_rendered_for_non_digid_user(self, m):
self.setUpMocks(m)

user = UserFactory()
user.login_type = LoginTypeChoices.default
user.save()

html, context = cms_tools.render_plugin(CasesPlugin, user=user)

self.assertIsNone(context["cases"])

# check that html empty
with self.assertRaises(lxml.etree.ParserError) as ctx:
pq(html)

self.assertEqual(str(ctx.exception), "Document is empty")

def test_cms_plugin_cases_rendered(self, m):
self.setUpMocks(m)
self.setUpMocksExtra(m) # create additional zaken

# the ZakenTestMixin user is a digid user
html, context = cms_tools.render_plugin(CasesPlugin, user=self.user)

cases = context["cases"]

# check that limiting display works (ZakenTestMixin creates 3 zaken)
self.assertEqual(len(cases), 2)

self.assertEqual(cases[0].omschrijving, "Coffee zaak 1")
self.assertEqual(cases[1].omschrijving, "Coffee zaak 2")

# check html
doc = pq(html)

case_descriptions = doc.find(".h4").find("span")

for case_description, case in zip(case_descriptions, cases):
self.assertEqual(case_description.text, case.omschrijving)

case_link_paths = (case.url.rsplit("/", 1)[-1] for case in cases)
html_case_links = doc.find("a")

for html_link, path in zip(html_case_links, case_link_paths):
self.assertEqual(html_link.attrib["href"], f"/cases/{path}/status/")
22 changes: 22 additions & 0 deletions src/open_inwoner/cms/utils/auth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import logging

from open_inwoner.openzaak.cases import fetch_roles_for_case_and_bsn

logger = logging.getLogger(__name__)


def check_user_auth(user, digid_required: bool = False) -> bool:
if not user.is_authenticated:
logger.debug("Permission denied: user not authenticated")
return False
if digid_required and not getattr(user, "bsn", None):
logger.debug("Permission denied: user has no BSN")
return False
return True


def check_user_access_rights(user, case_url) -> bool:
if not fetch_roles_for_case_and_bsn(case_url, user.bsn):
f"Permission denied: no role for the case {case_url}"
return False
return True
10 changes: 8 additions & 2 deletions src/open_inwoner/cms/utils/plugin_mixins.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
from cms.models import Page
from cms.plugin_base import CMSPluginBase


class CMSActiveAppMixin:
"""
Render only plugins for active CMS apps
"""

app_hook = None

@property
def render_plugin(self):
def render_plugin(self) -> bool:
"""
Return `True` if plugin should be rendered, `False` otherwise
"""
if self.app_hook is None:
raise ValueError(f"Apphook for plugin '{self.name}' is not defined")

Expand Down
1 change: 1 addition & 0 deletions src/open_inwoner/conf/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,7 @@
"content": {
"plugins": [
# "TextPlugin",
"CasesPlugin",
"PicturePlugin",
"VideoPlayerPlugin",
"CategoriesPlugin",
Expand Down
Loading
Loading