Misc v3 linear tasks (#767)

* v3_reroute 404 error

* hash change

* fixed issue with error conversion

* added new model confirmation tests
+ title name change

* renaming, fields

* owner; test changes

* clippy prepare

* fmt

* merge fixes

* clippy

* working merge

* revs

* merge fixes
This commit is contained in:
Wyatt Verchere
2023-12-01 19:15:00 -08:00
committed by GitHub
parent 2d92b08404
commit a70df067bc
119 changed files with 2897 additions and 1334 deletions

View File

@@ -0,0 +1,272 @@
use super::ApiError;
use crate::database::redis::RedisPool;
use crate::routes::{v2_reroute, v3};
use crate::{models::ids::VersionId, queue::session::AuthQueue};
use actix_web::{get, web, HttpRequest, HttpResponse};
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use sqlx::PgPool;
use std::collections::HashMap;
pub fn config(cfg: &mut web::ServiceConfig) {
cfg.service(
web::scope("analytics")
.service(playtimes_get)
.service(views_get)
.service(downloads_get)
.service(revenue_get)
.service(countries_downloads_get)
.service(countries_views_get),
);
}
/// The json data to be passed to fetch analytic data
/// Either a list of project_ids or version_ids can be used, but not both. Unauthorized projects/versions will be filtered out.
/// start_date and end_date are optional, and default to two weeks ago, and the maximum date respectively
/// start_date and end_date are inclusive
/// resolution_minutes is optional. This refers to the window by which we are looking (every day, every minute, etc) and defaults to 1440 (1 day)
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct GetData {
// only one of project_ids or version_ids should be used
// if neither are provided, all projects the user has access to will be used
pub project_ids: Option<String>,
pub version_ids: Option<String>,
pub start_date: Option<DateTime<Utc>>, // defaults to 2 weeks ago
pub end_date: Option<DateTime<Utc>>, // defaults to now
pub resolution_minutes: Option<u32>, // defaults to 1 day. Ignored in routes that do not aggregate over a resolution (eg: /countries)
}
/// Get playtime data for a set of projects or versions
/// Data is returned as a hashmap of project/version ids to a hashmap of days to playtime data
/// eg:
/// {
/// "4N1tEhnO": {
/// "20230824": 23
/// }
///}
/// Either a list of project_ids or version_ids can be used, but not both. Unauthorized projects/versions will be filtered out.
#[derive(Serialize, Deserialize, Clone)]
pub struct FetchedPlaytime {
pub time: u64,
pub total_seconds: u64,
pub loader_seconds: HashMap<String, u64>,
pub game_version_seconds: HashMap<String, u64>,
pub parent_seconds: HashMap<VersionId, u64>,
}
#[get("playtime")]
pub async fn playtimes_get(
req: HttpRequest,
clickhouse: web::Data<clickhouse::Client>,
data: web::Query<GetData>,
session_queue: web::Data<AuthQueue>,
pool: web::Data<PgPool>,
redis: web::Data<RedisPool>,
) -> Result<HttpResponse, ApiError> {
let data = data.into_inner();
v3::analytics_get::playtimes_get(
req,
clickhouse,
web::Query(v3::analytics_get::GetData {
project_ids: data.project_ids,
version_ids: data.version_ids,
start_date: data.start_date,
end_date: data.end_date,
resolution_minutes: data.resolution_minutes,
}),
session_queue,
pool,
redis,
)
.await
}
/// Get view data for a set of projects or versions
/// Data is returned as a hashmap of project/version ids to a hashmap of days to views
/// eg:
/// {
/// "4N1tEhnO": {
/// "20230824": 1090
/// }
///}
/// Either a list of project_ids or version_ids can be used, but not both. Unauthorized projects/versions will be filtered out.
#[get("views")]
pub async fn views_get(
req: HttpRequest,
clickhouse: web::Data<clickhouse::Client>,
data: web::Query<GetData>,
session_queue: web::Data<AuthQueue>,
pool: web::Data<PgPool>,
redis: web::Data<RedisPool>,
) -> Result<HttpResponse, ApiError> {
let data = data.into_inner();
v3::analytics_get::views_get(
req,
clickhouse,
web::Query(v3::analytics_get::GetData {
project_ids: data.project_ids,
version_ids: data.version_ids,
start_date: data.start_date,
end_date: data.end_date,
resolution_minutes: data.resolution_minutes,
}),
session_queue,
pool,
redis,
)
.await
.or_else(v2_reroute::flatten_404_error)
}
/// Get download data for a set of projects or versions
/// Data is returned as a hashmap of project/version ids to a hashmap of days to downloads
/// eg:
/// {
/// "4N1tEhnO": {
/// "20230824": 32
/// }
///}
/// Either a list of project_ids or version_ids can be used, but not both. Unauthorized projects/versions will be filtered out.
#[get("downloads")]
pub async fn downloads_get(
req: HttpRequest,
clickhouse: web::Data<clickhouse::Client>,
data: web::Query<GetData>,
session_queue: web::Data<AuthQueue>,
pool: web::Data<PgPool>,
redis: web::Data<RedisPool>,
) -> Result<HttpResponse, ApiError> {
let data = data.into_inner();
v3::analytics_get::downloads_get(
req,
clickhouse,
web::Query(v3::analytics_get::GetData {
project_ids: data.project_ids,
version_ids: data.version_ids,
start_date: data.start_date,
end_date: data.end_date,
resolution_minutes: data.resolution_minutes,
}),
session_queue,
pool,
redis,
)
.await
.or_else(v2_reroute::flatten_404_error)
}
/// Get payout data for a set of projects
/// Data is returned as a hashmap of project ids to a hashmap of days to amount earned per day
/// eg:
/// {
/// "4N1tEhnO": {
/// "20230824": 0.001
/// }
///}
/// ONLY project IDs can be used. Unauthorized projects will be filtered out.
#[get("revenue")]
pub async fn revenue_get(
req: HttpRequest,
data: web::Query<GetData>,
session_queue: web::Data<AuthQueue>,
pool: web::Data<PgPool>,
redis: web::Data<RedisPool>,
) -> Result<HttpResponse, ApiError> {
let data = data.into_inner();
v3::analytics_get::revenue_get(
req,
web::Query(v3::analytics_get::GetData {
project_ids: data.project_ids,
version_ids: None,
start_date: data.start_date,
end_date: data.end_date,
resolution_minutes: data.resolution_minutes,
}),
session_queue,
pool,
redis,
)
.await
.or_else(v2_reroute::flatten_404_error)
}
/// Get country data for a set of projects or versions
/// Data is returned as a hashmap of project/version ids to a hashmap of coutnry to downloads.
/// Unknown countries are labeled "".
/// This is usuable to see significant performing countries per project
/// eg:
/// {
/// "4N1tEhnO": {
/// "CAN": 22
/// }
///}
/// Either a list of project_ids or version_ids can be used, but not both. Unauthorized projects/versions will be filtered out.
/// For this endpoint, provided dates are a range to aggregate over, not specific days to fetch
#[get("countries/downloads")]
pub async fn countries_downloads_get(
req: HttpRequest,
clickhouse: web::Data<clickhouse::Client>,
data: web::Query<GetData>,
session_queue: web::Data<AuthQueue>,
pool: web::Data<PgPool>,
redis: web::Data<RedisPool>,
) -> Result<HttpResponse, ApiError> {
let data = data.into_inner();
v3::analytics_get::countries_downloads_get(
req,
clickhouse,
web::Query(v3::analytics_get::GetData {
project_ids: data.project_ids,
version_ids: data.version_ids,
start_date: data.start_date,
end_date: data.end_date,
resolution_minutes: data.resolution_minutes,
}),
session_queue,
pool,
redis,
)
.await
.or_else(v2_reroute::flatten_404_error)
}
/// Get country data for a set of projects or versions
/// Data is returned as a hashmap of project/version ids to a hashmap of coutnry to views.
/// Unknown countries are labeled "".
/// This is usuable to see significant performing countries per project
/// eg:
/// {
/// "4N1tEhnO": {
/// "CAN": 56165
/// }
///}
/// Either a list of project_ids or version_ids can be used, but not both. Unauthorized projects/versions will be filtered out.
/// For this endpoint, provided dates are a range to aggregate over, not specific days to fetch
#[get("countries/views")]
pub async fn countries_views_get(
req: HttpRequest,
clickhouse: web::Data<clickhouse::Client>,
data: web::Query<GetData>,
session_queue: web::Data<AuthQueue>,
pool: web::Data<PgPool>,
redis: web::Data<RedisPool>,
) -> Result<HttpResponse, ApiError> {
let data = data.into_inner();
v3::analytics_get::countries_views_get(
req,
clickhouse,
web::Query(v3::analytics_get::GetData {
project_ids: data.project_ids,
version_ids: data.version_ids,
start_date: data.start_date,
end_date: data.end_date,
resolution_minutes: data.resolution_minutes,
}),
session_queue,
pool,
redis,
)
.await
.or_else(v2_reroute::flatten_404_error)
}

View File

@@ -0,0 +1,191 @@
use crate::database::redis::RedisPool;
use crate::file_hosting::FileHost;
use crate::models::collections::CollectionStatus;
use crate::queue::session::AuthQueue;
use crate::routes::v3::project_creation::CreateError;
use crate::routes::{v3, ApiError};
use actix_web::web::Data;
use actix_web::{delete, get, patch, post, web, HttpRequest, HttpResponse};
use serde::{Deserialize, Serialize};
use sqlx::PgPool;
use std::sync::Arc;
use validator::Validate;
pub fn config(cfg: &mut web::ServiceConfig) {
cfg.service(collections_get);
cfg.service(collection_create);
cfg.service(
web::scope("collection")
.service(collection_get)
.service(collection_delete)
.service(collection_edit)
.service(collection_icon_edit)
.service(delete_collection_icon),
);
}
#[derive(Serialize, Deserialize, Validate, Clone)]
pub struct CollectionCreateData {
#[validate(
length(min = 3, max = 64),
custom(function = "crate::util::validate::validate_name")
)]
/// The title or name of the project.
pub title: String,
#[validate(length(min = 3, max = 255))]
/// A short description of the collection.
pub description: String,
#[validate(length(max = 32))]
#[serde(default = "Vec::new")]
/// A list of initial projects to use with the created collection
pub projects: Vec<String>,
}
#[post("collection")]
pub async fn collection_create(
req: HttpRequest,
collection_create_data: web::Json<CollectionCreateData>,
client: Data<PgPool>,
redis: Data<RedisPool>,
session_queue: Data<AuthQueue>,
) -> Result<HttpResponse, CreateError> {
let collection_create_data = collection_create_data.into_inner();
v3::collections::collection_create(
req,
web::Json(v3::collections::CollectionCreateData {
name: collection_create_data.title,
description: collection_create_data.description,
projects: collection_create_data.projects,
}),
client,
redis,
session_queue,
)
.await
}
#[derive(Serialize, Deserialize)]
pub struct CollectionIds {
pub ids: String,
}
#[get("collections")]
pub async fn collections_get(
req: HttpRequest,
web::Query(ids): web::Query<CollectionIds>,
pool: web::Data<PgPool>,
redis: web::Data<RedisPool>,
session_queue: web::Data<AuthQueue>,
) -> Result<HttpResponse, ApiError> {
v3::collections::collections_get(
req,
web::Query(v3::collections::CollectionIds { ids: ids.ids }),
pool,
redis,
session_queue,
)
.await
}
#[get("{id}")]
pub async fn collection_get(
req: HttpRequest,
info: web::Path<(String,)>,
pool: web::Data<PgPool>,
redis: web::Data<RedisPool>,
session_queue: web::Data<AuthQueue>,
) -> Result<HttpResponse, ApiError> {
v3::collections::collection_get(req, info, pool, redis, session_queue).await
}
#[derive(Deserialize, Validate)]
pub struct EditCollection {
#[validate(
length(min = 3, max = 64),
custom(function = "crate::util::validate::validate_name")
)]
pub title: Option<String>,
#[validate(length(min = 3, max = 256))]
pub description: Option<String>,
pub status: Option<CollectionStatus>,
#[validate(length(max = 64))]
pub new_projects: Option<Vec<String>>,
}
#[patch("{id}")]
pub async fn collection_edit(
req: HttpRequest,
info: web::Path<(String,)>,
pool: web::Data<PgPool>,
new_collection: web::Json<EditCollection>,
redis: web::Data<RedisPool>,
session_queue: web::Data<AuthQueue>,
) -> Result<HttpResponse, ApiError> {
let new_collection = new_collection.into_inner();
v3::collections::collection_edit(
req,
info,
pool,
web::Json(v3::collections::EditCollection {
name: new_collection.title,
description: new_collection.description,
status: new_collection.status,
new_projects: new_collection.new_projects,
}),
redis,
session_queue,
)
.await
}
#[derive(Serialize, Deserialize)]
pub struct Extension {
pub ext: String,
}
#[patch("{id}/icon")]
#[allow(clippy::too_many_arguments)]
pub async fn collection_icon_edit(
web::Query(ext): web::Query<Extension>,
req: HttpRequest,
info: web::Path<(String,)>,
pool: web::Data<PgPool>,
redis: web::Data<RedisPool>,
file_host: web::Data<Arc<dyn FileHost + Send + Sync>>,
payload: web::Payload,
session_queue: web::Data<AuthQueue>,
) -> Result<HttpResponse, ApiError> {
v3::collections::collection_icon_edit(
web::Query(v3::collections::Extension { ext: ext.ext }),
req,
info,
pool,
redis,
file_host,
payload,
session_queue,
)
.await
}
#[delete("{id}/icon")]
pub async fn delete_collection_icon(
req: HttpRequest,
info: web::Path<(String,)>,
pool: web::Data<PgPool>,
redis: web::Data<RedisPool>,
file_host: web::Data<Arc<dyn FileHost + Send + Sync>>,
session_queue: web::Data<AuthQueue>,
) -> Result<HttpResponse, ApiError> {
v3::collections::delete_collection_icon(req, info, pool, redis, file_host, session_queue).await
}
#[delete("{id}")]
pub async fn collection_delete(
req: HttpRequest,
info: web::Path<(String,)>,
pool: web::Data<PgPool>,
redis: web::Data<RedisPool>,
session_queue: web::Data<AuthQueue>,
) -> Result<HttpResponse, ApiError> {
v3::collections::collection_delete(req, info, pool, redis, session_queue).await
}

