Skip to content

Commit 6b875ff

Browse files
committed
Merge branch 'main' into errors-patch
2 parents 5b1eeb2 + af0de37 commit 6b875ff

File tree

10 files changed

+115
-48
lines changed

10 files changed

+115
-48
lines changed

.sqlx/query-01959e9a4fdc1c6b0d9dbeff80c79a58e0bae2d79af6c2b9e53ead7d9b6e214d.json

Lines changed: 40 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "geode-index"
3-
version = "0.44.1"
3+
version = "0.45.0"
44
edition = "2021"
55

66
[dependencies]

src/auth/github.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,9 @@ impl GithubClient {
113113

114114
if !res.status().is_success() {
115115
log::error!(
116-
"GitHub OAuth device flow start request failed with code {}",
117-
res.status()
116+
"GitHub OAuth device flow failed to start. Error code: {}. Body: {}",
117+
res.status(),
118+
res.text().await.unwrap_or("No body received".into())
118119
);
119120
return Err(AuthenticationError::InternalError(
120121
"Failed to start GitHub device flow".into(),
Lines changed: 11 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::types::api::ApiError;
1+
use crate::database::DatabaseError;
22
use chrono::{Days, Utc};
33
use sqlx::types::ipnetwork::IpNetwork;
44
use sqlx::PgConnection;
@@ -7,7 +7,7 @@ pub async fn create(
77
ip: IpNetwork,
88
mod_version_id: i32,
99
conn: &mut PgConnection,
10-
) -> Result<bool, ApiError> {
10+
) -> Result<bool, DatabaseError> {
1111
let result = sqlx::query!(
1212
"INSERT INTO mod_downloads (mod_version_id, ip)
1313
VALUES ($1, $2)
@@ -17,13 +17,8 @@ pub async fn create(
1717
)
1818
.execute(&mut *conn)
1919
.await
20-
.map_err(|e| {
21-
log::error!(
22-
"Failed to insert new download for mod_version id {}: {}",
23-
mod_version_id,
24-
e
25-
);
26-
ApiError::DbError
20+
.inspect_err(|e| {
21+
log::error!("Failed to insert new download for mod_version id {mod_version_id}: {e}");
2722
})?;
2823

2924
Ok(result.rows_affected() > 0)
@@ -33,8 +28,8 @@ pub async fn has_downloaded_mod(
3328
ip: IpNetwork,
3429
mod_id: &str,
3530
conn: &mut PgConnection,
36-
) -> Result<bool, ApiError> {
37-
Ok(sqlx::query!(
31+
) -> Result<bool, DatabaseError> {
32+
sqlx::query!(
3833
"SELECT ip FROM mod_downloads md
3934
INNER JOIN mod_versions mv ON md.mod_version_id = mv.id
4035
WHERE mv.mod_id = $1
@@ -45,14 +40,12 @@ pub async fn has_downloaded_mod(
4540
)
4641
.fetch_optional(&mut *conn)
4742
.await
48-
.map_err(|e| {
49-
log::error!("Failed to check if mod has been downloaded: {}", e);
50-
ApiError::DbError
51-
})?
52-
.is_some())
43+
.inspect_err(|e| log::error!("mod_downloads::has_downloaded_mod query error: {e}"))
44+
.map_err(|e| e.into())
45+
.map(|x| x.is_some())
5346
}
5447

55-
pub async fn cleanup(conn: &mut PgConnection) -> Result<(), ApiError> {
48+
pub async fn cleanup(conn: &mut PgConnection) -> Result<(), DatabaseError> {
5649
let date = Utc::now().checked_sub_days(Days::new(30)).unwrap();
5750
sqlx::query!(
5851
"DELETE FROM mod_downloads md
@@ -61,10 +54,7 @@ pub async fn cleanup(conn: &mut PgConnection) -> Result<(), ApiError> {
6154
)
6255
.execute(&mut *conn)
6356
.await
64-
.map_err(|e| {
65-
log::error!("Failed to cleanup downloads: {}", e);
66-
ApiError::DbError
67-
})?;
57+
.inspect_err(|e| log::error!("mod_downloads::cleanup query failed: {e}"))?;
6858

6959
Ok(())
7060
}

src/database/repository/mod_tags.rs

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,40 @@ pub async fn get_all_writable(conn: &mut PgConnection) -> Result<Vec<Tag>, Datab
2727
Ok(tags)
2828
}
2929

30+
pub async fn get_allowed_for_mod(
31+
id: &str,
32+
conn: &mut PgConnection,
33+
) -> Result<Vec<Tag>, DatabaseError> {
34+
let mut writable = get_all_writable(&mut *conn).await?;
35+
let allowed_readonly = sqlx::query!(
36+
"SELECT DISTINCT
37+
t.id,
38+
t.name,
39+
t.display_name,
40+
t.is_readonly
41+
FROM mod_tags t
42+
INNER JOIN mods_mod_tags mmt ON mmt.tag_id = t.id
43+
WHERE t.is_readonly = true
44+
AND mmt.mod_id = $1",
45+
id
46+
)
47+
.fetch_all(&mut *conn)
48+
.await
49+
.inspect_err(|e| log::error!("mod_tags::get_allowed_for_mod failed: {e}"))?
50+
.into_iter()
51+
.map(|i| Tag {
52+
id: i.id,
53+
display_name: i.display_name.unwrap_or(i.name.clone()),
54+
name: i.name,
55+
is_readonly: i.is_readonly,
56+
})
57+
.collect::<Vec<Tag>>();
58+
59+
writable.extend(allowed_readonly);
60+
61+
return Ok(writable);
62+
}
63+
3064
pub async fn get_all(conn: &mut PgConnection) -> Result<Vec<Tag>, DatabaseError> {
3165
let tags = sqlx::query!(
3266
"SELECT
@@ -88,13 +122,13 @@ pub async fn update_for_mod(
88122

89123
let insertable = tags
90124
.iter()
91-
.filter(|t| !existing.iter().any(|e| e.id == t.id))
125+
.filter(|t| !t.is_readonly && !existing.iter().any(|e| e.id == t.id))
92126
.map(|x| x.id)
93127
.collect::<Vec<_>>();
94128

95129
let deletable = existing
96130
.iter()
97-
.filter(|e| !e.is_readonly && !tags.iter().any(|t| e.id == t.id))
131+
.filter(|i| !i.is_readonly && !tags.iter().any(|j| i.id == j.id))
98132
.map(|x| x.id)
99133
.collect::<Vec<_>>();
100134

src/endpoints/mod_versions.rs

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -211,23 +211,25 @@ pub async fn download_version(
211211
));
212212
};
213213

214-
let net: IpNetwork = ip.parse().or(Err(ApiError::InternalError))?;
214+
let net = ip.parse::<IpNetwork>().ok();
215215

216-
let mut tx = pool.begin().await?;
216+
if let Some(net) = net {
217+
let mut tx = pool.begin().await?;
217218

218-
let downloaded_mod_previously =
219-
mod_downloads::has_downloaded_mod(net, &mod_version.mod_id, &mut tx).await?;
220-
let inserted = mod_downloads::create(net, mod_version.id, &mut tx).await?;
219+
let downloaded_mod_previously =
220+
mod_downloads::has_downloaded_mod(net, &mod_version.mod_id, &mut tx).await?;
221+
let inserted = mod_downloads::create(net, mod_version.id, &mut tx).await?;
221222

222-
if inserted {
223-
mod_versions::increment_downloads(mod_version.id, &mut tx).await?;
223+
if inserted {
224+
mod_versions::increment_downloads(mod_version.id, &mut tx).await?;
224225

225-
if !downloaded_mod_previously {
226-
mods::increment_downloads(&mod_version.mod_id, &mut tx).await?;
226+
if !downloaded_mod_previously {
227+
mods::increment_downloads(&mod_version.mod_id, &mut tx).await?;
228+
}
227229
}
228-
}
229230

230-
let _ = tx.commit().await;
231+
let _ = tx.commit().await;
232+
}
231233

232234
Ok(HttpResponse::Found()
233235
.append_header(("Location", url))
@@ -363,7 +365,7 @@ pub async fn create_version(
363365
}
364366
if let Some(tags) = &json.tags {
365367
if !tags.is_empty() {
366-
let tags = models::tag::parse_tag_list(tags, &mut tx).await?;
368+
let tags = models::tag::parse_tag_list(tags, &the_mod.id, &mut tx).await?;
367369
mod_tags::update_for_mod(&the_mod.id, &tags, &mut tx).await?;
368370
}
369371
}
@@ -480,7 +482,7 @@ pub async fn update_version(
480482

481483
// Update tags with data from mod.json
482484
let tags = if let Some(tags) = &json.tags {
483-
models::tag::parse_tag_list(tags, &mut tx).await?
485+
models::tag::parse_tag_list(tags, &the_mod.id, &mut tx).await?
484486
} else {
485487
vec![]
486488
};

src/endpoints/mods.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use crate::extractors::auth::Auth;
1313
use crate::mod_zip;
1414
use crate::types::api::{create_download_link, ApiResponse};
1515
use crate::types::mod_json::ModJson;
16+
use crate::types::models;
1617
use crate::types::models::incompatibility::Incompatibility;
1718
use crate::types::models::mod_entity::{Mod, ModUpdate};
1819
use crate::types::models::mod_gd_version::{GDVersionEnum, VerPlatform};
@@ -22,7 +23,6 @@ use crate::webhook::discord::DiscordWebhook;
2223
use actix_web::{get, post, put, web, HttpResponse, Responder};
2324
use serde::Deserialize;
2425
use sqlx::Acquire;
25-
use crate::types::models;
2626

2727
#[derive(Deserialize, Default)]
2828
#[serde(rename_all = "snake_case")]
@@ -185,7 +185,7 @@ pub async fn create(
185185
}
186186

187187
if let Some(tags) = &json.tags {
188-
let tag_list = models::tag::parse_tag_list(tags, &mut tx).await?;
188+
let tag_list = models::tag::parse_tag_list(tags, &the_mod.id, &mut tx).await?;
189189
mod_tags::update_for_mod(&the_mod.id, &tag_list, &mut tx).await?;
190190
}
191191
if let Some(l) = json.links.clone() {
@@ -348,8 +348,8 @@ pub async fn update_mod(
348348
base_url: data.app_url().to_string(),
349349
featured: payload.featured,
350350
}
351-
.to_discord_webhook()
352-
.send(data.webhook_url());
351+
.to_discord_webhook()
352+
.send(data.webhook_url());
353353
}
354354
}
355355
}

src/mod_zip.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@ use image::{DynamicImage, GenericImageView};
99
use zip::read::ZipFile;
1010
use zip::ZipArchive;
1111

12-
use crate::types::api::ApiError;
13-
1412
pub fn extract_mod_logo(file: &mut ZipFile<Cursor<Bytes>>) -> Result<Vec<u8>, ApiError> {
1513
let mut logo: Vec<u8> = Vec::with_capacity(file.size() as usize);
1614
file.read_to_end(&mut logo)

src/types/models/tag.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,13 +99,14 @@ impl Tag {
9999

100100
pub async fn parse_tag_list(
101101
tags: &[String],
102+
mod_id: &str,
102103
conn: &mut PgConnection,
103104
) -> Result<Vec<Tag>, ApiError> {
104105
if tags.is_empty() {
105106
return Ok(vec![]);
106107
}
107108

108-
let db_tags = mod_tags::get_all_writable(&mut *conn).await?;
109+
let db_tags = mod_tags::get_allowed_for_mod(mod_id, &mut *conn).await?;
109110

110111
let mut ret = Vec::with_capacity(tags.len());
111112
for tag in tags {
@@ -119,7 +120,8 @@ pub async fn parse_tag_list(
119120
.join(", ");
120121

121122
return Err(ApiError::BadRequest(format!(
122-
"Tag '{tags}' isn't allowed. Only the following are allowed: '{taglist}'"
123+
"Tag '{}' isn't allowed. Only the following are allowed: '{}'",
124+
tag, taglist
123125
)));
124126
}
125127
}

0 commit comments

Comments
 (0)