diff --git a/src/routes/v3/projects.rs b/src/routes/v3/projects.rs index 0d37dc45..a7ab61fe 100644 --- a/src/routes/v3/projects.rs +++ b/src/routes/v3/projects.rs @@ -6,7 +6,7 @@ use crate::auth::{filter_visible_projects, get_user_from_headers}; use crate::database::models::notification_item::NotificationBuilder; use crate::database::models::project_item::{GalleryItem, ModCategory}; use crate::database::models::thread_item::ThreadMessageBuilder; -use crate::database::models::{ids as db_ids, image_item}; +use crate::database::models::{ids as db_ids, image_item, TeamMember}; use crate::database::redis::RedisPool; use crate::database::{self, models as db_models}; use crate::file_hosting::FileHost; @@ -2194,18 +2194,26 @@ pub async fn project_get_organization( redis: web::Data, session_queue: web::Data, ) -> Result { - let user = get_user_from_headers(&req, &**pool, &redis, &session_queue, None) - .await? - .1; - let string = info.into_inner().0; + let current_user = get_user_from_headers( + &req, + &**pool, + &redis, + &session_queue, + Some(&[Scopes::PROJECT_READ, Scopes::ORGANIZATION_READ]), + ) + .await + .map(|x| x.1) + .ok(); + let user_id = current_user.as_ref().map(|x| x.id.into()); + let string = info.into_inner().0; let result = db_models::Project::get(&string, &**pool, &redis) .await? .ok_or_else(|| { ApiError::InvalidInput("The specified project does not exist!".to_string()) })?; - if is_visible_project(&result.inner, &Some(user), &pool).await? { + if !is_visible_project(&result.inner, ¤t_user, &pool).await? { Err(ApiError::InvalidInput( "The specified project does not exist!".to_string(), )) @@ -2213,10 +2221,44 @@ pub async fn project_get_organization( let organization = db_models::Organization::get_id(organization_id, &**pool, &redis) .await? .ok_or_else(|| { - ApiError::InvalidInput("The specified organization does not exist!".to_string()) + ApiError::InvalidInput("The attached organization does not exist!".to_string()) })?; - Ok(HttpResponse::Ok().json(organization)) + let members_data = + TeamMember::get_from_team_full(organization.team_id, &**pool, &redis).await?; + + let users = crate::database::models::User::get_many_ids( + &members_data.iter().map(|x| x.user_id).collect::>(), + &**pool, + &redis, + ) + .await?; + let logged_in = current_user + .as_ref() + .and_then(|user| { + members_data + .iter() + .find(|x| x.user_id == user.id.into() && x.accepted) + }) + .is_some(); + let team_members: Vec<_> = members_data + .into_iter() + .filter(|x| { + logged_in + || x.accepted + || user_id + .map(|y: crate::database::models::UserId| y == x.user_id) + .unwrap_or(false) + }) + .flat_map(|data| { + users.iter().find(|x| x.id == data.user_id).map(|user| { + crate::models::teams::TeamMember::from(data, user.clone(), !logged_in) + }) + }) + .collect(); + + let organization = models::organizations::Organization::from(organization, team_members); + return Ok(HttpResponse::Ok().json(organization)); } else { Err(ApiError::NotFound) } diff --git a/tests/common/api_v3/project.rs b/tests/common/api_v3/project.rs index 46c087ad..8aa09570 100644 --- a/tests/common/api_v3/project.rs +++ b/tests/common/api_v3/project.rs @@ -9,7 +9,8 @@ use async_trait::async_trait; use bytes::Bytes; use chrono::{DateTime, Utc}; use labrinth::{ - models::projects::Project, routes::v3::projects::ReturnSearchResults, + models::{organizations::Organization, projects::Project}, + routes::v3::projects::ReturnSearchResults, util::actix::AppendsMultipart, }; use rust_decimal::Decimal; @@ -483,6 +484,29 @@ impl ApiV3 { test::read_body_json(resp).await } + pub async fn get_project_organization( + &self, + id_or_slug: &str, + pat: Option<&str>, + ) -> ServiceResponse { + let req = test::TestRequest::get() + .uri(&format!("/v3/project/{id_or_slug}/organization")) + .append_pat(pat) + .to_request(); + + self.call(req).await + } + + pub async fn get_project_organization_deserialized( + &self, + id_or_slug: &str, + pat: Option<&str>, + ) -> Organization { + let resp = self.get_project_organization(id_or_slug, pat).await; + assert_eq!(resp.status(), 200); + test::read_body_json(resp).await + } + pub async fn search_deserialized( &self, query: Option<&str>, diff --git a/tests/organizations.rs b/tests/organizations.rs index 1e071e4d..cad33fdc 100644 --- a/tests/organizations.rs +++ b/tests/organizations.rs @@ -84,6 +84,28 @@ async fn create_organization() { .await; } +#[actix_rt::test] +async fn get_project_organization() { + with_test_environment(None, |test_env: TestEnvironment| async move { + let api = &test_env.api; + let zeta_organization_id = &test_env.dummy.organization_zeta.organization_id; + let alpha_project_id = &test_env.dummy.project_alpha.project_id; + + // ADd alpha project to zeta organization + let resp = api + .organization_add_project(zeta_organization_id, alpha_project_id, USER_USER_PAT) + .await; + assert_eq!(resp.status(), 200); + + // Get project organization + let zeta = api + .get_project_organization_deserialized(alpha_project_id, USER_USER_PAT) + .await; + assert_eq!(zeta.id.to_string(), zeta_organization_id.to_string()); + }) + .await; +} + #[actix_rt::test] async fn patch_organization() { with_test_environment(None, |test_env: TestEnvironment| async move {