Skip to content

Commit

Permalink
Merge pull request #721 from UW-GAC/feature/auth-domain-audit-user-fe…
Browse files Browse the repository at this point in the history
…edback

Upload workspace audit - user feedback
  • Loading branch information
amstilp authored Sep 3, 2024
2 parents c7bf1e5 + 3f04ec3 commit d51c74f
Show file tree
Hide file tree
Showing 8 changed files with 326 additions and 32 deletions.
7 changes: 4 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ jobs:
- name: Run tests
run: |
pytest --cov=gregor_django -n auto
mv .coverage .coverage-${{ strategy.job-index }}
mv .coverage coverage-${{ strategy.job-index }}
- name: List files for debugging purposes
run: ls -lhta
Expand All @@ -102,7 +102,8 @@ jobs:
uses: actions/upload-artifact@v4
with:
name: coverage-data-${{ strategy.job-index }}
path: .coverage-${{ strategy.job-index }}
path: coverage-${{ strategy.job-index }}
if-no-files-found: error

coverage:
needs:
Expand All @@ -129,7 +130,7 @@ jobs:

- name: Merge coverage files
run: |
python -m coverage combine ./artifacts/coverage-data*/.coverage-*
python -m coverage combine ./artifacts/coverage-data*/coverage-*
python -m coverage xml
ls -la .coverage*
Expand Down
31 changes: 5 additions & 26 deletions gregor_django/gregor_anvil/audit/upload_workspace_sharing_audit.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,28 +20,18 @@ class UploadWorkspaceSharingAuditResult(GREGoRAuditResult):
action: str = None
current_sharing_instance: WorkspaceGroupSharing = None

def get_action_url(self):
"""The URL that handles the action needed."""
# return reverse(
# "gregor_anvil:audit:upload_workspaces:sharing:resolve",
# args=[
# self.dbgap_application.dbgap_project_id,
# self.workspace.workspace.billing_project.name,
# self.workspace.workspace.name,
# ],
# )
return ""

def get_table_dictionary(self):
"""Return a dictionary that can be used to populate an instance of `dbGaPDataSharingSnapshotAuditTable`."""
can_compute = None
if self.current_sharing_instance and self.current_sharing_instance.access != WorkspaceGroupSharing.READER:
can_compute = self.current_sharing_instance.can_compute
row = {
"workspace": self.workspace,
"managed_group": self.managed_group,
"access": self.current_sharing_instance.access if self.current_sharing_instance else None,
"can_compute": self.current_sharing_instance.can_compute if self.current_sharing_instance else None,
"can_compute": can_compute,
"note": self.note,
"action": self.action,
"action_url": self.get_action_url(),
}
return row

Expand All @@ -50,8 +40,6 @@ def get_table_dictionary(self):
class VerifiedShared(UploadWorkspaceSharingAuditResult):
"""Audit results class for when Sharing has been verified."""

is_shared: bool = True

def __str__(self):
return f"Verified sharing: {self.note}"

Expand All @@ -60,8 +48,6 @@ def __str__(self):
class VerifiedNotShared(UploadWorkspaceSharingAuditResult):
"""Audit results class for when no Sharing has been verified."""

is_shared: bool = False

def __str__(self):
return f"Verified not shared: {self.note}"

Expand All @@ -70,7 +56,6 @@ def __str__(self):
class ShareAsReader(UploadWorkspaceSharingAuditResult):
"""Audit results class for when Sharing should be granted as a reader."""

is_shared: bool = False
action: str = "Share as reader"

def __str__(self):
Expand All @@ -81,7 +66,6 @@ def __str__(self):
class ShareAsWriter(UploadWorkspaceSharingAuditResult):
"""Audit results class for when Sharing should be granted as a writer."""

is_shared: bool = False
action: str = "Share as writer"

def __str__(self):
Expand All @@ -92,7 +76,6 @@ def __str__(self):
class ShareAsOwner(UploadWorkspaceSharingAuditResult):
"""Audit results class for when Sharing should be granted as an owner."""

is_shared: bool = False
action: str = "Share as owner"

