1use actix_web::{
4 delete, get, patch, post,
5 web::{Json, Path, Query},
6 HttpResponse, Result,
7};
8use uuid::Uuid;
9
10use crate::{
11 config::{
12 auth::user_info::UserInfo,
13 data::{SharedBroadcaster, SharedPool},
14 },
15 model::dto::{
16 actions::Action,
17 areas::{AreaKind, AreaSearchParameters, AreaUpdate, NewAreaDto, UpdateAreaDto},
18 core::ActionDtoWrapper,
19 },
20 service::{
21 areas,
22 map_access_control::{check_permissions, AccessRights},
23 },
24};
25
26#[utoipa::path(
32 context_path = "/api/maps/{map_id}/areas",
33 params(
34 ("map_id" = i32, Path, description = "The id of the map the layer is on"),
35 AreaSearchParameters
36 ),
37 responses(
38 (status = 200, description = "Find areas", body = Vec<AreaDto>),
39 ),
40 security(
41 ("oauth2" = [])
42 )
43)]
44#[get("")]
45pub async fn find(
46 search_params: Query<AreaSearchParameters>,
47 pool: SharedPool,
48 user_info: UserInfo,
49 path: Path<i32>,
50) -> Result<HttpResponse> {
51 check_permissions(path.into_inner(), &pool, user_info, AccessRights::Read).await?;
52 let response = areas::find(search_params.into_inner(), &pool).await?;
53 Ok(HttpResponse::Ok().json(response))
54}
55
56#[utoipa::path(
62 context_path = "/api/maps/{map_id}/areas",
63 params(
64 ("map_id" = i32, Path, description = "The id of the map the layer is on"),
65 ("area_kind" = AreaKind, Path, description = "The type of area"),
66 ),
67 request_body = NewAreaDto,
68 responses(
69 (status = 201, description = "Create an areas", body = AreaDto)
70 ),
71 security(
72 ("oauth2" = [])
73 )
74)]
75#[post("/{area_kind}")]
76pub async fn create(
77 path: Path<(i32, AreaKind)>,
78 new_areas: Json<ActionDtoWrapper<Vec<NewAreaDto>>>,
79 pool: SharedPool,
80 broadcaster: SharedBroadcaster,
81 user_info: UserInfo,
82) -> Result<HttpResponse> {
83 let user_id = user_info.id;
84 let (map_id, area_kind) = path.into_inner();
85
86 check_permissions(map_id, &pool, user_info, AccessRights::Write).await?;
87
88 let ActionDtoWrapper { action_id, dto } = new_areas.into_inner();
89
90 let created_areas = areas::create(area_kind, dto, &pool).await?;
91
92 broadcaster
93 .broadcast(
94 map_id,
95 Action::new_create_area_action(area_kind, created_areas.clone(), user_id, action_id),
96 )
97 .await;
98
99 Ok(HttpResponse::Created().json(created_areas))
100}
101
102#[utoipa::path(
108 context_path = "/api/maps/{map_id}/areas",
109 params(
110 ("map_id" = i32, Path, description = "The id of the map the layer is on"),
111 ("area_kind" = AreaKind, Path, description = "The type of area"),
112 ),
113 request_body = ActionDtoWrapperUpdateAreas,
114 responses(
115 (status = 200, description = "Update multiple areas of the same kind", body = Vec<AreaDto>)
116 ),
117 security(
118 ("oauth2" = [])
119 )
120)]
121#[patch("/{area_kind}")]
122pub async fn update(
123 path: Path<(i32, AreaKind)>,
124 update_areas: Json<ActionDtoWrapper<UpdateAreaDto>>,
125 pool: SharedPool,
126 broadcaster: SharedBroadcaster,
127 user_info: UserInfo,
128) -> Result<HttpResponse> {
129 let (map_id, area_kind) = path.into_inner();
130
131 let user_id = user_info.id;
132
133 check_permissions(map_id, &pool, user_info, AccessRights::Write).await?;
134
135 let ActionDtoWrapper { action_id, dto } = update_areas.into_inner();
136
137 let updated = areas::update(area_kind, dto.clone(), &pool).await?;
138
139 let action = match dto.update {
140 AreaUpdate::UpdateValue(_) => {
141 Action::new_update_area_action(area_kind, &updated, user_id, action_id)
142 }
143 AreaUpdate::UpdateAddDate(_) => {
144 Action::new_update_area_add_date_action(area_kind, &updated, user_id, action_id)
145 }
146 AreaUpdate::UpdateRemoveDate(_) => {
147 Action::new_update_area_remove_date_action(area_kind, &updated, user_id, action_id)
148 }
149 AreaUpdate::UpdateNotes(_) => {
150 Action::new_update_area_notes_action(area_kind, &updated, user_id, action_id)
151 }
152 };
153 broadcaster.broadcast(map_id, action).await;
154
155 Ok(HttpResponse::Ok().json(updated))
156}
157
158#[utoipa::path(
164 context_path = "/api/maps/{map_id}/areas",
165 params(
166 ("map_id" = i32, Path, description = "The id of the map the layer is on"),
167 ("area_kind" = AreaKind, Path, description = "The type of area"),
168 ),
169 request_body = ActionDtoWrapperDeleteAreas,
170 responses(
171 (status = 200, description = "Areas deleted")
172 ),
173 security(
174 ("oauth2" = [])
175 )
176)]
177#[delete("/{area_kind}")]
178pub async fn delete(
179 path: Path<(i32, AreaKind)>,
180 ids: Json<ActionDtoWrapper<Vec<Uuid>>>,
181 pool: SharedPool,
182 broadcaster: SharedBroadcaster,
183 user_info: UserInfo,
184) -> Result<HttpResponse> {
185 let (map_id, area_kind) = path.into_inner();
186
187 let user_id = user_info.id;
188
189 check_permissions(map_id, &pool, user_info, AccessRights::Write).await?;
190
191 let ActionDtoWrapper { action_id, dto } = ids.into_inner();
192
193 areas::delete_by_ids(area_kind, dto.clone(), &pool).await?;
194
195 broadcaster
196 .broadcast(
197 map_id,
198 Action::new_delete_area_action(area_kind, dto, user_id, action_id),
199 )
200 .await;
201
202 Ok(HttpResponse::Ok().finish())
203}