diff --git a/Cargo.lock b/Cargo.lock index a83e19cae..a4708e5c4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -343,12 +343,6 @@ dependencies = [ "syn", ] -[[package]] -name = "async_once" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ce4f10ea3abcd6617873bae9f91d1c5332b4a778bd9ce34d0cd517474c1de82" - [[package]] name = "atoi" version = "1.0.0" @@ -527,42 +521,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1db59621ec70f09c5e9b597b220c7a2b43611f4710dc03ceb8748637775692c" -[[package]] -name = "cached" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aadf76ddea74bab35ebeb8f1eb115b9bc04eaee42d8acc0d5f477dee6b176c9a" -dependencies = [ - "async-trait", - "async_once", - "cached_proc_macro", - "cached_proc_macro_types", - "futures", - "hashbrown 0.12.1", - "lazy_static", - "once_cell", - "thiserror", - "tokio", -] - -[[package]] -name = "cached_proc_macro" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bce0f37f9b77c6b93cdf3f060c89adca303d2ab052cacb3c3d1ab543e8cecd2f" -dependencies = [ - "cached_proc_macro_types", - "darling", - "quote", - "syn", -] - -[[package]] -name = "cached_proc_macro_types" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a4f925191b4367301851c6d99b09890311d74b0d43f274c0b34c86d308a3663" - [[package]] name = "castaway" version = "0.1.2" @@ -1460,7 +1418,6 @@ dependencies = [ "base64", "bitflags", "bytes", - "cached", "censor", "chrono", "dashmap", @@ -2730,21 +2687,9 @@ dependencies = [ "pin-project-lite", "signal-hook-registry", "socket2", - "tokio-macros", "winapi", ] -[[package]] -name = "tokio-macros" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "tokio-native-tls" version = "0.3.0" diff --git a/Cargo.toml b/Cargo.toml index 8abd6103a..9c02d2261 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -62,6 +62,4 @@ bytes = "1.1.0" dashmap = "5.2.0" -cached = "0.34.0" - censor = "0.2.0" \ No newline at end of file diff --git a/sqlx-data.json b/sqlx-data.json index d3553a70d..71e62f455 100644 --- a/sqlx-data.json +++ b/sqlx-data.json @@ -207,6 +207,230 @@ }, "query": "\n UPDATE versions\n SET name = $1\n WHERE (id = $2)\n " }, + "0aa77d3833a3f0b2ed198b7928ef4170c6e3dffcf5144050c8b11fcb911e127f": { + "describe": { + "columns": [ + { + "name": "id", + "ordinal": 0, + "type_info": "Int8" + }, + { + "name": "project_type", + "ordinal": 1, + "type_info": "Int4" + }, + { + "name": "title", + "ordinal": 2, + "type_info": "Varchar" + }, + { + "name": "description", + "ordinal": 3, + "type_info": "Varchar" + }, + { + "name": "downloads", + "ordinal": 4, + "type_info": "Int4" + }, + { + "name": "follows", + "ordinal": 5, + "type_info": "Int4" + }, + { + "name": "icon_url", + "ordinal": 6, + "type_info": "Varchar" + }, + { + "name": "body", + "ordinal": 7, + "type_info": "Varchar" + }, + { + "name": "body_url", + "ordinal": 8, + "type_info": "Varchar" + }, + { + "name": "published", + "ordinal": 9, + "type_info": "Timestamptz" + }, + { + "name": "updated", + "ordinal": 10, + "type_info": "Timestamptz" + }, + { + "name": "approved", + "ordinal": 11, + "type_info": "Timestamptz" + }, + { + "name": "status", + "ordinal": 12, + "type_info": "Int4" + }, + { + "name": "issues_url", + "ordinal": 13, + "type_info": "Varchar" + }, + { + "name": "source_url", + "ordinal": 14, + "type_info": "Varchar" + }, + { + "name": "wiki_url", + "ordinal": 15, + "type_info": "Varchar" + }, + { + "name": "discord_url", + "ordinal": 16, + "type_info": "Varchar" + }, + { + "name": "license_url", + "ordinal": 17, + "type_info": "Varchar" + }, + { + "name": "team_id", + "ordinal": 18, + "type_info": "Int8" + }, + { + "name": "client_side", + "ordinal": 19, + "type_info": "Int4" + }, + { + "name": "server_side", + "ordinal": 20, + "type_info": "Int4" + }, + { + "name": "license", + "ordinal": 21, + "type_info": "Int4" + }, + { + "name": "slug", + "ordinal": 22, + "type_info": "Varchar" + }, + { + "name": "moderation_message", + "ordinal": 23, + "type_info": "Varchar" + }, + { + "name": "moderation_message_body", + "ordinal": 24, + "type_info": "Varchar" + }, + { + "name": "status_name", + "ordinal": 25, + "type_info": "Varchar" + }, + { + "name": "client_side_type", + "ordinal": 26, + "type_info": "Varchar" + }, + { + "name": "server_side_type", + "ordinal": 27, + "type_info": "Varchar" + }, + { + "name": "short", + "ordinal": 28, + "type_info": "Varchar" + }, + { + "name": "license_name", + "ordinal": 29, + "type_info": "Varchar" + }, + { + "name": "project_type_name", + "ordinal": 30, + "type_info": "Varchar" + }, + { + "name": "categories", + "ordinal": 31, + "type_info": "TextArray" + }, + { + "name": "versions", + "ordinal": 32, + "type_info": "TextArray" + }, + { + "name": "gallery", + "ordinal": 33, + "type_info": "TextArray" + }, + { + "name": "donations", + "ordinal": 34, + "type_info": "TextArray" + } + ], + "nullable": [ + false, + false, + false, + false, + false, + false, + true, + false, + true, + false, + false, + true, + false, + true, + true, + true, + true, + true, + false, + false, + false, + false, + true, + true, + true, + false, + false, + false, + false, + false, + false, + null, + null, + null, + null + ], + "parameters": { + "Left": [ + "Int8Array" + ] + } + }, + "query": "\n SELECT m.id id, m.project_type project_type, m.title title, m.description description, m.downloads downloads, m.follows follows,\n m.icon_url icon_url, m.body body, m.body_url body_url, m.published published,\n m.updated updated, m.approved approved, m.status status,\n m.issues_url issues_url, m.source_url source_url, m.wiki_url wiki_url, m.discord_url discord_url, m.license_url license_url,\n m.team_id team_id, m.client_side client_side, m.server_side server_side, m.license license, m.slug slug, m.moderation_message moderation_message, m.moderation_message_body moderation_message_body,\n s.status status_name, cs.name client_side_type, ss.name server_side_type, l.short short, l.name license_name, pt.name project_type_name,\n ARRAY_AGG(DISTINCT c.category || ' |||| ' || mc.is_additional) filter (where c.category is not null) categories,\n ARRAY_AGG(DISTINCT v.id || ' |||| ' || v.date_published) filter (where v.id is not null) versions,\n ARRAY_AGG(DISTINCT mg.image_url || ' |||| ' || mg.featured || ' |||| ' || mg.created || ' |||| ' || COALESCE(mg.title, ' ') || ' |||| ' || COALESCE(mg.description, ' ')) filter (where mg.image_url is not null) gallery,\n ARRAY_AGG(DISTINCT md.joining_platform_id || ' |||| ' || dp.short || ' |||| ' || dp.name || ' |||| ' || md.url) filter (where md.joining_platform_id is not null) donations\n FROM mods m\n INNER JOIN project_types pt ON pt.id = m.project_type\n INNER JOIN statuses s ON s.id = m.status\n INNER JOIN side_types cs ON m.client_side = cs.id\n INNER JOIN side_types ss ON m.server_side = ss.id\n INNER JOIN licenses l ON m.license = l.id\n LEFT JOIN mods_donations md ON md.joining_mod_id = m.id\n LEFT JOIN donation_platforms dp ON md.joining_platform_id = dp.id\n LEFT JOIN mods_categories mc ON mc.joining_mod_id = m.id\n LEFT JOIN categories c ON mc.joining_category_id = c.id\n LEFT JOIN versions v ON v.mod_id = m.id\n LEFT JOIN mods_gallery mg ON mg.mod_id = m.id\n WHERE m.id = ANY($1)\n GROUP BY pt.id, s.id, cs.id, ss.id, l.id, m.id;\n " + }, "0ca11a32b2860e4f5c3d20892a5be3cb419e084f42ba0f98e09b9995027fcc4e": { "describe": { "columns": [ @@ -3282,236 +3506,6 @@ }, "query": "\n DELETE FROM team_members\n WHERE (team_id = $1 AND user_id = $2 AND NOT role = $3)\n " }, - "8c733fda1bd2b010f0b625dc7d08f673252fc0c004ca96ba880918a3c7c40258": { - "describe": { - "columns": [ - { - "name": "id", - "ordinal": 0, - "type_info": "Int8" - }, - { - "name": "project_type", - "ordinal": 1, - "type_info": "Int4" - }, - { - "name": "title", - "ordinal": 2, - "type_info": "Varchar" - }, - { - "name": "description", - "ordinal": 3, - "type_info": "Varchar" - }, - { - "name": "downloads", - "ordinal": 4, - "type_info": "Int4" - }, - { - "name": "follows", - "ordinal": 5, - "type_info": "Int4" - }, - { - "name": "icon_url", - "ordinal": 6, - "type_info": "Varchar" - }, - { - "name": "body", - "ordinal": 7, - "type_info": "Varchar" - }, - { - "name": "body_url", - "ordinal": 8, - "type_info": "Varchar" - }, - { - "name": "published", - "ordinal": 9, - "type_info": "Timestamptz" - }, - { - "name": "updated", - "ordinal": 10, - "type_info": "Timestamptz" - }, - { - "name": "approved", - "ordinal": 11, - "type_info": "Timestamptz" - }, - { - "name": "status", - "ordinal": 12, - "type_info": "Int4" - }, - { - "name": "issues_url", - "ordinal": 13, - "type_info": "Varchar" - }, - { - "name": "source_url", - "ordinal": 14, - "type_info": "Varchar" - }, - { - "name": "wiki_url", - "ordinal": 15, - "type_info": "Varchar" - }, - { - "name": "discord_url", - "ordinal": 16, - "type_info": "Varchar" - }, - { - "name": "license_url", - "ordinal": 17, - "type_info": "Varchar" - }, - { - "name": "team_id", - "ordinal": 18, - "type_info": "Int8" - }, - { - "name": "client_side", - "ordinal": 19, - "type_info": "Int4" - }, - { - "name": "server_side", - "ordinal": 20, - "type_info": "Int4" - }, - { - "name": "license", - "ordinal": 21, - "type_info": "Int4" - }, - { - "name": "slug", - "ordinal": 22, - "type_info": "Varchar" - }, - { - "name": "moderation_message", - "ordinal": 23, - "type_info": "Varchar" - }, - { - "name": "moderation_message_body", - "ordinal": 24, - "type_info": "Varchar" - }, - { - "name": "status_name", - "ordinal": 25, - "type_info": "Varchar" - }, - { - "name": "client_side_type", - "ordinal": 26, - "type_info": "Varchar" - }, - { - "name": "server_side_type", - "ordinal": 27, - "type_info": "Varchar" - }, - { - "name": "short", - "ordinal": 28, - "type_info": "Varchar" - }, - { - "name": "license_name", - "ordinal": 29, - "type_info": "Varchar" - }, - { - "name": "project_type_name", - "ordinal": 30, - "type_info": "Varchar" - }, - { - "name": "categories", - "ordinal": 31, - "type_info": "VarcharArray" - }, - { - "name": "additional_categories", - "ordinal": 32, - "type_info": "VarcharArray" - }, - { - "name": "versions", - "ordinal": 33, - "type_info": "TextArray" - }, - { - "name": "gallery", - "ordinal": 34, - "type_info": "TextArray" - }, - { - "name": "donations", - "ordinal": 35, - "type_info": "TextArray" - } - ], - "nullable": [ - false, - false, - false, - false, - false, - false, - true, - false, - true, - false, - false, - true, - false, - true, - true, - true, - true, - true, - false, - false, - false, - false, - true, - true, - true, - false, - false, - false, - false, - false, - false, - null, - null, - null, - null, - null - ], - "parameters": { - "Left": [ - "Int8" - ] - } - }, - "query": "\n SELECT m.id id, m.project_type project_type, m.title title, m.description description, m.downloads downloads, m.follows follows,\n m.icon_url icon_url, m.body body, m.body_url body_url, m.published published,\n m.updated updated, m.approved approved, m.status status,\n m.issues_url issues_url, m.source_url source_url, m.wiki_url wiki_url, m.discord_url discord_url, m.license_url license_url,\n m.team_id team_id, m.client_side client_side, m.server_side server_side, m.license license, m.slug slug, m.moderation_message moderation_message, m.moderation_message_body moderation_message_body,\n s.status status_name, cs.name client_side_type, ss.name server_side_type, l.short short, l.name license_name, pt.name project_type_name,\n ARRAY_AGG(DISTINCT c.category) filter (where c.category is not null) categories,\n ARRAY_AGG(DISTINCT ca.category) filter (where ca.category is not null) additional_categories,\n ARRAY_AGG(DISTINCT v.id || ' |||| ' || v.date_published) filter (where v.id is not null) versions,\n ARRAY_AGG(DISTINCT mg.image_url || ' |||| ' || mg.featured || ' |||| ' || mg.created || ' |||| ' || COALESCE(mg.title, ' ') || ' |||| ' || COALESCE(mg.description, ' ')) filter (where mg.image_url is not null) gallery,\n ARRAY_AGG(DISTINCT md.joining_platform_id || ' |||| ' || dp.short || ' |||| ' || dp.name || ' |||| ' || md.url) filter (where md.joining_platform_id is not null) donations\n FROM mods m\n INNER JOIN project_types pt ON pt.id = m.project_type\n INNER JOIN statuses s ON s.id = m.status\n INNER JOIN side_types cs ON m.client_side = cs.id\n INNER JOIN side_types ss ON m.server_side = ss.id\n INNER JOIN licenses l ON m.license = l.id\n LEFT JOIN mods_donations md ON md.joining_mod_id = m.id\n LEFT JOIN donation_platforms dp ON md.joining_platform_id = dp.id\n LEFT JOIN mods_categories mc ON mc.joining_mod_id = m.id\n LEFT JOIN categories c ON mc.joining_category_id = c.id AND mc.is_additional = FALSE\n LEFT JOIN categories ca ON mc.joining_category_id = c.id AND mc.is_additional = TRUE\n LEFT JOIN versions v ON v.mod_id = m.id\n LEFT JOIN mods_gallery mg ON mg.mod_id = m.id\n WHERE m.id = $1\n GROUP BY pt.id, s.id, cs.id, ss.id, l.id, m.id;\n " - }, "8ced4b7a1c4f944b918d2d2eefc8007a3fb9565021ca8c44608caccbe1ab9674": { "describe": { "columns": [ @@ -4407,236 +4401,6 @@ }, "query": "\n DELETE FROM game_versions_versions gvv\n WHERE gvv.joining_version_id = $1\n " }, - "bee5860ccac3c22e1ce328cc4278c6f1586d45c1804332dc3a3e90c558bca144": { - "describe": { - "columns": [ - { - "name": "id", - "ordinal": 0, - "type_info": "Int8" - }, - { - "name": "project_type", - "ordinal": 1, - "type_info": "Int4" - }, - { - "name": "title", - "ordinal": 2, - "type_info": "Varchar" - }, - { - "name": "description", - "ordinal": 3, - "type_info": "Varchar" - }, - { - "name": "downloads", - "ordinal": 4, - "type_info": "Int4" - }, - { - "name": "follows", - "ordinal": 5, - "type_info": "Int4" - }, - { - "name": "icon_url", - "ordinal": 6, - "type_info": "Varchar" - }, - { - "name": "body", - "ordinal": 7, - "type_info": "Varchar" - }, - { - "name": "body_url", - "ordinal": 8, - "type_info": "Varchar" - }, - { - "name": "published", - "ordinal": 9, - "type_info": "Timestamptz" - }, - { - "name": "updated", - "ordinal": 10, - "type_info": "Timestamptz" - }, - { - "name": "approved", - "ordinal": 11, - "type_info": "Timestamptz" - }, - { - "name": "status", - "ordinal": 12, - "type_info": "Int4" - }, - { - "name": "issues_url", - "ordinal": 13, - "type_info": "Varchar" - }, - { - "name": "source_url", - "ordinal": 14, - "type_info": "Varchar" - }, - { - "name": "wiki_url", - "ordinal": 15, - "type_info": "Varchar" - }, - { - "name": "discord_url", - "ordinal": 16, - "type_info": "Varchar" - }, - { - "name": "license_url", - "ordinal": 17, - "type_info": "Varchar" - }, - { - "name": "team_id", - "ordinal": 18, - "type_info": "Int8" - }, - { - "name": "client_side", - "ordinal": 19, - "type_info": "Int4" - }, - { - "name": "server_side", - "ordinal": 20, - "type_info": "Int4" - }, - { - "name": "license", - "ordinal": 21, - "type_info": "Int4" - }, - { - "name": "slug", - "ordinal": 22, - "type_info": "Varchar" - }, - { - "name": "moderation_message", - "ordinal": 23, - "type_info": "Varchar" - }, - { - "name": "moderation_message_body", - "ordinal": 24, - "type_info": "Varchar" - }, - { - "name": "status_name", - "ordinal": 25, - "type_info": "Varchar" - }, - { - "name": "client_side_type", - "ordinal": 26, - "type_info": "Varchar" - }, - { - "name": "server_side_type", - "ordinal": 27, - "type_info": "Varchar" - }, - { - "name": "short", - "ordinal": 28, - "type_info": "Varchar" - }, - { - "name": "license_name", - "ordinal": 29, - "type_info": "Varchar" - }, - { - "name": "project_type_name", - "ordinal": 30, - "type_info": "Varchar" - }, - { - "name": "categories", - "ordinal": 31, - "type_info": "VarcharArray" - }, - { - "name": "additional_categories", - "ordinal": 32, - "type_info": "VarcharArray" - }, - { - "name": "versions", - "ordinal": 33, - "type_info": "TextArray" - }, - { - "name": "gallery", - "ordinal": 34, - "type_info": "TextArray" - }, - { - "name": "donations", - "ordinal": 35, - "type_info": "TextArray" - } - ], - "nullable": [ - false, - false, - false, - false, - false, - false, - true, - false, - true, - false, - false, - true, - false, - true, - true, - true, - true, - true, - false, - false, - false, - false, - true, - true, - true, - false, - false, - false, - false, - false, - false, - null, - null, - null, - null, - null - ], - "parameters": { - "Left": [ - "Int8Array" - ] - } - }, - "query": "\n SELECT m.id id, m.project_type project_type, m.title title, m.description description, m.downloads downloads, m.follows follows,\n m.icon_url icon_url, m.body body, m.body_url body_url, m.published published,\n m.updated updated, m.approved approved, m.status status,\n m.issues_url issues_url, m.source_url source_url, m.wiki_url wiki_url, m.discord_url discord_url, m.license_url license_url,\n m.team_id team_id, m.client_side client_side, m.server_side server_side, m.license license, m.slug slug, m.moderation_message moderation_message, m.moderation_message_body moderation_message_body,\n s.status status_name, cs.name client_side_type, ss.name server_side_type, l.short short, l.name license_name, pt.name project_type_name,\n ARRAY_AGG(DISTINCT c.category) filter (where c.category is not null) categories,\n ARRAY_AGG(DISTINCT ca.category) filter (where ca.category is not null) additional_categories,\n ARRAY_AGG(DISTINCT v.id || ' |||| ' || v.date_published) filter (where v.id is not null) versions,\n ARRAY_AGG(DISTINCT mg.image_url || ' |||| ' || mg.featured || ' |||| ' || mg.created || ' |||| ' || COALESCE(mg.title, ' ') || ' |||| ' || COALESCE(mg.description, ' ')) filter (where mg.image_url is not null) gallery,\n ARRAY_AGG(DISTINCT md.joining_platform_id || ' |||| ' || dp.short || ' |||| ' || dp.name || ' |||| ' || md.url) filter (where md.joining_platform_id is not null) donations\n FROM mods m\n INNER JOIN project_types pt ON pt.id = m.project_type\n INNER JOIN statuses s ON s.id = m.status\n INNER JOIN side_types cs ON m.client_side = cs.id\n INNER JOIN side_types ss ON m.server_side = ss.id\n INNER JOIN licenses l ON m.license = l.id\n LEFT JOIN mods_donations md ON md.joining_mod_id = m.id\n LEFT JOIN donation_platforms dp ON md.joining_platform_id = dp.id\n LEFT JOIN mods_categories mc ON mc.joining_mod_id = m.id\n LEFT JOIN categories c ON mc.joining_category_id = c.id AND mc.is_additional = FALSE\n LEFT JOIN categories ca ON mc.joining_category_id = c.id AND mc.is_additional = TRUE\n LEFT JOIN versions v ON v.mod_id = m.id\n LEFT JOIN mods_gallery mg ON mg.mod_id = m.id\n WHERE m.id = ANY($1)\n GROUP BY pt.id, s.id, cs.id, ss.id, l.id, m.id;\n " - }, "bf7f721664f5e0ed41adc41b5483037256635f28ff6c4e5d3cbcec4387f9c8ef": { "describe": { "columns": [ @@ -4735,33 +4499,6 @@ }, "query": "\n UPDATE versions\n SET version_type = $1\n WHERE (id = $2)\n " }, - "c265db2e2cc1ba34ca1f30a9401018eb7760c8f0bafb1e3a7576e62bc9d3f83a": { - "describe": { - "columns": [ - { - "name": "id", - "ordinal": 0, - "type_info": "Int8" - }, - { - "name": "mod_id", - "ordinal": 1, - "type_info": "Int8" - } - ], - "nullable": [ - false, - false - ], - "parameters": { - "Left": [ - "Text", - "Int8" - ] - } - }, - "query": "SELECT id, mod_id FROM versions\n WHERE (version_number = $1 AND mod_id = $2)" - }, "c3dcb5a8b798ea6c0922698a007dbc8ab549f5f85bad780da59163f4d6371238": { "describe": { "columns": [ @@ -4883,6 +4620,34 @@ }, "query": "\n SELECT category FROM categories\n WHERE id = $1\n " }, + "c6830506451f89d8fa97c70a1edf723cedffae550e91dd0fa09fa04306fd56e8": { + "describe": { + "columns": [ + { + "name": "id", + "ordinal": 0, + "type_info": "Int8" + }, + { + "name": "mod_id", + "ordinal": 1, + "type_info": "Int8" + } + ], + "nullable": [ + false, + false + ], + "parameters": { + "Left": [ + "Text", + "Int8", + "Int8" + ] + } + }, + "query": "SELECT id, mod_id FROM versions\n WHERE ((version_number = $1 OR id = $3) AND mod_id = $2)" + }, "c9d63ed46799db7c30a7e917d97a5d4b2b78b0234cce49e136fa57526b38c1ca": { "describe": { "columns": [ @@ -6052,6 +5817,230 @@ }, "query": "\n SELECT name FROM project_types pt\n INNER JOIN mods ON mods.project_type = pt.id\n WHERE mods.id = $1\n " }, + "ef86b7759f479cb04d6aaf02688315bb5674e6eadade41cdd11947943356bea8": { + "describe": { + "columns": [ + { + "name": "id", + "ordinal": 0, + "type_info": "Int8" + }, + { + "name": "project_type", + "ordinal": 1, + "type_info": "Int4" + }, + { + "name": "title", + "ordinal": 2, + "type_info": "Varchar" + }, + { + "name": "description", + "ordinal": 3, + "type_info": "Varchar" + }, + { + "name": "downloads", + "ordinal": 4, + "type_info": "Int4" + }, + { + "name": "follows", + "ordinal": 5, + "type_info": "Int4" + }, + { + "name": "icon_url", + "ordinal": 6, + "type_info": "Varchar" + }, + { + "name": "body", + "ordinal": 7, + "type_info": "Varchar" + }, + { + "name": "body_url", + "ordinal": 8, + "type_info": "Varchar" + }, + { + "name": "published", + "ordinal": 9, + "type_info": "Timestamptz" + }, + { + "name": "updated", + "ordinal": 10, + "type_info": "Timestamptz" + }, + { + "name": "approved", + "ordinal": 11, + "type_info": "Timestamptz" + }, + { + "name": "status", + "ordinal": 12, + "type_info": "Int4" + }, + { + "name": "issues_url", + "ordinal": 13, + "type_info": "Varchar" + }, + { + "name": "source_url", + "ordinal": 14, + "type_info": "Varchar" + }, + { + "name": "wiki_url", + "ordinal": 15, + "type_info": "Varchar" + }, + { + "name": "discord_url", + "ordinal": 16, + "type_info": "Varchar" + }, + { + "name": "license_url", + "ordinal": 17, + "type_info": "Varchar" + }, + { + "name": "team_id", + "ordinal": 18, + "type_info": "Int8" + }, + { + "name": "client_side", + "ordinal": 19, + "type_info": "Int4" + }, + { + "name": "server_side", + "ordinal": 20, + "type_info": "Int4" + }, + { + "name": "license", + "ordinal": 21, + "type_info": "Int4" + }, + { + "name": "slug", + "ordinal": 22, + "type_info": "Varchar" + }, + { + "name": "moderation_message", + "ordinal": 23, + "type_info": "Varchar" + }, + { + "name": "moderation_message_body", + "ordinal": 24, + "type_info": "Varchar" + }, + { + "name": "status_name", + "ordinal": 25, + "type_info": "Varchar" + }, + { + "name": "client_side_type", + "ordinal": 26, + "type_info": "Varchar" + }, + { + "name": "server_side_type", + "ordinal": 27, + "type_info": "Varchar" + }, + { + "name": "short", + "ordinal": 28, + "type_info": "Varchar" + }, + { + "name": "license_name", + "ordinal": 29, + "type_info": "Varchar" + }, + { + "name": "project_type_name", + "ordinal": 30, + "type_info": "Varchar" + }, + { + "name": "categories", + "ordinal": 31, + "type_info": "TextArray" + }, + { + "name": "versions", + "ordinal": 32, + "type_info": "TextArray" + }, + { + "name": "gallery", + "ordinal": 33, + "type_info": "TextArray" + }, + { + "name": "donations", + "ordinal": 34, + "type_info": "TextArray" + } + ], + "nullable": [ + false, + false, + false, + false, + false, + false, + true, + false, + true, + false, + false, + true, + false, + true, + true, + true, + true, + true, + false, + false, + false, + false, + true, + true, + true, + false, + false, + false, + false, + false, + false, + null, + null, + null, + null + ], + "parameters": { + "Left": [ + "Int8" + ] + } + }, + "query": "\n SELECT m.id id, m.project_type project_type, m.title title, m.description description, m.downloads downloads, m.follows follows,\n m.icon_url icon_url, m.body body, m.body_url body_url, m.published published,\n m.updated updated, m.approved approved, m.status status,\n m.issues_url issues_url, m.source_url source_url, m.wiki_url wiki_url, m.discord_url discord_url, m.license_url license_url,\n m.team_id team_id, m.client_side client_side, m.server_side server_side, m.license license, m.slug slug, m.moderation_message moderation_message, m.moderation_message_body moderation_message_body,\n s.status status_name, cs.name client_side_type, ss.name server_side_type, l.short short, l.name license_name, pt.name project_type_name,\n ARRAY_AGG(DISTINCT c.category || ' |||| ' || mc.is_additional) filter (where c.category is not null) categories,\n ARRAY_AGG(DISTINCT v.id || ' |||| ' || v.date_published) filter (where v.id is not null) versions,\n ARRAY_AGG(DISTINCT mg.image_url || ' |||| ' || mg.featured || ' |||| ' || mg.created || ' |||| ' || COALESCE(mg.title, ' ') || ' |||| ' || COALESCE(mg.description, ' ')) filter (where mg.image_url is not null) gallery,\n ARRAY_AGG(DISTINCT md.joining_platform_id || ' |||| ' || dp.short || ' |||| ' || dp.name || ' |||| ' || md.url) filter (where md.joining_platform_id is not null) donations\n FROM mods m\n INNER JOIN project_types pt ON pt.id = m.project_type\n INNER JOIN statuses s ON s.id = m.status\n INNER JOIN side_types cs ON m.client_side = cs.id\n INNER JOIN side_types ss ON m.server_side = ss.id\n INNER JOIN licenses l ON m.license = l.id\n LEFT JOIN mods_donations md ON md.joining_mod_id = m.id\n LEFT JOIN donation_platforms dp ON md.joining_platform_id = dp.id\n LEFT JOIN mods_categories mc ON mc.joining_mod_id = m.id\n LEFT JOIN categories c ON mc.joining_category_id = c.id\n LEFT JOIN versions v ON v.mod_id = m.id\n LEFT JOIN mods_gallery mg ON mg.mod_id = m.id\n WHERE m.id = $1\n GROUP BY pt.id, s.id, cs.id, ss.id, l.id, m.id;\n " + }, "f0db9d8606ccc2196a9cfafe0e7090dab42bf790f25e0469b8947fac1cf043d5": { "describe": { "columns": [ diff --git a/src/database/models/categories.rs b/src/database/models/categories.rs index 612ced558..5404644f7 100644 --- a/src/database/models/categories.rs +++ b/src/database/models/categories.rs @@ -74,10 +74,9 @@ impl Category { where E: sqlx::Executor<'a, Database = sqlx::Postgres>, { - if !name - .chars() - .all(|c| c.is_ascii_alphanumeric() || c == '-' || c == '_') - { + if !name.chars().all(|c| { + c.is_ascii_alphanumeric() || c == '-' || c == '_' || c == '+' + }) { return Err(DatabaseError::InvalidIdentifier(name.to_string())); } @@ -102,10 +101,9 @@ impl Category { where E: sqlx::Executor<'a, Database = sqlx::Postgres>, { - if !name - .chars() - .all(|c| c.is_ascii_alphanumeric() || c == '-' || c == '_') - { + if !name.chars().all(|c| { + c.is_ascii_alphanumeric() || c == '-' || c == '_' || c == '+' + }) { return Err(DatabaseError::InvalidIdentifier(name.to_string())); } @@ -203,10 +201,9 @@ impl<'a> CategoryBuilder<'a> { self, name: &'a str, ) -> Result, DatabaseError> { - if name - .chars() - .all(|c| c.is_ascii_alphanumeric() || c == '-' || c == '_') - { + if name.chars().all(|c| { + c.is_ascii_alphanumeric() || c == '-' || c == '_' || c == '+' + }) { Ok(Self { name: Some(name), ..self @@ -296,10 +293,9 @@ impl Loader { where E: sqlx::Executor<'a, Database = sqlx::Postgres>, { - if !name - .chars() - .all(|c| c.is_ascii_alphanumeric() || c == '-' || c == '_') - { + if !name.chars().all(|c| { + c.is_ascii_alphanumeric() || c == '-' || c == '_' || c == '+' + }) { return Err(DatabaseError::InvalidIdentifier(name.to_string())); } @@ -403,10 +399,9 @@ impl<'a> LoaderBuilder<'a> { self, name: &'a str, ) -> Result, DatabaseError> { - if name - .chars() - .all(|c| c.is_ascii_alphanumeric() || c == '-' || c == '_') - { + if name.chars().all(|c| { + c.is_ascii_alphanumeric() || c == '-' || c == '_' || c == '+' + }) { Ok(Self { name: Some(name), ..self @@ -501,10 +496,9 @@ impl GameVersion { where E: sqlx::Executor<'a, Database = sqlx::Postgres>, { - if !version - .chars() - .all(|c| c.is_ascii_alphanumeric() || "-_.".contains(c)) - { + if !version.chars().all(|c| { + c.is_ascii_alphanumeric() || c == '-' || c == '_' || c == '+' + }) { return Err(DatabaseError::InvalidIdentifier(version.to_string())); } @@ -676,7 +670,7 @@ impl<'a> GameVersionBuilder<'a> { ) -> Result, DatabaseError> { if version .chars() - .all(|c| c.is_ascii_alphanumeric() || "-_.".contains(c)) + .all(|c| c.is_ascii_alphanumeric() || "-_.+".contains(c)) { Ok(Self { version: Some(version), @@ -693,7 +687,7 @@ impl<'a> GameVersionBuilder<'a> { ) -> Result, DatabaseError> { if version_type .chars() - .all(|c| c.is_ascii_alphanumeric() || "-_.".contains(c)) + .all(|c| c.is_ascii_alphanumeric() || "-_.+".contains(c)) { Ok(Self { version_type: Some(version_type), @@ -851,10 +845,9 @@ impl<'a> LicenseBuilder<'a> { self, short: &'a str, ) -> Result, DatabaseError> { - if short - .chars() - .all(|c| c.is_ascii_alphanumeric() || "-_.".contains(c)) - { + if short.chars().all(|c| { + c.is_ascii_alphanumeric() || c == '-' || c == '_' || c == '+' + }) { Ok(Self { short: Some(short), ..self @@ -1011,10 +1004,9 @@ impl<'a> DonationPlatformBuilder<'a> { self, short: &'a str, ) -> Result, DatabaseError> { - if short - .chars() - .all(|c| c.is_ascii_alphanumeric() || "-_.".contains(c)) - { + if short.chars().all(|c| { + c.is_ascii_alphanumeric() || c == '-' || c == '_' || c == '+' + }) { Ok(Self { short: Some(short), ..self @@ -1075,10 +1067,9 @@ impl ReportType { where E: sqlx::Executor<'a, Database = sqlx::Postgres>, { - if !name - .chars() - .all(|c| c.is_ascii_alphanumeric() || c == '-' || c == '_') - { + if !name.chars().all(|c| { + c.is_ascii_alphanumeric() || c == '-' || c == '_' || c == '+' + }) { return Err(DatabaseError::InvalidIdentifier(name.to_string())); } @@ -1164,10 +1155,9 @@ impl<'a> ReportTypeBuilder<'a> { self, name: &'a str, ) -> Result, DatabaseError> { - if name - .chars() - .all(|c| c.is_ascii_alphanumeric() || c == '-' || c == '_') - { + if name.chars().all(|c| { + c.is_ascii_alphanumeric() || c == '-' || c == '_' || c == '+' + }) { Ok(Self { name: Some(name) }) } else { Err(DatabaseError::InvalidIdentifier(name.to_string())) @@ -1213,10 +1203,9 @@ impl ProjectType { where E: sqlx::Executor<'a, Database = sqlx::Postgres>, { - if !name - .chars() - .all(|c| c.is_ascii_alphanumeric() || c == '-' || c == '_') - { + if !name.chars().all(|c| { + c.is_ascii_alphanumeric() || c == '-' || c == '_' || c == '+' + }) { return Err(DatabaseError::InvalidIdentifier(name.to_string())); } @@ -1330,10 +1319,9 @@ impl<'a> ProjectTypeBuilder<'a> { self, name: &'a str, ) -> Result, DatabaseError> { - if name - .chars() - .all(|c| c.is_ascii_alphanumeric() || c == '-' || c == '_') - { + if name.chars().all(|c| { + c.is_ascii_alphanumeric() || c == '-' || c == '_' || c == '+' + }) { Ok(Self { name: Some(name) }) } else { Err(DatabaseError::InvalidIdentifier(name.to_string())) diff --git a/src/database/models/ids.rs b/src/database/models/ids.rs index bca034d59..9e97862b1 100644 --- a/src/database/models/ids.rs +++ b/src/database/models/ids.rs @@ -116,7 +116,7 @@ pub struct TeamId(pub i64); #[sqlx(transparent)] pub struct TeamMemberId(pub i64); -#[derive(Copy, Clone, Debug, Type, PartialEq)] +#[derive(Copy, Clone, Debug, Type, PartialEq, Eq)] #[sqlx(transparent)] pub struct ProjectId(pub i64); #[derive(Copy, Clone, Debug, Type)] diff --git a/src/database/models/mod.rs b/src/database/models/mod.rs index 9eea57b8e..6c81b53d3 100644 --- a/src/database/models/mod.rs +++ b/src/database/models/mod.rs @@ -30,7 +30,7 @@ pub enum DatabaseError { RandomId, #[error( "Invalid identifier: Category/version names must contain only ASCII \ - alphanumeric characters or '_-'." + alphanumeric characters or '_-+'." )] InvalidIdentifier(String), #[error("Invalid permissions bitflag!")] diff --git a/src/database/models/project_item.rs b/src/database/models/project_item.rs index ef487a798..ed81d18cd 100644 --- a/src/database/models/project_item.rs +++ b/src/database/models/project_item.rs @@ -629,8 +629,7 @@ impl Project { m.issues_url issues_url, m.source_url source_url, m.wiki_url wiki_url, m.discord_url discord_url, m.license_url license_url, m.team_id team_id, m.client_side client_side, m.server_side server_side, m.license license, m.slug slug, m.moderation_message moderation_message, m.moderation_message_body moderation_message_body, s.status status_name, cs.name client_side_type, ss.name server_side_type, l.short short, l.name license_name, pt.name project_type_name, - ARRAY_AGG(DISTINCT c.category) filter (where c.category is not null) categories, - ARRAY_AGG(DISTINCT ca.category) filter (where ca.category is not null) additional_categories, + ARRAY_AGG(DISTINCT c.category || ' |||| ' || mc.is_additional) filter (where c.category is not null) categories, ARRAY_AGG(DISTINCT v.id || ' |||| ' || v.date_published) filter (where v.id is not null) versions, ARRAY_AGG(DISTINCT mg.image_url || ' |||| ' || mg.featured || ' |||| ' || mg.created || ' |||| ' || COALESCE(mg.title, ' ') || ' |||| ' || COALESCE(mg.description, ' ')) filter (where mg.image_url is not null) gallery, ARRAY_AGG(DISTINCT md.joining_platform_id || ' |||| ' || dp.short || ' |||| ' || dp.name || ' |||| ' || md.url) filter (where md.joining_platform_id is not null) donations @@ -643,8 +642,7 @@ impl Project { LEFT JOIN mods_donations md ON md.joining_mod_id = m.id LEFT JOIN donation_platforms dp ON md.joining_platform_id = dp.id LEFT JOIN mods_categories mc ON mc.joining_mod_id = m.id - LEFT JOIN categories c ON mc.joining_category_id = c.id AND mc.is_additional = FALSE - LEFT JOIN categories ca ON mc.joining_category_id = c.id AND mc.is_additional = TRUE + LEFT JOIN categories c ON mc.joining_category_id = c.id LEFT JOIN versions v ON v.mod_id = m.id LEFT JOIN mods_gallery mg ON mg.mod_id = m.id WHERE m.id = $1 @@ -656,6 +654,23 @@ impl Project { .await?; if let Some(m) = result { + let categories_raw = m.categories.unwrap_or_default(); + + let mut categories = Vec::new(); + let mut additional_categories = Vec::new(); + + for category in categories_raw { + let category: Vec<&str> = category.split(" |||| ").collect(); + + if category.len() >= 2 { + if category[1].parse::().ok().unwrap_or_default() { + additional_categories.push(category[0].to_string()); + } else { + categories.push(category[0].to_string()); + } + } + } + Ok(Some(QueryProject { inner: Project { id: ProjectId(m.id), @@ -685,10 +700,8 @@ impl Project { approved: m.approved, }, project_type: m.project_type_name, - categories: m.categories.unwrap_or_default(), - additional_categories: m - .additional_categories - .unwrap_or_default(), + categories, + additional_categories, versions: { let versions = m.versions.unwrap_or_default(); @@ -803,8 +816,7 @@ impl Project { m.issues_url issues_url, m.source_url source_url, m.wiki_url wiki_url, m.discord_url discord_url, m.license_url license_url, m.team_id team_id, m.client_side client_side, m.server_side server_side, m.license license, m.slug slug, m.moderation_message moderation_message, m.moderation_message_body moderation_message_body, s.status status_name, cs.name client_side_type, ss.name server_side_type, l.short short, l.name license_name, pt.name project_type_name, - ARRAY_AGG(DISTINCT c.category) filter (where c.category is not null) categories, - ARRAY_AGG(DISTINCT ca.category) filter (where ca.category is not null) additional_categories, + ARRAY_AGG(DISTINCT c.category || ' |||| ' || mc.is_additional) filter (where c.category is not null) categories, ARRAY_AGG(DISTINCT v.id || ' |||| ' || v.date_published) filter (where v.id is not null) versions, ARRAY_AGG(DISTINCT mg.image_url || ' |||| ' || mg.featured || ' |||| ' || mg.created || ' |||| ' || COALESCE(mg.title, ' ') || ' |||| ' || COALESCE(mg.description, ' ')) filter (where mg.image_url is not null) gallery, ARRAY_AGG(DISTINCT md.joining_platform_id || ' |||| ' || dp.short || ' |||| ' || dp.name || ' |||| ' || md.url) filter (where md.joining_platform_id is not null) donations @@ -817,8 +829,7 @@ impl Project { LEFT JOIN mods_donations md ON md.joining_mod_id = m.id LEFT JOIN donation_platforms dp ON md.joining_platform_id = dp.id LEFT JOIN mods_categories mc ON mc.joining_mod_id = m.id - LEFT JOIN categories c ON mc.joining_category_id = c.id AND mc.is_additional = FALSE - LEFT JOIN categories ca ON mc.joining_category_id = c.id AND mc.is_additional = TRUE + LEFT JOIN categories c ON mc.joining_category_id = c.id LEFT JOIN versions v ON v.mod_id = m.id LEFT JOIN mods_gallery mg ON mg.mod_id = m.id WHERE m.id = ANY($1) @@ -830,6 +841,25 @@ impl Project { .try_filter_map(|e| async { Ok(e.right().map(|m| { let id = m.id; + + let categories_raw = m.categories.unwrap_or_default(); + + let mut categories = Vec::new(); + let mut additional_categories = Vec::new(); + + for category in categories_raw { + let category: Vec<&str> = + category.split(" |||| ").collect(); + + if category.len() >= 2 { + if category[1].parse::().ok().unwrap_or_default() { + additional_categories.push(category[0].to_string()); + } else { + categories.push(category[0].to_string()); + } + } + } + QueryProject { inner: Project { id: ProjectId(id), @@ -859,8 +889,8 @@ impl Project { approved: m.approved }, project_type: m.project_type_name, - categories: m.categories.unwrap_or_default(), - additional_categories: m.additional_categories.unwrap_or_default(), + categories, + additional_categories, versions: { let versions = m.versions.unwrap_or_default(); diff --git a/src/database/models/version_item.rs b/src/database/models/version_item.rs index 5b0a56188..7d66c3256 100644 --- a/src/database/models/version_item.rs +++ b/src/database/models/version_item.rs @@ -735,14 +735,14 @@ impl Version { if dependency.len() >= 4 { Some(QueryDependency { - project_id: match &*dependency[1] { + project_id: match dependency[1] { "0" => None, _ => match dependency[1].parse() { Ok(x) => Some(ProjectId(x)), Err(_) => None, }, }, - version_id: match &*dependency[0] { + version_id: match dependency[0] { "0" => None, _ => match dependency[0].parse() { Ok(x) => Some(VersionId(x)), @@ -896,14 +896,14 @@ impl Version { if dependency.len() >= 4 { Some(QueryDependency { - project_id: match &*dependency[1] { + project_id: match dependency[1] { "0" => None, _ => match dependency[1].parse() { Ok(x) => Some(ProjectId(x)), Err(_) => None, }, }, - version_id: match &*dependency[0] { + version_id: match dependency[0] { "0" => None, _ => match dependency[0].parse() { Ok(x) => Some(VersionId(x)), diff --git a/src/models/projects.rs b/src/models/projects.rs index 8f1f3c538..a5f850ae5 100644 --- a/src/models/projects.rs +++ b/src/models/projects.rs @@ -219,7 +219,10 @@ pub struct License { pub struct DonationLink { pub id: String, pub platform: String, - #[validate(url)] + #[validate( + custom(function = "crate::util::validate::validate_url"), + length(max = 2048) + )] pub url: String, } @@ -482,7 +485,7 @@ impl DependencyType { } /// A specific version of Minecraft -#[derive(Serialize, Deserialize, Clone, PartialEq)] +#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)] #[serde(transparent)] pub struct GameVersion(pub String); diff --git a/src/routes/admin.rs b/src/routes/admin.rs index 54fbe7aca..59a79ffa1 100644 --- a/src/routes/admin.rs +++ b/src/routes/admin.rs @@ -25,11 +25,18 @@ pub async fn count_download( let project_id: crate::database::models::ids::ProjectId = download_body.hash.into(); + let id_option = crate::models::ids::base62_impl::parse_base62( + &download_body.version_name, + ) + .ok() + .map(|x| x as i64); + let (version_id, project_id) = if let Some(version) = sqlx::query!( "SELECT id, mod_id FROM versions - WHERE (version_number = $1 AND mod_id = $2)", + WHERE ((version_number = $1 OR id = $3) AND mod_id = $2)", download_body.version_name, - project_id as crate::database::models::ids::ProjectId + project_id as crate::database::models::ids::ProjectId, + id_option ) .fetch_optional(pool.as_ref()) .await? diff --git a/src/routes/maven.rs b/src/routes/maven.rs index 5c6e7cde9..24e2f130e 100644 --- a/src/routes/maven.rs +++ b/src/routes/maven.rs @@ -118,7 +118,7 @@ pub async fn maven_metadata( .last() .unwrap_or(&"release".to_string()) .to_string(), - release: latest_release.unwrap_or_default().to_string(), + release: latest_release.unwrap_or_default(), versions: Versions { versions: new_versions, }, diff --git a/src/routes/project_creation.rs b/src/routes/project_creation.rs index ea02ae615..6eee7e798 100644 --- a/src/routes/project_creation.rs +++ b/src/routes/project_creation.rs @@ -170,19 +170,34 @@ struct ProjectCreateData { /// A list of the categories that the project is in. pub additional_categories: Vec, - #[validate(url, length(max = 2048))] + #[validate( + custom(function = "crate::util::validate::validate_url"), + length(max = 2048) + )] /// An optional link to where to submit bugs or issues with the project. pub issues_url: Option, - #[validate(url, length(max = 2048))] + #[validate( + custom(function = "crate::util::validate::validate_url"), + length(max = 2048) + )] /// An optional link to the source code for the project. pub source_url: Option, - #[validate(url, length(max = 2048))] + #[validate( + custom(function = "crate::util::validate::validate_url"), + length(max = 2048) + )] /// An optional link to the project's wiki page or other relevant information. pub wiki_url: Option, - #[validate(url, length(max = 2048))] + #[validate( + custom(function = "crate::util::validate::validate_url"), + length(max = 2048) + )] /// An optional link to the project's license page pub license_url: Option, - #[validate(url, length(max = 2048))] + #[validate( + custom(function = "crate::util::validate::validate_url"), + length(max = 2048) + )] /// An optional link to the project's discord. pub discord_url: Option, /// An optional list of all donation links the project has\ @@ -550,7 +565,7 @@ pub async fn project_create_inner( &cdn_url, &content_disposition, project_id, - &version_data.version_number, + created_version.version_id.into(), &*project_create_data.project_type, version_data.loaders.clone(), version_data.game_versions.clone(), diff --git a/src/routes/projects.rs b/src/routes/projects.rs index e1254dc20..63941f345 100644 --- a/src/routes/projects.rs +++ b/src/routes/projects.rs @@ -266,35 +266,50 @@ pub struct EditProject { skip_serializing_if = "Option::is_none", with = "::serde_with::rust::double_option" )] - #[validate(url, length(max = 2048))] + #[validate( + custom(function = "crate::util::validate::validate_url"), + length(max = 2048) + )] pub issues_url: Option>, #[serde( default, skip_serializing_if = "Option::is_none", with = "::serde_with::rust::double_option" )] - #[validate(url, length(max = 2048))] + #[validate( + custom(function = "crate::util::validate::validate_url"), + length(max = 2048) + )] pub source_url: Option>, #[serde( default, skip_serializing_if = "Option::is_none", with = "::serde_with::rust::double_option" )] - #[validate(url, length(max = 2048))] + #[validate( + custom(function = "crate::util::validate::validate_url"), + length(max = 2048) + )] pub wiki_url: Option>, #[serde( default, skip_serializing_if = "Option::is_none", with = "::serde_with::rust::double_option" )] - #[validate(url, length(max = 2048))] + #[validate( + custom(function = "crate::util::validate::validate_url"), + length(max = 2048) + )] pub license_url: Option>, #[serde( default, skip_serializing_if = "Option::is_none", with = "::serde_with::rust::double_option" )] - #[validate(url, length(max = 2048))] + #[validate( + custom(function = "crate::util::validate::validate_url"), + length(max = 2048) + )] pub discord_url: Option>, #[validate] pub donation_urls: Option>, diff --git a/src/routes/version_creation.rs b/src/routes/version_creation.rs index 051ed1eb5..13a848cb5 100644 --- a/src/routes/version_creation.rs +++ b/src/routes/version_creation.rs @@ -302,7 +302,7 @@ async fn version_create_inner( &cdn_url, &content_disposition, version.project_id.into(), - &version.version_number, + version.version_id.into(), &*project_type, version_data.loaders, version_data.game_versions, @@ -520,7 +520,6 @@ async fn upload_file_to_version_inner( } let project_id = ProjectId(version.project_id.0 as u64); - let version_number = version.version_number; let project_type = sqlx::query!( " @@ -567,7 +566,7 @@ async fn upload_file_to_version_inner( let mut dependencies = version .dependencies .iter() - .map(|x| models::version_item::DependencyBuilder { + .map(|x| DependencyBuilder { project_id: x.project_id, version_id: x.version_id, file_name: None, @@ -584,7 +583,7 @@ async fn upload_file_to_version_inner( &cdn_url, &content_disposition, project_id, - &version_number, + version_id.into(), &*project_type, version.loaders.clone().into_iter().map(Loader).collect(), version @@ -626,7 +625,7 @@ pub async fn upload_file( cdn_url: &str, content_disposition: &actix_web::http::header::ContentDisposition, project_id: ProjectId, - version_number: &str, + version_id: VersionId, project_type: &str, loaders: Vec, game_versions: Vec, @@ -748,13 +747,11 @@ pub async fn upload_file( let file_path_encode = format!( "data/{}/versions/{}/{}", project_id, - version_number, + version_id, urlencoding::encode(file_name) ); - let file_path = format!( - "data/{}/versions/{}/{}", - project_id, version_number, &file_name - ); + let file_path = + format!("data/{}/versions/{}/{}", project_id, version_id, &file_name); let upload_data = file_host .upload_file(content_type, &file_path, data.freeze()) diff --git a/src/search/mod.rs b/src/search/mod.rs index f1f8c7c2a..e1384cfd4 100644 --- a/src/search/mod.rs +++ b/src/search/mod.rs @@ -8,6 +8,7 @@ use meilisearch_sdk::document::Document; use serde::{Deserialize, Serialize}; use std::borrow::Cow; use std::cmp::min; +use std::fmt::Write; use thiserror::Error; pub mod indexing; @@ -20,6 +21,8 @@ pub enum SearchError { Serde(#[from] serde_json::Error), #[error("Error while parsing an integer: {0}")] IntParsing(#[from] std::num::ParseIntError), + #[error("Error while formatting strings: {0}")] + FormatError(#[from] std::fmt::Error), #[error("Environment Error")] Env(#[from] dotenv::Error), #[error("Invalid index to sort by: {0}")] @@ -34,6 +37,7 @@ impl actix_web::ResponseError for SearchError { SearchError::Serde(..) => StatusCode::BAD_REQUEST, SearchError::IntParsing(..) => StatusCode::BAD_REQUEST, SearchError::InvalidIndex(..) => StatusCode::BAD_REQUEST, + SearchError::FormatError(..) => StatusCode::BAD_REQUEST, } } @@ -45,6 +49,7 @@ impl actix_web::ResponseError for SearchError { SearchError::Serde(..) => "invalid_input", SearchError::IntParsing(..) => "invalid_input", SearchError::InvalidIndex(..) => "invalid_input", + SearchError::FormatError(..) => "invalid_input", }, description: &self.to_string(), }) @@ -215,7 +220,7 @@ pub async fn search_for_project( filter_string.push(')'); if !filters.is_empty() { - filter_string.push_str(&format!(" AND ({})", filter_string)) + write!(filter_string, " AND ({})", filters)?; } } else { filter_string.push_str(&*filters); diff --git a/src/util/validate.rs b/src/util/validate.rs index 5dc4912a8..778a5163e 100644 --- a/src/util/validate.rs +++ b/src/util/validate.rs @@ -88,3 +88,15 @@ pub fn validate_deps( Ok(()) } + +pub fn validate_url(value: &String) -> Result<(), validator::ValidationError> { + let url = url::Url::parse(value) + .ok() + .ok_or_else(|| validator::ValidationError::new("invalid URL"))?; + + if url.scheme() != "https" { + return Err(validator::ValidationError::new("URL must be https")); + } + + Ok(()) +} diff --git a/src/validate/plugin.rs b/src/validate/plugin.rs index 9effa2015..ead34e932 100644 --- a/src/validate/plugin.rs +++ b/src/validate/plugin.rs @@ -27,11 +27,11 @@ impl super::Validator for BukkitValidator { &self, archive: &mut ZipArchive>, ) -> Result { - archive.by_name("plugin.yml").map_err(|_| { - ValidationError::InvalidInput( - "No plugin.yml present for plugin file.".into(), - ) - })?; + if archive.by_name("plugin.yml").is_err() { + return Ok(ValidationResult::Warning( + "No plugin.yml present for plugin file.", + )); + } Ok(ValidationResult::Pass) }