def __str__(self):
Expand All @@ -103,7 +86,6 @@ def __str__(self):
class ShareWithCompute(UploadWorkspaceSharingAuditResult):
"""Audit results class for when Sharing should be granted with compute access."""

is_shared: bool = False
action: str = "Share with compute"

def __str__(self):
Expand All @@ -114,7 +96,6 @@ def __str__(self):
class StopSharing(UploadWorkspaceSharingAuditResult):
"""Audit results class for when Sharing should be removed for a known reason."""

is_shared: bool = True
action: str = "Stop sharing"

def __str__(self):
Expand All @@ -133,11 +114,9 @@ class UploadWorkspaceSharingAuditTable(tables.Table):

workspace = tables.Column(linkify=True)
managed_group = tables.Column(linkify=True)
# is_shared = tables.Column()
access = tables.Column(verbose_name="Current access")
can_compute = BooleanIconColumn(show_false_icon=True, null=True)
can_compute = BooleanIconColumn(show_false_icon=True, null=True, true_color="green", false_color="black")
note = tables.Column()
# action = tables.Column()
action = tables.TemplateColumn(
template_name="gregor_anvil/snippets/upload_workspace_sharing_audit_action_button.html"
)
Expand Down
254 changes: 254 additions & 0 deletions gregor_django/gregor_anvil/tests/test_audit.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,148 @@ def test_get_errors_table(self):
self.assertEqual(table.rows[0].get_cell("value"), "c")


class UploadWorkspaceSharingAuditResultTest(TestCase):
"""General tests of the UploadWorkspaceSharingAuditResult dataclasses."""

def test_shared_as_owner(self):
upload_workspace = factories.UploadWorkspaceFactory.create(upload_cycle__is_future=True)
group = ManagedGroupFactory.create()
sharing = WorkspaceGroupSharingFactory.create(
workspace=upload_workspace.workspace, group=group, access=WorkspaceGroupSharing.OWNER, can_compute=True
)
instance = upload_workspace_sharing_audit.UploadWorkspaceSharingAuditResult(
workspace=upload_workspace,
managed_group=group,
current_sharing_instance=sharing,
note="foo",
)
table_dictionary = instance.get_table_dictionary()
self.assertEqual(table_dictionary["access"], sharing.OWNER)
self.assertEqual(table_dictionary["can_compute"], True)

def test_shared_as_writer_with_compute(self):
upload_workspace = factories.UploadWorkspaceFactory.create(upload_cycle__is_future=True)
group = ManagedGroupFactory.create()
sharing = WorkspaceGroupSharingFactory.create(
workspace=upload_workspace.workspace, group=group, access=WorkspaceGroupSharing.WRITER, can_compute=True
)
instance = upload_workspace_sharing_audit.UploadWorkspaceSharingAuditResult(
workspace=upload_workspace,
managed_group=group,
current_sharing_instance=sharing,
note="foo",
)
table_dictionary = instance.get_table_dictionary()
self.assertEqual(table_dictionary["access"], sharing.WRITER)
self.assertEqual(table_dictionary["can_compute"], True)

def test_shared_as_writer_without_compute(self):
upload_workspace = factories.UploadWorkspaceFactory.create(upload_cycle__is_future=True)
group = ManagedGroupFactory.create()
sharing = WorkspaceGroupSharingFactory.create(
workspace=upload_workspace.workspace, group=group, access=WorkspaceGroupSharing.WRITER, can_compute=False
)
instance = upload_workspace_sharing_audit.UploadWorkspaceSharingAuditResult(
workspace=upload_workspace,
managed_group=group,
current_sharing_instance=sharing,
note="foo",
)
table_dictionary = instance.get_table_dictionary()
self.assertEqual(table_dictionary["access"], sharing.WRITER)
self.assertEqual(table_dictionary["can_compute"], False)

