backend/service/
map_collaborator.rs1use actix_http::StatusCode;
2use uuid::Uuid;
3
4use crate::{
5 config::data::{SharedHttpClient, SharedKeycloakApi, SharedPool},
6 error::ServiceError,
7 model::{
8 dto::{DeleteMapCollaboratorDto, MapCollaboratorDto, NewMapCollaboratorDto},
9 entity::{Map, MapCollaborator},
10 },
11 service::users,
12};
13
14const MAX_COLLABORATORS: usize = 30;
16
17pub async fn get_all(
23 map_id: i32,
24 pool: &SharedPool,
25 keycloak_api: &SharedKeycloakApi,
26 http_client: &SharedHttpClient,
27) -> Result<Vec<MapCollaboratorDto>, ServiceError> {
28 let mut conn = pool.get().await?;
29 let _ = Map::find_by_id(map_id, &mut conn).await?;
31
32 let collaborators = MapCollaborator::find_by_map_id(map_id, &mut conn).await?;
33
34 let collaborator_ids = collaborators.iter().map(|c| c.user_id).collect::<Vec<_>>();
35 let users = users::find_by_ids(collaborator_ids, keycloak_api, http_client).await?;
36
37 let dtos = collaborators
38 .into_iter()
39 .zip(users.into_iter())
40 .map(|(c, u)| MapCollaboratorDto::from((c, u)))
41 .collect::<Vec<MapCollaboratorDto>>();
42
43 Ok(dtos)
44}
45
46pub async fn create(
55 map_and_collaborator: (i32, NewMapCollaboratorDto),
56 user_id: Uuid,
57 pool: &SharedPool,
58 keycloak_api: &SharedKeycloakApi,
59 http_client: &SharedHttpClient,
60) -> Result<MapCollaboratorDto, ServiceError> {
61 let (map_id, ref new_map_collaborator) = map_and_collaborator;
62
63 if new_map_collaborator.user_id == user_id {
64 return Err(ServiceError::new(
65 StatusCode::BAD_REQUEST,
66 "You cannot add yourself as a collaborator.",
67 ));
68 }
69
70 let mut conn = pool.get().await?;
71
72 let map = Map::find_by_id(map_id, &mut conn).await?;
73
74 if map.created_by != user_id {
75 return Err(ServiceError::new(
76 StatusCode::FORBIDDEN,
77 "You are not the creator of this map.",
78 ));
79 }
80
81 let current_collaborators = MapCollaborator::find_by_map_id(map_id, &mut conn).await?;
82
83 if current_collaborators.len() >= MAX_COLLABORATORS {
84 return Err(ServiceError::new(
85 StatusCode::BAD_REQUEST,
86 &format!("A map can have at most {MAX_COLLABORATORS} collaborators."),
87 ));
88 }
89
90 let collaborator_user =
91 users::find_by_id(new_map_collaborator.user_id, keycloak_api, http_client).await?;
92
93 let collaborator = MapCollaborator::create(map_and_collaborator, &mut conn).await?;
94
95 Ok(MapCollaboratorDto::from((collaborator, collaborator_user)))
96}
97
98pub async fn delete(
105 map_and_dto: (i32, DeleteMapCollaboratorDto),
106 user_id: Uuid,
107 pool: &SharedPool,
108) -> Result<(), ServiceError> {
109 let (map_id, _) = map_and_dto;
110
111 let mut conn = pool.get().await?;
112
113 let map = Map::find_by_id(map_id, &mut conn).await?;
114
115 if map.created_by != user_id {
116 return Err(ServiceError::new(
117 StatusCode::FORBIDDEN,
118 "You are not the creator of this map.",
119 ));
120 }
121
122 MapCollaborator::delete(map_and_dto, &mut conn).await?;
123
124 Ok(())
125}