Repository: Sage-Bionetworks/challengeutils

Issue:
`--admin` check for `validate-project` does not work as expected
**Describe the bug**

The project associated with submission ID 9731653 is a publicly accessible Synapse project, but comes back as INVALID when `--admin <some user/team>` is flagged. e.g.

```
$ challengeutils validate-project 9731653 syn28590455 --admin "RARE-X Organizers"
INFO:challengeutils.__main__:{'submission_errors': 'Project is private; please update its sharing settings. Writeup should be shared with RARE-X Organizers.', 'submission_status': 'INVALID'}
```

**Expected behavior**
Because the project is publicly accessible, the submission should come back as VALID, since the admin team could technically view the project.


**Priority**
High - needed for the RARE-X challenge which will open soon.

Comments:

Patch:
diff --git a/challengeutils/submission.py b/challengeutils/submission.py
index 6a625d0..3c3c74e 100644
--- a/challengeutils/submission.py
+++ b/challengeutils/submission.py
@@ -103,18 +103,14 @@ def validate_project(syn, submission, challenge, public=False, admin=None):
     """
     writeup = syn.getSubmission(submission)
     errors = []
-
     type_error = _validate_ent_type(writeup)
     if type_error:
         errors.append(type_error)
-
     contents_error = _validate_project_id(writeup, challenge)
     if contents_error:
         errors.append(contents_error)
-
     permissions_error = _check_project_permissions(syn, writeup, public, admin)
     errors.extend(permissions_error)
-
     status = "INVALID" if errors else "VALIDATED"
     return {"submission_errors": "\n".join(errors), "submission_status": status}
 
@@ -142,7 +138,6 @@ def archive_project(syn, submission, admin):
 # TODO: move to utils module
 def _validate_ent_type(submission):
     """Check entity type of submission."""
-
     try:
         if not isinstance(submission.entity, entity.Project):
             ent_type = re.search(r"entity\.(.*?)'", str(type(submission.entity))).group(
@@ -157,7 +152,6 @@ def _validate_ent_type(submission):
 
 def _validate_project_id(proj, challenge):
     """Check that submission is not the Challenge site."""
-
     return (
         "Submission should not be the Challenge site."
         if proj.entityId == challenge
@@ -167,56 +161,48 @@ def _validate_project_id(proj, challenge):
 
 def _validate_public_permissions(syn, proj):
     """Ensure project is shared with the public."""
-
     error = "Your project is not publicly available."
-
     try:
         # Remove error message if the project is accessible by the public.
-        syn_users_perms = syn.getPermissions(proj.entityId, AUTHENTICATED_USERS)
         public_perms = syn.getPermissions(proj.entityId)
-        if (
-            "READ" in syn_users_perms and "DOWNLOAD" in syn_users_perms
-        ) and "READ" in public_perms:
+        if "READ" in public_perms:
             error = ""
-
     except SynapseHTTPError as e:
         # Raise exception message if error is not a permissions error.
         if e.response.status_code != 403:
             raise e
-
     return error
 
 
 def _validate_admin_permissions(syn, proj, admin):
     """Ensure project is shared with the given admin."""
-
     error = (
         "Project is private; please update its sharing settings."
         f" Writeup should be shared with {admin}."
     )
     try:
-        # Remove error message if admin has read and download permissions.
+        # Remove error message if admin has read and download permissions
+        # OR if the project is publicly availably.
         admin_perms = syn.getPermissions(proj.entityId, admin)
-        if "READ" in admin_perms and "DOWNLOAD" in admin_perms:
+        public_perms = syn.getPermissions(proj.entityId)
+        if "READ" in public_perms or (
+            "READ" in admin_perms and "DOWNLOAD" in admin_perms
+        ):
             error = ""
-
     except SynapseHTTPError as e:
         # Raise exception message if error is not a permissions error.
         if e.response.status_code != 403:
             raise e
-
     return error
 
 
 def _check_project_permissions(syn, submission, public, admin):
     """Check the submission sharing settings."""
-
     errors = []
     if public:
         public_error = _validate_public_permissions(syn, submission)
         if public_error:
             errors.append(public_error)
-
     if not public and admin is not None:
         admin_error = _validate_admin_permissions(syn, submission, admin)
         if admin_error:


Test patch:
diff --git a/tests/test_submission.py b/tests/test_submission.py
index 7680620..c30051b 100644
--- a/tests/test_submission.py
+++ b/tests/test_submission.py
@@ -69,7 +69,7 @@ def test__validate_admin_permissions_admin_permissions_req():
     admin = "me"
     with patch.object(SYN, "getPermissions") as patch_perms:
         errors = submission._validate_admin_permissions(SYN, PROJ, admin=admin)
-        patch_perms.assert_called_once()
+        assert patch_perms.call_count == 2
 
         message = (
             "Project is private; please update its sharing settings."
@@ -86,7 +86,7 @@ def test__validate_public_permissions_public_permissions_req():
     """
     with patch.object(SYN, "getPermissions") as patch_perms:
         errors = submission._validate_public_permissions(SYN, PROJ)
-        assert patch_perms.call_count == 2
+        patch_perms.assert_called_once()
         assert errors == "Your project is not publicly available."