Skip to content

Commit

Permalink
Merge pull request #639 from UW-GAC/main
Browse files Browse the repository at this point in the history
Deploy to stage
  • Loading branch information
amstilp authored Jul 3, 2024
2 parents 199063d + a6e07fd commit 6768282
Show file tree
Hide file tree
Showing 14 changed files with 671 additions and 25 deletions.
7 changes: 4 additions & 3 deletions primed/cdsa/adapters.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
from anvil_consortium_manager.adapters.workspace import BaseWorkspaceAdapter
from anvil_consortium_manager.forms import WorkspaceForm
from anvil_consortium_manager.models import Workspace

from primed.miscellaneous_workspaces.tables import DataPrepWorkspaceUserTable
from primed.primed_anvil.adapters import WorkspaceAdminSharingAdapterMixin, WorkspaceAuthDomainAdapterMixin
from primed.primed_anvil.forms import WorkspaceAuthDomainDisabledForm

from . import forms, models, tables


class CDSAWorkspaceAdapter(BaseWorkspaceAdapter):
class CDSAWorkspaceAdapter(WorkspaceAuthDomainAdapterMixin, WorkspaceAdminSharingAdapterMixin, BaseWorkspaceAdapter):
"""Adapter for CDSAWorkspaces."""

type = "cdsa"
name = "CDSA workspace"
description = "Workspaces containing data from the Consortium Data Sharing Agreement"
list_table_class_staff_view = tables.CDSAWorkspaceStaffTable
list_table_class_view = tables.CDSAWorkspaceUserTable
workspace_form_class = WorkspaceForm
workspace_form_class = WorkspaceAuthDomainDisabledForm
workspace_data_model = models.CDSAWorkspace
workspace_data_form_class = forms.CDSAWorkspaceForm
workspace_detail_template_name = "cdsa/cdsaworkspace_detail.html"
Expand Down
122 changes: 121 additions & 1 deletion primed/cdsa/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
GroupGroupMembership,
ManagedGroup,
Workspace,
WorkspaceGroupSharing,
)
from anvil_consortium_manager.tests.api_factories import ErrorResponseFactory
from anvil_consortium_manager.tests.factories import (
Expand Down Expand Up @@ -10262,30 +10263,65 @@ def setUp(self):
)
self.requester = UserFactory.create()
self.workspace_type = "cdsa"
# Create the admins group.
ManagedGroupFactory.create(name=settings.ANVIL_CC_ADMINS_GROUP_NAME)

def get_url(self, *args):
"""Get the url for the view being tested."""
return reverse("anvil_consortium_manager:workspaces:new", args=args)

