You've already forked AstralRinth
forked from didirus/AstralRinth
Misc testing improvements (#805)
* made dummy data more consistent; not an option * fixed variable dropping issue crashing actix (?) * removed scopes specific tests, removed schedule tests * team routes use api * removed printlns, fmt clippy prepare
This commit is contained in:
@@ -1,16 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n UPDATE versions\n SET status = $1, date_published = $2\n WHERE (id = $3)\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Varchar",
|
||||
"Timestamptz",
|
||||
"Int8"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "03006da8781d9c07d564c6b406221cb0557623abe3242e79a21868482e6d9898"
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n UPDATE mods\n SET status = $1, approved = $2\n WHERE (id = $3)\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Varchar",
|
||||
"Timestamptz",
|
||||
"Int8"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "a440cb2567825c3cc540c9b0831ee840f6e2a6394e89a851b83fc78220594cf2"
|
||||
}
|
||||
@@ -9,8 +9,7 @@ use crate::models::v2::projects::LegacyVersion;
|
||||
use crate::queue::session::AuthQueue;
|
||||
use crate::routes::{v2_reroute, v3};
|
||||
use crate::search::SearchConfig;
|
||||
use actix_web::{delete, get, patch, post, web, HttpRequest, HttpResponse};
|
||||
use chrono::{DateTime, Utc};
|
||||
use actix_web::{delete, get, patch, web, HttpRequest, HttpResponse};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sqlx::PgPool;
|
||||
use validator::Validate;
|
||||
@@ -24,7 +23,6 @@ pub fn config(cfg: &mut web::ServiceConfig) {
|
||||
.service(version_get)
|
||||
.service(version_delete)
|
||||
.service(version_edit)
|
||||
.service(version_schedule)
|
||||
.service(super::version_creation::upload_file_to_version),
|
||||
);
|
||||
}
|
||||
@@ -275,36 +273,3 @@ pub async fn version_delete(
|
||||
.await
|
||||
.or_else(v2_reroute::flatten_404_error)
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct SchedulingData {
|
||||
pub time: DateTime<Utc>,
|
||||
pub requested_status: VersionStatus,
|
||||
}
|
||||
|
||||
#[post("{id}/schedule")]
|
||||
pub async fn version_schedule(
|
||||
req: HttpRequest,
|
||||
info: web::Path<(VersionId,)>,
|
||||
pool: web::Data<PgPool>,
|
||||
redis: web::Data<RedisPool>,
|
||||
scheduling_data: web::Json<SchedulingData>,
|
||||
session_queue: web::Data<AuthQueue>,
|
||||
) -> Result<HttpResponse, ApiError> {
|
||||
// Returns NoContent, so we don't need to convert the response
|
||||
let scheduling_data = scheduling_data.into_inner();
|
||||
let scheduling_data = v3::versions::SchedulingData {
|
||||
time: scheduling_data.time,
|
||||
requested_status: scheduling_data.requested_status,
|
||||
};
|
||||
v3::versions::version_schedule(
|
||||
req,
|
||||
info,
|
||||
pool,
|
||||
redis,
|
||||
web::Json(scheduling_data),
|
||||
session_queue,
|
||||
)
|
||||
.await
|
||||
.or_else(v2_reroute::flatten_404_error)
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ use crate::util::img;
|
||||
use crate::util::routes::read_from_payload;
|
||||
use crate::util::validate::validation_errors_to_string;
|
||||
use actix_web::{web, HttpRequest, HttpResponse};
|
||||
use chrono::{DateTime, Utc};
|
||||
use chrono::Utc;
|
||||
use futures::TryStreamExt;
|
||||
use itertools::Itertools;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -54,7 +54,6 @@ pub fn config(cfg: &mut web::ServiceConfig) {
|
||||
.route("{id}/gallery", web::delete().to(delete_gallery_item))
|
||||
.route("{id}/follow", web::post().to(project_follow))
|
||||
.route("{id}/follow", web::delete().to(project_unfollow))
|
||||
.route("{id}/schedule", web::post().to(project_schedule))
|
||||
.service(
|
||||
web::scope("{project_id}")
|
||||
.route(
|
||||
@@ -1305,100 +1304,6 @@ pub async fn bulk_edit_project_categories(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct SchedulingData {
|
||||
pub time: DateTime<Utc>,
|
||||
pub requested_status: ProjectStatus,
|
||||
}
|
||||
|
||||
pub async fn project_schedule(
|
||||
req: HttpRequest,
|
||||
info: web::Path<(String,)>,
|
||||
pool: web::Data<PgPool>,
|
||||
redis: web::Data<RedisPool>,
|
||||
session_queue: web::Data<AuthQueue>,
|
||||
scheduling_data: web::Json<SchedulingData>,
|
||||
) -> Result<HttpResponse, ApiError> {
|
||||
let user = get_user_from_headers(
|
||||
&req,
|
||||
&**pool,
|
||||
&redis,
|
||||
&session_queue,
|
||||
Some(&[Scopes::PROJECT_WRITE]),
|
||||
)
|
||||
.await?
|
||||
.1;
|
||||
|
||||
if scheduling_data.time < Utc::now() {
|
||||
return Err(ApiError::InvalidInput(
|
||||
"You cannot schedule a project to be released in the past!".to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
if !scheduling_data.requested_status.can_be_requested() {
|
||||
return Err(ApiError::InvalidInput(
|
||||
"Specified requested status cannot be requested!".to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
let string = info.into_inner().0;
|
||||
let result = db_models::Project::get(&string, &**pool, &redis).await?;
|
||||
|
||||
if let Some(project_item) = result {
|
||||
let (team_member, organization_team_member) =
|
||||
db_models::TeamMember::get_for_project_permissions(
|
||||
&project_item.inner,
|
||||
user.id.into(),
|
||||
&**pool,
|
||||
)
|
||||
.await?;
|
||||
|
||||
let permissions = ProjectPermissions::get_permissions_by_role(
|
||||
&user.role,
|
||||
&team_member.clone(),
|
||||
&organization_team_member.clone(),
|
||||
)
|
||||
.unwrap_or_default();
|
||||
|
||||
if !user.role.is_mod() && !permissions.contains(ProjectPermissions::EDIT_DETAILS) {
|
||||
return Err(ApiError::CustomAuthentication(
|
||||
"You do not have permission to edit this project's scheduling data!".to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
if !project_item.inner.status.is_approved() {
|
||||
return Err(ApiError::InvalidInput(
|
||||
"This project has not been approved yet. Submit to the queue with the private status to schedule it in the future!".to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
sqlx::query!(
|
||||
"
|
||||
UPDATE mods
|
||||
SET status = $1, approved = $2
|
||||
WHERE (id = $3)
|
||||
",
|
||||
ProjectStatus::Scheduled.as_str(),
|
||||
scheduling_data.time,
|
||||
project_item.inner.id as db_ids::ProjectId,
|
||||
)
|
||||
.execute(&**pool)
|
||||
.await?;
|
||||
|
||||
db_models::Project::clear_cache(
|
||||
project_item.inner.id,
|
||||
project_item.inner.slug,
|
||||
None,
|
||||
&redis,
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(HttpResponse::NoContent().body(""))
|
||||
} else {
|
||||
Err(ApiError::NotFound)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct Extension {
|
||||
pub ext: String,
|
||||
|
||||
@@ -25,7 +25,6 @@ use crate::search::SearchConfig;
|
||||
use crate::util::img;
|
||||
use crate::util::validate::validation_errors_to_string;
|
||||
use actix_web::{web, HttpRequest, HttpResponse};
|
||||
use chrono::{DateTime, Utc};
|
||||
use itertools::Itertools;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sqlx::PgPool;
|
||||
@@ -43,7 +42,6 @@ pub fn config(cfg: &mut web::ServiceConfig) {
|
||||
.route("{id}", web::get().to(version_get))
|
||||
.route("{id}", web::patch().to(version_edit))
|
||||
.route("{id}", web::delete().to(version_delete))
|
||||
.route("{id}/schedule", web::post().to(version_schedule))
|
||||
.route(
|
||||
"{version_id}/file",
|
||||
web::post().to(super::version_creation::upload_file_to_version),
|
||||
@@ -828,108 +826,6 @@ pub async fn version_list(
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct SchedulingData {
|
||||
pub time: DateTime<Utc>,
|
||||
pub requested_status: VersionStatus,
|
||||
}
|
||||
|
||||
pub async fn version_schedule(
|
||||
req: HttpRequest,
|
||||
info: web::Path<(models::ids::VersionId,)>,
|
||||
pool: web::Data<PgPool>,
|
||||
redis: web::Data<RedisPool>,
|
||||
scheduling_data: web::Json<SchedulingData>,
|
||||
session_queue: web::Data<AuthQueue>,
|
||||
) -> Result<HttpResponse, ApiError> {
|
||||
let user = get_user_from_headers(
|
||||
&req,
|
||||
&**pool,
|
||||
&redis,
|
||||
&session_queue,
|
||||
Some(&[Scopes::VERSION_WRITE]),
|
||||
)
|
||||
.await?
|
||||
.1;
|
||||
|
||||
if scheduling_data.time < Utc::now() {
|
||||
return Err(ApiError::InvalidInput(
|
||||
"You cannot schedule a version to be released in the past!".to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
if !scheduling_data.requested_status.can_be_requested() {
|
||||
return Err(ApiError::InvalidInput(
|
||||
"Specified requested status cannot be requested!".to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
let string = info.into_inner().0;
|
||||
let result = database::models::Version::get(string.into(), &**pool, &redis).await?;
|
||||
|
||||
if let Some(version_item) = result {
|
||||
let team_member = database::models::TeamMember::get_from_user_id_project(
|
||||
version_item.inner.project_id,
|
||||
user.id.into(),
|
||||
&**pool,
|
||||
)
|
||||
.await?;
|
||||
|
||||
let organization_item =
|
||||
database::models::Organization::get_associated_organization_project_id(
|
||||
version_item.inner.project_id,
|
||||
&**pool,
|
||||
)
|
||||
.await
|
||||
.map_err(ApiError::Database)?;
|
||||
|
||||
let organization_team_member = if let Some(organization) = &organization_item {
|
||||
database::models::TeamMember::get_from_user_id(
|
||||
organization.team_id,
|
||||
user.id.into(),
|
||||
&**pool,
|
||||
)
|
||||
.await?
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let permissions = ProjectPermissions::get_permissions_by_role(
|
||||
&user.role,
|
||||
&team_member,
|
||||
&organization_team_member,
|
||||
)
|
||||
.unwrap_or_default();
|
||||
|
||||
if !user.role.is_mod() && !permissions.contains(ProjectPermissions::EDIT_DETAILS) {
|
||||
return Err(ApiError::CustomAuthentication(
|
||||
"You do not have permission to edit this version's scheduling data!".to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
let mut transaction = pool.begin().await?;
|
||||
sqlx::query!(
|
||||
"
|
||||
UPDATE versions
|
||||
SET status = $1, date_published = $2
|
||||
WHERE (id = $3)
|
||||
",
|
||||
VersionStatus::Scheduled.as_str(),
|
||||
scheduling_data.time,
|
||||
version_item.inner.id as database::models::ids::VersionId,
|
||||
)
|
||||
.execute(&mut *transaction)
|
||||
.await?;
|
||||
|
||||
transaction.commit().await?;
|
||||
database::models::Version::clear_cache(&version_item, &redis).await?;
|
||||
|
||||
Ok(HttpResponse::NoContent().body(""))
|
||||
} else {
|
||||
Err(ApiError::NotFound)
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn version_delete(
|
||||
req: HttpRequest,
|
||||
info: web::Path<(models::ids::VersionId,)>,
|
||||
|
||||
@@ -19,13 +19,7 @@ pub async fn analytics_revenue() {
|
||||
with_test_environment(None, |test_env: TestEnvironment<ApiV3>| async move {
|
||||
let api = &test_env.api;
|
||||
|
||||
let alpha_project_id = test_env
|
||||
.dummy
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.project_alpha
|
||||
.project_id
|
||||
.clone();
|
||||
let alpha_project_id = test_env.dummy.project_alpha.project_id.clone();
|
||||
|
||||
let pool = test_env.db.pool.clone();
|
||||
|
||||
@@ -143,27 +137,9 @@ fn to_f64_vec_rounded_up(d: Vec<Decimal>) -> Vec<f64> {
|
||||
#[actix_rt::test]
|
||||
pub async fn permissions_analytics_revenue() {
|
||||
with_test_environment(None, |test_env: TestEnvironment<ApiV3>| async move {
|
||||
let alpha_project_id = test_env
|
||||
.dummy
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.project_alpha
|
||||
.project_id
|
||||
.clone();
|
||||
let alpha_version_id = test_env
|
||||
.dummy
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.project_alpha
|
||||
.version_id
|
||||
.clone();
|
||||
let alpha_team_id = test_env
|
||||
.dummy
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.project_alpha
|
||||
.team_id
|
||||
.clone();
|
||||
let alpha_project_id = test_env.dummy.project_alpha.project_id.clone();
|
||||
let alpha_version_id = test_env.dummy.project_alpha.version_id.clone();
|
||||
let alpha_team_id = test_env.dummy.project_alpha.team_id.clone();
|
||||
|
||||
let api = &test_env.api;
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ use crate::common::{api_v2::ApiV2, api_v3::ApiV3, dummy_data::TestFile};
|
||||
use super::{
|
||||
models::{CommonProject, CommonVersion},
|
||||
request_data::{ImageData, ProjectCreationRequestData},
|
||||
Api, ApiProject, ApiTags, ApiTeams, ApiVersion,
|
||||
Api, ApiProject, ApiTags, ApiTeams, ApiUser, ApiVersion,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@@ -71,17 +71,28 @@ delegate_api_variant!(
|
||||
[remove_project, ServiceResponse, project_slug_or_id: &str, pat: Option<&str>],
|
||||
[get_project, ServiceResponse, id_or_slug: &str, pat: Option<&str>],
|
||||
[get_project_deserialized_common, CommonProject, id_or_slug: &str, pat: Option<&str>],
|
||||
[get_projects, ServiceResponse, ids_or_slugs: &[&str], pat: Option<&str>],
|
||||
[get_project_dependencies, ServiceResponse, id_or_slug: &str, pat: Option<&str>],
|
||||
[get_user_projects, ServiceResponse, user_id_or_username: &str, pat: Option<&str>],
|
||||
[get_user_projects_deserialized_common, Vec<CommonProject>, user_id_or_username: &str, pat: Option<&str>],
|
||||
[edit_project, ServiceResponse, id_or_slug: &str, patch: serde_json::Value, pat: Option<&str>],
|
||||
[edit_project_bulk, ServiceResponse, ids_or_slugs: &[&str], patch: serde_json::Value, pat: Option<&str>],
|
||||
[edit_project_icon, ServiceResponse, id_or_slug: &str, icon: Option<ImageData>, pat: Option<&str>],
|
||||
[schedule_project, ServiceResponse, id_or_slug: &str, requested_status: &str, date : chrono::DateTime<chrono::Utc>, pat: Option<&str>],
|
||||
[add_gallery_item, ServiceResponse, id_or_slug: &str, image: ImageData, featured: bool, title: Option<String>, description: Option<String>, ordering: Option<i32>, pat: Option<&str>],
|
||||
[remove_gallery_item, ServiceResponse, id_or_slug: &str, image_url: &str, pat: Option<&str>],
|
||||
[edit_gallery_item, ServiceResponse, id_or_slug: &str, image_url: &str, patch: HashMap<String, String>, pat: Option<&str>],
|
||||
[create_report, ServiceResponse, report_type: &str, id: &str, item_type: crate::common::api_common::models::CommonItemType, body: &str, pat: Option<&str>],
|
||||
[get_report, ServiceResponse, id: &str, pat: Option<&str>],
|
||||
[get_reports, ServiceResponse, ids: &[&str], pat: Option<&str>],
|
||||
[get_user_reports, ServiceResponse, pat: Option<&str>],
|
||||
[edit_report, ServiceResponse, id: &str, patch: serde_json::Value, pat: Option<&str>],
|
||||
[delete_report, ServiceResponse, id: &str, pat: Option<&str>],
|
||||
[get_thread, ServiceResponse, id: &str, pat: Option<&str>],
|
||||
[get_threads, ServiceResponse, ids: &[&str], pat: Option<&str>],
|
||||
[write_to_thread, ServiceResponse, id: &str, r#type : &str, message: &str, pat: Option<&str>],
|
||||
[get_moderation_inbox, ServiceResponse, pat: Option<&str>],
|
||||
[read_thread, ServiceResponse, id: &str, pat: Option<&str>],
|
||||
[delete_thread_message, ServiceResponse, id: &str, pat: Option<&str>],
|
||||
}
|
||||
);
|
||||
|
||||
@@ -100,6 +111,7 @@ delegate_api_variant!(
|
||||
impl ApiTeams for GenericApi {
|
||||
[get_team_members, ServiceResponse, team_id: &str, pat: Option<&str>],
|
||||
[get_team_members_deserialized_common, Vec<crate::common::api_common::models::CommonTeamMember>, team_id: &str, pat: Option<&str>],
|
||||
[get_teams_members, ServiceResponse, ids: &[&str], pat: Option<&str>],
|
||||
[get_project_members, ServiceResponse, id_or_slug: &str, pat: Option<&str>],
|
||||
[get_project_members_deserialized_common, Vec<crate::common::api_common::models::CommonTeamMember>, id_or_slug: &str, pat: Option<&str>],
|
||||
[get_organization_members, ServiceResponse, id_or_title: &str, pat: Option<&str>],
|
||||
@@ -110,9 +122,23 @@ delegate_api_variant!(
|
||||
[transfer_team_ownership, ServiceResponse, team_id: &str, user_id: &str, pat: Option<&str>],
|
||||
[get_user_notifications, ServiceResponse, user_id: &str, pat: Option<&str>],
|
||||
[get_user_notifications_deserialized_common, Vec<crate::common::api_common::models::CommonNotification>, user_id: &str, pat: Option<&str>],
|
||||
[get_notification, ServiceResponse, notification_id: &str, pat: Option<&str>],
|
||||
[get_notifications, ServiceResponse, ids: &[&str], pat: Option<&str>],
|
||||
[mark_notification_read, ServiceResponse, notification_id: &str, pat: Option<&str>],
|
||||
[mark_notifications_read, ServiceResponse, ids: &[&str], pat: Option<&str>],
|
||||
[add_user_to_team, ServiceResponse, team_id: &str, user_id: &str, project_permissions: Option<ProjectPermissions>, organization_permissions: Option<OrganizationPermissions>, pat: Option<&str>],
|
||||
[delete_notification, ServiceResponse, notification_id: &str, pat: Option<&str>],
|
||||
[delete_notifications, ServiceResponse, ids: &[&str], pat: Option<&str>],
|
||||
}
|
||||
);
|
||||
|
||||
delegate_api_variant!(
|
||||
#[async_trait(?Send)]
|
||||
impl ApiUser for GenericApi {
|
||||
[get_user, ServiceResponse, id_or_username: &str, pat: Option<&str>],
|
||||
[get_current_user, ServiceResponse, pat: Option<&str>],
|
||||
[edit_user, ServiceResponse, id_or_username: &str, patch: serde_json::Value, pat: Option<&str>],
|
||||
[delete_user, ServiceResponse, id_or_username: &str, pat: Option<&str>],
|
||||
}
|
||||
);
|
||||
|
||||
@@ -125,6 +151,7 @@ delegate_api_variant!(
|
||||
[get_version_deserialized_common, CommonVersion, id_or_slug: &str, pat: Option<&str>],
|
||||
[get_versions, ServiceResponse, ids_or_slugs: Vec<String>, pat: Option<&str>],
|
||||
[get_versions_deserialized_common, Vec<CommonVersion>, ids_or_slugs: Vec<String>, pat: Option<&str>],
|
||||
[download_version_redirect, ServiceResponse, hash: &str, algorithm: &str, pat: Option<&str>],
|
||||
[edit_version, ServiceResponse, id_or_slug: &str, patch: serde_json::Value, pat: Option<&str>],
|
||||
[get_version_from_hash, ServiceResponse, id_or_slug: &str, hash: &str, pat: Option<&str>],
|
||||
[get_version_from_hash_deserialized_common, CommonVersion, id_or_slug: &str, hash: &str, pat: Option<&str>],
|
||||
|
||||
@@ -7,7 +7,6 @@ use self::models::{
|
||||
use self::request_data::{ImageData, ProjectCreationRequestData};
|
||||
use actix_web::dev::ServiceResponse;
|
||||
use async_trait::async_trait;
|
||||
use chrono::{DateTime, Utc};
|
||||
use labrinth::{
|
||||
models::{
|
||||
projects::{ProjectId, VersionType},
|
||||
@@ -27,7 +26,7 @@ pub trait ApiBuildable: Api {
|
||||
}
|
||||
|
||||
#[async_trait(?Send)]
|
||||
pub trait Api: ApiProject + ApiTags + ApiTeams + ApiVersion {
|
||||
pub trait Api: ApiProject + ApiTags + ApiTeams + ApiUser + ApiVersion {
|
||||
async fn call(&self, req: actix_http::Request) -> ServiceResponse;
|
||||
async fn reset_search_index(&self) -> ServiceResponse;
|
||||
}
|
||||
@@ -59,6 +58,12 @@ pub trait ApiProject {
|
||||
id_or_slug: &str,
|
||||
pat: Option<&str>,
|
||||
) -> CommonProject;
|
||||
async fn get_projects(&self, ids_or_slugs: &[&str], pat: Option<&str>) -> ServiceResponse;
|
||||
async fn get_project_dependencies(
|
||||
&self,
|
||||
id_or_slug: &str,
|
||||
pat: Option<&str>,
|
||||
) -> ServiceResponse;
|
||||
async fn get_user_projects(
|
||||
&self,
|
||||
user_id_or_username: &str,
|
||||
@@ -87,13 +92,6 @@ pub trait ApiProject {
|
||||
icon: Option<ImageData>,
|
||||
pat: Option<&str>,
|
||||
) -> ServiceResponse;
|
||||
async fn schedule_project(
|
||||
&self,
|
||||
id_or_slug: &str,
|
||||
requested_status: &str,
|
||||
date: DateTime<Utc>,
|
||||
pat: Option<&str>,
|
||||
) -> ServiceResponse;
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
async fn add_gallery_item(
|
||||
&self,
|
||||
@@ -127,6 +125,27 @@ pub trait ApiProject {
|
||||
pat: Option<&str>,
|
||||
) -> ServiceResponse;
|
||||
async fn get_report(&self, id: &str, pat: Option<&str>) -> ServiceResponse;
|
||||
async fn get_reports(&self, ids: &[&str], pat: Option<&str>) -> ServiceResponse;
|
||||
async fn get_user_reports(&self, pat: Option<&str>) -> ServiceResponse;
|
||||
async fn edit_report(
|
||||
&self,
|
||||
id: &str,
|
||||
patch: serde_json::Value,
|
||||
pat: Option<&str>,
|
||||
) -> ServiceResponse;
|
||||
async fn delete_report(&self, id: &str, pat: Option<&str>) -> ServiceResponse;
|
||||
async fn get_thread(&self, id: &str, pat: Option<&str>) -> ServiceResponse;
|
||||
async fn get_threads(&self, ids: &[&str], pat: Option<&str>) -> ServiceResponse;
|
||||
async fn write_to_thread(
|
||||
&self,
|
||||
id: &str,
|
||||
r#type: &str,
|
||||
message: &str,
|
||||
pat: Option<&str>,
|
||||
) -> ServiceResponse;
|
||||
async fn get_moderation_inbox(&self, pat: Option<&str>) -> ServiceResponse;
|
||||
async fn read_thread(&self, id: &str, pat: Option<&str>) -> ServiceResponse;
|
||||
async fn delete_thread_message(&self, id: &str, pat: Option<&str>) -> ServiceResponse;
|
||||
}
|
||||
|
||||
#[async_trait(?Send)]
|
||||
@@ -145,6 +164,7 @@ pub trait ApiTeams {
|
||||
team_id: &str,
|
||||
pat: Option<&str>,
|
||||
) -> Vec<CommonTeamMember>;
|
||||
async fn get_teams_members(&self, team_ids: &[&str], pat: Option<&str>) -> ServiceResponse;
|
||||
async fn get_project_members(&self, id_or_slug: &str, pat: Option<&str>) -> ServiceResponse;
|
||||
async fn get_project_members_deserialized_common(
|
||||
&self,
|
||||
@@ -187,11 +207,14 @@ pub trait ApiTeams {
|
||||
user_id: &str,
|
||||
pat: Option<&str>,
|
||||
) -> Vec<CommonNotification>;
|
||||
async fn get_notification(&self, notification_id: &str, pat: Option<&str>) -> ServiceResponse;
|
||||
async fn get_notifications(&self, ids: &[&str], pat: Option<&str>) -> ServiceResponse;
|
||||
async fn mark_notification_read(
|
||||
&self,
|
||||
notification_id: &str,
|
||||
pat: Option<&str>,
|
||||
) -> ServiceResponse;
|
||||
async fn mark_notifications_read(&self, ids: &[&str], pat: Option<&str>) -> ServiceResponse;
|
||||
async fn add_user_to_team(
|
||||
&self,
|
||||
team_id: &str,
|
||||
@@ -205,6 +228,20 @@ pub trait ApiTeams {
|
||||
notification_id: &str,
|
||||
pat: Option<&str>,
|
||||
) -> ServiceResponse;
|
||||
async fn delete_notifications(&self, ids: &[&str], pat: Option<&str>) -> ServiceResponse;
|
||||
}
|
||||
|
||||
#[async_trait(?Send)]
|
||||
pub trait ApiUser {
|
||||
async fn get_user(&self, id_or_username: &str, pat: Option<&str>) -> ServiceResponse;
|
||||
async fn get_current_user(&self, pat: Option<&str>) -> ServiceResponse;
|
||||
async fn edit_user(
|
||||
&self,
|
||||
id_or_username: &str,
|
||||
patch: serde_json::Value,
|
||||
pat: Option<&str>,
|
||||
) -> ServiceResponse;
|
||||
async fn delete_user(&self, id_or_username: &str, pat: Option<&str>) -> ServiceResponse;
|
||||
}
|
||||
|
||||
#[async_trait(?Send)]
|
||||
@@ -227,34 +264,40 @@ pub trait ApiVersion {
|
||||
modify_json: Option<json_patch::Patch>,
|
||||
pat: Option<&str>,
|
||||
) -> CommonVersion;
|
||||
async fn get_version(&self, id_or_slug: &str, pat: Option<&str>) -> ServiceResponse;
|
||||
async fn get_version(&self, id: &str, pat: Option<&str>) -> ServiceResponse;
|
||||
async fn get_version_deserialized_common(
|
||||
&self,
|
||||
id_or_slug: &str,
|
||||
pat: Option<&str>,
|
||||
) -> CommonVersion;
|
||||
async fn get_versions(&self, ids_or_slugs: Vec<String>, pat: Option<&str>) -> ServiceResponse;
|
||||
async fn get_versions(&self, ids: Vec<String>, pat: Option<&str>) -> ServiceResponse;
|
||||
async fn get_versions_deserialized_common(
|
||||
&self,
|
||||
ids_or_slugs: Vec<String>,
|
||||
ids: Vec<String>,
|
||||
pat: Option<&str>,
|
||||
) -> Vec<CommonVersion>;
|
||||
async fn download_version_redirect(
|
||||
&self,
|
||||
hash: &str,
|
||||
algorithm: &str,
|
||||
pat: Option<&str>,
|
||||
) -> ServiceResponse;
|
||||
async fn edit_version(
|
||||
&self,
|
||||
id_or_slug: &str,
|
||||
id: &str,
|
||||
patch: serde_json::Value,
|
||||
pat: Option<&str>,
|
||||
) -> ServiceResponse;
|
||||
async fn get_version_from_hash(
|
||||
&self,
|
||||
id_or_slug: &str,
|
||||
hash: &str,
|
||||
algorithm: &str,
|
||||
pat: Option<&str>,
|
||||
) -> ServiceResponse;
|
||||
async fn get_version_from_hash_deserialized_common(
|
||||
&self,
|
||||
id_or_slug: &str,
|
||||
hash: &str,
|
||||
algorithm: &str,
|
||||
pat: Option<&str>,
|
||||
) -> CommonVersion;
|
||||
async fn get_versions_from_hashes(
|
||||
|
||||
@@ -13,6 +13,7 @@ pub mod project;
|
||||
pub mod request_data;
|
||||
pub mod tags;
|
||||
pub mod team;
|
||||
pub mod user;
|
||||
pub mod version;
|
||||
|
||||
#[derive(Clone)]
|
||||
|
||||
@@ -15,7 +15,6 @@ use actix_web::{
|
||||
};
|
||||
use async_trait::async_trait;
|
||||
use bytes::Bytes;
|
||||
use chrono::{DateTime, Utc};
|
||||
use labrinth::{
|
||||
models::v2::{projects::LegacyProject, search::LegacySearchResults},
|
||||
util::actix::AppendsMultipart,
|
||||
@@ -173,6 +172,30 @@ impl ApiProject for ApiV2 {
|
||||
serde_json::from_value(value).unwrap()
|
||||
}
|
||||
|
||||
async fn get_projects(&self, ids_or_slugs: &[&str], pat: Option<&str>) -> ServiceResponse {
|
||||
let ids_or_slugs = serde_json::to_string(ids_or_slugs).unwrap();
|
||||
let req = test::TestRequest::get()
|
||||
.uri(&format!(
|
||||
"/v2/projects?ids={encoded}",
|
||||
encoded = urlencoding::encode(&ids_or_slugs)
|
||||
))
|
||||
.append_pat(pat)
|
||||
.to_request();
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
async fn get_project_dependencies(
|
||||
&self,
|
||||
id_or_slug: &str,
|
||||
pat: Option<&str>,
|
||||
) -> ServiceResponse {
|
||||
let req = TestRequest::get()
|
||||
.uri(&format!("/v2/project/{id_or_slug}/dependencies"))
|
||||
.append_pat(pat)
|
||||
.to_request();
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
async fn get_user_projects(
|
||||
&self,
|
||||
user_id_or_username: &str,
|
||||
@@ -275,7 +298,7 @@ impl ApiProject for ApiV2 {
|
||||
pat: Option<&str>,
|
||||
) -> ServiceResponse {
|
||||
let req = test::TestRequest::post()
|
||||
.uri("/v3/report")
|
||||
.uri("/v2/report")
|
||||
.append_pat(pat)
|
||||
.set_json(json!(
|
||||
{
|
||||
@@ -292,28 +315,123 @@ impl ApiProject for ApiV2 {
|
||||
|
||||
async fn get_report(&self, id: &str, pat: Option<&str>) -> ServiceResponse {
|
||||
let req = test::TestRequest::get()
|
||||
.uri(&format!("/v3/report/{id}", id = id))
|
||||
.uri(&format!("/v2/report/{id}"))
|
||||
.append_pat(pat)
|
||||
.to_request();
|
||||
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
async fn schedule_project(
|
||||
async fn get_reports(&self, ids: &[&str], pat: Option<&str>) -> ServiceResponse {
|
||||
let ids_str = serde_json::to_string(ids).unwrap();
|
||||
let req = test::TestRequest::get()
|
||||
.uri(&format!(
|
||||
"/v2/reports?ids={encoded}",
|
||||
encoded = urlencoding::encode(&ids_str)
|
||||
))
|
||||
.append_pat(pat)
|
||||
.to_request();
|
||||
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
async fn get_user_reports(&self, pat: Option<&str>) -> ServiceResponse {
|
||||
let req = test::TestRequest::get()
|
||||
.uri("/v2/report")
|
||||
.append_pat(pat)
|
||||
.to_request();
|
||||
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
async fn delete_report(&self, id: &str, pat: Option<&str>) -> ServiceResponse {
|
||||
let req = test::TestRequest::delete()
|
||||
.uri(&format!("/v2/report/{id}"))
|
||||
.append_pat(pat)
|
||||
.to_request();
|
||||
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
async fn edit_report(
|
||||
&self,
|
||||
id_or_slug: &str,
|
||||
requested_status: &str,
|
||||
date: DateTime<Utc>,
|
||||
id: &str,
|
||||
patch: serde_json::Value,
|
||||
pat: Option<&str>,
|
||||
) -> ServiceResponse {
|
||||
let req = test::TestRequest::patch()
|
||||
.uri(&format!("/v2/report/{id}"))
|
||||
.append_pat(pat)
|
||||
.set_json(patch)
|
||||
.to_request();
|
||||
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
async fn get_thread(&self, id: &str, pat: Option<&str>) -> ServiceResponse {
|
||||
let req = test::TestRequest::get()
|
||||
.uri(&format!("/v3/thread/{id}"))
|
||||
.append_pat(pat)
|
||||
.to_request();
|
||||
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
async fn get_threads(&self, ids: &[&str], pat: Option<&str>) -> ServiceResponse {
|
||||
let ids_str = serde_json::to_string(ids).unwrap();
|
||||
let req = test::TestRequest::get()
|
||||
.uri(&format!(
|
||||
"/v3/threads?ids={encoded}",
|
||||
encoded = urlencoding::encode(&ids_str)
|
||||
))
|
||||
.append_pat(pat)
|
||||
.to_request();
|
||||
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
async fn write_to_thread(
|
||||
&self,
|
||||
id: &str,
|
||||
r#type: &str,
|
||||
content: &str,
|
||||
pat: Option<&str>,
|
||||
) -> ServiceResponse {
|
||||
let req = test::TestRequest::post()
|
||||
.uri(&format!("/v2/version/{id_or_slug}/schedule"))
|
||||
.set_json(json!(
|
||||
{
|
||||
"requested_status": requested_status,
|
||||
"time": date,
|
||||
.uri(&format!("/v2/thread/{id}"))
|
||||
.append_pat(pat)
|
||||
.set_json(json!({
|
||||
"body" : {
|
||||
"type": r#type,
|
||||
"body": content,
|
||||
}
|
||||
))
|
||||
}))
|
||||
.to_request();
|
||||
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
async fn get_moderation_inbox(&self, pat: Option<&str>) -> ServiceResponse {
|
||||
let req = test::TestRequest::get()
|
||||
.uri("/v2/thread/inbox")
|
||||
.append_pat(pat)
|
||||
.to_request();
|
||||
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
async fn read_thread(&self, id: &str, pat: Option<&str>) -> ServiceResponse {
|
||||
let req = test::TestRequest::post()
|
||||
.uri(&format!("/v2/thread/{id}/read"))
|
||||
.append_pat(pat)
|
||||
.to_request();
|
||||
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
async fn delete_thread_message(&self, id: &str, pat: Option<&str>) -> ServiceResponse {
|
||||
let req = test::TestRequest::delete()
|
||||
.uri(&format!("/v2/message/{id}"))
|
||||
.append_pat(pat)
|
||||
.to_request();
|
||||
|
||||
|
||||
@@ -72,6 +72,22 @@ impl ApiTeams for ApiV2 {
|
||||
test::read_body_json(resp).await
|
||||
}
|
||||
|
||||
async fn get_teams_members(
|
||||
&self,
|
||||
ids_or_titles: &[&str],
|
||||
pat: Option<&str>,
|
||||
) -> ServiceResponse {
|
||||
let ids_or_titles = serde_json::to_string(ids_or_titles).unwrap();
|
||||
let req = test::TestRequest::get()
|
||||
.uri(&format!(
|
||||
"/v2/teams?ids={}",
|
||||
urlencoding::encode(&ids_or_titles)
|
||||
))
|
||||
.append_pat(pat)
|
||||
.to_request();
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
async fn get_project_members(&self, id_or_title: &str, pat: Option<&str>) -> ServiceResponse {
|
||||
let req = test::TestRequest::get()
|
||||
.uri(&format!("/v2/project/{id_or_title}/members"))
|
||||
@@ -192,6 +208,30 @@ impl ApiTeams for ApiV2 {
|
||||
serde_json::from_value(value).unwrap()
|
||||
}
|
||||
|
||||
async fn get_notification(&self, notification_id: &str, pat: Option<&str>) -> ServiceResponse {
|
||||
let req = test::TestRequest::get()
|
||||
.uri(&format!("/v2/notification/{notification_id}"))
|
||||
.append_pat(pat)
|
||||
.to_request();
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
async fn get_notifications(
|
||||
&self,
|
||||
notification_ids: &[&str],
|
||||
pat: Option<&str>,
|
||||
) -> ServiceResponse {
|
||||
let notification_ids = serde_json::to_string(notification_ids).unwrap();
|
||||
let req = test::TestRequest::get()
|
||||
.uri(&format!(
|
||||
"/v2/notifications?ids={}",
|
||||
urlencoding::encode(¬ification_ids)
|
||||
))
|
||||
.append_pat(pat)
|
||||
.to_request();
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
async fn mark_notification_read(
|
||||
&self,
|
||||
notification_id: &str,
|
||||
@@ -204,6 +244,22 @@ impl ApiTeams for ApiV2 {
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
async fn mark_notifications_read(
|
||||
&self,
|
||||
notification_ids: &[&str],
|
||||
pat: Option<&str>,
|
||||
) -> ServiceResponse {
|
||||
let notification_ids = serde_json::to_string(notification_ids).unwrap();
|
||||
let req = test::TestRequest::patch()
|
||||
.uri(&format!(
|
||||
"/v2/notifications?ids={}",
|
||||
urlencoding::encode(¬ification_ids)
|
||||
))
|
||||
.append_pat(pat)
|
||||
.to_request();
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
async fn add_user_to_team(
|
||||
&self,
|
||||
team_id: &str,
|
||||
@@ -235,4 +291,20 @@ impl ApiTeams for ApiV2 {
|
||||
.to_request();
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
async fn delete_notifications(
|
||||
&self,
|
||||
notification_ids: &[&str],
|
||||
pat: Option<&str>,
|
||||
) -> ServiceResponse {
|
||||
let notification_ids = serde_json::to_string(notification_ids).unwrap();
|
||||
let req = test::TestRequest::delete()
|
||||
.uri(&format!(
|
||||
"/v2/notifications?ids={}",
|
||||
urlencoding::encode(¬ification_ids)
|
||||
))
|
||||
.append_pat(pat)
|
||||
.to_request();
|
||||
self.call(req).await
|
||||
}
|
||||
}
|
||||
|
||||
47
tests/common/api_v2/user.rs
Normal file
47
tests/common/api_v2/user.rs
Normal file
@@ -0,0 +1,47 @@
|
||||
use super::ApiV2;
|
||||
use crate::common::api_common::{Api, ApiUser, AppendsOptionalPat};
|
||||
use actix_web::{dev::ServiceResponse, test};
|
||||
use async_trait::async_trait;
|
||||
|
||||
#[async_trait(?Send)]
|
||||
impl ApiUser for ApiV2 {
|
||||
async fn get_user(&self, user_id_or_username: &str, pat: Option<&str>) -> ServiceResponse {
|
||||
let req = test::TestRequest::get()
|
||||
.uri(&format!("/v2/user/{}", user_id_or_username))
|
||||
.append_pat(pat)
|
||||
.to_request();
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
async fn get_current_user(&self, pat: Option<&str>) -> ServiceResponse {
|
||||
let req = test::TestRequest::get()
|
||||
.uri("/v2/user")
|
||||
.append_pat(pat)
|
||||
.to_request();
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
async fn edit_user(
|
||||
&self,
|
||||
user_id_or_username: &str,
|
||||
patch: serde_json::Value,
|
||||
pat: Option<&str>,
|
||||
) -> ServiceResponse {
|
||||
let req = test::TestRequest::patch()
|
||||
.uri(&format!("/v2/user/{}", user_id_or_username))
|
||||
.append_pat(pat)
|
||||
.set_json(patch)
|
||||
.to_request();
|
||||
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
async fn delete_user(&self, user_id_or_username: &str, pat: Option<&str>) -> ServiceResponse {
|
||||
let req = test::TestRequest::delete()
|
||||
.uri(&format!("/v2/user/{}", user_id_or_username))
|
||||
.append_pat(pat)
|
||||
.to_request();
|
||||
|
||||
self.call(req).await
|
||||
}
|
||||
}
|
||||
@@ -161,6 +161,22 @@ impl ApiVersion for ApiV2 {
|
||||
serde_json::from_value(value).unwrap()
|
||||
}
|
||||
|
||||
async fn download_version_redirect(
|
||||
&self,
|
||||
hash: &str,
|
||||
algorithm: &str,
|
||||
pat: Option<&str>,
|
||||
) -> ServiceResponse {
|
||||
let req = test::TestRequest::get()
|
||||
.uri(&format!("/v2/version_file/{hash}/download",))
|
||||
.set_json(json!({
|
||||
"algorithm": algorithm,
|
||||
}))
|
||||
.append_pat(pat)
|
||||
.to_request();
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
async fn edit_version(
|
||||
&self,
|
||||
version_id: &str,
|
||||
|
||||
155
tests/common/api_v3/collections.rs
Normal file
155
tests/common/api_v3/collections.rs
Normal file
@@ -0,0 +1,155 @@
|
||||
use actix_web::{
|
||||
dev::ServiceResponse,
|
||||
test::{self, TestRequest},
|
||||
};
|
||||
use bytes::Bytes;
|
||||
use labrinth::models::{collections::Collection, v3::projects::Project};
|
||||
use serde_json::json;
|
||||
|
||||
use crate::common::api_common::{request_data::ImageData, Api, AppendsOptionalPat};
|
||||
|
||||
use super::ApiV3;
|
||||
|
||||
impl ApiV3 {
|
||||
pub async fn create_collection(
|
||||
&self,
|
||||
collection_title: &str,
|
||||
description: &str,
|
||||
projects: &[&str],
|
||||
pat: Option<&str>,
|
||||
) -> ServiceResponse {
|
||||
let req = test::TestRequest::post()
|
||||
.uri("/v3/collection")
|
||||
.append_pat(pat)
|
||||
.set_json(json!({
|
||||
"name": collection_title,
|
||||
"description": description,
|
||||
"projects": projects,
|
||||
}))
|
||||
.to_request();
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
pub async fn get_collection(&self, id: &str, pat: Option<&str>) -> ServiceResponse {
|
||||
let req = TestRequest::get()
|
||||
.uri(&format!("/v3/collection/{id}"))
|
||||
.append_pat(pat)
|
||||
.to_request();
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
pub async fn get_collection_deserialized(&self, id: &str, pat: Option<&str>) -> Collection {
|
||||
let resp = self.get_collection(id, pat).await;
|
||||
assert_eq!(resp.status(), 200);
|
||||
test::read_body_json(resp).await
|
||||
}
|
||||
|
||||
pub async fn get_collections(&self, ids: &[&str], pat: Option<&str>) -> ServiceResponse {
|
||||
let ids = serde_json::to_string(ids).unwrap();
|
||||
let req = test::TestRequest::get()
|
||||
.uri(&format!(
|
||||
"/v3/collections?ids={}",
|
||||
urlencoding::encode(&ids)
|
||||
))
|
||||
.append_pat(pat)
|
||||
.to_request();
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
pub async fn get_collection_projects(&self, id: &str, pat: Option<&str>) -> ServiceResponse {
|
||||
let req = test::TestRequest::get()
|
||||
.uri(&format!("/v3/collection/{id}/projects"))
|
||||
.append_pat(pat)
|
||||
.to_request();
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
pub async fn get_collection_projects_deserialized(
|
||||
&self,
|
||||
id: &str,
|
||||
pat: Option<&str>,
|
||||
) -> Vec<Project> {
|
||||
let resp = self.get_collection_projects(id, pat).await;
|
||||
assert_eq!(resp.status(), 200);
|
||||
test::read_body_json(resp).await
|
||||
}
|
||||
|
||||
pub async fn edit_collection(
|
||||
&self,
|
||||
id: &str,
|
||||
patch: serde_json::Value,
|
||||
pat: Option<&str>,
|
||||
) -> ServiceResponse {
|
||||
let req = test::TestRequest::patch()
|
||||
.uri(&format!("/v3/collection/{id}"))
|
||||
.append_pat(pat)
|
||||
.set_json(patch)
|
||||
.to_request();
|
||||
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
pub async fn edit_collection_icon(
|
||||
&self,
|
||||
id: &str,
|
||||
icon: Option<ImageData>,
|
||||
pat: Option<&str>,
|
||||
) -> ServiceResponse {
|
||||
if let Some(icon) = icon {
|
||||
// If an icon is provided, upload it
|
||||
let req = test::TestRequest::patch()
|
||||
.uri(&format!(
|
||||
"/v3/collection/{id}/icon?ext={ext}",
|
||||
ext = icon.extension
|
||||
))
|
||||
.append_pat(pat)
|
||||
.set_payload(Bytes::from(icon.icon))
|
||||
.to_request();
|
||||
|
||||
self.call(req).await
|
||||
} else {
|
||||
// If no icon is provided, delete the icon
|
||||
let req = test::TestRequest::delete()
|
||||
.uri(&format!("/v3/collection/{id}/icon"))
|
||||
.append_pat(pat)
|
||||
.to_request();
|
||||
|
||||
self.call(req).await
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn delete_collection(&self, id: &str, pat: Option<&str>) -> ServiceResponse {
|
||||
let req = test::TestRequest::delete()
|
||||
.uri(&format!("/v3/collection/{id}"))
|
||||
.append_pat(pat)
|
||||
.to_request();
|
||||
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
pub async fn get_user_collections(
|
||||
&self,
|
||||
user_id_or_username: &str,
|
||||
pat: Option<&str>,
|
||||
) -> ServiceResponse {
|
||||
let req = test::TestRequest::get()
|
||||
.uri(&format!("/v3/user/{}/collections", user_id_or_username))
|
||||
.append_pat(pat)
|
||||
.to_request();
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
pub async fn get_user_collections_deserialized_common(
|
||||
&self,
|
||||
user_id_or_username: &str,
|
||||
pat: Option<&str>,
|
||||
) -> Vec<Collection> {
|
||||
let resp = self.get_user_collections(user_id_or_username, pat).await;
|
||||
assert_eq!(resp.status(), 200);
|
||||
// First, deserialize to the non-common format (to test the response is valid for this api version)
|
||||
let projects: Vec<Project> = test::read_body_json(resp).await;
|
||||
// Then, deserialize to the common format
|
||||
let value = serde_json::to_value(projects).unwrap();
|
||||
serde_json::from_value(value).unwrap()
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ use async_trait::async_trait;
|
||||
use labrinth::LabrinthConfig;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub mod collections;
|
||||
pub mod oauth;
|
||||
pub mod oauth_clients;
|
||||
pub mod organization;
|
||||
@@ -16,6 +17,7 @@ pub mod project;
|
||||
pub mod request_data;
|
||||
pub mod tags;
|
||||
pub mod team;
|
||||
pub mod user;
|
||||
pub mod version;
|
||||
|
||||
#[derive(Clone)]
|
||||
|
||||
@@ -46,6 +46,22 @@ impl ApiV3 {
|
||||
test::read_body_json(resp).await
|
||||
}
|
||||
|
||||
pub async fn get_organizations(
|
||||
&self,
|
||||
ids_or_titles: &[&str],
|
||||
pat: Option<&str>,
|
||||
) -> ServiceResponse {
|
||||
let ids_or_titles = serde_json::to_string(ids_or_titles).unwrap();
|
||||
let req = test::TestRequest::get()
|
||||
.uri(&format!(
|
||||
"/v3/organizations?ids={}",
|
||||
urlencoding::encode(&ids_or_titles)
|
||||
))
|
||||
.append_pat(pat)
|
||||
.to_request();
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
pub async fn get_organization_projects(
|
||||
&self,
|
||||
id_or_title: &str,
|
||||
|
||||
@@ -126,6 +126,30 @@ impl ApiProject for ApiV3 {
|
||||
serde_json::from_value(value).unwrap()
|
||||
}
|
||||
|
||||
async fn get_projects(&self, ids_or_slugs: &[&str], pat: Option<&str>) -> ServiceResponse {
|
||||
let ids_or_slugs = serde_json::to_string(ids_or_slugs).unwrap();
|
||||
let req = test::TestRequest::get()
|
||||
.uri(&format!(
|
||||
"/v2/projects?ids={encoded}",
|
||||
encoded = urlencoding::encode(&ids_or_slugs)
|
||||
))
|
||||
.append_pat(pat)
|
||||
.to_request();
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
async fn get_project_dependencies(
|
||||
&self,
|
||||
id_or_slug: &str,
|
||||
pat: Option<&str>,
|
||||
) -> ServiceResponse {
|
||||
let req = TestRequest::get()
|
||||
.uri(&format!("/v2/project/{id_or_slug}/dependencies"))
|
||||
.append_pat(pat)
|
||||
.to_request();
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
async fn get_user_projects(
|
||||
&self,
|
||||
user_id_or_username: &str,
|
||||
@@ -245,28 +269,53 @@ impl ApiProject for ApiV3 {
|
||||
|
||||
async fn get_report(&self, id: &str, pat: Option<&str>) -> ServiceResponse {
|
||||
let req = test::TestRequest::get()
|
||||
.uri(&format!("/v3/report/{id}", id = id))
|
||||
.uri(&format!("/v3/report/{id}"))
|
||||
.append_pat(pat)
|
||||
.to_request();
|
||||
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
async fn schedule_project(
|
||||
async fn get_reports(&self, ids: &[&str], pat: Option<&str>) -> ServiceResponse {
|
||||
let ids_str = serde_json::to_string(ids).unwrap();
|
||||
let req = test::TestRequest::get()
|
||||
.uri(&format!(
|
||||
"/v3/reports?ids={encoded}",
|
||||
encoded = urlencoding::encode(&ids_str)
|
||||
))
|
||||
.append_pat(pat)
|
||||
.to_request();
|
||||
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
async fn get_user_reports(&self, pat: Option<&str>) -> ServiceResponse {
|
||||
let req = test::TestRequest::get()
|
||||
.uri("/v3/report")
|
||||
.append_pat(pat)
|
||||
.to_request();
|
||||
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
async fn edit_report(
|
||||
&self,
|
||||
id_or_slug: &str,
|
||||
requested_status: &str,
|
||||
date: DateTime<Utc>,
|
||||
id: &str,
|
||||
patch: serde_json::Value,
|
||||
pat: Option<&str>,
|
||||
) -> ServiceResponse {
|
||||
let req = test::TestRequest::post()
|
||||
.uri(&format!("/v3/version/{id_or_slug}/schedule"))
|
||||
.set_json(json!(
|
||||
{
|
||||
"requested_status": requested_status,
|
||||
"time": date,
|
||||
}
|
||||
))
|
||||
let req = test::TestRequest::patch()
|
||||
.uri(&format!("/v3/report/{id}"))
|
||||
.append_pat(pat)
|
||||
.set_json(patch)
|
||||
.to_request();
|
||||
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
async fn delete_report(&self, id: &str, pat: Option<&str>) -> ServiceResponse {
|
||||
let req = test::TestRequest::delete()
|
||||
.uri(&format!("/v3/report/{id}"))
|
||||
.append_pat(pat)
|
||||
.to_request();
|
||||
|
||||
@@ -355,6 +404,76 @@ impl ApiProject for ApiV3 {
|
||||
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
async fn get_thread(&self, id: &str, pat: Option<&str>) -> ServiceResponse {
|
||||
let req = test::TestRequest::get()
|
||||
.uri(&format!("/v3/thread/{id}"))
|
||||
.append_pat(pat)
|
||||
.to_request();
|
||||
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
async fn get_threads(&self, ids: &[&str], pat: Option<&str>) -> ServiceResponse {
|
||||
let ids_str = serde_json::to_string(ids).unwrap();
|
||||
let req = test::TestRequest::get()
|
||||
.uri(&format!(
|
||||
"/v3/threads?ids={encoded}",
|
||||
encoded = urlencoding::encode(&ids_str)
|
||||
))
|
||||
.append_pat(pat)
|
||||
.to_request();
|
||||
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
async fn write_to_thread(
|
||||
&self,
|
||||
id: &str,
|
||||
r#type: &str,
|
||||
content: &str,
|
||||
pat: Option<&str>,
|
||||
) -> ServiceResponse {
|
||||
let req = test::TestRequest::post()
|
||||
.uri(&format!("/v3/thread/{id}"))
|
||||
.append_pat(pat)
|
||||
.set_json(json!({
|
||||
"body": {
|
||||
"type": r#type,
|
||||
"body": content
|
||||
}
|
||||
}))
|
||||
.to_request();
|
||||
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
async fn get_moderation_inbox(&self, pat: Option<&str>) -> ServiceResponse {
|
||||
let req = test::TestRequest::get()
|
||||
.uri("/v3/thread/inbox")
|
||||
.append_pat(pat)
|
||||
.to_request();
|
||||
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
async fn read_thread(&self, id: &str, pat: Option<&str>) -> ServiceResponse {
|
||||
let req = test::TestRequest::post()
|
||||
.uri(&format!("/v3/thread/{id}/read"))
|
||||
.append_pat(pat)
|
||||
.to_request();
|
||||
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
async fn delete_thread_message(&self, id: &str, pat: Option<&str>) -> ServiceResponse {
|
||||
let req = test::TestRequest::delete()
|
||||
.uri(&format!("/v3/message/{id}"))
|
||||
.append_pat(pat)
|
||||
.to_request();
|
||||
|
||||
self.call(req).await
|
||||
}
|
||||
}
|
||||
|
||||
impl ApiV3 {
|
||||
|
||||
@@ -63,6 +63,22 @@ impl ApiTeams for ApiV3 {
|
||||
serde_json::from_value(value).unwrap()
|
||||
}
|
||||
|
||||
async fn get_teams_members(
|
||||
&self,
|
||||
ids_or_titles: &[&str],
|
||||
pat: Option<&str>,
|
||||
) -> ServiceResponse {
|
||||
let ids_or_titles = serde_json::to_string(ids_or_titles).unwrap();
|
||||
let req = test::TestRequest::get()
|
||||
.uri(&format!(
|
||||
"/v3/teams?ids={}",
|
||||
urlencoding::encode(&ids_or_titles)
|
||||
))
|
||||
.append_pat(pat)
|
||||
.to_request();
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
async fn get_project_members(&self, id_or_title: &str, pat: Option<&str>) -> ServiceResponse {
|
||||
let req = test::TestRequest::get()
|
||||
.uri(&format!("/v3/project/{id_or_title}/members"))
|
||||
@@ -185,6 +201,30 @@ impl ApiTeams for ApiV3 {
|
||||
serde_json::from_value(value).unwrap()
|
||||
}
|
||||
|
||||
async fn get_notification(&self, notification_id: &str, pat: Option<&str>) -> ServiceResponse {
|
||||
let req = test::TestRequest::get()
|
||||
.uri(&format!("/v3/notification/{notification_id}"))
|
||||
.append_pat(pat)
|
||||
.to_request();
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
async fn get_notifications(
|
||||
&self,
|
||||
notification_ids: &[&str],
|
||||
pat: Option<&str>,
|
||||
) -> ServiceResponse {
|
||||
let notification_ids = serde_json::to_string(notification_ids).unwrap();
|
||||
let req = test::TestRequest::get()
|
||||
.uri(&format!(
|
||||
"/v3/notifications?ids={}",
|
||||
urlencoding::encode(¬ification_ids)
|
||||
))
|
||||
.append_pat(pat)
|
||||
.to_request();
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
async fn mark_notification_read(
|
||||
&self,
|
||||
notification_id: &str,
|
||||
@@ -196,6 +236,23 @@ impl ApiTeams for ApiV3 {
|
||||
.to_request();
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
async fn mark_notifications_read(
|
||||
&self,
|
||||
notification_ids: &[&str],
|
||||
pat: Option<&str>,
|
||||
) -> ServiceResponse {
|
||||
let notification_ids = serde_json::to_string(notification_ids).unwrap();
|
||||
let req = test::TestRequest::patch()
|
||||
.uri(&format!(
|
||||
"/v3/notifications?ids={}",
|
||||
urlencoding::encode(¬ification_ids)
|
||||
))
|
||||
.append_pat(pat)
|
||||
.to_request();
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
async fn add_user_to_team(
|
||||
&self,
|
||||
team_id: &str,
|
||||
@@ -227,4 +284,20 @@ impl ApiTeams for ApiV3 {
|
||||
.to_request();
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
async fn delete_notifications(
|
||||
&self,
|
||||
notification_ids: &[&str],
|
||||
pat: Option<&str>,
|
||||
) -> ServiceResponse {
|
||||
let notification_ids = serde_json::to_string(notification_ids).unwrap();
|
||||
let req = test::TestRequest::delete()
|
||||
.uri(&format!(
|
||||
"/v3/notifications?ids={}",
|
||||
urlencoding::encode(¬ification_ids)
|
||||
))
|
||||
.append_pat(pat)
|
||||
.to_request();
|
||||
self.call(req).await
|
||||
}
|
||||
}
|
||||
|
||||
48
tests/common/api_v3/user.rs
Normal file
48
tests/common/api_v3/user.rs
Normal file
@@ -0,0 +1,48 @@
|
||||
use actix_web::{dev::ServiceResponse, test};
|
||||
use async_trait::async_trait;
|
||||
|
||||
use crate::common::api_common::{Api, ApiUser, AppendsOptionalPat};
|
||||
|
||||
use super::ApiV3;
|
||||
|
||||
#[async_trait(?Send)]
|
||||
impl ApiUser for ApiV3 {
|
||||
async fn get_user(&self, user_id_or_username: &str, pat: Option<&str>) -> ServiceResponse {
|
||||
let req = test::TestRequest::get()
|
||||
.uri(&format!("/v3/user/{}", user_id_or_username))
|
||||
.append_pat(pat)
|
||||
.to_request();
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
async fn get_current_user(&self, pat: Option<&str>) -> ServiceResponse {
|
||||
let req = test::TestRequest::get()
|
||||
.uri("/v3/user")
|
||||
.append_pat(pat)
|
||||
.to_request();
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
async fn edit_user(
|
||||
&self,
|
||||
user_id_or_username: &str,
|
||||
patch: serde_json::Value,
|
||||
pat: Option<&str>,
|
||||
) -> ServiceResponse {
|
||||
let req = test::TestRequest::patch()
|
||||
.uri(&format!("/v3/user/{}", user_id_or_username))
|
||||
.append_pat(pat)
|
||||
.set_json(patch)
|
||||
.to_request();
|
||||
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
async fn delete_user(&self, user_id_or_username: &str, pat: Option<&str>) -> ServiceResponse {
|
||||
let req = test::TestRequest::delete()
|
||||
.uri(&format!("/v3/user/{}", user_id_or_username))
|
||||
.append_pat(pat)
|
||||
.to_request();
|
||||
self.call(req).await
|
||||
}
|
||||
}
|
||||
@@ -181,6 +181,22 @@ impl ApiVersion for ApiV3 {
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
async fn download_version_redirect(
|
||||
&self,
|
||||
hash: &str,
|
||||
algorithm: &str,
|
||||
pat: Option<&str>,
|
||||
) -> ServiceResponse {
|
||||
let req = test::TestRequest::get()
|
||||
.uri(&format!("/v3/version_file/{hash}/download",))
|
||||
.set_json(json!({
|
||||
"algorithm": algorithm,
|
||||
}))
|
||||
.append_pat(pat)
|
||||
.to_request();
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
async fn get_version_from_hash(
|
||||
&self,
|
||||
hash: &str,
|
||||
|
||||
@@ -168,21 +168,14 @@ impl TemporaryDatabase {
|
||||
|
||||
if !dummy_data_exists {
|
||||
// Add dummy data
|
||||
let temporary_test_env =
|
||||
TestEnvironment::<ApiV3>::build_with_db(TemporaryDatabase {
|
||||
pool: pool.clone(),
|
||||
database_name: TEMPLATE_DATABASE_NAME.to_string(),
|
||||
redis_pool: RedisPool::new(Some(generate_random_name(
|
||||
"test_template_",
|
||||
))),
|
||||
})
|
||||
.await;
|
||||
dummy_data::add_dummy_data(
|
||||
&temporary_test_env.setup_api,
|
||||
temporary_test_env.db.clone(),
|
||||
)
|
||||
.await;
|
||||
temporary_test_env.db.pool.close().await;
|
||||
let db = TemporaryDatabase {
|
||||
pool: pool.clone(),
|
||||
database_name: TEMPLATE_DATABASE_NAME.to_string(),
|
||||
redis_pool: RedisPool::new(Some(generate_random_name("test_template_"))),
|
||||
};
|
||||
let setup_api = TestEnvironment::<ApiV3>::build_setup_api(&db).await;
|
||||
dummy_data::add_dummy_data(&setup_api, db.clone()).await;
|
||||
db.pool.close().await;
|
||||
}
|
||||
pool.close().await;
|
||||
drop(pool);
|
||||
|
||||
@@ -65,33 +65,30 @@ where
|
||||
// Use .call(req) on it directly to make a test call as if test::call_service(req) were being used.
|
||||
#[derive(Clone)]
|
||||
pub struct TestEnvironment<A> {
|
||||
// test_app: Rc<dyn LocalService>, // Rc as it's not Send
|
||||
pub db: TemporaryDatabase,
|
||||
pub api: A,
|
||||
pub setup_api: ApiV3, // Used for setting up tests only (ie: in ScopesTest)
|
||||
pub dummy: Option<dummy_data::DummyData>,
|
||||
pub dummy: dummy_data::DummyData,
|
||||
}
|
||||
|
||||
impl<A: ApiBuildable> TestEnvironment<A> {
|
||||
async fn build(max_connections: Option<u32>) -> Self {
|
||||
let db = TemporaryDatabase::create(max_connections).await;
|
||||
let mut test_env = Self::build_with_db(db).await;
|
||||
|
||||
let dummy = dummy_data::get_dummy_data(&test_env.setup_api).await;
|
||||
test_env.dummy = Some(dummy);
|
||||
test_env
|
||||
}
|
||||
|
||||
pub async fn build_with_db(db: TemporaryDatabase) -> Self {
|
||||
let labrinth_config = setup(&db).await;
|
||||
let api = A::build(labrinth_config.clone()).await;
|
||||
let setup_api = ApiV3::build(labrinth_config).await;
|
||||
let dummy = dummy_data::get_dummy_data(&setup_api).await;
|
||||
Self {
|
||||
db,
|
||||
api: A::build(labrinth_config.clone()).await,
|
||||
setup_api: ApiV3::build(labrinth_config.clone()).await,
|
||||
dummy: None,
|
||||
// test_app
|
||||
api,
|
||||
setup_api,
|
||||
dummy,
|
||||
}
|
||||
}
|
||||
pub async fn build_setup_api(db: &TemporaryDatabase) -> ApiV3 {
|
||||
let labrinth_config = setup(db).await;
|
||||
ApiV3::build(labrinth_config).await
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Api> TestEnvironment<A> {
|
||||
@@ -108,7 +105,7 @@ impl<A: Api> TestEnvironment<A> {
|
||||
let resp = self
|
||||
.api
|
||||
.add_user_to_team(
|
||||
&self.dummy.as_ref().unwrap().project_alpha.team_id,
|
||||
&self.dummy.project_alpha.team_id,
|
||||
FRIEND_USER_ID,
|
||||
None,
|
||||
None,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#![allow(dead_code)]
|
||||
use actix_web::test::{self, TestRequest};
|
||||
use actix_web::{dev::ServiceResponse, test};
|
||||
use futures::Future;
|
||||
use labrinth::models::pats::Scopes;
|
||||
|
||||
use super::{
|
||||
@@ -59,13 +60,14 @@ impl<'a, A: Api> ScopeTest<'a, A> {
|
||||
// success_scopes : the scopes that we are testing that should succeed
|
||||
// returns a tuple of (failure_body, success_body)
|
||||
// Should return a String error if on unexpected status code, allowing unwrapping in tests.
|
||||
pub async fn test<T>(
|
||||
pub async fn test<T, Fut>(
|
||||
&self,
|
||||
req_gen: T,
|
||||
success_scopes: Scopes,
|
||||
) -> Result<(serde_json::Value, serde_json::Value), String>
|
||||
where
|
||||
T: Fn() -> TestRequest,
|
||||
T: Fn(Option<String>) -> Fut,
|
||||
Fut: Future<Output = ServiceResponse>, // Ensure Fut is Send and 'static
|
||||
{
|
||||
// First, create a PAT with failure scopes
|
||||
let failure_scopes = self
|
||||
@@ -79,11 +81,7 @@ impl<'a, A: Api> ScopeTest<'a, A> {
|
||||
|
||||
// Perform test twice, once with each PAT
|
||||
// the first time, we expect a 401 (or known failure code)
|
||||
let req = req_gen()
|
||||
.append_header(("Authorization", access_token_all_others.as_str()))
|
||||
.to_request();
|
||||
let resp = self.test_env.call(req).await;
|
||||
|
||||
let resp = req_gen(Some(access_token_all_others.clone())).await;
|
||||
if resp.status().as_u16() != self.expected_failure_code {
|
||||
return Err(format!(
|
||||
"Expected failure code {}, got {} ({:#?})",
|
||||
@@ -103,11 +101,7 @@ impl<'a, A: Api> ScopeTest<'a, A> {
|
||||
};
|
||||
|
||||
// The second time, we expect a success code
|
||||
let req = req_gen()
|
||||
.append_header(("Authorization", access_token.as_str()))
|
||||
.to_request();
|
||||
let resp = self.test_env.call(req).await;
|
||||
|
||||
let resp = req_gen(Some(access_token.clone())).await;
|
||||
if !(resp.status().is_success() || resp.status().is_redirection()) {
|
||||
return Err(format!(
|
||||
"Expected success code, got {} ({:#?})",
|
||||
|
||||
@@ -7,7 +7,7 @@ use serde_json::json;
|
||||
use crate::common::api_common::ApiVersion;
|
||||
use crate::common::database::*;
|
||||
|
||||
use crate::common::dummy_data::TestFile;
|
||||
use crate::common::dummy_data::{DummyProjectAlpha, DummyProjectBeta, TestFile};
|
||||
|
||||
// importing common module.
|
||||
mod common;
|
||||
@@ -17,33 +17,16 @@ mod common;
|
||||
async fn creating_loader_fields() {
|
||||
with_test_environment(None, |test_env: TestEnvironment<ApiV3>| async move {
|
||||
let api = &test_env.api;
|
||||
|
||||
let alpha_project_id = &test_env
|
||||
.dummy
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.project_alpha
|
||||
.project_id
|
||||
.clone();
|
||||
let alpha_project_id_parsed = test_env
|
||||
.dummy
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.project_alpha
|
||||
.project_id_parsed;
|
||||
let beta_project_id_parsed = test_env
|
||||
.dummy
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.project_beta
|
||||
.project_id_parsed;
|
||||
let alpha_version_id = &test_env
|
||||
.dummy
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.project_alpha
|
||||
.version_id
|
||||
.clone();
|
||||
let DummyProjectAlpha {
|
||||
project_id: alpha_project_id,
|
||||
project_id_parsed: alpha_project_id_parsed,
|
||||
version_id: alpha_version_id,
|
||||
..
|
||||
} = &test_env.dummy.project_alpha;
|
||||
let DummyProjectBeta {
|
||||
project_id_parsed: beta_project_id_parsed,
|
||||
..
|
||||
} = &test_env.dummy.project_beta;
|
||||
|
||||
// ALL THE FOLLOWING FOR CREATE AND PATCH
|
||||
// Cannot create a version with an extra argument that cannot be tied to a loader field ("invalid loader field")
|
||||
@@ -51,7 +34,7 @@ async fn creating_loader_fields() {
|
||||
// - Create version
|
||||
let resp = api
|
||||
.add_public_version(
|
||||
alpha_project_id_parsed,
|
||||
*alpha_project_id_parsed,
|
||||
"1.0.0",
|
||||
TestFile::build_random_jar(),
|
||||
None,
|
||||
@@ -84,7 +67,7 @@ async fn creating_loader_fields() {
|
||||
// - Create version
|
||||
let resp = api
|
||||
.add_public_version(
|
||||
alpha_project_id_parsed,
|
||||
*alpha_project_id_parsed,
|
||||
"1.0.0",
|
||||
TestFile::build_random_jar(),
|
||||
None,
|
||||
@@ -117,7 +100,7 @@ async fn creating_loader_fields() {
|
||||
// - Create version
|
||||
let resp = api
|
||||
.add_public_version(
|
||||
alpha_project_id_parsed,
|
||||
*alpha_project_id_parsed,
|
||||
"1.0.0",
|
||||
TestFile::build_random_jar(),
|
||||
None,
|
||||
@@ -139,7 +122,7 @@ async fn creating_loader_fields() {
|
||||
// - Create version
|
||||
let resp = api
|
||||
.add_public_version(
|
||||
alpha_project_id_parsed,
|
||||
*alpha_project_id_parsed,
|
||||
"1.0.0",
|
||||
TestFile::build_random_jar(),
|
||||
None,
|
||||
@@ -161,7 +144,7 @@ async fn creating_loader_fields() {
|
||||
// - Create version
|
||||
let resp: actix_web::dev::ServiceResponse = api
|
||||
.add_public_version(
|
||||
alpha_project_id_parsed,
|
||||
*alpha_project_id_parsed,
|
||||
"1.0.0",
|
||||
TestFile::build_random_jar(),
|
||||
None,
|
||||
@@ -201,7 +184,7 @@ async fn creating_loader_fields() {
|
||||
// - Create version
|
||||
let resp = api
|
||||
.add_public_version(
|
||||
alpha_project_id_parsed,
|
||||
*alpha_project_id_parsed,
|
||||
"1.0.0",
|
||||
TestFile::build_random_jar(),
|
||||
None,
|
||||
@@ -236,7 +219,7 @@ async fn creating_loader_fields() {
|
||||
// - Create version
|
||||
let v = api
|
||||
.add_public_version_deserialized(
|
||||
alpha_project_id_parsed,
|
||||
*alpha_project_id_parsed,
|
||||
"1.0.0",
|
||||
TestFile::build_random_jar(),
|
||||
None,
|
||||
@@ -272,7 +255,7 @@ async fn creating_loader_fields() {
|
||||
// - Create
|
||||
let v = api
|
||||
.add_public_version_deserialized(
|
||||
alpha_project_id_parsed,
|
||||
*alpha_project_id_parsed,
|
||||
"1.0.0",
|
||||
TestFile::build_random_jar(),
|
||||
None,
|
||||
@@ -325,7 +308,7 @@ async fn creating_loader_fields() {
|
||||
// Now that we've created a version, we need to make sure that the Project's loader fields are updated (aggregate)
|
||||
// First, add a new version
|
||||
api.add_public_version_deserialized(
|
||||
alpha_project_id_parsed,
|
||||
*alpha_project_id_parsed,
|
||||
"1.0.1",
|
||||
TestFile::build_random_jar(),
|
||||
None,
|
||||
@@ -347,7 +330,7 @@ async fn creating_loader_fields() {
|
||||
|
||||
// Also, add one to the beta project
|
||||
api.add_public_version_deserialized(
|
||||
beta_project_id_parsed,
|
||||
*beta_project_id_parsed,
|
||||
"1.0.1",
|
||||
TestFile::build_random_jar(),
|
||||
None,
|
||||
|
||||
@@ -10,13 +10,7 @@ mod common;
|
||||
#[actix_rt::test]
|
||||
pub async fn get_user_notifications_after_team_invitation_returns_notification() {
|
||||
with_test_environment_all(None, |test_env| async move {
|
||||
let alpha_team_id = test_env
|
||||
.dummy
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.project_alpha
|
||||
.team_id
|
||||
.clone();
|
||||
let alpha_team_id = test_env.dummy.project_alpha.team_id.clone();
|
||||
let api = test_env.api;
|
||||
api.get_user_notifications_deserialized_common(FRIEND_USER_ID, FRIEND_USER_PAT)
|
||||
.await;
|
||||
|
||||
@@ -24,7 +24,7 @@ async fn oauth_flow_happy_path() {
|
||||
valid_redirect_uri: base_redirect_uri,
|
||||
client_id,
|
||||
client_secret,
|
||||
} = env.dummy.as_ref().unwrap().oauth_client_alpha.clone();
|
||||
} = &env.dummy.oauth_client_alpha;
|
||||
|
||||
// Initiate authorization
|
||||
let redirect_uri = format!("{}?foo=bar", base_redirect_uri);
|
||||
@@ -32,7 +32,7 @@ async fn oauth_flow_happy_path() {
|
||||
let resp = env
|
||||
.api
|
||||
.oauth_authorize(
|
||||
&client_id,
|
||||
client_id,
|
||||
Some("USER_READ NOTIFICATION_READ"),
|
||||
Some(&redirect_uri),
|
||||
Some(original_state),
|
||||
@@ -60,7 +60,7 @@ async fn oauth_flow_happy_path() {
|
||||
auth_code.to_string(),
|
||||
Some(redirect_uri.clone()),
|
||||
client_id.to_string(),
|
||||
&client_secret,
|
||||
client_secret,
|
||||
)
|
||||
.await;
|
||||
assert_status(&resp, StatusCode::OK);
|
||||
@@ -82,7 +82,7 @@ async fn oauth_flow_happy_path() {
|
||||
#[actix_rt::test]
|
||||
async fn oauth_authorize_for_already_authorized_scopes_returns_auth_code() {
|
||||
with_test_environment(None, |env: TestEnvironment<ApiV3>| async move {
|
||||
let DummyOAuthClientAlpha { client_id, .. } = env.dummy.unwrap().oauth_client_alpha;
|
||||
let DummyOAuthClientAlpha { client_id, .. } = env.dummy.oauth_client_alpha;
|
||||
|
||||
let resp = env
|
||||
.api
|
||||
@@ -119,7 +119,7 @@ async fn get_oauth_token_with_already_used_auth_code_fails() {
|
||||
client_id,
|
||||
client_secret,
|
||||
..
|
||||
} = env.dummy.unwrap().oauth_client_alpha;
|
||||
} = env.dummy.oauth_client_alpha;
|
||||
|
||||
let resp = env
|
||||
.api
|
||||
@@ -152,7 +152,7 @@ async fn authorize_with_broader_scopes_can_complete_flow() {
|
||||
client_id,
|
||||
client_secret,
|
||||
..
|
||||
} = env.dummy.as_ref().unwrap().oauth_client_alpha.clone();
|
||||
} = env.dummy.oauth_client_alpha.clone();
|
||||
|
||||
let first_access_token = env
|
||||
.api
|
||||
@@ -209,7 +209,7 @@ async fn authorize_with_broader_scopes_can_complete_flow() {
|
||||
#[actix_rt::test]
|
||||
async fn oauth_authorize_with_broader_scopes_requires_user_accept() {
|
||||
with_test_environment(None, |env: TestEnvironment<ApiV3>| async move {
|
||||
let client_id = env.dummy.unwrap().oauth_client_alpha.client_id.clone();
|
||||
let client_id = env.dummy.oauth_client_alpha.client_id;
|
||||
let resp = env
|
||||
.api
|
||||
.oauth_authorize(&client_id, Some("USER_READ"), None, None, USER_USER_PAT)
|
||||
@@ -237,7 +237,7 @@ async fn oauth_authorize_with_broader_scopes_requires_user_accept() {
|
||||
#[actix_rt::test]
|
||||
async fn reject_authorize_ends_authorize_flow() {
|
||||
with_test_environment(None, |env: TestEnvironment<ApiV3>| async move {
|
||||
let client_id = env.dummy.unwrap().oauth_client_alpha.client_id.clone();
|
||||
let client_id = env.dummy.oauth_client_alpha.client_id;
|
||||
let resp = env
|
||||
.api
|
||||
.oauth_authorize(&client_id, None, None, None, USER_USER_PAT)
|
||||
@@ -256,7 +256,7 @@ async fn reject_authorize_ends_authorize_flow() {
|
||||
#[actix_rt::test]
|
||||
async fn accept_authorize_after_already_accepting_fails() {
|
||||
with_test_environment(None, |env: TestEnvironment<ApiV3>| async move {
|
||||
let client_id = env.dummy.unwrap().oauth_client_alpha.client_id.clone();
|
||||
let client_id = env.dummy.oauth_client_alpha.client_id;
|
||||
let resp = env
|
||||
.api
|
||||
.oauth_authorize(&client_id, None, None, None, USER_USER_PAT)
|
||||
@@ -278,12 +278,12 @@ async fn revoke_authorization_after_issuing_token_revokes_token() {
|
||||
client_id,
|
||||
client_secret,
|
||||
..
|
||||
} = env.dummy.as_ref().unwrap().oauth_client_alpha.clone();
|
||||
} = &env.dummy.oauth_client_alpha;
|
||||
let access_token = env
|
||||
.api
|
||||
.complete_full_authorize_flow(
|
||||
&client_id,
|
||||
&client_secret,
|
||||
client_id,
|
||||
client_secret,
|
||||
Some("NOTIFICATION_READ"),
|
||||
None,
|
||||
None,
|
||||
@@ -295,7 +295,7 @@ async fn revoke_authorization_after_issuing_token_revokes_token() {
|
||||
|
||||
let resp = env
|
||||
.api
|
||||
.revoke_oauth_authorization(&client_id, USER_USER_PAT)
|
||||
.revoke_oauth_authorization(client_id, USER_USER_PAT)
|
||||
.await;
|
||||
assert_status(&resp, StatusCode::OK);
|
||||
|
||||
|
||||
@@ -98,8 +98,7 @@ async fn create_oauth_client_with_restricted_scopes_fails() {
|
||||
#[actix_rt::test]
|
||||
async fn get_oauth_client_for_client_creator_succeeds() {
|
||||
with_test_environment(None, |env: TestEnvironment<ApiV3>| async move {
|
||||
let DummyOAuthClientAlpha { client_id, .. } =
|
||||
env.dummy.as_ref().unwrap().oauth_client_alpha.clone();
|
||||
let DummyOAuthClientAlpha { client_id, .. } = env.dummy.oauth_client_alpha.clone();
|
||||
|
||||
let resp = env
|
||||
.api
|
||||
@@ -116,8 +115,7 @@ async fn get_oauth_client_for_client_creator_succeeds() {
|
||||
#[actix_rt::test]
|
||||
async fn get_oauth_client_for_unrelated_user_fails() {
|
||||
with_test_environment(None, |env: TestEnvironment<ApiV3>| async move {
|
||||
let DummyOAuthClientAlpha { client_id, .. } =
|
||||
env.dummy.as_ref().unwrap().oauth_client_alpha.clone();
|
||||
let DummyOAuthClientAlpha { client_id, .. } = env.dummy.oauth_client_alpha.clone();
|
||||
|
||||
let resp = env
|
||||
.api
|
||||
@@ -132,7 +130,7 @@ async fn get_oauth_client_for_unrelated_user_fails() {
|
||||
#[actix_rt::test]
|
||||
async fn can_delete_oauth_client() {
|
||||
with_test_environment(None, |env: TestEnvironment<ApiV3>| async move {
|
||||
let client_id = env.dummy.unwrap().oauth_client_alpha.client_id.clone();
|
||||
let client_id = env.dummy.oauth_client_alpha.client_id.clone();
|
||||
let resp = env.api.delete_oauth_client(&client_id, USER_USER_PAT).await;
|
||||
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||
|
||||
@@ -152,7 +150,7 @@ async fn delete_oauth_client_after_issuing_access_tokens_revokes_tokens() {
|
||||
client_id,
|
||||
client_secret,
|
||||
..
|
||||
} = env.dummy.as_ref().unwrap().oauth_client_alpha.clone();
|
||||
} = env.dummy.oauth_client_alpha.clone();
|
||||
let access_token = env
|
||||
.api
|
||||
.complete_full_authorize_flow(
|
||||
@@ -184,7 +182,7 @@ async fn can_list_user_oauth_authorizations() {
|
||||
client_id,
|
||||
client_secret,
|
||||
..
|
||||
} = env.dummy.as_ref().unwrap().oauth_client_alpha.clone();
|
||||
} = env.dummy.oauth_client_alpha.clone();
|
||||
env.api
|
||||
.complete_full_authorize_flow(
|
||||
&client_id,
|
||||
|
||||
@@ -18,12 +18,7 @@ mod common;
|
||||
async fn create_organization() {
|
||||
with_test_environment(None, |test_env: TestEnvironment<ApiV3>| async move {
|
||||
let api = &test_env.api;
|
||||
let zeta_organization_slug = &test_env
|
||||
.dummy
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.organization_zeta
|
||||
.organization_id;
|
||||
let zeta_organization_slug = &test_env.dummy.organization_zeta.organization_id;
|
||||
|
||||
// Failed creations title:
|
||||
// - slug collision with zeta
|
||||
@@ -88,12 +83,7 @@ async fn patch_organization() {
|
||||
with_test_environment(None, |test_env: TestEnvironment<ApiV3>| async move {
|
||||
let api = &test_env.api;
|
||||
|
||||
let zeta_organization_id = &test_env
|
||||
.dummy
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.organization_zeta
|
||||
.organization_id;
|
||||
let zeta_organization_id = &test_env.dummy.organization_zeta.organization_id;
|
||||
|
||||
// Create 'theta' organization
|
||||
let resp = api
|
||||
@@ -169,12 +159,7 @@ async fn patch_organization() {
|
||||
async fn add_remove_icon() {
|
||||
with_test_environment(None, |test_env: TestEnvironment<ApiV3>| async move {
|
||||
let api = &test_env.api;
|
||||
let zeta_organization_id = &test_env
|
||||
.dummy
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.organization_zeta
|
||||
.organization_id;
|
||||
let zeta_organization_id = &test_env.dummy.organization_zeta.organization_id;
|
||||
|
||||
// Get project
|
||||
let resp = test_env
|
||||
@@ -221,12 +206,7 @@ async fn add_remove_icon() {
|
||||
async fn delete_org() {
|
||||
with_test_environment(None, |test_env: TestEnvironment<ApiV3>| async move {
|
||||
let api = &test_env.api;
|
||||
let zeta_organization_id = &test_env
|
||||
.dummy
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.organization_zeta
|
||||
.organization_id;
|
||||
let zeta_organization_id = &test_env.dummy.organization_zeta.organization_id;
|
||||
|
||||
let resp = api
|
||||
.delete_organization(zeta_organization_id, USER_USER_PAT)
|
||||
@@ -246,14 +226,9 @@ async fn delete_org() {
|
||||
#[actix_rt::test]
|
||||
async fn add_remove_organization_projects() {
|
||||
with_test_environment(None, |test_env: TestEnvironment<ApiV3>| async move {
|
||||
let alpha_project_id: &str = &test_env.dummy.as_ref().unwrap().project_alpha.project_id;
|
||||
let alpha_project_slug: &str = &test_env.dummy.as_ref().unwrap().project_alpha.project_slug;
|
||||
let zeta_organization_id: &str = &test_env
|
||||
.dummy
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.organization_zeta
|
||||
.organization_id;
|
||||
let alpha_project_id: &str = &test_env.dummy.project_alpha.project_id;
|
||||
let alpha_project_slug: &str = &test_env.dummy.project_alpha.project_slug;
|
||||
let zeta_organization_id: &str = &test_env.dummy.organization_zeta.organization_id;
|
||||
|
||||
// Add/remove project to organization, first by ID, then by slug
|
||||
for alpha in [alpha_project_id, alpha_project_slug] {
|
||||
@@ -331,13 +306,8 @@ async fn permissions_patch_organization() {
|
||||
#[actix_rt::test]
|
||||
async fn permissions_edit_details() {
|
||||
with_test_environment(None, |test_env: TestEnvironment<ApiV3>| async move {
|
||||
let zeta_organization_id = &test_env
|
||||
.dummy
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.organization_zeta
|
||||
.organization_id;
|
||||
let zeta_team_id = &test_env.dummy.as_ref().unwrap().organization_zeta.team_id;
|
||||
let zeta_organization_id = &test_env.dummy.organization_zeta.organization_id;
|
||||
let zeta_team_id = &test_env.dummy.organization_zeta.team_id;
|
||||
|
||||
let api = &test_env.api;
|
||||
let edit_details = OrganizationPermissions::EDIT_DETAILS;
|
||||
@@ -381,13 +351,8 @@ async fn permissions_manage_invites() {
|
||||
with_test_environment_all(None, |test_env| async move {
|
||||
let api = &test_env.api;
|
||||
|
||||
let zeta_organization_id = &test_env
|
||||
.dummy
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.organization_zeta
|
||||
.organization_id;
|
||||
let zeta_team_id = &test_env.dummy.as_ref().unwrap().organization_zeta.team_id;
|
||||
let zeta_organization_id = &test_env.dummy.organization_zeta.organization_id;
|
||||
let zeta_team_id = &test_env.dummy.organization_zeta.team_id;
|
||||
|
||||
let manage_invites = OrganizationPermissions::MANAGE_INVITES;
|
||||
|
||||
@@ -472,15 +437,10 @@ async fn permissions_add_remove_project() {
|
||||
with_test_environment(None, |test_env: TestEnvironment<ApiV3>| async move {
|
||||
let api = &test_env.api;
|
||||
|
||||
let alpha_project_id = &test_env.dummy.as_ref().unwrap().project_alpha.project_id;
|
||||
let alpha_team_id = &test_env.dummy.as_ref().unwrap().project_alpha.team_id;
|
||||
let zeta_organization_id = &test_env
|
||||
.dummy
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.organization_zeta
|
||||
.organization_id;
|
||||
let zeta_team_id = &test_env.dummy.as_ref().unwrap().organization_zeta.team_id;
|
||||
let alpha_project_id = &test_env.dummy.project_alpha.project_id;
|
||||
let alpha_team_id = &test_env.dummy.project_alpha.team_id;
|
||||
let zeta_organization_id = &test_env.dummy.organization_zeta.organization_id;
|
||||
let zeta_team_id = &test_env.dummy.organization_zeta.team_id;
|
||||
|
||||
let add_project = OrganizationPermissions::ADD_PROJECT;
|
||||
|
||||
@@ -557,13 +517,8 @@ async fn permissions_delete_organization() {
|
||||
#[actix_rt::test]
|
||||
async fn permissions_add_default_project_permissions() {
|
||||
with_test_environment_all(None, |test_env| async move {
|
||||
let zeta_organization_id = &test_env
|
||||
.dummy
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.organization_zeta
|
||||
.organization_id;
|
||||
let zeta_team_id = &test_env.dummy.as_ref().unwrap().organization_zeta.team_id;
|
||||
let zeta_organization_id = &test_env.dummy.organization_zeta.organization_id;
|
||||
let zeta_team_id = &test_env.dummy.organization_zeta.team_id;
|
||||
|
||||
let api = &test_env.api;
|
||||
|
||||
|
||||
@@ -60,6 +60,9 @@ pub async fn pat_full_test() {
|
||||
let mock_pat_test = |token: &str| {
|
||||
let token = token.to_string();
|
||||
async {
|
||||
// This uses a route directly instead of an api call because it doesn't relaly matter and we
|
||||
// want it to succeed no matter what.
|
||||
// This is an arbitrary request.
|
||||
let req = test::TestRequest::post()
|
||||
.uri("/v3/collection")
|
||||
.append_header(("Authorization", token))
|
||||
|
||||
198
tests/project.rs
198
tests/project.rs
@@ -2,7 +2,6 @@ use std::collections::HashMap;
|
||||
|
||||
use actix_http::StatusCode;
|
||||
use actix_web::test;
|
||||
use chrono::{Duration, Utc};
|
||||
use common::api_v3::ApiV3;
|
||||
use common::database::*;
|
||||
use common::dummy_data::DUMMY_CATEGORIES;
|
||||
@@ -20,25 +19,29 @@ use serde_json::json;
|
||||
|
||||
use crate::common::api_common::models::CommonItemType;
|
||||
use crate::common::api_common::request_data::ProjectCreationRequestData;
|
||||
use crate::common::api_common::{ApiProject, ApiTeams, ApiVersion, AppendsOptionalPat};
|
||||
use crate::common::dummy_data::{DummyImage, TestFile};
|
||||
use crate::common::api_common::{ApiProject, ApiTeams, ApiVersion};
|
||||
use crate::common::dummy_data::{DummyImage, DummyProjectAlpha, DummyProjectBeta, TestFile};
|
||||
mod common;
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_get_project() {
|
||||
// Test setup and dummy data
|
||||
with_test_environment_all(None, |test_env| async move {
|
||||
let alpha_project_id = &test_env.dummy.as_ref().unwrap().project_alpha.project_id;
|
||||
let beta_project_id = &test_env.dummy.as_ref().unwrap().project_beta.project_id;
|
||||
let alpha_project_slug = &test_env.dummy.as_ref().unwrap().project_alpha.project_slug;
|
||||
let alpha_version_id = &test_env.dummy.as_ref().unwrap().project_alpha.version_id;
|
||||
let DummyProjectAlpha {
|
||||
project_id: alpha_project_id,
|
||||
project_slug: alpha_project_slug,
|
||||
version_id: alpha_version_id,
|
||||
..
|
||||
} = &test_env.dummy.project_alpha;
|
||||
let DummyProjectBeta {
|
||||
project_id: beta_project_id,
|
||||
..
|
||||
} = &test_env.dummy.project_beta;
|
||||
|
||||
let api = &test_env.api;
|
||||
|
||||
// Perform request on dummy data
|
||||
let req = test::TestRequest::get()
|
||||
.uri(&format!("/v3/project/{alpha_project_id}"))
|
||||
.append_pat(USER_USER_PAT)
|
||||
.to_request();
|
||||
let resp = test_env.call(req).await;
|
||||
let resp = api.get_project(alpha_project_id, USER_USER_PAT).await;
|
||||
let status = resp.status();
|
||||
let body: serde_json::Value = test::read_body_json(resp).await;
|
||||
|
||||
@@ -71,11 +74,7 @@ async fn test_get_project() {
|
||||
assert_eq!(cached_project["inner"]["slug"], json!(alpha_project_slug));
|
||||
|
||||
// Make the request again, this time it should be cached
|
||||
let req = test::TestRequest::get()
|
||||
.uri(&format!("/v3/project/{alpha_project_id}"))
|
||||
.append_pat(USER_USER_PAT)
|
||||
.to_request();
|
||||
let resp = test_env.call(req).await;
|
||||
let resp = api.get_project(alpha_project_id, USER_USER_PAT).await;
|
||||
let status = resp.status();
|
||||
assert_eq!(status, 200);
|
||||
|
||||
@@ -84,21 +83,11 @@ async fn test_get_project() {
|
||||
assert_eq!(body["slug"], json!(alpha_project_slug));
|
||||
|
||||
// Request should fail on non-existent project
|
||||
let req = test::TestRequest::get()
|
||||
.uri("/v3/project/nonexistent")
|
||||
.append_pat(USER_USER_PAT)
|
||||
.to_request();
|
||||
|
||||
let resp = test_env.call(req).await;
|
||||
let resp = api.get_project("nonexistent", USER_USER_PAT).await;
|
||||
assert_eq!(resp.status(), 404);
|
||||
|
||||
// Similarly, request should fail on non-authorized user, on a yet-to-be-approved or hidden project, with a 404 (hiding the existence of the project)
|
||||
let req = test::TestRequest::get()
|
||||
.uri(&format!("/v3/project/{beta_project_id}"))
|
||||
.append_pat(ENEMY_USER_PAT)
|
||||
.to_request();
|
||||
|
||||
let resp = test_env.call(req).await;
|
||||
let resp = api.get_project(beta_project_id, ENEMY_USER_PAT).await;
|
||||
assert_eq!(resp.status(), 404);
|
||||
})
|
||||
.await;
|
||||
@@ -290,8 +279,8 @@ pub async fn test_patch_project() {
|
||||
with_test_environment(None, |test_env: TestEnvironment<ApiV3>| async move {
|
||||
let api = &test_env.api;
|
||||
|
||||
let alpha_project_slug = &test_env.dummy.as_ref().unwrap().project_alpha.project_slug;
|
||||
let beta_project_slug = &test_env.dummy.as_ref().unwrap().project_beta.project_slug;
|
||||
let alpha_project_slug = &test_env.dummy.project_alpha.project_slug;
|
||||
let beta_project_slug = &test_env.dummy.project_beta.project_slug;
|
||||
|
||||
// First, we do some patch requests that should fail.
|
||||
// Failure because the user is not authorized.
|
||||
@@ -472,7 +461,7 @@ pub async fn test_patch_v3() {
|
||||
with_test_environment(None, |test_env: TestEnvironment<ApiV3>| async move {
|
||||
let api = &test_env.api;
|
||||
|
||||
let alpha_project_slug = &test_env.dummy.as_ref().unwrap().project_alpha.project_slug;
|
||||
let alpha_project_slug = &test_env.dummy.project_alpha.project_slug;
|
||||
|
||||
// Sucessful request to patch many fields.
|
||||
let resp = api
|
||||
@@ -503,8 +492,8 @@ pub async fn test_patch_v3() {
|
||||
pub async fn test_bulk_edit_categories() {
|
||||
with_test_environment_all(None, |test_env| async move {
|
||||
let api = &test_env.api;
|
||||
let alpha_project_id: &str = &test_env.dummy.as_ref().unwrap().project_alpha.project_id;
|
||||
let beta_project_id: &str = &test_env.dummy.as_ref().unwrap().project_beta.project_id;
|
||||
let alpha_project_id: &str = &test_env.dummy.project_alpha.project_id;
|
||||
let beta_project_id: &str = &test_env.dummy.project_beta.project_id;
|
||||
|
||||
let resp = api
|
||||
.edit_project_bulk(
|
||||
@@ -544,8 +533,8 @@ pub async fn test_bulk_edit_categories() {
|
||||
pub async fn test_bulk_edit_links() {
|
||||
with_test_environment(None, |test_env: TestEnvironment<ApiV3>| async move {
|
||||
let api = &test_env.api;
|
||||
let alpha_project_id: &str = &test_env.dummy.as_ref().unwrap().project_alpha.project_id;
|
||||
let beta_project_id: &str = &test_env.dummy.as_ref().unwrap().project_beta.project_id;
|
||||
let alpha_project_id: &str = &test_env.dummy.project_alpha.project_id;
|
||||
let beta_project_id: &str = &test_env.dummy.project_beta.project_id;
|
||||
|
||||
// Sets links for issue, source, wiki, and patreon for all projects
|
||||
// The first loop, sets issue, the second, clears it for all projects.
|
||||
@@ -595,8 +584,8 @@ pub async fn test_bulk_edit_links() {
|
||||
async fn delete_project_with_report() {
|
||||
with_test_environment(None, |test_env: TestEnvironment<ApiV3>| async move {
|
||||
let api = &test_env.api;
|
||||
let alpha_project_id: &str = &test_env.dummy.as_ref().unwrap().project_alpha.project_id;
|
||||
let beta_project_id: &str = &test_env.dummy.as_ref().unwrap().project_beta.project_id;
|
||||
let alpha_project_id: &str = &test_env.dummy.project_alpha.project_id;
|
||||
let beta_project_id: &str = &test_env.dummy.project_beta.project_id;
|
||||
|
||||
// Create a report for the project
|
||||
let resp = api
|
||||
@@ -682,8 +671,8 @@ async fn delete_project_with_report() {
|
||||
#[actix_rt::test]
|
||||
async fn permissions_patch_project_v3() {
|
||||
with_test_environment(Some(8), |test_env: TestEnvironment<ApiV3>| async move {
|
||||
let alpha_project_id = &test_env.dummy.as_ref().unwrap().project_alpha.project_id;
|
||||
let alpha_team_id = &test_env.dummy.as_ref().unwrap().project_alpha.team_id;
|
||||
let alpha_project_id = &test_env.dummy.project_alpha.project_id;
|
||||
let alpha_team_id = &test_env.dummy.project_alpha.team_id;
|
||||
|
||||
let api = &test_env.api;
|
||||
// TODO: This should be a separate test from v3
|
||||
@@ -797,47 +786,69 @@ async fn permissions_patch_project_v3() {
|
||||
.await;
|
||||
}
|
||||
|
||||
// TODO: Project scheduling has been temporarily disabled, so this test is disabled as well
|
||||
// #[actix_rt::test]
|
||||
// async fn permissions_schedule() {
|
||||
// with_test_environment(None, |test_env : TestEnvironment<ApiV3>| async move {
|
||||
// let DummyProjectAlpha {
|
||||
// project_id: alpha_project_id,
|
||||
// team_id: alpha_team_id,
|
||||
// ..
|
||||
// } = &test_env.dummy.project_alpha;
|
||||
// let DummyProjectBeta {
|
||||
// project_id: beta_project_id,
|
||||
// version_id: beta_version_id,
|
||||
// team_id: beta_team_id,
|
||||
// ..
|
||||
// } = &test_env.dummy.project_beta;
|
||||
|
||||
// let edit_details = ProjectPermissions::EDIT_DETAILS;
|
||||
// let api = &test_env.api;
|
||||
|
||||
// // Approve beta version as private so we can schedule it
|
||||
// let resp = api
|
||||
// .edit_version(
|
||||
// beta_version_id,
|
||||
// json!({
|
||||
// "status": "unlisted"
|
||||
// }),
|
||||
// MOD_USER_PAT,
|
||||
// )
|
||||
// .await;
|
||||
// assert_eq!(resp.status(), 204);
|
||||
|
||||
// // Schedule version
|
||||
// let req_gen = |ctx: PermissionsTestContext| async move {
|
||||
// api.schedule_version(
|
||||
// beta_version_id,
|
||||
// "archived",
|
||||
// Utc::now() + Duration::days(1),
|
||||
// ctx.test_pat.as_deref(),
|
||||
// )
|
||||
// .await
|
||||
// };
|
||||
// PermissionsTest::new(&test_env)
|
||||
// .with_existing_project(beta_project_id, beta_team_id)
|
||||
// .with_user(FRIEND_USER_ID, FRIEND_USER_PAT, true)
|
||||
// .simple_project_permissions_test(edit_details, req_gen)
|
||||
// .await
|
||||
// .unwrap();
|
||||
// }).await
|
||||
// }
|
||||
|
||||
// Not covered by PATCH /project
|
||||
#[actix_rt::test]
|
||||
async fn permissions_edit_details() {
|
||||
with_test_environment_all(None, |test_env| async move {
|
||||
let alpha_project_id = &test_env.dummy.as_ref().unwrap().project_alpha.project_id;
|
||||
let alpha_team_id = &test_env.dummy.as_ref().unwrap().project_alpha.team_id;
|
||||
let beta_project_id = &test_env.dummy.as_ref().unwrap().project_beta.project_id;
|
||||
let beta_team_id = &test_env.dummy.as_ref().unwrap().project_beta.team_id;
|
||||
let beta_version_id = &test_env.dummy.as_ref().unwrap().project_beta.version_id;
|
||||
let DummyProjectAlpha {
|
||||
project_id: alpha_project_id,
|
||||
team_id: alpha_team_id,
|
||||
..
|
||||
} = &test_env.dummy.project_alpha;
|
||||
|
||||
let edit_details = ProjectPermissions::EDIT_DETAILS;
|
||||
let api = &test_env.api;
|
||||
|
||||
// Approve beta version as private so we can schedule it
|
||||
let req = test::TestRequest::patch()
|
||||
.uri(&format!("/v3/version/{beta_version_id}"))
|
||||
.append_pat(MOD_USER_PAT)
|
||||
.set_json(json!({
|
||||
"status": "unlisted"
|
||||
}))
|
||||
.to_request();
|
||||
let resp = test_env.call(req).await;
|
||||
assert_eq!(resp.status(), 204);
|
||||
|
||||
// Schedule version
|
||||
let req_gen = |ctx: PermissionsTestContext| async move {
|
||||
api.schedule_project(
|
||||
beta_version_id,
|
||||
"archived",
|
||||
Utc::now() + Duration::days(1),
|
||||
ctx.test_pat.as_deref(),
|
||||
)
|
||||
.await
|
||||
};
|
||||
PermissionsTest::new(&test_env)
|
||||
.with_existing_project(beta_project_id, beta_team_id)
|
||||
.with_user(FRIEND_USER_ID, FRIEND_USER_PAT, true)
|
||||
.simple_project_permissions_test(edit_details, req_gen)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// Icon edit
|
||||
// Uses alpha project to delete this icon
|
||||
let req_gen = |ctx: PermissionsTestContext| async move {
|
||||
@@ -889,11 +900,7 @@ async fn permissions_edit_details() {
|
||||
.await
|
||||
.unwrap();
|
||||
// Get project, as we need the gallery image url
|
||||
let req = test::TestRequest::get()
|
||||
.uri(&format!("/v3/project/{alpha_project_id}"))
|
||||
.append_pat(USER_USER_PAT)
|
||||
.to_request();
|
||||
let resp = test_env.call(req).await;
|
||||
let resp = api.get_project(alpha_project_id, USER_USER_PAT).await;
|
||||
let project: serde_json::Value = test::read_body_json(resp).await;
|
||||
let gallery_url = project["gallery"][0]["url"].as_str().unwrap();
|
||||
|
||||
@@ -940,10 +947,10 @@ async fn permissions_edit_details() {
|
||||
#[actix_rt::test]
|
||||
async fn permissions_upload_version() {
|
||||
with_test_environment(None, |test_env: TestEnvironment<ApiV3>| async move {
|
||||
let alpha_project_id = &test_env.dummy.as_ref().unwrap().project_alpha.project_id;
|
||||
let alpha_version_id = &test_env.dummy.as_ref().unwrap().project_alpha.version_id;
|
||||
let alpha_team_id = &test_env.dummy.as_ref().unwrap().project_alpha.team_id;
|
||||
let alpha_file_hash = &test_env.dummy.as_ref().unwrap().project_alpha.file_hash;
|
||||
let alpha_project_id = &test_env.dummy.project_alpha.project_id;
|
||||
let alpha_version_id = &test_env.dummy.project_alpha.version_id;
|
||||
let alpha_team_id = &test_env.dummy.project_alpha.team_id;
|
||||
let alpha_file_hash = &test_env.dummy.project_alpha.file_hash;
|
||||
|
||||
let api = &test_env.api;
|
||||
|
||||
@@ -1038,8 +1045,8 @@ async fn permissions_upload_version() {
|
||||
async fn permissions_manage_invites() {
|
||||
// Add member, remove member, edit member
|
||||
with_test_environment_all(None, |test_env| async move {
|
||||
let alpha_project_id = &test_env.dummy.as_ref().unwrap().project_alpha.project_id;
|
||||
let alpha_team_id = &test_env.dummy.as_ref().unwrap().project_alpha.team_id;
|
||||
let alpha_project_id = &test_env.dummy.project_alpha.project_id;
|
||||
let alpha_team_id = &test_env.dummy.project_alpha.team_id;
|
||||
|
||||
let api = &test_env.api;
|
||||
let manage_invites = ProjectPermissions::MANAGE_INVITES;
|
||||
@@ -1096,22 +1103,19 @@ async fn permissions_manage_invites() {
|
||||
.unwrap();
|
||||
|
||||
// re-add member for testing
|
||||
let req = test::TestRequest::post()
|
||||
.uri(&format!("/v3/team/{}/members", alpha_team_id))
|
||||
.append_pat(ADMIN_USER_PAT)
|
||||
.set_json(json!({
|
||||
"user_id": MOD_USER_ID,
|
||||
}))
|
||||
.to_request();
|
||||
let resp = test_env.call(req).await;
|
||||
let resp = api
|
||||
.add_user_to_team(
|
||||
alpha_team_id,
|
||||
MOD_USER_ID,
|
||||
Some(ProjectPermissions::empty()),
|
||||
None,
|
||||
ADMIN_USER_PAT,
|
||||
)
|
||||
.await;
|
||||
assert_eq!(resp.status(), 204);
|
||||
|
||||
// Accept invite
|
||||
let req = test::TestRequest::post()
|
||||
.uri(&format!("/v3/team/{}/join", alpha_team_id))
|
||||
.append_pat(MOD_USER_PAT)
|
||||
.to_request();
|
||||
let resp = test_env.call(req).await;
|
||||
let resp = api.join_team(alpha_team_id, MOD_USER_PAT).await;
|
||||
assert_eq!(resp.status(), 204);
|
||||
|
||||
// remove existing member (requires remove_member)
|
||||
|
||||
889
tests/scopes.rs
889
tests/scopes.rs
File diff suppressed because it is too large
Load Diff
563
tests/teams.rs
563
tests/teams.rs
@@ -1,8 +1,4 @@
|
||||
use crate::common::{
|
||||
api_common::{ApiTeams, AppendsOptionalPat},
|
||||
database::*,
|
||||
};
|
||||
use actix_web::test;
|
||||
use crate::common::{api_common::ApiTeams, database::*};
|
||||
use common::{
|
||||
api_v3::ApiV3,
|
||||
environment::{with_test_environment, with_test_environment_all, TestEnvironment},
|
||||
@@ -16,126 +12,248 @@ mod common;
|
||||
#[actix_rt::test]
|
||||
async fn test_get_team() {
|
||||
// Test setup and dummy data
|
||||
// Perform get_team related tests for a project team
|
||||
//TODO: This needs to consider organizations now as well
|
||||
with_test_environment_all(None, |test_env| async move {
|
||||
let alpha_project_id = &test_env.dummy.as_ref().unwrap().project_alpha.project_id;
|
||||
let alpha_team_id = &test_env.dummy.as_ref().unwrap().project_alpha.team_id;
|
||||
let zeta_organization_id = &test_env
|
||||
.dummy
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.organization_zeta
|
||||
.organization_id;
|
||||
let zeta_team_id = &test_env.dummy.as_ref().unwrap().organization_zeta.team_id;
|
||||
let api = &test_env.api;
|
||||
let alpha_project_id = &test_env.dummy.project_alpha.project_id;
|
||||
let alpha_team_id = &test_env.dummy.project_alpha.team_id;
|
||||
|
||||
// Perform tests for an organization team and a project team
|
||||
for (team_association_id, team_association, team_id) in [
|
||||
(alpha_project_id, "project", alpha_team_id),
|
||||
(zeta_organization_id, "organization", zeta_team_id),
|
||||
] {
|
||||
// A non-member of the team should get basic info but not be able to see private data
|
||||
for uri in [
|
||||
format!("/v3/team/{team_id}/members"),
|
||||
format!("/v3/{team_association}/{team_association_id}/members"),
|
||||
] {
|
||||
let req = test::TestRequest::get()
|
||||
.uri(&uri)
|
||||
.append_pat(FRIEND_USER_PAT)
|
||||
.to_request();
|
||||
// A non-member of the team should get basic info but not be able to see private data
|
||||
let members = api
|
||||
.get_team_members_deserialized_common(alpha_team_id, FRIEND_USER_PAT)
|
||||
.await;
|
||||
assert_eq!(members.len(), 1);
|
||||
assert_eq!(members[0].user.id.0, USER_USER_ID_PARSED as u64);
|
||||
assert!(members[0].permissions.is_none());
|
||||
|
||||
let resp = test_env.call(req).await;
|
||||
assert_eq!(resp.status(), 200);
|
||||
let value: serde_json::Value = test::read_body_json(resp).await;
|
||||
assert_eq!(value[0]["user"]["id"], USER_USER_ID);
|
||||
assert!(value[0]["permissions"].is_null());
|
||||
}
|
||||
let members = api
|
||||
.get_project_members_deserialized_common(alpha_project_id, FRIEND_USER_PAT)
|
||||
.await;
|
||||
assert_eq!(members.len(), 1);
|
||||
assert_eq!(members[0].user.id.0, USER_USER_ID_PARSED as u64);
|
||||
|
||||
// A non-accepted member of the team should:
|
||||
// - not be able to see private data about the team, but see all members including themselves
|
||||
// - should not appear in the team members list to enemy users
|
||||
let req = test::TestRequest::post()
|
||||
.uri(&format!("/v3/team/{team_id}/members"))
|
||||
.append_pat(USER_USER_PAT)
|
||||
.set_json(&json!({
|
||||
"user_id": FRIEND_USER_ID,
|
||||
}))
|
||||
.to_request();
|
||||
let resp = test_env.call(req).await;
|
||||
assert_eq!(resp.status(), 204);
|
||||
// A non-accepted member of the team should:
|
||||
// - not be able to see private data about the team, but see all members including themselves
|
||||
// - should not appear in the team members list to enemy users
|
||||
let resp = api
|
||||
.add_user_to_team(alpha_team_id, FRIEND_USER_ID, None, None, USER_USER_PAT)
|
||||
.await;
|
||||
assert_eq!(resp.status(), 204);
|
||||
|
||||
for uri in [
|
||||
format!("/v3/team/{team_id}/members"),
|
||||
format!("/v3/{team_association}/{team_association_id}/members"),
|
||||
] {
|
||||
let req = test::TestRequest::get()
|
||||
.uri(&uri)
|
||||
.append_pat(FRIEND_USER_PAT)
|
||||
.to_request();
|
||||
let resp = test_env.call(req).await;
|
||||
assert_eq!(resp.status(), 200);
|
||||
let value: serde_json::Value = test::read_body_json(resp).await;
|
||||
let members = value.as_array().unwrap();
|
||||
assert!(members.len() == 2); // USER_USER_ID and FRIEND_USER_ID should be in the team
|
||||
let user_user = members
|
||||
.iter()
|
||||
.find(|x| x["user"]["id"] == USER_USER_ID)
|
||||
.unwrap();
|
||||
let friend_user = members
|
||||
.iter()
|
||||
.find(|x| x["user"]["id"] == FRIEND_USER_ID)
|
||||
.unwrap();
|
||||
assert_eq!(user_user["user"]["id"], USER_USER_ID);
|
||||
assert!(user_user["permissions"].is_null()); // Should not see private data of the team
|
||||
assert_eq!(friend_user["user"]["id"], FRIEND_USER_ID);
|
||||
assert!(friend_user["permissions"].is_null());
|
||||
// Team check directly
|
||||
let members = api
|
||||
.get_team_members_deserialized_common(alpha_team_id, FRIEND_USER_PAT)
|
||||
.await;
|
||||
assert!(members.len() == 2); // USER_USER_ID and FRIEND_USER_ID should be in the team
|
||||
let user_user = members
|
||||
.iter()
|
||||
.find(|x| x.user.id.0 == USER_USER_ID_PARSED as u64)
|
||||
.unwrap();
|
||||
let friend_user = members
|
||||
.iter()
|
||||
.find(|x| x.user.id.0 == FRIEND_USER_ID_PARSED as u64)
|
||||
.unwrap();
|
||||
assert_eq!(user_user.user.id.0, USER_USER_ID_PARSED as u64);
|
||||
assert!(user_user.permissions.is_none()); // Should not see private data of the team
|
||||
assert_eq!(friend_user.user.id.0, FRIEND_USER_ID_PARSED as u64);
|
||||
assert!(friend_user.permissions.is_none());
|
||||
|
||||
let req = test::TestRequest::get()
|
||||
.uri(&uri)
|
||||
.append_pat(ENEMY_USER_PAT)
|
||||
.to_request();
|
||||
let resp = test_env.call(req).await;
|
||||
assert_eq!(resp.status(), 200);
|
||||
let value: serde_json::Value = test::read_body_json(resp).await;
|
||||
let members = value.as_array().unwrap();
|
||||
assert_eq!(members.len(), 1); // Only USER_USER_ID should be in the team
|
||||
assert_eq!(members[0]["user"]["id"], USER_USER_ID);
|
||||
assert!(members[0]["permissions"].is_null());
|
||||
}
|
||||
// An accepted member of the team should appear in the team members list
|
||||
// and should be able to see private data about the team
|
||||
let req = test::TestRequest::post()
|
||||
.uri(&format!("/v3/team/{team_id}/join"))
|
||||
.append_pat(FRIEND_USER_PAT)
|
||||
.to_request();
|
||||
let resp = test_env.call(req).await;
|
||||
assert_eq!(resp.status(), 204);
|
||||
// team check via association
|
||||
let members = api
|
||||
.get_project_members_deserialized_common(alpha_project_id, FRIEND_USER_PAT)
|
||||
.await;
|
||||
assert!(members.len() == 2); // USER_USER_ID and FRIEND_USER_ID should be in the team
|
||||
let user_user = members
|
||||
.iter()
|
||||
.find(|x| x.user.id.0 == USER_USER_ID_PARSED as u64)
|
||||
.unwrap();
|
||||
let friend_user = members
|
||||
.iter()
|
||||
.find(|x| x.user.id.0 == FRIEND_USER_ID_PARSED as u64)
|
||||
.unwrap();
|
||||
assert_eq!(user_user.user.id.0, USER_USER_ID_PARSED as u64);
|
||||
assert!(user_user.permissions.is_none()); // Should not see private data of the team
|
||||
assert_eq!(friend_user.user.id.0, FRIEND_USER_ID_PARSED as u64);
|
||||
assert!(friend_user.permissions.is_none());
|
||||
|
||||
for uri in [
|
||||
format!("/v3/team/{team_id}/members"),
|
||||
format!("/v3/{team_association}/{team_association_id}/members"),
|
||||
] {
|
||||
let req = test::TestRequest::get()
|
||||
.uri(&uri)
|
||||
.append_pat(FRIEND_USER_PAT)
|
||||
.to_request();
|
||||
let resp = test_env.call(req).await;
|
||||
assert_eq!(resp.status(), 200);
|
||||
let value: serde_json::Value = test::read_body_json(resp).await;
|
||||
let members = value.as_array().unwrap();
|
||||
assert!(members.len() == 2); // USER_USER_ID and FRIEND_USER_ID should be in the team
|
||||
let user_user = members
|
||||
.iter()
|
||||
.find(|x| x["user"]["id"] == USER_USER_ID)
|
||||
.unwrap();
|
||||
let friend_user = members
|
||||
.iter()
|
||||
.find(|x| x["user"]["id"] == FRIEND_USER_ID)
|
||||
.unwrap();
|
||||
assert_eq!(user_user["user"]["id"], USER_USER_ID);
|
||||
assert!(!user_user["permissions"].is_null()); // SHOULD see private data of the team
|
||||
assert_eq!(friend_user["user"]["id"], FRIEND_USER_ID);
|
||||
assert!(!friend_user["permissions"].is_null());
|
||||
}
|
||||
}
|
||||
// enemy team check directly
|
||||
let members = api
|
||||
.get_team_members_deserialized_common(alpha_team_id, ENEMY_USER_PAT)
|
||||
.await;
|
||||
assert_eq!(members.len(), 1); // Only USER_USER_ID should be in the team
|
||||
|
||||
// enemy team check via association
|
||||
let members = api
|
||||
.get_project_members_deserialized_common(alpha_project_id, ENEMY_USER_PAT)
|
||||
.await;
|
||||
assert_eq!(members.len(), 1); // Only USER_USER_ID should be in the team
|
||||
|
||||
// An accepted member of the team should appear in the team members list
|
||||
// and should be able to see private data about the team
|
||||
let resp = api.join_team(alpha_team_id, FRIEND_USER_PAT).await;
|
||||
assert_eq!(resp.status(), 204);
|
||||
|
||||
// Team check directly
|
||||
let members = api
|
||||
.get_team_members_deserialized_common(alpha_team_id, FRIEND_USER_PAT)
|
||||
.await;
|
||||
assert!(members.len() == 2); // USER_USER_ID and FRIEND_USER_ID should be in the team
|
||||
let user_user = members
|
||||
.iter()
|
||||
.find(|x| x.user.id.0 == USER_USER_ID_PARSED as u64)
|
||||
.unwrap();
|
||||
let friend_user = members
|
||||
.iter()
|
||||
.find(|x| x.user.id.0 == FRIEND_USER_ID_PARSED as u64)
|
||||
.unwrap();
|
||||
assert_eq!(user_user.user.id.0, USER_USER_ID_PARSED as u64);
|
||||
assert!(user_user.permissions.is_some()); // SHOULD see private data of the team
|
||||
assert_eq!(friend_user.user.id.0, FRIEND_USER_ID_PARSED as u64);
|
||||
assert!(friend_user.permissions.is_some());
|
||||
|
||||
// team check via association
|
||||
let members = api
|
||||
.get_project_members_deserialized_common(alpha_project_id, FRIEND_USER_PAT)
|
||||
.await;
|
||||
assert!(members.len() == 2); // USER_USER_ID and FRIEND_USER_ID should be in the team
|
||||
let user_user = members
|
||||
.iter()
|
||||
.find(|x| x.user.id.0 == USER_USER_ID_PARSED as u64)
|
||||
.unwrap();
|
||||
let friend_user = members
|
||||
.iter()
|
||||
.find(|x| x.user.id.0 == FRIEND_USER_ID_PARSED as u64)
|
||||
.unwrap();
|
||||
assert_eq!(user_user.user.id.0, USER_USER_ID_PARSED as u64);
|
||||
assert!(user_user.permissions.is_some()); // SHOULD see private data of the team
|
||||
assert_eq!(friend_user.user.id.0, FRIEND_USER_ID_PARSED as u64);
|
||||
assert!(friend_user.permissions.is_some());
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_get_team_organization() {
|
||||
// Test setup and dummy data
|
||||
// Perform get_team related tests for an organization team
|
||||
//TODO: This needs to consider users in organizations now and how they perceive as well
|
||||
with_test_environment(None, |test_env: TestEnvironment<ApiV3>| async move {
|
||||
let api = &test_env.api;
|
||||
let zeta_organization_id = &test_env.dummy.organization_zeta.organization_id;
|
||||
let zeta_team_id = &test_env.dummy.organization_zeta.team_id;
|
||||
|
||||
// A non-member of the team should get basic info but not be able to see private data
|
||||
let members = api
|
||||
.get_team_members_deserialized_common(zeta_team_id, FRIEND_USER_PAT)
|
||||
.await;
|
||||
assert_eq!(members.len(), 1);
|
||||
assert_eq!(members[0].user.id.0, USER_USER_ID_PARSED as u64);
|
||||
assert!(members[0].permissions.is_none());
|
||||
|
||||
let members = api
|
||||
.get_organization_members_deserialized_common(zeta_organization_id, FRIEND_USER_PAT)
|
||||
.await;
|
||||
assert_eq!(members.len(), 1);
|
||||
assert_eq!(members[0].user.id.0, USER_USER_ID_PARSED as u64);
|
||||
|
||||
// A non-accepted member of the team should:
|
||||
// - not be able to see private data about the team, but see all members including themselves
|
||||
// - should not appear in the team members list to enemy users
|
||||
let resp = api
|
||||
.add_user_to_team(zeta_team_id, FRIEND_USER_ID, None, None, USER_USER_PAT)
|
||||
.await;
|
||||
assert_eq!(resp.status(), 204);
|
||||
|
||||
// Team check directly
|
||||
let members = api
|
||||
.get_team_members_deserialized_common(zeta_team_id, FRIEND_USER_PAT)
|
||||
.await;
|
||||
assert!(members.len() == 2); // USER_USER_ID and FRIEND_USER_ID should be in the team
|
||||
let user_user = members
|
||||
.iter()
|
||||
.find(|x| x.user.id.0 == USER_USER_ID_PARSED as u64)
|
||||
.unwrap();
|
||||
let friend_user = members
|
||||
.iter()
|
||||
.find(|x| x.user.id.0 == FRIEND_USER_ID_PARSED as u64)
|
||||
.unwrap();
|
||||
assert_eq!(user_user.user.id.0, USER_USER_ID_PARSED as u64);
|
||||
assert!(user_user.permissions.is_none()); // Should not see private data of the team
|
||||
assert_eq!(friend_user.user.id.0, FRIEND_USER_ID_PARSED as u64);
|
||||
assert!(friend_user.permissions.is_none());
|
||||
|
||||
// team check via association
|
||||
let members = api
|
||||
.get_organization_members_deserialized_common(zeta_organization_id, FRIEND_USER_PAT)
|
||||
.await;
|
||||
|
||||
assert!(members.len() == 2); // USER_USER_ID and FRIEND_USER_ID should be in the team
|
||||
let user_user = members
|
||||
.iter()
|
||||
.find(|x| x.user.id.0 == USER_USER_ID_PARSED as u64)
|
||||
.unwrap();
|
||||
let friend_user = members
|
||||
.iter()
|
||||
.find(|x| x.user.id.0 == FRIEND_USER_ID_PARSED as u64)
|
||||
.unwrap();
|
||||
assert_eq!(user_user.user.id.0, USER_USER_ID_PARSED as u64);
|
||||
assert!(user_user.permissions.is_none()); // Should not see private data of the team
|
||||
assert_eq!(friend_user.user.id.0, FRIEND_USER_ID_PARSED as u64);
|
||||
assert!(friend_user.permissions.is_none());
|
||||
|
||||
// enemy team check directly
|
||||
let members = api
|
||||
.get_team_members_deserialized_common(zeta_team_id, ENEMY_USER_PAT)
|
||||
.await;
|
||||
assert_eq!(members.len(), 1); // Only USER_USER_ID should be in the team
|
||||
|
||||
// enemy team check via association
|
||||
let members = api
|
||||
.get_organization_members_deserialized_common(zeta_organization_id, ENEMY_USER_PAT)
|
||||
.await;
|
||||
assert_eq!(members.len(), 1); // Only USER_USER_ID should be in the team
|
||||
|
||||
// An accepted member of the team should appear in the team members list
|
||||
// and should be able to see private data about the team
|
||||
let resp = api.join_team(zeta_team_id, FRIEND_USER_PAT).await;
|
||||
assert_eq!(resp.status(), 204);
|
||||
|
||||
// Team check directly
|
||||
let members = api
|
||||
.get_team_members_deserialized_common(zeta_team_id, FRIEND_USER_PAT)
|
||||
.await;
|
||||
assert!(members.len() == 2); // USER_USER_ID and FRIEND_USER_ID should be in the team
|
||||
let user_user = members
|
||||
.iter()
|
||||
.find(|x| x.user.id.0 == USER_USER_ID_PARSED as u64)
|
||||
.unwrap();
|
||||
let friend_user = members
|
||||
.iter()
|
||||
.find(|x| x.user.id.0 == FRIEND_USER_ID_PARSED as u64)
|
||||
.unwrap();
|
||||
assert_eq!(user_user.user.id.0, USER_USER_ID_PARSED as u64);
|
||||
assert!(user_user.permissions.is_some()); // SHOULD see private data of the team
|
||||
assert_eq!(friend_user.user.id.0, FRIEND_USER_ID_PARSED as u64);
|
||||
assert!(friend_user.permissions.is_some());
|
||||
|
||||
// team check via association
|
||||
let members = api
|
||||
.get_organization_members_deserialized_common(zeta_organization_id, FRIEND_USER_PAT)
|
||||
.await;
|
||||
assert!(members.len() == 2); // USER_USER_ID and FRIEND_USER_ID should be in the team
|
||||
let user_user = members
|
||||
.iter()
|
||||
.find(|x| x.user.id.0 == USER_USER_ID_PARSED as u64)
|
||||
.unwrap();
|
||||
let friend_user = members
|
||||
.iter()
|
||||
.find(|x| x.user.id.0 == FRIEND_USER_ID_PARSED as u64)
|
||||
.unwrap();
|
||||
assert_eq!(user_user.user.id.0, USER_USER_ID_PARSED as u64);
|
||||
assert!(user_user.permissions.is_some()); // SHOULD see private data of the team
|
||||
assert_eq!(friend_user.user.id.0, FRIEND_USER_ID_PARSED as u64);
|
||||
assert!(friend_user.permissions.is_some());
|
||||
})
|
||||
.await;
|
||||
}
|
||||
@@ -143,69 +261,44 @@ async fn test_get_team() {
|
||||
#[actix_rt::test]
|
||||
async fn test_get_team_project_orgs() {
|
||||
// Test setup and dummy data
|
||||
with_test_environment_all(None, |test_env| async move {
|
||||
let alpha_project_id = &test_env.dummy.as_ref().unwrap().project_alpha.project_id;
|
||||
let alpha_team_id = &test_env.dummy.as_ref().unwrap().project_alpha.team_id;
|
||||
let zeta_organization_id = &test_env
|
||||
.dummy
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.organization_zeta
|
||||
.organization_id;
|
||||
let zeta_team_id = &test_env.dummy.as_ref().unwrap().organization_zeta.team_id;
|
||||
with_test_environment(None, |test_env: TestEnvironment<ApiV3>| async move {
|
||||
let alpha_project_id = &test_env.dummy.project_alpha.project_id;
|
||||
let alpha_team_id = &test_env.dummy.project_alpha.team_id;
|
||||
let zeta_organization_id = &test_env.dummy.organization_zeta.organization_id;
|
||||
let zeta_team_id = &test_env.dummy.organization_zeta.team_id;
|
||||
|
||||
// Attach alpha to zeta
|
||||
let req = test::TestRequest::post()
|
||||
.uri(&format!("/v3/organization/{zeta_organization_id}/projects"))
|
||||
.append_pat(USER_USER_PAT)
|
||||
.set_json(json!({
|
||||
"project_id": alpha_project_id,
|
||||
}))
|
||||
.to_request();
|
||||
let resp = test_env.call(req).await;
|
||||
let resp = test_env
|
||||
.api
|
||||
.organization_add_project(zeta_organization_id, alpha_project_id, USER_USER_PAT)
|
||||
.await;
|
||||
assert_eq!(resp.status(), 200);
|
||||
|
||||
// Invite and add friend to zeta
|
||||
let req = test::TestRequest::post()
|
||||
.uri(&format!("/v3/team/{zeta_team_id}/members"))
|
||||
.append_pat(USER_USER_PAT)
|
||||
.set_json(json!({
|
||||
"user_id": FRIEND_USER_ID,
|
||||
}))
|
||||
.to_request();
|
||||
let resp = test_env.call(req).await;
|
||||
let resp = test_env
|
||||
.api
|
||||
.add_user_to_team(zeta_team_id, FRIEND_USER_ID, None, None, USER_USER_PAT)
|
||||
.await;
|
||||
assert_eq!(resp.status(), 204);
|
||||
|
||||
let req = test::TestRequest::post()
|
||||
.uri(&format!("/v3/team/{zeta_team_id}/join"))
|
||||
.append_pat(FRIEND_USER_PAT)
|
||||
.to_request();
|
||||
let resp = test_env.call(req).await;
|
||||
let resp = test_env.api.join_team(zeta_team_id, FRIEND_USER_PAT).await;
|
||||
assert_eq!(resp.status(), 204);
|
||||
|
||||
// The team members route from teams (on a project's team):
|
||||
// - the members of the project team specifically
|
||||
// - not the ones from the organization
|
||||
let req = test::TestRequest::get()
|
||||
.uri(&format!("/v3/team/{alpha_team_id}/members"))
|
||||
.append_pat(FRIEND_USER_PAT)
|
||||
.to_request();
|
||||
let resp = test_env.call(req).await;
|
||||
assert_eq!(resp.status(), 200);
|
||||
let value: serde_json::Value = test::read_body_json(resp).await;
|
||||
let members = value.as_array().unwrap();
|
||||
let members = test_env
|
||||
.api
|
||||
.get_team_members_deserialized_common(alpha_team_id, FRIEND_USER_PAT)
|
||||
.await;
|
||||
assert_eq!(members.len(), 1);
|
||||
|
||||
// The team members route from project should show:
|
||||
// - the members of the project team including the ones from the organization
|
||||
let req = test::TestRequest::get()
|
||||
.uri(&format!("/v3/project/{alpha_project_id}/members"))
|
||||
.append_pat(FRIEND_USER_PAT)
|
||||
.to_request();
|
||||
let resp = test_env.call(req).await;
|
||||
assert_eq!(resp.status(), 200);
|
||||
let value: serde_json::Value = test::read_body_json(resp).await;
|
||||
let members = value.as_array().unwrap();
|
||||
let members = test_env
|
||||
.api
|
||||
.get_project_members_deserialized_common(alpha_project_id, FRIEND_USER_PAT)
|
||||
.await;
|
||||
assert_eq!(members.len(), 2);
|
||||
})
|
||||
.await;
|
||||
@@ -218,7 +311,7 @@ async fn test_patch_project_team_member() {
|
||||
with_test_environment_all(None, |test_env| async move {
|
||||
let api = &test_env.api;
|
||||
|
||||
let alpha_team_id = &test_env.dummy.as_ref().unwrap().project_alpha.team_id;
|
||||
let alpha_team_id = &test_env.dummy.project_alpha.team_id;
|
||||
|
||||
// Edit team as admin/mod but not a part of the team should be OK
|
||||
let resp = api.edit_team_member(alpha_team_id, USER_USER_ID, json!({}), ADMIN_USER_PAT).await;
|
||||
@@ -286,117 +379,91 @@ async fn test_patch_project_team_member() {
|
||||
#[actix_rt::test]
|
||||
async fn test_patch_organization_team_member() {
|
||||
// Test setup and dummy data
|
||||
with_test_environment_all(None, |test_env| async move {
|
||||
let zeta_team_id = &test_env.dummy.as_ref().unwrap().organization_zeta.team_id;
|
||||
with_test_environment(None, |test_env: TestEnvironment<ApiV3>| async move {
|
||||
let zeta_team_id = &test_env.dummy.organization_zeta.team_id;
|
||||
|
||||
// Edit team as admin/mod but not a part of the team should be OK
|
||||
let req = test::TestRequest::patch()
|
||||
.uri(&format!("/v3/team/{zeta_team_id}/members/{USER_USER_ID}"))
|
||||
.set_json(json!({}))
|
||||
.append_pat(ADMIN_USER_PAT)
|
||||
.to_request();
|
||||
let resp = test_env.call(req).await;
|
||||
let resp = test_env
|
||||
.api
|
||||
.edit_team_member(zeta_team_id, USER_USER_ID, json!({}), ADMIN_USER_PAT)
|
||||
.await;
|
||||
assert_eq!(resp.status(), 204);
|
||||
|
||||
// As a non-owner with full permissions, attempt to edit the owner's permissions
|
||||
let req = test::TestRequest::patch()
|
||||
.uri(&format!("/v3/team/{zeta_team_id}/members/{USER_USER_ID}"))
|
||||
.append_pat(ADMIN_USER_PAT)
|
||||
.set_json(json!({
|
||||
"permissions": 0
|
||||
}))
|
||||
.to_request();
|
||||
let resp = test_env.call(req).await;
|
||||
let resp = test_env
|
||||
.api
|
||||
.edit_team_member(zeta_team_id, USER_USER_ID, json!({ "permissions": 0 }), ADMIN_USER_PAT)
|
||||
.await;
|
||||
assert_eq!(resp.status(), 400);
|
||||
|
||||
// Should not be able to add permissions to a user that the adding-user does not have
|
||||
// (true for both project and org)
|
||||
|
||||
// first, invite friend
|
||||
let req = test::TestRequest::post()
|
||||
.uri(&format!("/v3/team/{zeta_team_id}/members"))
|
||||
.append_pat(USER_USER_PAT)
|
||||
.set_json(json!({
|
||||
"user_id": FRIEND_USER_ID,
|
||||
"organization_permissions": (OrganizationPermissions::EDIT_MEMBER | OrganizationPermissions::EDIT_MEMBER_DEFAULT_PERMISSIONS).bits(),
|
||||
})).to_request();
|
||||
let resp = test_env.call(req).await;
|
||||
let resp = test_env
|
||||
.api
|
||||
.add_user_to_team(zeta_team_id, FRIEND_USER_ID, None, Some(OrganizationPermissions::EDIT_MEMBER | OrganizationPermissions::EDIT_MEMBER_DEFAULT_PERMISSIONS), USER_USER_PAT)
|
||||
.await;
|
||||
assert_eq!(resp.status(), 204);
|
||||
|
||||
// accept
|
||||
let req = test::TestRequest::post()
|
||||
.uri(&format!("/v3/team/{zeta_team_id}/join"))
|
||||
.append_pat(FRIEND_USER_PAT)
|
||||
.to_request();
|
||||
let resp = test_env.call(req).await;
|
||||
let resp = test_env.api.join_team(zeta_team_id, FRIEND_USER_PAT).await;
|
||||
assert_eq!(resp.status(), 204);
|
||||
|
||||
// try to add permissions- fails, as we do not have EDIT_DETAILS
|
||||
let req = test::TestRequest::patch()
|
||||
.uri(&format!("/v3/team/{zeta_team_id}/members/{FRIEND_USER_ID}"))
|
||||
.append_pat(FRIEND_USER_PAT)
|
||||
.set_json(json!({
|
||||
"organization_permissions": (OrganizationPermissions::EDIT_MEMBER | OrganizationPermissions::EDIT_DETAILS).bits()
|
||||
}))
|
||||
.to_request();
|
||||
let resp = test_env.call(req).await;
|
||||
|
||||
let resp = test_env
|
||||
.api
|
||||
.edit_team_member(zeta_team_id, FRIEND_USER_ID, json!({ "organization_permissions": (OrganizationPermissions::EDIT_MEMBER | OrganizationPermissions::EDIT_DETAILS).bits() }), FRIEND_USER_PAT)
|
||||
.await;
|
||||
assert_eq!(resp.status(), 400);
|
||||
|
||||
// Cannot set payouts outside of 0 and 5000
|
||||
for payout in [-1, 5001] {
|
||||
let req = test::TestRequest::patch()
|
||||
.uri(&format!("/v3/team/{zeta_team_id}/members/{FRIEND_USER_ID}"))
|
||||
.append_pat(USER_USER_PAT)
|
||||
.set_json(json!({
|
||||
"payouts_split": payout
|
||||
}))
|
||||
.to_request();
|
||||
let resp = test_env.call(req).await;
|
||||
let resp = test_env
|
||||
.api
|
||||
.edit_team_member(zeta_team_id, FRIEND_USER_ID, json!({ "payouts_split": payout }), USER_USER_PAT)
|
||||
.await;
|
||||
assert_eq!(resp.status(), 400);
|
||||
}
|
||||
|
||||
// Successful patch
|
||||
let req = test::TestRequest::patch()
|
||||
.uri(&format!("/v3/team/{zeta_team_id}/members/{FRIEND_USER_ID}"))
|
||||
.append_pat(FRIEND_USER_PAT)
|
||||
.set_json(json!({
|
||||
"payouts_split": 51,
|
||||
"organization_permissions": (OrganizationPermissions::EDIT_MEMBER).bits(), // reduces permissions
|
||||
"permissions": (ProjectPermissions::EDIT_MEMBER).bits(),
|
||||
"role": "very-cool-member",
|
||||
"ordering": 5
|
||||
}))
|
||||
.to_request();
|
||||
let resp = test_env.call(req).await;
|
||||
|
||||
let resp = test_env
|
||||
.api
|
||||
.edit_team_member(
|
||||
zeta_team_id,
|
||||
FRIEND_USER_ID,
|
||||
json!({
|
||||
"payouts_split": 51,
|
||||
"organization_permissions": OrganizationPermissions::EDIT_MEMBER.bits(), // reduces permissions
|
||||
"permissions": (ProjectPermissions::EDIT_MEMBER).bits(),
|
||||
"role": "very-cool-member",
|
||||
"ordering": 5
|
||||
}),
|
||||
FRIEND_USER_PAT,
|
||||
)
|
||||
.await;
|
||||
assert_eq!(resp.status(), 204);
|
||||
|
||||
// Check results
|
||||
let req = test::TestRequest::get()
|
||||
.uri(&format!("/v3/team/{zeta_team_id}/members"))
|
||||
.append_pat(FRIEND_USER_PAT)
|
||||
.to_request();
|
||||
let resp = test_env.call(req).await;
|
||||
assert_eq!(resp.status(), 200);
|
||||
let value: serde_json::Value = test::read_body_json(resp).await;
|
||||
let member = value
|
||||
.as_array()
|
||||
.unwrap()
|
||||
let members = test_env
|
||||
.api
|
||||
.get_team_members_deserialized(zeta_team_id, FRIEND_USER_PAT)
|
||||
.await;
|
||||
let member = members
|
||||
.iter()
|
||||
.find(|x| x["user"]["id"] == FRIEND_USER_ID)
|
||||
.find(|x| x.user.id.0 == FRIEND_USER_ID_PARSED as u64)
|
||||
.unwrap();
|
||||
assert_eq!(member["payouts_split"], 51.0);
|
||||
assert_eq!(member.payouts_split.unwrap(), Decimal::from_f64_retain(51.0_f64).unwrap());
|
||||
assert_eq!(
|
||||
member["organization_permissions"],
|
||||
OrganizationPermissions::EDIT_MEMBER.bits()
|
||||
member.organization_permissions,
|
||||
Some(OrganizationPermissions::EDIT_MEMBER)
|
||||
);
|
||||
assert_eq!(
|
||||
member["permissions"],
|
||||
ProjectPermissions::EDIT_MEMBER.bits()
|
||||
member.permissions,
|
||||
Some(ProjectPermissions::EDIT_MEMBER)
|
||||
);
|
||||
assert_eq!(member["role"], "very-cool-member");
|
||||
assert_eq!(member["ordering"], 5);
|
||||
assert_eq!(member.role, "very-cool-member");
|
||||
assert_eq!(member.ordering, 5);
|
||||
|
||||
}).await;
|
||||
}
|
||||
@@ -408,7 +475,7 @@ async fn transfer_ownership_v3() {
|
||||
with_test_environment(None, |test_env: TestEnvironment<ApiV3>| async move {
|
||||
let api = &test_env.api;
|
||||
|
||||
let alpha_team_id = &test_env.dummy.as_ref().unwrap().project_alpha.team_id;
|
||||
let alpha_team_id = &test_env.dummy.project_alpha.team_id;
|
||||
|
||||
// Cannot set friend as owner (not a member)
|
||||
let resp = api
|
||||
@@ -514,10 +581,10 @@ async fn transfer_ownership_v3() {
|
||||
// let test_env = TestEnvironment::build(None).await;
|
||||
// let api = &test_env.api;
|
||||
|
||||
// let alpha_team_id = &test_env.dummy.as_ref().unwrap().project_alpha.team_id;
|
||||
// let alpha_project_id = &test_env.dummy.as_ref().unwrap().project_alpha.project_id;
|
||||
// let zeta_organization_id = &test_env.dummy.as_ref().unwrap().zeta_organization_id;
|
||||
// let zeta_team_id = &test_env.dummy.as_ref().unwrap().zeta_team_id;
|
||||
// let alpha_team_id = &test_env.dummy.project_alpha.team_id;
|
||||
// let alpha_project_id = &test_env.dummy.project_alpha.project_id;
|
||||
// let zeta_organization_id = &test_env.dummy.zeta_organization_id;
|
||||
// let zeta_team_id = &test_env.dummy.zeta_team_id;
|
||||
|
||||
// // Link alpha team to zeta org
|
||||
// let resp = api.organization_add_project(zeta_organization_id, alpha_project_id, USER_USER_PAT).await;
|
||||
|
||||
@@ -59,8 +59,8 @@ pub async fn get_user_projects_after_deleting_project_shows_removal() {
|
||||
#[actix_rt::test]
|
||||
pub async fn get_user_projects_after_joining_team_shows_team_projects() {
|
||||
with_test_environment_all(None, |test_env| async move {
|
||||
let alpha_team_id = &test_env.dummy.as_ref().unwrap().project_alpha.team_id;
|
||||
let alpha_project_id = &test_env.dummy.as_ref().unwrap().project_alpha.project_id;
|
||||
let alpha_team_id = &test_env.dummy.project_alpha.team_id;
|
||||
let alpha_project_id = &test_env.dummy.project_alpha.project_id;
|
||||
let api = test_env.api;
|
||||
api.get_user_projects_deserialized_common(FRIEND_USER_ID, FRIEND_USER_PAT)
|
||||
.await;
|
||||
@@ -82,8 +82,8 @@ pub async fn get_user_projects_after_joining_team_shows_team_projects() {
|
||||
#[actix_rt::test]
|
||||
pub async fn get_user_projects_after_leaving_team_shows_no_team_projects() {
|
||||
with_test_environment_all(None, |test_env| async move {
|
||||
let alpha_team_id = &test_env.dummy.as_ref().unwrap().project_alpha.team_id;
|
||||
let alpha_project_id = &test_env.dummy.as_ref().unwrap().project_alpha.project_id;
|
||||
let alpha_team_id = &test_env.dummy.project_alpha.team_id;
|
||||
let alpha_project_id = &test_env.dummy.project_alpha.project_id;
|
||||
let api = test_env.api;
|
||||
api.add_user_to_team(alpha_team_id, FRIEND_USER_ID, None, None, USER_USER_PAT)
|
||||
.await;
|
||||
|
||||
@@ -8,13 +8,7 @@ use crate::common::{
|
||||
#[actix_rt::test]
|
||||
pub async fn get_user_notifications_after_team_invitation_returns_notification() {
|
||||
with_test_environment(None, |test_env: TestEnvironment<ApiV2>| async move {
|
||||
let alpha_team_id = test_env
|
||||
.dummy
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.project_alpha
|
||||
.team_id
|
||||
.clone();
|
||||
let alpha_team_id = test_env.dummy.project_alpha.team_id.clone();
|
||||
let api = test_env.api;
|
||||
api.add_user_to_team(&alpha_team_id, FRIEND_USER_ID, None, None, USER_USER_PAT)
|
||||
.await;
|
||||
|
||||
@@ -228,10 +228,10 @@ async fn test_add_remove_project() {
|
||||
#[actix_rt::test]
|
||||
async fn permissions_upload_version() {
|
||||
with_test_environment(None, |test_env: TestEnvironment<ApiV2>| async move {
|
||||
let alpha_project_id = &test_env.dummy.as_ref().unwrap().project_alpha.project_id;
|
||||
let alpha_version_id = &test_env.dummy.as_ref().unwrap().project_alpha.version_id;
|
||||
let alpha_team_id = &test_env.dummy.as_ref().unwrap().project_alpha.team_id;
|
||||
let alpha_file_hash = &test_env.dummy.as_ref().unwrap().project_alpha.file_hash;
|
||||
let alpha_project_id = &test_env.dummy.project_alpha.project_id;
|
||||
let alpha_version_id = &test_env.dummy.project_alpha.version_id;
|
||||
let alpha_team_id = &test_env.dummy.project_alpha.team_id;
|
||||
let alpha_file_hash = &test_env.dummy.project_alpha.file_hash;
|
||||
|
||||
let api = &test_env.api;
|
||||
let basic_mod_different_file = TestFile::BasicModDifferent;
|
||||
@@ -331,7 +331,7 @@ pub async fn test_patch_v2() {
|
||||
with_test_environment(None, |test_env: TestEnvironment<ApiV2>| async move {
|
||||
let api = &test_env.api;
|
||||
|
||||
let alpha_project_slug = &test_env.dummy.as_ref().unwrap().project_alpha.project_slug;
|
||||
let alpha_project_slug = &test_env.dummy.project_alpha.project_slug;
|
||||
|
||||
// Sucessful request to patch many fields.
|
||||
let resp = api
|
||||
@@ -437,8 +437,8 @@ async fn permissions_patch_project_v2() {
|
||||
pub async fn test_bulk_edit_links() {
|
||||
with_test_environment(None, |test_env: TestEnvironment<ApiV2>| async move {
|
||||
let api = &test_env.api;
|
||||
let alpha_project_id: &str = &test_env.dummy.as_ref().unwrap().project_alpha.project_id;
|
||||
let beta_project_id: &str = &test_env.dummy.as_ref().unwrap().project_beta.project_id;
|
||||
let alpha_project_id: &str = &test_env.dummy.project_alpha.project_id;
|
||||
let beta_project_id: &str = &test_env.dummy.project_beta.project_id;
|
||||
|
||||
let resp = api
|
||||
.edit_project_bulk(
|
||||
|
||||
@@ -1,29 +1,27 @@
|
||||
use crate::common::api_common::ApiProject;
|
||||
use crate::common::api_common::ApiVersion;
|
||||
use crate::common::api_v2::request_data::get_public_project_creation_data;
|
||||
use crate::common::api_v2::request_data::get_public_version_creation_data;
|
||||
use crate::common::api_v2::ApiV2;
|
||||
use crate::common::dummy_data::TestFile;
|
||||
use crate::common::environment::with_test_environment;
|
||||
use crate::common::environment::TestEnvironment;
|
||||
use crate::common::scopes::ScopeTest;
|
||||
use actix_web::test;
|
||||
use labrinth::models::ids::base62_impl::parse_base62;
|
||||
use labrinth::models::pats::Scopes;
|
||||
use labrinth::models::projects::ProjectId;
|
||||
use labrinth::util::actix::AppendsMultipart;
|
||||
|
||||
// Project version creation scopes
|
||||
#[actix_rt::test]
|
||||
pub async fn project_version_create_scopes() {
|
||||
with_test_environment(None, |test_env: TestEnvironment<ApiV2>| async move {
|
||||
let api = &test_env.api;
|
||||
// Create project
|
||||
let create_project = Scopes::PROJECT_CREATE;
|
||||
|
||||
let req_gen = || {
|
||||
let req_gen = |pat: Option<String>| async move {
|
||||
let creation_data =
|
||||
get_public_project_creation_data("demo", Some(TestFile::BasicMod), None);
|
||||
test::TestRequest::post()
|
||||
.uri("/v2/project")
|
||||
.set_multipart(creation_data.segment_data)
|
||||
api.create_project(creation_data, pat.as_deref()).await
|
||||
};
|
||||
let (_, success) = ScopeTest::new(&test_env)
|
||||
.test(req_gen, create_project)
|
||||
@@ -34,17 +32,16 @@ pub async fn project_version_create_scopes() {
|
||||
|
||||
// Add version to project
|
||||
let create_version = Scopes::VERSION_CREATE;
|
||||
let req_gen = || {
|
||||
let creation_data = get_public_version_creation_data(
|
||||
let req_gen = |pat: Option<String>| async move {
|
||||
api.add_public_version(
|
||||
project_id,
|
||||
"1.2.3.4",
|
||||
TestFile::BasicModDifferent,
|
||||
None,
|
||||
None,
|
||||
);
|
||||
test::TestRequest::post()
|
||||
.uri("/v2/version")
|
||||
.set_multipart(creation_data.segment_data)
|
||||
pat.as_deref(),
|
||||
)
|
||||
.await
|
||||
};
|
||||
ScopeTest::new(&test_env)
|
||||
.test(req_gen, create_version)
|
||||
|
||||
@@ -17,7 +17,7 @@ async fn transfer_ownership_v2() {
|
||||
with_test_environment(None, |test_env: TestEnvironment<ApiV2>| async move {
|
||||
let api = &test_env.api;
|
||||
|
||||
let alpha_team_id = &test_env.dummy.as_ref().unwrap().project_alpha.team_id;
|
||||
let alpha_team_id = &test_env.dummy.project_alpha.team_id;
|
||||
|
||||
// Cannot set friend as owner (not a member)
|
||||
let resp = api
|
||||
|
||||
@@ -9,6 +9,7 @@ use serde_json::json;
|
||||
|
||||
use crate::common::api_common::{ApiProject, ApiVersion};
|
||||
use crate::common::api_v2::ApiV2;
|
||||
use crate::common::dummy_data::{DummyProjectAlpha, DummyProjectBeta};
|
||||
use crate::common::environment::{with_test_environment, TestEnvironment};
|
||||
use crate::common::{
|
||||
database::{ENEMY_USER_PAT, USER_USER_PAT},
|
||||
@@ -20,7 +21,7 @@ pub async fn test_patch_version() {
|
||||
with_test_environment(None, |test_env: TestEnvironment<ApiV2>| async move {
|
||||
let api = &test_env.api;
|
||||
|
||||
let alpha_version_id = &test_env.dummy.as_ref().unwrap().project_alpha.version_id;
|
||||
let alpha_version_id = &test_env.dummy.project_alpha.version_id;
|
||||
|
||||
// // First, we do some patch requests that should fail.
|
||||
// // Failure because the user is not authorized.
|
||||
@@ -132,18 +133,18 @@ async fn version_updates() {
|
||||
// Test setup and dummy data
|
||||
with_test_environment(None, |test_env: TestEnvironment<ApiV2>| async move {
|
||||
let api = &test_env.api;
|
||||
|
||||
let alpha_project_id: &String = &test_env.dummy.as_ref().unwrap().project_alpha.project_id;
|
||||
let alpha_project_id_parsed = test_env
|
||||
.dummy
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.project_alpha
|
||||
.project_id_parsed;
|
||||
let alpha_version_id = &test_env.dummy.as_ref().unwrap().project_alpha.version_id;
|
||||
let beta_version_id = &test_env.dummy.as_ref().unwrap().project_beta.version_id;
|
||||
let alpha_version_hash = &test_env.dummy.as_ref().unwrap().project_alpha.file_hash;
|
||||
let beta_version_hash = &test_env.dummy.as_ref().unwrap().project_beta.file_hash;
|
||||
let DummyProjectAlpha {
|
||||
project_id: alpha_project_id,
|
||||
project_id_parsed: alpha_project_id_parsed,
|
||||
version_id: alpha_version_id,
|
||||
file_hash: alpha_version_hash,
|
||||
..
|
||||
} = &test_env.dummy.project_alpha;
|
||||
let DummyProjectBeta {
|
||||
version_id: beta_version_id,
|
||||
file_hash: beta_version_hash,
|
||||
..
|
||||
} = &test_env.dummy.project_beta;
|
||||
|
||||
// Quick test, using get version from hash
|
||||
let version = api
|
||||
@@ -224,7 +225,7 @@ async fn version_updates() {
|
||||
{
|
||||
let version = api
|
||||
.add_public_version_deserialized_common(
|
||||
alpha_project_id_parsed,
|
||||
*alpha_project_id_parsed,
|
||||
version_number,
|
||||
TestFile::build_random_jar(),
|
||||
None,
|
||||
|
||||
@@ -2,7 +2,7 @@ use std::collections::HashMap;
|
||||
|
||||
use crate::common::api_common::ApiVersion;
|
||||
use crate::common::database::*;
|
||||
use crate::common::dummy_data::TestFile;
|
||||
use crate::common::dummy_data::{DummyProjectAlpha, DummyProjectBeta, TestFile};
|
||||
use crate::common::{asserts::assert_status, get_json_val_str};
|
||||
use actix_http::StatusCode;
|
||||
use actix_web::test;
|
||||
@@ -27,9 +27,15 @@ async fn test_get_version() {
|
||||
// Test setup and dummy data
|
||||
with_test_environment_all(None, |test_env| async move {
|
||||
let api = &test_env.api;
|
||||
let alpha_project_id: &String = &test_env.dummy.as_ref().unwrap().project_alpha.project_id;
|
||||
let alpha_version_id = &test_env.dummy.as_ref().unwrap().project_alpha.version_id;
|
||||
let beta_version_id = &test_env.dummy.as_ref().unwrap().project_beta.version_id;
|
||||
let DummyProjectAlpha {
|
||||
project_id: alpha_project_id,
|
||||
version_id: alpha_version_id,
|
||||
..
|
||||
} = &test_env.dummy.project_alpha;
|
||||
let DummyProjectBeta {
|
||||
version_id: beta_version_id,
|
||||
..
|
||||
} = &test_env.dummy.project_beta;
|
||||
|
||||
// Perform request on dummy data
|
||||
let version = api
|
||||
@@ -82,19 +88,18 @@ async fn version_updates() {
|
||||
None,
|
||||
|test_env: common::environment::TestEnvironment<ApiV3>| async move {
|
||||
let api = &test_env.api;
|
||||
|
||||
let alpha_project_id: &String =
|
||||
&test_env.dummy.as_ref().unwrap().project_alpha.project_id;
|
||||
let alpha_project_id_parsed = test_env
|
||||
.dummy
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.project_alpha
|
||||
.project_id_parsed;
|
||||
let alpha_version_id = &test_env.dummy.as_ref().unwrap().project_alpha.version_id;
|
||||
let beta_version_id = &test_env.dummy.as_ref().unwrap().project_beta.version_id;
|
||||
let alpha_version_hash = &test_env.dummy.as_ref().unwrap().project_alpha.file_hash;
|
||||
let beta_version_hash = &test_env.dummy.as_ref().unwrap().project_beta.file_hash;
|
||||
let DummyProjectAlpha {
|
||||
project_id: alpha_project_id,
|
||||
project_id_parsed: alpha_project_id_parsed,
|
||||
version_id: alpha_version_id,
|
||||
file_hash: alpha_version_hash,
|
||||
..
|
||||
} = &test_env.dummy.project_alpha;
|
||||
let DummyProjectBeta {
|
||||
version_id: beta_version_id,
|
||||
file_hash: beta_version_hash,
|
||||
..
|
||||
} = &test_env.dummy.project_beta;
|
||||
|
||||
// Quick test, using get version from hash
|
||||
let version = api
|
||||
@@ -179,7 +184,7 @@ async fn version_updates() {
|
||||
{
|
||||
let version = api
|
||||
.add_public_version_deserialized(
|
||||
alpha_project_id_parsed,
|
||||
*alpha_project_id_parsed,
|
||||
version_number,
|
||||
TestFile::build_random_jar(),
|
||||
None,
|
||||
@@ -382,17 +387,15 @@ pub async fn test_patch_version() {
|
||||
with_test_environment_all(None, |test_env| async move {
|
||||
let api = &test_env.api;
|
||||
|
||||
let alpha_version_id = &test_env.dummy.as_ref().unwrap().project_alpha.version_id;
|
||||
let beta_project_id = &test_env.dummy.as_ref().unwrap().project_beta.project_id;
|
||||
let beta_project_id_parsed = &test_env
|
||||
.dummy
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.project_beta
|
||||
.project_id_parsed;
|
||||
let alpha_version_id = &test_env.dummy.project_alpha.version_id;
|
||||
let DummyProjectBeta {
|
||||
project_id: beta_project_id,
|
||||
project_id_parsed: beta_project_id_parsed,
|
||||
..
|
||||
} = &test_env.dummy.project_beta;
|
||||
|
||||
// // First, we do some patch requests that should fail.
|
||||
// // Failure because the user is not authorized.
|
||||
// First, we do some patch requests that should fail.
|
||||
// Failure because the user is not authorized.
|
||||
let resp = api
|
||||
.edit_version(
|
||||
alpha_version_id,
|
||||
@@ -510,8 +513,8 @@ pub async fn test_patch_version() {
|
||||
pub async fn test_project_versions() {
|
||||
with_test_environment_all(None, |test_env| async move {
|
||||
let api = &test_env.api;
|
||||
let alpha_project_id: &String = &test_env.dummy.as_ref().unwrap().project_alpha.project_id;
|
||||
let alpha_version_id = &test_env.dummy.as_ref().unwrap().project_alpha.version_id;
|
||||
let alpha_project_id: &String = &test_env.dummy.project_alpha.project_id;
|
||||
let alpha_version_id = &test_env.dummy.project_alpha.version_id;
|
||||
|
||||
let versions = api
|
||||
.get_project_versions_deserialized_common(
|
||||
@@ -534,7 +537,7 @@ pub async fn test_project_versions() {
|
||||
#[actix_rt::test]
|
||||
async fn can_create_version_with_ordering() {
|
||||
with_test_environment_all(None, |env| async move {
|
||||
let alpha_project_id_parsed = env.dummy.as_ref().unwrap().project_alpha.project_id_parsed;
|
||||
let alpha_project_id_parsed = env.dummy.project_alpha.project_id_parsed;
|
||||
|
||||
let new_version_id = get_json_val_str(
|
||||
env.api
|
||||
@@ -562,7 +565,7 @@ async fn can_create_version_with_ordering() {
|
||||
#[actix_rt::test]
|
||||
async fn edit_version_ordering_works() {
|
||||
with_test_environment_all(None, |env| async move {
|
||||
let alpha_version_id = env.dummy.as_ref().unwrap().project_alpha.version_id.clone();
|
||||
let alpha_version_id = env.dummy.project_alpha.version_id.clone();
|
||||
|
||||
let resp = env
|
||||
.api
|
||||
@@ -582,8 +585,8 @@ async fn edit_version_ordering_works() {
|
||||
#[actix_rt::test]
|
||||
async fn version_ordering_for_specified_orderings_orders_lower_order_first() {
|
||||
with_test_environment_all(None, |env| async move {
|
||||
let alpha_project_id_parsed = env.dummy.as_ref().unwrap().project_alpha.project_id_parsed;
|
||||
let alpha_version_id = env.dummy.as_ref().unwrap().project_alpha.version_id.clone();
|
||||
let alpha_project_id_parsed = env.dummy.project_alpha.project_id_parsed;
|
||||
let alpha_version_id = env.dummy.project_alpha.version_id.clone();
|
||||
let new_version_id = get_json_val_str(
|
||||
env.api
|
||||
.add_public_version_deserialized_common(
|
||||
@@ -616,8 +619,8 @@ async fn version_ordering_for_specified_orderings_orders_lower_order_first() {
|
||||
#[actix_rt::test]
|
||||
async fn version_ordering_when_unspecified_orders_oldest_first() {
|
||||
with_test_environment_all(None, |env| async move {
|
||||
let alpha_project_id_parsed = env.dummy.as_ref().unwrap().project_alpha.project_id_parsed;
|
||||
let alpha_version_id: String = env.dummy.as_ref().unwrap().project_alpha.version_id.clone();
|
||||
let alpha_project_id_parsed = env.dummy.project_alpha.project_id_parsed;
|
||||
let alpha_version_id: String = env.dummy.project_alpha.version_id.clone();
|
||||
let new_version_id = get_json_val_str(
|
||||
env.api
|
||||
.add_public_version_deserialized_common(
|
||||
@@ -647,8 +650,8 @@ async fn version_ordering_when_unspecified_orders_oldest_first() {
|
||||
#[actix_rt::test]
|
||||
async fn version_ordering_when_specified_orders_specified_before_unspecified() {
|
||||
with_test_environment_all(None, |env| async move {
|
||||
let alpha_project_id_parsed = env.dummy.as_ref().unwrap().project_alpha.project_id_parsed;
|
||||
let alpha_version_id = env.dummy.as_ref().unwrap().project_alpha.version_id.clone();
|
||||
let alpha_project_id_parsed = env.dummy.project_alpha.project_id_parsed;
|
||||
let alpha_version_id = env.dummy.project_alpha.version_id.clone();
|
||||
let new_version_id = get_json_val_str(
|
||||
env.api
|
||||
.add_public_version_deserialized_common(
|
||||
|
||||
Reference in New Issue
Block a user