def test_shared_as_reader(self):
upload_workspace = factories.UploadWorkspaceFactory.create(upload_cycle__is_future=True)
group = ManagedGroupFactory.create()
sharing = WorkspaceGroupSharingFactory.create(
workspace=upload_workspace.workspace, group=group, access=WorkspaceGroupSharing.READER
)
instance = upload_workspace_sharing_audit.UploadWorkspaceSharingAuditResult(
workspace=upload_workspace,
managed_group=group,
current_sharing_instance=sharing,
note="foo",
)
table_dictionary = instance.get_table_dictionary()
self.assertEqual(table_dictionary["access"], sharing.READER)
self.assertIsNone(table_dictionary["can_compute"])

def test_not_shared(self):
upload_workspace = factories.UploadWorkspaceFactory.create(upload_cycle__is_future=True)
group = ManagedGroupFactory.create()
instance = upload_workspace_sharing_audit.UploadWorkspaceSharingAuditResult(
workspace=upload_workspace,
managed_group=group,
current_sharing_instance=None,
note="foo",
)
table_dictionary = instance.get_table_dictionary()
self.assertIsNone(table_dictionary["access"])
self.assertIsNone(table_dictionary["can_compute"])


class UploadWorkspaceSharingAuditTableTest(TestCase):
"""General tests of the UploadWorkspaceSharingAuditTable class."""

def test_no_rows(self):
"""Table works with no rows."""
table = upload_workspace_sharing_audit.UploadWorkspaceSharingAuditTable([])
self.assertIsInstance(table, upload_workspace_sharing_audit.UploadWorkspaceSharingAuditTable)
self.assertEqual(len(table.rows), 0)

def test_one_row(self):
"""Table works with one row."""
upload_workspace = factories.UploadWorkspaceFactory.create()
group = ManagedGroupFactory.create()
WorkspaceGroupSharingFactory.create(
workspace=upload_workspace.workspace, group=group, access=WorkspaceGroupSharing.READER
)
data = [
{
"workspace": upload_workspace,
"managed_group": group,
"access": WorkspaceGroupSharing.READER,
"can_compute": None,
"note": "a note",
"action": "",
},
]
table = upload_workspace_sharing_audit.UploadWorkspaceSharingAuditTable(data)
self.assertIsInstance(table, upload_workspace_sharing_audit.UploadWorkspaceSharingAuditTable)
self.assertEqual(len(table.rows), 1)

def test_two_rows(self):
"""Table works with two rows."""
upload_workspace = factories.UploadWorkspaceFactory.create()
group_1 = ManagedGroupFactory.create()
group_2 = ManagedGroupFactory.create()
WorkspaceGroupSharingFactory.create(
workspace=upload_workspace.workspace, group=group_1, access=WorkspaceGroupSharing.READER
)
data = [
{
"workspace": upload_workspace,
"managed_group": group_1,
"access": WorkspaceGroupSharing.READER,
"can_compute": None,
"note": "a note",
"action": "",
},
{
"workspace": upload_workspace,
"managed_group": group_2,
"access": None,
"can_compute": None,
"note": "a note",
"action": "",
},
]
table = upload_workspace_sharing_audit.UploadWorkspaceSharingAuditTable(data)
self.assertIsInstance(table, upload_workspace_sharing_audit.UploadWorkspaceSharingAuditTable)
self.assertEqual(len(table.rows), 2)


class UploadWorkspaceSharingAuditTest(TestCase):
"""General tests of the `UploadWorkspaceSharingAudit` class."""

Expand Down Expand Up @@ -3860,6 +4002,118 @@ def test_other_group_shared_as_owner(self):
self.assertEqual(record.note, upload_workspace_sharing_audit.UploadWorkspaceSharingAudit.OTHER_GROUP_NO_ACCESS)


class UploadWorkspaceAuthDomainAuditResultTest(TestCase):
"""General tests of the UploadWorkspaceAuthDomainAuditResult dataclasses."""