def test_creates_upload_workspace_without_duos(self):
def test_creates_workspace(self):
"""Posting valid data to the form creates a workspace data object when using a custom adapter."""
study = factories.StudyFactory.create()
duo_permission = DataUsePermissionFactory.create()
# Create an extra that won't be specified.
DataUseModifierFactory.create()
billing_project = BillingProjectFactory.create(name="test-billing-project")
# API response for workspace creation.
url = self.api_client.rawls_entry_point + "/api/workspaces"
json_data = {
"namespace": "test-billing-project",
"name": "test-workspace",
"attributes": {},
"authorizationDomain": [{"membersGroupName": "AUTH_test-workspace"}],
}
self.anvil_response_mock.add(
responses.POST,
url,
status=self.api_success_code,
match=[responses.matchers.json_params_matcher(json_data)],
)
# API response for auth domain ManagedGroup creation.
self.anvil_response_mock.add(
responses.POST,
self.api_client.sam_entry_point + "/api/groups/v1/AUTH_test-workspace",
status=self.api_success_code,
)
# API response for auth domain PRIMED_ADMINS membership.
self.anvil_response_mock.add(
responses.PUT,
self.api_client.sam_entry_point
+ "/api/groups/v1/AUTH_test-workspace/admin/[email protected]",
status=204,
)
# API response for PRIMED_ADMINS workspace owner.
acls = [
{
"email": "[email protected]",
"accessLevel": "OWNER",
"canShare": False,
"canCompute": True,
}
]
self.anvil_response_mock.add(
responses.PATCH,
self.api_client.rawls_entry_point
+ "/api/workspaces/test-billing-project/test-workspace/acl?inviteUsersNotFound=false",
status=200,
match=[responses.matchers.json_params_matcher(acls)],
json={"invitesSent": {}, "usersNotFound": {}, "usersUpdated": acls},
)
# Make the post request
self.client.force_login(self.user)
response = self.client.post(
self.get_url(self.workspace_type),
Expand Down Expand Up @@ -10315,6 +10351,24 @@ def test_creates_upload_workspace_without_duos(self):
self.assertEqual(new_workspace_data.data_use_permission, duo_permission)
self.assertEqual(new_workspace_data.acknowledgments, "test acknowledgments")
self.assertEqual(new_workspace_data.requested_by, self.requester)
# Check that auth domain exists.
self.assertEqual(new_workspace.authorization_domains.count(), 1)
auth_domain = new_workspace.authorization_domains.first()
self.assertEqual(auth_domain.name, "AUTH_test-workspace")
self.assertTrue(auth_domain.is_managed_by_app)
self.assertEqual(auth_domain.email, "[email protected]")
# Check that auth domain admin is correct.
membership = GroupGroupMembership.objects.get(
parent_group=auth_domain, child_group__name="TEST_PRIMED_CC_ADMINS"
)
self.assertEqual(membership.role, membership.ADMIN)
# Check that workspace sharing is correct.
sharing = WorkspaceGroupSharing.objects.get(
workspace=new_workspace,
group__name="TEST_PRIMED_CC_ADMINS",
)
self.assertEqual(sharing.access, sharing.OWNER)
self.assertEqual(sharing.can_compute, True)

def test_creates_upload_workspace_with_duo_modifiers(self):
"""Posting valid data to the form creates a workspace data object when using a custom adapter."""
Expand All @@ -10325,18 +10379,51 @@ def test_creates_upload_workspace_with_duo_modifiers(self):
# Create an extra that won't be specified.
DataUseModifierFactory.create()
billing_project = BillingProjectFactory.create(name="test-billing-project")
# API response for workspace creation.
url = self.api_client.rawls_entry_point + "/api/workspaces"
json_data = {
"namespace": "test-billing-project",
"name": "test-workspace",
"attributes": {},
"authorizationDomain": [{"membersGroupName": "AUTH_test-workspace"}],
}
self.anvil_response_mock.add(
responses.POST,
url,
status=self.api_success_code,
match=[responses.matchers.json_params_matcher(json_data)],
)
# API response for auth domain ManagedGroup creation.
self.anvil_response_mock.add(
responses.POST,
self.api_client.sam_entry_point + "/api/groups/v1/AUTH_test-workspace",
status=self.api_success_code,
)
# API response for auth domain PRIMED_ADMINS membership.
self.anvil_response_mock.add(
responses.PUT,
self.api_client.sam_entry_point
+ "/api/groups/v1/AUTH_test-workspace/admin/[email protected]",
status=204,
)
# API response for PRIMED_ADMINS workspace owner.
acls = [
{
"email": "[email protected]",
"accessLevel": "OWNER",
"canShare": False,
"canCompute": True,
}
]
self.anvil_response_mock.add(
responses.PATCH,
self.api_client.rawls_entry_point
+ "/api/workspaces/test-billing-project/test-workspace/acl?inviteUsersNotFound=false",
status=200,
match=[responses.matchers.json_params_matcher(acls)],
json={"invitesSent": {}, "usersNotFound": {}, "usersUpdated": acls},
)
# Make the post request
self.client.force_login(self.user)
response = self.client.post(
self.get_url(self.workspace_type),
Expand Down Expand Up @@ -10371,18 +10458,51 @@ def test_creates_upload_workspace_with_disease_term(self):
data_use_permission = DataUsePermissionFactory.create(requires_disease_term=True)
# Create an extra that won't be specified.
billing_project = BillingProjectFactory.create(name="test-billing-project")
# API response for workspace creation.
url = self.api_client.rawls_entry_point + "/api/workspaces"
json_data = {
"namespace": "test-billing-project",
"name": "test-workspace",
"attributes": {},
"authorizationDomain": [{"membersGroupName": "AUTH_test-workspace"}],
}
self.anvil_response_mock.add(
responses.POST,
url,
status=self.api_success_code,
match=[responses.matchers.json_params_matcher(json_data)],
)
# API response for auth domain ManagedGroup creation.
self.anvil_response_mock.add(
responses.POST,
self.api_client.sam_entry_point + "/api/groups/v1/AUTH_test-workspace",
status=self.api_success_code,
)
# API response for auth domain PRIMED_ADMINS membership.
self.anvil_response_mock.add(
responses.PUT,
self.api_client.sam_entry_point
+ "/api/groups/v1/AUTH_test-workspace/admin/[email protected]",
status=204,
)
# API response for PRIMED_ADMINS workspace owner.
acls = [
{
"email": "[email protected]",
"accessLevel": "OWNER",
"canShare": False,
"canCompute": True,
}
]
self.anvil_response_mock.add(
responses.PATCH,
self.api_client.rawls_entry_point
+ "/api/workspaces/test-billing-project/test-workspace/acl?inviteUsersNotFound=false",
status=200,
match=[responses.matchers.json_params_matcher(acls)],
json={"invitesSent": {}, "usersNotFound": {}, "usersUpdated": acls},
)
# Make the post request
self.client.force_login(self.user)
response = self.client.post(
self.get_url(self.workspace_type),
Expand Down
12 changes: 9 additions & 3 deletions primed/collaborative_analysis/adapters.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
from anvil_consortium_manager.adapters.workspace import BaseWorkspaceAdapter
from anvil_consortium_manager.forms import WorkspaceForm

from primed.primed_anvil.adapters import WorkspaceAdminSharingAdapterMixin, WorkspaceAuthDomainAdapterMixin
from primed.primed_anvil.forms import WorkspaceAuthDomainDisabledForm

from . import forms, models, tables


class CollaborativeAnalysisWorkspaceAdapter(BaseWorkspaceAdapter):
class CollaborativeAnalysisWorkspaceAdapter(
WorkspaceAuthDomainAdapterMixin,
WorkspaceAdminSharingAdapterMixin,
BaseWorkspaceAdapter,
):
"""Adapter for CollaborativeAnalysisWorkspace."""

type = "collab_analysis"
name = "Collaborative Analysis workspace"
description = "Workspaces used for collaborative analyses"
list_table_class_staff_view = tables.CollaborativeAnalysisWorkspaceStaffTable
list_table_class_view = tables.CollaborativeAnalysisWorkspaceUserTable
workspace_form_class = WorkspaceForm
workspace_form_class = WorkspaceAuthDomainDisabledForm
workspace_data_model = models.CollaborativeAnalysisWorkspace
workspace_data_form_class = forms.CollaborativeAnalysisWorkspaceForm
workspace_detail_template_name = "collaborative_analysis/collaborativeanalysisworkspace_detail.html"
66 changes: 66 additions & 0 deletions primed/collaborative_analysis/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
GroupAccountMembership,
GroupGroupMembership,
Workspace,
WorkspaceGroupSharing,
)
from anvil_consortium_manager.tests.api_factories import ErrorResponseFactory
from anvil_consortium_manager.tests.factories import (
Expand Down Expand Up @@ -186,6 +187,8 @@ def setUp(self):
self.custodian = UserFactory.create()
self.source_workspace = dbGaPWorkspaceFactory.create().workspace
self.analyst_group = ManagedGroupFactory.create()
# Create the admins group.
self.admins_group = ManagedGroupFactory.create(name=settings.ANVIL_CC_ADMINS_GROUP_NAME)

def get_url(self, *args):
"""Get the url for the view being tested."""
Expand All @@ -194,18 +197,63 @@ def get_url(self, *args):
def test_creates_workspace(self):
"""Posting valid data to the form creates a workspace data object when using a custom adapter."""
billing_project = BillingProjectFactory.create(name="test-billing-project")
# url = self.api_client.rawls_entry_point + "/api/workspaces"
# json_data = {
# "namespace": "test-billing-project",
# "name": "test-workspace",
# "attributes": {},
# }
# self.anvil_response_mock.add(
# responses.POST,
# url,
# status=self.api_success_code,
# match=[responses.matchers.json_params_matcher(json_data)],
# )
# API response for workspace creation.
url = self.api_client.rawls_entry_point + "/api/workspaces"
json_data = {
"namespace": "test-billing-project",
"name": "test-workspace",
"attributes": {},
"authorizationDomain": [{"membersGroupName": "AUTH_test-workspace"}],
}
self.anvil_response_mock.add(
responses.POST,
url,
status=self.api_success_code,
match=[responses.matchers.json_params_matcher(json_data)],
)
# API response for auth domain ManagedGroup creation.
self.anvil_response_mock.add(
responses.POST,
self.api_client.sam_entry_point + "/api/groups/v1/AUTH_test-workspace",
status=self.api_success_code,
)
# API response for auth domain PRIMED_ADMINS membership.
self.anvil_response_mock.add(
responses.PUT,
self.api_client.sam_entry_point
+ "/api/groups/v1/AUTH_test-workspace/admin/[email protected]",
status=204,
)
# API response for PRIMED_ADMINS workspace owner.
acls = [
{
"email": "[email protected]",
"accessLevel": "OWNER",
"canShare": False,
"canCompute": True,
}
]
self.anvil_response_mock.add(
responses.PATCH,
self.api_client.rawls_entry_point
+ "/api/workspaces/test-billing-project/test-workspace/acl?inviteUsersNotFound=false",
status=200,
match=[responses.matchers.json_params_matcher(acls)],
json={"invitesSent": {}, "usersNotFound": {}, "usersUpdated": acls},
)
# Make the post request
self.client.force_login(self.user)
response = self.client.post(
self.get_url(self.workspace_type),
Expand All @@ -230,6 +278,24 @@ def test_creates_workspace(self):
self.assertEqual(models.CollaborativeAnalysisWorkspace.objects.count(), 1)
new_workspace_data = models.CollaborativeAnalysisWorkspace.objects.latest("pk")
self.assertEqual(new_workspace_data.workspace, new_workspace)
# Check that auth domain exists.
self.assertEqual(new_workspace.authorization_domains.count(), 1)
auth_domain = new_workspace.authorization_domains.first()
self.assertEqual(auth_domain.name, "AUTH_test-workspace")
self.assertTrue(auth_domain.is_managed_by_app)
self.assertEqual(auth_domain.email, "[email protected]")
# Check that auth domain admin is correct.
membership = GroupGroupMembership.objects.get(
parent_group=auth_domain, child_group__name="TEST_PRIMED_CC_ADMINS"
)
self.assertEqual(membership.role, membership.ADMIN)
# Check that workspace sharing is correct.
sharing = WorkspaceGroupSharing.objects.get(
workspace=new_workspace,
group__name="TEST_PRIMED_CC_ADMINS",
)
self.assertEqual(sharing.access, sharing.OWNER)
self.assertEqual(sharing.can_compute, True)


class CollaborativeAnalysisWorkspaceImportTest(AnVILAPIMockTestMixin, TestCase):
Expand Down
7 changes: 4 additions & 3 deletions primed/dbgap/adapters.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
from anvil_consortium_manager.adapters.workspace import BaseWorkspaceAdapter
from anvil_consortium_manager.forms import WorkspaceForm
from anvil_consortium_manager.models import Workspace

from primed.miscellaneous_workspaces.tables import DataPrepWorkspaceUserTable
from primed.primed_anvil.adapters import WorkspaceAdminSharingAdapterMixin, WorkspaceAuthDomainAdapterMixin
from primed.primed_anvil.forms import WorkspaceAuthDomainDisabledForm

from . import forms, models, tables


class dbGaPWorkspaceAdapter(BaseWorkspaceAdapter):
class dbGaPWorkspaceAdapter(WorkspaceAuthDomainAdapterMixin, WorkspaceAdminSharingAdapterMixin, BaseWorkspaceAdapter):
"""Adapter for dbGaPWorkspaces."""

type = "dbgap"
name = "dbGaP workspace"
description = "Workspaces containing data from released dbGaP accessions"
list_table_class_staff_view = tables.dbGaPWorkspaceStaffTable
list_table_class_view = tables.dbGaPWorkspaceUserTable
workspace_form_class = WorkspaceForm
workspace_form_class = WorkspaceAuthDomainDisabledForm
workspace_data_model = models.dbGaPWorkspace
workspace_data_form_class = forms.dbGaPWorkspaceForm
workspace_detail_template_name = "dbgap/dbgapworkspace_detail.html"
Expand Down
Loading

0 comments on commit 6768282

Please sign in to comment.