View File

@@ -1,7 +1,7 @@
use super::ApiError;
use crate::database::redis::RedisPool;
use crate::queue::session::AuthQueue;
use crate::routes::v3;
use crate::{database::redis::RedisPool, routes::v2_reroute};
use actix_web::{get, web, HttpRequest, HttpResponse};
use serde::Deserialize;
use sqlx::PgPool;
@@ -36,4 +36,5 @@ pub async fn get_projects(
session_queue,
)
.await
.or_else(v2_reroute::flatten_404_error)
}

View File

@@ -1,6 +1,9 @@
use crate::database::redis::RedisPool;
use crate::models::ids::NotificationId;
use crate::models::notifications::Notification;
use crate::models::v2::notifications::LegacyNotification;
use crate::queue::session::AuthQueue;
use crate::routes::v2_reroute;
use crate::routes::v3;
use crate::routes::ApiError;
use actix_web::{delete, get, patch, web, HttpRequest, HttpResponse};
@@ -33,7 +36,7 @@ pub async fn notifications_get(
redis: web::Data<RedisPool>,
session_queue: web::Data<AuthQueue>,
) -> Result<HttpResponse, ApiError> {
v3::notifications::notifications_get(
let resp = v3::notifications::notifications_get(
req,
web::Query(v3::notifications::NotificationIds { ids: ids.ids }),
pool,
@@ -41,6 +44,17 @@ pub async fn notifications_get(
session_queue,
)
.await
.or_else(v2_reroute::flatten_404_error);
match v2_reroute::extract_ok_json::<Vec<Notification>>(resp?).await {
Ok(notifications) => {
let notifications: Vec<LegacyNotification> = notifications
.into_iter()
.map(LegacyNotification::from)
.collect();
Ok(HttpResponse::Ok().json(notifications))
}
Err(response) => Ok(response),
}
}
#[get("{id}")]
@@ -51,7 +65,16 @@ pub async fn notification_get(
redis: web::Data<RedisPool>,
session_queue: web::Data<AuthQueue>,
) -> Result<HttpResponse, ApiError> {
v3::notifications::notification_get(req, info, pool, redis, session_queue).await
let response = v3::notifications::notification_get(req, info, pool, redis, session_queue)
.await
.or_else(v2_reroute::flatten_404_error)?;
match v2_reroute::extract_ok_json::<Notification>(response).await {
Ok(notification) => {
let notification = LegacyNotification::from(notification);
Ok(HttpResponse::Ok().json(notification))
}
Err(response) => Ok(response),
}
}
#[patch("{id}")]
@@ -62,7 +85,9 @@ pub async fn notification_read(
redis: web::Data<RedisPool>,
session_queue: web::Data<AuthQueue>,
) -> Result<HttpResponse, ApiError> {
v3::notifications::notification_read(req, info, pool, redis, session_queue).await
v3::notifications::notification_read(req, info, pool, redis, session_queue)
.await
.or_else(v2_reroute::flatten_404_error)
}
#[delete("{id}")]
@@ -73,7 +98,9 @@ pub async fn notification_delete(
redis: web::Data<RedisPool>,
session_queue: web::Data<AuthQueue>,
) -> Result<HttpResponse, ApiError> {
v3::notifications::notification_delete(req, info, pool, redis, session_queue).await
v3::notifications::notification_delete(req, info, pool, redis, session_queue)
.await
.or_else(v2_reroute::flatten_404_error)
}
#[patch("notifications")]
@@ -92,6 +119,7 @@ pub async fn notifications_read(
session_queue,
)
.await
.or_else(v2_reroute::flatten_404_error)
}
#[delete("notifications")]
@@ -110,4 +138,5 @@ pub async fn notifications_delete(
session_queue,
)
.await
.or_else(v2_reroute::flatten_404_error)
}

