applification: ne pas afficher les applications non visibles (#75116) #147

Merged
lguerin merged 2 commits from wip/75116-application-visible into main 2023-04-17 16:36:44 +02:00
5 changed files with 122 additions and 11 deletions

View File

@ -531,7 +531,8 @@ def test_export_import_redirect_url(pub):
get_app(pub).get('/api/export-import/roles/test/redirect/', status=404)
def create_bundle(elements, *args):
def create_bundle(elements, *args, **kwargs):
visible = kwargs.get('visible', True)
tar_io = io.BytesIO()
with tarfile.open(mode='w', fileobj=tar_io) as tar:
manifest_json = {
@ -540,6 +541,7 @@ def create_bundle(elements, *args):
'icon': 'foo.png',
'description': 'Foo Bar',
'documentation_url': 'http://foo.bar',
'visible': visible,
'version_number': '42.0',
'version_notes': 'foo bar blah',
'elements': elements,
@ -740,8 +742,13 @@ def test_export_import_bundle_import(pub):
assert application.version_notes == 'foo bar blah'
assert application.icon.base_filename == 'foo.png'
assert application.editable is False
assert application.visible is True
assert ApplicationElement.count() == 15
# check editable flag is kept on install
application.editable = False
application.store()
# create some links to elements not present in manifest: they should be unlinked
element1 = ApplicationElement()
element1.application_id = application.id
@ -798,6 +805,8 @@ def test_export_import_bundle_import(pub):
)
== []
)
application = Application.select()[0]
assert application.editable is False
# change immutable attributes and check they are not reset
formdef = FormDef.select()[0]
@ -930,6 +939,7 @@ def test_export_import_bundle_declare(pub):
('comment-templates/test', comment_template),
('roles/test', role),
('wscalls/test', wscall),
visible=False,
)
resp = get_app(pub).put(sign_uri('/api/export-import/bundle-declare/'), bundle)
@ -948,6 +958,7 @@ def test_export_import_bundle_declare(pub):
assert application.version_notes == 'foo bar blah'
assert application.icon.base_filename == 'foo.png'
assert application.editable is True
assert application.visible is False
assert ApplicationElement.count() == 15
# create some links to elements not present in manifest: they should be unlinked

View File

