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

dbGaP application views for PIs #599

Merged
merged 41 commits into from
Jun 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
0215478
Allow a dbGaP PI to view their dbGaP application detail view
amstilp Jun 6, 2024
e8eaae0
Allow dbGaP PIs to see DAR snapshots for their application
amstilp Jun 6, 2024
014e538
Reduce database queries in dbGaP Detail views
amstilp Jun 6, 2024
f4bbec4
Allow dbGaP PIs to see the DAR history page
amstilp Jun 6, 2024
31a6873
Show PI name instead of username in dbGaP application
amstilp Jun 7, 2024
2721588
Add link to PI user profile on dbGaP application page
amstilp Jun 7, 2024
1a53c66
Track collaborators associated with a dbGaP application
amstilp Jun 7, 2024
1f1b58e
Switch dbGaPApplicationDetail view to use MultiTableMixin
amstilp Jun 7, 2024
1d99d30
Add a table to show User, account, and group membership
amstilp Jun 7, 2024
8c8e4dc
Add a table of collaborators to the dbGaPApplicationDetail page
amstilp Jun 7, 2024
03a5879
Add form and view to update dbGaP application collaborators
amstilp Jun 7, 2024
19cd56c
Change collaborators widget to autocomplete selector
amstilp Jun 7, 2024
7edb105
Start reworking audit namespaces
amstilp Jun 10, 2024
0c93614
Move dbGaP audit code into its own subdirectory
amstilp Jun 11, 2024
fa255f4
Add skeleton classes for collaborator audits
amstilp Jun 11, 2024
068e138
Add initial auditing classes for dbGaPCollaboratorAudit
amstilp Jun 12, 2024
9900d19
Rename access audit templates for clarity
amstilp Jun 12, 2024
b79340c
Change collaborator to user in audit result classes
amstilp Jun 13, 2024
9339fee
Add definition and tests for dbGaPCollaboratorAudit view
amstilp Jun 13, 2024
12095a8
Add a method to audit an application and a group
amstilp Jun 13, 2024
7e2268a
Dispatch audit based on object type using an internal method
amstilp Jun 13, 2024
15455fa
Use case-insensitive strings when looking up objects by email
amstilp Jun 13, 2024
7a112a1
Add view to resolve collaborator audits
amstilp Jun 13, 2024
90df70b
Use admins group in settings file in audits
amstilp Jun 13, 2024
8130caa
Add tests for collaborator audit result classes
amstilp Jun 13, 2024
4c9b194
Limit the number of pytest-xdist workers to 4
amstilp Jun 14, 2024
e2a3eab
Add tests for the dbGaPCollaboratorAuditTable
amstilp Jun 14, 2024
cbd3f05
Run the collaborator audit as part of the run_dbgap_audit command
amstilp Jun 14, 2024
e72ccc6
Clean up test coverage
amstilp Jun 14, 2024
d2cc1da
Allow collaborators on dbGaP applications to see info
amstilp Jun 14, 2024
3f608b5
Update language on templates
amstilp Jun 14, 2024
0c0ec2d
Add collaborator audit to navbar
amstilp Jun 14, 2024
31331f3
Add phenotype inventory link to navbar
amstilp Jun 14, 2024
216c78f
Add tests for collaborator links on dbGaPApplicationDetail view
amstilp Jun 14, 2024
fecded2
Add dbGaP application info to user profile
amstilp Jun 18, 2024
746736a
Clean up test coverage
amstilp Jun 18, 2024
308e988
Fix url in run_collaborative_analysis_audit
amstilp Jun 18, 2024
6619790
Fix accordion ids and collapse targets
amstilp Jun 18, 2024
9edcecc
Add statement when there are no associated dbGaP apps
amstilp Jun 18, 2024
4e4d9d2
Allow staff view users to see data access mechanisms
amstilp Jun 18, 2024
d96949e
Add CDSA "coming soon" to profile page
amstilp Jun 18, 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
3 changes: 2 additions & 1 deletion primed/collaborative_analysis/audit.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
GroupGroupMembership,
ManagedGroup,
)
from django.conf import settings
from django.urls import reverse

from primed.primed_anvil.audit import PRIMEDAudit, PRIMEDAuditResult
Expand Down Expand Up @@ -176,7 +177,7 @@ def _audit_workspace(self, workspace):
)
.exclude(
# Ignore cc admins group - it is handled differently because it should have admin privileges.
child_group__name="PRIMED_CC_ADMINS",
child_group__name=settings.ANVIL_CC_ADMINS_GROUP_NAME,
)
.exclude(
# Ignore allowed groups - they will be checked separately later.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def handle(self, *args, **options):
# Report errors and needs access.
audit_ok = data_access_audit.ok()
# Construct the url for handling errors.
url = "https://" + Site.objects.get_current().domain + reverse("dbgap:audit:all")
url = "https://" + Site.objects.get_current().domain + reverse("collaborative_analysis:audit:all")
if audit_ok:
self.stdout.write(self.style.SUCCESS("ok!"))
else:
Expand Down
19 changes: 17 additions & 2 deletions primed/collaborative_analysis/tests/test_audit.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
WorkspaceAuthorizationDomainFactory,
WorkspaceFactory,
)
from django.test import TestCase
from django.test import TestCase, override_settings
from django.urls import reverse

