headless_lms_server/controllers/main_frontend/
proposed_edits.rs1use std::sync::Arc;
2
3use models::proposed_page_edits::{self, EditProposalInfo, PageProposal, ProposalCount};
4use utoipa::OpenApi;
5
6use crate::{
7 domain::{
8 models_requests::{self, JwtKey},
9 request_id::RequestId,
10 },
11 prelude::*,
12};
13
14#[derive(OpenApi)]
15#[openapi(paths(get_edit_proposals, get_edit_proposal_count, process_edit_proposal))]
16pub(crate) struct MainFrontendProposedEditsApiDoc;
17
18#[derive(Debug, Deserialize)]
19
20pub struct GetEditProposalsQuery {
21 pending: bool,
22 #[serde(flatten)]
23 pagination: Pagination,
24}
25
26#[instrument(skip(pool))]
30#[utoipa::path(
31 get,
32 path = "/course/{course_id}",
33 operation_id = "getEditProposals",
34 tag = "proposed_edits",
35 params(
36 ("course_id" = Uuid, Path, description = "Course id"),
37 ("pending" = bool, Query, description = "Whether to fetch pending proposals"),
38 ("page" = Option<i64>, Query, description = "Page number"),
39 ("limit" = Option<i64>, Query, description = "Page size")
40 ),
41 responses(
42 (status = 200, description = "Edit proposals", body = Vec<PageProposal>)
43 )
44)]
45pub async fn get_edit_proposals(
46 course_id: web::Path<Uuid>,
47 pool: web::Data<PgPool>,
48 query: web::Query<GetEditProposalsQuery>,
49 user: AuthUser,
50) -> ControllerResult<web::Json<Vec<PageProposal>>> {
51 let mut conn = pool.acquire().await?;
52
53 let feedback = proposed_page_edits::get_proposals_for_course(
54 &mut conn,
55 *course_id,
56 query.pending,
57 query.pagination,
58 )
59 .await?;
60
61 let token = authorize(
62 &mut conn,
63 Act::Teach,
64 Some(user.id),
65 Res::Course(*course_id),
66 )
67 .await?;
68 token.authorized_ok(web::Json(feedback))
69}
70
71#[instrument(skip(pool))]
75#[utoipa::path(
76 get,
77 path = "/course/{course_id}/count",
78 operation_id = "getEditProposalCount",
79 tag = "proposed_edits",
80 params(
81 ("course_id" = Uuid, Path, description = "Course id")
82 ),
83 responses(
84 (status = 200, description = "Edit proposal counts", body = ProposalCount)
85 )
86)]
87pub async fn get_edit_proposal_count(
88 course_id: web::Path<Uuid>,
89 pool: web::Data<PgPool>,
90 user: AuthUser,
91) -> ControllerResult<web::Json<ProposalCount>> {
92 let mut conn = pool.acquire().await?;
93
94 let edit_proposal_count =
95 proposed_page_edits::get_proposal_count_for_course(&mut conn, *course_id).await?;
96
97 let token = authorize(
98 &mut conn,
99 Act::Teach,
100 Some(user.id),
101 Res::Course(*course_id),
102 )
103 .await?;
104 token.authorized_ok(web::Json(edit_proposal_count))
105}
106
107#[instrument(skip(pool, app_conf))]
111#[utoipa::path(
112 post,
113 path = "/process-edit-proposal",
114 operation_id = "processEditProposal",
115 tag = "proposed_edits",
116 request_body = EditProposalInfo,
117 responses(
118 (status = 200, description = "Processed edit proposal")
119 )
120)]
121pub async fn process_edit_proposal(
122 request_id: RequestId,
123 proposal: web::Json<EditProposalInfo>,
124 app_conf: web::Data<ApplicationConfiguration>,
125 user: AuthUser,
126 pool: web::Data<PgPool>,
127 jwt_key: web::Data<JwtKey>,
128) -> ControllerResult<HttpResponse> {
129 let mut conn = pool.acquire().await?;
130 let proposal = proposal.into_inner();
131
132 proposed_page_edits::process_proposal(
133 &mut conn,
134 proposal.page_id,
135 proposal.page_proposal_id,
136 proposal.block_proposals,
137 user.id,
138 models_requests::make_spec_fetcher(
139 app_conf.base_url.clone(),
140 request_id.0,
141 Arc::clone(&jwt_key),
142 ),
143 models_requests::fetch_service_info,
144 )
145 .await?;
146
147 let token = authorize(
148 &mut conn,
149 Act::Edit,
150 Some(user.id),
151 Res::Page(proposal.page_id),
152 )
153 .await?;
154 token.authorized_ok(HttpResponse::Ok().finish())
155}
156
157pub fn _add_routes(cfg: &mut ServiceConfig) {
165 cfg.route("/course/{course_id}", web::get().to(get_edit_proposals))
166 .route(
167 "/course/{course_id}/count",
168 web::get().to(get_edit_proposal_count),
169 )
170 .route(
171 "/process-edit-proposal",
172 web::post().to(process_edit_proposal),
173 );
174}