1#![allow(clippy::needless_for_each)]
4
5use actix_web::web;
6use utoipa::{
7 openapi::security::{AuthorizationCode, Flow, OAuth2, Scopes, SecurityScheme},
8 Modify, OpenApi,
9};
10use utoipa_swagger_ui::SwaggerUi;
11
12use crate::{
13 config::auth::Config,
14 controller::{
15 areas, base_layer_image, config, drawings, guided_tours, layers, map, map_collaborators,
16 plant_layer, plantings, plants, seed, timeline, users,
17 },
18 keycloak_api,
19 model::{
20 dto::{
21 areas::{
22 AreaDto, AreaKind, NewAreaDto, UpdateAddDateAreaDto, UpdateAreaDto,
23 UpdateRemoveDateAreaDto,
24 },
25 base_layer_images::{BaseLayerImageDto, UpdateBaseLayerImageDto},
26 core::{
27 ActionDtoWrapperDeleteDrawings, ActionDtoWrapperDeleteLayer,
28 ActionDtoWrapperDeletePlantings, ActionDtoWrapperNewDrawings,
29 ActionDtoWrapperNewLayer, ActionDtoWrapperNewPlantings,
30 ActionDtoWrapperUpdateDrawings, ActionDtoWrapperUpdateLayer,
31 ActionDtoWrapperUpdatePlantings, TimelinePagePlantingsDto,
32 },
33 drawings::{
34 DrawingDto, EllipseProperties, FreeLineProperties, ImageProperties,
35 LabelTextProperties, PolygonProperties, RectangleProperties,
36 UpdateAddDateDrawingDto, UpdateNotesDrawingDto, UpdateRemoveDateDrawingDto,
37 },
38 layers::LayerDto,
39 plantings::{
40 MovePlantingDto, PlantingDto, TransformPlantingDto, UpdateAddDatePlantingDto,
41 UpdatePlantingDto, UpdatePlantingNoteDto, UpdateRemoveDatePlantingDto,
42 },
43 timeline::{TimelineDto, TimelineEntryDto},
44 ConfigDto, Coordinates, DeleteMapCollaboratorDto, GuidedToursDto, MapCollaboratorDto,
45 MapDto, NewMapCollaboratorDto, NewMapDto, NewSeedDto, PageLayerDto, PageMapDto,
46 PagePlantsSummaryDto, PageSeedDto, PlantsSummaryDto, RelationDto, RelationsDto,
47 SeedDto, UpdateGuidedToursDto, UpdateMapDto,
48 },
49 r#enum::{
50 privacy_access_control::PrivacyAccessControl, quality::Quality, quantity::Quantity,
51 shade::Shade, spatial_relation_type::SpatialRelationType,
52 },
53 },
54};
55
56#[derive(OpenApi)]
58#[openapi(paths(config::get), components(schemas(ConfigDto)))]
59struct ConfigApiDoc;
60
61#[derive(OpenApi)]
63#[openapi(
64 paths(
65 seed::find,
66 seed::find_by_id,
67 seed::create,
68 seed::delete_by_id
69 ),
70 components(
71 schemas(
72 PageSeedDto,
73 SeedDto,
74 NewSeedDto,
75 Quality,
76 Quantity
77 )
78 ),
79 modifiers(&SecurityAddon)
80)]
81struct SeedApiDoc;
82
83#[derive(OpenApi)]
85#[openapi(
86 paths(
87 plants::find,
88 plants::find_by_id
89 ),
90 components(
91 schemas(
92 PagePlantsSummaryDto,
93 PlantsSummaryDto
94 )
95 ),
96 modifiers(&SecurityAddon)
97)]
98struct PlantsApiDoc;
99
100#[derive(OpenApi)]
102#[openapi(
103 paths(
104 map::find,
105 map::find_by_id,
106 map::create,
107 map::update
108 ),
109 components(
110 schemas(
111 PageMapDto,
112 MapDto,
113 NewMapDto,
114 UpdateMapDto,
115 PrivacyAccessControl,
116 Coordinates
117 )
118 ),
119 modifiers(&SecurityAddon)
120)]
121struct MapApiDoc;
122
123#[derive(OpenApi)]
125#[openapi(
126 paths(
127 layers::find,
128 layers::find_by_id,
129 layers::create,
130 layers::delete
131 ),
132 components(
133 schemas(
134 LayerDto,
135 PageLayerDto,
136 ActionDtoWrapperNewLayer,
137 ActionDtoWrapperUpdateLayer,
138 ActionDtoWrapperDeleteLayer,
139 )
140 ),
141 modifiers(&SecurityAddon)
142)]
143struct LayerApiDoc;
144
145#[derive(OpenApi)]
147#[openapi(
148 paths(
149 plant_layer::heatmap,
150 plant_layer::find_relations
151 ),
152 components(
153 schemas(
154 RelationsDto,
155 RelationDto,
156 SpatialRelationType
157 )
158 ),
159 modifiers(&SecurityAddon)
160)]
161struct PlantLayerApiDoc;
162
163#[derive(OpenApi)]
165#[openapi(
166 paths(
167 base_layer_image::find,
168 base_layer_image::create,
169 base_layer_image::update,
170 base_layer_image::delete
171 ),
172 components(
173 schemas(
174 BaseLayerImageDto,
175 UpdateBaseLayerImageDto,
176 )
177 ),
178 modifiers(&SecurityAddon)
179)]
180struct BaseLayerImagesApiDoc;
181
182#[derive(OpenApi)]
184#[openapi(
185 paths(
186 plantings::find,
187 plantings::create,
188 plantings::update,
189 plantings::delete
190 ),
191 components(
192 schemas(
193 PlantingDto,
194 TimelinePagePlantingsDto,
195 UpdatePlantingDto,
196 TransformPlantingDto,
197 MovePlantingDto,
198 UpdateAddDatePlantingDto,
199 UpdateRemoveDatePlantingDto,
200 UpdatePlantingNoteDto,
201 ActionDtoWrapperNewPlantings,
202 ActionDtoWrapperUpdatePlantings,
203 ActionDtoWrapperDeletePlantings,
204 ActionDtoWrapperDeleteDrawings,
205 )
206 ),
207 modifiers(&SecurityAddon)
208)]
209struct PlantingsApiDoc;
210
211#[derive(OpenApi)]
213#[openapi(
214 paths(
215 areas::find,
216 areas::create,
217 areas::update,
218 areas::delete
219 ),
220 components(
221 schemas(
222 AreaKind,
223 AreaDto,
224 NewAreaDto,
225 UpdateAreaDto,
226 UpdateAddDateAreaDto,
227 UpdateRemoveDateAreaDto,
228 Shade
229 )
230 ),
231 modifiers(&SecurityAddon)
232)]
233struct AreasApiDoc;
234
235#[derive(OpenApi)]
237#[openapi(
238 paths(
239 users::find
240 ),
241 components(
242 schemas(
243 keycloak_api::UserDto
244 )
245 ),
246 modifiers(&SecurityAddon)
247)]
248struct UsersApiDoc;
249
250#[derive(OpenApi)]
252#[openapi(
253 paths(
254 guided_tours::setup,
255 guided_tours::find_by_user,
256 guided_tours::update
257 ),
258 components(
259 schemas(
260 GuidedToursDto,
261 UpdateGuidedToursDto
262 )
263 ),
264 modifiers(&SecurityAddon)
265)]
266struct GuidedToursApiDoc;
267
268#[derive(OpenApi)]
270#[openapi(
271 paths(
272 timeline::get_timeline,
273 ),
274 components(
275 schemas(
276 TimelineEntryDto,
277 TimelineDto
278 )
279 ),
280 modifiers(&SecurityAddon)
281)]
282struct TimelineApiDoc;
283
284#[derive(OpenApi)]
286#[openapi(
287 paths(
288 drawings::find,
289 drawings::create,
290 drawings::update,
291 drawings::delete,
292 ),
293 components(
294 schemas(
295 DrawingDto,
296 RectangleProperties,
297 EllipseProperties,
298 FreeLineProperties,
299 PolygonProperties,
300 LabelTextProperties,
301 ImageProperties,
302 UpdateAddDateDrawingDto,
303 UpdateRemoveDateDrawingDto,
304 UpdateNotesDrawingDto,
305 ActionDtoWrapperNewDrawings,
306 ActionDtoWrapperUpdateDrawings,
307 ActionDtoWrapperDeleteDrawings,
308 )
309 ),
310 modifiers(&SecurityAddon)
311)]
312struct DrawingsApiDoc;
313
314#[derive(OpenApi)]
316#[openapi(
317 paths(
318 map_collaborators::create,
319 map_collaborators::find,
320 map_collaborators::delete,
321 ),
322 components(
323 schemas(
324 NewMapCollaboratorDto,
325 MapCollaboratorDto,
326 DeleteMapCollaboratorDto,
327 )
328 ),
329 modifiers(&SecurityAddon)
330)]
331struct MapCollaboratorsApiDoc;
332
333pub fn config(cfg: &mut web::ServiceConfig) {
335 let mut openapi = ConfigApiDoc::openapi();
336 openapi.merge(SeedApiDoc::openapi());
337 openapi.merge(PlantsApiDoc::openapi());
338 openapi.merge(MapApiDoc::openapi());
339 openapi.merge(LayerApiDoc::openapi());
340 openapi.merge(PlantLayerApiDoc::openapi());
341 openapi.merge(BaseLayerImagesApiDoc::openapi());
342 openapi.merge(PlantingsApiDoc::openapi());
343 openapi.merge(AreasApiDoc::openapi());
344 openapi.merge(UsersApiDoc::openapi());
345 openapi.merge(TimelineApiDoc::openapi());
346 openapi.merge(DrawingsApiDoc::openapi());
347 openapi.merge(GuidedToursApiDoc::openapi());
348 openapi.merge(MapCollaboratorsApiDoc::openapi());
349
350 cfg.service(SwaggerUi::new("/doc/api/swagger/ui/{_:.*}").url("/doc/api/openapi.json", openapi));
351}
352
353struct SecurityAddon;
355
356impl Modify for SecurityAddon {
357 fn modify(&self, openapi: &mut utoipa::openapi::OpenApi) {
358 #[allow(clippy::unwrap_used)]
360 let components = openapi.components.as_mut().unwrap();
361
362 let config = &Config::get().openid_configuration;
363 let oauth2 = OAuth2::new([Flow::AuthorizationCode(AuthorizationCode::new(
364 config.authorization_endpoint.clone(),
365 config.token_endpoint.clone(),
366 Scopes::new(),
367 ))]);
368 components.add_security_scheme("oauth2", SecurityScheme::OAuth2(oauth2));
369 }
370}