from primed.cdsa.tests.factories import CDSAWorkspaceFactory
Expand Down Expand Up @@ -845,7 +845,22 @@ def test_unexpected_group_in_auth_domain(self):
def test_ignores_primed_admins_group(self):
workspace = factories.CollaborativeAnalysisWorkspaceFactory.create()
# Add a group to the auth domain.
group = ManagedGroupFactory.create(name="PRIMED_CC_ADMINS")
group = ManagedGroupFactory.create(name="TEST_PRIMED_CC_ADMINS")
GroupGroupMembershipFactory.create(
parent_group=workspace.workspace.authorization_domains.first(),
child_group=group,
)
collab_audit = audit.CollaborativeAnalysisWorkspaceAccessAudit()
collab_audit._audit_workspace(workspace)
self.assertEqual(len(collab_audit.verified), 0)
self.assertEqual(len(collab_audit.needs_action), 0)
self.assertEqual(len(collab_audit.errors), 0)

@override_settings(ANVIL_CC_ADMINS_GROUP_NAME="FOOBAR")
def test_ignores_primed_admins_group_different_setting(self):
workspace = factories.CollaborativeAnalysisWorkspaceFactory.create()
# Add a group to the auth domain.
group = ManagedGroupFactory.create(name="FOOBAR")
GroupGroupMembershipFactory.create(
parent_group=workspace.workspace.authorization_domains.first(),
child_group=group,
Expand Down
2 changes: 1 addition & 1 deletion primed/collaborative_analysis/tests/test_commands.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""Tests for management commands in the `dbgap` app."""
"""Tests for management commands in the `collaborative_analysis` app."""

from io import StringIO

Expand Down
Empty file added primed/dbgap/audit/__init__.py
Empty file.
18 changes: 9 additions & 9 deletions primed/dbgap/audit.py → primed/dbgap/audit/access_audit.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from primed.primed_anvil.audit import PRIMEDAudit, PRIMEDAuditResult
from primed.primed_anvil.tables import BooleanIconColumn

from .models import (
from ..models import (
dbGaPApplication,
dbGaPDataAccessRequest,
dbGaPDataAccessSnapshot,
Expand All @@ -17,7 +17,7 @@

# Dataclasses for storing audit results?
@dataclass
class AuditResult(PRIMEDAuditResult):
class AccessAuditResult(PRIMEDAuditResult):
"""Base class to hold results for auditing dbGaP workspace access for a dbGaPDataAccessSnapshot."""

workspace: dbGaPWorkspace
Expand All @@ -36,7 +36,7 @@ def __post_init__(self):
def get_action_url(self):
"""The URL that handles the action needed."""
return reverse(
"dbgap:audit:resolve",
"dbgap:audit:access:resolve",
args=[
self.dbgap_application.dbgap_project_id,
self.workspace.workspace.billing_project.name,
Expand Down Expand Up @@ -67,7 +67,7 @@ def get_table_dictionary(self):


@dataclass
class VerifiedAccess(AuditResult):
class VerifiedAccess(AccessAuditResult):
"""Audit results class for when access has been verified."""

has_access: bool = True
Expand All @@ -77,7 +77,7 @@ def __str__(self):


@dataclass
class VerifiedNoAccess(AuditResult):
class VerifiedNoAccess(AccessAuditResult):
"""Audit results class for when no access has been verified."""

has_access: bool = False
Expand All @@ -87,7 +87,7 @@ def __str__(self):


@dataclass
class GrantAccess(AuditResult):
class GrantAccess(AccessAuditResult):
"""Audit results class for when access should be granted."""

has_access: bool = False
Expand All @@ -98,7 +98,7 @@ def __str__(self):


@dataclass
class RemoveAccess(AuditResult):
class RemoveAccess(AccessAuditResult):
"""Audit results class for when access should be removed for a known reason."""

has_access: bool = True
Expand All @@ -109,7 +109,7 @@ def __str__(self):


@dataclass
class Error(AuditResult):
class Error(AccessAuditResult):
"""Audit results class for when an error has been detected (e.g., has access and never should have)."""

pass
Expand All @@ -125,7 +125,7 @@ class dbGaPAccessAuditTable(tables.Table):
dar_consent = tables.Column(verbose_name="DAR consent")
has_access = BooleanIconColumn(show_false_icon=True)
note = tables.Column()
action = tables.TemplateColumn(template_name="dbgap/snippets/dbgap_audit_action_button.html")
action = tables.TemplateColumn(template_name="dbgap/snippets/dbgap_access_audit_action_button.html")

class Meta:
attrs = {"class": "table align-middle"}
Expand Down
Loading