backend/controller/
map_collaborators.rs

1use actix_web::{
2    delete, get, post,
3    web::{Json, Path},
4    HttpResponse, Result,
5};
6
7use crate::{
8    config::{
9        auth::user_info::UserInfo,
10        data::{SharedHttpClient, SharedKeycloakApi, SharedPool},
11    },
12    model::dto::{DeleteMapCollaboratorDto, NewMapCollaboratorDto},
13    service::{map_access_control::check_permissions, map_collaborator},
14};
15
16/// Endpoint for getting all [`MapCollaborator`](crate::model::entity::MapCollaborator)s of a map.
17///
18/// # Errors
19/// * If the connection to the database could not be established.
20/// * If the connection to the Keycloak API could not be established.
21#[utoipa::path(
22    context_path = "/api/maps/{map_id}/collaborators",
23    params(
24        ("map_id" = i32, Path, description = "The id of the map on which to collaborate"),
25    ),
26    responses(
27        (status = 200, description = "The collaborators of this map", body = Vec<MapCollaboratorDto>),
28    ),
29    security(
30        ("oauth2" = [])
31    )
32)]
33#[get("")]
34pub async fn find(
35    map_id: Path<i32>,
36    pool: SharedPool,
37    keycloak_api: SharedKeycloakApi,
38    http_client: SharedHttpClient,
39    user_info: UserInfo,
40) -> Result<HttpResponse> {
41    let id = map_id.into_inner();
42    check_permissions(id, &pool, user_info).await?;
43    let response = map_collaborator::get_all(id, &pool, &keycloak_api, &http_client).await?;
44
45    Ok(HttpResponse::Ok().json(response))
46}
47
48/// Endpoint for creating a new [`MapCollaborator`](crate::model::entity::MapCollaborator).
49///
50/// # Errors
51/// * If the connection to the database could not be established.
52/// * If the connection to the Keycloak API could not be established.
53#[utoipa::path(
54    context_path = "/api/maps/{map_id}/collaborators",
55    params(
56        ("map_id" = i32, Path, description = "The id of the map on which to collaborate"),
57    ),
58    request_body = NewMapCollaboratorDto,
59    responses(
60        (status = 201, description = "Add a new map collaborator", body = MapCollaboratorDto),
61    ),
62    security(
63        ("oauth2" = [])
64    )
65)]
66#[post("")]
67pub async fn create(
68    json: Json<NewMapCollaboratorDto>,
69    map_id: Path<i32>,
70    user_info: UserInfo,
71    pool: SharedPool,
72    keycloak_api: SharedKeycloakApi,
73    http_client: SharedHttpClient,
74) -> Result<HttpResponse> {
75    let id = map_id.into_inner();
76    let user_id = user_info.id;
77    check_permissions(id, &pool, user_info).await?;
78    let response = map_collaborator::create(
79        (id, json.into_inner()),
80        user_id,
81        &pool,
82        &keycloak_api,
83        &http_client,
84    )
85    .await?;
86
87    Ok(HttpResponse::Created().json(response))
88}
89
90/// Endpoint for deleting a collaborator from a map.
91///
92/// # Errors
93/// * If the user is not the creator of the map.
94/// * If the connection to the database could not be established.
95#[utoipa::path(
96    context_path = "/api/maps/{map_id}/collaborators",
97    params(
98        ("map_id" = i32, Path, description = "The id of the map on which to collaborate"),
99    ),
100    request_body = DeleteMapCollaboratorDto,
101    responses(
102        (status = 204, description = "The collaborator was removed from the map"),
103    ),
104    security(
105        ("oauth2" = [])
106    )
107)]
108#[delete("")]
109pub async fn delete(
110    map_id: Path<i32>,
111    dto: Json<DeleteMapCollaboratorDto>,
112    user_info: UserInfo,
113    pool: SharedPool,
114) -> Result<HttpResponse> {
115    let id = map_id.into_inner();
116    let user_id = user_info.id;
117    check_permissions(id, &pool, user_info).await?;
118    map_collaborator::delete((id, dto.into_inner()), user_id, &pool).await?;
119
120    Ok(HttpResponse::NoContent().finish())
121}