View File

@@ -0,0 +1,265 @@
use crate::database::redis::RedisPool;
use crate::file_hosting::FileHost;
use crate::models::projects::Project;
use crate::models::v2::projects::LegacyProject;
use crate::queue::session::AuthQueue;
use crate::routes::v3::project_creation::CreateError;
use crate::routes::{v2_reroute, v3, ApiError};
use actix_web::{delete, get, patch, post, web, HttpRequest, HttpResponse};
use serde::{Deserialize, Serialize};
use sqlx::PgPool;
use std::sync::Arc;
use validator::Validate;
pub fn config(cfg: &mut web::ServiceConfig) {
cfg.service(organizations_get).service(organization_create);
cfg.service(
web::scope("organization")
.service(organization_get)
.service(organizations_edit)
.service(organization_delete)
.service(organization_projects_get)
.service(organization_projects_add)
.service(organization_projects_remove)
.service(organization_icon_edit)
.service(delete_organization_icon)
.service(super::teams::team_members_get_organization),
);
}
#[derive(Deserialize, Validate)]
pub struct NewOrganization {
#[validate(
length(min = 3, max = 64),
regex = "crate::util::validate::RE_URL_SAFE"
)]
// Title of the organization, also used as slug
pub title: String,
#[validate(length(min = 3, max = 256))]
pub description: String,
}
#[post("organization")]
pub async fn organization_create(
req: HttpRequest,
new_organization: web::Json<NewOrganization>,
pool: web::Data<PgPool>,
redis: web::Data<RedisPool>,
session_queue: web::Data<AuthQueue>,
) -> Result<HttpResponse, CreateError> {
let new_organization = new_organization.into_inner();
v3::organizations::organization_create(
req,
web::Json(v3::organizations::NewOrganization {
name: new_organization.title,
description: new_organization.description,
}),
pool.clone(),
redis.clone(),
session_queue,
)
.await
}
#[get("{id}")]
pub async fn organization_get(
req: HttpRequest,
info: web::Path<(String,)>,
pool: web::Data<PgPool>,
redis: web::Data<RedisPool>,
session_queue: web::Data<AuthQueue>,
) -> Result<HttpResponse, ApiError> {
v3::organizations::organization_get(req, info, pool.clone(), redis.clone(), session_queue).await
}
#[derive(Deserialize)]
pub struct OrganizationIds {
pub ids: String,
}
#[get("organizations")]
pub async fn organizations_get(
req: HttpRequest,
web::Query(ids): web::Query<OrganizationIds>,
pool: web::Data<PgPool>,
redis: web::Data<RedisPool>,
session_queue: web::Data<AuthQueue>,
) -> Result<HttpResponse, ApiError> {
v3::organizations::organizations_get(
req,
web::Query(v3::organizations::OrganizationIds { ids: ids.ids }),
pool,
redis,
session_queue,
)
.await
}
#[derive(Serialize, Deserialize, Validate)]
pub struct OrganizationEdit {
#[validate(length(min = 3, max = 256))]
pub description: Option<String>,
#[validate(
length(min = 3, max = 64),
regex = "crate::util::validate::RE_URL_SAFE"
)]
// Title of the organization, also used as slug
pub title: Option<String>,
}
#[patch("{id}")]
pub async fn organizations_edit(
req: HttpRequest,
info: web::Path<(String,)>,
new_organization: web::Json<OrganizationEdit>,
pool: web::Data<PgPool>,
redis: web::Data<RedisPool>,
session_queue: web::Data<AuthQueue>,
) -> Result<HttpResponse, ApiError> {
let new_organization = new_organization.into_inner();
v3::organizations::organizations_edit(
req,
info,
web::Json(v3::organizations::OrganizationEdit {
description: new_organization.description,
name: new_organization.title,
}),
pool.clone(),
redis.clone(),
session_queue,
)
.await
}
#[delete("{id}")]
pub async fn organization_delete(
req: HttpRequest,
info: web::Path<(String,)>,
pool: web::Data<PgPool>,
redis: web::Data<RedisPool>,
session_queue: web::Data<AuthQueue>,
) -> Result<HttpResponse, ApiError> {
v3::organizations::organization_delete(req, info, pool.clone(), redis.clone(), session_queue)
.await
}
#[get("{id}/projects")]
pub async fn organization_projects_get(
req: HttpRequest,
info: web::Path<(String,)>,
pool: web::Data<PgPool>,
redis: web::Data<RedisPool>,
session_queue: web::Data<AuthQueue>,
) -> Result<HttpResponse, ApiError> {
let response = v3::organizations::organization_projects_get(
req,
info,
pool.clone(),
redis.clone(),
session_queue,
)
.await?;
// Convert v3 projects to v2
match v2_reroute::extract_ok_json::<Vec<Project>>(response).await {
Ok(project) => {
let legacy_projects = LegacyProject::from_many(project, &**pool, &redis).await?;
Ok(HttpResponse::Ok().json(legacy_projects))
}
Err(response) => Ok(response),
}
}
#[derive(Deserialize)]
pub struct OrganizationProjectAdd {
pub project_id: String, // Also allow title/slug
}
#[post("{id}/projects")]
pub async fn organization_projects_add(
req: HttpRequest,
info: web::Path<(String,)>,
project_info: web::Json<OrganizationProjectAdd>,
pool: web::Data<PgPool>,
redis: web::Data<RedisPool>,
session_queue: web::Data<AuthQueue>,
) -> Result<HttpResponse, ApiError> {
let project_info = project_info.into_inner();
v3::organizations::organization_projects_add(
req,
info,
web::Json(v3::organizations::OrganizationProjectAdd {
project_id: project_info.project_id,
}),
pool.clone(),
redis.clone(),
session_queue,
)
.await
}
#[delete("{organization_id}/projects/{project_id}")]
pub async fn organization_projects_remove(
req: HttpRequest,
info: web::Path<(String, String)>,
pool: web::Data<PgPool>,
redis: web::Data<RedisPool>,
session_queue: web::Data<AuthQueue>,
) -> Result<HttpResponse, ApiError> {
v3::organizations::organization_projects_remove(
req,
info,
pool.clone(),
redis.clone(),
session_queue,
)
.await
}
#[derive(Serialize, Deserialize)]
pub struct Extension {
pub ext: String,
}
#[patch("{id}/icon")]
#[allow(clippy::too_many_arguments)]
pub async fn organization_icon_edit(
web::Query(ext): web::Query<Extension>,
req: HttpRequest,
info: web::Path<(String,)>,
pool: web::Data<PgPool>,
redis: web::Data<RedisPool>,
file_host: web::Data<Arc<dyn FileHost + Send + Sync>>,
payload: web::Payload,
session_queue: web::Data<AuthQueue>,
) -> Result<HttpResponse, ApiError> {
v3::organizations::organization_icon_edit(
web::Query(v3::organizations::Extension { ext: ext.ext }),
req,
info,
pool.clone(),
redis.clone(),
file_host,
payload,
session_queue,
)
.await
}
#[delete("{id}/icon")]
pub async fn delete_organization_icon(
req: HttpRequest,
info: web::Path<(String,)>,
pool: web::Data<PgPool>,
redis: web::Data<RedisPool>,
file_host: web::Data<Arc<dyn FileHost + Send + Sync>>,
session_queue: web::Data<AuthQueue>,
) -> Result<HttpResponse, ApiError> {
v3::organizations::delete_organization_icon(
req,
info,
pool.clone(),
redis.clone(),
file_host,
session_queue,
)
.await
}

