diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 525f35bb..c3efd102 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -102,6 +102,7 @@ Fixed - ``addremotesite`` crash in ``TimelineAPI.add_event()`` (#1425) - ``addremotesite`` allows creation of site with mode identical to host (#1426) - Public guest access field not correctly hidden in project form (#1429) + - Revoked remote projects displayed in project detail view (#1432) - **Sodarcache** - REST API set view ``app_name`` incorrectly set (#1405) @@ -116,6 +117,7 @@ Removed - ``CORE_API_*`` Django settings (#1278) - Project starring timeline event creation (#1294) - ``user_email_additional`` app setting (#874) + - ``get_visible_projects()`` template tag (#1432) v0.13.4 (2024-02-16) diff --git a/projectroles/templates/projectroles/project_detail.html b/projectroles/templates/projectroles/project_detail.html index 821109a5..c3b16c71 100644 --- a/projectroles/templates/projectroles/project_detail.html +++ b/projectroles/templates/projectroles/project_detail.html @@ -11,7 +11,6 @@ {% has_perm 'projectroles.view_project' request.user object as can_view_project %} {% has_perm 'projectroles.update_project' request.user object as can_update_project %} -{% has_perm 'projectroles.view_hidden_projects' request.user object as can_view_hidden_projects %} {% sodar_constant 'PROJECT_TYPE_CATEGORY' as PROJECT_TYPE_CATEGORY %} {% if can_view_project %} @@ -20,8 +19,7 @@
{# Links to remote projects #} {% if object.type == 'PROJECT' %} - {% get_visible_projects target_projects can_view_hidden_projects as visible_target_projects %} - {% if visible_target_projects %} + {% if target_projects %}

@@ -30,7 +28,7 @@

- {% for rp in visible_target_projects %} + {% for rp in target_projects %} {% endfor %}
- {% elif object.is_remote %}
-

{% get_display_name object.type title=True %} on Other Sites

+

+ + {% get_display_name object.type title=True %} on Other Sites +

diff --git a/projectroles/templatetags/projectroles_common_tags.py b/projectroles/templatetags/projectroles_common_tags.py index 956c9ed9..96930c39 100644 --- a/projectroles/templatetags/projectroles_common_tags.py +++ b/projectroles/templatetags/projectroles_common_tags.py @@ -292,17 +292,6 @@ def get_remote_icon(project, request): return '' -@register.simple_tag -def get_visible_projects(projects, can_view_hidden_projects=False): - """ - Return all projects that are either visible by user display or by view - hidden permission. - """ - return [ - p for p in projects if p.site.user_display or can_view_hidden_projects - ] - - @register.simple_tag def render_markdown(raw_markdown): """Markdown field rendering helper""" diff --git a/projectroles/tests/test_templatetags.py b/projectroles/tests/test_templatetags.py index 4e37a91c..73297dfa 100644 --- a/projectroles/tests/test_templatetags.py +++ b/projectroles/tests/test_templatetags.py @@ -13,13 +13,7 @@ import projectroles from projectroles.app_settings import AppSettingAPI -from projectroles.models import ( - Project, - RemoteProject, - RemoteSite, - AppSetting, - SODAR_CONSTANTS, -) +from projectroles.models import AppSetting, SODAR_CONSTANTS from projectroles.plugins import get_app_plugin, get_active_plugins from projectroles.templatetags import ( projectroles_common_tags as c_tags, @@ -303,48 +297,6 @@ def test_get_info_link(self): # TODO: Test get_remote_icon() (need to set up remote projects) - def test_get_visible_projects(self): - """Test get_visible_projects()""" - # Setup projects - create_values = {'title': 'TestProject'} - project = Project.objects.create(**create_values) - - # Setup sites - create_values = { - 'name': 'VisibleSite', - 'url': 'visible.site', - 'mode': SITE_MODE_TARGET, - 'user_display': True, - } - visible_site = RemoteSite.objects.create(**create_values) - - create_values = { - 'name': 'InvisibleSite', - 'url': 'invisible.site', - 'mode': SITE_MODE_TARGET, - 'user_display': False, - } - invisible_site = RemoteSite.objects.create(**create_values) - - # Setup remote projects - create_values = { - 'project_uuid': project.sodar_uuid, - 'project': project, - 'site': visible_site, - 'level': REMOTE_LEVEL_READ_ROLES, - } - visible_project = RemoteProject.objects.create(**create_values) - - create_values['site'] = invisible_site - invisible_project = RemoteProject.objects.create(**create_values) - - # Test returned peer projects - peer_projects = c_tags.get_visible_projects( - [visible_project, invisible_project] - ) - - self.assertEqual(peer_projects, [visible_project]) - def test_render_markdown(self): """Test render_markdown()""" raw_md = '**Some markdown**' diff --git a/projectroles/tests/test_ui.py b/projectroles/tests/test_ui.py index 8d0fde87..e82f684a 100644 --- a/projectroles/tests/test_ui.py +++ b/projectroles/tests/test_ui.py @@ -56,6 +56,8 @@ SITE_MODE_TARGET = SODAR_CONSTANTS['SITE_MODE_TARGET'] SITE_MODE_SOURCE = SODAR_CONSTANTS['SITE_MODE_SOURCE'] SITE_MODE_PEER = SODAR_CONSTANTS['SITE_MODE_PEER'] +REMOTE_LEVEL_READ_ROLES = SODAR_CONSTANTS['REMOTE_LEVEL_READ_ROLES'] +REMOTE_LEVEL_REVOKED = SODAR_CONSTANTS['REMOTE_LEVEL_REVOKED'] # Local constants PROJECT_LINK_IDS = [ @@ -1230,7 +1232,10 @@ def _get_pr_links(cls, *args): return ['sodar-pr-link-project-' + x for x in args] def _setup_remote_project( - self, site_mode=SITE_MODE_TARGET, user_visibility=True + self, + site_mode=SITE_MODE_TARGET, + level=REMOTE_LEVEL_READ_ROLES, + user_visibility=True, ): """Create remote site and project with given user_visibility setting""" self.remote_site = self.make_site( @@ -1246,7 +1251,7 @@ def _setup_remote_project( self.remote_project = self.make_remote_project( project_uuid=self.project.sodar_uuid, site=self.remote_site, - level=SODAR_CONSTANTS['REMOTE_LEVEL_READ_ROLES'], + level=level, project=self.project, ) @@ -1358,9 +1363,9 @@ def test_plugin_cards(self): ) self.assert_element_count(expected, url, 'sodar-pr-app-item') - def test_remote_project_visible(self): - """Test project card for enabled visbility for all users""" - self._setup_remote_project(user_visibility=True) + def test_remote_project(self): + """Test remote project visbility for all users""" + self._setup_remote_project() users = [ self.superuser, self.user_owner_cat, @@ -1375,7 +1380,6 @@ def test_remote_project_visible(self): url = reverse( 'projectroles:detail', kwargs={'project': self.project.sodar_uuid} ) - # Visibile for all users for user in users: self.login_and_redirect(user, url) project_details = self.selenium.find_element( @@ -1386,14 +1390,13 @@ def test_remote_project_visible(self): ) self.assertEqual(remote_project.text, REMOTE_SITE_NAME) - def test_remote_project_invisible(self): - """Test project card for disabled visibility for different users""" + def test_remote_project_user_visibility_disabled(self): + """Test remote project visibility with user_visibility=False""" self._setup_remote_project(user_visibility=False) users = [self.user_delegate, self.user_contributor, self.user_guest] url = reverse( 'projectroles:detail', kwargs={'project': self.project.sodar_uuid} ) - # Invisible for basic users for user in users: self.login_and_redirect(user, url) with self.assertRaises(NoSuchElementException): @@ -1411,7 +1414,31 @@ def test_remote_project_invisible(self): ) self.assertEqual(remote_project.text, REMOTE_SITE_NAME) - def test_peer_project_source_invisible(self): + def test_remote_project_revoked(self): + """Test remote project with REVOKED level""" + self._setup_remote_project(level=REMOTE_LEVEL_REVOKED) + users = [ + self.superuser, + self.user_owner_cat, + self.user_delegate_cat, + self.user_contributor_cat, + self.user_guest_cat, + self.user_owner, + self.user_delegate, + self.user_contributor, + self.user_guest, + ] + url = reverse( + 'projectroles:detail', kwargs={'project': self.project.sodar_uuid} + ) + for user in users: + self.login_and_redirect(user, url) + with self.assertRaises(NoSuchElementException): + self.selenium.find_element( + By.ID, 'sodar-pr-details-card-remote' + ) + + def test_peer_project_source(self): """Test visibility of peer projects on SOURCE site""" self._setup_remote_project(site_mode=SITE_MODE_PEER) url = reverse( @@ -1437,9 +1464,9 @@ def test_peer_project_source_invisible(self): ) @override_settings(PROJECTROLES_SITE_MODE=SITE_MODE_TARGET) - def test_peer_project_target_visible(self): - """Test visibility of peer projects on TARGET site (user_display=False)""" - # There needs to be a source mode remote project as master project, + def test_peer_project(self): + """Test peer projects on TARGET site with user_display=True""" + # There needs to be a source mode remote project as source project, # otherwise peer project logic wont be reached source_site = self.make_site( name='Second Remote Site', @@ -1452,7 +1479,7 @@ def test_peer_project_target_visible(self): self.make_remote_project( project_uuid=self.project.sodar_uuid, site=source_site, - level=SODAR_CONSTANTS['REMOTE_LEVEL_READ_ROLES'], + level=REMOTE_LEVEL_READ_ROLES, project=self.project, ) self._setup_remote_project(site_mode=SITE_MODE_PEER) @@ -1488,10 +1515,8 @@ def test_peer_project_target_visible(self): ) @override_settings(PROJECTROLES_SITE_MODE=SITE_MODE_TARGET) - def test_peer_project_target_invisible(self): - """Test invisibility of peer projects on TARGET site for users (user_display=False)""" - # There needs to be a source mode remote project as master project, - # otherwise peer project logic wont be reached + def test_peer_project_user_visibility_disabled(self): + """Test peer projects on TARGET site with user_display=False""" source_site = self.make_site( name='Second Remote Site', url='second_remote.site', @@ -1503,7 +1528,7 @@ def test_peer_project_target_invisible(self): self.make_remote_project( project_uuid=self.project.sodar_uuid, site=source_site, - level=SODAR_CONSTANTS['REMOTE_LEVEL_READ_ROLES'], + level=REMOTE_LEVEL_READ_ROLES, project=self.project, ) self._setup_remote_project( @@ -1549,6 +1574,51 @@ def test_peer_project_target_invisible(self): remote_links[0].get_attribute('class'), ) + @override_settings(PROJECTROLES_SITE_MODE=SITE_MODE_TARGET) + def test_peer_project_revoked(self): + """Test peer project with REVOKED level""" + source_site = self.make_site( + name='Second Remote Site', + url='second_remote.site', + mode=SITE_MODE_SOURCE, + description='', + secret=build_secret(), + user_display=False, + ) + self.make_remote_project( + project_uuid=self.project.sodar_uuid, + site=source_site, + level=REMOTE_LEVEL_READ_ROLES, + project=self.project, + ) + self._setup_remote_project( + site_mode=SITE_MODE_PEER, level=REMOTE_LEVEL_REVOKED + ) + url = reverse( + 'projectroles:detail', kwargs={'project': self.project.sodar_uuid} + ) + users = [ + self.superuser, + self.user_owner_cat, + self.user_owner, + self.user_delegate_cat, + self.user_contributor_cat, + self.user_guest_cat, + self.user_delegate, + self.user_contributor, + self.user_guest, + ] + for user in users: + self.login_and_redirect(user, url) + remote_links = self.selenium.find_elements( + By.CLASS_NAME, 'sodar-pr-link-remote' + ) + self.assertEqual(len(remote_links), 1) + self.assertIn( + 'sodar-pr-link-remote-master', + remote_links[0].get_attribute('class'), + ) + def test_archive_visibility_default(self): """Test archive icon and alert visibility (should not be visible)""" users = [ @@ -1807,7 +1877,7 @@ def test_remote_field_disable(self): self.remote_project = self.make_remote_project( project_uuid=self.project.sodar_uuid, site=self.remote_site, - level=SODAR_CONSTANTS['REMOTE_LEVEL_READ_ROLES'], + level=REMOTE_LEVEL_READ_ROLES, project=self.project, ) self.login_and_redirect(self.superuser, self.url) @@ -1823,7 +1893,7 @@ def test_remote_field_disable_cancel(self): self.remote_project = self.make_remote_project( project_uuid=self.project.sodar_uuid, site=self.remote_site, - level=SODAR_CONSTANTS['REMOTE_LEVEL_READ_ROLES'], + level=REMOTE_LEVEL_READ_ROLES, project=self.project, ) self.login_and_redirect(self.superuser, self.url) diff --git a/projectroles/views.py b/projectroles/views.py index 35777a8f..e05d5276 100644 --- a/projectroles/views.py +++ b/projectroles/views.py @@ -616,13 +616,22 @@ def get_context_data(self, *args, **kwargs): else: context['role'] = None + # Remote projects + q_kwargs = { + 'project_uuid': self.object.sodar_uuid, + 'level': REMOTE_LEVEL_READ_ROLES, + } + if not self.request.user.has_perm( + 'projectroles.view_hidden_projects', self.object + ): + q_kwargs['site__user_display'] = True if settings.PROJECTROLES_SITE_MODE == SITE_MODE_SOURCE: context['target_projects'] = RemoteProject.objects.filter( - project_uuid=self.object.sodar_uuid, site__mode=SITE_MODE_TARGET + site__mode=SITE_MODE_TARGET, **q_kwargs ).order_by('site__name') elif settings.PROJECTROLES_SITE_MODE == SITE_MODE_TARGET: context['peer_projects'] = RemoteProject.objects.filter( - project_uuid=self.object.sodar_uuid, site__mode=SITE_MODE_PEER + site__mode=SITE_MODE_PEER, **q_kwargs ).order_by('site__name') return context