@@ -1151,7 +1151,7 @@ async def get_submission(
1151
1151
raise HTTPException (status_code = 403 , detail = "Must have access." )
1152
1152
1153
1153
1154
- def can_save_submission (role : models .SubmissionRole , data : dict ):
1154
+ def can_save_submission (role : models .SubmissionRole , data : dict , status : str ):
1155
1155
"""Compare a patch payload with what the user can actually save."""
1156
1156
metadata_contributor_fields = set (["sampleData" , "metadata_submission" ])
1157
1157
editor_fields = set (
@@ -1174,13 +1174,16 @@ def can_save_submission(role: models.SubmissionRole, data: dict):
1174
1174
models .SubmissionEditorRole .metadata_contributor : metadata_contributor_fields ,
1175
1175
}
1176
1176
permission_level = models .SubmissionEditorRole (role .role )
1177
- if permission_level == models .SubmissionEditorRole .owner :
1178
- return True
1179
- elif permission_level == models .SubmissionEditorRole .viewer :
1180
- return False
1177
+ if status in [SubmissionStatusEnum .InProgress .text , SubmissionStatusEnum .UpdatesRequired .text ]:
1178
+ if permission_level == models .SubmissionEditorRole .owner :
1179
+ return True
1180
+ elif permission_level == models .SubmissionEditorRole .viewer :
1181
+ return False
1182
+ else :
1183
+ allowed_fields = fields_for_permission [permission_level ]
1184
+ return all ([field in allowed_fields for field in attempted_patch_fields ])
1181
1185
else :
1182
- allowed_fields = fields_for_permission [permission_level ]
1183
- return all ([field in allowed_fields for field in attempted_patch_fields ])
1186
+ return False
1184
1187
1185
1188
1186
1189
@router .patch (
@@ -1202,7 +1205,11 @@ async def update_submission(
1202
1205
1203
1206
current_user_role = crud .get_submission_role (db , id , user .orcid )
1204
1207
if not (
1205
- user .is_admin or (current_user_role and can_save_submission (current_user_role , body_dict ))
1208
+ user .is_admin
1209
+ or (
1210
+ current_user_role
1211
+ and can_save_submission (current_user_role , body_dict , submission .status )
1212
+ )
1206
1213
):
1207
1214
raise HTTPException (403 , detail = "Must have access." )
1208
1215
@@ -1270,15 +1277,9 @@ def create_github_issue(submission: schemas_submission.SubmissionMetadataSchema,
1270
1277
headers = {"Authorization" : f"Bearer { token } " , "Content-Type" : "text/plain; charset=utf-8" }
1271
1278
1272
1279
# Check for existing issues first
1273
- existing_issue = check_existing_github_issue (submission .id , headers , gh_url , user )
1274
- if existing_issue :
1275
- logging .info (
1276
- f"GitHub issue already exists for submission { submission .id } : \
1277
- { existing_issue ['html_url' ]} "
1278
- )
1279
- return existing_issue
1280
+ existing_issue = check_existing_github_issues (submission .id , headers , gh_url , user )
1280
1281
1281
- else :
1282
+ if existing_issue is None :
1282
1283
1283
1284
# Gathering the fields we want to display in the issue
1284
1285
study_form = submission .metadata_submission .studyForm
@@ -1337,100 +1338,82 @@ def create_github_issue(submission: schemas_submission.SubmissionMetadataSchema,
1337
1338
return res
1338
1339
1339
1340
1340
- def update_github_issue_for_resubmission ( existing_issue , user , headers ):
1341
+ def check_existing_github_issues ( submission_id : UUID , headers : dict , gh_url : str , user ):
1341
1342
"""
1342
- Update an existing GitHub issue to note that the submission was resubmitted.
1343
- Adds a comment and optionally reopens the issue if it was closed.
1343
+ Check if a GitHub issue already exists for the given submission ID using GitHub's search API.
1344
1344
"""
1345
- try :
1346
- issue_number = existing_issue .get ("number" )
1347
- issue_url = existing_issue .get ("url" ) # API URL for the issue
1345
+ expected_title = f"NMDC Submission: { submission_id } "
1346
+ params = {
1347
+ "state" : "all" ,
1348
+ "per_page" : 100 ,
1349
+ }
1350
+ response = requests .get (gh_url , headers = headers , params = cast (Any , params ))
1348
1351
1349
- if not issue_number or not issue_url :
1350
- logging .error ("Could not find issue number or URL for existing GitHub issue" )
1351
- return existing_issue
1352
+ if response .status_code == 200 :
1353
+ issues = response .json ()
1352
1354
1353
- # Create a comment noting the resubmission
1354
- from datetime import datetime
1355
+ # Look for an issue with matching title
1356
+ for issue in issues :
1357
+ if issue .get ("title" ) == expected_title :
1358
+ updated_issue = update_github_issue_for_resubmission (issue , user , headers )
1359
+ return updated_issue
1360
+ else :
1361
+ return None # No matching gihub issues
1362
+ else :
1363
+ raise HTTPException (
1364
+ status_code = response .status_code ,
1365
+ detail = f"Search for existing Github issues failed: { response .reason } " ,
1366
+ )
1367
+
1368
+
1369
+ def update_github_issue_for_resubmission (existing_issue , user , headers ):
1370
+ """
1371
+ Update an existing GitHub issue to note that the submission was resubmitted.
1372
+ Adds a comment and reopens the issue if it was closed.
1373
+ """
1374
+ issue_url = existing_issue .get ("url" ) # API URL for the issue
1355
1375
1356
- timestamp = datetime .utcnow ().strftime ("%Y-%m-%d %H:%M:%S UTC" )
1376
+ # Create a comment noting the resubmission
1377
+ from datetime import datetime
1357
1378
1358
- comment_body = f"""
1379
+ timestamp = datetime .utcnow ().strftime ("%Y-%m-%d %H:%M:%S UTC" )
1380
+ comment_body = f"""
1359
1381
## 🔄 Submission Resubmitted
1360
1382
1361
1383
**Resubmitted by:** { user .name } ({ user .orcid } )
1362
1384
**Timestamp:** { timestamp }
1363
1385
**Status:** { SubmissionStatusEnum .SubmittedPendingReview .text }
1364
1386
1365
1387
The submission has been updated and resubmitted for review.
1366
- """ .strip ()
1388
+ """ .strip ()
1389
+
1390
+ # Add comment to the issue
1391
+ comment_url = f"{ issue_url } /comments"
1392
+ comment_payload = {"body" : comment_body }
1367
1393
1368
- # Add comment to the issue
1369
- comment_url = f"{ issue_url } /comments"
1370
- comment_payload = {"body" : comment_body }
1394
+ comment_response = requests .post (comment_url , headers = headers , data = json .dumps (comment_payload ))
1371
1395
1372
- comment_response = requests .post (
1373
- comment_url , headers = headers , data = json .dumps (comment_payload )
1396
+ if comment_response .status_code != 201 :
1397
+ raise HTTPException (
1398
+ status_code = comment_response .status_code ,
1399
+ detail = f"Failed to add comment to GitHub issue: { comment_response .reason } " ,
1374
1400
)
1375
1401
1376
- if comment_response .status_code == 201 :
1377
- logging .info (f"Successfully added resubmission comment to GitHub issue #{ issue_number } " )
1378
- else :
1379
- logging .error (f"Failed to add comment to GitHub issue: { comment_response .status_code } " )
1402
+ # If the issue is closed, reopen it
1403
+ if existing_issue .get ("state" ) == "closed" :
1404
+ reopen_payload = {"state" : "open" , "state_reason" : "reopened" }
1380
1405
1381
- # If the issue is closed, reopen it
1382
- if existing_issue . get ( "state" ) == "closed" :
1383
- reopen_payload = { "state" : "open" , "state_reason" : "reopened" }
1406
+ reopen_response = requests . patch (
1407
+ issue_url , headers = headers , data = json . dumps ( reopen_payload )
1408
+ )
1384
1409
1385
- reopen_response = requests .patch (
1386
- issue_url , headers = headers , data = json .dumps (reopen_payload )
1410
+ if reopen_response .status_code != 200 :
1411
+ raise HTTPException (
1412
+ status_code = reopen_response .status_code ,
1413
+ detail = f"Failed to reopen GitHub issue: { reopen_response .reason } " ,
1387
1414
)
1388
1415
1389
- if reopen_response .status_code == 200 :
1390
- logging .info (f"Successfully reopened GitHub issue #{ issue_number } " )
1391
- else :
1392
- logging .error (f"Failed to reopen GitHub issue: { reopen_response .status_code } " )
1393
-
1394
- return existing_issue
1395
-
1396
- except Exception as e :
1397
- logging .error (f"Error updating GitHub issue for resubmission: { str (e )} " )
1398
- return existing_issue
1399
-
1400
-
1401
- def check_existing_github_issue (submission_id : UUID , headers : dict , gh_base_url : str , user ):
1402
- """
1403
- Check if a GitHub issue already exists for the given submission ID using GitHub's search API.
1404
- """
1405
- try :
1406
- repo_url = gh_base_url .replace ("/issues" , "" )
1407
- search_url = f"{ repo_url } /issues"
1408
- expected_title = f"NMDC Submission: { submission_id } "
1409
- params = {
1410
- "state" : "all" ,
1411
- "per_page" : 100 ,
1412
- }
1413
- response = requests .get (search_url , headers = headers , params = cast (Any , params ))
1414
-
1415
- if response .status_code == 200 :
1416
- issues = response .json ()
1417
-
1418
- # Look for an issue with matching title
1419
- for issue in issues :
1420
- if issue .get ("title" ) == expected_title :
1421
- logging .info (f"Found existing GitHub issue for submission { submission_id } " )
1422
- updated_issue = update_github_issue_for_resubmission (issue , user , headers )
1423
- return updated_issue
1424
- else :
1425
- logging .info (f"No existing GitHub issue found for submission { submission_id } " )
1426
- return None
1427
- else :
1428
- logging .warning (f"Failed to search GitHub issues: { response .status_code } " )
1429
- return None
1430
-
1431
- except Exception as e :
1432
- logging .error (f"Error searching GitHub issues: { str (e )} " )
1433
- return None
1416
+ return existing_issue
1434
1417
1435
1418
1436
1419
@router .delete (
0 commit comments