View File

@@ -213,10 +213,10 @@ pub async fn project_create(
}
Ok(v3::project_creation::ProjectCreateData {
title: legacy_create.title,
name: legacy_create.title,
slug: legacy_create.slug,
description: legacy_create.description,
body: legacy_create.body,
summary: legacy_create.description, // Description becomes summary
description: legacy_create.body, // Body becomes description
initial_versions,
categories: legacy_create.categories,
additional_categories: legacy_create.additional_categories,

View File

@@ -102,6 +102,8 @@ pub async fn project_search(
format!("game_versions:{}", val)
} else if facet.starts_with("project_type:") {
format!("project_types:{}", val)
} else if facet.starts_with("title:") {
format!("name:{}", val)
} else {
facet.to_string()
}
@@ -143,7 +145,10 @@ pub async fn random_projects_get(
let count = v3::projects::RandomProjects { count: count.count };
let response =
v3::projects::random_projects_get(web::Query(count), pool.clone(), redis.clone()).await?;
v3::projects::random_projects_get(web::Query(count), pool.clone(), redis.clone())
.await
.or_else(v2_reroute::flatten_404_error)
.or_else(v2_reroute::flatten_404_error)?;
// Convert response to V2 format
match v2_reroute::extract_ok_json::<Vec<Project>>(response).await {
Ok(project) => {
@@ -170,7 +175,9 @@ pub async fn projects_get(
redis.clone(),
session_queue,
)
.await?;
.await
.or_else(v2_reroute::flatten_404_error)
.or_else(v2_reroute::flatten_404_error)?;
// Convert response to V2 format
match v2_reroute::extract_ok_json::<Vec<Project>>(response).await {
@@ -191,10 +198,11 @@ pub async fn project_get(
session_queue: web::Data<AuthQueue>,
) -> Result<HttpResponse, ApiError> {
// Convert V2 data to V3 data
// Call V3 project creation
let response =
v3::projects::project_get(req, info, pool.clone(), redis.clone(), session_queue).await?;
let response = v3::projects::project_get(req, info, pool.clone(), redis.clone(), session_queue)
.await
.or_else(v2_reroute::flatten_404_error)
.or_else(v2_reroute::flatten_404_error)?;
// Convert response to V2 format
match v2_reroute::extract_ok_json::<Project>(response).await {
@@ -217,7 +225,10 @@ pub async fn project_get_check(
pool: web::Data<PgPool>,
redis: web::Data<RedisPool>,
) -> Result<HttpResponse, ApiError> {
v3::projects::project_get_check(info, pool, redis).await
v3::projects::project_get_check(info, pool, redis)
.await
.or_else(v2_reroute::flatten_404_error)
.or_else(v2_reroute::flatten_404_error)
}
#[derive(Serialize)]
@@ -235,7 +246,10 @@ pub async fn dependency_list(
session_queue: web::Data<AuthQueue>,
) -> Result<HttpResponse, ApiError> {
// TODO: requires V2 conversion and tests, probably
v3::projects::dependency_list(req, info, pool, redis, session_queue).await
v3::projects::dependency_list(req, info, pool, redis, session_queue)
.await
.or_else(v2_reroute::flatten_404_error)
.or_else(v2_reroute::flatten_404_error)
}
#[derive(Serialize, Deserialize, Validate)]
@@ -426,9 +440,9 @@ pub async fn project_edit(
}
let new_project = v3::projects::EditProject {
title: v2_new_project.title,
description: v2_new_project.description,
body: v2_new_project.body,
name: v2_new_project.title,
summary: v2_new_project.description, // Description becomes summary
description: v2_new_project.body, // Body becomes description
categories: v2_new_project.categories,
additional_categories: v2_new_project.additional_categories,
license_url: v2_new_project.license_url,
@@ -453,7 +467,8 @@ pub async fn project_edit(
redis.clone(),
session_queue.clone(),
)
.await?;
.await
.or_else(v2_reroute::flatten_404_error)?;
// If client and server side were set, we will call
// the version setting route for each version to set the side types for each of them.
@@ -642,6 +657,7 @@ pub async fn projects_edit(
session_queue,
)
.await
.or_else(v2_reroute::flatten_404_error)
}
#[derive(Serialize, Deserialize)]
@@ -672,6 +688,7 @@ pub async fn project_icon_edit(
session_queue,
)
.await
.or_else(v2_reroute::flatten_404_error)
}
#[delete("{id}/icon")]
@@ -683,7 +700,9 @@ pub async fn delete_project_icon(
file_host: web::Data<Arc<dyn FileHost + Send + Sync>>,
session_queue: web::Data<AuthQueue>,
) -> Result<HttpResponse, ApiError> {
v3::projects::delete_project_icon(req, info, pool, redis, file_host, session_queue).await
v3::projects::delete_project_icon(req, info, pool, redis, file_host, session_queue)
.await
.or_else(v2_reroute::flatten_404_error)
}
#[derive(Serialize, Deserialize, Validate)]
@@ -714,7 +733,7 @@ pub async fn add_gallery_item(
req,
web::Query(v3::projects::GalleryCreateQuery {
featured: item.featured,
title: item.title,
name: item.title,
description: item.description,
ordering: item.ordering,
}),
@@ -726,6 +745,7 @@ pub async fn add_gallery_item(
session_queue,
)
.await
.or_else(v2_reroute::flatten_404_error)
}
#[derive(Serialize, Deserialize, Validate)]
@@ -764,7 +784,7 @@ pub async fn edit_gallery_item(
web::Query(v3::projects::GalleryEditQuery {
url: item.url,
featured: item.featured,
title: item.title,
name: item.title,
description: item.description,
ordering: item.ordering,
}),
@@ -774,6 +794,7 @@ pub async fn edit_gallery_item(
session_queue,
)
.await
.or_else(v2_reroute::flatten_404_error)
}
#[derive(Serialize, Deserialize)]
@@ -801,6 +822,7 @@ pub async fn delete_gallery_item(
session_queue,
)
.await
.or_else(v2_reroute::flatten_404_error)
}
#[delete("{id}")]
@@ -812,7 +834,9 @@ pub async fn project_delete(
config: web::Data<SearchConfig>,
session_queue: web::Data<AuthQueue>,
) -> Result<HttpResponse, ApiError> {
v3::projects::project_delete(req, info, pool, redis, config, session_queue).await
v3::projects::project_delete(req, info, pool, redis, config, session_queue)
.await
.or_else(v2_reroute::flatten_404_error)
}
#[post("{id}/follow")]
@@ -823,7 +847,9 @@ pub async fn project_follow(
redis: web::Data<RedisPool>,
session_queue: web::Data<AuthQueue>,
) -> Result<HttpResponse, ApiError> {
v3::projects::project_follow(req, info, pool, redis, session_queue).await
v3::projects::project_follow(req, info, pool, redis, session_queue)
.await
.or_else(v2_reroute::flatten_404_error)
}
#[delete("{id}/follow")]
@@ -834,5 +860,7 @@ pub async fn project_unfollow(
redis: web::Data<RedisPool>,
session_queue: web::Data<AuthQueue>,
) -> Result<HttpResponse, ApiError> {
v3::projects::project_unfollow(req, info, pool, redis, session_queue).await
v3::projects::project_unfollow(req, info, pool, redis, session_queue)
.await
.or_else(v2_reroute::flatten_404_error)
}

View File

@@ -2,7 +2,7 @@ use crate::database::redis::RedisPool;
use crate::models::ids::ImageId;
use crate::models::reports::ItemType;
use crate::queue::session::AuthQueue;
use crate::routes::{v3, ApiError};
use crate::routes::{v2_reroute, v3, ApiError};
use actix_web::{delete, get, patch, post, web, HttpRequest, HttpResponse};
use serde::Deserialize;
use sqlx::PgPool;
@@ -37,7 +37,9 @@ pub async fn report_create(
redis: web::Data<RedisPool>,
session_queue: web::Data<AuthQueue>,
) -> Result<HttpResponse, ApiError> {
v3::reports::report_create(req, pool, body, redis, session_queue).await
v3::reports::report_create(req, pool, body, redis, session_queue)
.await
.or_else(v2_reroute::flatten_404_error)
}
#[derive(Deserialize)]
@@ -74,6 +76,7 @@ pub async fn reports(
session_queue,
)
.await
.or_else(v2_reroute::flatten_404_error)
}
#[derive(Deserialize)]
@@ -97,6 +100,7 @@ pub async fn reports_get(
session_queue,
)
.await
.or_else(v2_reroute::flatten_404_error)
}
#[get("report/{id}")]
@@ -107,7 +111,9 @@ pub async fn report_get(
info: web::Path<(crate::models::reports::ReportId,)>,
session_queue: web::Data<AuthQueue>,
) -> Result<HttpResponse, ApiError> {
v3::reports::report_get(req, pool, redis, info, session_queue).await
v3::reports::report_get(req, pool, redis, info, session_queue)
.await
.or_else(v2_reroute::flatten_404_error)
}
#[derive(Deserialize, Validate)]
@@ -139,6 +145,7 @@ pub async fn report_edit(
}),
)
.await
.or_else(v2_reroute::flatten_404_error)
}
#[delete("report/{id}")]
@@ -149,5 +156,7 @@ pub async fn report_delete(
redis: web::Data<RedisPool>,
session_queue: web::Data<AuthQueue>,
) -> Result<HttpResponse, ApiError> {
v3::reports::report_delete(req, pool, info, redis, session_queue).await
v3::reports::report_delete(req, pool, info, redis, session_queue)
.await
.or_else(v2_reroute::flatten_404_error)
}

View File

@@ -1,4 +1,4 @@
use crate::routes::{v3, ApiError};
use crate::routes::{v2_reroute, v3, ApiError};
use actix_web::{get, web, HttpResponse};
use sqlx::PgPool;
@@ -8,5 +8,7 @@ pub fn config(cfg: &mut web::ServiceConfig) {
#[get("statistics")]
pub async fn get_stats(pool: web::Data<PgPool>) -> Result<HttpResponse, ApiError> {
v3::statistics::get_stats(pool).await
v3::statistics::get_stats(pool)
.await
.or_else(v2_reroute::flatten_404_error)
}

View File

@@ -161,7 +161,9 @@ pub struct LicenseText {
#[get("license/{id}")]
pub async fn license_text(params: web::Path<(String,)>) -> Result<HttpResponse, ApiError> {
v3::tags::license_text(params).await
v3::tags::license_text(params)
.await
.or_else(v2_reroute::flatten_404_error)
}
#[derive(serde::Serialize)]
@@ -192,6 +194,7 @@ pub async fn donation_platform_list(
Err(response) => response,
},
)
.or_else(v2_reroute::flatten_404_error)
}
#[get("report_type")]
@@ -199,7 +202,9 @@ pub async fn report_type_list(
pool: web::Data<PgPool>,
redis: web::Data<RedisPool>,
) -> Result<HttpResponse, ApiError> {
v3::tags::report_type_list(pool, redis).await
v3::tags::report_type_list(pool, redis)
.await
.or_else(v2_reroute::flatten_404_error)
}
#[get("project_type")]
@@ -207,7 +212,9 @@ pub async fn project_type_list(
pool: web::Data<PgPool>,
redis: web::Data<RedisPool>,
) -> Result<HttpResponse, ApiError> {
v3::tags::project_type_list(pool, redis).await
v3::tags::project_type_list(pool, redis)
.await
.or_else(v2_reroute::flatten_404_error)
}
#[get("side_type")]

View File

@@ -1,8 +1,9 @@
use crate::database::redis::RedisPool;
use crate::models::teams::{OrganizationPermissions, ProjectPermissions, TeamId};
use crate::models::teams::{OrganizationPermissions, ProjectPermissions, TeamId, TeamMember};
use crate::models::users::UserId;
use crate::models::v2::teams::LegacyTeamMember;
use crate::queue::session::AuthQueue;
use crate::routes::{v3, ApiError};
use crate::routes::{v2_reroute, v3, ApiError};
use actix_web::{delete, get, patch, post, web, HttpRequest, HttpResponse};
use rust_decimal::Decimal;
use serde::{Deserialize, Serialize};
@@ -34,7 +35,20 @@ pub async fn team_members_get_project(
redis: web::Data<RedisPool>,
session_queue: web::Data<AuthQueue>,
) -> Result<HttpResponse, ApiError> {
v3::teams::team_members_get_project(req, info, pool, redis, session_queue).await
let response = v3::teams::team_members_get_project(req, info, pool, redis, session_queue)
.await
.or_else(v2_reroute::flatten_404_error)?;
// Convert response to V2 format
match v2_reroute::extract_ok_json::<Vec<TeamMember>>(response).await {
Ok(members) => {
let members = members
.into_iter()
.map(LegacyTeamMember::from)
.collect::<Vec<_>>();
Ok(HttpResponse::Ok().json(members))
}
Err(response) => Ok(response),
}
}
// Returns all members of a team, but not necessarily those of a project-team's organization (unlike team_members_get_project)
@@ -46,7 +60,20 @@ pub async fn team_members_get(
redis: web::Data<RedisPool>,
session_queue: web::Data<AuthQueue>,
) -> Result<HttpResponse, ApiError> {
v3::teams::team_members_get(req, info, pool, redis, session_queue).await
let response = v3::teams::team_members_get(req, info, pool, redis, session_queue)
.await
.or_else(v2_reroute::flatten_404_error)?;
// Convert response to V2 format
match v2_reroute::extract_ok_json::<Vec<TeamMember>>(response).await {
Ok(members) => {
let members = members
.into_iter()
.map(LegacyTeamMember::from)
.collect::<Vec<_>>();
Ok(HttpResponse::Ok().json(members))
}
Err(response) => Ok(response),
}
}
#[derive(Serialize, Deserialize)]
@@ -62,7 +89,7 @@ pub async fn teams_get(
redis: web::Data<RedisPool>,
session_queue: web::Data<AuthQueue>,
) -> Result<HttpResponse, ApiError> {
v3::teams::teams_get(
let response = v3::teams::teams_get(
req,
web::Query(v3::teams::TeamIds { ids: ids.ids }),
pool,
@@ -70,6 +97,23 @@ pub async fn teams_get(
session_queue,
)
.await
.or_else(v2_reroute::flatten_404_error);
// Convert response to V2 format
match v2_reroute::extract_ok_json::<Vec<Vec<TeamMember>>>(response?).await {
Ok(members) => {
let members = members
.into_iter()
.map(|members| {
members
.into_iter()
.map(LegacyTeamMember::from)
.collect::<Vec<_>>()
})
.collect::<Vec<_>>();
Ok(HttpResponse::Ok().json(members))
}
Err(response) => Ok(response),
}
}
#[post("{id}/join")]
@@ -80,7 +124,9 @@ pub async fn join_team(
redis: web::Data<RedisPool>,
session_queue: web::Data<AuthQueue>,
) -> Result<HttpResponse, ApiError> {
v3::teams::join_team(req, info, pool, redis, session_queue).await
v3::teams::join_team(req, info, pool, redis, session_queue)
.await
.or_else(v2_reroute::flatten_404_error)
}
fn default_role() -> String {
@@ -132,6 +178,7 @@ pub async fn add_team_member(
session_queue,
)
.await
.or_else(v2_reroute::flatten_404_error)
}
#[derive(Serialize, Deserialize, Clone)]
@@ -167,6 +214,7 @@ pub async fn edit_team_member(
session_queue,
)
.await
.or_else(v2_reroute::flatten_404_error)
}
#[derive(Deserialize)]
@@ -194,6 +242,7 @@ pub async fn transfer_ownership(
session_queue,
)
.await
.or_else(v2_reroute::flatten_404_error)
}
#[delete("{id}/members/{user_id}")]
@@ -204,5 +253,7 @@ pub async fn remove_team_member(
redis: web::Data<RedisPool>,
session_queue: web::Data<AuthQueue>,
) -> Result<HttpResponse, ApiError> {
v3::teams::remove_team_member(req, info, pool, redis, session_queue).await
v3::teams::remove_team_member(req, info, pool, redis, session_queue)
.await
.or_else(v2_reroute::flatten_404_error)
}

View File

@@ -5,7 +5,7 @@ use crate::file_hosting::FileHost;
use crate::models::ids::ThreadMessageId;
use crate::models::threads::{MessageBody, ThreadId};
use crate::queue::session::AuthQueue;
use crate::routes::{v3, ApiError};
use crate::routes::{v2_reroute, v3, ApiError};
use actix_web::{delete, get, post, web, HttpRequest, HttpResponse};
use serde::Deserialize;
use sqlx::PgPool;
@@ -30,7 +30,9 @@ pub async fn thread_get(
redis: web::Data<RedisPool>,
session_queue: web::Data<AuthQueue>,
) -> Result<HttpResponse, ApiError> {
v3::threads::thread_get(req, info, pool, redis, session_queue).await
v3::threads::thread_get(req, info, pool, redis, session_queue)
.await
.or_else(v2_reroute::flatten_404_error)
}
#[derive(Deserialize)]
@@ -54,6 +56,7 @@ pub async fn threads_get(
session_queue,
)
.await
.or_else(v2_reroute::flatten_404_error)
}
#[derive(Deserialize)]
@@ -82,6 +85,7 @@ pub async fn thread_send_message(
session_queue,
)
.await
.or_else(v2_reroute::flatten_404_error)
}
#[get("inbox")]
@@ -91,7 +95,9 @@ pub async fn moderation_inbox(
redis: web::Data<RedisPool>,
session_queue: web::Data<AuthQueue>,
) -> Result<HttpResponse, ApiError> {
v3::threads::moderation_inbox(req, pool, redis, session_queue).await
v3::threads::moderation_inbox(req, pool, redis, session_queue)
.await
.or_else(v2_reroute::flatten_404_error)
}
#[post("{id}/read")]
@@ -102,7 +108,9 @@ pub async fn thread_read(
redis: web::Data<RedisPool>,
session_queue: web::Data<AuthQueue>,
) -> Result<HttpResponse, ApiError> {
v3::threads::thread_read(req, info, pool, redis, session_queue).await
v3::threads::thread_read(req, info, pool, redis, session_queue)
.await
.or_else(v2_reroute::flatten_404_error)
}
#[delete("{id}")]
@@ -114,5 +122,7 @@ pub async fn message_delete(
session_queue: web::Data<AuthQueue>,
file_host: web::Data<Arc<dyn FileHost + Send + Sync>>,
) -> Result<HttpResponse, ApiError> {
v3::threads::message_delete(req, info, pool, redis, session_queue, file_host).await
v3::threads::message_delete(req, info, pool, redis, session_queue, file_host)
.await
.or_else(v2_reroute::flatten_404_error)
}

