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