headless_lms_server/controllers/main_frontend/
shared_submissions.rs1use crate::{domain::models_requests, prelude::*};
2use headless_lms_models::exercise_slide_submission_shares::ExerciseSlideSubmissionShare;
3use headless_lms_models::exercise_slide_submissions::ExerciseSlideSubmissionInfo;
4use utoipa::OpenApi;
5
6#[derive(OpenApi)]
7#[openapi(paths(
8 get_shared_submission_info,
9 list_own_shares,
10 revoke_share,
11 revoke_shares_of_submission
12))]
13pub(crate) struct MainFrontendSharedSubmissionsApiDoc;
14
15#[utoipa::path(
24 get,
25 path = "/{token}",
26 operation_id = "getSharedSubmissionInfo",
27 tag = "shared_submissions",
28 params(
29 ("token" = Uuid, Path, description = "Submission share token")
30 ),
31 responses(
32 (status = 200, description = "Data needed to render the shared submission", body = ExerciseSlideSubmissionInfo)
33 )
34)]
35#[instrument(skip(pool, file_store, app_conf))]
36async fn get_shared_submission_info(
37 token: web::Path<Uuid>,
38 pool: web::Data<PgPool>,
39 _user: AuthUser,
40 file_store: web::Data<dyn FileStore>,
41 app_conf: web::Data<ApplicationConfiguration>,
42) -> ControllerResult<web::Json<ExerciseSlideSubmissionInfo>> {
43 let mut conn = pool.acquire().await?;
44 let auth_token = skip_authorize();
46
47 let share = models::exercise_slide_submission_shares::get_by_id(&mut conn, *token).await?;
48 let submission = models::exercise_slide_submissions::get_by_id(
49 &mut conn,
50 share.exercise_slide_submission_id,
51 )
52 .await?;
53 let mut res = models::exercise_slide_submissions::get_exercise_slide_submission_info(
54 &mut conn,
55 share.exercise_slide_submission_id,
56 submission.user_id,
57 models_requests::fetch_service_info,
58 true,
59 file_store.as_ref(),
60 app_conf.as_ref(),
61 )
62 .await?;
63
64 res.strip_for_shared_view();
67
68 auth_token.authorized_ok(web::Json(res))
69}
70
71#[utoipa::path(
76 get,
77 path = "",
78 operation_id = "listOwnSubmissionShares",
79 tag = "shared_submissions",
80 responses(
81 (status = 200, description = "The caller's live shares, newest first", body = Vec<ExerciseSlideSubmissionShare>)
82 )
83)]
84#[instrument(skip(pool))]
85async fn list_own_shares(
86 pool: web::Data<PgPool>,
87 user: AuthUser,
88) -> ControllerResult<web::Json<Vec<ExerciseSlideSubmissionShare>>> {
89 let mut conn = pool.acquire().await?;
90 let auth_token = skip_authorize();
92 let shares =
93 models::exercise_slide_submission_shares::list_by_creator(&mut conn, user.id).await?;
94 auth_token.authorized_ok(web::Json(shares))
95}
96
97#[utoipa::path(
105 delete,
106 path = "/{token}",
107 operation_id = "revokeSubmissionShare",
108 tag = "shared_submissions",
109 params(
110 ("token" = Uuid, Path, description = "Submission share token")
111 ),
112 responses(
113 (status = 200, description = "Whether a live share was withdrawn", body = bool)
114 )
115)]
116#[instrument(skip(pool))]
117async fn revoke_share(
118 token: web::Path<Uuid>,
119 pool: web::Data<PgPool>,
120 user: AuthUser,
121) -> ControllerResult<web::Json<bool>> {
122 let mut conn = pool.acquire().await?;
123 let auth_token = skip_authorize();
125 let revoked =
126 models::exercise_slide_submission_shares::revoke(&mut conn, *token, user.id).await?;
127 auth_token.authorized_ok(web::Json(revoked))
128}
129
130#[utoipa::path(
135 delete,
136 path = "/of-submission/{submission_id}",
137 operation_id = "revokeSubmissionSharesOfSubmission",
138 tag = "shared_submissions",
139 params(
140 ("submission_id" = Uuid, Path, description = "Exercise slide submission id")
141 ),
142 responses(
143 (status = 200, description = "How many shares were withdrawn", body = i64)
144 )
145)]
146#[instrument(skip(pool))]
147async fn revoke_shares_of_submission(
148 submission_id: web::Path<Uuid>,
149 pool: web::Data<PgPool>,
150 user: AuthUser,
151) -> ControllerResult<web::Json<i64>> {
152 let mut conn = pool.acquire().await?;
153 let auth_token = skip_authorize();
155 let revoked = models::exercise_slide_submission_shares::revoke_all_for_submission(
156 &mut conn,
157 *submission_id,
158 user.id,
159 )
160 .await?;
161 auth_token.authorized_ok(web::Json(revoked as i64))
162}
163
164pub fn _add_routes(cfg: &mut ServiceConfig) {
165 cfg.route("", web::get().to(list_own_shares))
166 .route(
167 "/of-submission/{submission_id}",
168 web::delete().to(revoke_shares_of_submission),
169 )
170 .route("/{token}", web::get().to(get_shared_submission_info))
171 .route("/{token}", web::delete().to(revoke_share));
172}