View File

@@ -1,7 +1,9 @@
use crate::database::redis::RedisPool;
use crate::file_hosting::FileHost;
use crate::models::notifications::Notification;
use crate::models::projects::Project;
use crate::models::users::{Badges, Role};
use crate::models::v2::notifications::LegacyNotification;
use crate::models::v2::projects::LegacyProject;
use crate::queue::session::AuthQueue;
use crate::routes::{v2_reroute, v3, ApiError};
@@ -36,7 +38,9 @@ pub async fn user_auth_get(
redis: web::Data<RedisPool>,
session_queue: web::Data<AuthQueue>,
) -> Result<HttpResponse, ApiError> {
v3::users::user_auth_get(req, pool, redis, session_queue).await
v3::users::user_auth_get(req, pool, redis, session_queue)
.await
.or_else(v2_reroute::flatten_404_error)
}
#[derive(Serialize, Deserialize)]
@@ -50,7 +54,9 @@ pub async fn users_get(
pool: web::Data<PgPool>,
redis: web::Data<RedisPool>,
) -> Result<HttpResponse, ApiError> {
v3::users::users_get(web::Query(v3::users::UserIds { ids: ids.ids }), pool, redis).await
v3::users::users_get(web::Query(v3::users::UserIds { ids: ids.ids }), pool, redis)
.await
.or_else(v2_reroute::flatten_404_error)
}
#[get("{id}")]
@@ -59,7 +65,9 @@ pub async fn user_get(
pool: web::Data<PgPool>,
redis: web::Data<RedisPool>,
) -> Result<HttpResponse, ApiError> {
v3::users::user_get(info, pool, redis).await
v3::users::user_get(info, pool, redis)
.await
.or_else(v2_reroute::flatten_404_error)
}
#[get("{user_id}/projects")]
@@ -70,8 +78,9 @@ pub async fn projects_list(
redis: web::Data<RedisPool>,
session_queue: web::Data<AuthQueue>,
) -> Result<HttpResponse, ApiError> {
let response =
v3::users::projects_list(req, info, pool.clone(), redis.clone(), session_queue).await?;
let response = v3::users::projects_list(req, info, pool.clone(), redis.clone(), session_queue)
.await
.or_else(v2_reroute::flatten_404_error)?;
// Convert to V2 projects
match v2_reroute::extract_ok_json::<Vec<Project>>(response).await {
@@ -135,6 +144,7 @@ pub async fn user_edit(
session_queue,
)
.await
.or_else(v2_reroute::flatten_404_error)
}
#[derive(Serialize, Deserialize)]
@@ -165,6 +175,7 @@ pub async fn user_icon_edit(
session_queue,
)
.await
.or_else(v2_reroute::flatten_404_error)
}
#[derive(Deserialize)]
@@ -198,6 +209,7 @@ pub async fn user_delete(
session_queue,
)
.await
.or_else(v2_reroute::flatten_404_error)
}
#[get("{id}/follows")]
@@ -208,7 +220,9 @@ pub async fn user_follows(
redis: web::Data<RedisPool>,
session_queue: web::Data<AuthQueue>,
) -> Result<HttpResponse, ApiError> {
v3::users::user_follows(req, info, pool, redis, session_queue).await
v3::users::user_follows(req, info, pool, redis, session_queue)
.await
.or_else(v2_reroute::flatten_404_error)
}
#[get("{id}/notifications")]
@@ -219,5 +233,18 @@ pub async fn user_notifications(
redis: web::Data<RedisPool>,
session_queue: web::Data<AuthQueue>,
) -> Result<HttpResponse, ApiError> {
v3::users::user_notifications(req, info, pool, redis, session_queue).await
let response = v3::users::user_notifications(req, info, pool, redis, session_queue)
.await
.or_else(v2_reroute::flatten_404_error)?;
// Convert response to V2 format
match v2_reroute::extract_ok_json::<Vec<Notification>>(response).await {
Ok(notifications) => {
let legacy_notifications: Vec<LegacyNotification> = notifications
.into_iter()
.map(LegacyNotification::from)
.collect();
Ok(HttpResponse::Ok().json(legacy_notifications))
}
Err(response) => Ok(response),
}
}

