@@ -54,6 +54,21 @@ pub async fn get_unapproved(
5454 ) )
5555}
5656
57+ /// Gets all papers which have been soft-deleted.
58+ pub async fn get_trash ( State ( state) : State < RouterState > ) -> HandlerReturn < Vec < AdminDashboardQP > > {
59+ let papers: Vec < AdminDashboardQP > = state. db . get_soft_deleted_papers ( ) . await ?;
60+
61+ let papers = papers
62+ . iter ( )
63+ . map ( |paper| paper. clone ( ) . with_url ( & state. env_vars ) )
64+ . collect :: < Result < Vec < qp:: AdminDashboardQP > , color_eyre:: eyre:: Error > > ( ) ?;
65+
66+ Ok ( BackendResponse :: ok (
67+ format ! ( "Successfully fetched {} papers." , papers. len( ) ) ,
68+ papers,
69+ ) )
70+ }
71+
5772/// Fetches a paper by id.
5873pub async fn get_paper_details (
5974 State ( state) : State < RouterState > ,
@@ -423,11 +438,7 @@ pub async fn upload(
423438 total_count
424439 ) ;
425440
426- let _ = send_slack_message (
427- & state. env_vars . slack_webhook_url ,
428- & message,
429- )
430- . await ;
441+ let _ = send_slack_message ( & state. env_vars . slack_webhook_url , & message) . await ;
431442
432443 Ok ( BackendResponse :: ok (
433444 format ! ( "Successfully processed {} files" , upload_statuses. len( ) ) ,
@@ -463,6 +474,68 @@ pub async fn delete(
463474 }
464475}
465476
477+ #[ derive( Deserialize ) ]
478+ /// The request format for the hard delete endpoint
479+ pub struct HardDeleteReq {
480+ ids : Vec < i32 > ,
481+ }
482+
483+ #[ derive( Serialize ) ]
484+ /// The status of a paper to be deleted
485+ pub struct DeleteStatus {
486+ id : i32 ,
487+ status : Status ,
488+ message : String
489+ }
490+
491+ /// Hard deletes papers from a list of ids.
492+ ///
493+ /// Request format - [`HardDeleteReq`]
494+ pub async fn hard_delete (
495+ State ( state) : State < RouterState > ,
496+ Json ( body) : Json < HardDeleteReq > ,
497+ ) -> HandlerReturn < Vec < DeleteStatus > > {
498+ let mut delete_statuses = Vec :: < DeleteStatus > :: new ( ) ;
499+ let mut deleted_count = 0 ;
500+ for id in body. ids {
501+ if let Ok ( paper) = state. db . get_paper_by_id ( id) . await {
502+ let tx = state. db . hard_delete ( id) . await ?;
503+ let filepath = state. env_vars . paths . get_path_from_slug ( & paper. qp . filelink ) ;
504+ if fs:: remove_file ( & filepath) . await . is_ok ( ) {
505+ if tx. commit ( ) . await . is_ok ( ) {
506+ delete_statuses. push ( DeleteStatus {
507+ id,
508+ status : Status :: Success ,
509+ message : "Successfully hard deleted the paper." . into ( ) ,
510+ } ) ;
511+ deleted_count += 1 ;
512+ } else {
513+ delete_statuses. push ( DeleteStatus {
514+ id,
515+ status : Status :: Error ,
516+ message : "Error committing the transaction." . into ( ) ,
517+ } ) ;
518+ }
519+ } else {
520+ tx. rollback ( ) . await ?;
521+ delete_statuses. push ( DeleteStatus {
522+ id,
523+ status : Status :: Error ,
524+ message : "Failed to delete file." . into ( ) ,
525+ } ) ;
526+ }
527+ }
528+ }
529+
530+ let message = if deleted_count > 0 {
531+ format ! ( "Successfully hard deleted {} papers." , deleted_count)
532+ } else {
533+ "No papers were deleted." . into ( )
534+ } ;
535+
536+ Ok ( BackendResponse :: ok ( message, delete_statuses) )
537+ }
538+
466539/// Fetches all question papers that match one or more properties specified. `course_name` is compulsory.
467540///
468541/// # Request Query Parameters
0 commit comments