You've already forked AstralRinth
forked from didirus/AstralRinth
Update Rust dependencies (#4139)
* Update Rust version * Update async-compression 0.4.25 -> 0.4.27 * Update async-tungstenite 0.29.1 -> 0.30.0 * Update bytemuck 1.23.0 -> 1.23.1 * Update clap 4.5.40 -> 4.5.43 * Update deadpool-redis 0.21.1 -> 0.22.0 and redis 0.31.0 -> 0.32.4 * Update enumset 1.1.6 -> 1.1.7 * Update hyper-util 0.1.14 -> 0.1.16 * Update indexmap 2.9.0 -> 2.10.0 * Update indicatif 0.17.11 -> 0.18.0 * Update jemalloc_pprof 0.7.0 -> 0.8.1 * Update lettre 0.11.17 -> 0.11.18 * Update meilisearch-sdk 0.28.0 -> 0.29.1 * Update notify 8.0.0 -> 8.2.0 and notify-debouncer-mini 0.6.0 -> 0.7.0 * Update quick-xml 0.37.5 -> 0.38.1 * Fix theseus lint * Update reqwest 0.12.20 -> 0.12.22 * Cargo fmt in theseus * Update rgb 0.8.50 -> 0.8.52 * Update sentry 0.41.0 -> 0.42.0 and sentry-actix 0.41.0 -> 0.42.0 * Update serde_json 1.0.140 -> 1.0.142 * Update serde_with 3.13.0 -> 3.14.0 * Update spdx 0.10.8 -> 0.10.9 * Update sysinfo 0.35.2 -> 0.36.1 * Update tauri suite * Fix build by updating mappings * Update tokio 1.45.1 -> 1.47.1 and tokio-util 0.7.15 -> 0.7.16 * Update tracing-actix-web 0.7.18 -> 0.7.19 * Update zip 4.2.0 -> 4.3.0 * Misc Cargo.lock updates * Update Dockerfiles
This commit is contained in:
@@ -286,17 +286,17 @@ pub async fn refund_charge(
|
||||
.upsert(&mut transaction)
|
||||
.await?;
|
||||
|
||||
if body.0.unprovision.unwrap_or(false) {
|
||||
if let Some(subscription_id) = charge.subscription_id {
|
||||
let open_charge =
|
||||
DBCharge::get_open_subscription(subscription_id, &**pool)
|
||||
.await?;
|
||||
if let Some(mut open_charge) = open_charge {
|
||||
open_charge.status = ChargeStatus::Cancelled;
|
||||
open_charge.due = Utc::now();
|
||||
if body.0.unprovision.unwrap_or(false)
|
||||
&& let Some(subscription_id) = charge.subscription_id
|
||||
{
|
||||
let open_charge =
|
||||
DBCharge::get_open_subscription(subscription_id, &**pool)
|
||||
.await?;
|
||||
if let Some(mut open_charge) = open_charge {
|
||||
open_charge.status = ChargeStatus::Cancelled;
|
||||
open_charge.due = Utc::now();
|
||||
|
||||
open_charge.upsert(&mut transaction).await?;
|
||||
}
|
||||
open_charge.upsert(&mut transaction).await?;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -392,17 +392,16 @@ pub async fn edit_subscription(
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(interval) = &edit_subscription.interval {
|
||||
if let Price::Recurring { intervals } = ¤t_price.prices {
|
||||
if let Some(price) = intervals.get(interval) {
|
||||
open_charge.subscription_interval = Some(*interval);
|
||||
open_charge.amount = *price as i64;
|
||||
} else {
|
||||
return Err(ApiError::InvalidInput(
|
||||
"Interval is not valid for this subscription!"
|
||||
.to_string(),
|
||||
));
|
||||
}
|
||||
if let Some(interval) = &edit_subscription.interval
|
||||
&& let Price::Recurring { intervals } = ¤t_price.prices
|
||||
{
|
||||
if let Some(price) = intervals.get(interval) {
|
||||
open_charge.subscription_interval = Some(*interval);
|
||||
open_charge.amount = *price as i64;
|
||||
} else {
|
||||
return Err(ApiError::InvalidInput(
|
||||
"Interval is not valid for this subscription!".to_string(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1225,38 +1224,36 @@ pub async fn initiate_payment(
|
||||
}
|
||||
};
|
||||
|
||||
if let Price::Recurring { .. } = price_item.prices {
|
||||
if product.unitary {
|
||||
let user_subscriptions =
|
||||
if let Price::Recurring { .. } = price_item.prices
|
||||
&& product.unitary
|
||||
{
|
||||
let user_subscriptions =
|
||||
user_subscription_item::DBUserSubscription::get_all_user(
|
||||
user.id.into(),
|
||||
&**pool,
|
||||
)
|
||||
.await?;
|
||||
|
||||
let user_products =
|
||||
product_item::DBProductPrice::get_many(
|
||||
&user_subscriptions
|
||||
.iter()
|
||||
.filter(|x| {
|
||||
x.status
|
||||
== SubscriptionStatus::Provisioned
|
||||
})
|
||||
.map(|x| x.price_id)
|
||||
.collect::<Vec<_>>(),
|
||||
&**pool,
|
||||
)
|
||||
.await?;
|
||||
let user_products = product_item::DBProductPrice::get_many(
|
||||
&user_subscriptions
|
||||
.iter()
|
||||
.filter(|x| {
|
||||
x.status == SubscriptionStatus::Provisioned
|
||||
})
|
||||
.map(|x| x.price_id)
|
||||
.collect::<Vec<_>>(),
|
||||
&**pool,
|
||||
)
|
||||
.await?;
|
||||
|
||||
if user_products
|
||||
.into_iter()
|
||||
.any(|x| x.product_id == product.id)
|
||||
{
|
||||
return Err(ApiError::InvalidInput(
|
||||
"You are already subscribed to this product!"
|
||||
.to_string(),
|
||||
));
|
||||
}
|
||||
if user_products
|
||||
.into_iter()
|
||||
.any(|x| x.product_id == product.id)
|
||||
{
|
||||
return Err(ApiError::InvalidInput(
|
||||
"You are already subscribed to this product!"
|
||||
.to_string(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2004,38 +2001,36 @@ pub async fn stripe_webhook(
|
||||
EventType::PaymentMethodAttached => {
|
||||
if let EventObject::PaymentMethod(payment_method) =
|
||||
event.data.object
|
||||
{
|
||||
if let Some(customer_id) =
|
||||
&& let Some(customer_id) =
|
||||
payment_method.customer.map(|x| x.id())
|
||||
{
|
||||
let customer = stripe::Customer::retrieve(
|
||||
&stripe_client,
|
||||
&customer_id,
|
||||
&[],
|
||||
)
|
||||
.await?;
|
||||
|
||||
if customer
|
||||
.invoice_settings
|
||||
.is_none_or(|x| x.default_payment_method.is_none())
|
||||
{
|
||||
let customer = stripe::Customer::retrieve(
|
||||
stripe::Customer::update(
|
||||
&stripe_client,
|
||||
&customer_id,
|
||||
&[],
|
||||
UpdateCustomer {
|
||||
invoice_settings: Some(
|
||||
CustomerInvoiceSettings {
|
||||
default_payment_method: Some(
|
||||
payment_method.id.to_string(),
|
||||
),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
|
||||
if customer
|
||||
.invoice_settings
|
||||
.is_none_or(|x| x.default_payment_method.is_none())
|
||||
{
|
||||
stripe::Customer::update(
|
||||
&stripe_client,
|
||||
&customer_id,
|
||||
UpdateCustomer {
|
||||
invoice_settings: Some(
|
||||
CustomerInvoiceSettings {
|
||||
default_payment_method: Some(
|
||||
payment_method.id.to_string(),
|
||||
),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,13 +79,12 @@ impl TempUser {
|
||||
file_host: &Arc<dyn FileHost + Send + Sync>,
|
||||
redis: &RedisPool,
|
||||
) -> Result<crate::database::models::DBUserId, AuthenticationError> {
|
||||
if let Some(email) = &self.email {
|
||||
if crate::database::models::DBUser::get_by_email(email, client)
|
||||
if let Some(email) = &self.email
|
||||
&& crate::database::models::DBUser::get_by_email(email, client)
|
||||
.await?
|
||||
.is_some()
|
||||
{
|
||||
return Err(AuthenticationError::DuplicateUser);
|
||||
}
|
||||
{
|
||||
return Err(AuthenticationError::DuplicateUser);
|
||||
}
|
||||
|
||||
let user_id =
|
||||
@@ -1269,19 +1268,19 @@ pub async fn delete_auth_provider(
|
||||
.update_user_id(user.id.into(), None, &mut transaction)
|
||||
.await?;
|
||||
|
||||
if delete_provider.provider != AuthProvider::PayPal {
|
||||
if let Some(email) = user.email {
|
||||
send_email(
|
||||
email,
|
||||
"Authentication method removed",
|
||||
&format!(
|
||||
"When logging into Modrinth, you can no longer log in using the {} authentication provider.",
|
||||
delete_provider.provider.as_str()
|
||||
),
|
||||
"If you did not make this change, please contact us immediately through our support channels on Discord or via email (support@modrinth.com).",
|
||||
None,
|
||||
)?;
|
||||
}
|
||||
if delete_provider.provider != AuthProvider::PayPal
|
||||
&& let Some(email) = user.email
|
||||
{
|
||||
send_email(
|
||||
email,
|
||||
"Authentication method removed",
|
||||
&format!(
|
||||
"When logging into Modrinth, you can no longer log in using the {} authentication provider.",
|
||||
delete_provider.provider.as_str()
|
||||
),
|
||||
"If you did not make this change, please contact us immediately through our support channels on Discord or via email (support@modrinth.com).",
|
||||
None,
|
||||
)?;
|
||||
}
|
||||
|
||||
transaction.commit().await?;
|
||||
|
||||
@@ -189,17 +189,16 @@ pub async fn get_project_meta(
|
||||
.iter()
|
||||
.find(|x| Some(x.1.id as i32) == row.flame_project_id)
|
||||
.map(|x| x.0.clone())
|
||||
&& let Some(val) = merged.flame_files.remove(&sha1)
|
||||
{
|
||||
if let Some(val) = merged.flame_files.remove(&sha1) {
|
||||
merged.identified.insert(
|
||||
sha1,
|
||||
IdentifiedFile {
|
||||
file_name: val.file_name.clone(),
|
||||
status: ApprovalType::from_string(&row.status)
|
||||
.unwrap_or(ApprovalType::Unidentified),
|
||||
},
|
||||
);
|
||||
}
|
||||
merged.identified.insert(
|
||||
sha1,
|
||||
IdentifiedFile {
|
||||
file_name: val.file_name.clone(),
|
||||
status: ApprovalType::from_string(&row.status)
|
||||
.unwrap_or(ApprovalType::Unidentified),
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -185,69 +185,69 @@ pub async fn edit_pat(
|
||||
)
|
||||
.await?;
|
||||
|
||||
if let Some(pat) = pat {
|
||||
if pat.user_id == user.id.into() {
|
||||
let mut transaction = pool.begin().await?;
|
||||
if let Some(pat) = pat
|
||||
&& pat.user_id == user.id.into()
|
||||
{
|
||||
let mut transaction = pool.begin().await?;
|
||||
|
||||
if let Some(scopes) = &info.scopes {
|
||||
if scopes.is_restricted() {
|
||||
return Err(ApiError::InvalidInput(
|
||||
"Invalid scopes requested!".to_string(),
|
||||
));
|
||||
}
|
||||
if let Some(scopes) = &info.scopes {
|
||||
if scopes.is_restricted() {
|
||||
return Err(ApiError::InvalidInput(
|
||||
"Invalid scopes requested!".to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
sqlx::query!(
|
||||
"
|
||||
sqlx::query!(
|
||||
"
|
||||
UPDATE pats
|
||||
SET scopes = $1
|
||||
WHERE id = $2
|
||||
",
|
||||
scopes.bits() as i64,
|
||||
pat.id.0
|
||||
)
|
||||
.execute(&mut *transaction)
|
||||
.await?;
|
||||
}
|
||||
if let Some(name) = &info.name {
|
||||
sqlx::query!(
|
||||
"
|
||||
scopes.bits() as i64,
|
||||
pat.id.0
|
||||
)
|
||||
.execute(&mut *transaction)
|
||||
.await?;
|
||||
}
|
||||
if let Some(name) = &info.name {
|
||||
sqlx::query!(
|
||||
"
|
||||
UPDATE pats
|
||||
SET name = $1
|
||||
WHERE id = $2
|
||||
",
|
||||
name,
|
||||
pat.id.0
|
||||
)
|
||||
.execute(&mut *transaction)
|
||||
.await?;
|
||||
name,
|
||||
pat.id.0
|
||||
)
|
||||
.execute(&mut *transaction)
|
||||
.await?;
|
||||
}
|
||||
if let Some(expires) = &info.expires {
|
||||
if expires < &Utc::now() {
|
||||
return Err(ApiError::InvalidInput(
|
||||
"Expire date must be in the future!".to_string(),
|
||||
));
|
||||
}
|
||||
if let Some(expires) = &info.expires {
|
||||
if expires < &Utc::now() {
|
||||
return Err(ApiError::InvalidInput(
|
||||
"Expire date must be in the future!".to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
sqlx::query!(
|
||||
"
|
||||
sqlx::query!(
|
||||
"
|
||||
UPDATE pats
|
||||
SET expires = $1
|
||||
WHERE id = $2
|
||||
",
|
||||
expires,
|
||||
pat.id.0
|
||||
)
|
||||
.execute(&mut *transaction)
|
||||
.await?;
|
||||
}
|
||||
|
||||
transaction.commit().await?;
|
||||
database::models::pat_item::DBPersonalAccessToken::clear_cache(
|
||||
vec![(Some(pat.id), Some(pat.access_token), Some(pat.user_id))],
|
||||
&redis,
|
||||
expires,
|
||||
pat.id.0
|
||||
)
|
||||
.execute(&mut *transaction)
|
||||
.await?;
|
||||
}
|
||||
|
||||
transaction.commit().await?;
|
||||
database::models::pat_item::DBPersonalAccessToken::clear_cache(
|
||||
vec![(Some(pat.id), Some(pat.access_token), Some(pat.user_id))],
|
||||
&redis,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
|
||||
Ok(HttpResponse::NoContent().finish())
|
||||
@@ -276,21 +276,21 @@ pub async fn delete_pat(
|
||||
)
|
||||
.await?;
|
||||
|
||||
if let Some(pat) = pat {
|
||||
if pat.user_id == user.id.into() {
|
||||
let mut transaction = pool.begin().await?;
|
||||
database::models::pat_item::DBPersonalAccessToken::remove(
|
||||
pat.id,
|
||||
&mut transaction,
|
||||
)
|
||||
.await?;
|
||||
transaction.commit().await?;
|
||||
database::models::pat_item::DBPersonalAccessToken::clear_cache(
|
||||
vec![(Some(pat.id), Some(pat.access_token), Some(pat.user_id))],
|
||||
&redis,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
if let Some(pat) = pat
|
||||
&& pat.user_id == user.id.into()
|
||||
{
|
||||
let mut transaction = pool.begin().await?;
|
||||
database::models::pat_item::DBPersonalAccessToken::remove(
|
||||
pat.id,
|
||||
&mut transaction,
|
||||
)
|
||||
.await?;
|
||||
transaction.commit().await?;
|
||||
database::models::pat_item::DBPersonalAccessToken::clear_cache(
|
||||
vec![(Some(pat.id), Some(pat.access_token), Some(pat.user_id))],
|
||||
&redis,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
|
||||
Ok(HttpResponse::NoContent().finish())
|
||||
|
||||
@@ -185,21 +185,21 @@ pub async fn delete(
|
||||
|
||||
let session = DBSession::get(info.into_inner().0, &**pool, &redis).await?;
|
||||
|
||||
if let Some(session) = session {
|
||||
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),
|
||||
Some(session.session),
|
||||
Some(session.user_id),
|
||||
)],
|
||||
&redis,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
if let Some(session) = session
|
||||
&& 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),
|
||||
Some(session.session),
|
||||
Some(session.user_id),
|
||||
)],
|
||||
&redis,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
|
||||
Ok(HttpResponse::NoContent().body(""))
|
||||
|
||||
@@ -401,14 +401,13 @@ async fn broadcast_to_known_local_friends(
|
||||
friend.user_id
|
||||
};
|
||||
|
||||
if friend.accepted {
|
||||
if let Some(socket_ids) =
|
||||
if friend.accepted
|
||||
&& let Some(socket_ids) =
|
||||
sockets.sockets_by_user_id.get(&friend_id.into())
|
||||
{
|
||||
for socket_id in socket_ids.iter() {
|
||||
if let Some(socket) = sockets.sockets.get(&socket_id) {
|
||||
let _ = send_message(socket.value(), &message).await;
|
||||
}
|
||||
{
|
||||
for socket_id in socket_ids.iter() {
|
||||
if let Some(socket) = sockets.sockets.get(&socket_id) {
|
||||
let _ = send_message(socket.value(), &message).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -387,17 +387,16 @@ pub async fn revenue_get(
|
||||
.map(|x| (x.to_string(), HashMap::new()))
|
||||
.collect::<HashMap<_, _>>();
|
||||
for value in payouts_values {
|
||||
if let Some(mod_id) = value.mod_id {
|
||||
if let Some(amount) = value.amount_sum {
|
||||
if let Some(interval_start) = value.interval_start {
|
||||
let id_string = to_base62(mod_id as u64);
|
||||
if !hm.contains_key(&id_string) {
|
||||
hm.insert(id_string.clone(), HashMap::new());
|
||||
}
|
||||
if let Some(hm) = hm.get_mut(&id_string) {
|
||||
hm.insert(interval_start.timestamp(), amount);
|
||||
}
|
||||
}
|
||||
if let Some(mod_id) = value.mod_id
|
||||
&& let Some(amount) = value.amount_sum
|
||||
&& let Some(interval_start) = value.interval_start
|
||||
{
|
||||
let id_string = to_base62(mod_id as u64);
|
||||
if !hm.contains_key(&id_string) {
|
||||
hm.insert(id_string.clone(), HashMap::new());
|
||||
}
|
||||
if let Some(hm) = hm.get_mut(&id_string) {
|
||||
hm.insert(interval_start.timestamp(), amount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -192,10 +192,10 @@ pub async fn collection_get(
|
||||
.map(|x| x.1)
|
||||
.ok();
|
||||
|
||||
if let Some(data) = collection_data {
|
||||
if is_visible_collection(&data, &user_option, false).await? {
|
||||
return Ok(HttpResponse::Ok().json(Collection::from(data)));
|
||||
}
|
||||
if let Some(data) = collection_data
|
||||
&& is_visible_collection(&data, &user_option, false).await?
|
||||
{
|
||||
return Ok(HttpResponse::Ok().json(Collection::from(data)));
|
||||
}
|
||||
Err(ApiError::NotFound)
|
||||
}
|
||||
|
||||
@@ -536,11 +536,9 @@ pub async fn create_payout(
|
||||
Some(true),
|
||||
)
|
||||
.await
|
||||
&& let Some(data) = res.items.first()
|
||||
{
|
||||
if let Some(data) = res.items.first() {
|
||||
payout_item.platform_id =
|
||||
Some(data.payout_item_id.clone());
|
||||
}
|
||||
payout_item.platform_id = Some(data.payout_item_id.clone());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -182,10 +182,10 @@ pub async fn project_get(
|
||||
.map(|x| x.1)
|
||||
.ok();
|
||||
|
||||
if let Some(data) = project_data {
|
||||
if is_visible_project(&data.inner, &user_option, &pool, false).await? {
|
||||
return Ok(HttpResponse::Ok().json(Project::from(data)));
|
||||
}
|
||||
if let Some(data) = project_data
|
||||
&& is_visible_project(&data.inner, &user_option, &pool, false).await?
|
||||
{
|
||||
return Ok(HttpResponse::Ok().json(Project::from(data)));
|
||||
}
|
||||
Err(ApiError::NotFound)
|
||||
}
|
||||
@@ -405,34 +405,36 @@ pub async fn project_edit(
|
||||
.await?;
|
||||
}
|
||||
|
||||
if status.is_searchable() && !project_item.inner.webhook_sent {
|
||||
if let Ok(webhook_url) = dotenvy::var("PUBLIC_DISCORD_WEBHOOK") {
|
||||
crate::util::webhook::send_discord_webhook(
|
||||
project_item.inner.id.into(),
|
||||
&pool,
|
||||
&redis,
|
||||
webhook_url,
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.ok();
|
||||
if status.is_searchable()
|
||||
&& !project_item.inner.webhook_sent
|
||||
&& let Ok(webhook_url) = dotenvy::var("PUBLIC_DISCORD_WEBHOOK")
|
||||
{
|
||||
crate::util::webhook::send_discord_webhook(
|
||||
project_item.inner.id.into(),
|
||||
&pool,
|
||||
&redis,
|
||||
webhook_url,
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.ok();
|
||||
|
||||
sqlx::query!(
|
||||
"
|
||||
sqlx::query!(
|
||||
"
|
||||
UPDATE mods
|
||||
SET webhook_sent = TRUE
|
||||
WHERE id = $1
|
||||
",
|
||||
id as db_ids::DBProjectId,
|
||||
)
|
||||
.execute(&mut *transaction)
|
||||
.await?;
|
||||
}
|
||||
id as db_ids::DBProjectId,
|
||||
)
|
||||
.execute(&mut *transaction)
|
||||
.await?;
|
||||
}
|
||||
|
||||
if user.role.is_mod() {
|
||||
if let Ok(webhook_url) = dotenvy::var("MODERATION_SLACK_WEBHOOK") {
|
||||
crate::util::webhook::send_slack_webhook(
|
||||
if user.role.is_mod()
|
||||
&& let Ok(webhook_url) = dotenvy::var("MODERATION_SLACK_WEBHOOK")
|
||||
{
|
||||
crate::util::webhook::send_slack_webhook(
|
||||
project_item.inner.id.into(),
|
||||
&pool,
|
||||
&redis,
|
||||
@@ -451,7 +453,6 @@ pub async fn project_edit(
|
||||
)
|
||||
.await
|
||||
.ok();
|
||||
}
|
||||
}
|
||||
|
||||
if team_member.is_none_or(|x| !x.accepted) {
|
||||
@@ -694,45 +695,45 @@ pub async fn project_edit(
|
||||
.await?;
|
||||
}
|
||||
|
||||
if let Some(links) = &new_project.link_urls {
|
||||
if !links.is_empty() {
|
||||
if !perms.contains(ProjectPermissions::EDIT_DETAILS) {
|
||||
return Err(ApiError::CustomAuthentication(
|
||||
if let Some(links) = &new_project.link_urls
|
||||
&& !links.is_empty()
|
||||
{
|
||||
if !perms.contains(ProjectPermissions::EDIT_DETAILS) {
|
||||
return Err(ApiError::CustomAuthentication(
|
||||
"You do not have the permissions to edit the links of this project!"
|
||||
.to_string(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
let ids_to_delete = links.keys().cloned().collect::<Vec<String>>();
|
||||
// Deletes all links from hashmap- either will be deleted or be replaced
|
||||
sqlx::query!(
|
||||
"
|
||||
let ids_to_delete = links.keys().cloned().collect::<Vec<String>>();
|
||||
// Deletes all links from hashmap- either will be deleted or be replaced
|
||||
sqlx::query!(
|
||||
"
|
||||
DELETE FROM mods_links
|
||||
WHERE joining_mod_id = $1 AND joining_platform_id IN (
|
||||
SELECT id FROM link_platforms WHERE name = ANY($2)
|
||||
)
|
||||
",
|
||||
id as db_ids::DBProjectId,
|
||||
&ids_to_delete
|
||||
)
|
||||
.execute(&mut *transaction)
|
||||
.await?;
|
||||
id as db_ids::DBProjectId,
|
||||
&ids_to_delete
|
||||
)
|
||||
.execute(&mut *transaction)
|
||||
.await?;
|
||||
|
||||
for (platform, url) in links {
|
||||
if let Some(url) = url {
|
||||
let platform_id =
|
||||
db_models::categories::LinkPlatform::get_id(
|
||||
platform,
|
||||
&mut *transaction,
|
||||
)
|
||||
.await?
|
||||
.ok_or_else(|| {
|
||||
ApiError::InvalidInput(format!(
|
||||
"Platform {} does not exist.",
|
||||
platform.clone()
|
||||
))
|
||||
})?;
|
||||
sqlx::query!(
|
||||
for (platform, url) in links {
|
||||
if let Some(url) = url {
|
||||
let platform_id = db_models::categories::LinkPlatform::get_id(
|
||||
platform,
|
||||
&mut *transaction,
|
||||
)
|
||||
.await?
|
||||
.ok_or_else(|| {
|
||||
ApiError::InvalidInput(format!(
|
||||
"Platform {} does not exist.",
|
||||
platform.clone()
|
||||
))
|
||||
})?;
|
||||
sqlx::query!(
|
||||
"
|
||||
INSERT INTO mods_links (joining_mod_id, joining_platform_id, url)
|
||||
VALUES ($1, $2, $3)
|
||||
@@ -743,7 +744,6 @@ pub async fn project_edit(
|
||||
)
|
||||
.execute(&mut *transaction)
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2455,7 +2455,7 @@ pub async fn project_get_organization(
|
||||
organization,
|
||||
team_members,
|
||||
);
|
||||
return Ok(HttpResponse::Ok().json(organization));
|
||||
Ok(HttpResponse::Ok().json(organization))
|
||||
} else {
|
||||
Err(ApiError::NotFound)
|
||||
}
|
||||
|
||||
@@ -767,12 +767,13 @@ pub async fn edit_team_member(
|
||||
));
|
||||
}
|
||||
|
||||
if let Some(new_permissions) = edit_member.permissions {
|
||||
if !permissions.contains(new_permissions) {
|
||||
return Err(ApiError::InvalidInput(
|
||||
"The new permissions have permissions that you don't have".to_string(),
|
||||
));
|
||||
}
|
||||
if let Some(new_permissions) = edit_member.permissions
|
||||
&& !permissions.contains(new_permissions)
|
||||
{
|
||||
return Err(ApiError::InvalidInput(
|
||||
"The new permissions have permissions that you don't have"
|
||||
.to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
if edit_member.organization_permissions.is_some() {
|
||||
@@ -800,13 +801,12 @@ pub async fn edit_team_member(
|
||||
}
|
||||
|
||||
if let Some(new_permissions) = edit_member.organization_permissions
|
||||
&& !organization_permissions.contains(new_permissions)
|
||||
{
|
||||
if !organization_permissions.contains(new_permissions) {
|
||||
return Err(ApiError::InvalidInput(
|
||||
return Err(ApiError::InvalidInput(
|
||||
"The new organization permissions have permissions that you don't have"
|
||||
.to_string(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
if edit_member.permissions.is_some()
|
||||
@@ -822,13 +822,13 @@ pub async fn edit_team_member(
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(payouts_split) = edit_member.payouts_split {
|
||||
if payouts_split < Decimal::ZERO || payouts_split > Decimal::from(5000)
|
||||
{
|
||||
return Err(ApiError::InvalidInput(
|
||||
"Payouts split must be between 0 and 5000!".to_string(),
|
||||
));
|
||||
}
|
||||
if let Some(payouts_split) = edit_member.payouts_split
|
||||
&& (payouts_split < Decimal::ZERO
|
||||
|| payouts_split > Decimal::from(5000))
|
||||
{
|
||||
return Err(ApiError::InvalidInput(
|
||||
"Payouts split must be between 0 and 5000!".to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
DBTeamMember::edit_team_member(
|
||||
@@ -883,13 +883,13 @@ pub async fn transfer_ownership(
|
||||
DBTeam::get_association(id.into(), &**pool).await?;
|
||||
if let Some(TeamAssociationId::Project(pid)) = team_association_id {
|
||||
let result = DBProject::get_id(pid, &**pool, &redis).await?;
|
||||
if let Some(project_item) = result {
|
||||
if project_item.inner.organization_id.is_some() {
|
||||
return Err(ApiError::InvalidInput(
|
||||
if let Some(project_item) = result
|
||||
&& project_item.inner.organization_id.is_some()
|
||||
{
|
||||
return Err(ApiError::InvalidInput(
|
||||
"You cannot transfer ownership of a project team that is owend by an organization"
|
||||
.to_string(),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -289,36 +289,33 @@ pub async fn thread_get(
|
||||
.await?
|
||||
.1;
|
||||
|
||||
if let Some(mut data) = thread_data {
|
||||
if is_authorized_thread(&data, &user, &pool).await? {
|
||||
let authors = &mut data.members;
|
||||
if let Some(mut data) = thread_data
|
||||
&& is_authorized_thread(&data, &user, &pool).await?
|
||||
{
|
||||
let authors = &mut data.members;
|
||||
|
||||
authors.append(
|
||||
&mut data
|
||||
.messages
|
||||
.iter()
|
||||
.filter_map(|x| {
|
||||
if x.hide_identity && !user.role.is_mod() {
|
||||
None
|
||||
} else {
|
||||
x.author_id
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
);
|
||||
authors.append(
|
||||
&mut data
|
||||
.messages
|
||||
.iter()
|
||||
.filter_map(|x| {
|
||||
if x.hide_identity && !user.role.is_mod() {
|
||||
None
|
||||
} else {
|
||||
x.author_id
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
);
|
||||
|
||||
let users: Vec<User> = database::models::DBUser::get_many_ids(
|
||||
authors, &**pool, &redis,
|
||||
)
|
||||
.await?
|
||||
.into_iter()
|
||||
.map(From::from)
|
||||
.collect();
|
||||
let users: Vec<User> =
|
||||
database::models::DBUser::get_many_ids(authors, &**pool, &redis)
|
||||
.await?
|
||||
.into_iter()
|
||||
.map(From::from)
|
||||
.collect();
|
||||
|
||||
return Ok(
|
||||
HttpResponse::Ok().json(Thread::from(data, users, &user))
|
||||
);
|
||||
}
|
||||
return Ok(HttpResponse::Ok().json(Thread::from(data, users, &user)));
|
||||
}
|
||||
Err(ApiError::NotFound)
|
||||
}
|
||||
@@ -454,33 +451,32 @@ pub async fn thread_send_message(
|
||||
)
|
||||
.await?;
|
||||
|
||||
if let Some(project) = project {
|
||||
if project.inner.status != ProjectStatus::Processing
|
||||
&& user.role.is_mod()
|
||||
{
|
||||
let members =
|
||||
database::models::DBTeamMember::get_from_team_full(
|
||||
project.inner.team_id,
|
||||
&**pool,
|
||||
&redis,
|
||||
)
|
||||
.await?;
|
||||
|
||||
NotificationBuilder {
|
||||
body: NotificationBody::ModeratorMessage {
|
||||
thread_id: thread.id.into(),
|
||||
message_id: id.into(),
|
||||
project_id: Some(project.inner.id.into()),
|
||||
report_id: None,
|
||||
},
|
||||
}
|
||||
.insert_many(
|
||||
members.into_iter().map(|x| x.user_id).collect(),
|
||||
&mut transaction,
|
||||
if let Some(project) = project
|
||||
&& project.inner.status != ProjectStatus::Processing
|
||||
&& user.role.is_mod()
|
||||
{
|
||||
let members =
|
||||
database::models::DBTeamMember::get_from_team_full(
|
||||
project.inner.team_id,
|
||||
&**pool,
|
||||
&redis,
|
||||
)
|
||||
.await?;
|
||||
|
||||
NotificationBuilder {
|
||||
body: NotificationBody::ModeratorMessage {
|
||||
thread_id: thread.id.into(),
|
||||
message_id: id.into(),
|
||||
project_id: Some(project.inner.id.into()),
|
||||
report_id: None,
|
||||
},
|
||||
}
|
||||
.insert_many(
|
||||
members.into_iter().map(|x| x.user_id).collect(),
|
||||
&mut transaction,
|
||||
&redis,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
} else if let Some(report_id) = thread.report_id {
|
||||
let report = database::models::report_item::DBReport::get(
|
||||
|
||||
@@ -522,10 +522,10 @@ async fn version_create_inner(
|
||||
.fetch_optional(pool)
|
||||
.await?;
|
||||
|
||||
if let Some(project_status) = project_status {
|
||||
if project_status.status == ProjectStatus::Processing.as_str() {
|
||||
moderation_queue.projects.insert(project_id.into());
|
||||
}
|
||||
if let Some(project_status) = project_status
|
||||
&& project_status.status == ProjectStatus::Processing.as_str()
|
||||
{
|
||||
moderation_queue.projects.insert(project_id.into());
|
||||
}
|
||||
|
||||
Ok(HttpResponse::Ok().json(response))
|
||||
@@ -871,16 +871,16 @@ pub async fn upload_file(
|
||||
ref format,
|
||||
ref files,
|
||||
} = validation_result
|
||||
&& dependencies.is_empty()
|
||||
{
|
||||
if dependencies.is_empty() {
|
||||
let hashes: Vec<Vec<u8>> = format
|
||||
.files
|
||||
.iter()
|
||||
.filter_map(|x| x.hashes.get(&PackFileHash::Sha1))
|
||||
.map(|x| x.as_bytes().to_vec())
|
||||
.collect();
|
||||
let hashes: Vec<Vec<u8>> = format
|
||||
.files
|
||||
.iter()
|
||||
.filter_map(|x| x.hashes.get(&PackFileHash::Sha1))
|
||||
.map(|x| x.as_bytes().to_vec())
|
||||
.collect();
|
||||
|
||||
let res = sqlx::query!(
|
||||
let res = sqlx::query!(
|
||||
"
|
||||
SELECT v.id version_id, v.mod_id project_id, h.hash hash FROM hashes h
|
||||
INNER JOIN files f on h.file_id = f.id
|
||||
@@ -892,45 +892,44 @@ pub async fn upload_file(
|
||||
.fetch_all(&mut **transaction)
|
||||
.await?;
|
||||
|
||||
for file in &format.files {
|
||||
if let Some(dep) = res.iter().find(|x| {
|
||||
Some(&*x.hash)
|
||||
== file
|
||||
.hashes
|
||||
.get(&PackFileHash::Sha1)
|
||||
.map(|x| x.as_bytes())
|
||||
}) {
|
||||
dependencies.push(DependencyBuilder {
|
||||
project_id: Some(models::DBProjectId(dep.project_id)),
|
||||
version_id: Some(models::DBVersionId(dep.version_id)),
|
||||
file_name: None,
|
||||
dependency_type: DependencyType::Embedded.to_string(),
|
||||
});
|
||||
} else if let Some(first_download) = file.downloads.first() {
|
||||
dependencies.push(DependencyBuilder {
|
||||
project_id: None,
|
||||
version_id: None,
|
||||
file_name: Some(
|
||||
first_download
|
||||
.rsplit('/')
|
||||
.next()
|
||||
.unwrap_or(first_download)
|
||||
.to_string(),
|
||||
),
|
||||
dependency_type: DependencyType::Embedded.to_string(),
|
||||
});
|
||||
}
|
||||
for file in &format.files {
|
||||
if let Some(dep) = res.iter().find(|x| {
|
||||
Some(&*x.hash)
|
||||
== file
|
||||
.hashes
|
||||
.get(&PackFileHash::Sha1)
|
||||
.map(|x| x.as_bytes())
|
||||
}) {
|
||||
dependencies.push(DependencyBuilder {
|
||||
project_id: Some(models::DBProjectId(dep.project_id)),
|
||||
version_id: Some(models::DBVersionId(dep.version_id)),
|
||||
file_name: None,
|
||||
dependency_type: DependencyType::Embedded.to_string(),
|
||||
});
|
||||
} else if let Some(first_download) = file.downloads.first() {
|
||||
dependencies.push(DependencyBuilder {
|
||||
project_id: None,
|
||||
version_id: None,
|
||||
file_name: Some(
|
||||
first_download
|
||||
.rsplit('/')
|
||||
.next()
|
||||
.unwrap_or(first_download)
|
||||
.to_string(),
|
||||
),
|
||||
dependency_type: DependencyType::Embedded.to_string(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
for file in files {
|
||||
if !file.is_empty() {
|
||||
dependencies.push(DependencyBuilder {
|
||||
project_id: None,
|
||||
version_id: None,
|
||||
file_name: Some(file.to_string()),
|
||||
dependency_type: DependencyType::Embedded.to_string(),
|
||||
});
|
||||
}
|
||||
for file in files {
|
||||
if !file.is_empty() {
|
||||
dependencies.push(DependencyBuilder {
|
||||
project_id: None,
|
||||
version_id: None,
|
||||
file_name: Some(file.to_string()),
|
||||
dependency_type: DependencyType::Embedded.to_string(),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -974,10 +973,10 @@ pub async fn upload_file(
|
||||
));
|
||||
}
|
||||
|
||||
if let ValidationResult::Warning(msg) = validation_result {
|
||||
if primary {
|
||||
return Err(CreateError::InvalidInput(msg.to_string()));
|
||||
}
|
||||
if let ValidationResult::Warning(msg) = validation_result
|
||||
&& primary
|
||||
{
|
||||
return Err(CreateError::InvalidInput(msg.to_string()));
|
||||
}
|
||||
|
||||
let url = format!("{cdn_url}/{file_path_encode}");
|
||||
|
||||
@@ -148,65 +148,55 @@ pub async fn get_update_from_hash(
|
||||
&redis,
|
||||
)
|
||||
.await?
|
||||
{
|
||||
if let Some(project) = database::models::DBProject::get_id(
|
||||
&& let Some(project) = database::models::DBProject::get_id(
|
||||
file.project_id,
|
||||
&**pool,
|
||||
&redis,
|
||||
)
|
||||
.await?
|
||||
{
|
||||
let mut versions = database::models::DBVersion::get_many(
|
||||
&project.versions,
|
||||
&**pool,
|
||||
&redis,
|
||||
)
|
||||
.await?
|
||||
.into_iter()
|
||||
.filter(|x| {
|
||||
let mut bool = true;
|
||||
if let Some(version_types) = &update_data.version_types {
|
||||
bool &= version_types
|
||||
.iter()
|
||||
.any(|y| y.as_str() == x.inner.version_type);
|
||||
}
|
||||
if let Some(loaders) = &update_data.loaders {
|
||||
bool &= x.loaders.iter().any(|y| loaders.contains(y));
|
||||
}
|
||||
if let Some(loader_fields) = &update_data.loader_fields {
|
||||
for (key, values) in loader_fields {
|
||||
bool &= if let Some(x_vf) = x
|
||||
.version_fields
|
||||
.iter()
|
||||
.find(|y| y.field_name == *key)
|
||||
{
|
||||
values
|
||||
.iter()
|
||||
.any(|v| x_vf.value.contains_json_value(v))
|
||||
} else {
|
||||
true
|
||||
};
|
||||
}
|
||||
}
|
||||
bool
|
||||
})
|
||||
.sorted();
|
||||
|
||||
if let Some(first) = versions.next_back() {
|
||||
if !is_visible_version(
|
||||
&first.inner,
|
||||
&user_option,
|
||||
&pool,
|
||||
&redis,
|
||||
)
|
||||
.await?
|
||||
{
|
||||
return Err(ApiError::NotFound);
|
||||
}
|
||||
|
||||
return Ok(HttpResponse::Ok()
|
||||
.json(models::projects::Version::from(first)));
|
||||
{
|
||||
let mut versions = database::models::DBVersion::get_many(
|
||||
&project.versions,
|
||||
&**pool,
|
||||
&redis,
|
||||
)
|
||||
.await?
|
||||
.into_iter()
|
||||
.filter(|x| {
|
||||
let mut bool = true;
|
||||
if let Some(version_types) = &update_data.version_types {
|
||||
bool &= version_types
|
||||
.iter()
|
||||
.any(|y| y.as_str() == x.inner.version_type);
|
||||
}
|
||||
if let Some(loaders) = &update_data.loaders {
|
||||
bool &= x.loaders.iter().any(|y| loaders.contains(y));
|
||||
}
|
||||
if let Some(loader_fields) = &update_data.loader_fields {
|
||||
for (key, values) in loader_fields {
|
||||
bool &= if let Some(x_vf) =
|
||||
x.version_fields.iter().find(|y| y.field_name == *key)
|
||||
{
|
||||
values.iter().any(|v| x_vf.value.contains_json_value(v))
|
||||
} else {
|
||||
true
|
||||
};
|
||||
}
|
||||
}
|
||||
bool
|
||||
})
|
||||
.sorted();
|
||||
|
||||
if let Some(first) = versions.next_back() {
|
||||
if !is_visible_version(&first.inner, &user_option, &pool, &redis)
|
||||
.await?
|
||||
{
|
||||
return Err(ApiError::NotFound);
|
||||
}
|
||||
|
||||
return Ok(
|
||||
HttpResponse::Ok().json(models::projects::Version::from(first))
|
||||
);
|
||||
}
|
||||
}
|
||||
Err(ApiError::NotFound)
|
||||
@@ -398,13 +388,12 @@ pub async fn update_files(
|
||||
if let Some(version) = versions
|
||||
.iter()
|
||||
.find(|x| x.inner.project_id == file.project_id)
|
||||
&& let Some(hash) = file.hashes.get(&algorithm)
|
||||
{
|
||||
if let Some(hash) = file.hashes.get(&algorithm) {
|
||||
response.insert(
|
||||
hash.clone(),
|
||||
models::projects::Version::from(version.clone()),
|
||||
);
|
||||
}
|
||||
response.insert(
|
||||
hash.clone(),
|
||||
models::projects::Version::from(version.clone()),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -484,69 +473,59 @@ pub async fn update_individual_files(
|
||||
|
||||
for project in projects {
|
||||
for file in files.iter().filter(|x| x.project_id == project.inner.id) {
|
||||
if let Some(hash) = file.hashes.get(&algorithm) {
|
||||
if let Some(query_file) =
|
||||
if let Some(hash) = file.hashes.get(&algorithm)
|
||||
&& let Some(query_file) =
|
||||
update_data.hashes.iter().find(|x| &x.hash == hash)
|
||||
{
|
||||
let version = all_versions
|
||||
.iter()
|
||||
.filter(|x| x.inner.project_id == file.project_id)
|
||||
.filter(|x| {
|
||||
let mut bool = true;
|
||||
{
|
||||
let version = all_versions
|
||||
.iter()
|
||||
.filter(|x| x.inner.project_id == file.project_id)
|
||||
.filter(|x| {
|
||||
let mut bool = true;
|
||||
|
||||
if let Some(version_types) =
|
||||
&query_file.version_types
|
||||
{
|
||||
bool &= version_types.iter().any(|y| {
|
||||
y.as_str() == x.inner.version_type
|
||||
});
|
||||
}
|
||||
if let Some(loaders) = &query_file.loaders {
|
||||
bool &= x
|
||||
.loaders
|
||||
.iter()
|
||||
.any(|y| loaders.contains(y));
|
||||
}
|
||||
|
||||
if let Some(loader_fields) =
|
||||
&query_file.loader_fields
|
||||
{
|
||||
for (key, values) in loader_fields {
|
||||
bool &= if let Some(x_vf) = x
|
||||
.version_fields
|
||||
.iter()
|
||||
.find(|y| y.field_name == *key)
|
||||
{
|
||||
values.iter().any(|v| {
|
||||
x_vf.value.contains_json_value(v)
|
||||
})
|
||||
} else {
|
||||
true
|
||||
};
|
||||
}
|
||||
}
|
||||
bool
|
||||
})
|
||||
.sorted()
|
||||
.next_back();
|
||||
|
||||
if let Some(version) = version {
|
||||
if is_visible_version(
|
||||
&version.inner,
|
||||
&user_option,
|
||||
&pool,
|
||||
&redis,
|
||||
)
|
||||
.await?
|
||||
{
|
||||
response.insert(
|
||||
hash.clone(),
|
||||
models::projects::Version::from(
|
||||
version.clone(),
|
||||
),
|
||||
);
|
||||
if let Some(version_types) = &query_file.version_types {
|
||||
bool &= version_types
|
||||
.iter()
|
||||
.any(|y| y.as_str() == x.inner.version_type);
|
||||
}
|
||||
}
|
||||
if let Some(loaders) = &query_file.loaders {
|
||||
bool &=
|
||||
x.loaders.iter().any(|y| loaders.contains(y));
|
||||
}
|
||||
|
||||
if let Some(loader_fields) = &query_file.loader_fields {
|
||||
for (key, values) in loader_fields {
|
||||
bool &= if let Some(x_vf) = x
|
||||
.version_fields
|
||||
.iter()
|
||||
.find(|y| y.field_name == *key)
|
||||
{
|
||||
values.iter().any(|v| {
|
||||
x_vf.value.contains_json_value(v)
|
||||
})
|
||||
} else {
|
||||
true
|
||||
};
|
||||
}
|
||||
}
|
||||
bool
|
||||
})
|
||||
.sorted()
|
||||
.next_back();
|
||||
|
||||
if let Some(version) = version
|
||||
&& is_visible_version(
|
||||
&version.inner,
|
||||
&user_option,
|
||||
&pool,
|
||||
&redis,
|
||||
)
|
||||
.await?
|
||||
{
|
||||
response.insert(
|
||||
hash.clone(),
|
||||
models::projects::Version::from(version.clone()),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,13 +106,12 @@ pub async fn version_project_get_helper(
|
||||
|| x.inner.version_number == id.1
|
||||
});
|
||||
|
||||
if let Some(version) = version {
|
||||
if is_visible_version(&version.inner, &user_option, &pool, &redis)
|
||||
if let Some(version) = version
|
||||
&& is_visible_version(&version.inner, &user_option, &pool, &redis)
|
||||
.await?
|
||||
{
|
||||
return Ok(HttpResponse::Ok()
|
||||
.json(models::projects::Version::from(version)));
|
||||
}
|
||||
{
|
||||
return Ok(HttpResponse::Ok()
|
||||
.json(models::projects::Version::from(version)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,12 +189,12 @@ pub async fn version_get_helper(
|
||||
.map(|x| x.1)
|
||||
.ok();
|
||||
|
||||
if let Some(data) = version_data {
|
||||
if is_visible_version(&data.inner, &user_option, &pool, &redis).await? {
|
||||
return Ok(
|
||||
HttpResponse::Ok().json(models::projects::Version::from(data))
|
||||
);
|
||||
}
|
||||
if let Some(data) = version_data
|
||||
&& is_visible_version(&data.inner, &user_option, &pool, &redis).await?
|
||||
{
|
||||
return Ok(
|
||||
HttpResponse::Ok().json(models::projects::Version::from(data))
|
||||
);
|
||||
}
|
||||
|
||||
Err(ApiError::NotFound)
|
||||
|
||||
Reference in New Issue
Block a user