View File

@@ -3,7 +3,7 @@ use crate::database::redis::RedisPool;
use crate::models::projects::{Project, Version, VersionType};
use crate::models::v2::projects::{LegacyProject, LegacyVersion};
use crate::queue::session::AuthQueue;
use crate::routes::v3::version_file::{default_algorithm, HashQuery};
use crate::routes::v3::version_file::HashQuery;
use crate::routes::{v2_reroute, v3};
use actix_web::{delete, get, post, web, HttpRequest, HttpResponse};
use serde::{Deserialize, Serialize};
@@ -40,10 +40,11 @@ pub async fn get_version_from_hash(
) -> Result<HttpResponse, ApiError> {
let response =
v3::version_file::get_version_from_hash(req, info, pool, redis, hash_query, session_queue)
.await;
.await
.or_else(v2_reroute::flatten_404_error)?;
// Convert response to V2 format
match v2_reroute::extract_ok_json::<Version>(response?).await {
match v2_reroute::extract_ok_json::<Version>(response).await {
Ok(version) => {
let v2_version = LegacyVersion::from(version);
Ok(HttpResponse::Ok().json(v2_version))
@@ -62,7 +63,9 @@ pub async fn download_version(
hash_query: web::Query<HashQuery>,
session_queue: web::Data<AuthQueue>,
) -> Result<HttpResponse, ApiError> {
v3::version_file::download_version(req, info, pool, redis, hash_query, session_queue).await
v3::version_file::download_version(req, info, pool, redis, hash_query, session_queue)
.await
.or_else(v2_reroute::flatten_404_error)
}
// under /api/v1/version_file/{hash}
@@ -75,7 +78,9 @@ pub async fn delete_file(
hash_query: web::Query<HashQuery>,
session_queue: web::Data<AuthQueue>,
) -> Result<HttpResponse, ApiError> {
v3::version_file::delete_file(req, info, pool, redis, hash_query, session_queue).await
v3::version_file::delete_file(req, info, pool, redis, hash_query, session_queue)
.await
.or_else(v2_reroute::flatten_404_error)
}
#[derive(Serialize, Deserialize)]
@@ -119,7 +124,8 @@ pub async fn get_update_from_hash(
web::Json(update_data),
session_queue,
)
.await?;
.await
.or_else(v2_reroute::flatten_404_error)?;
// Convert response to V2 format
match v2_reroute::extract_ok_json::<Version>(response).await {
@@ -134,8 +140,7 @@ pub async fn get_update_from_hash(
// Requests above with multiple versions below
#[derive(Deserialize)]
pub struct FileHashes {
#[serde(default = "default_algorithm")]
pub algorithm: String,
pub algorithm: Option<String>,
pub hashes: Vec<String>,
}
@@ -160,7 +165,8 @@ pub async fn get_versions_from_hashes(
web::Json(file_data),
session_queue,
)
.await?;
.await
.or_else(v2_reroute::flatten_404_error)?;
// Convert to V2
match v2_reroute::extract_ok_json::<HashMap<String, Version>>(response).await {
@@ -198,7 +204,8 @@ pub async fn get_projects_from_hashes(
web::Json(file_data),
session_queue,
)
.await?;
.await
.or_else(v2_reroute::flatten_404_error)?;
// Convert to V2
match v2_reroute::extract_ok_json::<HashMap<String, Project>>(response).await {
@@ -230,8 +237,7 @@ pub async fn get_projects_from_hashes(
#[derive(Deserialize)]
pub struct ManyUpdateData {
#[serde(default = "default_algorithm")]
pub algorithm: String,
pub algorithm: Option<String>, // Defaults to calculation based on size of hash
pub hashes: Vec<String>,
pub loaders: Option<Vec<String>>,
pub game_versions: Option<Vec<String>>,
@@ -265,7 +271,8 @@ pub async fn update_files(
let response =
v3::version_file::update_files(req, pool, redis, web::Json(update_data), session_queue)
.await?;
.await
.or_else(v2_reroute::flatten_404_error)?;
// Convert response to V2 format
match v2_reroute::extract_ok_json::<HashMap<String, Version>>(response).await {
@@ -293,8 +300,7 @@ pub struct FileUpdateData {
#[derive(Deserialize)]
pub struct ManyFileUpdateData {
#[serde(default = "default_algorithm")]
pub algorithm: String,
pub algorithm: Option<String>, // Defaults to calculation based on size of hash
pub hashes: Vec<FileUpdateData>,
}
@@ -338,7 +344,8 @@ pub async fn update_individual_files(
web::Json(update_data),
session_queue,
)
.await?;
.await
.or_else(v2_reroute::flatten_404_error)?;
// Convert response to V2 format
match v2_reroute::extract_ok_json::<HashMap<String, Version>>(response).await {

View File

@@ -73,7 +73,8 @@ pub async fn version_list(
let response =
v3::versions::version_list(req, info, web::Query(filters), pool, redis, session_queue)
.await?;
.await
.or_else(v2_reroute::flatten_404_error)?;
// Convert response to V2 format
match v2_reroute::extract_ok_json::<Vec<Version>>(response).await {
@@ -98,8 +99,9 @@ pub async fn version_project_get(
session_queue: web::Data<AuthQueue>,
) -> Result<HttpResponse, ApiError> {
let id = info.into_inner();
let response =
v3::versions::version_project_get_helper(req, id, pool, redis, session_queue).await?;
let response = v3::versions::version_project_get_helper(req, id, pool, redis, session_queue)
.await
.or_else(v2_reroute::flatten_404_error)?;
// Convert response to V2 format
match v2_reroute::extract_ok_json::<Version>(response).await {
Ok(version) => {
@@ -124,8 +126,9 @@ pub async fn versions_get(
session_queue: web::Data<AuthQueue>,
) -> Result<HttpResponse, ApiError> {
let ids = v3::versions::VersionIds { ids: ids.ids };
let response =
v3::versions::versions_get(req, web::Query(ids), pool, redis, session_queue).await?;
let response = v3::versions::versions_get(req, web::Query(ids), pool, redis, session_queue)
.await
.or_else(v2_reroute::flatten_404_error)?;
// Convert response to V2 format
match v2_reroute::extract_ok_json::<Vec<Version>>(response).await {
@@ -149,7 +152,9 @@ pub async fn version_get(
session_queue: web::Data<AuthQueue>,
) -> Result<HttpResponse, ApiError> {
let id = info.into_inner().0;
let response = v3::versions::version_get_helper(req, id, pool, redis, session_queue).await?;
let response = v3::versions::version_get_helper(req, id, pool, redis, session_queue)
.await
.or_else(v2_reroute::flatten_404_error)?;
// Convert response to V2 format
match v2_reroute::extract_ok_json::<Version>(response).await {
Ok(version) => {
@@ -248,7 +253,8 @@ pub async fn version_edit(
web::Json(serde_json::to_value(new_version)?),
session_queue,
)
.await?;
.await
.or_else(v2_reroute::flatten_404_error)?;
Ok(response)
}
@@ -260,5 +266,7 @@ pub async fn version_delete(
redis: web::Data<RedisPool>,
session_queue: web::Data<AuthQueue>,
) -> Result<HttpResponse, ApiError> {
v3::versions::version_delete(req, info, pool, redis, session_queue).await
v3::versions::version_delete(req, info, pool, redis, session_queue)
.await
.or_else(v2_reroute::flatten_404_error)
}