headless_lms_server/controllers/main_frontend/
page_audio_files.rs1use std::path::Path;
4
5use futures::StreamExt;
6use models::page_audio_files::PageAudioFile;
7
8use crate::prelude::*;
9
10#[instrument(skip(request, payload, pool, file_store))]
25async fn set_page_audio(
26 request: HttpRequest,
27 mut payload: Multipart,
28 page_id: web::Path<Uuid>,
29 pool: web::Data<PgPool>,
30 user: AuthUser,
31 file_store: web::Data<dyn FileStore>,
32) -> ControllerResult<web::Json<bool>> {
33 let mut conn = pool.acquire().await?;
34 let page = models::pages::get_page(&mut conn, *page_id).await?;
35 if let Some(course_id) = page.course_id {
36 let token = authorize(&mut conn, Act::Edit, Some(user.id), Res::Course(course_id)).await?;
37
38 let field = match payload.next().await {
39 Some(Ok(field)) => field,
40 Some(Err(error)) => {
41 return Err(ControllerError::new(
42 ControllerErrorType::InternalServerError,
43 error.to_string(),
44 None,
45 ));
46 }
47 None => {
48 return Err(ControllerError::new(
49 ControllerErrorType::BadRequest,
50 "Didn't upload any files",
51 None,
52 ));
53 }
54 };
55
56 let mime_type = field
57 .content_type()
58 .map(|ct| ct.to_string())
59 .unwrap_or_else(|| "".to_string());
60
61 match mime_type.as_str() {
62 "audio/mpeg" | "audio/ogg" => {}
63 unsupported => {
64 return Err(ControllerError::new(
65 ControllerErrorType::BadRequest,
66 format!("Unsupported audio Mime type: {}", unsupported),
67 None,
68 ));
69 }
70 };
71
72 let course = models::courses::get_course(&mut conn, page.course_id.unwrap()).await?;
73 let media_path = upload_field_from_cms(
74 request.headers(),
75 field,
76 StoreKind::Course(course.id),
77 file_store.as_ref(),
78 &mut conn,
79 user,
80 )
81 .await?;
82
83 models::page_audio_files::insert_page_audio(
84 &mut conn,
85 page.id,
86 &media_path.as_path().to_string_lossy(),
87 &mime_type,
88 )
89 .await?;
90
91 token.authorized_ok(web::Json(true))
92 } else {
93 Err(ControllerError::new(
94 ControllerErrorType::BadRequest,
95 "The page needs to be related to a course.".to_string(),
96 None,
97 ))
98 }
99}
100
101#[instrument(skip(pool, file_store))]
113async fn remove_page_audio(
114 page_audio_id: web::Path<Uuid>,
115 page_id: web::Path<Uuid>,
116 pool: web::Data<PgPool>,
117 user: AuthUser,
118 file_store: web::Data<dyn FileStore>,
119) -> ControllerResult<web::Json<()>> {
120 let mut conn = pool.acquire().await?;
121 let audio =
122 models::page_audio_files::get_page_audio_files_by_id(&mut conn, *page_audio_id).await?;
123 let page = models::pages::get_page(&mut conn, audio.page_id).await?;
124 if let Some(course_id) = page.course_id {
125 let token = authorize(&mut conn, Act::Edit, Some(user.id), Res::Course(course_id)).await?;
126
127 let path = models::page_audio_files::delete_page_audio(&mut conn, *page_audio_id).await?;
128 file_store.delete(Path::new(&path)).await.map_err(|_| {
129 ControllerError::new(
130 ControllerErrorType::BadRequest,
131 "Could not delete the file from the file store".to_string(),
132 None,
133 )
134 })?;
135 token.authorized_ok(web::Json(()))
136 } else {
137 Err(ControllerError::new(
138 ControllerErrorType::BadRequest,
139 "The page needs to be related to a course.".to_string(),
140 None,
141 ))
142 }
143}
144
145#[instrument(skip(app_conf))]
151
152async fn get_page_audio(
153 page_id: web::Path<Uuid>,
154 pool: web::Data<PgPool>,
155 user: AuthUser,
156 app_conf: web::Data<ApplicationConfiguration>,
157) -> ControllerResult<web::Json<Vec<PageAudioFile>>> {
158 let mut conn = pool.acquire().await?;
159 let token = authorize(&mut conn, Act::Edit, Some(user.id), Res::Page(*page_id)).await?;
160
161 let mut page_audio_files =
162 models::page_audio_files::get_page_audio_files(&mut conn, *page_id).await?;
163
164 let base_url = &app_conf.base_url;
165 for audio in page_audio_files.iter_mut() {
166 audio.path = format!("{base_url}/api/v0/files/{}", audio.path);
167 }
168
169 token.authorized_ok(web::Json(page_audio_files))
170}
171
172pub fn _add_routes(cfg: &mut ServiceConfig) {
180 cfg.route("/{page_id}", web::post().to(set_page_audio))
181 .route("/{file_id}", web::delete().to(remove_page_audio))
182 .route("/{page_id}/files", web::get().to(get_page_audio));
183}