Skip to content

Commit

Permalink
fix detail view REVOKED project visibility, refactor (#1432)
Browse files Browse the repository at this point in the history
  • Loading branch information
mikkonie committed Jun 18, 2024
1 parent 6074417 commit faf0257
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 95 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand All @@ -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)
Expand Down
25 changes: 13 additions & 12 deletions projectroles/templates/projectroles/project_detail.html
Original file line number Diff line number Diff line change
Expand Up @@ -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 %}
Expand All @@ -20,8 +19,7 @@
<div class="container-fluid sodar-page-container">
{# 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 %}
<div class="card" id="sodar-pr-details-card-remote">
<div class="card-header">
<h4>
Expand All @@ -30,7 +28,7 @@ <h4>
</h4>
</div>
<div class="card-body pb-2 mr-2">
{% for rp in visible_target_projects %}
{% for rp in target_projects %}
<a class="btn {% if rp.site.user_display %}btn-info{% else %}btn-secondary{% endif %} mr-1 mb-1"
href="{{ rp.site.get_url }}{% url 'projectroles:detail' project=object.sodar_uuid %}"
role="button"
Expand All @@ -42,11 +40,13 @@ <h4>
{% endfor %}
</div>
</div>

{% elif object.is_remote %}
<div class="card" id="sodar-pr-details-card-remote">
<div class="card-header">
<h4><i class="iconify" data-icon="mdi:cloud"></i> {% get_display_name object.type title=True %} on Other Sites</h4>
<h4>
<i class="iconify" data-icon="mdi:cloud"></i>
{% get_display_name object.type title=True %} on Other Sites
</h4>
</div>
<div class="card-body pb-2 mr-2">
<a class="btn btn-info mb-1 sodar-pr-link-remote sodar-pr-link-remote-master"
Expand All @@ -55,17 +55,18 @@ <h4><i class="iconify" data-icon="mdi:cloud"></i> {% get_display_name object.typ
title="{% if object.get_source_site.description %}{{ object.get_source_site.description }}{% endif %}"
data-toggle="tooltip"
target="_blank">
<i class="iconify" data-icon="mdi:cloud-outline"></i> {{ object.get_source_site.name }} (Master Project)
<i class="iconify" data-icon="mdi:cloud-outline"></i>
{{ object.get_source_site.name }}
(Source {% get_display_name object.type title=True %})
</a>
{% get_visible_projects peer_projects can_view_hidden_projects as visible_peer_projects %}
{% for peer_p in visible_peer_projects %}
{% for rp in peer_projects %}
<a class="btn btn-info mb-1 sodar-pr-link-remote sodar-pr-link-remote-peer"
href="{{ peer_p.site.get_url }}{% url 'projectroles:detail' project=peer_p.sodar_uuid %}"
href="{{ rp.site.get_url }}{% url 'projectroles:detail' project=rp.sodar_uuid %}"
role="button"
title="{% if peer_p.site.description %}{{ peer_p.site.description }}{% endif %}"
title="{% if rp.site.description %}{{ peer_p.site.description }}{% endif %}"
data-toggle="tooltip"
target="_blank">
<i class="iconify" data-icon="mdi:cloud-outline"></i> {{ peer_p.site.name }}
<i class="iconify" data-icon="mdi:cloud-outline"></i> {{ rp.site.name }}
</a>
{% endfor %}
</div>
Expand Down
11 changes: 0 additions & 11 deletions projectroles/templatetags/projectroles_common_tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"""
Expand Down
50 changes: 1 addition & 49 deletions projectroles/tests/test_templatetags.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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**'
Expand Down
112 changes: 91 additions & 21 deletions projectroles/tests/test_ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 = [
Expand Down Expand Up @@ -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(
Expand All @@ -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,
)

Expand Down Expand Up @@ -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,
Expand All @@ -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(
Expand All @@ -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):
Expand All @@ -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(
Expand All @@ -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',
Expand All @@ -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)
Expand Down Expand Up @@ -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',
Expand All @@ -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(
Expand Down Expand Up @@ -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 = [
Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand Down
Loading

0 comments on commit faf0257

Please sign in to comment.