@@ -24,6 +24,12 @@ def create(url_prefix: str) -> APIRouter:
2424 router = APIRouter ()
2525 version = "v1"
2626
27+ router .post (
28+ f"{ url_prefix } /submissions/retract/{ version } /{{submission_identifier}}" ,
29+ tags = ["Reviewing" ],
30+ description = "Retract an asset under review, setting its status to 'draft'." ,
31+ )(retract_submission )
32+
2733 router .get (
2834 f"{ url_prefix } /submissions/{ version } /" ,
2935 tags = ["Reviewing" ],
@@ -64,27 +70,27 @@ def _get_single_submission(
6470) -> Submission | None :
6571 with DbSession () as session :
6672 has_review = select (1 ).where (Submission .identifier == Review .submission_identifier ).exists ()
67- query = select (Submission ).where (~ has_review )
68-
73+ submissions = select (Submission ).where (~ has_review )
6974 if which == ListMode .NEWEST :
70- query = query .order_by (Submission .request_date .desc ()) # type: ignore[attr-defined]
75+ submissions = submissions .order_by (Submission .request_date .desc ()) # type: ignore[attr-defined]
7176 if from_requestee is not None :
72- query = query .where (Submission .requestee_identifier == from_requestee )
77+ submissions = submissions .where (Submission .requestee_identifier == from_requestee )
7378
74- return session .scalars (query ).first ()
79+ return session .scalars (submissions ).first ()
7580
7681
7782def _get_submissions_by_state (
7883 * ,
79- which : Literal [ListMode .COMPLETED , ListMode .PENDING ],
84+ which : Literal [ListMode .COMPLETED , ListMode .PENDING , ListMode . ALL ],
8085 from_requestee : str | None = None ,
8186) -> Sequence [Submission ]:
8287 with DbSession () as session :
8388 has_review = select (1 ).where (Submission .identifier == Review .submission_identifier ).exists ()
89+ submissions = select (Submission )
8490 if which == ListMode .PENDING :
85- submissions = select ( Submission ) .where (~ has_review )
91+ submissions = submissions .where (~ has_review )
8692 if which == ListMode .COMPLETED :
87- submissions = select ( Submission ) .where (has_review )
93+ submissions = submissions .where (has_review )
8894 if from_requestee is not None :
8995 submissions = submissions .where (Submission .requestee_identifier == from_requestee )
9096 return session .scalars (submissions ).all ()
@@ -98,7 +104,7 @@ def list_submissions(
98104 if mode in [ListMode .NEWEST , ListMode .OLDEST ]:
99105 submission = _get_single_submission (which = mode , from_requestee = user_filter ) # type: ignore[arg-type]
100106 return [submission ] if submission else []
101- if mode in [ListMode .PENDING , ListMode .COMPLETED ]:
107+ if mode in [ListMode .PENDING , ListMode .COMPLETED , ListMode . ALL ]:
102108 return _get_submissions_by_state (which = mode , from_requestee = user_filter ) # type: ignore[arg-type]
103109 raise ValueError (f"`mode` should be one of { ListMode !r} but is { mode !r} ." )
104110
@@ -108,8 +114,7 @@ def get_submission(
108114 user : KeycloakUser = Depends (get_user_or_raise ),
109115 session : Session = Depends (get_session ),
110116) -> Submission :
111- query = select (Submission ).where (Submission .identifier == identifier )
112- submission = session .scalars (query ).first ()
117+ submission = session .get (Submission , identifier )
113118 if not submission :
114119 raise HTTPException (
115120 status_code = HTTPStatus .NOT_FOUND ,
@@ -169,3 +174,35 @@ def _review_resource(
169174 session .add (review )
170175 session .commit ()
171176 return review
177+
178+
179+ def retract_submission (
180+ submission_identifier : str ,
181+ user : KeycloakUser = Depends (get_user_or_raise ),
182+ ):
183+ with DbSession () as session :
184+ submission = session .get (Submission , submission_identifier )
185+ if not user_can_administer (user , submission .asset .aiod_entry ):
186+ # Could choose to instead give same error as if resource does not exist.
187+ msg = f"You do not have permission to retract { submission .asset_type } { submission .asset .identifier } ."
188+ raise HTTPException (status_code = status .HTTP_403_FORBIDDEN , detail = msg )
189+
190+ if submission is None or not submission .is_pending :
191+ raise HTTPException (
192+ status_code = status .HTTP_400_BAD_REQUEST ,
193+ detail = "Cannot retract this asset, as it is not under review." ,
194+ )
195+
196+ retraction = Review (
197+ decision = Decision .RETRACTED ,
198+ reviewer_identifier = user ._subject_identifier ,
199+ submission_identifier = submission .identifier ,
200+ )
201+ submission .asset .aiod_entry .status = EntryStatus .DRAFT
202+ session .add (retraction )
203+ session .commit ()
204+ return {
205+ "review_identifier" : retraction .identifier ,
206+ "submission_identifier" : submission .identifier ,
207+ "decision" : retraction .decision ,
208+ }
0 commit comments