feat: Add PUT route for updating teams in user assets

- Introduced a new module `put_teams` to handle updates for teams.
- Added a PUT route for `/teams` in the user assets router, allowing for team modifications.
- Enhanced the routing capabilities of the user assets API to support both GET and PUT requests for teams.
This commit is contained in:
dal 2025-01-20 16:50:50 -07:00
parent dcb7c5ef98
commit 9b33f26f17
No known key found for this signature in database
GPG Key ID: 16F4B0E1E9F61122
2 changed files with 103 additions and 1 deletions

View File

@ -1,10 +1,11 @@
use axum::{routing::get, Router};
use axum::{routing::get, routing::put, Router};
pub mod list_attributes;
pub mod list_dataset_groups;
pub mod list_datasets;
pub mod list_permission_groups;
pub mod list_teams;
pub mod put_teams;
pub fn router() -> Router {
Router::new()
@ -19,4 +20,5 @@ pub fn router() -> Router {
get(list_permission_groups::list_permission_groups),
)
.route("/teams", get(list_teams::list_teams))
.route("/teams", put(put_teams::put_teams))
}

View File

@ -0,0 +1,100 @@
use anyhow::Result;
use axum::extract::Path;
use axum::http::StatusCode;
use axum::{Extension, Json};
use diesel::prelude::*;
use diesel_async::RunQueryDsl;
use serde::Serialize;
use tokio::spawn;
use uuid::Uuid;
use crate::database::lib::get_pg_pool;
use crate::database::models::User;
use crate::database::schema::{teams_to_users};
use crate::routes::rest::ApiResponse;
use crate::utils::security::checks::is_user_workspace_admin_or_data_admin;
use crate::utils::user::user_info::get_user_organization_id;
#[derive(Debug, Serialize)]
pub struct TeamAssignment {
pub id: Uuid,
pub assigned: bool,
}
pub async fn put_teams(
Extension(user): Extension<User>,
Path(id): Path<Uuid>,
Json(assignments): Json<Vec<TeamAssignment>>,
) -> Result<ApiResponse<()>, (StatusCode, &'static str)> {
match put_teams_handler(user, id, assignments).await {
Ok(_) => (),
Err(e) => {
tracing::error!("Error listing teams: {:?}", e);
return Err((StatusCode::INTERNAL_SERVER_ERROR, "Error listing teams"));
}
};
Ok(ApiResponse::NoContent)
}
async fn put_teams_handler(
user: User,
user_id: Uuid,
assignments: Vec<TeamAssignment>,
) -> Result<()> {
let organization_id = get_user_organization_id(&user_id).await?;
if !is_user_workspace_admin_or_data_admin(&user, &organization_id).await? {
return Err(anyhow::anyhow!("User is not authorized to list teams"));
};
let (to_assign, to_unassign): (Vec<_>, Vec<_>) =
assignments.into_iter().partition(|a| a.assigned);
let assign_handle = {
let user_id = user_id;
spawn(async move {
if !to_assign.is_empty() {
let mut conn = get_pg_pool().get().await?;
for team in to_assign {
diesel::insert_into(teams_to_users::table)
.values((
teams_to_users::team_id.eq(team.id),
teams_to_users::user_id.eq(user_id),
))
.on_conflict((teams_to_users::team_id, teams_to_users::user_id))
.do_update()
.set(teams_to_users::deleted_at.eq(None::<chrono::DateTime<chrono::Utc>>))
.execute(&mut *conn)
.await?;
}
}
Ok::<_, anyhow::Error>(())
})
};
let unassign_handle = {
let user_id = user_id;
spawn(async move {
if !to_unassign.is_empty() {
let mut conn = get_pg_pool().get().await?;
diesel::update(teams_to_users::table)
.filter(
teams_to_users::team_id
.eq_any(to_unassign.iter().map(|a| a.id))
.and(teams_to_users::user_id.eq(user_id)),
)
.set(teams_to_users::deleted_at.eq(chrono::Utc::now()))
.execute(&mut *conn)
.await?;
}
Ok::<_, anyhow::Error>(())
})
};
let (assign_result, unassign_result) = tokio::try_join!(assign_handle, unassign_handle)?;
assign_result?;
unassign_result?;
Ok(())
}