use actix_http::StatusCode;
use uuid::Uuid;
use crate::{
config::data::{SharedHttpClient, SharedKeycloakApi, SharedPool},
error::ServiceError,
model::{
dto::{DeleteMapCollaboratorDto, MapCollaboratorDto, NewMapCollaboratorDto},
entity::{Map, MapCollaborator},
},
service::users,
};
const MAX_COLLABORATORS: usize = 30;
pub async fn get_all(
map_id: i32,
pool: &SharedPool,
keycloak_api: &SharedKeycloakApi,
http_client: &SharedHttpClient,
) -> Result<Vec<MapCollaboratorDto>, ServiceError> {
let mut conn = pool.get().await?;
let _ = Map::find_by_id(map_id, &mut conn).await?;
let collaborators = MapCollaborator::find_by_map_id(map_id, &mut conn).await?;
let collaborator_ids = collaborators.iter().map(|c| c.user_id).collect::<Vec<_>>();
let users = users::find_by_ids(collaborator_ids, keycloak_api, http_client).await?;
let dtos = collaborators
.into_iter()
.zip(users.into_iter())
.map(|(c, u)| MapCollaboratorDto::from((c, u)))
.collect::<Vec<MapCollaboratorDto>>();
Ok(dtos)
}
pub async fn create(
map_and_collaborator: (i32, NewMapCollaboratorDto),
user_id: Uuid,
pool: &SharedPool,
keycloak_api: &SharedKeycloakApi,
http_client: &SharedHttpClient,
) -> Result<MapCollaboratorDto, ServiceError> {
let (map_id, ref new_map_collaborator) = map_and_collaborator;
if new_map_collaborator.user_id == user_id {
return Err(ServiceError::new(
StatusCode::BAD_REQUEST,
"You cannot add yourself as a collaborator.",
));
}
let mut conn = pool.get().await?;
let map = Map::find_by_id(map_id, &mut conn).await?;
if map.created_by != user_id {
return Err(ServiceError::new(
StatusCode::FORBIDDEN,
"You are not the creator of this map.",
));
}
let current_collaborators = MapCollaborator::find_by_map_id(map_id, &mut conn).await?;
if current_collaborators.len() >= MAX_COLLABORATORS {
return Err(ServiceError::new(
StatusCode::BAD_REQUEST,
&format!("A map can have at most {MAX_COLLABORATORS} collaborators."),
));
}
let collaborator_user =
users::find_by_id(new_map_collaborator.user_id, keycloak_api, http_client).await?;
let collaborator = MapCollaborator::create(map_and_collaborator, &mut conn).await?;
Ok(MapCollaboratorDto::from((collaborator, collaborator_user)))
}
pub async fn delete(
map_and_dto: (i32, DeleteMapCollaboratorDto),
user_id: Uuid,
pool: &SharedPool,
) -> Result<(), ServiceError> {
let (map_id, _) = map_and_dto;
let mut conn = pool.get().await?;
let map = Map::find_by_id(map_id, &mut conn).await?;
if map.created_by != user_id {
return Err(ServiceError::new(
StatusCode::FORBIDDEN,
"You are not the creator of this map.",
));
}
MapCollaborator::delete(map_and_dto, &mut conn).await?;
Ok(())
}