def test_member_as_admin(self):
upload_workspace = factories.UploadWorkspaceFactory.create(upload_cycle__is_future=True)
group = ManagedGroupFactory.create()
membership = GroupGroupMembershipFactory.create(
parent_group=upload_workspace.workspace.authorization_domains.first(),
child_group=group,
role=GroupGroupMembership.ADMIN,
)
instance = upload_workspace_auth_domain_audit.UploadWorkspaceAuthDomainAuditResult(
workspace=upload_workspace,
managed_group=group,
current_membership_instance=membership,
note="foo",
)
table_dictionary = instance.get_table_dictionary()
self.assertEqual(table_dictionary["role"], membership.ADMIN)

def test_member_as_member(self):
upload_workspace = factories.UploadWorkspaceFactory.create(upload_cycle__is_future=True)
group = ManagedGroupFactory.create()
membership = GroupGroupMembershipFactory.create(
parent_group=upload_workspace.workspace.authorization_domains.first(),
child_group=group,
role=GroupGroupMembership.MEMBER,
)
instance = upload_workspace_auth_domain_audit.UploadWorkspaceAuthDomainAuditResult(
workspace=upload_workspace,
managed_group=group,
current_membership_instance=membership,
note="foo",
)
table_dictionary = instance.get_table_dictionary()
self.assertEqual(table_dictionary["role"], membership.MEMBER)

def test_not_member(self):
upload_workspace = factories.UploadWorkspaceFactory.create(upload_cycle__is_future=True)
group = ManagedGroupFactory.create()
instance = upload_workspace_auth_domain_audit.UploadWorkspaceAuthDomainAuditResult(
workspace=upload_workspace,
managed_group=group,
current_membership_instance=None,
note="foo",
)
table_dictionary = instance.get_table_dictionary()
self.assertIsNone(table_dictionary["role"])


class UploadWorkspaceAuthDomainAuditTableTest(TestCase):
"""General tests of the UploadWorkspaceAuthDomainAuditTable class."""

def test_no_rows(self):
"""Table works with no rows."""
table = upload_workspace_auth_domain_audit.UploadWorkspaceAuthDomainAuditTable([])
self.assertIsInstance(table, upload_workspace_auth_domain_audit.UploadWorkspaceAuthDomainAuditTable)
self.assertEqual(len(table.rows), 0)

def test_one_row(self):
"""Table works with one row."""
upload_workspace = factories.UploadWorkspaceFactory.create()
group = ManagedGroupFactory.create()
GroupGroupMembershipFactory.create(
parent_group=upload_workspace.workspace.authorization_domains.first(),
child_group=group,
role=GroupGroupMembership.MEMBER,
)
data = [
{
"workspace": upload_workspace,
"managed_group": group,
"role": GroupGroupMembership.MEMBER,
"note": "a note",
"action": "",
},
]
table = upload_workspace_auth_domain_audit.UploadWorkspaceAuthDomainAuditTable(data)
self.assertIsInstance(table, upload_workspace_auth_domain_audit.UploadWorkspaceAuthDomainAuditTable)
self.assertEqual(len(table.rows), 1)

def test_two_rows(self):
"""Table works with two rows."""
upload_workspace = factories.UploadWorkspaceFactory.create()
group_1 = ManagedGroupFactory.create()
group_2 = ManagedGroupFactory.create()
GroupGroupMembershipFactory.create(
parent_group=upload_workspace.workspace.authorization_domains.first(),
child_group=group_1,
role=GroupGroupMembership.MEMBER,
)
data = [
{
"workspace": upload_workspace,
"managed_group": group_1,
"role": GroupGroupMembership.MEMBER,
"note": "a note",
"action": "",
},
{
"workspace": upload_workspace,
"managed_group": group_2,
"role": None,
"note": "a note",
"action": "",
},
]
table = upload_workspace_auth_domain_audit.UploadWorkspaceAuthDomainAuditTable(data)
self.assertIsInstance(table, upload_workspace_auth_domain_audit.UploadWorkspaceAuthDomainAuditTable)
self.assertEqual(len(table.rows), 2)


class UploadWorkspaceAuthDomainAuditTest(TestCase):
"""General tests of the `UploadWorkspaceAuthDomainAudit` class."""

Expand Down
Loading

0 comments on commit d51c74f

Please sign in to comment.