1use actix_web::web::Query;
4use actix_web::{
5 delete, get, patch, post,
6 web::{Json, Path},
7 HttpResponse, Result,
8};
9use uuid::Uuid;
10
11use crate::service::map_access_control::{check_creation_permission, AccessRights};
12use crate::{
13 config::{
14 auth::user_info::UserInfo,
15 data::{SharedBroadcaster, SharedPool},
16 },
17 model::dto::{
18 actions::{Action, ActionType, UpdateMapGeometryActionPayload},
19 MapSearchParameters, NewMapDto, PageParameters, UpdateMapDto, UpdateMapGeometryDto,
20 },
21 service,
22 service::map_access_control::check_permissions,
23};
24
25#[utoipa::path(
32 context_path = "/api/maps",
33 params(
34 MapSearchParameters,
35 PageParameters
36 ),
37 responses(
38 (status = 200, description = "Fetch or search all maps", body = PageMapDto)
39 ),
40 security(
41 ("oauth2" = [])
42 )
43)]
44#[get("")]
45pub async fn find(
46 search_query: Query<MapSearchParameters>,
47 page_query: Query<PageParameters>,
48 pool: SharedPool,
49 user_info: UserInfo,
50) -> Result<HttpResponse> {
51 let response = service::map::find(
52 search_query.into_inner(),
53 page_query.into_inner(),
54 &pool,
55 user_info,
56 )
57 .await?;
58 Ok(HttpResponse::Ok().json(response))
59}
60
61#[utoipa::path(
67 context_path = "/api/maps",
68 responses(
69 (status = 200, description = "Fetch a map by id", body = MapDto)
70 ),
71 security(
72 ("oauth2" = [])
73 )
74)]
75#[get("/{map_id}")]
76pub async fn find_by_id(
77 map_id: Path<i32>,
78 pool: SharedPool,
79 user_info: UserInfo,
80) -> Result<HttpResponse> {
81 let id = map_id.into_inner();
82 check_permissions(id, &pool, user_info, AccessRights::Read).await?;
83 let response = service::map::find_by_id(id.into(), &pool).await?;
84 Ok(HttpResponse::Ok().json(response))
85}
86
87#[utoipa::path(
92 context_path = "/api/maps",
93 request_body = NewMapDto,
94 responses(
95 (status = 201, description = "Create a new map", body = MapDto)
96 ),
97 security(
98 ("oauth2" = [])
99 )
100)]
101#[post("")]
102pub async fn create(
103 new_map_json: Json<NewMapDto>,
104 user_info: UserInfo,
105 pool: SharedPool,
106) -> Result<HttpResponse> {
107 check_creation_permission(&user_info).await?;
108 let response = service::map::create(new_map_json.0, user_info.id, &pool).await?;
109 Ok(HttpResponse::Created().json(response))
110}
111
112#[utoipa::path(
118 context_path = "/api/maps",
119 request_body = UpdateMapDto,
120 responses(
121 (status = 200, description = "Update a map", body = MapDto)
122 ),
123 security(
124 ("oauth2" = [])
125 )
126)]
127#[patch("/{map_id}")]
128pub async fn update(
129 map_update_json: Json<UpdateMapDto>,
130 map_id: Path<i32>,
131 user_info: UserInfo,
132 pool: SharedPool,
133) -> Result<HttpResponse> {
134 let id = map_id.into_inner();
135 check_permissions(id, &pool, user_info, AccessRights::Write).await?;
136 let response = service::map::update(map_update_json.0, id.into(), &pool).await?;
137 Ok(HttpResponse::Ok().json(response))
138}
139#[utoipa::path(
145context_path = "/api/maps",
146request_body = UpdateMapDto,
147responses(
148(status = 200, description = "Update a map", body = MapDto)
149),
150security(
151("oauth2" = [])
152)
153)]
154#[patch("/{map_id}/geometry")]
155pub async fn update_geometry(
156 map_update_geometry_json: Json<UpdateMapGeometryDto>,
157 map_id: Path<i32>,
158 user_info: UserInfo,
159 pool: SharedPool,
160 broadcaster: SharedBroadcaster,
161) -> Result<HttpResponse> {
162 let map_id_inner = map_id.into_inner();
163 let user_id = user_info.id;
164 check_permissions(map_id_inner, &pool, user_info, AccessRights::Write).await?;
165
166 let response = service::map::update_geometry(
167 map_update_geometry_json.0.clone(),
168 map_id_inner.into(),
169 &pool,
170 )
171 .await?;
172
173 broadcaster
174 .broadcast(
175 map_id_inner,
176 Action {
177 action_id: Uuid::now_v7(),
178 user_id,
179 action: ActionType::UpdateMapGeometry(UpdateMapGeometryActionPayload::new(
180 map_update_geometry_json.0,
181 map_id_inner,
182 )),
183 },
184 )
185 .await;
186
187 Ok(HttpResponse::Ok().json(response))
188}
189
190#[utoipa::path(
196 context_path = "/api/maps",
197 responses(
198 (status = 200, description = "Delete a map by id")
199 ),
200 security(
201 ("oauth2" = [])
202 )
203)]
204#[delete("/{map_id}")]
205pub async fn delete_by_id(
206 map_id: Path<i32>,
207 user_info: UserInfo,
208 pool: SharedPool,
209) -> Result<HttpResponse> {
210 let m_id = map_id.into_inner();
211 check_permissions(m_id, &pool, user_info, AccessRights::Write).await?;
212 service::map::delete_by_id(m_id.into(), &pool).await?;
213 Ok(HttpResponse::Ok().finish())
214}