You've already forked AstralRinth
forked from didirus/AstralRinth
Fixes failing tests (#813)
* fixes failing tests * fmt clippy * updated dockerfile * fixes failing tests; adds important fix from extracts_versions PR * assert_eq -> assert_status, giving better error messages * fixed random failure bug * fmt, clippy, etc
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
FROM rust:1.68.0 as build
|
FROM rust:1.75.0 as build
|
||||||
ENV PKG_CONFIG_ALLOW_CROSS=1
|
ENV PKG_CONFIG_ALLOW_CROSS=1
|
||||||
|
|
||||||
WORKDIR /usr/src/labrinth
|
WORKDIR /usr/src/labrinth
|
||||||
|
|||||||
@@ -47,8 +47,9 @@ impl FileHost for MockHost {
|
|||||||
) -> Result<DeleteFileData, FileHostingError> {
|
) -> Result<DeleteFileData, FileHostingError> {
|
||||||
let path = std::path::Path::new(&dotenvy::var("MOCK_FILE_PATH").unwrap())
|
let path = std::path::Path::new(&dotenvy::var("MOCK_FILE_PATH").unwrap())
|
||||||
.join(file_name.replace("../", ""));
|
.join(file_name.replace("../", ""));
|
||||||
std::fs::remove_file(path)?;
|
if path.exists() {
|
||||||
|
std::fs::remove_file(path)?;
|
||||||
|
}
|
||||||
Ok(DeleteFileData {
|
Ok(DeleteFileData {
|
||||||
file_id: file_id.to_string(),
|
file_id: file_id.to_string(),
|
||||||
file_name: file_name.to_string(),
|
file_name: file_name.to_string(),
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ pub struct LabrinthConfig {
|
|||||||
pub fn app_setup(
|
pub fn app_setup(
|
||||||
pool: sqlx::Pool<Postgres>,
|
pool: sqlx::Pool<Postgres>,
|
||||||
redis_pool: RedisPool,
|
redis_pool: RedisPool,
|
||||||
|
search_config: search::SearchConfig,
|
||||||
clickhouse: &mut Client,
|
clickhouse: &mut Client,
|
||||||
file_host: Arc<dyn file_hosting::FileHost + Send + Sync>,
|
file_host: Arc<dyn file_hosting::FileHost + Send + Sync>,
|
||||||
maxmind: Arc<queue::maxmind::MaxMindIndexer>,
|
maxmind: Arc<queue::maxmind::MaxMindIndexer>,
|
||||||
@@ -66,11 +67,6 @@ pub fn app_setup(
|
|||||||
dotenvy::var("BIND_ADDR").unwrap()
|
dotenvy::var("BIND_ADDR").unwrap()
|
||||||
);
|
);
|
||||||
|
|
||||||
let search_config = search::SearchConfig {
|
|
||||||
address: dotenvy::var("MEILISEARCH_ADDR").unwrap(),
|
|
||||||
key: dotenvy::var("MEILISEARCH_KEY").unwrap(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut scheduler = scheduler::Scheduler::new();
|
let mut scheduler = scheduler::Scheduler::new();
|
||||||
|
|
||||||
// The interval in seconds at which the local database is indexed
|
// The interval in seconds at which the local database is indexed
|
||||||
|
|||||||
@@ -6,10 +6,10 @@ use labrinth::file_hosting::S3Host;
|
|||||||
use labrinth::ratelimit::errors::ARError;
|
use labrinth::ratelimit::errors::ARError;
|
||||||
use labrinth::ratelimit::memory::{MemoryStore, MemoryStoreActor};
|
use labrinth::ratelimit::memory::{MemoryStore, MemoryStoreActor};
|
||||||
use labrinth::ratelimit::middleware::RateLimiter;
|
use labrinth::ratelimit::middleware::RateLimiter;
|
||||||
|
use labrinth::search;
|
||||||
use labrinth::util::env::parse_var;
|
use labrinth::util::env::parse_var;
|
||||||
use labrinth::{check_env_vars, clickhouse, database, file_hosting, queue};
|
use labrinth::{check_env_vars, clickhouse, database, file_hosting, queue};
|
||||||
use log::{error, info};
|
use log::{error, info};
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@@ -93,11 +93,13 @@ async fn main() -> std::io::Result<()> {
|
|||||||
.build()
|
.build()
|
||||||
.expect("Failed to create prometheus metrics middleware");
|
.expect("Failed to create prometheus metrics middleware");
|
||||||
|
|
||||||
|
let search_config = search::SearchConfig::new(None);
|
||||||
info!("Starting Actix HTTP server!");
|
info!("Starting Actix HTTP server!");
|
||||||
|
|
||||||
let labrinth_config = labrinth::app_setup(
|
let labrinth_config = labrinth::app_setup(
|
||||||
pool.clone(),
|
pool.clone(),
|
||||||
redis_pool.clone(),
|
redis_pool.clone(),
|
||||||
|
search_config.clone(),
|
||||||
&mut clickhouse,
|
&mut clickhouse,
|
||||||
file_host.clone(),
|
file_host.clone(),
|
||||||
maxmind_reader.clone(),
|
maxmind_reader.clone(),
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ pub struct Organization {
|
|||||||
pub id: OrganizationId,
|
pub id: OrganizationId,
|
||||||
/// The slug of the organization
|
/// The slug of the organization
|
||||||
pub slug: String,
|
pub slug: String,
|
||||||
/// The title (and slug) of the organization
|
/// The title of the organization
|
||||||
pub name: String,
|
pub name: String,
|
||||||
/// The associated team of the organization
|
/// The associated team of the organization
|
||||||
pub team_id: TeamId,
|
pub team_id: TeamId,
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ pub fn root_config(cfg: &mut web::ServiceConfig) {
|
|||||||
pub enum ApiError {
|
pub enum ApiError {
|
||||||
#[error("Environment Error")]
|
#[error("Environment Error")]
|
||||||
Env(#[from] dotenvy::Error),
|
Env(#[from] dotenvy::Error),
|
||||||
#[error("Error while uploading file")]
|
#[error("Error while uploading file: {0}")]
|
||||||
FileHosting(#[from] FileHostingError),
|
FileHosting(#[from] FileHostingError),
|
||||||
#[error("Database Error: {0}")]
|
#[error("Database Error: {0}")]
|
||||||
Database(#[from] crate::database::models::DatabaseError),
|
Database(#[from] crate::database::models::DatabaseError),
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use sqlx::PgPool;
|
|||||||
use validator::Validate;
|
use validator::Validate;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
auth::get_user_from_headers,
|
auth::{filter_visible_projects, get_user_from_headers},
|
||||||
database::{models::User, redis::RedisPool},
|
database::{models::User, redis::RedisPool},
|
||||||
file_hosting::FileHost,
|
file_hosting::FileHost,
|
||||||
models::{
|
models::{
|
||||||
@@ -65,23 +65,12 @@ pub async fn projects_list(
|
|||||||
let id_option = User::get(&info.into_inner().0, &**pool, &redis).await?;
|
let id_option = User::get(&info.into_inner().0, &**pool, &redis).await?;
|
||||||
|
|
||||||
if let Some(id) = id_option.map(|x| x.id) {
|
if let Some(id) = id_option.map(|x| x.id) {
|
||||||
let user_id: UserId = id.into();
|
|
||||||
|
|
||||||
let can_view_private = user
|
|
||||||
.map(|y| y.role.is_mod() || y.id == user_id)
|
|
||||||
.unwrap_or(false);
|
|
||||||
|
|
||||||
let project_data = User::get_projects(id, &**pool, &redis).await?;
|
let project_data = User::get_projects(id, &**pool, &redis).await?;
|
||||||
|
|
||||||
let response: Vec<_> =
|
let projects: Vec<_> =
|
||||||
crate::database::Project::get_many_ids(&project_data, &**pool, &redis)
|
crate::database::Project::get_many_ids(&project_data, &**pool, &redis).await?;
|
||||||
.await?
|
let projects = filter_visible_projects(projects, &user, &pool).await?;
|
||||||
.into_iter()
|
Ok(HttpResponse::Ok().json(projects))
|
||||||
.filter(|x| can_view_private || x.inner.status.is_searchable())
|
|
||||||
.map(Project::from)
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
Ok(HttpResponse::Ok().json(response))
|
|
||||||
} else {
|
} else {
|
||||||
Err(ApiError::NotFound)
|
Err(ApiError::NotFound)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -107,11 +107,12 @@ pub async fn get_indexes(
|
|||||||
config: &SearchConfig,
|
config: &SearchConfig,
|
||||||
) -> Result<Vec<Index>, meilisearch_sdk::errors::Error> {
|
) -> Result<Vec<Index>, meilisearch_sdk::errors::Error> {
|
||||||
let client = config.make_client();
|
let client = config.make_client();
|
||||||
|
let project_name = config.get_index_name("projects");
|
||||||
let projects_index = create_or_update_index(&client, "projects", None).await?;
|
let project_filtered_name = config.get_index_name("projects_filtered");
|
||||||
|
let projects_index = create_or_update_index(&client, &project_name, None).await?;
|
||||||
let projects_filtered_index = create_or_update_index(
|
let projects_filtered_index = create_or_update_index(
|
||||||
&client,
|
&client,
|
||||||
"projects_filtered",
|
&project_filtered_name,
|
||||||
Some(&[
|
Some(&[
|
||||||
"sort",
|
"sort",
|
||||||
"words",
|
"words",
|
||||||
@@ -128,7 +129,7 @@ pub async fn get_indexes(
|
|||||||
|
|
||||||
async fn create_or_update_index(
|
async fn create_or_update_index(
|
||||||
client: &Client,
|
client: &Client,
|
||||||
name: &'static str,
|
name: &str,
|
||||||
custom_rules: Option<&'static [&'static str]>,
|
custom_rules: Option<&'static [&'static str]>,
|
||||||
) -> Result<Index, meilisearch_sdk::errors::Error> {
|
) -> Result<Index, meilisearch_sdk::errors::Error> {
|
||||||
info!("Updating/creating index.");
|
info!("Updating/creating index.");
|
||||||
@@ -207,7 +208,6 @@ async fn create_or_update_index(
|
|||||||
typo_tolerance: None, // We don't use typo tolerance right now
|
typo_tolerance: None, // We don't use typo tolerance right now
|
||||||
dictionary: None, // We don't use dictionary right now
|
dictionary: None, // We don't use dictionary right now
|
||||||
};
|
};
|
||||||
|
|
||||||
if old_settings.synonyms != settings.synonyms
|
if old_settings.synonyms != settings.synonyms
|
||||||
|| old_settings.stop_words != settings.stop_words
|
|| old_settings.stop_words != settings.stop_words
|
||||||
|| old_settings.ranking_rules != settings.ranking_rules
|
|| old_settings.ranking_rules != settings.ranking_rules
|
||||||
@@ -294,16 +294,23 @@ async fn update_and_add_to_index(
|
|||||||
new_filterable_attributes.extend(additional_fields.iter().map(|s| s.to_string()));
|
new_filterable_attributes.extend(additional_fields.iter().map(|s| s.to_string()));
|
||||||
new_displayed_attributes.extend(additional_fields.iter().map(|s| s.to_string()));
|
new_displayed_attributes.extend(additional_fields.iter().map(|s| s.to_string()));
|
||||||
info!("add attributes.");
|
info!("add attributes.");
|
||||||
index
|
let filterable_task = index
|
||||||
.set_filterable_attributes(new_filterable_attributes)
|
.set_filterable_attributes(new_filterable_attributes)
|
||||||
.await?;
|
.await?;
|
||||||
index
|
let displayable_task = index
|
||||||
.set_displayed_attributes(new_displayed_attributes)
|
.set_displayed_attributes(new_displayed_attributes)
|
||||||
.await?;
|
.await?;
|
||||||
|
filterable_task
|
||||||
|
.wait_for_completion(client, None, Some(TIMEOUT))
|
||||||
|
.await?;
|
||||||
|
displayable_task
|
||||||
|
.wait_for_completion(client, None, Some(TIMEOUT))
|
||||||
|
.await?;
|
||||||
|
|
||||||
info!("Adding to index.");
|
info!("Adding to index.");
|
||||||
|
|
||||||
add_to_index(client, index, projects).await?;
|
add_to_index(client, index, projects).await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -315,7 +322,6 @@ pub async fn add_projects(
|
|||||||
) -> Result<(), IndexingError> {
|
) -> Result<(), IndexingError> {
|
||||||
let client = config.make_client();
|
let client = config.make_client();
|
||||||
for index in indices {
|
for index in indices {
|
||||||
info!("adding projects part1 or 2.");
|
|
||||||
update_and_add_to_index(&client, index, &projects, &additional_fields).await?;
|
update_and_add_to_index(&client, index, &projects, &additional_fields).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -329,7 +335,6 @@ fn default_settings() -> Settings {
|
|||||||
sorted_sortable.sort();
|
sorted_sortable.sort();
|
||||||
let mut sorted_attrs = DEFAULT_ATTRIBUTES_FOR_FACETING.to_vec();
|
let mut sorted_attrs = DEFAULT_ATTRIBUTES_FOR_FACETING.to_vec();
|
||||||
sorted_attrs.sort();
|
sorted_attrs.sort();
|
||||||
|
|
||||||
Settings::new()
|
Settings::new()
|
||||||
.with_distinct_attribute("project_id")
|
.with_distinct_attribute("project_id")
|
||||||
.with_displayed_attributes(sorted_display)
|
.with_displayed_attributes(sorted_display)
|
||||||
|
|||||||
@@ -59,16 +59,34 @@ impl actix_web::ResponseError for SearchError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct SearchConfig {
|
pub struct SearchConfig {
|
||||||
pub address: String,
|
pub address: String,
|
||||||
pub key: String,
|
pub key: String,
|
||||||
|
pub meta_namespace: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SearchConfig {
|
impl SearchConfig {
|
||||||
|
// Panics if the environment variables are not set,
|
||||||
|
// but these are already checked for on startup.
|
||||||
|
pub fn new(meta_namespace: Option<String>) -> Self {
|
||||||
|
let address = dotenvy::var("MEILISEARCH_ADDR").expect("MEILISEARCH_ADDR not set");
|
||||||
|
let key = dotenvy::var("MEILISEARCH_KEY").expect("MEILISEARCH_KEY not set");
|
||||||
|
|
||||||
|
Self {
|
||||||
|
address,
|
||||||
|
key,
|
||||||
|
meta_namespace: meta_namespace.unwrap_or_default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn make_client(&self) -> Client {
|
pub fn make_client(&self) -> Client {
|
||||||
Client::new(self.address.as_str(), Some(self.key.as_str()))
|
Client::new(self.address.as_str(), Some(self.key.as_str()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_index_name(&self, index: &str) -> String {
|
||||||
|
format!("{}_{}", self.meta_namespace, index)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A project document used for uploading projects to MeiliSearch's indices.
|
/// A project document used for uploading projects to MeiliSearch's indices.
|
||||||
@@ -172,13 +190,18 @@ pub struct ResultSearchProject {
|
|||||||
pub loader_fields: HashMap<String, Vec<serde_json::Value>>,
|
pub loader_fields: HashMap<String, Vec<serde_json::Value>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_sort_index(index: &str) -> Result<(&str, [&str; 1]), SearchError> {
|
pub fn get_sort_index(
|
||||||
|
config: &SearchConfig,
|
||||||
|
index: &str,
|
||||||
|
) -> Result<(String, [&'static str; 1]), SearchError> {
|
||||||
|
let projects_name = config.get_index_name("projects");
|
||||||
|
let projects_filtered_name = config.get_index_name("projects_filtered");
|
||||||
Ok(match index {
|
Ok(match index {
|
||||||
"relevance" => ("projects", ["downloads:desc"]),
|
"relevance" => (projects_name, ["downloads:desc"]),
|
||||||
"downloads" => ("projects_filtered", ["downloads:desc"]),
|
"downloads" => (projects_filtered_name, ["downloads:desc"]),
|
||||||
"follows" => ("projects", ["follows:desc"]),
|
"follows" => (projects_name, ["follows:desc"]),
|
||||||
"updated" => ("projects", ["date_modified:desc"]),
|
"updated" => (projects_name, ["date_modified:desc"]),
|
||||||
"newest" => ("projects", ["date_created:desc"]),
|
"newest" => (projects_name, ["date_created:desc"]),
|
||||||
i => return Err(SearchError::InvalidIndex(i.to_string())),
|
i => return Err(SearchError::InvalidIndex(i.to_string())),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -193,8 +216,7 @@ pub async fn search_for_project(
|
|||||||
let index = info.index.as_deref().unwrap_or("relevance");
|
let index = info.index.as_deref().unwrap_or("relevance");
|
||||||
let limit = info.limit.as_deref().unwrap_or("10").parse()?;
|
let limit = info.limit.as_deref().unwrap_or("10").parse()?;
|
||||||
|
|
||||||
let sort = get_sort_index(index)?;
|
let sort = get_sort_index(config, index)?;
|
||||||
|
|
||||||
let meilisearch_index = client.get_index(sort.0).await?;
|
let meilisearch_index = client.get_index(sort.0).await?;
|
||||||
|
|
||||||
let mut filter_string = String::new();
|
let mut filter_string = String::new();
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ impl ApiV2 {
|
|||||||
pat: Option<&str>,
|
pat: Option<&str>,
|
||||||
) -> LegacyProject {
|
) -> LegacyProject {
|
||||||
let resp = self.get_project(id_or_slug, pat).await;
|
let resp = self.get_project(id_or_slug, pat).await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
test::read_body_json(resp).await
|
test::read_body_json(resp).await
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ impl ApiV2 {
|
|||||||
pat: Option<&str>,
|
pat: Option<&str>,
|
||||||
) -> Vec<LegacyProject> {
|
) -> Vec<LegacyProject> {
|
||||||
let resp = self.get_user_projects(user_id_or_username, pat).await;
|
let resp = self.get_user_projects(user_id_or_username, pat).await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
test::read_body_json(resp).await
|
test::read_body_json(resp).await
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,8 +72,7 @@ impl ApiV2 {
|
|||||||
.append_pat(pat)
|
.append_pat(pat)
|
||||||
.to_request();
|
.to_request();
|
||||||
let resp = self.call(req).await;
|
let resp = self.call(req).await;
|
||||||
let status = resp.status();
|
assert_status(&resp, StatusCode::OK);
|
||||||
assert_eq!(status, 200);
|
|
||||||
test::read_body_json(resp).await
|
test::read_body_json(resp).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -164,7 +163,7 @@ impl ApiProject for ApiV2 {
|
|||||||
pat: Option<&str>,
|
pat: Option<&str>,
|
||||||
) -> CommonProject {
|
) -> CommonProject {
|
||||||
let resp = self.get_project(id_or_slug, pat).await;
|
let resp = self.get_project(id_or_slug, pat).await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
// First, deserialize to the non-common format (to test the response is valid for this api version)
|
// First, deserialize to the non-common format (to test the response is valid for this api version)
|
||||||
let project: LegacyProject = test::read_body_json(resp).await;
|
let project: LegacyProject = test::read_body_json(resp).await;
|
||||||
// Then, deserialize to the common format
|
// Then, deserialize to the common format
|
||||||
@@ -214,7 +213,7 @@ impl ApiProject for ApiV2 {
|
|||||||
pat: Option<&str>,
|
pat: Option<&str>,
|
||||||
) -> Vec<CommonProject> {
|
) -> Vec<CommonProject> {
|
||||||
let resp = self.get_user_projects(user_id_or_username, pat).await;
|
let resp = self.get_user_projects(user_id_or_username, pat).await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
// First, deserialize to the non-common format (to test the response is valid for this api version)
|
// First, deserialize to the non-common format (to test the response is valid for this api version)
|
||||||
let projects: Vec<LegacyProject> = test::read_body_json(resp).await;
|
let projects: Vec<LegacyProject> = test::read_body_json(resp).await;
|
||||||
// Then, deserialize to the common format
|
// Then, deserialize to the common format
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use actix_http::StatusCode;
|
||||||
use actix_web::{
|
use actix_web::{
|
||||||
dev::ServiceResponse,
|
dev::ServiceResponse,
|
||||||
test::{self, TestRequest},
|
test::{self, TestRequest},
|
||||||
@@ -12,6 +13,7 @@ use crate::common::{
|
|||||||
models::{CommonCategoryData, CommonLoaderData},
|
models::{CommonCategoryData, CommonLoaderData},
|
||||||
Api, ApiTags, AppendsOptionalPat,
|
Api, ApiTags, AppendsOptionalPat,
|
||||||
},
|
},
|
||||||
|
asserts::assert_status,
|
||||||
database::ADMIN_USER_PAT,
|
database::ADMIN_USER_PAT,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -30,7 +32,7 @@ impl ApiV2 {
|
|||||||
|
|
||||||
pub async fn get_side_types_deserialized(&self) -> Vec<String> {
|
pub async fn get_side_types_deserialized(&self) -> Vec<String> {
|
||||||
let resp = self.get_side_types().await;
|
let resp = self.get_side_types().await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
test::read_body_json(resp).await
|
test::read_body_json(resp).await
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,19 +46,19 @@ impl ApiV2 {
|
|||||||
|
|
||||||
pub async fn get_game_versions_deserialized(&self) -> Vec<GameVersionQueryData> {
|
pub async fn get_game_versions_deserialized(&self) -> Vec<GameVersionQueryData> {
|
||||||
let resp = self.get_game_versions().await;
|
let resp = self.get_game_versions().await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
test::read_body_json(resp).await
|
test::read_body_json(resp).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_loaders_deserialized(&self) -> Vec<LoaderData> {
|
pub async fn get_loaders_deserialized(&self) -> Vec<LoaderData> {
|
||||||
let resp = self.get_loaders().await;
|
let resp = self.get_loaders().await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
test::read_body_json(resp).await
|
test::read_body_json(resp).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_categories_deserialized(&self) -> Vec<CategoryData> {
|
pub async fn get_categories_deserialized(&self) -> Vec<CategoryData> {
|
||||||
let resp = self.get_categories().await;
|
let resp = self.get_categories().await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
test::read_body_json(resp).await
|
test::read_body_json(resp).await
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,8 +72,7 @@ impl ApiV2 {
|
|||||||
|
|
||||||
pub async fn get_donation_platforms_deserialized(&self) -> Vec<DonationPlatformQueryData> {
|
pub async fn get_donation_platforms_deserialized(&self) -> Vec<DonationPlatformQueryData> {
|
||||||
let resp = self.get_donation_platforms().await;
|
let resp = self.get_donation_platforms().await;
|
||||||
println!("Response: {:?}", resp.response().body());
|
assert_status(&resp, StatusCode::OK);
|
||||||
assert_eq!(resp.status(), 200);
|
|
||||||
test::read_body_json(resp).await
|
test::read_body_json(resp).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -88,7 +89,7 @@ impl ApiTags for ApiV2 {
|
|||||||
|
|
||||||
async fn get_loaders_deserialized_common(&self) -> Vec<CommonLoaderData> {
|
async fn get_loaders_deserialized_common(&self) -> Vec<CommonLoaderData> {
|
||||||
let resp = self.get_loaders().await;
|
let resp = self.get_loaders().await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
// First, deserialize to the non-common format (to test the response is valid for this api version)
|
// First, deserialize to the non-common format (to test the response is valid for this api version)
|
||||||
let v: Vec<LoaderData> = test::read_body_json(resp).await;
|
let v: Vec<LoaderData> = test::read_body_json(resp).await;
|
||||||
// Then, deserialize to the common format
|
// Then, deserialize to the common format
|
||||||
@@ -106,7 +107,7 @@ impl ApiTags for ApiV2 {
|
|||||||
|
|
||||||
async fn get_categories_deserialized_common(&self) -> Vec<CommonCategoryData> {
|
async fn get_categories_deserialized_common(&self) -> Vec<CommonCategoryData> {
|
||||||
let resp = self.get_categories().await;
|
let resp = self.get_categories().await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
// First, deserialize to the non-common format (to test the response is valid for this api version)
|
// First, deserialize to the non-common format (to test the response is valid for this api version)
|
||||||
let v: Vec<CategoryData> = test::read_body_json(resp).await;
|
let v: Vec<CategoryData> = test::read_body_json(resp).await;
|
||||||
// Then, deserialize to the common format
|
// Then, deserialize to the common format
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ impl ApiV2 {
|
|||||||
pat: Option<&str>,
|
pat: Option<&str>,
|
||||||
) -> Vec<LegacyTeamMember> {
|
) -> Vec<LegacyTeamMember> {
|
||||||
let resp = self.get_organization_members(id_or_title, pat).await;
|
let resp = self.get_organization_members(id_or_title, pat).await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
test::read_body_json(resp).await
|
test::read_body_json(resp).await
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,7 +34,7 @@ impl ApiV2 {
|
|||||||
pat: Option<&str>,
|
pat: Option<&str>,
|
||||||
) -> Vec<LegacyTeamMember> {
|
) -> Vec<LegacyTeamMember> {
|
||||||
let resp = self.get_team_members(team_id, pat).await;
|
let resp = self.get_team_members(team_id, pat).await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
test::read_body_json(resp).await
|
test::read_body_json(resp).await
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,7 +44,7 @@ impl ApiV2 {
|
|||||||
pat: Option<&str>,
|
pat: Option<&str>,
|
||||||
) -> Vec<LegacyNotification> {
|
) -> Vec<LegacyNotification> {
|
||||||
let resp = self.get_user_notifications(user_id, pat).await;
|
let resp = self.get_user_notifications(user_id, pat).await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
test::read_body_json(resp).await
|
test::read_body_json(resp).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -65,7 +65,7 @@ impl ApiTeams for ApiV2 {
|
|||||||
pat: Option<&str>,
|
pat: Option<&str>,
|
||||||
) -> Vec<CommonTeamMember> {
|
) -> Vec<CommonTeamMember> {
|
||||||
let resp = self.get_team_members(id_or_title, pat).await;
|
let resp = self.get_team_members(id_or_title, pat).await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
// TODO: Note, this does NOT deserialize to any other struct first, as currently TeamMember is the same in v2 and v3.
|
// TODO: Note, this does NOT deserialize to any other struct first, as currently TeamMember is the same in v2 and v3.
|
||||||
// CommonTeamMember = TeamMember (v3)
|
// CommonTeamMember = TeamMember (v3)
|
||||||
// This may yet change, so we should keep common struct.
|
// This may yet change, so we should keep common struct.
|
||||||
@@ -102,7 +102,7 @@ impl ApiTeams for ApiV2 {
|
|||||||
pat: Option<&str>,
|
pat: Option<&str>,
|
||||||
) -> Vec<CommonTeamMember> {
|
) -> Vec<CommonTeamMember> {
|
||||||
let resp = self.get_project_members(id_or_title, pat).await;
|
let resp = self.get_project_members(id_or_title, pat).await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
// TODO: Note, this does NOT deserialize to any other struct first, as currently TeamMember is the same in v2 and v3.
|
// TODO: Note, this does NOT deserialize to any other struct first, as currently TeamMember is the same in v2 and v3.
|
||||||
// CommonTeamMember = TeamMember (v3)
|
// CommonTeamMember = TeamMember (v3)
|
||||||
// This may yet change, so we should keep common struct.
|
// This may yet change, so we should keep common struct.
|
||||||
@@ -127,7 +127,7 @@ impl ApiTeams for ApiV2 {
|
|||||||
pat: Option<&str>,
|
pat: Option<&str>,
|
||||||
) -> Vec<CommonTeamMember> {
|
) -> Vec<CommonTeamMember> {
|
||||||
let resp = self.get_organization_members(id_or_title, pat).await;
|
let resp = self.get_organization_members(id_or_title, pat).await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
// TODO: Note, this does NOT deserialize to any other struct first, as currently TeamMember is the same in v2 and v3.
|
// TODO: Note, this does NOT deserialize to any other struct first, as currently TeamMember is the same in v2 and v3.
|
||||||
// CommonTeamMember = TeamMember (v3)
|
// CommonTeamMember = TeamMember (v3)
|
||||||
// This may yet change, so we should keep common struct.
|
// This may yet change, so we should keep common struct.
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ pub fn url_encode_json_serialized_vec(elements: &[String]) -> String {
|
|||||||
impl ApiV2 {
|
impl ApiV2 {
|
||||||
pub async fn get_version_deserialized(&self, id: &str, pat: Option<&str>) -> LegacyVersion {
|
pub async fn get_version_deserialized(&self, id: &str, pat: Option<&str>) -> LegacyVersion {
|
||||||
let resp = self.get_version(id, pat).await;
|
let resp = self.get_version(id, pat).await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
test::read_body_json(resp).await
|
test::read_body_json(resp).await
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,7 +44,7 @@ impl ApiV2 {
|
|||||||
pat: Option<&str>,
|
pat: Option<&str>,
|
||||||
) -> LegacyVersion {
|
) -> LegacyVersion {
|
||||||
let resp = self.get_version_from_hash(hash, algorithm, pat).await;
|
let resp = self.get_version_from_hash(hash, algorithm, pat).await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
test::read_body_json(resp).await
|
test::read_body_json(resp).await
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,7 +55,7 @@ impl ApiV2 {
|
|||||||
pat: Option<&str>,
|
pat: Option<&str>,
|
||||||
) -> HashMap<String, LegacyVersion> {
|
) -> HashMap<String, LegacyVersion> {
|
||||||
let resp = self.get_versions_from_hashes(hashes, algorithm, pat).await;
|
let resp = self.get_versions_from_hashes(hashes, algorithm, pat).await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
test::read_body_json(resp).await
|
test::read_body_json(resp).await
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,7 +83,7 @@ impl ApiV2 {
|
|||||||
pat: Option<&str>,
|
pat: Option<&str>,
|
||||||
) -> HashMap<String, LegacyVersion> {
|
) -> HashMap<String, LegacyVersion> {
|
||||||
let resp = self.update_individual_files(algorithm, hashes, pat).await;
|
let resp = self.update_individual_files(algorithm, hashes, pat).await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
test::read_body_json(resp).await
|
test::read_body_json(resp).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -135,7 +135,7 @@ impl ApiVersion for ApiV2 {
|
|||||||
pat,
|
pat,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
// First, deserialize to the non-common format (to test the response is valid for this api version)
|
// First, deserialize to the non-common format (to test the response is valid for this api version)
|
||||||
let v: LegacyVersion = test::read_body_json(resp).await;
|
let v: LegacyVersion = test::read_body_json(resp).await;
|
||||||
// Then, deserialize to the common format
|
// Then, deserialize to the common format
|
||||||
@@ -153,7 +153,7 @@ impl ApiVersion for ApiV2 {
|
|||||||
|
|
||||||
async fn get_version_deserialized_common(&self, id: &str, pat: Option<&str>) -> CommonVersion {
|
async fn get_version_deserialized_common(&self, id: &str, pat: Option<&str>) -> CommonVersion {
|
||||||
let resp = self.get_version(id, pat).await;
|
let resp = self.get_version(id, pat).await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
// First, deserialize to the non-common format (to test the response is valid for this api version)
|
// First, deserialize to the non-common format (to test the response is valid for this api version)
|
||||||
let v: LegacyVersion = test::read_body_json(resp).await;
|
let v: LegacyVersion = test::read_body_json(resp).await;
|
||||||
// Then, deserialize to the common format
|
// Then, deserialize to the common format
|
||||||
@@ -212,7 +212,7 @@ impl ApiVersion for ApiV2 {
|
|||||||
pat: Option<&str>,
|
pat: Option<&str>,
|
||||||
) -> CommonVersion {
|
) -> CommonVersion {
|
||||||
let resp = self.get_version_from_hash(hash, algorithm, pat).await;
|
let resp = self.get_version_from_hash(hash, algorithm, pat).await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
// First, deserialize to the non-common format (to test the response is valid for this api version)
|
// First, deserialize to the non-common format (to test the response is valid for this api version)
|
||||||
let v: LegacyVersion = test::read_body_json(resp).await;
|
let v: LegacyVersion = test::read_body_json(resp).await;
|
||||||
// Then, deserialize to the common format
|
// Then, deserialize to the common format
|
||||||
@@ -244,7 +244,7 @@ impl ApiVersion for ApiV2 {
|
|||||||
pat: Option<&str>,
|
pat: Option<&str>,
|
||||||
) -> HashMap<String, CommonVersion> {
|
) -> HashMap<String, CommonVersion> {
|
||||||
let resp = self.get_versions_from_hashes(hashes, algorithm, pat).await;
|
let resp = self.get_versions_from_hashes(hashes, algorithm, pat).await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
// First, deserialize to the non-common format (to test the response is valid for this api version)
|
// First, deserialize to the non-common format (to test the response is valid for this api version)
|
||||||
let v: HashMap<String, LegacyVersion> = test::read_body_json(resp).await;
|
let v: HashMap<String, LegacyVersion> = test::read_body_json(resp).await;
|
||||||
// Then, deserialize to the common format
|
// Then, deserialize to the common format
|
||||||
@@ -287,7 +287,7 @@ impl ApiVersion for ApiV2 {
|
|||||||
let resp = self
|
let resp = self
|
||||||
.get_update_from_hash(hash, algorithm, loaders, game_versions, version_types, pat)
|
.get_update_from_hash(hash, algorithm, loaders, game_versions, version_types, pat)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
// First, deserialize to the non-common format (to test the response is valid for this api version)
|
// First, deserialize to the non-common format (to test the response is valid for this api version)
|
||||||
let v: LegacyVersion = test::read_body_json(resp).await;
|
let v: LegacyVersion = test::read_body_json(resp).await;
|
||||||
// Then, deserialize to the common format
|
// Then, deserialize to the common format
|
||||||
@@ -337,7 +337,7 @@ impl ApiVersion for ApiV2 {
|
|||||||
pat,
|
pat,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
// First, deserialize to the non-common format (to test the response is valid for this api version)
|
// First, deserialize to the non-common format (to test the response is valid for this api version)
|
||||||
let v: HashMap<String, LegacyVersion> = test::read_body_json(resp).await;
|
let v: HashMap<String, LegacyVersion> = test::read_body_json(resp).await;
|
||||||
// Then, deserialize to the common format
|
// Then, deserialize to the common format
|
||||||
@@ -420,7 +420,7 @@ impl ApiVersion for ApiV2 {
|
|||||||
pat,
|
pat,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
// First, deserialize to the non-common format (to test the response is valid for this api version)
|
// First, deserialize to the non-common format (to test the response is valid for this api version)
|
||||||
let v: Vec<LegacyVersion> = test::read_body_json(resp).await;
|
let v: Vec<LegacyVersion> = test::read_body_json(resp).await;
|
||||||
// Then, deserialize to the common format
|
// Then, deserialize to the common format
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use actix_http::StatusCode;
|
||||||
use actix_web::{
|
use actix_web::{
|
||||||
dev::ServiceResponse,
|
dev::ServiceResponse,
|
||||||
test::{self, TestRequest},
|
test::{self, TestRequest},
|
||||||
@@ -6,7 +7,10 @@ use bytes::Bytes;
|
|||||||
use labrinth::models::{collections::Collection, v3::projects::Project};
|
use labrinth::models::{collections::Collection, v3::projects::Project};
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
|
|
||||||
use crate::common::api_common::{request_data::ImageData, Api, AppendsOptionalPat};
|
use crate::common::{
|
||||||
|
api_common::{request_data::ImageData, Api, AppendsOptionalPat},
|
||||||
|
asserts::assert_status,
|
||||||
|
};
|
||||||
|
|
||||||
use super::ApiV3;
|
use super::ApiV3;
|
||||||
|
|
||||||
@@ -40,7 +44,7 @@ impl ApiV3 {
|
|||||||
|
|
||||||
pub async fn get_collection_deserialized(&self, id: &str, pat: Option<&str>) -> Collection {
|
pub async fn get_collection_deserialized(&self, id: &str, pat: Option<&str>) -> Collection {
|
||||||
let resp = self.get_collection(id, pat).await;
|
let resp = self.get_collection(id, pat).await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
test::read_body_json(resp).await
|
test::read_body_json(resp).await
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,7 +74,7 @@ impl ApiV3 {
|
|||||||
pat: Option<&str>,
|
pat: Option<&str>,
|
||||||
) -> Vec<Project> {
|
) -> Vec<Project> {
|
||||||
let resp = self.get_collection_projects(id, pat).await;
|
let resp = self.get_collection_projects(id, pat).await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
test::read_body_json(resp).await
|
test::read_body_json(resp).await
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,7 +149,7 @@ impl ApiV3 {
|
|||||||
pat: Option<&str>,
|
pat: Option<&str>,
|
||||||
) -> Vec<Collection> {
|
) -> Vec<Collection> {
|
||||||
let resp = self.get_user_collections(user_id_or_username, pat).await;
|
let resp = self.get_user_collections(user_id_or_username, pat).await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
// First, deserialize to the non-common format (to test the response is valid for this api version)
|
// 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;
|
let projects: Vec<Project> = test::read_body_json(resp).await;
|
||||||
// Then, deserialize to the common format
|
// Then, deserialize to the common format
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use actix_http::StatusCode;
|
||||||
use actix_web::{
|
use actix_web::{
|
||||||
dev::ServiceResponse,
|
dev::ServiceResponse,
|
||||||
test::{self, TestRequest},
|
test::{self, TestRequest},
|
||||||
@@ -6,7 +7,10 @@ use bytes::Bytes;
|
|||||||
use labrinth::models::{organizations::Organization, users::UserId, v3::projects::Project};
|
use labrinth::models::{organizations::Organization, users::UserId, v3::projects::Project};
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
|
|
||||||
use crate::common::api_common::{request_data::ImageData, Api, AppendsOptionalPat};
|
use crate::common::{
|
||||||
|
api_common::{request_data::ImageData, Api, AppendsOptionalPat},
|
||||||
|
asserts::assert_status,
|
||||||
|
};
|
||||||
|
|
||||||
use super::ApiV3;
|
use super::ApiV3;
|
||||||
|
|
||||||
@@ -14,6 +18,7 @@ impl ApiV3 {
|
|||||||
pub async fn create_organization(
|
pub async fn create_organization(
|
||||||
&self,
|
&self,
|
||||||
organization_title: &str,
|
organization_title: &str,
|
||||||
|
organization_slug: &str,
|
||||||
description: &str,
|
description: &str,
|
||||||
pat: Option<&str>,
|
pat: Option<&str>,
|
||||||
) -> ServiceResponse {
|
) -> ServiceResponse {
|
||||||
@@ -22,6 +27,7 @@ impl ApiV3 {
|
|||||||
.append_pat(pat)
|
.append_pat(pat)
|
||||||
.set_json(json!({
|
.set_json(json!({
|
||||||
"name": organization_title,
|
"name": organization_title,
|
||||||
|
"slug": organization_slug,
|
||||||
"description": description,
|
"description": description,
|
||||||
}))
|
}))
|
||||||
.to_request();
|
.to_request();
|
||||||
@@ -42,7 +48,7 @@ impl ApiV3 {
|
|||||||
pat: Option<&str>,
|
pat: Option<&str>,
|
||||||
) -> Organization {
|
) -> Organization {
|
||||||
let resp = self.get_organization(id_or_title, pat).await;
|
let resp = self.get_organization(id_or_title, pat).await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
test::read_body_json(resp).await
|
test::read_body_json(resp).await
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,7 +86,7 @@ impl ApiV3 {
|
|||||||
pat: Option<&str>,
|
pat: Option<&str>,
|
||||||
) -> Vec<Project> {
|
) -> Vec<Project> {
|
||||||
let resp = self.get_organization_projects(id_or_title, pat).await;
|
let resp = self.get_organization_projects(id_or_title, pat).await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
test::read_body_json(resp).await
|
test::read_body_json(resp).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ impl ApiProject for ApiV3 {
|
|||||||
pat: Option<&str>,
|
pat: Option<&str>,
|
||||||
) -> CommonProject {
|
) -> CommonProject {
|
||||||
let resp = self.get_project(id_or_slug, pat).await;
|
let resp = self.get_project(id_or_slug, pat).await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
// First, deserialize to the non-common format (to test the response is valid for this api version)
|
// First, deserialize to the non-common format (to test the response is valid for this api version)
|
||||||
let project: Project = test::read_body_json(resp).await;
|
let project: Project = test::read_body_json(resp).await;
|
||||||
// Then, deserialize to the common format
|
// Then, deserialize to the common format
|
||||||
@@ -169,7 +169,7 @@ impl ApiProject for ApiV3 {
|
|||||||
pat: Option<&str>,
|
pat: Option<&str>,
|
||||||
) -> Vec<CommonProject> {
|
) -> Vec<CommonProject> {
|
||||||
let resp = self.get_user_projects(user_id_or_username, pat).await;
|
let resp = self.get_user_projects(user_id_or_username, pat).await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
// First, deserialize to the non-common format (to test the response is valid for this api version)
|
// 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;
|
let projects: Vec<Project> = test::read_body_json(resp).await;
|
||||||
// Then, deserialize to the common format
|
// Then, deserialize to the common format
|
||||||
@@ -383,10 +383,7 @@ impl ApiProject for ApiV3 {
|
|||||||
.append_pat(pat)
|
.append_pat(pat)
|
||||||
.to_request();
|
.to_request();
|
||||||
|
|
||||||
let t = self.call(req).await;
|
self.call(req).await
|
||||||
println!("Status: {}", t.status());
|
|
||||||
println!("respone Body: {:?}", t.response().body());
|
|
||||||
t
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn remove_gallery_item(
|
async fn remove_gallery_item(
|
||||||
@@ -480,7 +477,7 @@ impl ApiProject for ApiV3 {
|
|||||||
impl ApiV3 {
|
impl ApiV3 {
|
||||||
pub async fn get_project_deserialized(&self, id_or_slug: &str, pat: Option<&str>) -> Project {
|
pub async fn get_project_deserialized(&self, id_or_slug: &str, pat: Option<&str>) -> Project {
|
||||||
let resp = self.get_project(id_or_slug, pat).await;
|
let resp = self.get_project(id_or_slug, pat).await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
test::read_body_json(resp).await
|
test::read_body_json(resp).await
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -503,7 +500,7 @@ impl ApiV3 {
|
|||||||
pat: Option<&str>,
|
pat: Option<&str>,
|
||||||
) -> Organization {
|
) -> Organization {
|
||||||
let resp = self.get_project_organization(id_or_slug, pat).await;
|
let resp = self.get_project_organization(id_or_slug, pat).await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
test::read_body_json(resp).await
|
test::read_body_json(resp).await
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -530,8 +527,7 @@ impl ApiV3 {
|
|||||||
.append_pat(pat)
|
.append_pat(pat)
|
||||||
.to_request();
|
.to_request();
|
||||||
let resp = self.call(req).await;
|
let resp = self.call(req).await;
|
||||||
let status = resp.status();
|
assert_status(&resp, StatusCode::OK);
|
||||||
assert_eq!(status, 200);
|
|
||||||
test::read_body_json(resp).await
|
test::read_body_json(resp).await
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -598,7 +594,7 @@ impl ApiV3 {
|
|||||||
pat,
|
pat,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
test::read_body_json(resp).await
|
test::read_body_json(resp).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use actix_http::StatusCode;
|
||||||
use actix_web::{
|
use actix_web::{
|
||||||
dev::ServiceResponse,
|
dev::ServiceResponse,
|
||||||
test::{self, TestRequest},
|
test::{self, TestRequest},
|
||||||
@@ -13,6 +14,7 @@ use crate::common::{
|
|||||||
models::{CommonCategoryData, CommonLoaderData},
|
models::{CommonCategoryData, CommonLoaderData},
|
||||||
Api, ApiTags, AppendsOptionalPat,
|
Api, ApiTags, AppendsOptionalPat,
|
||||||
},
|
},
|
||||||
|
asserts::assert_status,
|
||||||
database::ADMIN_USER_PAT,
|
database::ADMIN_USER_PAT,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -30,7 +32,7 @@ impl ApiTags for ApiV3 {
|
|||||||
|
|
||||||
async fn get_loaders_deserialized_common(&self) -> Vec<CommonLoaderData> {
|
async fn get_loaders_deserialized_common(&self) -> Vec<CommonLoaderData> {
|
||||||
let resp = self.get_loaders().await;
|
let resp = self.get_loaders().await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
// First, deserialize to the non-common format (to test the response is valid for this api version)
|
// First, deserialize to the non-common format (to test the response is valid for this api version)
|
||||||
let v: Vec<LoaderData> = test::read_body_json(resp).await;
|
let v: Vec<LoaderData> = test::read_body_json(resp).await;
|
||||||
// Then, deserialize to the common format
|
// Then, deserialize to the common format
|
||||||
@@ -48,7 +50,7 @@ impl ApiTags for ApiV3 {
|
|||||||
|
|
||||||
async fn get_categories_deserialized_common(&self) -> Vec<CommonCategoryData> {
|
async fn get_categories_deserialized_common(&self) -> Vec<CommonCategoryData> {
|
||||||
let resp = self.get_categories().await;
|
let resp = self.get_categories().await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
// First, deserialize to the non-common format (to test the response is valid for this api version)
|
// First, deserialize to the non-common format (to test the response is valid for this api version)
|
||||||
let v: Vec<CategoryData> = test::read_body_json(resp).await;
|
let v: Vec<CategoryData> = test::read_body_json(resp).await;
|
||||||
// Then, deserialize to the common format
|
// Then, deserialize to the common format
|
||||||
@@ -60,7 +62,7 @@ impl ApiTags for ApiV3 {
|
|||||||
impl ApiV3 {
|
impl ApiV3 {
|
||||||
pub async fn get_loaders_deserialized(&self) -> Vec<LoaderData> {
|
pub async fn get_loaders_deserialized(&self) -> Vec<LoaderData> {
|
||||||
let resp = self.get_loaders().await;
|
let resp = self.get_loaders().await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
test::read_body_json(resp).await
|
test::read_body_json(resp).await
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,7 +79,7 @@ impl ApiV3 {
|
|||||||
loader_field: &str,
|
loader_field: &str,
|
||||||
) -> Vec<LoaderFieldEnumValue> {
|
) -> Vec<LoaderFieldEnumValue> {
|
||||||
let resp = self.get_loader_field_variants(loader_field).await;
|
let resp = self.get_loader_field_variants(loader_field).await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
test::read_body_json(resp).await
|
test::read_body_json(resp).await
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,7 +94,7 @@ impl ApiV3 {
|
|||||||
|
|
||||||
pub async fn get_games_deserialized(&self) -> Vec<GameData> {
|
pub async fn get_games_deserialized(&self) -> Vec<GameData> {
|
||||||
let resp = self.get_games().await;
|
let resp = self.get_games().await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
test::read_body_json(resp).await
|
test::read_body_json(resp).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ impl ApiV3 {
|
|||||||
pat: Option<&str>,
|
pat: Option<&str>,
|
||||||
) -> Vec<TeamMember> {
|
) -> Vec<TeamMember> {
|
||||||
let resp = self.get_organization_members(id_or_title, pat).await;
|
let resp = self.get_organization_members(id_or_title, pat).await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
test::read_body_json(resp).await
|
test::read_body_json(resp).await
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,7 +34,7 @@ impl ApiV3 {
|
|||||||
pat: Option<&str>,
|
pat: Option<&str>,
|
||||||
) -> Vec<TeamMember> {
|
) -> Vec<TeamMember> {
|
||||||
let resp = self.get_team_members(team_id, pat).await;
|
let resp = self.get_team_members(team_id, pat).await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
test::read_body_json(resp).await
|
test::read_body_json(resp).await
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,7 +44,7 @@ impl ApiV3 {
|
|||||||
pat: Option<&str>,
|
pat: Option<&str>,
|
||||||
) -> Vec<TeamMember> {
|
) -> Vec<TeamMember> {
|
||||||
let resp = self.get_project_members(project_id, pat).await;
|
let resp = self.get_project_members(project_id, pat).await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
test::read_body_json(resp).await
|
test::read_body_json(resp).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -65,7 +65,7 @@ impl ApiTeams for ApiV3 {
|
|||||||
pat: Option<&str>,
|
pat: Option<&str>,
|
||||||
) -> Vec<CommonTeamMember> {
|
) -> Vec<CommonTeamMember> {
|
||||||
let resp = self.get_team_members(id_or_title, pat).await;
|
let resp = self.get_team_members(id_or_title, pat).await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
// First, deserialize to the non-common format (to test the response is valid for this api version)
|
// First, deserialize to the non-common format (to test the response is valid for this api version)
|
||||||
let v: Vec<TeamMember> = test::read_body_json(resp).await;
|
let v: Vec<TeamMember> = test::read_body_json(resp).await;
|
||||||
// Then, deserialize to the common format
|
// Then, deserialize to the common format
|
||||||
@@ -103,7 +103,7 @@ impl ApiTeams for ApiV3 {
|
|||||||
pat: Option<&str>,
|
pat: Option<&str>,
|
||||||
) -> Vec<CommonTeamMember> {
|
) -> Vec<CommonTeamMember> {
|
||||||
let resp = self.get_project_members(id_or_title, pat).await;
|
let resp = self.get_project_members(id_or_title, pat).await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
// First, deserialize to the non-common format (to test the response is valid for this api version)
|
// First, deserialize to the non-common format (to test the response is valid for this api version)
|
||||||
let v: Vec<TeamMember> = test::read_body_json(resp).await;
|
let v: Vec<TeamMember> = test::read_body_json(resp).await;
|
||||||
// Then, deserialize to the common format
|
// Then, deserialize to the common format
|
||||||
@@ -129,7 +129,7 @@ impl ApiTeams for ApiV3 {
|
|||||||
pat: Option<&str>,
|
pat: Option<&str>,
|
||||||
) -> Vec<CommonTeamMember> {
|
) -> Vec<CommonTeamMember> {
|
||||||
let resp = self.get_organization_members(id_or_title, pat).await;
|
let resp = self.get_organization_members(id_or_title, pat).await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
// First, deserialize to the non-common format (to test the response is valid for this api version)
|
// First, deserialize to the non-common format (to test the response is valid for this api version)
|
||||||
let v: Vec<TeamMember> = test::read_body_json(resp).await;
|
let v: Vec<TeamMember> = test::read_body_json(resp).await;
|
||||||
// Then, deserialize to the common format
|
// Then, deserialize to the common format
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ impl ApiV3 {
|
|||||||
|
|
||||||
pub async fn get_version_deserialized(&self, id: &str, pat: Option<&str>) -> Version {
|
pub async fn get_version_deserialized(&self, id: &str, pat: Option<&str>) -> Version {
|
||||||
let resp = self.get_version(id, pat).await;
|
let resp = self.get_version(id, pat).await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
test::read_body_json(resp).await
|
test::read_body_json(resp).await
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,7 +88,7 @@ impl ApiV3 {
|
|||||||
pat: Option<&str>,
|
pat: Option<&str>,
|
||||||
) -> HashMap<String, Version> {
|
) -> HashMap<String, Version> {
|
||||||
let resp = self.update_individual_files(algorithm, hashes, pat).await;
|
let resp = self.update_individual_files(algorithm, hashes, pat).await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
test::read_body_json(resp).await
|
test::read_body_json(resp).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -158,7 +158,7 @@ impl ApiVersion for ApiV3 {
|
|||||||
|
|
||||||
async fn get_version_deserialized_common(&self, id: &str, pat: Option<&str>) -> CommonVersion {
|
async fn get_version_deserialized_common(&self, id: &str, pat: Option<&str>) -> CommonVersion {
|
||||||
let resp = self.get_version(id, pat).await;
|
let resp = self.get_version(id, pat).await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
// First, deserialize to the non-common format (to test the response is valid for this api version)
|
// First, deserialize to the non-common format (to test the response is valid for this api version)
|
||||||
let v: Version = test::read_body_json(resp).await;
|
let v: Version = test::read_body_json(resp).await;
|
||||||
// Then, deserialize to the common format
|
// Then, deserialize to the common format
|
||||||
@@ -217,7 +217,7 @@ impl ApiVersion for ApiV3 {
|
|||||||
pat: Option<&str>,
|
pat: Option<&str>,
|
||||||
) -> CommonVersion {
|
) -> CommonVersion {
|
||||||
let resp = self.get_version_from_hash(hash, algorithm, pat).await;
|
let resp = self.get_version_from_hash(hash, algorithm, pat).await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
// First, deserialize to the non-common format (to test the response is valid for this api version)
|
// First, deserialize to the non-common format (to test the response is valid for this api version)
|
||||||
let v: Version = test::read_body_json(resp).await;
|
let v: Version = test::read_body_json(resp).await;
|
||||||
// Then, deserialize to the common format
|
// Then, deserialize to the common format
|
||||||
@@ -249,7 +249,7 @@ impl ApiVersion for ApiV3 {
|
|||||||
pat: Option<&str>,
|
pat: Option<&str>,
|
||||||
) -> HashMap<String, CommonVersion> {
|
) -> HashMap<String, CommonVersion> {
|
||||||
let resp = self.get_versions_from_hashes(hashes, algorithm, pat).await;
|
let resp = self.get_versions_from_hashes(hashes, algorithm, pat).await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
// First, deserialize to the non-common format (to test the response is valid for this api version)
|
// First, deserialize to the non-common format (to test the response is valid for this api version)
|
||||||
let v: HashMap<String, Version> = test::read_body_json(resp).await;
|
let v: HashMap<String, Version> = test::read_body_json(resp).await;
|
||||||
// Then, deserialize to the common format
|
// Then, deserialize to the common format
|
||||||
@@ -301,7 +301,7 @@ impl ApiVersion for ApiV3 {
|
|||||||
let resp = self
|
let resp = self
|
||||||
.get_update_from_hash(hash, algorithm, loaders, game_versions, version_types, pat)
|
.get_update_from_hash(hash, algorithm, loaders, game_versions, version_types, pat)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
// First, deserialize to the non-common format (to test the response is valid for this api version)
|
// First, deserialize to the non-common format (to test the response is valid for this api version)
|
||||||
let v: Version = test::read_body_json(resp).await;
|
let v: Version = test::read_body_json(resp).await;
|
||||||
// Then, deserialize to the common format
|
// Then, deserialize to the common format
|
||||||
@@ -361,7 +361,7 @@ impl ApiVersion for ApiV3 {
|
|||||||
pat,
|
pat,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
// First, deserialize to the non-common format (to test the response is valid for this api version)
|
// First, deserialize to the non-common format (to test the response is valid for this api version)
|
||||||
let v: HashMap<String, Version> = test::read_body_json(resp).await;
|
let v: HashMap<String, Version> = test::read_body_json(resp).await;
|
||||||
// Then, deserialize to the common format
|
// Then, deserialize to the common format
|
||||||
@@ -444,7 +444,7 @@ impl ApiVersion for ApiV3 {
|
|||||||
pat,
|
pat,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
// First, deserialize to the non-common format (to test the response is valid for this api version)
|
// First, deserialize to the non-common format (to test the response is valid for this api version)
|
||||||
let v: Vec<Version> = test::read_body_json(resp).await;
|
let v: Vec<Version> = test::read_body_json(resp).await;
|
||||||
// Then, deserialize to the common format
|
// Then, deserialize to the common format
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
use labrinth::database::redis::RedisPool;
|
use labrinth::{database::redis::RedisPool, search};
|
||||||
use sqlx::{postgres::PgPoolOptions, PgPool};
|
use sqlx::{postgres::PgPoolOptions, PgPool};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
@@ -39,6 +39,7 @@ const TEMPLATE_DATABASE_NAME: &str = "labrinth_tests_template";
|
|||||||
pub struct TemporaryDatabase {
|
pub struct TemporaryDatabase {
|
||||||
pub pool: PgPool,
|
pub pool: PgPool,
|
||||||
pub redis_pool: RedisPool,
|
pub redis_pool: RedisPool,
|
||||||
|
pub search_config: labrinth::search::SearchConfig,
|
||||||
pub database_name: String,
|
pub database_name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,10 +85,13 @@ impl TemporaryDatabase {
|
|||||||
// Gets new Redis pool
|
// Gets new Redis pool
|
||||||
let redis_pool = RedisPool::new(Some(temp_database_name.clone()));
|
let redis_pool = RedisPool::new(Some(temp_database_name.clone()));
|
||||||
|
|
||||||
|
// Create new meilisearch config
|
||||||
|
let search_config = search::SearchConfig::new(Some(temp_database_name.clone()));
|
||||||
Self {
|
Self {
|
||||||
pool,
|
pool,
|
||||||
database_name: temp_database_name,
|
database_name: temp_database_name,
|
||||||
redis_pool,
|
redis_pool,
|
||||||
|
search_config,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -168,10 +172,12 @@ impl TemporaryDatabase {
|
|||||||
|
|
||||||
if !dummy_data_exists {
|
if !dummy_data_exists {
|
||||||
// Add dummy data
|
// Add dummy data
|
||||||
|
let name = generate_random_name("test_template_");
|
||||||
let db = TemporaryDatabase {
|
let db = TemporaryDatabase {
|
||||||
pool: pool.clone(),
|
pool: pool.clone(),
|
||||||
database_name: TEMPLATE_DATABASE_NAME.to_string(),
|
database_name: TEMPLATE_DATABASE_NAME.to_string(),
|
||||||
redis_pool: RedisPool::new(Some(generate_random_name("test_template_"))),
|
redis_pool: RedisPool::new(Some(name.clone())),
|
||||||
|
search_config: search::SearchConfig::new(Some(name)),
|
||||||
};
|
};
|
||||||
let setup_api = TestEnvironment::<ApiV3>::build_setup_api(&db).await;
|
let setup_api = TestEnvironment::<ApiV3>::build_setup_api(&db).await;
|
||||||
dummy_data::add_dummy_data(&setup_api, db.clone()).await;
|
dummy_data::add_dummy_data(&setup_api, db.clone()).await;
|
||||||
|
|||||||
@@ -207,7 +207,7 @@ impl DummyData {
|
|||||||
organization_zeta: DummyOrganizationZeta {
|
organization_zeta: DummyOrganizationZeta {
|
||||||
organization_id: organization_zeta.id.to_string(),
|
organization_id: organization_zeta.id.to_string(),
|
||||||
team_id: organization_zeta.team_id.to_string(),
|
team_id: organization_zeta.team_id.to_string(),
|
||||||
organization_name: organization_zeta.name,
|
organization_slug: organization_zeta.slug,
|
||||||
},
|
},
|
||||||
|
|
||||||
oauth_client_alpha: DummyOAuthClientAlpha {
|
oauth_client_alpha: DummyOAuthClientAlpha {
|
||||||
@@ -249,7 +249,7 @@ pub struct DummyProjectBeta {
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct DummyOrganizationZeta {
|
pub struct DummyOrganizationZeta {
|
||||||
pub organization_id: String,
|
pub organization_id: String,
|
||||||
pub organization_name: String,
|
pub organization_slug: String,
|
||||||
pub team_id: String,
|
pub team_id: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -390,7 +390,7 @@ pub async fn add_project_beta(api: &ApiV3) -> (Project, Version) {
|
|||||||
.set_multipart(vec![json_segment.clone(), file_segment.clone()])
|
.set_multipart(vec![json_segment.clone(), file_segment.clone()])
|
||||||
.to_request();
|
.to_request();
|
||||||
let resp = api.call(req).await;
|
let resp = api.call(req).await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
|
|
||||||
get_project_beta(api).await
|
get_project_beta(api).await
|
||||||
}
|
}
|
||||||
@@ -401,13 +401,14 @@ pub async fn add_organization_zeta(api: &ApiV3) -> Organization {
|
|||||||
.uri("/v3/organization")
|
.uri("/v3/organization")
|
||||||
.append_pat(USER_USER_PAT)
|
.append_pat(USER_USER_PAT)
|
||||||
.set_json(json!({
|
.set_json(json!({
|
||||||
"name": "zeta",
|
"name": "Zeta",
|
||||||
|
"slug": "zeta",
|
||||||
"description": "A dummy organization for testing with."
|
"description": "A dummy organization for testing with."
|
||||||
}))
|
}))
|
||||||
.to_request();
|
.to_request();
|
||||||
let resp = api.call(req).await;
|
let resp = api.call(req).await;
|
||||||
|
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
|
|
||||||
get_organization_zeta(api).await
|
get_organization_zeta(api).await
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ pub async fn setup(db: &database::TemporaryDatabase) -> LabrinthConfig {
|
|||||||
|
|
||||||
let pool = db.pool.clone();
|
let pool = db.pool.clone();
|
||||||
let redis_pool = db.redis_pool.clone();
|
let redis_pool = db.redis_pool.clone();
|
||||||
|
let search_config = db.search_config.clone();
|
||||||
let file_host: Arc<dyn file_hosting::FileHost + Send + Sync> =
|
let file_host: Arc<dyn file_hosting::FileHost + Send + Sync> =
|
||||||
Arc::new(file_hosting::MockHost::new());
|
Arc::new(file_hosting::MockHost::new());
|
||||||
let mut clickhouse = clickhouse::init_client().await.unwrap();
|
let mut clickhouse = clickhouse::init_client().await.unwrap();
|
||||||
@@ -36,6 +37,7 @@ pub async fn setup(db: &database::TemporaryDatabase) -> LabrinthConfig {
|
|||||||
labrinth::app_setup(
|
labrinth::app_setup(
|
||||||
pool.clone(),
|
pool.clone(),
|
||||||
redis_pool.clone(),
|
redis_pool.clone(),
|
||||||
|
search_config,
|
||||||
&mut clickhouse,
|
&mut clickhouse,
|
||||||
file_host.clone(),
|
file_host.clone(),
|
||||||
maxmind_reader,
|
maxmind_reader,
|
||||||
|
|||||||
@@ -356,12 +356,13 @@ impl<'a, A: Api> PermissionsTest<'a, A> {
|
|||||||
.await;
|
.await;
|
||||||
if !self.allowed_failure_codes.contains(&resp.status().as_u16()) {
|
if !self.allowed_failure_codes.contains(&resp.status().as_u16()) {
|
||||||
return Err(format!(
|
return Err(format!(
|
||||||
"Failure permissions test failed. Expected failure codes {} got {}",
|
"Failure permissions test failed. Expected failure codes {} got {}. Body: {:#?}",
|
||||||
self.allowed_failure_codes
|
self.allowed_failure_codes
|
||||||
.iter()
|
.iter()
|
||||||
.map(|code| code.to_string())
|
.map(|code| code.to_string())
|
||||||
.join(","),
|
.join(","),
|
||||||
resp.status().as_u16()
|
resp.status().as_u16(),
|
||||||
|
resp.response().body()
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -385,8 +386,9 @@ impl<'a, A: Api> PermissionsTest<'a, A> {
|
|||||||
.await;
|
.await;
|
||||||
if !resp.status().is_success() {
|
if !resp.status().is_success() {
|
||||||
return Err(format!(
|
return Err(format!(
|
||||||
"Success permissions test failed. Expected success, got {}",
|
"Success permissions test failed. Expected success, got {}. Body: {:#?}",
|
||||||
resp.status().as_u16()
|
resp.status().as_u16(),
|
||||||
|
resp.response().body()
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1007,15 +1009,15 @@ async fn create_dummy_project(setup_api: &ApiV3) -> (String, String) {
|
|||||||
|
|
||||||
async fn create_dummy_org(setup_api: &ApiV3) -> (String, String) {
|
async fn create_dummy_org(setup_api: &ApiV3) -> (String, String) {
|
||||||
// Create a very simple organization
|
// Create a very simple organization
|
||||||
let name = generate_random_name("test_org");
|
let slug = generate_random_name("test_org");
|
||||||
|
|
||||||
let resp = setup_api
|
let resp = setup_api
|
||||||
.create_organization(&name, "Example description.", ADMIN_USER_PAT)
|
.create_organization("Example org", &slug, "Example description.", ADMIN_USER_PAT)
|
||||||
.await;
|
.await;
|
||||||
assert!(resp.status().is_success());
|
assert!(resp.status().is_success());
|
||||||
|
|
||||||
let organization = setup_api
|
let organization = setup_api
|
||||||
.get_organization_deserialized(&name, ADMIN_USER_PAT)
|
.get_organization_deserialized(&slug, ADMIN_USER_PAT)
|
||||||
.await;
|
.await;
|
||||||
let organizaion_id = organization.id.to_string();
|
let organizaion_id = organization.id.to_string();
|
||||||
let team_id = organization.team_id.to_string();
|
let team_id = organization.team_id.to_string();
|
||||||
@@ -1109,7 +1111,7 @@ async fn get_project_permissions(
|
|||||||
.await;
|
.await;
|
||||||
let permissions = members
|
let permissions = members
|
||||||
.iter()
|
.iter()
|
||||||
.find(|member| &member.user.id.to_string() == user_id)
|
.find(|member| member.user.id.to_string() == user_id)
|
||||||
.and_then(|member| member.permissions);
|
.and_then(|member| member.permissions);
|
||||||
|
|
||||||
let organization_members = match organization {
|
let organization_members = match organization {
|
||||||
@@ -1123,7 +1125,7 @@ async fn get_project_permissions(
|
|||||||
let organization_default_project_permissions = match organization_members {
|
let organization_default_project_permissions = match organization_members {
|
||||||
Some(members) => members
|
Some(members) => members
|
||||||
.iter()
|
.iter()
|
||||||
.find(|member| &member.user.id.to_string() == user_id)
|
.find(|member| member.user.id.to_string() == user_id)
|
||||||
.and_then(|member| member.permissions),
|
.and_then(|member| member.permissions),
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
use std::{collections::HashMap, sync::Arc};
|
use std::{collections::HashMap, sync::Arc};
|
||||||
|
|
||||||
|
use actix_http::StatusCode;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
|
|
||||||
use crate::common::{
|
use crate::common::{
|
||||||
@@ -10,7 +11,7 @@ use crate::common::{
|
|||||||
dummy_data::{TestFile, DUMMY_CATEGORIES},
|
dummy_data::{TestFile, DUMMY_CATEGORIES},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{api_v3::ApiV3, environment::TestEnvironment};
|
use super::{api_v3::ApiV3, asserts::assert_status, environment::TestEnvironment};
|
||||||
|
|
||||||
pub async fn setup_search_projects(test_env: &TestEnvironment<ApiV3>) -> Arc<HashMap<u64, u64>> {
|
pub async fn setup_search_projects(test_env: &TestEnvironment<ApiV3>) -> Arc<HashMap<u64, u64>> {
|
||||||
// Test setup and dummy data
|
// Test setup and dummy data
|
||||||
@@ -47,7 +48,7 @@ pub async fn setup_search_projects(test_env: &TestEnvironment<ApiV3>) -> Arc<Has
|
|||||||
MOD_USER_PAT,
|
MOD_USER_PAT,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
(project.id.0, id)
|
(project.id.0, id)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -209,7 +210,7 @@ pub async fn setup_search_projects(test_env: &TestEnvironment<ApiV3>) -> Arc<Has
|
|||||||
|
|
||||||
// Forcibly reset the search index
|
// Forcibly reset the search index
|
||||||
let resp = api.reset_search_index().await;
|
let resp = api.reset_search_index().await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
id_conversion
|
id_conversion
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use actix_http::StatusCode;
|
||||||
use actix_web::test;
|
use actix_web::test;
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use common::api_common::ApiProject;
|
use common::api_common::ApiProject;
|
||||||
@@ -6,6 +7,8 @@ use common::api_v3::ApiV3;
|
|||||||
use common::database::USER_USER_PAT;
|
use common::database::USER_USER_PAT;
|
||||||
use common::environment::{with_test_environment, TestEnvironment};
|
use common::environment::{with_test_environment, TestEnvironment};
|
||||||
|
|
||||||
|
use crate::common::asserts::assert_status;
|
||||||
|
|
||||||
mod common;
|
mod common;
|
||||||
|
|
||||||
#[actix_rt::test]
|
#[actix_rt::test]
|
||||||
@@ -14,7 +17,7 @@ pub async fn error_404_body() {
|
|||||||
// 3 errors should have 404 as non-blank body, for missing resources
|
// 3 errors should have 404 as non-blank body, for missing resources
|
||||||
let api = &test_env.api;
|
let api = &test_env.api;
|
||||||
let resp = api.get_project("does-not-exist", USER_USER_PAT).await;
|
let resp = api.get_project("does-not-exist", USER_USER_PAT).await;
|
||||||
assert_eq!(resp.status(), 404);
|
assert_status(&resp, StatusCode::NOT_FOUND);
|
||||||
let body = test::read_body(resp).await;
|
let body = test::read_body(resp).await;
|
||||||
let empty_bytes = Bytes::from_static(b"");
|
let empty_bytes = Bytes::from_static(b"");
|
||||||
assert_ne!(body, empty_bytes);
|
assert_ne!(body, empty_bytes);
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
|
||||||
|
use actix_http::StatusCode;
|
||||||
use common::api_v3::ApiV3;
|
use common::api_v3::ApiV3;
|
||||||
use common::environment::{with_test_environment, TestEnvironment};
|
use common::environment::{with_test_environment, TestEnvironment};
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
|
|
||||||
use crate::common::api_common::ApiVersion;
|
use crate::common::api_common::ApiVersion;
|
||||||
|
use crate::common::asserts::assert_status;
|
||||||
use crate::common::database::*;
|
use crate::common::database::*;
|
||||||
|
|
||||||
use crate::common::dummy_data::{DummyProjectAlpha, DummyProjectBeta, TestFile};
|
use crate::common::dummy_data::{DummyProjectAlpha, DummyProjectBeta, TestFile};
|
||||||
@@ -49,7 +51,7 @@ async fn creating_loader_fields() {
|
|||||||
USER_USER_PAT,
|
USER_USER_PAT,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 400);
|
assert_status(&resp, StatusCode::BAD_REQUEST);
|
||||||
// - Patch
|
// - Patch
|
||||||
let resp = api
|
let resp = api
|
||||||
.edit_version(
|
.edit_version(
|
||||||
@@ -60,7 +62,7 @@ async fn creating_loader_fields() {
|
|||||||
USER_USER_PAT,
|
USER_USER_PAT,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 400);
|
assert_status(&resp, StatusCode::BAD_REQUEST);
|
||||||
|
|
||||||
// Cannot create a version with a loader field that isnt used by the loader
|
// Cannot create a version with a loader field that isnt used by the loader
|
||||||
// TODO: - Create project
|
// TODO: - Create project
|
||||||
@@ -82,7 +84,7 @@ async fn creating_loader_fields() {
|
|||||||
USER_USER_PAT,
|
USER_USER_PAT,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 400);
|
assert_status(&resp, StatusCode::BAD_REQUEST);
|
||||||
// - Patch
|
// - Patch
|
||||||
let resp = api
|
let resp = api
|
||||||
.edit_version(
|
.edit_version(
|
||||||
@@ -93,7 +95,7 @@ async fn creating_loader_fields() {
|
|||||||
USER_USER_PAT,
|
USER_USER_PAT,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 400);
|
assert_status(&resp, StatusCode::BAD_REQUEST);
|
||||||
|
|
||||||
// Cannot create a version without an applicable loader field that is not optional
|
// Cannot create a version without an applicable loader field that is not optional
|
||||||
// TODO: - Create project
|
// TODO: - Create project
|
||||||
@@ -115,7 +117,7 @@ async fn creating_loader_fields() {
|
|||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
assert_eq!(resp.status(), 400);
|
assert_status(&resp, StatusCode::BAD_REQUEST);
|
||||||
|
|
||||||
// Cannot create a version without a loader field array that has a minimum of 1
|
// Cannot create a version without a loader field array that has a minimum of 1
|
||||||
// TODO: - Create project
|
// TODO: - Create project
|
||||||
@@ -136,7 +138,7 @@ async fn creating_loader_fields() {
|
|||||||
USER_USER_PAT,
|
USER_USER_PAT,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 400);
|
assert_status(&resp, StatusCode::BAD_REQUEST);
|
||||||
|
|
||||||
// TODO: Create a test for too many elements in the array when we have a LF that has a max (past max)
|
// TODO: Create a test for too many elements in the array when we have a LF that has a max (past max)
|
||||||
// Cannot create a version with a loader field array that has fewer than the minimum elements
|
// Cannot create a version with a loader field array that has fewer than the minimum elements
|
||||||
@@ -159,7 +161,7 @@ async fn creating_loader_fields() {
|
|||||||
USER_USER_PAT,
|
USER_USER_PAT,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 400);
|
assert_status(&resp, StatusCode::BAD_REQUEST);
|
||||||
|
|
||||||
// - Patch
|
// - Patch
|
||||||
let resp = api
|
let resp = api
|
||||||
@@ -171,7 +173,7 @@ async fn creating_loader_fields() {
|
|||||||
USER_USER_PAT,
|
USER_USER_PAT,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 400);
|
assert_status(&resp, StatusCode::BAD_REQUEST);
|
||||||
|
|
||||||
// Cannot create an invalid data type for the loader field type (including bad variant for the type)
|
// Cannot create an invalid data type for the loader field type (including bad variant for the type)
|
||||||
for bad_type_game_versions in [
|
for bad_type_game_versions in [
|
||||||
@@ -199,7 +201,7 @@ async fn creating_loader_fields() {
|
|||||||
USER_USER_PAT,
|
USER_USER_PAT,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 400);
|
assert_status(&resp, StatusCode::BAD_REQUEST);
|
||||||
|
|
||||||
// - Patch
|
// - Patch
|
||||||
let resp = api
|
let resp = api
|
||||||
@@ -211,7 +213,7 @@ async fn creating_loader_fields() {
|
|||||||
USER_USER_PAT,
|
USER_USER_PAT,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 400);
|
assert_status(&resp, StatusCode::BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Can create with optional loader fields (other tests have checked if we can create without them)
|
// Can create with optional loader fields (other tests have checked if we can create without them)
|
||||||
@@ -245,7 +247,7 @@ async fn creating_loader_fields() {
|
|||||||
USER_USER_PAT,
|
USER_USER_PAT,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
let v = api
|
let v = api
|
||||||
.get_version_deserialized(alpha_version_id, USER_USER_PAT)
|
.get_version_deserialized(alpha_version_id, USER_USER_PAT)
|
||||||
.await;
|
.await;
|
||||||
@@ -296,7 +298,7 @@ async fn creating_loader_fields() {
|
|||||||
USER_USER_PAT,
|
USER_USER_PAT,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
let v = api
|
let v = api
|
||||||
.get_version_deserialized(alpha_version_id, USER_USER_PAT)
|
.get_version_deserialized(alpha_version_id, USER_USER_PAT)
|
||||||
.await;
|
.await;
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
use crate::common::{
|
use crate::common::{
|
||||||
api_common::{ApiProject, ApiTeams},
|
api_common::{ApiProject, ApiTeams},
|
||||||
|
asserts::assert_status,
|
||||||
database::{
|
database::{
|
||||||
generate_random_name, ADMIN_USER_PAT, ENEMY_USER_ID_PARSED, ENEMY_USER_PAT,
|
generate_random_name, ADMIN_USER_PAT, ENEMY_USER_ID_PARSED, ENEMY_USER_PAT,
|
||||||
FRIEND_USER_ID_PARSED, MOD_USER_ID, MOD_USER_PAT, USER_USER_ID, USER_USER_ID_PARSED,
|
FRIEND_USER_ID_PARSED, MOD_USER_ID, MOD_USER_PAT, USER_USER_ID, USER_USER_ID_PARSED,
|
||||||
},
|
},
|
||||||
dummy_data::{DummyImage, DummyOrganizationZeta, DummyProjectAlpha, DummyProjectBeta},
|
dummy_data::{DummyImage, DummyOrganizationZeta, DummyProjectAlpha, DummyProjectBeta},
|
||||||
};
|
};
|
||||||
|
use actix_http::StatusCode;
|
||||||
use common::{
|
use common::{
|
||||||
api_v3::ApiV3,
|
api_v3::ApiV3,
|
||||||
database::{FRIEND_USER_ID, FRIEND_USER_PAT, USER_USER_PAT},
|
database::{FRIEND_USER_ID, FRIEND_USER_PAT, USER_USER_PAT},
|
||||||
@@ -27,45 +29,61 @@ async fn create_organization() {
|
|||||||
let zeta_organization_slug = &test_env.dummy.organization_zeta.organization_id;
|
let zeta_organization_slug = &test_env.dummy.organization_zeta.organization_id;
|
||||||
|
|
||||||
// Failed creations title:
|
// Failed creations title:
|
||||||
|
// - too short title
|
||||||
|
// - too long title
|
||||||
|
for title in ["a", &"a".repeat(100)] {
|
||||||
|
let resp = api
|
||||||
|
.create_organization(title, "theta", "theta_description", USER_USER_PAT)
|
||||||
|
.await;
|
||||||
|
assert_status(&resp, StatusCode::BAD_REQUEST);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Failed creations slug:
|
||||||
// - slug collision with zeta
|
// - slug collision with zeta
|
||||||
// - too short slug
|
// - too short slug
|
||||||
// - too long slug
|
// - too long slug
|
||||||
// - not url safe slug
|
// - not url safe slug
|
||||||
for title in [
|
for slug in [
|
||||||
zeta_organization_slug,
|
zeta_organization_slug,
|
||||||
"a",
|
"a",
|
||||||
&"a".repeat(100),
|
&"a".repeat(100),
|
||||||
"not url safe%&^!#$##!@#$%^&*()",
|
"not url safe%&^!#$##!@#$%^&*()",
|
||||||
] {
|
] {
|
||||||
let resp = api
|
let resp = api
|
||||||
.create_organization(title, "theta_description", USER_USER_PAT)
|
.create_organization("Theta Org", slug, "theta_description", USER_USER_PAT)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 400);
|
assert_status(&resp, StatusCode::BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Failed creations description:
|
// Failed creations description:
|
||||||
// - too short slug
|
// - too short desc
|
||||||
// - too long slug
|
// - too long desc
|
||||||
for description in ["a", &"a".repeat(300)] {
|
for description in ["a", &"a".repeat(300)] {
|
||||||
let resp = api
|
let resp = api
|
||||||
.create_organization("theta", description, USER_USER_PAT)
|
.create_organization("Theta Org", "theta", description, USER_USER_PAT)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 400);
|
assert_status(&resp, StatusCode::BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create 'theta' organization
|
// Create 'theta' organization
|
||||||
let resp = api
|
let resp = api
|
||||||
.create_organization("theta", "not url safe%&^!#$##!@#$%^&", USER_USER_PAT)
|
.create_organization(
|
||||||
|
"Theta Org",
|
||||||
|
"theta",
|
||||||
|
"not url safe%&^!#$##!@#$%^&",
|
||||||
|
USER_USER_PAT,
|
||||||
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
|
|
||||||
// Get organization using slug
|
// Get organization using slug
|
||||||
let theta = api
|
let theta = api
|
||||||
.get_organization_deserialized("theta", USER_USER_PAT)
|
.get_organization_deserialized("theta", USER_USER_PAT)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(theta.name, "theta");
|
assert_eq!(theta.name, "Theta Org");
|
||||||
|
assert_eq!(theta.slug, "theta");
|
||||||
assert_eq!(theta.description, "not url safe%&^!#$##!@#$%^&");
|
assert_eq!(theta.description, "not url safe%&^!#$##!@#$%^&");
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
|
|
||||||
// Get created team
|
// Get created team
|
||||||
let members = api
|
let members = api
|
||||||
@@ -95,7 +113,7 @@ async fn get_project_organization() {
|
|||||||
let resp = api
|
let resp = api
|
||||||
.organization_add_project(zeta_organization_id, alpha_project_id, USER_USER_PAT)
|
.organization_add_project(zeta_organization_id, alpha_project_id, USER_USER_PAT)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
|
|
||||||
// Get project organization
|
// Get project organization
|
||||||
let zeta = api
|
let zeta = api
|
||||||
@@ -115,9 +133,25 @@ async fn patch_organization() {
|
|||||||
|
|
||||||
// Create 'theta' organization
|
// Create 'theta' organization
|
||||||
let resp = api
|
let resp = api
|
||||||
.create_organization("theta", "theta_description", USER_USER_PAT)
|
.create_organization("Theta Org", "theta", "theta_description", USER_USER_PAT)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
|
|
||||||
|
// Failed patch to theta title:
|
||||||
|
// - too short title
|
||||||
|
// - too long title
|
||||||
|
for title in ["a", &"a".repeat(100)] {
|
||||||
|
let resp = api
|
||||||
|
.edit_organization(
|
||||||
|
"theta",
|
||||||
|
json!({
|
||||||
|
"name": title,
|
||||||
|
}),
|
||||||
|
USER_USER_PAT,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
assert_status(&resp, StatusCode::BAD_REQUEST);
|
||||||
|
}
|
||||||
|
|
||||||
// Failed patch to zeta slug:
|
// Failed patch to zeta slug:
|
||||||
// - slug collision with theta
|
// - slug collision with theta
|
||||||
@@ -134,13 +168,13 @@ async fn patch_organization() {
|
|||||||
.edit_organization(
|
.edit_organization(
|
||||||
zeta_organization_id,
|
zeta_organization_id,
|
||||||
json!({
|
json!({
|
||||||
"name": title,
|
"slug": title,
|
||||||
"description": "theta_description"
|
"description": "theta_description"
|
||||||
}),
|
}),
|
||||||
USER_USER_PAT,
|
USER_USER_PAT,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 400);
|
assert_status(&resp, StatusCode::BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Failed patch to zeta description:
|
// Failed patch to zeta description:
|
||||||
@@ -156,7 +190,7 @@ async fn patch_organization() {
|
|||||||
USER_USER_PAT,
|
USER_USER_PAT,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 400);
|
assert_status(&resp, StatusCode::BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Successful patch to many fields
|
// Successful patch to many fields
|
||||||
@@ -165,18 +199,20 @@ async fn patch_organization() {
|
|||||||
zeta_organization_id,
|
zeta_organization_id,
|
||||||
json!({
|
json!({
|
||||||
"name": "new_title",
|
"name": "new_title",
|
||||||
|
"slug": "new_slug",
|
||||||
"description": "not url safe%&^!#$##!@#$%^&" // not-URL-safe description should still work
|
"description": "not url safe%&^!#$##!@#$%^&" // not-URL-safe description should still work
|
||||||
}),
|
}),
|
||||||
USER_USER_PAT,
|
USER_USER_PAT,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
// Get project using new slug
|
// Get project using new slug
|
||||||
let new_title = api
|
let new_title = api
|
||||||
.get_organization_deserialized("new_title", USER_USER_PAT)
|
.get_organization_deserialized("new_slug", USER_USER_PAT)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(new_title.name, "new_title");
|
assert_eq!(new_title.name, "new_title");
|
||||||
|
assert_eq!(new_title.slug, "new_slug");
|
||||||
assert_eq!(new_title.description, "not url safe%&^!#$##!@#$%^&");
|
assert_eq!(new_title.description, "not url safe%&^!#$##!@#$%^&");
|
||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
@@ -185,7 +221,7 @@ async fn patch_organization() {
|
|||||||
// add/remove icon
|
// add/remove icon
|
||||||
#[actix_rt::test]
|
#[actix_rt::test]
|
||||||
async fn add_remove_icon() {
|
async fn add_remove_icon() {
|
||||||
with_test_environment(None, |test_env: TestEnvironment<ApiV3>| async move {
|
with_test_environment(Some(10), |test_env: TestEnvironment<ApiV3>| async move {
|
||||||
let api = &test_env.api;
|
let api = &test_env.api;
|
||||||
let zeta_organization_id = &test_env.dummy.organization_zeta.organization_id;
|
let zeta_organization_id = &test_env.dummy.organization_zeta.organization_id;
|
||||||
|
|
||||||
@@ -205,7 +241,7 @@ async fn add_remove_icon() {
|
|||||||
USER_USER_PAT,
|
USER_USER_PAT,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
// Get project
|
// Get project
|
||||||
let zeta_org = api
|
let zeta_org = api
|
||||||
@@ -218,7 +254,7 @@ async fn add_remove_icon() {
|
|||||||
let resp = api
|
let resp = api
|
||||||
.edit_organization_icon(zeta_organization_id, None, USER_USER_PAT)
|
.edit_organization_icon(zeta_organization_id, None, USER_USER_PAT)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
// Get project
|
// Get project
|
||||||
let zeta_org = api
|
let zeta_org = api
|
||||||
@@ -239,13 +275,13 @@ async fn delete_org() {
|
|||||||
let resp = api
|
let resp = api
|
||||||
.delete_organization(zeta_organization_id, USER_USER_PAT)
|
.delete_organization(zeta_organization_id, USER_USER_PAT)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
// Get organization, which should no longer exist
|
// Get organization, which should no longer exist
|
||||||
let resp = api
|
let resp = api
|
||||||
.get_organization(zeta_organization_id, USER_USER_PAT)
|
.get_organization(zeta_organization_id, USER_USER_PAT)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 404);
|
assert_status(&resp, StatusCode::NOT_FOUND);
|
||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
@@ -264,7 +300,7 @@ async fn add_remove_organization_projects() {
|
|||||||
.api
|
.api
|
||||||
.organization_add_project(zeta_organization_id, alpha, USER_USER_PAT)
|
.organization_add_project(zeta_organization_id, alpha, USER_USER_PAT)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
|
|
||||||
// Get organization projects
|
// Get organization projects
|
||||||
let projects = test_env
|
let projects = test_env
|
||||||
@@ -284,7 +320,7 @@ async fn add_remove_organization_projects() {
|
|||||||
USER_USER_PAT,
|
USER_USER_PAT,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
|
|
||||||
// Get organization projects
|
// Get organization projects
|
||||||
let projects = test_env
|
let projects = test_env
|
||||||
@@ -338,11 +374,11 @@ async fn add_remove_organization_project_ownership_to_user() {
|
|||||||
USER_USER_PAT,
|
USER_USER_PAT,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
// Accept invites
|
// Accept invites
|
||||||
let resp = test_env.api.join_team(team, FRIEND_USER_PAT).await;
|
let resp = test_env.api.join_team(team, FRIEND_USER_PAT).await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
// For each team, confirm there are two members, but only one owner of the project, and it is USER_USER_ID
|
// For each team, confirm there are two members, but only one owner of the project, and it is USER_USER_ID
|
||||||
@@ -362,7 +398,7 @@ async fn add_remove_organization_project_ownership_to_user() {
|
|||||||
.api
|
.api
|
||||||
.transfer_team_ownership(beta_team_id, FRIEND_USER_ID, USER_USER_PAT)
|
.transfer_team_ownership(beta_team_id, FRIEND_USER_ID, USER_USER_PAT)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
// Confirm there are still two users, but now FRIEND_USER_ID is the owner
|
// Confirm there are still two users, but now FRIEND_USER_ID is the owner
|
||||||
let members = test_env
|
let members = test_env
|
||||||
@@ -383,7 +419,7 @@ async fn add_remove_organization_project_ownership_to_user() {
|
|||||||
.api
|
.api
|
||||||
.organization_add_project(zeta_organization_id, project_id, pat)
|
.organization_add_project(zeta_organization_id, project_id, pat)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
|
|
||||||
// Get and confirm it has been added
|
// Get and confirm it has been added
|
||||||
let project = test_env.api.get_project_deserialized(project_id, pat).await;
|
let project = test_env.api.get_project_deserialized(project_id, pat).await;
|
||||||
@@ -416,7 +452,7 @@ async fn add_remove_organization_project_ownership_to_user() {
|
|||||||
.api
|
.api
|
||||||
.transfer_team_ownership(zeta_team_id, FRIEND_USER_ID, USER_USER_PAT)
|
.transfer_team_ownership(zeta_team_id, FRIEND_USER_ID, USER_USER_PAT)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
// Confirm there are no members of the alpha project OR the beta project
|
// Confirm there are no members of the alpha project OR the beta project
|
||||||
// - Friend was removed as a member of these projects when ownership was transferred to them
|
// - Friend was removed as a member of these projects when ownership was transferred to them
|
||||||
@@ -433,14 +469,14 @@ async fn add_remove_organization_project_ownership_to_user() {
|
|||||||
.api
|
.api
|
||||||
.add_user_to_team(alpha_team_id, FRIEND_USER_ID, None, None, USER_USER_PAT)
|
.add_user_to_team(alpha_team_id, FRIEND_USER_ID, None, None, USER_USER_PAT)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 400);
|
assert_status(&resp, StatusCode::BAD_REQUEST);
|
||||||
|
|
||||||
// As friend, can add user to alpha project, as they are not the org owner
|
// As friend, can add user to alpha project, as they are not the org owner
|
||||||
let resp = test_env
|
let resp = test_env
|
||||||
.api
|
.api
|
||||||
.add_user_to_team(alpha_team_id, USER_USER_ID, None, None, FRIEND_USER_PAT)
|
.add_user_to_team(alpha_team_id, USER_USER_ID, None, None, FRIEND_USER_PAT)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
// At this point, friend owns the org
|
// At this point, friend owns the org
|
||||||
// Alpha member has user as a member, but not as an owner
|
// Alpha member has user as a member, but not as an owner
|
||||||
@@ -457,7 +493,7 @@ async fn add_remove_organization_project_ownership_to_user() {
|
|||||||
USER_USER_PAT,
|
USER_USER_PAT,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 400);
|
assert_status(&resp, StatusCode::BAD_REQUEST);
|
||||||
|
|
||||||
// Set user's permissions within the project that it is a member of to none (for a later test)
|
// Set user's permissions within the project that it is a member of to none (for a later test)
|
||||||
let resp = test_env
|
let resp = test_env
|
||||||
@@ -471,7 +507,7 @@ async fn add_remove_organization_project_ownership_to_user() {
|
|||||||
FRIEND_USER_PAT,
|
FRIEND_USER_PAT,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
// Remove project from organization with a user that is an organization member, and a project member
|
// Remove project from organization with a user that is an organization member, and a project member
|
||||||
// This should succeed
|
// This should succeed
|
||||||
@@ -484,7 +520,7 @@ async fn add_remove_organization_project_ownership_to_user() {
|
|||||||
USER_USER_PAT,
|
USER_USER_PAT,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
|
|
||||||
// Remove project from organization with a user that is an organization member, but not a project member
|
// Remove project from organization with a user that is an organization member, but not a project member
|
||||||
// This should succeed
|
// This should succeed
|
||||||
@@ -497,7 +533,7 @@ async fn add_remove_organization_project_ownership_to_user() {
|
|||||||
USER_USER_PAT,
|
USER_USER_PAT,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
|
|
||||||
// For each of alpha and beta, confirm:
|
// For each of alpha and beta, confirm:
|
||||||
// - There is one member of each project, the owner, USER_USER_ID
|
// - There is one member of each project, the owner, USER_USER_ID
|
||||||
@@ -559,11 +595,11 @@ async fn delete_organization_means_all_projects_to_org_owner() {
|
|||||||
.api
|
.api
|
||||||
.add_user_to_team(zeta_team_id, FRIEND_USER_ID, None, None, USER_USER_PAT)
|
.add_user_to_team(zeta_team_id, FRIEND_USER_ID, None, None, USER_USER_PAT)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
// Accept invite
|
// Accept invite
|
||||||
let resp = test_env.api.join_team(zeta_team_id, FRIEND_USER_PAT).await;
|
let resp = test_env.api.join_team(zeta_team_id, FRIEND_USER_PAT).await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
// Confirm there is only one owner of the project, and it is USER_USER_ID
|
// Confirm there is only one owner of the project, and it is USER_USER_ID
|
||||||
let members = test_env
|
let members = test_env
|
||||||
@@ -579,7 +615,7 @@ async fn delete_organization_means_all_projects_to_org_owner() {
|
|||||||
.api
|
.api
|
||||||
.organization_add_project(zeta_organization_id, alpha_project_id, USER_USER_PAT)
|
.organization_add_project(zeta_organization_id, alpha_project_id, USER_USER_PAT)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
|
|
||||||
// Add beta to zeta organization
|
// Add beta to zeta organization
|
||||||
test_env
|
test_env
|
||||||
@@ -592,13 +628,13 @@ async fn delete_organization_means_all_projects_to_org_owner() {
|
|||||||
.api
|
.api
|
||||||
.add_user_to_team(beta_team_id, FRIEND_USER_ID, None, None, USER_USER_PAT)
|
.add_user_to_team(beta_team_id, FRIEND_USER_ID, None, None, USER_USER_PAT)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
// Try to accept invite
|
// Try to accept invite
|
||||||
// This returns a failure, because since beta and FRIEND are in the organizations,
|
// This returns a failure, because since beta and FRIEND are in the organizations,
|
||||||
// they can be added to the project without an invite
|
// they can be added to the project without an invite
|
||||||
let resp = test_env.api.join_team(beta_team_id, FRIEND_USER_PAT).await;
|
let resp = test_env.api.join_team(beta_team_id, FRIEND_USER_PAT).await;
|
||||||
assert_eq!(resp.status(), 400);
|
assert_status(&resp, StatusCode::BAD_REQUEST);
|
||||||
|
|
||||||
// Confirm there is NO owner of the project, as it is owned by the organization
|
// Confirm there is NO owner of the project, as it is owned by the organization
|
||||||
let members = test_env
|
let members = test_env
|
||||||
@@ -613,7 +649,7 @@ async fn delete_organization_means_all_projects_to_org_owner() {
|
|||||||
.api
|
.api
|
||||||
.transfer_team_ownership(zeta_team_id, FRIEND_USER_ID, USER_USER_PAT)
|
.transfer_team_ownership(zeta_team_id, FRIEND_USER_ID, USER_USER_PAT)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
// Confirm there is NO owner of the project, as it is owned by the organization
|
// Confirm there is NO owner of the project, as it is owned by the organization
|
||||||
let members = test_env
|
let members = test_env
|
||||||
@@ -628,7 +664,7 @@ async fn delete_organization_means_all_projects_to_org_owner() {
|
|||||||
.api
|
.api
|
||||||
.delete_organization(zeta_organization_id, FRIEND_USER_PAT)
|
.delete_organization(zeta_organization_id, FRIEND_USER_PAT)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
// Confirm there is only one owner of the alpha project, and it is now FRIEND_USER_ID
|
// Confirm there is only one owner of the alpha project, and it is now FRIEND_USER_ID
|
||||||
let members = test_env
|
let members = test_env
|
||||||
@@ -708,7 +744,7 @@ async fn permissions_patch_organization() {
|
|||||||
// Not covered by PATCH /organization
|
// Not covered by PATCH /organization
|
||||||
#[actix_rt::test]
|
#[actix_rt::test]
|
||||||
async fn permissions_edit_details() {
|
async fn permissions_edit_details() {
|
||||||
with_test_environment(None, |test_env: TestEnvironment<ApiV3>| async move {
|
with_test_environment(Some(12), |test_env: TestEnvironment<ApiV3>| async move {
|
||||||
let zeta_organization_id = &test_env.dummy.organization_zeta.organization_id;
|
let zeta_organization_id = &test_env.dummy.organization_zeta.organization_id;
|
||||||
let zeta_team_id = &test_env.dummy.organization_zeta.team_id;
|
let zeta_team_id = &test_env.dummy.organization_zeta.team_id;
|
||||||
|
|
||||||
@@ -814,9 +850,9 @@ async fn permissions_manage_invites() {
|
|||||||
let resp = api
|
let resp = api
|
||||||
.add_user_to_team(zeta_team_id, MOD_USER_ID, None, None, ADMIN_USER_PAT)
|
.add_user_to_team(zeta_team_id, MOD_USER_ID, None, None, ADMIN_USER_PAT)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
let resp = api.join_team(zeta_team_id, MOD_USER_PAT).await;
|
let resp = api.join_team(zeta_team_id, MOD_USER_PAT).await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
// remove existing member (requires remove_member)
|
// remove existing member (requires remove_member)
|
||||||
let remove_member = OrganizationPermissions::REMOVE_MEMBER;
|
let remove_member = OrganizationPermissions::REMOVE_MEMBER;
|
||||||
@@ -852,13 +888,13 @@ async fn permissions_add_remove_project() {
|
|||||||
let resp = api
|
let resp = api
|
||||||
.add_user_to_team(alpha_team_id, FRIEND_USER_ID, None, None, USER_USER_PAT)
|
.add_user_to_team(alpha_team_id, FRIEND_USER_ID, None, None, USER_USER_PAT)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
let resp = api.join_team(alpha_team_id, FRIEND_USER_PAT).await;
|
let resp = api.join_team(alpha_team_id, FRIEND_USER_PAT).await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
let resp = api
|
let resp = api
|
||||||
.transfer_team_ownership(alpha_team_id, FRIEND_USER_ID, USER_USER_PAT)
|
.transfer_team_ownership(alpha_team_id, FRIEND_USER_ID, USER_USER_PAT)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
// Now, FRIEND_USER_ID owns the alpha project
|
// Now, FRIEND_USER_ID owns the alpha project
|
||||||
// Add alpha project to zeta organization
|
// Add alpha project to zeta organization
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use actix_http::StatusCode;
|
||||||
use actix_web::test;
|
use actix_web::test;
|
||||||
use chrono::{Duration, Utc};
|
use chrono::{Duration, Utc};
|
||||||
use common::{database::*, environment::with_test_environment_all};
|
use common::{database::*, environment::with_test_environment_all};
|
||||||
@@ -5,7 +6,7 @@ use common::{database::*, environment::with_test_environment_all};
|
|||||||
use labrinth::models::pats::Scopes;
|
use labrinth::models::pats::Scopes;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
|
|
||||||
use crate::common::api_common::AppendsOptionalPat;
|
use crate::common::{api_common::AppendsOptionalPat, asserts::assert_status};
|
||||||
|
|
||||||
mod common;
|
mod common;
|
||||||
|
|
||||||
@@ -30,7 +31,7 @@ pub async fn pat_full_test() {
|
|||||||
}))
|
}))
|
||||||
.to_request();
|
.to_request();
|
||||||
let resp = test_env.call(req).await;
|
let resp = test_env.call(req).await;
|
||||||
assert_eq!(resp.status().as_u16(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
let success: serde_json::Value = test::read_body_json(resp).await;
|
let success: serde_json::Value = test::read_body_json(resp).await;
|
||||||
let id = success["id"].as_str().unwrap();
|
let id = success["id"].as_str().unwrap();
|
||||||
|
|
||||||
@@ -48,7 +49,7 @@ pub async fn pat_full_test() {
|
|||||||
.uri("/_internal/pat")
|
.uri("/_internal/pat")
|
||||||
.to_request();
|
.to_request();
|
||||||
let resp = test_env.call(req).await;
|
let resp = test_env.call(req).await;
|
||||||
assert_eq!(resp.status().as_u16(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
let success: serde_json::Value = test::read_body_json(resp).await;
|
let success: serde_json::Value = test::read_body_json(resp).await;
|
||||||
|
|
||||||
// Ensure access token is NOT returned for any PATs
|
// Ensure access token is NOT returned for any PATs
|
||||||
@@ -87,7 +88,7 @@ pub async fn pat_full_test() {
|
|||||||
}))
|
}))
|
||||||
.to_request();
|
.to_request();
|
||||||
let resp = test_env.call(req).await;
|
let resp = test_env.call(req).await;
|
||||||
assert_eq!(resp.status().as_u16(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
assert_eq!(mock_pat_test(access_token).await, 401); // No longer works
|
assert_eq!(mock_pat_test(access_token).await, 401); // No longer works
|
||||||
|
|
||||||
// Change scopes back, and set expiry to the past, and test again
|
// Change scopes back, and set expiry to the past, and test again
|
||||||
@@ -100,7 +101,7 @@ pub async fn pat_full_test() {
|
|||||||
}))
|
}))
|
||||||
.to_request();
|
.to_request();
|
||||||
let resp = test_env.call(req).await;
|
let resp = test_env.call(req).await;
|
||||||
assert_eq!(resp.status().as_u16(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
// Wait 1 second before testing again for expiry
|
// Wait 1 second before testing again for expiry
|
||||||
tokio::time::sleep(Duration::seconds(1).to_std().unwrap()).await;
|
tokio::time::sleep(Duration::seconds(1).to_std().unwrap()).await;
|
||||||
@@ -115,7 +116,7 @@ pub async fn pat_full_test() {
|
|||||||
}))
|
}))
|
||||||
.to_request();
|
.to_request();
|
||||||
let resp = test_env.call(req).await;
|
let resp = test_env.call(req).await;
|
||||||
assert_eq!(resp.status().as_u16(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
assert_eq!(mock_pat_test(access_token).await, 200); // Works again
|
assert_eq!(mock_pat_test(access_token).await, 200); // Works again
|
||||||
|
|
||||||
// Patching to a bad expiry should fail
|
// Patching to a bad expiry should fail
|
||||||
@@ -127,7 +128,7 @@ pub async fn pat_full_test() {
|
|||||||
}))
|
}))
|
||||||
.to_request();
|
.to_request();
|
||||||
let resp = test_env.call(req).await;
|
let resp = test_env.call(req).await;
|
||||||
assert_eq!(resp.status().as_u16(), 400);
|
assert_status(&resp, StatusCode::BAD_REQUEST);
|
||||||
|
|
||||||
// Similar to above with PAT creation, patching to a bad scope should fail
|
// Similar to above with PAT creation, patching to a bad scope should fail
|
||||||
for i in 0..64 {
|
for i in 0..64 {
|
||||||
@@ -156,7 +157,7 @@ pub async fn pat_full_test() {
|
|||||||
.uri(&format!("/_internal/pat/{}", id))
|
.uri(&format!("/_internal/pat/{}", id))
|
||||||
.to_request();
|
.to_request();
|
||||||
let resp = test_env.call(req).await;
|
let resp = test_env.call(req).await;
|
||||||
assert_eq!(resp.status().as_u16(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
@@ -175,7 +176,7 @@ pub async fn bad_pats() {
|
|||||||
}))
|
}))
|
||||||
.to_request();
|
.to_request();
|
||||||
let resp = test_env.call(req).await;
|
let resp = test_env.call(req).await;
|
||||||
assert_eq!(resp.status().as_u16(), 400);
|
assert_status(&resp, StatusCode::BAD_REQUEST);
|
||||||
|
|
||||||
// Name too short or too long should fail
|
// Name too short or too long should fail
|
||||||
for name in ["n", "this_name_is_too_long".repeat(16).as_str()] {
|
for name in ["n", "this_name_is_too_long".repeat(16).as_str()] {
|
||||||
@@ -189,7 +190,7 @@ pub async fn bad_pats() {
|
|||||||
}))
|
}))
|
||||||
.to_request();
|
.to_request();
|
||||||
let resp = test_env.call(req).await;
|
let resp = test_env.call(req).await;
|
||||||
assert_eq!(resp.status().as_u16(), 400);
|
assert_status(&resp, StatusCode::BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creating a PAT with an expiry in the past should fail
|
// Creating a PAT with an expiry in the past should fail
|
||||||
@@ -203,7 +204,7 @@ pub async fn bad_pats() {
|
|||||||
}))
|
}))
|
||||||
.to_request();
|
.to_request();
|
||||||
let resp = test_env.call(req).await;
|
let resp = test_env.call(req).await;
|
||||||
assert_eq!(resp.status().as_u16(), 400);
|
assert_status(&resp, StatusCode::BAD_REQUEST);
|
||||||
|
|
||||||
// Make a PAT with each scope, with the result varying by whether that scope is restricted
|
// Make a PAT with each scope, with the result varying by whether that scope is restricted
|
||||||
for i in 0..64 {
|
for i in 0..64 {
|
||||||
@@ -238,7 +239,7 @@ pub async fn bad_pats() {
|
|||||||
}))
|
}))
|
||||||
.to_request();
|
.to_request();
|
||||||
let resp = test_env.call(req).await;
|
let resp = test_env.call(req).await;
|
||||||
assert_eq!(resp.status().as_u16(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
let success: serde_json::Value = test::read_body_json(resp).await;
|
let success: serde_json::Value = test::read_body_json(resp).await;
|
||||||
let id = success["id"].as_str().unwrap();
|
let id = success["id"].as_str().unwrap();
|
||||||
|
|
||||||
@@ -252,7 +253,7 @@ pub async fn bad_pats() {
|
|||||||
}))
|
}))
|
||||||
.to_request();
|
.to_request();
|
||||||
let resp = test_env.call(req).await;
|
let resp = test_env.call(req).await;
|
||||||
assert_eq!(resp.status().as_u16(), 400);
|
assert_status(&resp, StatusCode::BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Patching to a bad expiry should fail
|
// Patching to a bad expiry should fail
|
||||||
@@ -264,7 +265,7 @@ pub async fn bad_pats() {
|
|||||||
}))
|
}))
|
||||||
.to_request();
|
.to_request();
|
||||||
let resp = test_env.call(req).await;
|
let resp = test_env.call(req).await;
|
||||||
assert_eq!(resp.status().as_u16(), 400);
|
assert_status(&resp, StatusCode::BAD_REQUEST);
|
||||||
|
|
||||||
// Similar to above with PAT creation, patching to a bad scope should fail
|
// Similar to above with PAT creation, patching to a bad scope should fail
|
||||||
for i in 0..64 {
|
for i in 0..64 {
|
||||||
|
|||||||
214
tests/project.rs
214
tests/project.rs
@@ -3,6 +3,7 @@ use std::collections::HashMap;
|
|||||||
use actix_http::StatusCode;
|
use actix_http::StatusCode;
|
||||||
use actix_web::test;
|
use actix_web::test;
|
||||||
use common::api_v3::ApiV3;
|
use common::api_v3::ApiV3;
|
||||||
|
use common::asserts::assert_status;
|
||||||
use common::database::*;
|
use common::database::*;
|
||||||
use common::dummy_data::DUMMY_CATEGORIES;
|
use common::dummy_data::DUMMY_CATEGORIES;
|
||||||
|
|
||||||
@@ -20,7 +21,9 @@ use serde_json::json;
|
|||||||
use crate::common::api_common::models::CommonItemType;
|
use crate::common::api_common::models::CommonItemType;
|
||||||
use crate::common::api_common::request_data::ProjectCreationRequestData;
|
use crate::common::api_common::request_data::ProjectCreationRequestData;
|
||||||
use crate::common::api_common::{ApiProject, ApiTeams, ApiVersion};
|
use crate::common::api_common::{ApiProject, ApiTeams, ApiVersion};
|
||||||
use crate::common::dummy_data::{DummyImage, DummyProjectAlpha, DummyProjectBeta, TestFile};
|
use crate::common::dummy_data::{
|
||||||
|
DummyImage, DummyOrganizationZeta, DummyProjectAlpha, DummyProjectBeta, TestFile,
|
||||||
|
};
|
||||||
mod common;
|
mod common;
|
||||||
|
|
||||||
#[actix_rt::test]
|
#[actix_rt::test]
|
||||||
@@ -42,10 +45,9 @@ async fn test_get_project() {
|
|||||||
|
|
||||||
// Perform request on dummy data
|
// Perform request on dummy data
|
||||||
let resp = api.get_project(alpha_project_id, USER_USER_PAT).await;
|
let resp = api.get_project(alpha_project_id, USER_USER_PAT).await;
|
||||||
let status = resp.status();
|
assert_status(&resp, StatusCode::OK);
|
||||||
let body: serde_json::Value = test::read_body_json(resp).await;
|
let body: serde_json::Value = test::read_body_json(resp).await;
|
||||||
|
|
||||||
assert_eq!(status, 200);
|
|
||||||
assert_eq!(body["id"], json!(alpha_project_id));
|
assert_eq!(body["id"], json!(alpha_project_id));
|
||||||
assert_eq!(body["slug"], json!(alpha_project_slug));
|
assert_eq!(body["slug"], json!(alpha_project_slug));
|
||||||
let versions = body["versions"].as_array().unwrap();
|
let versions = body["versions"].as_array().unwrap();
|
||||||
@@ -75,8 +77,7 @@ async fn test_get_project() {
|
|||||||
|
|
||||||
// Make the request again, this time it should be cached
|
// Make the request again, this time it should be cached
|
||||||
let resp = api.get_project(alpha_project_id, USER_USER_PAT).await;
|
let resp = api.get_project(alpha_project_id, USER_USER_PAT).await;
|
||||||
let status = resp.status();
|
assert_status(&resp, StatusCode::OK);
|
||||||
assert_eq!(status, 200);
|
|
||||||
|
|
||||||
let body: serde_json::Value = test::read_body_json(resp).await;
|
let body: serde_json::Value = test::read_body_json(resp).await;
|
||||||
assert_eq!(body["id"], json!(alpha_project_id));
|
assert_eq!(body["id"], json!(alpha_project_id));
|
||||||
@@ -84,11 +85,11 @@ async fn test_get_project() {
|
|||||||
|
|
||||||
// Request should fail on non-existent project
|
// Request should fail on non-existent project
|
||||||
let resp = api.get_project("nonexistent", USER_USER_PAT).await;
|
let resp = api.get_project("nonexistent", USER_USER_PAT).await;
|
||||||
assert_eq!(resp.status(), 404);
|
assert_status(&resp, StatusCode::NOT_FOUND);
|
||||||
|
|
||||||
// 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)
|
// 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 resp = api.get_project(beta_project_id, ENEMY_USER_PAT).await;
|
let resp = api.get_project(beta_project_id, ENEMY_USER_PAT).await;
|
||||||
assert_eq!(resp.status(), 404);
|
assert_status(&resp, StatusCode::NOT_FOUND);
|
||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
@@ -170,8 +171,7 @@ async fn test_add_remove_project() {
|
|||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
let status = resp.status();
|
assert_status(&resp, StatusCode::OK);
|
||||||
assert_eq!(status, 200);
|
|
||||||
|
|
||||||
// Get the project we just made, and confirm that it's correct
|
// Get the project we just made, and confirm that it's correct
|
||||||
let project = api
|
let project = api
|
||||||
@@ -204,7 +204,7 @@ async fn test_add_remove_project() {
|
|||||||
USER_USER_PAT,
|
USER_USER_PAT,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 400);
|
assert_status(&resp, StatusCode::BAD_REQUEST);
|
||||||
|
|
||||||
// Reusing with the same slug and a different file should fail
|
// Reusing with the same slug and a different file should fail
|
||||||
let resp = api
|
let resp = api
|
||||||
@@ -220,7 +220,7 @@ async fn test_add_remove_project() {
|
|||||||
USER_USER_PAT,
|
USER_USER_PAT,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 400);
|
assert_status(&resp, StatusCode::BAD_REQUEST);
|
||||||
|
|
||||||
// Different slug, different file should succeed
|
// Different slug, different file should succeed
|
||||||
let resp = api
|
let resp = api
|
||||||
@@ -236,7 +236,7 @@ async fn test_add_remove_project() {
|
|||||||
USER_USER_PAT,
|
USER_USER_PAT,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
|
|
||||||
// Get
|
// Get
|
||||||
let project = api
|
let project = api
|
||||||
@@ -246,7 +246,7 @@ async fn test_add_remove_project() {
|
|||||||
|
|
||||||
// Remove the project
|
// Remove the project
|
||||||
let resp = test_env.api.remove_project("demo", USER_USER_PAT).await;
|
let resp = test_env.api.remove_project("demo", USER_USER_PAT).await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
// Confirm that the project is gone from the cache
|
// Confirm that the project is gone from the cache
|
||||||
let mut redis_pool = test_env.db.redis_pool.connect().await.unwrap();
|
let mut redis_pool = test_env.db.redis_pool.connect().await.unwrap();
|
||||||
@@ -269,7 +269,7 @@ async fn test_add_remove_project() {
|
|||||||
|
|
||||||
// Old slug no longer works
|
// Old slug no longer works
|
||||||
let resp = api.get_project("demo", USER_USER_PAT).await;
|
let resp = api.get_project("demo", USER_USER_PAT).await;
|
||||||
assert_eq!(resp.status(), 404);
|
assert_status(&resp, StatusCode::NOT_FOUND);
|
||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
@@ -293,7 +293,7 @@ pub async fn test_patch_project() {
|
|||||||
ENEMY_USER_PAT,
|
ENEMY_USER_PAT,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 401);
|
assert_status(&resp, StatusCode::UNAUTHORIZED);
|
||||||
|
|
||||||
// Failure because we are setting URL fields to invalid urls.
|
// Failure because we are setting URL fields to invalid urls.
|
||||||
for url_type in ["issues", "source", "wiki", "discord"] {
|
for url_type in ["issues", "source", "wiki", "discord"] {
|
||||||
@@ -308,7 +308,7 @@ pub async fn test_patch_project() {
|
|||||||
USER_USER_PAT,
|
USER_USER_PAT,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 400);
|
assert_status(&resp, StatusCode::BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Failure because these are illegal requested statuses for a normal user.
|
// Failure because these are illegal requested statuses for a normal user.
|
||||||
@@ -322,7 +322,7 @@ pub async fn test_patch_project() {
|
|||||||
USER_USER_PAT,
|
USER_USER_PAT,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 400);
|
assert_status(&resp, StatusCode::BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Failure because these should not be able to be set by a non-mod
|
// Failure because these should not be able to be set by a non-mod
|
||||||
@@ -336,7 +336,7 @@ pub async fn test_patch_project() {
|
|||||||
USER_USER_PAT,
|
USER_USER_PAT,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 401);
|
assert_status(&resp, StatusCode::UNAUTHORIZED);
|
||||||
|
|
||||||
// (should work for a mod, though)
|
// (should work for a mod, though)
|
||||||
let resp = api
|
let resp = api
|
||||||
@@ -348,7 +348,7 @@ pub async fn test_patch_project() {
|
|||||||
MOD_USER_PAT,
|
MOD_USER_PAT,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Failed patch to alpha slug:
|
// Failed patch to alpha slug:
|
||||||
@@ -372,7 +372,7 @@ pub async fn test_patch_project() {
|
|||||||
USER_USER_PAT,
|
USER_USER_PAT,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 400);
|
assert_status(&resp, StatusCode::BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not allowed to directly set status, as 'beta_project_slug' (the other project) is "processing" and cannot have its status changed like this.
|
// Not allowed to directly set status, as 'beta_project_slug' (the other project) is "processing" and cannot have its status changed like this.
|
||||||
@@ -385,7 +385,7 @@ pub async fn test_patch_project() {
|
|||||||
USER_USER_PAT,
|
USER_USER_PAT,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 401);
|
assert_status(&resp, StatusCode::UNAUTHORIZED);
|
||||||
|
|
||||||
// Sucessful request to patch many fields.
|
// Sucessful request to patch many fields.
|
||||||
let resp = api
|
let resp = api
|
||||||
@@ -406,11 +406,11 @@ pub async fn test_patch_project() {
|
|||||||
USER_USER_PAT,
|
USER_USER_PAT,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
// Old slug no longer works
|
// Old slug no longer works
|
||||||
let resp = api.get_project(alpha_project_slug, USER_USER_PAT).await;
|
let resp = api.get_project(alpha_project_slug, USER_USER_PAT).await;
|
||||||
assert_eq!(resp.status(), 404);
|
assert_status(&resp, StatusCode::NOT_FOUND);
|
||||||
|
|
||||||
// New slug does work
|
// New slug does work
|
||||||
let project = api.get_project_deserialized("newslug", USER_USER_PAT).await;
|
let project = api.get_project_deserialized("newslug", USER_USER_PAT).await;
|
||||||
@@ -447,7 +447,7 @@ pub async fn test_patch_project() {
|
|||||||
USER_USER_PAT,
|
USER_USER_PAT,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
let project = api.get_project_deserialized("newslug", USER_USER_PAT).await;
|
let project = api.get_project_deserialized("newslug", USER_USER_PAT).await;
|
||||||
assert_eq!(project.link_urls.len(), 3);
|
assert_eq!(project.link_urls.len(), 3);
|
||||||
assert!(!project.link_urls.contains_key("issues"));
|
assert!(!project.link_urls.contains_key("issues"));
|
||||||
@@ -475,7 +475,7 @@ pub async fn test_patch_v3() {
|
|||||||
USER_USER_PAT,
|
USER_USER_PAT,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
let project = api
|
let project = api
|
||||||
.get_project_deserialized(alpha_project_slug, USER_USER_PAT)
|
.get_project_deserialized(alpha_project_slug, USER_USER_PAT)
|
||||||
@@ -509,7 +509,7 @@ pub async fn test_bulk_edit_categories() {
|
|||||||
ADMIN_USER_PAT,
|
ADMIN_USER_PAT,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), StatusCode::NO_CONTENT);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
let alpha_body = api
|
let alpha_body = api
|
||||||
.get_project_deserialized_common(alpha_project_id, ADMIN_USER_PAT)
|
.get_project_deserialized_common(alpha_project_id, ADMIN_USER_PAT)
|
||||||
@@ -552,7 +552,7 @@ pub async fn test_bulk_edit_links() {
|
|||||||
ADMIN_USER_PAT,
|
ADMIN_USER_PAT,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), StatusCode::NO_CONTENT);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
let alpha_body = api
|
let alpha_body = api
|
||||||
.get_project_deserialized(alpha_project_id, ADMIN_USER_PAT)
|
.get_project_deserialized(alpha_project_id, ADMIN_USER_PAT)
|
||||||
@@ -597,7 +597,7 @@ async fn delete_project_with_report() {
|
|||||||
ENEMY_USER_PAT, // Enemy makes a report
|
ENEMY_USER_PAT, // Enemy makes a report
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), StatusCode::OK);
|
assert_status(&resp, StatusCode::OK);
|
||||||
let value = test::read_body_json::<serde_json::Value, _>(resp).await;
|
let value = test::read_body_json::<serde_json::Value, _>(resp).await;
|
||||||
let alpha_report_id = value["id"].as_str().unwrap();
|
let alpha_report_id = value["id"].as_str().unwrap();
|
||||||
|
|
||||||
@@ -608,7 +608,7 @@ async fn delete_project_with_report() {
|
|||||||
ENEMY_USER_PAT, // Enemy makes a report
|
ENEMY_USER_PAT, // Enemy makes a report
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), StatusCode::OK);
|
assert_status(&resp, StatusCode::OK);
|
||||||
|
|
||||||
// Do the same for beta
|
// Do the same for beta
|
||||||
let resp = api
|
let resp = api
|
||||||
@@ -620,13 +620,13 @@ async fn delete_project_with_report() {
|
|||||||
ENEMY_USER_PAT, // Enemy makes a report
|
ENEMY_USER_PAT, // Enemy makes a report
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), StatusCode::OK);
|
assert_status(&resp, StatusCode::OK);
|
||||||
let value = test::read_body_json::<serde_json::Value, _>(resp).await;
|
let value = test::read_body_json::<serde_json::Value, _>(resp).await;
|
||||||
let beta_report_id = value["id"].as_str().unwrap();
|
let beta_report_id = value["id"].as_str().unwrap();
|
||||||
|
|
||||||
// Delete the project
|
// Delete the project
|
||||||
let resp = api.remove_project(alpha_project_id, USER_USER_PAT).await;
|
let resp = api.remove_project(alpha_project_id, USER_USER_PAT).await;
|
||||||
assert_eq!(resp.status(), StatusCode::NO_CONTENT);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
// Confirm that the project is gone from the cache
|
// Confirm that the project is gone from the cache
|
||||||
let mut redis_pool = test_env.db.redis_pool.connect().await.unwrap();
|
let mut redis_pool = test_env.db.redis_pool.connect().await.unwrap();
|
||||||
@@ -654,7 +654,7 @@ async fn delete_project_with_report() {
|
|||||||
ENEMY_USER_PAT, // Enemy makes a report
|
ENEMY_USER_PAT, // Enemy makes a report
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), StatusCode::NOT_FOUND);
|
assert_status(&resp, StatusCode::NOT_FOUND);
|
||||||
|
|
||||||
// Confirm that report for beta still exists
|
// Confirm that report for beta still exists
|
||||||
let resp = api
|
let resp = api
|
||||||
@@ -663,7 +663,7 @@ async fn delete_project_with_report() {
|
|||||||
ENEMY_USER_PAT, // Enemy makes a report
|
ENEMY_USER_PAT, // Enemy makes a report
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), StatusCode::OK);
|
assert_status(&resp, StatusCode::OK);
|
||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
@@ -815,7 +815,7 @@ async fn permissions_patch_project_v3() {
|
|||||||
// MOD_USER_PAT,
|
// MOD_USER_PAT,
|
||||||
// )
|
// )
|
||||||
// .await;
|
// .await;
|
||||||
// assert_eq!(resp.status(), 204);
|
// assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
// // Schedule version
|
// // Schedule version
|
||||||
// let req_gen = |ctx: PermissionsTestContext| async move {
|
// let req_gen = |ctx: PermissionsTestContext| async move {
|
||||||
@@ -839,7 +839,7 @@ async fn permissions_patch_project_v3() {
|
|||||||
// Not covered by PATCH /project
|
// Not covered by PATCH /project
|
||||||
#[actix_rt::test]
|
#[actix_rt::test]
|
||||||
async fn permissions_edit_details() {
|
async fn permissions_edit_details() {
|
||||||
with_test_environment_all(None, |test_env| async move {
|
with_test_environment_all(Some(10), |test_env| async move {
|
||||||
let DummyProjectAlpha {
|
let DummyProjectAlpha {
|
||||||
project_id: alpha_project_id,
|
project_id: alpha_project_id,
|
||||||
team_id: alpha_team_id,
|
team_id: alpha_team_id,
|
||||||
@@ -1112,11 +1112,11 @@ async fn permissions_manage_invites() {
|
|||||||
ADMIN_USER_PAT,
|
ADMIN_USER_PAT,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
// Accept invite
|
// Accept invite
|
||||||
let resp = api.join_team(alpha_team_id, MOD_USER_PAT).await;
|
let resp = api.join_team(alpha_team_id, MOD_USER_PAT).await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
// remove existing member (requires remove_member)
|
// remove existing member (requires remove_member)
|
||||||
let remove_member = ProjectPermissions::REMOVE_MEMBER;
|
let remove_member = ProjectPermissions::REMOVE_MEMBER;
|
||||||
@@ -1223,7 +1223,7 @@ async fn align_search_projects() {
|
|||||||
let project_model = api
|
let project_model = api
|
||||||
.get_project(&project.id.to_string(), USER_USER_PAT)
|
.get_project(&project.id.to_string(), USER_USER_PAT)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(project_model.status(), 200);
|
assert_status(&project_model, StatusCode::OK);
|
||||||
let mut project_model: Project = test::read_body_json(project_model).await;
|
let mut project_model: Project = test::read_body_json(project_model).await;
|
||||||
|
|
||||||
// Body/description is huge- don't store it in search, so it's OK if they differ here
|
// Body/description is huge- don't store it in search, so it's OK if they differ here
|
||||||
@@ -1233,9 +1233,24 @@ async fn align_search_projects() {
|
|||||||
// Aggregate project loader fields will not match exactly,
|
// Aggregate project loader fields will not match exactly,
|
||||||
// because the search will only return the matching version, whereas the project returns the aggregate.
|
// because the search will only return the matching version, whereas the project returns the aggregate.
|
||||||
// So, we remove them from both.
|
// So, we remove them from both.
|
||||||
|
let project_model_mrpack_loaders: Vec<_> = project_model
|
||||||
|
.fields
|
||||||
|
.remove("mrpack_loaders")
|
||||||
|
.unwrap_or_default()
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|v| v.as_str().map(|v| v.to_string()))
|
||||||
|
.collect();
|
||||||
project_model.fields = HashMap::new();
|
project_model.fields = HashMap::new();
|
||||||
project.fields = HashMap::new();
|
project.fields = HashMap::new();
|
||||||
|
|
||||||
|
// For a similar reason we also remove the mrpack loaders from the additional categories of the search model
|
||||||
|
// (Becasue they are not returned by the search)
|
||||||
|
// TODO: get models to match *exactly* without an additional project fetch,
|
||||||
|
// including these fields removed here
|
||||||
|
project
|
||||||
|
.additional_categories
|
||||||
|
.retain(|x| !project_model_mrpack_loaders.contains(x));
|
||||||
|
|
||||||
let project_model = serde_json::to_value(project_model).unwrap();
|
let project_model = serde_json::to_value(project_model).unwrap();
|
||||||
let searched_project_serialized = serde_json::to_value(project).unwrap();
|
let searched_project_serialized = serde_json::to_value(project).unwrap();
|
||||||
assert_eq!(project_model, searched_project_serialized);
|
assert_eq!(project_model, searched_project_serialized);
|
||||||
@@ -1244,6 +1259,129 @@ async fn align_search_projects() {
|
|||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[actix_rt::test]
|
||||||
|
async fn projects_various_visibility() {
|
||||||
|
// For testing the filter_visible_projects and is_visible_project
|
||||||
|
with_test_environment(
|
||||||
|
None,
|
||||||
|
|env: common::environment::TestEnvironment<ApiV3>| async move {
|
||||||
|
let DummyProjectAlpha {
|
||||||
|
project_id: alpha_project_id,
|
||||||
|
project_id_parsed: alpha_project_id_parsed,
|
||||||
|
..
|
||||||
|
} = &env.dummy.project_alpha;
|
||||||
|
let DummyProjectBeta {
|
||||||
|
project_id: beta_project_id,
|
||||||
|
project_id_parsed: beta_project_id_parsed,
|
||||||
|
..
|
||||||
|
} = &env.dummy.project_beta;
|
||||||
|
let DummyOrganizationZeta {
|
||||||
|
organization_id: zeta_organization_id,
|
||||||
|
team_id: zeta_team_id,
|
||||||
|
..
|
||||||
|
} = &env.dummy.organization_zeta;
|
||||||
|
|
||||||
|
// Invite friend to org zeta and accept it
|
||||||
|
let resp = env
|
||||||
|
.api
|
||||||
|
.add_user_to_team(
|
||||||
|
zeta_team_id,
|
||||||
|
FRIEND_USER_ID,
|
||||||
|
Some(ProjectPermissions::empty()),
|
||||||
|
None,
|
||||||
|
USER_USER_PAT,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
let resp = env.api.join_team(zeta_team_id, FRIEND_USER_PAT).await;
|
||||||
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
|
let visible_pat_pairs = vec![
|
||||||
|
(&alpha_project_id_parsed, USER_USER_PAT, StatusCode::OK),
|
||||||
|
(&alpha_project_id_parsed, FRIEND_USER_PAT, StatusCode::OK),
|
||||||
|
(&alpha_project_id_parsed, ENEMY_USER_PAT, StatusCode::OK),
|
||||||
|
(&beta_project_id_parsed, USER_USER_PAT, StatusCode::OK),
|
||||||
|
(
|
||||||
|
&beta_project_id_parsed,
|
||||||
|
FRIEND_USER_PAT,
|
||||||
|
StatusCode::NOT_FOUND,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
&beta_project_id_parsed,
|
||||||
|
ENEMY_USER_PAT,
|
||||||
|
StatusCode::NOT_FOUND,
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
// Tests get_project, a route that uses is_visible_project
|
||||||
|
for (project_id, pat, expected_status) in visible_pat_pairs {
|
||||||
|
let resp = env.api.get_project(&project_id.to_string(), pat).await;
|
||||||
|
assert_status(&resp, expected_status);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test get_user_projects, a route that uses filter_visible_projects
|
||||||
|
let visible_pat_pairs = vec![
|
||||||
|
(USER_USER_PAT, 2),
|
||||||
|
(FRIEND_USER_PAT, 1),
|
||||||
|
(ENEMY_USER_PAT, 1),
|
||||||
|
];
|
||||||
|
for (pat, expected_count) in visible_pat_pairs {
|
||||||
|
let projects = env
|
||||||
|
.api
|
||||||
|
.get_user_projects_deserialized_common(USER_USER_ID, pat)
|
||||||
|
.await;
|
||||||
|
assert_eq!(projects.len(), expected_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add projects to org zeta
|
||||||
|
let resp = env
|
||||||
|
.api
|
||||||
|
.organization_add_project(zeta_organization_id, alpha_project_id, USER_USER_PAT)
|
||||||
|
.await;
|
||||||
|
assert_status(&resp, StatusCode::OK);
|
||||||
|
let resp = env
|
||||||
|
.api
|
||||||
|
.organization_add_project(zeta_organization_id, beta_project_id, USER_USER_PAT)
|
||||||
|
.await;
|
||||||
|
assert_status(&resp, StatusCode::OK);
|
||||||
|
|
||||||
|
// Test get_project, a route that uses is_visible_project
|
||||||
|
let visible_pat_pairs = vec![
|
||||||
|
(&alpha_project_id_parsed, USER_USER_PAT, StatusCode::OK),
|
||||||
|
(&alpha_project_id_parsed, FRIEND_USER_PAT, StatusCode::OK),
|
||||||
|
(&alpha_project_id_parsed, ENEMY_USER_PAT, StatusCode::OK),
|
||||||
|
(&beta_project_id_parsed, USER_USER_PAT, StatusCode::OK),
|
||||||
|
(&beta_project_id_parsed, FRIEND_USER_PAT, StatusCode::OK),
|
||||||
|
(
|
||||||
|
&beta_project_id_parsed,
|
||||||
|
ENEMY_USER_PAT,
|
||||||
|
StatusCode::NOT_FOUND,
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
for (project_id, pat, expected_status) in visible_pat_pairs {
|
||||||
|
let resp = env.api.get_project(&project_id.to_string(), pat).await;
|
||||||
|
assert_status(&resp, expected_status);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test get_user_projects, a route that uses filter_visible_projects
|
||||||
|
let visible_pat_pairs = vec![
|
||||||
|
(USER_USER_PAT, 2),
|
||||||
|
(FRIEND_USER_PAT, 2),
|
||||||
|
(ENEMY_USER_PAT, 1),
|
||||||
|
];
|
||||||
|
for (pat, expected_count) in visible_pat_pairs {
|
||||||
|
let projects = env
|
||||||
|
.api
|
||||||
|
.get_user_projects_deserialized_common(USER_USER_ID, pat)
|
||||||
|
.await;
|
||||||
|
assert_eq!(projects.len(), expected_count);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
|
||||||
// Route tests:
|
// Route tests:
|
||||||
// TODO: Missing routes on projects
|
// TODO: Missing routes on projects
|
||||||
// TODO: using permissions/scopes, can we SEE projects existence that we are not allowed to? (ie 401 instead of 404)
|
// TODO: using permissions/scopes, can we SEE projects existence that we are not allowed to? (ie 401 instead of 404)
|
||||||
|
|||||||
@@ -2,12 +2,14 @@ use std::collections::HashMap;
|
|||||||
|
|
||||||
use crate::common::api_common::{ApiProject, ApiTeams, ApiUser, ApiVersion, AppendsOptionalPat};
|
use crate::common::api_common::{ApiProject, ApiTeams, ApiUser, ApiVersion, AppendsOptionalPat};
|
||||||
use crate::common::dummy_data::{DummyImage, DummyProjectAlpha, DummyProjectBeta};
|
use crate::common::dummy_data::{DummyImage, DummyProjectAlpha, DummyProjectBeta};
|
||||||
|
use actix_http::StatusCode;
|
||||||
use actix_web::test;
|
use actix_web::test;
|
||||||
use chrono::{Duration, Utc};
|
use chrono::{Duration, Utc};
|
||||||
use common::api_common::models::CommonItemType;
|
use common::api_common::models::CommonItemType;
|
||||||
use common::api_common::Api;
|
use common::api_common::Api;
|
||||||
use common::api_v3::request_data::get_public_project_creation_data;
|
use common::api_v3::request_data::get_public_project_creation_data;
|
||||||
use common::api_v3::ApiV3;
|
use common::api_v3::ApiV3;
|
||||||
|
use common::asserts::assert_status;
|
||||||
use common::dummy_data::TestFile;
|
use common::dummy_data::TestFile;
|
||||||
use common::environment::{with_test_environment, with_test_environment_all, TestEnvironment};
|
use common::environment::{with_test_environment, with_test_environment_all, TestEnvironment};
|
||||||
use common::{database::*, scopes::ScopeTest};
|
use common::{database::*, scopes::ScopeTest};
|
||||||
@@ -114,7 +116,7 @@ pub async fn notifications_scopes() {
|
|||||||
.api
|
.api
|
||||||
.add_user_to_team(alpha_team_id, FRIEND_USER_ID, None, None, USER_USER_PAT)
|
.add_user_to_team(alpha_team_id, FRIEND_USER_ID, None, None, USER_USER_PAT)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
// Notification get
|
// Notification get
|
||||||
let read_notifications = Scopes::NOTIFICATION_READ;
|
let read_notifications = Scopes::NOTIFICATION_READ;
|
||||||
@@ -187,7 +189,7 @@ pub async fn notifications_scopes() {
|
|||||||
.api
|
.api
|
||||||
.add_user_to_team(alpha_team_id, MOD_USER_ID, None, None, USER_USER_PAT)
|
.add_user_to_team(alpha_team_id, MOD_USER_ID, None, None, USER_USER_PAT)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
let read_notifications = Scopes::NOTIFICATION_READ;
|
let read_notifications = Scopes::NOTIFICATION_READ;
|
||||||
let req_gen = |pat: Option<String>| async move {
|
let req_gen = |pat: Option<String>| async move {
|
||||||
api.get_user_notifications(MOD_USER_ID, pat.as_deref())
|
api.get_user_notifications(MOD_USER_ID, pat.as_deref())
|
||||||
@@ -386,7 +388,7 @@ pub async fn project_version_reads_scopes() {
|
|||||||
.api
|
.api
|
||||||
.edit_version(beta_version_id, json!({ "status": "draft" }), USER_USER_PAT)
|
.edit_version(beta_version_id, json!({ "status": "draft" }), USER_USER_PAT)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
let req_gen = |pat: Option<String>| async move {
|
let req_gen = |pat: Option<String>| async move {
|
||||||
api.get_version_from_hash(beta_file_hash, "sha1", pat.as_deref())
|
api.get_version_from_hash(beta_file_hash, "sha1", pat.as_deref())
|
||||||
@@ -1084,7 +1086,7 @@ pub async fn organization_scopes() {
|
|||||||
// Create organization
|
// Create organization
|
||||||
let organization_create = Scopes::ORGANIZATION_CREATE;
|
let organization_create = Scopes::ORGANIZATION_CREATE;
|
||||||
let req_gen = |pat: Option<String>| async move {
|
let req_gen = |pat: Option<String>| async move {
|
||||||
api.create_organization("TestOrg", "TestOrg Description", pat.as_deref())
|
api.create_organization("Test Org", "TestOrg", "TestOrg Description", pat.as_deref())
|
||||||
.await
|
.await
|
||||||
};
|
};
|
||||||
let (_, success) = ScopeTest::new(&test_env)
|
let (_, success) = ScopeTest::new(&test_env)
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use crate::common::{api_common::ApiTeams, database::*};
|
use crate::common::{api_common::ApiTeams, asserts::assert_status, database::*};
|
||||||
|
use actix_http::StatusCode;
|
||||||
use common::{
|
use common::{
|
||||||
api_v3::ApiV3,
|
api_v3::ApiV3,
|
||||||
environment::{with_test_environment, with_test_environment_all, TestEnvironment},
|
environment::{with_test_environment, with_test_environment_all, TestEnvironment},
|
||||||
@@ -39,7 +40,7 @@ async fn test_get_team() {
|
|||||||
let resp = api
|
let resp = api
|
||||||
.add_user_to_team(alpha_team_id, FRIEND_USER_ID, None, None, USER_USER_PAT)
|
.add_user_to_team(alpha_team_id, FRIEND_USER_ID, None, None, USER_USER_PAT)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
// Team check directly
|
// Team check directly
|
||||||
let members = api
|
let members = api
|
||||||
@@ -92,7 +93,7 @@ async fn test_get_team() {
|
|||||||
// An accepted member of the team should appear in the team members list
|
// An accepted member of the team should appear in the team members list
|
||||||
// and should be able to see private data about the team
|
// and should be able to see private data about the team
|
||||||
let resp = api.join_team(alpha_team_id, FRIEND_USER_PAT).await;
|
let resp = api.join_team(alpha_team_id, FRIEND_USER_PAT).await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
// Team check directly
|
// Team check directly
|
||||||
let members = api
|
let members = api
|
||||||
@@ -163,7 +164,7 @@ async fn test_get_team_organization() {
|
|||||||
let resp = api
|
let resp = api
|
||||||
.add_user_to_team(zeta_team_id, FRIEND_USER_ID, None, None, USER_USER_PAT)
|
.add_user_to_team(zeta_team_id, FRIEND_USER_ID, None, None, USER_USER_PAT)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
// Team check directly
|
// Team check directly
|
||||||
let members = api
|
let members = api
|
||||||
@@ -217,7 +218,7 @@ async fn test_get_team_organization() {
|
|||||||
// An accepted member of the team should appear in the team members list
|
// An accepted member of the team should appear in the team members list
|
||||||
// and should be able to see private data about the team
|
// and should be able to see private data about the team
|
||||||
let resp = api.join_team(zeta_team_id, FRIEND_USER_PAT).await;
|
let resp = api.join_team(zeta_team_id, FRIEND_USER_PAT).await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
// Team check directly
|
// Team check directly
|
||||||
let members = api
|
let members = api
|
||||||
@@ -272,17 +273,17 @@ async fn test_get_team_project_orgs() {
|
|||||||
.api
|
.api
|
||||||
.organization_add_project(zeta_organization_id, alpha_project_id, USER_USER_PAT)
|
.organization_add_project(zeta_organization_id, alpha_project_id, USER_USER_PAT)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
|
|
||||||
// Invite and add friend to zeta
|
// Invite and add friend to zeta
|
||||||
let resp = test_env
|
let resp = test_env
|
||||||
.api
|
.api
|
||||||
.add_user_to_team(zeta_team_id, FRIEND_USER_ID, None, None, USER_USER_PAT)
|
.add_user_to_team(zeta_team_id, FRIEND_USER_ID, None, None, USER_USER_PAT)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
let resp = test_env.api.join_team(zeta_team_id, FRIEND_USER_PAT).await;
|
let resp = test_env.api.join_team(zeta_team_id, FRIEND_USER_PAT).await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
// The team members route from teams (on a project's team):
|
// The team members route from teams (on a project's team):
|
||||||
// - the members of the project team specifically
|
// - the members of the project team specifically
|
||||||
@@ -315,19 +316,19 @@ async fn test_patch_project_team_member() {
|
|||||||
|
|
||||||
// Edit team as admin/mod but not a part of the team should be OK
|
// 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;
|
let resp = api.edit_team_member(alpha_team_id, USER_USER_ID, json!({}), ADMIN_USER_PAT).await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
// As a non-owner with full permissions, attempt to edit the owner's permissions
|
// As a non-owner with full permissions, attempt to edit the owner's permissions
|
||||||
let resp = api.edit_team_member(alpha_team_id, USER_USER_ID, json!({
|
let resp = api.edit_team_member(alpha_team_id, USER_USER_ID, json!({
|
||||||
"permissions": 0
|
"permissions": 0
|
||||||
}), ADMIN_USER_PAT).await;
|
}), ADMIN_USER_PAT).await;
|
||||||
assert_eq!(resp.status(), 400);
|
assert_status(&resp, StatusCode::BAD_REQUEST);
|
||||||
|
|
||||||
// Should not be able to edit organization permissions of a project team
|
// Should not be able to edit organization permissions of a project team
|
||||||
let resp = api.edit_team_member(alpha_team_id, USER_USER_ID, json!({
|
let resp = api.edit_team_member(alpha_team_id, USER_USER_ID, json!({
|
||||||
"organization_permissions": 0
|
"organization_permissions": 0
|
||||||
}), USER_USER_PAT).await;
|
}), USER_USER_PAT).await;
|
||||||
assert_eq!(resp.status(), 400);
|
assert_status(&resp, StatusCode::BAD_REQUEST);
|
||||||
|
|
||||||
// Should not be able to add permissions to a user that the adding-user does not have
|
// Should not be able to add permissions to a user that the adding-user does not have
|
||||||
// (true for both project and org)
|
// (true for both project and org)
|
||||||
@@ -336,24 +337,24 @@ async fn test_patch_project_team_member() {
|
|||||||
let resp = api.add_user_to_team(alpha_team_id, FRIEND_USER_ID,
|
let resp = api.add_user_to_team(alpha_team_id, FRIEND_USER_ID,
|
||||||
Some(ProjectPermissions::EDIT_MEMBER | ProjectPermissions::EDIT_BODY),
|
Some(ProjectPermissions::EDIT_MEMBER | ProjectPermissions::EDIT_BODY),
|
||||||
None, USER_USER_PAT).await;
|
None, USER_USER_PAT).await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
// accept
|
// accept
|
||||||
let resp = api.join_team(alpha_team_id, FRIEND_USER_PAT).await;
|
let resp = api.join_team(alpha_team_id, FRIEND_USER_PAT).await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
// try to add permissions
|
// try to add permissions
|
||||||
let resp = api.edit_team_member(alpha_team_id, FRIEND_USER_ID, json!({
|
let resp = api.edit_team_member(alpha_team_id, FRIEND_USER_ID, json!({
|
||||||
"permissions": (ProjectPermissions::EDIT_MEMBER | ProjectPermissions::EDIT_DETAILS).bits()
|
"permissions": (ProjectPermissions::EDIT_MEMBER | ProjectPermissions::EDIT_DETAILS).bits()
|
||||||
}), FRIEND_USER_PAT).await; // should this be friend_user_pat
|
}), FRIEND_USER_PAT).await; // should this be friend_user_pat
|
||||||
assert_eq!(resp.status(), 400);
|
assert_status(&resp, StatusCode::BAD_REQUEST);
|
||||||
|
|
||||||
// Cannot set payouts outside of 0 and 5000
|
// Cannot set payouts outside of 0 and 5000
|
||||||
for payout in [-1, 5001] {
|
for payout in [-1, 5001] {
|
||||||
let resp = api.edit_team_member(alpha_team_id, FRIEND_USER_ID, json!({
|
let resp = api.edit_team_member(alpha_team_id, FRIEND_USER_ID, json!({
|
||||||
"payouts_split": payout
|
"payouts_split": payout
|
||||||
}), USER_USER_PAT).await;
|
}), USER_USER_PAT).await;
|
||||||
assert_eq!(resp.status(), 400);
|
assert_status(&resp, StatusCode::BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Successful patch
|
// Successful patch
|
||||||
@@ -363,7 +364,7 @@ async fn test_patch_project_team_member() {
|
|||||||
"role": "membe2r",
|
"role": "membe2r",
|
||||||
"ordering": 5
|
"ordering": 5
|
||||||
}), FRIEND_USER_PAT).await;
|
}), FRIEND_USER_PAT).await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
// Check results
|
// Check results
|
||||||
let members = api.get_team_members_deserialized_common(alpha_team_id, FRIEND_USER_PAT).await;
|
let members = api.get_team_members_deserialized_common(alpha_team_id, FRIEND_USER_PAT).await;
|
||||||
@@ -387,14 +388,14 @@ async fn test_patch_organization_team_member() {
|
|||||||
.api
|
.api
|
||||||
.edit_team_member(zeta_team_id, USER_USER_ID, json!({}), ADMIN_USER_PAT)
|
.edit_team_member(zeta_team_id, USER_USER_ID, json!({}), ADMIN_USER_PAT)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
// As a non-owner with full permissions, attempt to edit the owner's permissions
|
// As a non-owner with full permissions, attempt to edit the owner's permissions
|
||||||
let resp = test_env
|
let resp = test_env
|
||||||
.api
|
.api
|
||||||
.edit_team_member(zeta_team_id, USER_USER_ID, json!({ "permissions": 0 }), ADMIN_USER_PAT)
|
.edit_team_member(zeta_team_id, USER_USER_ID, json!({ "permissions": 0 }), ADMIN_USER_PAT)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 400);
|
assert_status(&resp, StatusCode::BAD_REQUEST);
|
||||||
|
|
||||||
// Should not be able to add permissions to a user that the adding-user does not have
|
// Should not be able to add permissions to a user that the adding-user does not have
|
||||||
// (true for both project and org)
|
// (true for both project and org)
|
||||||
@@ -404,18 +405,18 @@ async fn test_patch_organization_team_member() {
|
|||||||
.api
|
.api
|
||||||
.add_user_to_team(zeta_team_id, FRIEND_USER_ID, None, Some(OrganizationPermissions::EDIT_MEMBER | OrganizationPermissions::EDIT_MEMBER_DEFAULT_PERMISSIONS), USER_USER_PAT)
|
.add_user_to_team(zeta_team_id, FRIEND_USER_ID, None, Some(OrganizationPermissions::EDIT_MEMBER | OrganizationPermissions::EDIT_MEMBER_DEFAULT_PERMISSIONS), USER_USER_PAT)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
// accept
|
// accept
|
||||||
let resp = test_env.api.join_team(zeta_team_id, FRIEND_USER_PAT).await;
|
let resp = test_env.api.join_team(zeta_team_id, FRIEND_USER_PAT).await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
// try to add permissions- fails, as we do not have EDIT_DETAILS
|
// try to add permissions- fails, as we do not have EDIT_DETAILS
|
||||||
let resp = test_env
|
let resp = test_env
|
||||||
.api
|
.api
|
||||||
.edit_team_member(zeta_team_id, FRIEND_USER_ID, json!({ "organization_permissions": (OrganizationPermissions::EDIT_MEMBER | OrganizationPermissions::EDIT_DETAILS).bits() }), FRIEND_USER_PAT)
|
.edit_team_member(zeta_team_id, FRIEND_USER_ID, json!({ "organization_permissions": (OrganizationPermissions::EDIT_MEMBER | OrganizationPermissions::EDIT_DETAILS).bits() }), FRIEND_USER_PAT)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 400);
|
assert_status(&resp, StatusCode::BAD_REQUEST);
|
||||||
|
|
||||||
// Cannot set payouts outside of 0 and 5000
|
// Cannot set payouts outside of 0 and 5000
|
||||||
for payout in [-1, 5001] {
|
for payout in [-1, 5001] {
|
||||||
@@ -423,7 +424,7 @@ async fn test_patch_organization_team_member() {
|
|||||||
.api
|
.api
|
||||||
.edit_team_member(zeta_team_id, FRIEND_USER_ID, json!({ "payouts_split": payout }), USER_USER_PAT)
|
.edit_team_member(zeta_team_id, FRIEND_USER_ID, json!({ "payouts_split": payout }), USER_USER_PAT)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 400);
|
assert_status(&resp, StatusCode::BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Successful patch
|
// Successful patch
|
||||||
@@ -442,7 +443,7 @@ async fn test_patch_organization_team_member() {
|
|||||||
FRIEND_USER_PAT,
|
FRIEND_USER_PAT,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
// Check results
|
// Check results
|
||||||
let members = test_env
|
let members = test_env
|
||||||
@@ -481,39 +482,39 @@ async fn transfer_ownership_v3() {
|
|||||||
let resp = api
|
let resp = api
|
||||||
.transfer_team_ownership(alpha_team_id, FRIEND_USER_ID, USER_USER_PAT)
|
.transfer_team_ownership(alpha_team_id, FRIEND_USER_ID, USER_USER_PAT)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 400);
|
assert_status(&resp, StatusCode::BAD_REQUEST);
|
||||||
let resp = api
|
let resp = api
|
||||||
.transfer_team_ownership(alpha_team_id, FRIEND_USER_ID, FRIEND_USER_PAT)
|
.transfer_team_ownership(alpha_team_id, FRIEND_USER_ID, FRIEND_USER_PAT)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 401);
|
assert_status(&resp, StatusCode::UNAUTHORIZED);
|
||||||
|
|
||||||
// first, invite friend
|
// first, invite friend
|
||||||
let resp = api
|
let resp = api
|
||||||
.add_user_to_team(alpha_team_id, FRIEND_USER_ID, None, None, USER_USER_PAT)
|
.add_user_to_team(alpha_team_id, FRIEND_USER_ID, None, None, USER_USER_PAT)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
// still cannot set friend as owner (not accepted)
|
// still cannot set friend as owner (not accepted)
|
||||||
let resp = api
|
let resp = api
|
||||||
.transfer_team_ownership(alpha_team_id, FRIEND_USER_ID, USER_USER_PAT)
|
.transfer_team_ownership(alpha_team_id, FRIEND_USER_ID, USER_USER_PAT)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 400);
|
assert_status(&resp, StatusCode::BAD_REQUEST);
|
||||||
|
|
||||||
// accept
|
// accept
|
||||||
let resp = api.join_team(alpha_team_id, FRIEND_USER_PAT).await;
|
let resp = api.join_team(alpha_team_id, FRIEND_USER_PAT).await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
// Cannot set ourselves as owner if we are not owner
|
// Cannot set ourselves as owner if we are not owner
|
||||||
let resp = api
|
let resp = api
|
||||||
.transfer_team_ownership(alpha_team_id, FRIEND_USER_ID, FRIEND_USER_PAT)
|
.transfer_team_ownership(alpha_team_id, FRIEND_USER_ID, FRIEND_USER_PAT)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 401);
|
assert_status(&resp, StatusCode::UNAUTHORIZED);
|
||||||
|
|
||||||
// Can set friend as owner
|
// Can set friend as owner
|
||||||
let resp = api
|
let resp = api
|
||||||
.transfer_team_ownership(alpha_team_id, FRIEND_USER_ID, USER_USER_PAT)
|
.transfer_team_ownership(alpha_team_id, FRIEND_USER_ID, USER_USER_PAT)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
// Check
|
// Check
|
||||||
let members = api
|
let members = api
|
||||||
@@ -542,7 +543,7 @@ async fn transfer_ownership_v3() {
|
|||||||
let resp = api
|
let resp = api
|
||||||
.remove_from_team(alpha_team_id, FRIEND_USER_ID, USER_USER_PAT)
|
.remove_from_team(alpha_team_id, FRIEND_USER_ID, USER_USER_PAT)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 401);
|
assert_status(&resp, StatusCode::UNAUTHORIZED);
|
||||||
|
|
||||||
// V3 only- confirm the owner can change their role without losing ownership
|
// V3 only- confirm the owner can change their role without losing ownership
|
||||||
let resp = api
|
let resp = api
|
||||||
@@ -555,7 +556,7 @@ async fn transfer_ownership_v3() {
|
|||||||
FRIEND_USER_PAT,
|
FRIEND_USER_PAT,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
let members = api
|
let members = api
|
||||||
.get_team_members_deserialized(alpha_team_id, USER_USER_PAT)
|
.get_team_members_deserialized(alpha_team_id, USER_USER_PAT)
|
||||||
@@ -588,25 +589,25 @@ async fn transfer_ownership_v3() {
|
|||||||
|
|
||||||
// // Link alpha team to zeta org
|
// // Link alpha team to zeta org
|
||||||
// let resp = api.organization_add_project(zeta_organization_id, alpha_project_id, USER_USER_PAT).await;
|
// let resp = api.organization_add_project(zeta_organization_id, alpha_project_id, USER_USER_PAT).await;
|
||||||
// assert_eq!(resp.status(), 200);
|
// assert_status(&resp, StatusCode::OK);
|
||||||
|
|
||||||
// // Invite friend to zeta team with all project default permissions
|
// // Invite friend to zeta team with all project default permissions
|
||||||
// let resp = api.add_user_to_team(&zeta_team_id, FRIEND_USER_ID, Some(ProjectPermissions::all()), Some(OrganizationPermissions::all()), USER_USER_PAT).await;
|
// let resp = api.add_user_to_team(&zeta_team_id, FRIEND_USER_ID, Some(ProjectPermissions::all()), Some(OrganizationPermissions::all()), USER_USER_PAT).await;
|
||||||
// assert_eq!(resp.status(), 204);
|
// assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
// // Accept invite to zeta team
|
// // Accept invite to zeta team
|
||||||
// let resp = api.join_team(&zeta_team_id, FRIEND_USER_PAT).await;
|
// let resp = api.join_team(&zeta_team_id, FRIEND_USER_PAT).await;
|
||||||
// assert_eq!(resp.status(), 204);
|
// assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
// // Attempt, as friend, to edit details of alpha project (should succeed, org invite accepted)
|
// // Attempt, as friend, to edit details of alpha project (should succeed, org invite accepted)
|
||||||
// let resp = api.edit_project(alpha_project_id, json!({
|
// let resp = api.edit_project(alpha_project_id, json!({
|
||||||
// "title": "new name"
|
// "title": "new name"
|
||||||
// }), FRIEND_USER_PAT).await;
|
// }), FRIEND_USER_PAT).await;
|
||||||
// assert_eq!(resp.status(), 204);
|
// assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
// // Invite friend to alpha team with *no* project permissions
|
// // Invite friend to alpha team with *no* project permissions
|
||||||
// let resp = api.add_user_to_team(&alpha_team_id, FRIEND_USER_ID, Some(ProjectPermissions::empty()), None, USER_USER_PAT).await;
|
// let resp = api.add_user_to_team(&alpha_team_id, FRIEND_USER_ID, Some(ProjectPermissions::empty()), None, USER_USER_PAT).await;
|
||||||
// assert_eq!(resp.status(), 204);
|
// assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
// // Do not accept invite to alpha team
|
// // Do not accept invite to alpha team
|
||||||
|
|
||||||
@@ -614,7 +615,7 @@ async fn transfer_ownership_v3() {
|
|||||||
// let resp = api.edit_project(alpha_project_id, json!({
|
// let resp = api.edit_project(alpha_project_id, json!({
|
||||||
// "title": "new name"
|
// "title": "new name"
|
||||||
// }), FRIEND_USER_PAT).await;
|
// }), FRIEND_USER_PAT).await;
|
||||||
// assert_eq!(resp.status(), 401);
|
// assert_status(&resp, StatusCode::UNAUTHORIZED);
|
||||||
|
|
||||||
// test_env.cleanup().await;
|
// test_env.cleanup().await;
|
||||||
// }
|
// }
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
use crate::common::api_common::ApiProject;
|
use crate::common::api_common::ApiProject;
|
||||||
|
use crate::common::asserts::assert_status;
|
||||||
|
use actix_http::StatusCode;
|
||||||
use actix_web::test;
|
use actix_web::test;
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
|
|
||||||
@@ -13,7 +15,7 @@ pub async fn error_404_empty() {
|
|||||||
// V2 errors should have 404 as blank body, for missing resources
|
// V2 errors should have 404 as blank body, for missing resources
|
||||||
let api = &test_env.api;
|
let api = &test_env.api;
|
||||||
let resp = api.get_project("does-not-exist", USER_USER_PAT).await;
|
let resp = api.get_project("does-not-exist", USER_USER_PAT).await;
|
||||||
assert_eq!(resp.status(), 404);
|
assert_status(&resp, StatusCode::NOT_FOUND);
|
||||||
let body = test::read_body(resp).await;
|
let body = test::read_body(resp).await;
|
||||||
let empty_bytes = Bytes::from_static(b"");
|
let empty_bytes = Bytes::from_static(b"");
|
||||||
assert_eq!(body, empty_bytes);
|
assert_eq!(body, empty_bytes);
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ use std::sync::Arc;
|
|||||||
use crate::common::{
|
use crate::common::{
|
||||||
api_common::{ApiProject, ApiVersion, AppendsOptionalPat},
|
api_common::{ApiProject, ApiVersion, AppendsOptionalPat},
|
||||||
api_v2::{request_data::get_public_project_creation_data_json, ApiV2},
|
api_v2::{request_data::get_public_project_creation_data_json, ApiV2},
|
||||||
|
asserts::assert_status,
|
||||||
database::{
|
database::{
|
||||||
generate_random_name, ADMIN_USER_PAT, FRIEND_USER_ID, FRIEND_USER_PAT, USER_USER_PAT,
|
generate_random_name, ADMIN_USER_PAT, FRIEND_USER_ID, FRIEND_USER_PAT, USER_USER_PAT,
|
||||||
},
|
},
|
||||||
@@ -132,10 +133,8 @@ async fn test_add_remove_project() {
|
|||||||
.append_pat(USER_USER_PAT)
|
.append_pat(USER_USER_PAT)
|
||||||
.set_multipart(vec![json_segment.clone(), file_segment.clone()])
|
.set_multipart(vec![json_segment.clone(), file_segment.clone()])
|
||||||
.to_request();
|
.to_request();
|
||||||
let resp = test_env.call(req).await;
|
let resp: actix_web::dev::ServiceResponse = test_env.call(req).await;
|
||||||
|
assert_status(&resp, StatusCode::OK);
|
||||||
let status = resp.status();
|
|
||||||
assert_eq!(status, 200);
|
|
||||||
|
|
||||||
// Get the project we just made, and confirm that it's correct
|
// Get the project we just made, and confirm that it's correct
|
||||||
let project = api.get_project_deserialized("demo", USER_USER_PAT).await;
|
let project = api.get_project_deserialized("demo", USER_USER_PAT).await;
|
||||||
@@ -163,7 +162,7 @@ async fn test_add_remove_project() {
|
|||||||
.to_request();
|
.to_request();
|
||||||
|
|
||||||
let resp = test_env.call(req).await;
|
let resp = test_env.call(req).await;
|
||||||
assert_eq!(resp.status(), 400);
|
assert_status(&resp, StatusCode::BAD_REQUEST);
|
||||||
|
|
||||||
// Reusing with the same slug and a different file should fail
|
// Reusing with the same slug and a different file should fail
|
||||||
let req = test::TestRequest::post()
|
let req = test::TestRequest::post()
|
||||||
@@ -176,7 +175,7 @@ async fn test_add_remove_project() {
|
|||||||
.to_request();
|
.to_request();
|
||||||
|
|
||||||
let resp = test_env.call(req).await;
|
let resp = test_env.call(req).await;
|
||||||
assert_eq!(resp.status(), 400);
|
assert_status(&resp, StatusCode::BAD_REQUEST);
|
||||||
|
|
||||||
// Different slug, different file should succeed
|
// Different slug, different file should succeed
|
||||||
let req = test::TestRequest::post()
|
let req = test::TestRequest::post()
|
||||||
@@ -189,7 +188,7 @@ async fn test_add_remove_project() {
|
|||||||
.to_request();
|
.to_request();
|
||||||
|
|
||||||
let resp = test_env.call(req).await;
|
let resp = test_env.call(req).await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
|
|
||||||
// Get
|
// Get
|
||||||
let project = api.get_project_deserialized("demo", USER_USER_PAT).await;
|
let project = api.get_project_deserialized("demo", USER_USER_PAT).await;
|
||||||
@@ -197,7 +196,7 @@ async fn test_add_remove_project() {
|
|||||||
|
|
||||||
// Remove the project
|
// Remove the project
|
||||||
let resp = test_env.api.remove_project("demo", USER_USER_PAT).await;
|
let resp = test_env.api.remove_project("demo", USER_USER_PAT).await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
// Confirm that the project is gone from the cache
|
// Confirm that the project is gone from the cache
|
||||||
let mut redis_conn = test_env.db.redis_pool.connect().await.unwrap();
|
let mut redis_conn = test_env.db.redis_pool.connect().await.unwrap();
|
||||||
@@ -220,7 +219,7 @@ async fn test_add_remove_project() {
|
|||||||
|
|
||||||
// Old slug no longer works
|
// Old slug no longer works
|
||||||
let resp = api.get_project("demo", USER_USER_PAT).await;
|
let resp = api.get_project("demo", USER_USER_PAT).await;
|
||||||
assert_eq!(resp.status(), 404);
|
assert_status(&resp, StatusCode::NOT_FOUND);
|
||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
@@ -344,7 +343,7 @@ pub async fn test_patch_v2() {
|
|||||||
USER_USER_PAT,
|
USER_USER_PAT,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
let project = api
|
let project = api
|
||||||
.get_project_deserialized(alpha_project_slug, USER_USER_PAT)
|
.get_project_deserialized(alpha_project_slug, USER_USER_PAT)
|
||||||
@@ -456,7 +455,7 @@ pub async fn test_bulk_edit_links() {
|
|||||||
ADMIN_USER_PAT,
|
ADMIN_USER_PAT,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), StatusCode::NO_CONTENT);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
let alpha_body = api
|
let alpha_body = api
|
||||||
.get_project_deserialized(alpha_project_id, ADMIN_USER_PAT)
|
.get_project_deserialized(alpha_project_id, ADMIN_USER_PAT)
|
||||||
@@ -496,7 +495,7 @@ pub async fn test_bulk_edit_links() {
|
|||||||
ADMIN_USER_PAT,
|
ADMIN_USER_PAT,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), StatusCode::NO_CONTENT);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
let alpha_body = api
|
let alpha_body = api
|
||||||
.get_project_deserialized(alpha_project_id, ADMIN_USER_PAT)
|
.get_project_deserialized(alpha_project_id, ADMIN_USER_PAT)
|
||||||
@@ -568,7 +567,7 @@ pub async fn test_bulk_edit_links() {
|
|||||||
ADMIN_USER_PAT,
|
ADMIN_USER_PAT,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), StatusCode::NO_CONTENT);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
let alpha_body = api
|
let alpha_body = api
|
||||||
.get_project_deserialized(alpha_project_id, ADMIN_USER_PAT)
|
.get_project_deserialized(alpha_project_id, ADMIN_USER_PAT)
|
||||||
|
|||||||
@@ -2,11 +2,13 @@ use crate::common::api_common::Api;
|
|||||||
use crate::common::api_common::ApiProject;
|
use crate::common::api_common::ApiProject;
|
||||||
use crate::common::api_common::ApiVersion;
|
use crate::common::api_common::ApiVersion;
|
||||||
use crate::common::api_v2::ApiV2;
|
use crate::common::api_v2::ApiV2;
|
||||||
|
use crate::common::asserts::assert_status;
|
||||||
use crate::common::database::*;
|
use crate::common::database::*;
|
||||||
use crate::common::dummy_data::TestFile;
|
use crate::common::dummy_data::TestFile;
|
||||||
use crate::common::dummy_data::DUMMY_CATEGORIES;
|
use crate::common::dummy_data::DUMMY_CATEGORIES;
|
||||||
use crate::common::environment::with_test_environment;
|
use crate::common::environment::with_test_environment;
|
||||||
use crate::common::environment::TestEnvironment;
|
use crate::common::environment::TestEnvironment;
|
||||||
|
use actix_http::StatusCode;
|
||||||
use futures::stream::StreamExt;
|
use futures::stream::StreamExt;
|
||||||
use labrinth::models::ids::base62_impl::parse_base62;
|
use labrinth::models::ids::base62_impl::parse_base62;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
@@ -53,7 +55,7 @@ async fn search_projects() {
|
|||||||
MOD_USER_PAT,
|
MOD_USER_PAT,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
(project.id.0, id)
|
(project.id.0, id)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -282,7 +284,7 @@ async fn search_projects() {
|
|||||||
|
|
||||||
// Forcibly reset the search index
|
// Forcibly reset the search index
|
||||||
let resp = api.reset_search_index().await;
|
let resp = api.reset_search_index().await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
// Test searches
|
// Test searches
|
||||||
let stream = futures::stream::iter(pairs);
|
let stream = futures::stream::iter(pairs);
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
|
use actix_http::StatusCode;
|
||||||
use labrinth::models::teams::ProjectPermissions;
|
use labrinth::models::teams::ProjectPermissions;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
|
|
||||||
use crate::common::{
|
use crate::common::{
|
||||||
api_common::ApiTeams,
|
api_common::ApiTeams,
|
||||||
api_v2::ApiV2,
|
api_v2::ApiV2,
|
||||||
|
asserts::assert_status,
|
||||||
database::{
|
database::{
|
||||||
FRIEND_USER_ID, FRIEND_USER_ID_PARSED, FRIEND_USER_PAT, USER_USER_ID_PARSED, USER_USER_PAT,
|
FRIEND_USER_ID, FRIEND_USER_ID_PARSED, FRIEND_USER_PAT, USER_USER_ID_PARSED, USER_USER_PAT,
|
||||||
},
|
},
|
||||||
@@ -23,35 +25,35 @@ async fn transfer_ownership_v2() {
|
|||||||
let resp = api
|
let resp = api
|
||||||
.transfer_team_ownership(alpha_team_id, FRIEND_USER_ID, USER_USER_PAT)
|
.transfer_team_ownership(alpha_team_id, FRIEND_USER_ID, USER_USER_PAT)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 400);
|
assert_status(&resp, StatusCode::BAD_REQUEST);
|
||||||
|
|
||||||
// first, invite friend
|
// first, invite friend
|
||||||
let resp = api
|
let resp = api
|
||||||
.add_user_to_team(alpha_team_id, FRIEND_USER_ID, None, None, USER_USER_PAT)
|
.add_user_to_team(alpha_team_id, FRIEND_USER_ID, None, None, USER_USER_PAT)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
// still cannot set friend as owner (not accepted)
|
// still cannot set friend as owner (not accepted)
|
||||||
let resp = api
|
let resp = api
|
||||||
.transfer_team_ownership(alpha_team_id, FRIEND_USER_ID, USER_USER_PAT)
|
.transfer_team_ownership(alpha_team_id, FRIEND_USER_ID, USER_USER_PAT)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 400);
|
assert_status(&resp, StatusCode::BAD_REQUEST);
|
||||||
|
|
||||||
// accept
|
// accept
|
||||||
let resp = api.join_team(alpha_team_id, FRIEND_USER_PAT).await;
|
let resp = api.join_team(alpha_team_id, FRIEND_USER_PAT).await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
// Cannot set ourselves as owner if we are not owner
|
// Cannot set ourselves as owner if we are not owner
|
||||||
let resp = api
|
let resp = api
|
||||||
.transfer_team_ownership(alpha_team_id, FRIEND_USER_ID, FRIEND_USER_PAT)
|
.transfer_team_ownership(alpha_team_id, FRIEND_USER_ID, FRIEND_USER_PAT)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 401);
|
assert_status(&resp, StatusCode::UNAUTHORIZED);
|
||||||
|
|
||||||
// Can set friend as owner
|
// Can set friend as owner
|
||||||
let resp = api
|
let resp = api
|
||||||
.transfer_team_ownership(alpha_team_id, FRIEND_USER_ID, USER_USER_PAT)
|
.transfer_team_ownership(alpha_team_id, FRIEND_USER_ID, USER_USER_PAT)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
// Check
|
// Check
|
||||||
let members = api
|
let members = api
|
||||||
@@ -78,7 +80,7 @@ async fn transfer_ownership_v2() {
|
|||||||
let resp = api
|
let resp = api
|
||||||
.remove_from_team(alpha_team_id, FRIEND_USER_ID, USER_USER_PAT)
|
.remove_from_team(alpha_team_id, FRIEND_USER_ID, USER_USER_PAT)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 401);
|
assert_status(&resp, StatusCode::UNAUTHORIZED);
|
||||||
|
|
||||||
// V2 only- confirm the owner changing the role to member does nothing
|
// V2 only- confirm the owner changing the role to member does nothing
|
||||||
let resp = api
|
let resp = api
|
||||||
@@ -91,7 +93,7 @@ async fn transfer_ownership_v2() {
|
|||||||
FRIEND_USER_PAT,
|
FRIEND_USER_PAT,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
let members = api
|
let members = api
|
||||||
.get_team_members_deserialized(alpha_team_id, USER_USER_PAT)
|
.get_team_members_deserialized(alpha_team_id, USER_USER_PAT)
|
||||||
.await;
|
.await;
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use actix_http::StatusCode;
|
||||||
use actix_web::test;
|
use actix_web::test;
|
||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
use labrinth::models::projects::VersionId;
|
use labrinth::models::projects::VersionId;
|
||||||
@@ -9,6 +10,7 @@ use serde_json::json;
|
|||||||
|
|
||||||
use crate::common::api_common::{ApiProject, ApiVersion};
|
use crate::common::api_common::{ApiProject, ApiVersion};
|
||||||
use crate::common::api_v2::ApiV2;
|
use crate::common::api_v2::ApiV2;
|
||||||
|
use crate::common::asserts::assert_status;
|
||||||
use crate::common::dummy_data::{DummyProjectAlpha, DummyProjectBeta};
|
use crate::common::dummy_data::{DummyProjectAlpha, DummyProjectBeta};
|
||||||
use crate::common::environment::{with_test_environment, TestEnvironment};
|
use crate::common::environment::{with_test_environment, TestEnvironment};
|
||||||
use crate::common::{
|
use crate::common::{
|
||||||
@@ -34,7 +36,7 @@ pub async fn test_patch_version() {
|
|||||||
ENEMY_USER_PAT,
|
ENEMY_USER_PAT,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 401);
|
assert_status(&resp, StatusCode::UNAUTHORIZED);
|
||||||
|
|
||||||
// Failure because these are illegal requested statuses for a normal user.
|
// Failure because these are illegal requested statuses for a normal user.
|
||||||
for req in ["unknown", "scheduled"] {
|
for req in ["unknown", "scheduled"] {
|
||||||
@@ -48,7 +50,7 @@ pub async fn test_patch_version() {
|
|||||||
USER_USER_PAT,
|
USER_USER_PAT,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 400);
|
assert_status(&resp, StatusCode::BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sucessful request to patch many fields.
|
// Sucessful request to patch many fields.
|
||||||
@@ -72,7 +74,7 @@ pub async fn test_patch_version() {
|
|||||||
USER_USER_PAT,
|
USER_USER_PAT,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
let version = api
|
let version = api
|
||||||
.get_version_deserialized(alpha_version_id, USER_USER_PAT)
|
.get_version_deserialized(alpha_version_id, USER_USER_PAT)
|
||||||
@@ -100,7 +102,7 @@ pub async fn test_patch_version() {
|
|||||||
USER_USER_PAT,
|
USER_USER_PAT,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
let version = api
|
let version = api
|
||||||
.get_version_deserialized(alpha_version_id, USER_USER_PAT)
|
.get_version_deserialized(alpha_version_id, USER_USER_PAT)
|
||||||
@@ -117,7 +119,7 @@ pub async fn test_patch_version() {
|
|||||||
USER_USER_PAT,
|
USER_USER_PAT,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
let version = api
|
let version = api
|
||||||
.get_version_deserialized(alpha_version_id, USER_USER_PAT)
|
.get_version_deserialized(alpha_version_id, USER_USER_PAT)
|
||||||
@@ -260,12 +262,12 @@ async fn version_updates() {
|
|||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
if success {
|
if success {
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
let body: serde_json::Value = test::read_body_json(resp).await;
|
let body: serde_json::Value = test::read_body_json(resp).await;
|
||||||
let id = body["id"].as_str().unwrap();
|
let id = body["id"].as_str().unwrap();
|
||||||
assert_eq!(id, &result_id.to_string());
|
assert_eq!(id, &result_id.to_string());
|
||||||
} else {
|
} else {
|
||||||
assert_eq!(resp.status(), 404);
|
assert_status(&resp, StatusCode::NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
// update_files
|
// update_files
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ async fn test_get_version() {
|
|||||||
|
|
||||||
// Request should fail on non-existent version
|
// Request should fail on non-existent version
|
||||||
let resp = api.get_version("false", USER_USER_PAT).await;
|
let resp = api.get_version("false", USER_USER_PAT).await;
|
||||||
assert_eq!(resp.status(), 404);
|
assert_status(&resp, StatusCode::NOT_FOUND);
|
||||||
|
|
||||||
// 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)
|
// 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)
|
||||||
// TODO: beta version should already be draft in dummy data, but theres a bug in finding it that
|
// TODO: beta version should already be draft in dummy data, but theres a bug in finding it that
|
||||||
@@ -74,9 +74,9 @@ async fn test_get_version() {
|
|||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
let resp = api.get_version(beta_version_id, USER_USER_PAT).await;
|
let resp = api.get_version(beta_version_id, USER_USER_PAT).await;
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
let resp = api.get_version(beta_version_id, ENEMY_USER_PAT).await;
|
let resp = api.get_version(beta_version_id, ENEMY_USER_PAT).await;
|
||||||
assert_eq!(resp.status(), 404);
|
assert_status(&resp, StatusCode::NOT_FOUND);
|
||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
@@ -219,12 +219,12 @@ async fn version_updates() {
|
|||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
if success {
|
if success {
|
||||||
assert_eq!(resp.status(), 200);
|
assert_status(&resp, StatusCode::OK);
|
||||||
let body: serde_json::Value = test::read_body_json(resp).await;
|
let body: serde_json::Value = test::read_body_json(resp).await;
|
||||||
let id = body["id"].as_str().unwrap();
|
let id = body["id"].as_str().unwrap();
|
||||||
assert_eq!(id, &result_id.to_string());
|
assert_eq!(id, &result_id.to_string());
|
||||||
} else {
|
} else {
|
||||||
assert_eq!(resp.status(), 404);
|
assert_status(&resp, StatusCode::NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
// update_files
|
// update_files
|
||||||
@@ -405,7 +405,7 @@ pub async fn test_patch_version() {
|
|||||||
ENEMY_USER_PAT,
|
ENEMY_USER_PAT,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 401);
|
assert_status(&resp, StatusCode::UNAUTHORIZED);
|
||||||
|
|
||||||
// Failure because these are illegal requested statuses for a normal user.
|
// Failure because these are illegal requested statuses for a normal user.
|
||||||
for req in ["unknown", "scheduled"] {
|
for req in ["unknown", "scheduled"] {
|
||||||
@@ -419,7 +419,7 @@ pub async fn test_patch_version() {
|
|||||||
USER_USER_PAT,
|
USER_USER_PAT,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 400);
|
assert_status(&resp, StatusCode::BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sucessful request to patch many fields.
|
// Sucessful request to patch many fields.
|
||||||
@@ -447,7 +447,7 @@ pub async fn test_patch_version() {
|
|||||||
USER_USER_PAT,
|
USER_USER_PAT,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
let version = api
|
let version = api
|
||||||
.get_version_deserialized_common(alpha_version_id, USER_USER_PAT)
|
.get_version_deserialized_common(alpha_version_id, USER_USER_PAT)
|
||||||
@@ -483,7 +483,7 @@ pub async fn test_patch_version() {
|
|||||||
USER_USER_PAT,
|
USER_USER_PAT,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
let version = api
|
let version = api
|
||||||
.get_version_deserialized_common(alpha_version_id, USER_USER_PAT)
|
.get_version_deserialized_common(alpha_version_id, USER_USER_PAT)
|
||||||
@@ -499,7 +499,7 @@ pub async fn test_patch_version() {
|
|||||||
USER_USER_PAT,
|
USER_USER_PAT,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(resp.status(), 204);
|
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||||
|
|
||||||
let version = api
|
let version = api
|
||||||
.get_version_deserialized_common(alpha_version_id, USER_USER_PAT)
|
.get_version_deserialized_common(alpha_version_id, USER_USER_PAT)
|
||||||
|
|||||||
Reference in New Issue
Block a user