You've already forked AstralRinth
forked from didirus/AstralRinth
Testing bug fixes (#788)
* fixes * adds tests- fixes failures * changes * moved transaction commits/caches around * collections nullable * merge fixes * sqlx prepare * revs * lf fixes * made changes back * added collections update --------- Co-authored-by: Geometrically <18202329+Geometrically@users.noreply.github.com>
This commit is contained in:
@@ -13,7 +13,7 @@ pub struct CollectionBuilder {
|
||||
pub collection_id: CollectionId,
|
||||
pub user_id: UserId,
|
||||
pub name: String,
|
||||
pub description: String,
|
||||
pub description: Option<String>,
|
||||
pub status: CollectionStatus,
|
||||
pub projects: Vec<ProjectId>,
|
||||
}
|
||||
@@ -45,7 +45,7 @@ pub struct Collection {
|
||||
pub id: CollectionId,
|
||||
pub user_id: UserId,
|
||||
pub name: String,
|
||||
pub description: String,
|
||||
pub description: Option<String>,
|
||||
pub created: DateTime<Utc>,
|
||||
pub updated: DateTime<Utc>,
|
||||
pub icon_url: Option<String>,
|
||||
@@ -73,7 +73,7 @@ impl Collection {
|
||||
self.id as CollectionId,
|
||||
self.user_id as UserId,
|
||||
&self.name,
|
||||
&self.description,
|
||||
self.description.as_ref(),
|
||||
self.created,
|
||||
self.icon_url.as_ref(),
|
||||
self.status.to_string(),
|
||||
|
||||
@@ -344,6 +344,28 @@ impl Project {
|
||||
.execute(&mut **transaction)
|
||||
.await?;
|
||||
|
||||
// Notably joins with report id and not thread.mod_id directly, as
|
||||
// this is set to null for threads that are reports.
|
||||
let report_threads = sqlx::query!(
|
||||
"
|
||||
SELECT t.id
|
||||
FROM threads t
|
||||
INNER JOIN reports r ON t.report_id = r.id
|
||||
WHERE r.mod_id = $1 AND report_id IS NOT NULL
|
||||
",
|
||||
id as ProjectId,
|
||||
)
|
||||
.fetch_many(&mut **transaction)
|
||||
.try_filter_map(|e| async { Ok(e.right().map(|x| ThreadId(x.id))) })
|
||||
.try_collect::<Vec<_>>()
|
||||
.await?;
|
||||
|
||||
for thread_id in report_threads {
|
||||
models::Thread::remove_full(thread_id, transaction).await?;
|
||||
}
|
||||
|
||||
models::Thread::remove_full(project.thread_id, transaction).await?;
|
||||
|
||||
sqlx::query!(
|
||||
"
|
||||
DELETE FROM reports
|
||||
@@ -398,8 +420,6 @@ impl Project {
|
||||
.execute(&mut **transaction)
|
||||
.await?;
|
||||
|
||||
models::Thread::remove_full(project.thread_id, transaction).await?;
|
||||
|
||||
sqlx::query!(
|
||||
"
|
||||
DELETE FROM mods
|
||||
|
||||
@@ -14,7 +14,7 @@ use crate::models::projects::{
|
||||
ProjectStatus, Version, VersionFile, VersionStatus, VersionType,
|
||||
};
|
||||
use crate::models::threads::ThreadId;
|
||||
use crate::routes::v2_reroute;
|
||||
use crate::routes::v2_reroute::{self, capitalize_first};
|
||||
use chrono::{DateTime, Utc};
|
||||
use itertools::Itertools;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -395,11 +395,3 @@ impl TryFrom<Link> for DonationLink {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn capitalize_first(input: &str) -> String {
|
||||
let mut result = input.to_owned();
|
||||
if let Some(first_char) = result.get_mut(0..1) {
|
||||
first_char.make_ascii_uppercase();
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ pub struct Collection {
|
||||
/// The title or name of the collection.
|
||||
pub name: String,
|
||||
/// A short description of the collection.
|
||||
pub description: String,
|
||||
pub description: Option<String>,
|
||||
|
||||
/// An icon URL for the collection.
|
||||
pub icon_url: Option<String>,
|
||||
|
||||
@@ -720,6 +720,8 @@ pub async fn process_payout(
|
||||
.execute(&mut *transaction)
|
||||
.await?;
|
||||
|
||||
transaction.commit().await?;
|
||||
|
||||
if !clear_cache_users.is_empty() {
|
||||
crate::database::models::User::clear_caches(
|
||||
&clear_cache_users
|
||||
@@ -731,8 +733,6 @@ pub async fn process_payout(
|
||||
.await?;
|
||||
}
|
||||
|
||||
transaction.commit().await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -131,11 +131,10 @@ impl AuthQueue {
|
||||
.execute(&mut *transaction)
|
||||
.await?;
|
||||
|
||||
PersonalAccessToken::clear_cache(clear_cache_pats, redis).await?;
|
||||
|
||||
update_oauth_access_token_last_used(oauth_access_token_queue, &mut transaction).await?;
|
||||
|
||||
transaction.commit().await?;
|
||||
PersonalAccessToken::clear_cache(clear_cache_pats, redis).await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -1195,8 +1195,8 @@ pub async fn auth_callback(
|
||||
)?;
|
||||
}
|
||||
|
||||
crate::database::models::User::clear_caches(&[(id, None)], &redis).await?;
|
||||
transaction.commit().await?;
|
||||
crate::database::models::User::clear_caches(&[(id, None)], &redis).await?;
|
||||
|
||||
if let Some(url) = url {
|
||||
Ok(HttpResponse::TemporaryRedirect()
|
||||
@@ -1395,8 +1395,8 @@ pub async fn delete_auth_provider(
|
||||
}
|
||||
}
|
||||
|
||||
crate::database::models::User::clear_caches(&[(user.id.into(), None)], &redis).await?;
|
||||
transaction.commit().await?;
|
||||
crate::database::models::User::clear_caches(&[(user.id.into(), None)], &redis).await?;
|
||||
|
||||
Ok(HttpResponse::NoContent().finish())
|
||||
}
|
||||
@@ -1864,8 +1864,8 @@ pub async fn finish_2fa_flow(
|
||||
)?;
|
||||
}
|
||||
|
||||
crate::database::models::User::clear_caches(&[(user.id.into(), None)], &redis).await?;
|
||||
transaction.commit().await?;
|
||||
crate::database::models::User::clear_caches(&[(user.id.into(), None)], &redis).await?;
|
||||
|
||||
Ok(HttpResponse::Ok().json(serde_json::json!({
|
||||
"backup_codes": codes,
|
||||
@@ -1952,8 +1952,8 @@ pub async fn remove_2fa(
|
||||
)?;
|
||||
}
|
||||
|
||||
crate::database::models::User::clear_caches(&[(user.id, None)], &redis).await?;
|
||||
transaction.commit().await?;
|
||||
crate::database::models::User::clear_caches(&[(user.id, None)], &redis).await?;
|
||||
|
||||
Ok(HttpResponse::NoContent().finish())
|
||||
}
|
||||
@@ -2138,8 +2138,8 @@ pub async fn change_password(
|
||||
)?;
|
||||
}
|
||||
|
||||
crate::database::models::User::clear_caches(&[(user.id, None)], &redis).await?;
|
||||
transaction.commit().await?;
|
||||
crate::database::models::User::clear_caches(&[(user.id, None)], &redis).await?;
|
||||
|
||||
Ok(HttpResponse::Ok().finish())
|
||||
}
|
||||
@@ -2210,8 +2210,8 @@ pub async fn set_email(
|
||||
"We need to verify your email address.",
|
||||
)?;
|
||||
|
||||
crate::database::models::User::clear_caches(&[(user.id.into(), None)], &redis).await?;
|
||||
transaction.commit().await?;
|
||||
crate::database::models::User::clear_caches(&[(user.id.into(), None)], &redis).await?;
|
||||
|
||||
Ok(HttpResponse::Ok().finish())
|
||||
}
|
||||
@@ -2300,8 +2300,8 @@ pub async fn verify_email(
|
||||
.await?;
|
||||
|
||||
Flow::remove(&email.flow, &redis).await?;
|
||||
crate::database::models::User::clear_caches(&[(user.id, None)], &redis).await?;
|
||||
transaction.commit().await?;
|
||||
crate::database::models::User::clear_caches(&[(user.id, None)], &redis).await?;
|
||||
|
||||
Ok(HttpResponse::NoContent().finish())
|
||||
} else {
|
||||
|
||||
@@ -127,12 +127,12 @@ pub async fn create_pat(
|
||||
.insert(&mut transaction)
|
||||
.await?;
|
||||
|
||||
transaction.commit().await?;
|
||||
database::models::pat_item::PersonalAccessToken::clear_cache(
|
||||
vec![(None, None, Some(user.id.into()))],
|
||||
&redis,
|
||||
)
|
||||
.await?;
|
||||
transaction.commit().await?;
|
||||
|
||||
Ok(HttpResponse::Ok().json(PersonalAccessToken {
|
||||
id: id.into(),
|
||||
@@ -232,12 +232,12 @@ pub async fn edit_pat(
|
||||
.await?;
|
||||
}
|
||||
|
||||
transaction.commit().await?;
|
||||
database::models::pat_item::PersonalAccessToken::clear_cache(
|
||||
vec![(Some(pat.id), Some(pat.access_token), Some(pat.user_id))],
|
||||
&redis,
|
||||
)
|
||||
.await?;
|
||||
transaction.commit().await?;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -269,12 +269,12 @@ pub async fn delete_pat(
|
||||
let mut transaction = pool.begin().await?;
|
||||
database::models::pat_item::PersonalAccessToken::remove(pat.id, &mut transaction)
|
||||
.await?;
|
||||
transaction.commit().await?;
|
||||
database::models::pat_item::PersonalAccessToken::clear_cache(
|
||||
vec![(Some(pat.id), Some(pat.access_token), Some(pat.user_id))],
|
||||
&redis,
|
||||
)
|
||||
.await?;
|
||||
transaction.commit().await?;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -187,6 +187,7 @@ pub async fn delete(
|
||||
if session.user_id == current_user.id.into() {
|
||||
let mut transaction = pool.begin().await?;
|
||||
DBSession::remove(session.id, &mut transaction).await?;
|
||||
transaction.commit().await?;
|
||||
DBSession::clear_cache(
|
||||
vec![(
|
||||
Some(session.id),
|
||||
@@ -196,7 +197,6 @@ pub async fn delete(
|
||||
&redis,
|
||||
)
|
||||
.await?;
|
||||
transaction.commit().await?;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -232,6 +232,7 @@ pub async fn refresh(
|
||||
|
||||
DBSession::remove(session.id, &mut transaction).await?;
|
||||
let new_session = issue_session(req, session.user_id, &mut transaction, &redis).await?;
|
||||
transaction.commit().await?;
|
||||
DBSession::clear_cache(
|
||||
vec![(
|
||||
Some(session.id),
|
||||
@@ -242,8 +243,6 @@ pub async fn refresh(
|
||||
)
|
||||
.await?;
|
||||
|
||||
transaction.commit().await?;
|
||||
|
||||
Ok(HttpResponse::Ok().json(Session::from(new_session, true, None)))
|
||||
} else {
|
||||
Err(ApiError::Authentication(
|
||||
|
||||
@@ -4,6 +4,7 @@ use super::ApiError;
|
||||
use crate::database::models::loader_fields::LoaderFieldEnumValue;
|
||||
use crate::database::redis::RedisPool;
|
||||
use crate::models::v2::projects::LegacySideType;
|
||||
use crate::routes::v2_reroute::capitalize_first;
|
||||
use crate::routes::v3::tags::{
|
||||
LinkPlatformQueryData, LoaderData as LoaderDataV3, LoaderFieldsEnumQuery,
|
||||
};
|
||||
@@ -172,11 +173,12 @@ pub async fn license_text(params: web::Path<(String,)>) -> Result<HttpResponse,
|
||||
.or_else(v2_reroute::flatten_404_error)
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize)]
|
||||
#[derive(serde::Serialize, serde::Deserialize, PartialEq, Eq, Debug)]
|
||||
pub struct DonationPlatformQueryData {
|
||||
// The difference between name and short is removed in v3.
|
||||
// Now, the 'id' becomes the name, and the 'name' is removed (the frontend uses the id as the name)
|
||||
// pub short: String,
|
||||
pub short: String,
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
@@ -193,7 +195,26 @@ pub async fn donation_platform_list(
|
||||
Ok(platforms) => {
|
||||
let platforms = platforms
|
||||
.into_iter()
|
||||
.map(|p| DonationPlatformQueryData { name: p.name })
|
||||
.filter_map(|p| {
|
||||
if p.donation {
|
||||
Some(DonationPlatformQueryData {
|
||||
// Short vs name is no longer a recognized difference in v3.
|
||||
// We capitalize to recreate the old behavior, with some special handling.
|
||||
// This may result in different behaviour for platforms added after the v3 migration.
|
||||
name: match p.name.as_str() {
|
||||
"bmac" => "Buy Me A Coffee".to_string(),
|
||||
"github" => "GitHub Sponsors".to_string(),
|
||||
"ko-fi" => "Ko-fi".to_string(),
|
||||
"paypal" => "PayPal".to_string(),
|
||||
// Otherwise, capitalize it
|
||||
_ => capitalize_first(&p.name),
|
||||
},
|
||||
short: p.name,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
HttpResponse::Ok().json(platforms)
|
||||
}
|
||||
|
||||
@@ -100,34 +100,66 @@ pub async fn version_create(
|
||||
json!(legacy_create.game_versions),
|
||||
);
|
||||
|
||||
// Get all possible side-types for loaders given- we will use these to check if we need to convert/apply singleplayer, etc.
|
||||
let loaders = match v3::tags::loader_list(client.clone(), redis.clone()).await {
|
||||
Ok(loader_response) => match v2_reroute::extract_ok_json::<
|
||||
Vec<v3::tags::LoaderData>,
|
||||
>(loader_response)
|
||||
.await
|
||||
{
|
||||
Ok(loaders) => loaders,
|
||||
Err(_) => vec![],
|
||||
},
|
||||
Err(_) => vec![],
|
||||
};
|
||||
|
||||
let loader_fields_aggregate = loaders
|
||||
.into_iter()
|
||||
.filter_map(|loader| {
|
||||
if legacy_create.loaders.contains(&Loader(loader.name.clone())) {
|
||||
Some(loader.supported_fields)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.flatten()
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// Copies side types of another version of the project.
|
||||
// If no version exists, defaults to all false.
|
||||
// TODO: write test for this to ensure predictible unchanging behaviour
|
||||
// This is inherently lossy, but not much can be done about it, as side types are no longer associated with projects,
|
||||
// so the 'missing' ones can't be easily accessed.
|
||||
// so the 'missing' ones can't be easily accessed, and versions do need to have these fields explicitly set.
|
||||
let side_type_loader_field_names = [
|
||||
"singleplayer",
|
||||
"client_and_server",
|
||||
"client_only",
|
||||
"server_only",
|
||||
];
|
||||
fields.extend(
|
||||
side_type_loader_field_names
|
||||
.iter()
|
||||
.map(|f| (f.to_string(), json!(false))),
|
||||
);
|
||||
if let Some(example_version_fields) =
|
||||
get_example_version_fields(legacy_create.project_id, client, &redis).await?
|
||||
{
|
||||
fields.extend(example_version_fields.into_iter().filter_map(|f| {
|
||||
if side_type_loader_field_names.contains(&f.field_name.as_str()) {
|
||||
Some((f.field_name, f.value.serialize_internal()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
// Check if loader_fields_aggregate contains any of these side types
|
||||
// We assume these four fields are linked together.
|
||||
if loader_fields_aggregate
|
||||
.iter()
|
||||
.any(|f| side_type_loader_field_names.contains(&f.as_str()))
|
||||
{
|
||||
// If so, we get the fields of the example version of the project, and set the side types to match.
|
||||
fields.extend(
|
||||
side_type_loader_field_names
|
||||
.iter()
|
||||
.map(|f| (f.to_string(), json!(false))),
|
||||
);
|
||||
if let Some(example_version_fields) =
|
||||
get_example_version_fields(legacy_create.project_id, client, &redis).await?
|
||||
{
|
||||
fields.extend(example_version_fields.into_iter().filter_map(|f| {
|
||||
if side_type_loader_field_names.contains(&f.field_name.as_str()) {
|
||||
Some((f.field_name, f.value.serialize_internal()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
// Handle project type via file extension prediction
|
||||
let mut project_type = None;
|
||||
for file_part in &legacy_create.file_parts {
|
||||
|
||||
@@ -300,6 +300,14 @@ pub fn convert_side_types_v2_bools(
|
||||
}
|
||||
}
|
||||
|
||||
pub fn capitalize_first(input: &str) -> String {
|
||||
let mut result = input.to_owned();
|
||||
if let Some(first_char) = result.get_mut(0..1) {
|
||||
first_char.make_ascii_uppercase();
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
@@ -46,7 +46,7 @@ pub struct CollectionCreateData {
|
||||
pub name: String,
|
||||
#[validate(length(min = 3, max = 255))]
|
||||
/// A short description of the collection.
|
||||
pub description: String,
|
||||
pub description: Option<String>,
|
||||
#[validate(length(max = 32))]
|
||||
#[serde(default = "Vec::new")]
|
||||
/// A list of initial projects to use with the created collection
|
||||
@@ -198,7 +198,12 @@ pub struct EditCollection {
|
||||
)]
|
||||
pub name: Option<String>,
|
||||
#[validate(length(min = 3, max = 256))]
|
||||
pub description: Option<String>,
|
||||
#[serde(
|
||||
default,
|
||||
skip_serializing_if = "Option::is_none",
|
||||
with = "::serde_with::rust::double_option"
|
||||
)]
|
||||
pub description: Option<Option<String>>,
|
||||
pub status: Option<CollectionStatus>,
|
||||
#[validate(length(max = 64))]
|
||||
pub new_projects: Option<Vec<String>>,
|
||||
@@ -260,7 +265,7 @@ pub async fn collection_edit(
|
||||
SET description = $1
|
||||
WHERE (id = $2)
|
||||
",
|
||||
description,
|
||||
description.as_ref(),
|
||||
id as database::models::ids::CollectionId,
|
||||
)
|
||||
.execute(&mut *transaction)
|
||||
@@ -328,11 +333,22 @@ pub async fn collection_edit(
|
||||
)
|
||||
.execute(&mut *transaction)
|
||||
.await?;
|
||||
|
||||
sqlx::query!(
|
||||
"
|
||||
UPDATE collections
|
||||
SET updated = NOW()
|
||||
WHERE id = $1
|
||||
",
|
||||
collection_item.id as database::models::ids::CollectionId,
|
||||
)
|
||||
.execute(&mut *transaction)
|
||||
.await?;
|
||||
}
|
||||
|
||||
transaction.commit().await?;
|
||||
database::models::Collection::clear_cache(collection_item.id, &redis).await?;
|
||||
|
||||
transaction.commit().await?;
|
||||
Ok(HttpResponse::NoContent().body(""))
|
||||
} else {
|
||||
Err(ApiError::NotFound)
|
||||
@@ -417,9 +433,8 @@ pub async fn collection_icon_edit(
|
||||
.execute(&mut *transaction)
|
||||
.await?;
|
||||
|
||||
database::models::Collection::clear_cache(collection_item.id, &redis).await?;
|
||||
|
||||
transaction.commit().await?;
|
||||
database::models::Collection::clear_cache(collection_item.id, &redis).await?;
|
||||
|
||||
Ok(HttpResponse::NoContent().body(""))
|
||||
} else {
|
||||
@@ -481,9 +496,8 @@ pub async fn delete_collection_icon(
|
||||
.execute(&mut *transaction)
|
||||
.await?;
|
||||
|
||||
database::models::Collection::clear_cache(collection_item.id, &redis).await?;
|
||||
|
||||
transaction.commit().await?;
|
||||
database::models::Collection::clear_cache(collection_item.id, &redis).await?;
|
||||
|
||||
Ok(HttpResponse::NoContent().body(""))
|
||||
}
|
||||
@@ -519,9 +533,9 @@ pub async fn collection_delete(
|
||||
|
||||
let result =
|
||||
database::models::Collection::remove(collection.id, &mut transaction, &redis).await?;
|
||||
database::models::Collection::clear_cache(collection.id, &redis).await?;
|
||||
|
||||
transaction.commit().await?;
|
||||
database::models::Collection::clear_cache(collection.id, &redis).await?;
|
||||
|
||||
if result.is_some() {
|
||||
Ok(HttpResponse::NoContent().body(""))
|
||||
|
||||
@@ -456,6 +456,7 @@ pub async fn organizations_edit(
|
||||
.await?;
|
||||
}
|
||||
|
||||
transaction.commit().await?;
|
||||
database::models::Organization::clear_cache(
|
||||
organization_item.id,
|
||||
Some(organization_item.name),
|
||||
@@ -463,7 +464,6 @@ pub async fn organizations_edit(
|
||||
)
|
||||
.await?;
|
||||
|
||||
transaction.commit().await?;
|
||||
Ok(HttpResponse::NoContent().body(""))
|
||||
} else {
|
||||
Err(ApiError::CustomAuthentication(
|
||||
@@ -819,6 +819,7 @@ pub async fn organization_icon_edit(
|
||||
.execute(&mut *transaction)
|
||||
.await?;
|
||||
|
||||
transaction.commit().await?;
|
||||
database::models::Organization::clear_cache(
|
||||
organization_item.id,
|
||||
Some(organization_item.name),
|
||||
@@ -826,8 +827,6 @@ pub async fn organization_icon_edit(
|
||||
)
|
||||
.await?;
|
||||
|
||||
transaction.commit().await?;
|
||||
|
||||
Ok(HttpResponse::NoContent().body(""))
|
||||
} else {
|
||||
Err(ApiError::InvalidInput(format!(
|
||||
@@ -904,6 +903,8 @@ pub async fn delete_organization_icon(
|
||||
.execute(&mut *transaction)
|
||||
.await?;
|
||||
|
||||
transaction.commit().await?;
|
||||
|
||||
database::models::Organization::clear_cache(
|
||||
organization_item.id,
|
||||
Some(organization_item.name),
|
||||
@@ -911,7 +912,5 @@ pub async fn delete_organization_icon(
|
||||
)
|
||||
.await?;
|
||||
|
||||
transaction.commit().await?;
|
||||
|
||||
Ok(HttpResponse::NoContent().body(""))
|
||||
}
|
||||
|
||||
@@ -144,12 +144,6 @@ pub async fn paypal_webhook(
|
||||
.execute(&mut *transaction)
|
||||
.await?;
|
||||
|
||||
crate::database::models::user_item::User::clear_caches(
|
||||
&[(crate::database::models::UserId(result.user_id), None)],
|
||||
&redis,
|
||||
)
|
||||
.await?;
|
||||
|
||||
sqlx::query!(
|
||||
"
|
||||
UPDATE payouts
|
||||
@@ -168,6 +162,12 @@ pub async fn paypal_webhook(
|
||||
.await?;
|
||||
|
||||
transaction.commit().await?;
|
||||
|
||||
crate::database::models::user_item::User::clear_caches(
|
||||
&[(crate::database::models::UserId(result.user_id), None)],
|
||||
&redis,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
"PAYMENT.PAYOUTS-ITEM.SUCCEEDED" => {
|
||||
@@ -265,12 +265,6 @@ pub async fn tremendous_webhook(
|
||||
.execute(&mut *transaction)
|
||||
.await?;
|
||||
|
||||
crate::database::models::user_item::User::clear_caches(
|
||||
&[(crate::database::models::UserId(result.user_id), None)],
|
||||
&redis,
|
||||
)
|
||||
.await?;
|
||||
|
||||
sqlx::query!(
|
||||
"
|
||||
UPDATE payouts
|
||||
@@ -289,6 +283,12 @@ pub async fn tremendous_webhook(
|
||||
.await?;
|
||||
|
||||
transaction.commit().await?;
|
||||
|
||||
crate::database::models::user_item::User::clear_caches(
|
||||
&[(crate::database::models::UserId(result.user_id), None)],
|
||||
&redis,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
"REWARDS.DELIVERY.SUCCEEDED" => {
|
||||
@@ -616,9 +616,9 @@ pub async fn create_payout(
|
||||
.execute(&mut *transaction)
|
||||
.await?;
|
||||
payout_item.insert(&mut transaction).await?;
|
||||
crate::database::models::User::clear_caches(&[(user.id, None)], &redis).await?;
|
||||
|
||||
transaction.commit().await?;
|
||||
crate::database::models::User::clear_caches(&[(user.id, None)], &redis).await?;
|
||||
|
||||
Ok(HttpResponse::NoContent().finish())
|
||||
}
|
||||
|
||||
@@ -839,6 +839,8 @@ pub async fn project_edit(
|
||||
};
|
||||
|
||||
img::delete_unused_images(context, checkable_strings, &mut transaction, &redis).await?;
|
||||
|
||||
transaction.commit().await?;
|
||||
db_models::Project::clear_cache(
|
||||
project_item.inner.id,
|
||||
project_item.inner.slug,
|
||||
@@ -847,7 +849,6 @@ pub async fn project_edit(
|
||||
)
|
||||
.await?;
|
||||
|
||||
transaction.commit().await?;
|
||||
Ok(HttpResponse::NoContent().body(""))
|
||||
} else {
|
||||
Err(ApiError::CustomAuthentication(
|
||||
@@ -1501,6 +1502,7 @@ pub async fn project_icon_edit(
|
||||
.execute(&mut *transaction)
|
||||
.await?;
|
||||
|
||||
transaction.commit().await?;
|
||||
db_models::Project::clear_cache(
|
||||
project_item.inner.id,
|
||||
project_item.inner.slug,
|
||||
@@ -1509,8 +1511,6 @@ pub async fn project_icon_edit(
|
||||
)
|
||||
.await?;
|
||||
|
||||
transaction.commit().await?;
|
||||
|
||||
Ok(HttpResponse::NoContent().body(""))
|
||||
} else {
|
||||
Err(ApiError::InvalidInput(format!(
|
||||
@@ -1596,11 +1596,10 @@ pub async fn delete_project_icon(
|
||||
.execute(&mut *transaction)
|
||||
.await?;
|
||||
|
||||
transaction.commit().await?;
|
||||
db_models::Project::clear_cache(project_item.inner.id, project_item.inner.slug, None, &redis)
|
||||
.await?;
|
||||
|
||||
transaction.commit().await?;
|
||||
|
||||
Ok(HttpResponse::NoContent().body(""))
|
||||
}
|
||||
|
||||
@@ -1736,6 +1735,7 @@ pub async fn add_gallery_item(
|
||||
}];
|
||||
GalleryItem::insert_many(gallery_item, project_item.inner.id, &mut transaction).await?;
|
||||
|
||||
transaction.commit().await?;
|
||||
db_models::Project::clear_cache(
|
||||
project_item.inner.id,
|
||||
project_item.inner.slug,
|
||||
@@ -1744,8 +1744,6 @@ pub async fn add_gallery_item(
|
||||
)
|
||||
.await?;
|
||||
|
||||
transaction.commit().await?;
|
||||
|
||||
Ok(HttpResponse::NoContent().body(""))
|
||||
} else {
|
||||
Err(ApiError::InvalidInput(format!(
|
||||
@@ -1921,11 +1919,11 @@ pub async fn edit_gallery_item(
|
||||
.await?;
|
||||
}
|
||||
|
||||
transaction.commit().await?;
|
||||
|
||||
db_models::Project::clear_cache(project_item.inner.id, project_item.inner.slug, None, &redis)
|
||||
.await?;
|
||||
|
||||
transaction.commit().await?;
|
||||
|
||||
Ok(HttpResponse::NoContent().body(""))
|
||||
}
|
||||
|
||||
@@ -2027,11 +2025,11 @@ pub async fn delete_gallery_item(
|
||||
.execute(&mut *transaction)
|
||||
.await?;
|
||||
|
||||
transaction.commit().await?;
|
||||
|
||||
db_models::Project::clear_cache(project_item.inner.id, project_item.inner.slug, None, &redis)
|
||||
.await?;
|
||||
|
||||
transaction.commit().await?;
|
||||
|
||||
Ok(HttpResponse::NoContent().body(""))
|
||||
}
|
||||
|
||||
|
||||
@@ -217,6 +217,7 @@ pub async fn license_text(params: web::Path<(String,)>) -> Result<HttpResponse,
|
||||
#[derive(serde::Serialize, serde::Deserialize)]
|
||||
pub struct LinkPlatformQueryData {
|
||||
pub name: String,
|
||||
pub donation: bool,
|
||||
}
|
||||
|
||||
pub async fn link_platform_list(
|
||||
@@ -226,7 +227,10 @@ pub async fn link_platform_list(
|
||||
let results: Vec<LinkPlatformQueryData> = LinkPlatform::list(&**pool, &redis)
|
||||
.await?
|
||||
.into_iter()
|
||||
.map(|x| LinkPlatformQueryData { name: x.name })
|
||||
.map(|x| LinkPlatformQueryData {
|
||||
name: x.name,
|
||||
donation: x.donation,
|
||||
})
|
||||
.collect();
|
||||
Ok(HttpResponse::Ok().json(results))
|
||||
}
|
||||
|
||||
@@ -348,10 +348,10 @@ pub async fn join_team(
|
||||
)
|
||||
.await?;
|
||||
|
||||
transaction.commit().await?;
|
||||
|
||||
User::clear_project_cache(&[current_user.id.into()], &redis).await?;
|
||||
TeamMember::clear_cache(team_id, &redis).await?;
|
||||
|
||||
transaction.commit().await?;
|
||||
} else {
|
||||
return Err(ApiError::InvalidInput(
|
||||
"There is no pending request from this team".to_string(),
|
||||
@@ -542,9 +542,8 @@ pub async fn add_team_member(
|
||||
}
|
||||
}
|
||||
|
||||
TeamMember::clear_cache(team_id, &redis).await?;
|
||||
|
||||
transaction.commit().await?;
|
||||
TeamMember::clear_cache(team_id, &redis).await?;
|
||||
|
||||
Ok(HttpResponse::NoContent().body(""))
|
||||
}
|
||||
@@ -691,9 +690,8 @@ pub async fn edit_team_member(
|
||||
)
|
||||
.await?;
|
||||
|
||||
TeamMember::clear_cache(id, &redis).await?;
|
||||
|
||||
transaction.commit().await?;
|
||||
TeamMember::clear_cache(id, &redis).await?;
|
||||
|
||||
Ok(HttpResponse::NoContent().body(""))
|
||||
}
|
||||
@@ -797,9 +795,8 @@ pub async fn transfer_ownership(
|
||||
)
|
||||
.await?;
|
||||
|
||||
TeamMember::clear_cache(id.into(), &redis).await?;
|
||||
|
||||
transaction.commit().await?;
|
||||
TeamMember::clear_cache(id.into(), &redis).await?;
|
||||
|
||||
Ok(HttpResponse::NoContent().body(""))
|
||||
}
|
||||
@@ -925,10 +922,11 @@ pub async fn remove_team_member(
|
||||
}
|
||||
}
|
||||
|
||||
transaction.commit().await?;
|
||||
|
||||
TeamMember::clear_cache(id, &redis).await?;
|
||||
User::clear_project_cache(&[delete_member.user_id], &redis).await?;
|
||||
|
||||
transaction.commit().await?;
|
||||
Ok(HttpResponse::NoContent().body(""))
|
||||
} else {
|
||||
Err(ApiError::NotFound)
|
||||
|
||||
@@ -449,8 +449,8 @@ pub async fn user_edit(
|
||||
.await?;
|
||||
}
|
||||
|
||||
User::clear_caches(&[(id, Some(actual_user.username))], &redis).await?;
|
||||
transaction.commit().await?;
|
||||
User::clear_caches(&[(id, Some(actual_user.username))], &redis).await?;
|
||||
Ok(HttpResponse::NoContent().body(""))
|
||||
} else {
|
||||
Err(ApiError::CustomAuthentication(
|
||||
|
||||
@@ -664,6 +664,7 @@ pub async fn version_edit_helper(
|
||||
|
||||
img::delete_unused_images(context, checkable_strings, &mut transaction, &redis).await?;
|
||||
|
||||
transaction.commit().await?;
|
||||
database::models::Version::clear_cache(&version_item, &redis).await?;
|
||||
database::models::Project::clear_cache(
|
||||
version_item.inner.project_id,
|
||||
@@ -672,7 +673,6 @@ pub async fn version_edit_helper(
|
||||
&redis,
|
||||
)
|
||||
.await?;
|
||||
transaction.commit().await?;
|
||||
Ok(HttpResponse::NoContent().body(""))
|
||||
} else {
|
||||
Err(ApiError::CustomAuthentication(
|
||||
@@ -921,8 +921,8 @@ pub async fn version_schedule(
|
||||
.execute(&mut *transaction)
|
||||
.await?;
|
||||
|
||||
database::models::Version::clear_cache(&version_item, &redis).await?;
|
||||
transaction.commit().await?;
|
||||
database::models::Version::clear_cache(&version_item, &redis).await?;
|
||||
|
||||
Ok(HttpResponse::NoContent().body(""))
|
||||
} else {
|
||||
@@ -1004,12 +1004,11 @@ pub async fn version_delete(
|
||||
|
||||
let result =
|
||||
database::models::Version::remove_full(version.inner.id, &redis, &mut transaction).await?;
|
||||
transaction.commit().await?;
|
||||
remove_documents(&[version.inner.id.into()], &search_config).await?;
|
||||
database::models::Project::clear_cache(version.inner.project_id, None, Some(true), &redis)
|
||||
.await?;
|
||||
|
||||
transaction.commit().await?;
|
||||
|
||||
if result.is_some() {
|
||||
Ok(HttpResponse::NoContent().body(""))
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user