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

Deploy to stage #639

Merged
merged 19 commits into from
Jul 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
1f15ded
Remove debugging print statement in template
amstilp Jul 1, 2024
0e9e593
Merge pull request #636 from UW-GAC/bugfix/remove-stray-print-in-temp…
amstilp Jul 1, 2024
1d7dd85
Use temporary version of ACM in requirements file
amstilp Jul 2, 2024
54c5ddb
Add a custom WorkspaceForm with auth domain disabled
amstilp Jul 2, 2024
bbfe205
Add skeleton methods to CDSAWorkspace adapter
amstilp Jul 2, 2024
a8a09e6
Automate some CDSA workspace creation tasks
amstilp Jul 2, 2024
fe36463
Add tests specifically for the adapter methods
amstilp Jul 2, 2024
ca3c00c
Update adapter method names based on new ACM changes
amstilp Jul 2, 2024
b6bef3b
Split adapter behavior into reusable mixins
amstilp Jul 2, 2024
4f6faf9
Use new adapter behaviors for dbGaPWorkspaces
amstilp Jul 3, 2024
e89f8dd
Use the adapter behaviors for CollaborativeAnalysisWorkspaces
amstilp Jul 3, 2024
d3474d9
Use the WorkspaceAuthDomainDisabled form for dbGaP and collab adapters
amstilp Jul 3, 2024
7720627
Automatically share all other workspaces with admins group
amstilp Jul 3, 2024
8314a91
Rename adapter mixins to have Mixin in the class name
amstilp Jul 3, 2024
0b743a3
Move adapter mixin tests into a general test file
amstilp Jul 3, 2024
1ab1105
Update requirements.in file with new ACM version
amstilp Jul 3, 2024
2c521ed
Compile requirements files
amstilp Jul 3, 2024
242fba8
Merge pull request #638 from UW-GAC/pip-tools/update-requirements-fil…
amstilp Jul 3, 2024
a6e07fd
Merge pull request #637 from UW-GAC/feature/acm-v0.24-and-custom-adap…
amstilp Jul 3, 2024
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
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/TEST_PRIMED_CC_ADMINS@firecloud.org",
status=204,
)
# API response for PRIMED_ADMINS workspace owner.
acls = [
{
"email": "TEST_PRIMED_CC_ADMINS@firecloud.org",
"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, "AUTH_test-workspace@firecloud.org")
# 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/TEST_PRIMED_CC_ADMINS@firecloud.org",
status=204,
)
# API response for PRIMED_ADMINS workspace owner.
acls = [
{
"email": "TEST_PRIMED_CC_ADMINS@firecloud.org",
"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/TEST_PRIMED_CC_ADMINS@firecloud.org",
status=204,
)
# API response for PRIMED_ADMINS workspace owner.
acls = [
{
"email": "TEST_PRIMED_CC_ADMINS@firecloud.org",
"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/TEST_PRIMED_CC_ADMINS@firecloud.org",
status=204,
)
# API response for PRIMED_ADMINS workspace owner.
acls = [
{
"email": "TEST_PRIMED_CC_ADMINS@firecloud.org",
"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, "AUTH_test-workspace@firecloud.org")
# 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