@ -199,6 +199,18 @@ def test_formdefs(pub, application_with_icon, application_without_icon, icon):
assert resp.pyquery('h2').text() == application.name
assert len(resp.pyquery('ul.objects-list li')) == 1
# check visible flag
application = Application.get(application.id)
application.visible = False
application.store()
resp = app.get('/backoffice/forms/')
assert len(resp.pyquery('.extra-actions-menu li')) == 0
app.get('/backoffice/forms/application/%s/' % application.id, status=404)
assert len(resp.pyquery('img.application-icon')) == 0
resp = app.get('/backoffice/forms/categories/')
assert len(resp.pyquery('.extra-actions-menu li')) == 0
app.get('/backoffice/forms/categories/application/%s/' % application.id, status=404)
@pytest.mark.parametrize('icon', [True, False])
def test_carddefs(pub, application_with_icon, application_without_icon, icon):
@ -327,6 +339,18 @@ def test_carddefs(pub, application_with_icon, application_without_icon, icon):
assert resp.pyquery('h2').text() == application.name
assert len(resp.pyquery('ul.objects-list li')) == 1
# check visible flag
application = Application.get(application.id)
application.visible = False
application.store()
resp = app.get('/backoffice/cards/')
assert len(resp.pyquery('.extra-actions-menu li')) == 0
app.get('/backoffice/cards/application/%s/' % application.id, status=404)
assert len(resp.pyquery('img.application-icon')) == 0
resp = app.get('/backoffice/cards/categories/')
assert len(resp.pyquery('.extra-actions-menu li')) == 0
app.get('/backoffice/cards/categories/application/%s/' % application.id, status=404)
@pytest.mark.parametrize('icon', [True, False])
def test_workflows(pub, application_with_icon, application_without_icon, icon):
@ -513,6 +537,18 @@ def test_workflows(pub, application_with_icon, application_without_icon, icon):
assert resp.pyquery('h2').text() == application.name
assert len(resp.pyquery('ul.objects-list li')) == 1
# check visible flag
application = Application.get(application.id)
application.visible = False
application.store()
resp = app.get('/backoffice/forms/')
assert len(resp.pyquery('.extra-actions-menu li')) == 0
app.get('/backoffice/forms/application/%s/' % application.id, status=404)
assert len(resp.pyquery('img.application-icon')) == 0
resp = app.get('/backoffice/forms/categories/')
assert len(resp.pyquery('.extra-actions-menu li')) == 0
app.get('/backoffice/forms/categories/application/%s/' % application.id, status=404)
@pytest.mark.parametrize('icon', [True, False])
def test_blockdefs(pub, application_with_icon, application_without_icon, icon):
@ -639,6 +675,18 @@ def test_blockdefs(pub, application_with_icon, application_without_icon, icon):
assert resp.pyquery('h2').text() == application.name
assert len(resp.pyquery('ul.objects-list li')) == 1
# check visible flag
application = Application.get(application.id)
application.visible = False
application.store()
resp = app.get('/backoffice/forms/blocks/')
assert len(resp.pyquery('.extra-actions-menu li')) == 0
app.get('/backoffice/forms/blocks/application/%s/' % application.id, status=404)
assert len(resp.pyquery('img.application-icon')) == 0
resp = app.get('/backoffice/forms/blocks/categories/')
assert len(resp.pyquery('.extra-actions-menu li')) == 0
app.get('/backoffice/forms/blocks/categories/application/%s/' % application.id, status=404)
@pytest.mark.parametrize('icon', [True, False])
def test_mailtemplates(pub, application_with_icon, application_without_icon, icon):
@ -775,6 +823,18 @@ def test_mailtemplates(pub, application_with_icon, application_without_icon, ico
assert resp.pyquery('h2').text() == application.name
assert len(resp.pyquery('ul.objects-list li')) == 1
# check visible flag
application = Application.get(application.id)
application.visible = False
application.store()
resp = app.get('/backoffice/workflows/mail-templates/')
assert len(resp.pyquery('.extra-actions-menu li')) == 0
app.get('/backoffice/workflows/mail-templates/application/%s/' % application.id, status=404)
assert len(resp.pyquery('img.application-icon')) == 0
resp = app.get('/backoffice/workflows/mail-templates/categories/')
assert len(resp.pyquery('.extra-actions-menu li')) == 0
app.get('/backoffice/workflows/mail-templates/categories/application/%s/' % application.id, status=404)
@pytest.mark.parametrize('icon', [True, False])
def test_commenttemplates(pub, application_with_icon, application_without_icon, icon):
@ -916,6 +976,18 @@ def test_commenttemplates(pub, application_with_icon, application_without_icon,
assert resp.pyquery('h2').text() == application.name
assert len(resp.pyquery('ul.objects-list li')) == 1
# check visible flag
application = Application.get(application.id)
application.visible = False
application.store()
resp = app.get('/backoffice/workflows/comment-templates/')
assert len(resp.pyquery('.extra-actions-menu li')) == 0
app.get('/backoffice/workflows/comment-templates/application/%s/' % application.id, status=404)
assert len(resp.pyquery('img.application-icon')) == 0
resp = app.get('/backoffice/workflows/comment-templates/categories/')
assert len(resp.pyquery('.extra-actions-menu li')) == 0
app.get('/backoffice/workflows/comment-templates/categories/application/%s/' % application.id, status=404)
@pytest.mark.parametrize('icon', [True, False])
def test_datasources(pub, application_with_icon, application_without_icon, icon):
@ -1159,6 +1231,18 @@ def test_datasources(pub, application_with_icon, application_without_icon, icon)
assert resp.pyquery('h2').text() == application.name
assert len(resp.pyquery('ul.objects-list li')) == 1
# check visible flag
application = Application.get(application.id)
application.visible = False
application.store()
resp = app.get('/backoffice/forms/data-sources/')
assert len(resp.pyquery('.extra-actions-menu li')) == 0
app.get('/backoffice/forms/data-sources/application/%s/' % application.id, status=404)
assert len(resp.pyquery('img.application-icon')) == 0
resp = app.get('/backoffice/forms/data-sources/categories/')
assert len(resp.pyquery('.extra-actions-menu li')) == 0
app.get('/backoffice/forms/data-sources/categories/application/%s/' % application.id, status=404)
@pytest.mark.parametrize('icon', [True, False])
def test_wscalls(pub, application_with_icon, application_without_icon, icon):
@ -1227,6 +1311,15 @@ def test_wscalls(pub, application_with_icon, application_without_icon, icon):
assert resp.pyquery('ul.objects-list li:nth-child(1)').text() == 'wscall2 (wscall2)'
assert resp.pyquery('ul.objects-list li:nth-child(2)').text() == 'wscall3 (wscall3)'
# check visible flag
application = Application.get(application.id)
application.visible = False
application.store()
resp = app.get('/backoffice/settings/wscalls/')
assert len(resp.pyquery('.extra-actions-menu li')) == 0
app.get('/backoffice/settings/wscalls/application/%s/' % application.id, status=404)
assert len(resp.pyquery('img.application-icon')) == 0
def test_object_applications(pub, application_without_icon):
application = application_without_icon

View File

@ -248,7 +248,9 @@ class BundleImportJob(AfterJob):
tar_io = io.BytesIO(self.tar_content)
with tarfile.open(fileobj=tar_io) as self.tar:
manifest = json.loads(self.tar.extractfile('manifest.json').read().decode())
self.application = Application.update_or_create_from_manifest(manifest, self.tar)
self.application = Application.update_or_create_from_manifest(
manifest, self.tar, editable=False, install=False
)
# count number of actions
self.total_count = 0
@ -366,7 +368,9 @@ class BundleDeclareJob(BundleImportJob):
tar_io = io.BytesIO(self.tar_content)
with tarfile.open(fileobj=tar_io) as self.tar:
manifest = json.loads(self.tar.extractfile('manifest.json').read().decode())
self.application = Application.update_or_create_from_manifest(manifest, self.tar, editable=True)
self.application = Application.update_or_create_from_manifest(
manifest, self.tar, editable=True, install=True
)
# count number of actions
self.total_count = len([x for x in manifest.get('elements') if x.get('type') in object_types])

View File

@ -47,11 +47,12 @@ class Application(sql.Application):
raise KeyError(slug)
@classmethod
def update_or_create_from_manifest(cls, manifest, tar, editable=False):
def update_or_create_from_manifest(cls, manifest, tar, editable=False, install=True):
application = cls.get_by_slug(manifest.get('slug'), ignore_errors=True)
if application is None:
application = cls()
application.slug = manifest.get('slug')
application.editable = editable
application.name = manifest.get('application')
application.description = manifest.get('description')
application.documentation_url = manifest.get('documentation_url')
@ -62,8 +63,9 @@ class Application(sql.Application):
application.icon = None
application.version_number = manifest.get('version_number') or 'unknown'
application.version_notes = manifest.get('version_notes')
application.editable = editable
application.visible = True
if not install:
application.editable = editable
application.visible = manifest.get('visible', True)
application.store()
return application
@ -71,7 +73,7 @@ class Application(sql.Application):
def select_for_object_type(cls, object_type):
elements = ApplicationElement.select([sql.Equal('object_type', object_type)])
application_ids = [e.application_id for e in elements]
return cls.get_ids(application_ids, ignore_errors=True, order_by='name')
return [a for a in cls.get_ids(application_ids, ignore_errors=True, order_by='name') if a.visible]
@classmethod
def populate_objects(cls, objects):
@ -81,13 +83,14 @@ class Application(sql.Application):
for element in elements:
elements_by_objects[(element.object_type, element.object_id)].append(element)
application_ids = [e.application_id for e in elements]
applications_by_ids = {a.id: a for a in cls.get_ids(application_ids, ignore_errors=True)}
applications_by_ids = {a.id: a for a in cls.get_ids(application_ids, ignore_errors=True) if a.visible}
for obj in objects:
applications = []
elements = elements_by_objects.get((obj.xml_root_node, obj.id)) or []
for element in elements:
application = applications_by_ids.get(element.application_id)
applications.append(application)
if application:
applications.append(application)
obj._applications = sorted(applications, key=lambda a: a.name)
@classmethod
@ -96,7 +99,7 @@ class Application(sql.Application):
[sql.Equal('object_type', obj.xml_root_node), sql.Equal('object_id', obj.id)]
)
application_ids = [e.application_id for e in elements]
applications_by_ids = {a.id: a for a in cls.get_ids(application_ids, ignore_errors=True)}
applications_by_ids = {a.id: a for a in cls.get_ids(application_ids, ignore_errors=True) if a.visible}
applications = []
for element in elements:
application = applications_by_ids.get(element.application_id)

View File

@ -34,7 +34,7 @@ class ApplicationsDirectory(Directory):
from wcs.applications import Application
application = Application.get_by_slug(component, ignore_errors=True)
if not application:
if not application or not application.visible:
raise errors.TraversalError()
return ApplicationDirectory(self.object_type, application)