Staging bug fixes (#819)
* Staging bug fixes * Finish fixes * fix tests * Update migration * Update migrations * fix side types being added for ineligible loaders * fix tests * Fix tests * Finish fixes * Add slug display names
This commit is contained in:
parent
cf9c8cbb4f
commit
f5802fee31
@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n INSERT INTO team_members (\n id, team_id, user_id, role, permissions, organization_permissions, is_owner, accepted\n )\n VALUES (\n $1, $2, $3, $4, $5, $6, $7, $8\n )\n ",
|
||||
"query": "\n INSERT INTO team_members (\n id, team_id, user_id, role, permissions, organization_permissions, is_owner, accepted, payouts_split\n )\n VALUES (\n $1, $2, $3, $4, $5, $6, $7, $8, $9\n )\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
@ -12,10 +12,11 @@
|
||||
"Int8",
|
||||
"Int8",
|
||||
"Bool",
|
||||
"Bool"
|
||||
"Bool",
|
||||
"Numeric"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "8d6166509c910b6400efc1d1398aae92ebe04b0d4d1fe1762208167cee23b645"
|
||||
"hash": "02a585c845168c1bd8a82c30af351db75597da5456e29efc033ebb098e81e905"
|
||||
}
|
||||
20
.sqlx/query-0c2addb0d7a87fa558821ff8e943bbb751fb2bdc22d1a5368f61cc7827586840.json
generated
Normal file
20
.sqlx/query-0c2addb0d7a87fa558821ff8e943bbb751fb2bdc22d1a5368f61cc7827586840.json
generated
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n INSERT INTO files (id, version_id, url, filename, is_primary, size, file_type)\n VALUES ($1, $2, $3, $4, $5, $6, $7)\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Int8",
|
||||
"Int8",
|
||||
"Varchar",
|
||||
"Varchar",
|
||||
"Bool",
|
||||
"Int4",
|
||||
"Varchar"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "0c2addb0d7a87fa558821ff8e943bbb751fb2bdc22d1a5368f61cc7827586840"
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n INSERT INTO mods (\n id, team_id, name, summary, description,\n published, downloads, icon_url, status, requested_status,\n license_url, license,\n slug, color, monetization_status\n )\n VALUES (\n $1, $2, $3, $4, $5, $6, \n $7, $8, $9, $10, \n $11, $12, \n LOWER($13), $14, $15\n )\n ",
|
||||
"query": "\n INSERT INTO mods (\n id, team_id, name, summary, description,\n published, downloads, icon_url, status, requested_status,\n license_url, license,\n slug, color, monetization_status, organization_id\n )\n VALUES (\n $1, $2, $3, $4, $5, $6, \n $7, $8, $9, $10, \n $11, $12, \n LOWER($13), $14, $15, $16\n )\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
@ -19,10 +19,11 @@
|
||||
"Varchar",
|
||||
"Text",
|
||||
"Int4",
|
||||
"Varchar"
|
||||
"Varchar",
|
||||
"Int8"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "9b0c04bc7d44a60c175259cfe86b8e7ba0340ea9c89be30a89cc224d0f7e9727"
|
||||
"hash": "177b15719778b7788b88877af6affb8dba11da318b14dab7fcc7165c46bbecf5"
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n INSERT INTO files (id, version_id, url, filename, is_primary, size, file_type)\n SELECT * FROM UNNEST($1::bigint[], $2::bigint[], $3::varchar[], $4::varchar[], $5::bool[], $6::integer[], $7::varchar[])\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Int8Array",
|
||||
"Int8Array",
|
||||
"VarcharArray",
|
||||
"VarcharArray",
|
||||
"BoolArray",
|
||||
"Int4Array",
|
||||
"VarcharArray"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "24ae57ca296554a29b414caca866cfe7ab956ea28450d40a564498c3d27b937f"
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n SELECT EXISTS(SELECT 1 FROM organizations WHERE name = LOWER($1))\n ",
|
||||
"query": "\n SELECT EXISTS(SELECT 1 FROM organizations WHERE LOWER(slug) = LOWER($1))\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@ -18,5 +18,5 @@
|
||||
null
|
||||
]
|
||||
},
|
||||
"hash": "da30019590b9d0f7e21668997e780044c67a7c5d225e556c7ec2a4d7709db5ea"
|
||||
"hash": "38f651362c0778254c28ccd4745af611f4deb6e72f52b8cf65d0515f0fe14779"
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n SELECT o.id, o.name, o.team_id, o.description, o.icon_url, o.color\n FROM organizations o\n WHERE o.id = ANY($1) OR LOWER(o.name) = ANY($2)\n GROUP BY o.id;\n ",
|
||||
"query": "\n SELECT o.id, o.slug, o.name, o.team_id, o.description, o.icon_url, o.color\n FROM organizations o\n WHERE o.id = ANY($1) OR LOWER(o.slug) = ANY($2)\n GROUP BY o.id;\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@ -10,26 +10,31 @@
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "name",
|
||||
"name": "slug",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "name",
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"name": "team_id",
|
||||
"type_info": "Int8"
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"ordinal": 4,
|
||||
"name": "description",
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"ordinal": 4,
|
||||
"ordinal": 5,
|
||||
"name": "icon_url",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 5,
|
||||
"ordinal": 6,
|
||||
"name": "color",
|
||||
"type_info": "Int4"
|
||||
}
|
||||
@ -45,9 +50,10 @@
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "ca9f3298ff92051412f5096690b3314fe91fe0b7c79ab2f7d09396af47b85ee6"
|
||||
"hash": "4deaf065c12dbfd5f585286001fdf66f60524ec13eab7d922db9290237297849"
|
||||
}
|
||||
20
.sqlx/query-a004ad357abfc01b4ab8a2e0a78e2b38f8a0edb7e3b2174d040ac4bb6e5bde39.json
generated
Normal file
20
.sqlx/query-a004ad357abfc01b4ab8a2e0a78e2b38f8a0edb7e3b2174d040ac4bb6e5bde39.json
generated
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n INSERT INTO organizations (id, slug, name, team_id, description, icon_url, color)\n VALUES ($1, $2, $3, $4, $5, $6, $7)\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Int8",
|
||||
"Varchar",
|
||||
"Text",
|
||||
"Int8",
|
||||
"Text",
|
||||
"Varchar",
|
||||
"Int4"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "a004ad357abfc01b4ab8a2e0a78e2b38f8a0edb7e3b2174d040ac4bb6e5bde39"
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n SELECT m.id FROM organizations o\n INNER JOIN mods m ON m.organization_id = o.id\n WHERE (o.id = $1 AND $1 IS NOT NULL) OR (o.name = $2 AND $2 IS NOT NULL)\n ",
|
||||
"query": "\n SELECT m.id FROM organizations o\n INNER JOIN mods m ON m.organization_id = o.id\n WHERE (o.id = $1 AND $1 IS NOT NULL) OR (o.slug = $2 AND $2 IS NOT NULL)\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@ -19,5 +19,5 @@
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "da962cbb02919ea79e1106e6e5de39224d240d9b8afb5cead28578ca65e281ae"
|
||||
"hash": "a3448f22ec82f75ab2f3769b7d0a653a7d7315fb5e4696c26c6a96e6fc11e907"
|
||||
}
|
||||
@ -1,19 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n INSERT INTO organizations (id, name, team_id, description, icon_url, color)\n VALUES ($1, $2, $3, $4, $5, $6)\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Int8",
|
||||
"Varchar",
|
||||
"Int8",
|
||||
"Text",
|
||||
"Varchar",
|
||||
"Int4"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "bd48b18b9bef07185d2d050c7c978904cfbdf4ec765b7d3568f930939e236cbe"
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n SELECT o.id, o.name, o.team_id, o.description, o.icon_url, o.color\n FROM organizations o\n LEFT JOIN mods m ON m.organization_id = o.id\n WHERE m.id = $1\n GROUP BY o.id;\n ",
|
||||
"query": "\n SELECT o.id, o.slug, o.name, o.team_id, o.description, o.icon_url, o.color\n FROM organizations o\n LEFT JOIN mods m ON m.organization_id = o.id\n WHERE m.id = $1\n GROUP BY o.id;\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@ -10,26 +10,31 @@
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "name",
|
||||
"name": "slug",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "name",
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"name": "team_id",
|
||||
"type_info": "Int8"
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"ordinal": 4,
|
||||
"name": "description",
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"ordinal": 4,
|
||||
"ordinal": 5,
|
||||
"name": "icon_url",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 5,
|
||||
"ordinal": 6,
|
||||
"name": "color",
|
||||
"type_info": "Int4"
|
||||
}
|
||||
@ -44,9 +49,10 @@
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "26a6271a6d365e64c68ea5855109f1597a121b2e0075b20e2bc34659a269294b"
|
||||
"hash": "c0f23758b879b8a1304ad895b9bcf52b90913f23f96d16c24137b0d529a7475a"
|
||||
}
|
||||
16
.sqlx/query-cb57ae673f1a7e50cc319efddb9bdc82e2251596bcf85aea52e8def343e423b8.json
generated
Normal file
16
.sqlx/query-cb57ae673f1a7e50cc319efddb9bdc82e2251596bcf85aea52e8def343e423b8.json
generated
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n INSERT INTO hashes (file_id, algorithm, hash)\n VALUES ($1, $2, $3)\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Int8",
|
||||
"Varchar",
|
||||
"Bytea"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "cb57ae673f1a7e50cc319efddb9bdc82e2251596bcf85aea52e8def343e423b8"
|
||||
}
|
||||
@ -1,16 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n INSERT INTO hashes (file_id, algorithm, hash)\n SELECT * FROM UNNEST($1::bigint[], $2::varchar[], $3::bytea[])\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Int8Array",
|
||||
"VarcharArray",
|
||||
"ByteaArray"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "d2e826d4fa4e3e730cc84c97964c0c5fdd25cd49ddff8c593bd9b8a3b4d5ff1e"
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n UPDATE organizations\n SET name = LOWER($1)\n WHERE (id = $2)\n ",
|
||||
"query": "\n UPDATE organizations\n SET name = $1\n WHERE (id = $2)\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
@ -11,5 +11,5 @@
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "eefe0f3e40273da9adea96cdef5fd5cff917a864a701408455cc6b02cd005cf7"
|
||||
"hash": "dbbfd789feb09459ef25b90eba9458e0d4bceb6389eae13a166556f828a6c3a6"
|
||||
}
|
||||
15
.sqlx/query-ed7cc47dc2acfcaf27c4e763390371dccddbeea902928f1382c9505742f0a9a9.json
generated
Normal file
15
.sqlx/query-ed7cc47dc2acfcaf27c4e763390371dccddbeea902928f1382c9505742f0a9a9.json
generated
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n UPDATE organizations\n SET slug = $1\n WHERE (id = $2)\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Varchar",
|
||||
"Int8"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "ed7cc47dc2acfcaf27c4e763390371dccddbeea902928f1382c9505742f0a9a9"
|
||||
}
|
||||
@ -77,7 +77,7 @@ FROM versions v
|
||||
INNER JOIN mods m ON v.mod_id = m.id
|
||||
INNER JOIN loader_field_enum_values lfev ON m.client_side = lfev.original_id
|
||||
CROSS JOIN loader_fields lf
|
||||
WHERE client_side IS NOT NULL AND lfev.enum_id = 1 AND lf.field = 'client_side';
|
||||
WHERE client_side IS NOT NULL AND lfev.enum_id = 1 AND lf.field = 'client_side' AND NOT (ARRAY['vanilla', 'minecraft', 'optifine', 'iris', 'canvas', 'bukkit', 'folia', 'paper', 'purpur', 'spigot', 'sponge', 'datapack', 'bungeecord', 'velocity', 'waterfall'] @> m.loaders::text[]);;
|
||||
|
||||
INSERT INTO version_fields (version_id, field_id, enum_value)
|
||||
SELECT v.id, lf.id, lfev.id -- Note: bug fix/edited 2023-11-27
|
||||
@ -85,7 +85,7 @@ FROM versions v
|
||||
INNER JOIN mods m ON v.mod_id = m.id
|
||||
INNER JOIN loader_field_enum_values lfev ON m.server_side = lfev.original_id
|
||||
CROSS JOIN loader_fields lf
|
||||
WHERE server_side IS NOT NULL AND lfev.enum_id = 1 AND lf.field = 'server_side';
|
||||
WHERE server_side IS NOT NULL AND lfev.enum_id = 1 AND lf.field = 'server_side' AND NOT (ARRAY['vanilla', 'minecraft', 'optifine', 'iris', 'canvas', 'bukkit', 'folia', 'paper', 'purpur', 'spigot', 'sponge', 'datapack', 'bungeecord', 'velocity', 'waterfall'] @> m.loaders::text[]);
|
||||
|
||||
ALTER TABLE mods DROP COLUMN client_side;
|
||||
ALTER TABLE mods DROP COLUMN server_side;
|
||||
@ -99,8 +99,12 @@ SELECT id, 2, version, created, json_build_object('type', type, 'major', major)
|
||||
INSERT INTO loader_fields (field, field_type, enum_type, optional, min_val) VALUES('game_versions', 'array_enum', 2, false, 0);
|
||||
INSERT INTO loader_fields_loaders (loader_id, loader_field_id) SELECT l.id, lf.id FROM loaders l CROSS JOIN loader_fields lf WHERE lf.field = 'game_versions' AND l.loader = ANY( ARRAY['forge', 'fabric', 'quilt', 'modloader','rift','liteloader', 'neoforge']);
|
||||
|
||||
INSERT INTO version_fields(version_id, field_id, enum_value)
|
||||
SELECT gvv.joining_version_id, lf.id, lfev.id
|
||||
-- remove dangling game versions
|
||||
DELETE FROM game_versions_versions
|
||||
WHERE joining_version_id NOT IN (SELECT id FROM versions);
|
||||
|
||||
INSERT INTO version_fields(version_id, field_id, enum_value)
|
||||
SELECT gvv.joining_version_id, lf.id, lfev.id
|
||||
FROM game_versions_versions gvv INNER JOIN loader_field_enum_values lfev ON gvv.game_version_id = lfev.original_id
|
||||
CROSS JOIN loader_fields lf
|
||||
WHERE lf.field = 'game_versions' AND lfev.enum_id = 2;
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
ALTER TABLE users DROP COLUMN IF EXISTS paypal_email;
|
||||
|
||||
ALTER TABLE users
|
||||
ADD COLUMN paypal_country text NULL,
|
||||
ADD COLUMN paypal_email text NULL,
|
||||
|
||||
@ -4,13 +4,18 @@
|
||||
-- This also allows v2 routes (which have things such as client_side to remain to work with these loaders)
|
||||
INSERT INTO loader_fields_loaders
|
||||
SELECT l.id, lf.id FROM loaders l CROSS JOIN loader_fields lf
|
||||
WHERE lf.field=ANY(ARRAY['game_versions','client_and_server','server_only','client_only','singleplayer'])
|
||||
WHERE lf.field=ANY(ARRAY['client_and_server','server_only','client_only','singleplayer'])
|
||||
AND
|
||||
l.loader NOT IN ('vanilla', 'minecraft', 'optifine', 'iris', 'canvas')
|
||||
l.loader NOT IN ('vanilla', 'minecraft', 'optifine', 'iris', 'canvas', 'bukkit', 'folia', 'paper', 'purpur', 'spigot', 'sponge', 'datapack', 'bungeecord', 'velocity', 'waterfall')
|
||||
ON CONFLICT DO NOTHING;
|
||||
|
||||
INSERT INTO loader_fields_loaders
|
||||
SELECT l.id, lf.id FROM loaders l CROSS JOIN loader_fields lf
|
||||
WHERE lf.field=ANY(ARRAY['game_versions'])
|
||||
ON CONFLICT DO NOTHING;
|
||||
|
||||
-- All existing loader_project_types so far should have a games entry as minecraft
|
||||
INSERT INTO loaders_project_types_games
|
||||
SELECT lpt.joining_loader_id, lpt.joining_project_type_id, g.id FROM loaders_project_types lpt CROSS JOIN games g
|
||||
WHERE g.name='minecraft-java'
|
||||
ON CONFLICT DO NOTHING;
|
||||
ON CONFLICT DO NOTHING;
|
||||
|
||||
7
migrations/20240104203711_orgs-names.sql
Normal file
7
migrations/20240104203711_orgs-names.sql
Normal file
@ -0,0 +1,7 @@
|
||||
-- Add migration script here
|
||||
ALTER TABLE organizations RENAME COLUMN name TO slug;
|
||||
|
||||
ALTER TABLE organizations ADD COLUMN name text NULL;
|
||||
UPDATE organizations SET name = slug;
|
||||
ALTER TABLE organizations ALTER COLUMN name SET NOT NULL;
|
||||
|
||||
@ -15,7 +15,10 @@ pub struct Organization {
|
||||
/// The id of the organization
|
||||
pub id: OrganizationId,
|
||||
|
||||
/// The title (and slug) of the organization
|
||||
/// The slug of the organization
|
||||
pub slug: String,
|
||||
|
||||
/// The title of the organization
|
||||
pub name: String,
|
||||
|
||||
/// The associated team of the organization
|
||||
@ -36,10 +39,11 @@ impl Organization {
|
||||
) -> Result<(), super::DatabaseError> {
|
||||
sqlx::query!(
|
||||
"
|
||||
INSERT INTO organizations (id, name, team_id, description, icon_url, color)
|
||||
VALUES ($1, $2, $3, $4, $5, $6)
|
||||
INSERT INTO organizations (id, slug, name, team_id, description, icon_url, color)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
||||
",
|
||||
self.id.0,
|
||||
self.slug,
|
||||
self.name,
|
||||
self.team_id as TeamId,
|
||||
self.description,
|
||||
@ -149,7 +153,7 @@ impl Organization {
|
||||
{
|
||||
remaining_strings.retain(|x| {
|
||||
&to_base62(organization.id.0 as u64) != x
|
||||
&& organization.name.to_lowercase() != x.to_lowercase()
|
||||
&& organization.slug.to_lowercase() != x.to_lowercase()
|
||||
});
|
||||
found_organizations.push(organization);
|
||||
continue;
|
||||
@ -166,9 +170,9 @@ impl Organization {
|
||||
|
||||
let organizations: Vec<Organization> = sqlx::query!(
|
||||
"
|
||||
SELECT o.id, o.name, o.team_id, o.description, o.icon_url, o.color
|
||||
SELECT o.id, o.slug, o.name, o.team_id, o.description, o.icon_url, o.color
|
||||
FROM organizations o
|
||||
WHERE o.id = ANY($1) OR LOWER(o.name) = ANY($2)
|
||||
WHERE o.id = ANY($1) OR LOWER(o.slug) = ANY($2)
|
||||
GROUP BY o.id;
|
||||
",
|
||||
&organization_ids_parsed,
|
||||
@ -181,6 +185,7 @@ impl Organization {
|
||||
.try_filter_map(|e| async {
|
||||
Ok(e.right().map(|m| Organization {
|
||||
id: OrganizationId(m.id),
|
||||
slug: m.slug,
|
||||
name: m.name,
|
||||
team_id: TeamId(m.team_id),
|
||||
description: m.description,
|
||||
@ -203,7 +208,7 @@ impl Organization {
|
||||
redis
|
||||
.set(
|
||||
ORGANIZATIONS_TITLES_NAMESPACE,
|
||||
&organization.name.to_lowercase(),
|
||||
&organization.slug.to_lowercase(),
|
||||
&organization.id.0.to_string(),
|
||||
None,
|
||||
)
|
||||
@ -226,7 +231,7 @@ impl Organization {
|
||||
{
|
||||
let result = sqlx::query!(
|
||||
"
|
||||
SELECT o.id, o.name, o.team_id, o.description, o.icon_url, o.color
|
||||
SELECT o.id, o.slug, o.name, o.team_id, o.description, o.icon_url, o.color
|
||||
FROM organizations o
|
||||
LEFT JOIN mods m ON m.organization_id = o.id
|
||||
WHERE m.id = $1
|
||||
@ -240,6 +245,7 @@ impl Organization {
|
||||
if let Some(result) = result {
|
||||
Ok(Some(Organization {
|
||||
id: OrganizationId(result.id),
|
||||
slug: result.slug,
|
||||
name: result.name,
|
||||
team_id: TeamId(result.team_id),
|
||||
description: result.description,
|
||||
@ -299,7 +305,7 @@ impl Organization {
|
||||
|
||||
pub async fn clear_cache(
|
||||
id: OrganizationId,
|
||||
title: Option<String>,
|
||||
slug: Option<String>,
|
||||
redis: &RedisPool,
|
||||
) -> Result<(), super::DatabaseError> {
|
||||
let mut redis = redis.connect().await?;
|
||||
@ -309,7 +315,7 @@ impl Organization {
|
||||
(ORGANIZATIONS_NAMESPACE, Some(id.0.to_string())),
|
||||
(
|
||||
ORGANIZATIONS_TITLES_NAMESPACE,
|
||||
title.map(|x| x.to_lowercase()),
|
||||
slug.map(|x| x.to_lowercase()),
|
||||
),
|
||||
])
|
||||
.await?;
|
||||
|
||||
@ -273,13 +273,13 @@ impl Project {
|
||||
id, team_id, name, summary, description,
|
||||
published, downloads, icon_url, status, requested_status,
|
||||
license_url, license,
|
||||
slug, color, monetization_status
|
||||
slug, color, monetization_status, organization_id
|
||||
)
|
||||
VALUES (
|
||||
$1, $2, $3, $4, $5, $6,
|
||||
$7, $8, $9, $10,
|
||||
$11, $12,
|
||||
LOWER($13), $14, $15
|
||||
LOWER($13), $14, $15, $16
|
||||
)
|
||||
",
|
||||
self.id as ProjectId,
|
||||
@ -297,6 +297,7 @@ impl Project {
|
||||
self.slug.as_ref(),
|
||||
self.color.map(|x| x as i32),
|
||||
self.monetization_status.as_str(),
|
||||
self.organization_id.map(|x| x.0 as i64),
|
||||
)
|
||||
.execute(&mut **transaction)
|
||||
.await?;
|
||||
|
||||
@ -412,10 +412,10 @@ impl TeamMember {
|
||||
sqlx::query!(
|
||||
"
|
||||
INSERT INTO team_members (
|
||||
id, team_id, user_id, role, permissions, organization_permissions, is_owner, accepted
|
||||
id, team_id, user_id, role, permissions, organization_permissions, is_owner, accepted, payouts_split
|
||||
)
|
||||
VALUES (
|
||||
$1, $2, $3, $4, $5, $6, $7, $8
|
||||
$1, $2, $3, $4, $5, $6, $7, $8, $9
|
||||
)
|
||||
",
|
||||
self.id as TeamMemberId,
|
||||
@ -426,6 +426,7 @@ impl TeamMember {
|
||||
self.organization_permissions.map(|p| p.bits() as i64),
|
||||
self.is_owner,
|
||||
self.accepted,
|
||||
self.payouts_split
|
||||
)
|
||||
.execute(&mut **transaction)
|
||||
.await?;
|
||||
|
||||
@ -126,70 +126,42 @@ pub struct VersionFileBuilder {
|
||||
}
|
||||
|
||||
impl VersionFileBuilder {
|
||||
pub async fn insert_many(
|
||||
version_files: Vec<Self>,
|
||||
pub async fn insert(
|
||||
self,
|
||||
version_id: VersionId,
|
||||
transaction: &mut sqlx::Transaction<'_, sqlx::Postgres>,
|
||||
) -> Result<FileId, DatabaseError> {
|
||||
let file_id = generate_file_id(transaction).await?;
|
||||
let file_id = generate_file_id(&mut *transaction).await?;
|
||||
|
||||
let (file_ids, version_ids, urls, filenames, primary, sizes, file_types): (
|
||||
Vec<_>,
|
||||
Vec<_>,
|
||||
Vec<_>,
|
||||
Vec<_>,
|
||||
Vec<_>,
|
||||
Vec<_>,
|
||||
Vec<_>,
|
||||
) = version_files
|
||||
.iter()
|
||||
.map(|f| {
|
||||
(
|
||||
file_id.0,
|
||||
version_id.0,
|
||||
f.url.clone(),
|
||||
f.filename.clone(),
|
||||
f.primary,
|
||||
f.size as i32,
|
||||
f.file_type.map(|x| x.to_string()),
|
||||
)
|
||||
})
|
||||
.multiunzip();
|
||||
sqlx::query!(
|
||||
"
|
||||
INSERT INTO files (id, version_id, url, filename, is_primary, size, file_type)
|
||||
SELECT * FROM UNNEST($1::bigint[], $2::bigint[], $3::varchar[], $4::varchar[], $5::bool[], $6::integer[], $7::varchar[])
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
||||
",
|
||||
&file_ids[..],
|
||||
&version_ids[..],
|
||||
&urls[..],
|
||||
&filenames[..],
|
||||
&primary[..],
|
||||
&sizes[..],
|
||||
&file_types[..] as &[Option<String>],
|
||||
file_id as FileId,
|
||||
version_id as VersionId,
|
||||
self.url,
|
||||
self.filename,
|
||||
self.primary,
|
||||
self.size as i32,
|
||||
self.file_type.map(|x| x.as_str()),
|
||||
)
|
||||
.execute(&mut **transaction)
|
||||
.await?;
|
||||
|
||||
let (file_ids, algorithms, hashes): (Vec<_>, Vec<_>, Vec<_>) = version_files
|
||||
.into_iter()
|
||||
.flat_map(|f| {
|
||||
f.hashes
|
||||
.into_iter()
|
||||
.map(|h| (file_id.0, h.algorithm, h.hash))
|
||||
})
|
||||
.multiunzip();
|
||||
sqlx::query!(
|
||||
"
|
||||
INSERT INTO hashes (file_id, algorithm, hash)
|
||||
SELECT * FROM UNNEST($1::bigint[], $2::varchar[], $3::bytea[])
|
||||
",
|
||||
&file_ids[..],
|
||||
&algorithms[..],
|
||||
&hashes[..],
|
||||
)
|
||||
.execute(&mut **transaction)
|
||||
.await?;
|
||||
for hash in self.hashes {
|
||||
sqlx::query!(
|
||||
"
|
||||
INSERT INTO hashes (file_id, algorithm, hash)
|
||||
VALUES ($1, $2, $3)
|
||||
",
|
||||
file_id as FileId,
|
||||
hash.algorithm,
|
||||
hash.hash,
|
||||
)
|
||||
.execute(&mut **transaction)
|
||||
.await?;
|
||||
}
|
||||
|
||||
Ok(file_id)
|
||||
}
|
||||
@ -242,7 +214,10 @@ impl VersionBuilder {
|
||||
version_id,
|
||||
..
|
||||
} = self;
|
||||
VersionFileBuilder::insert_many(files, self.version_id, transaction).await?;
|
||||
|
||||
for file in files {
|
||||
file.insert(version_id, transaction).await?;
|
||||
}
|
||||
|
||||
DependencyBuilder::insert_many(dependencies, self.version_id, transaction).await?;
|
||||
|
||||
|
||||
@ -83,24 +83,23 @@ impl LegacyProject {
|
||||
let mut game_versions = Vec::new();
|
||||
|
||||
// V2 versions only have one project type- v3 versions can rarely have multiple.
|
||||
// We'll prioritize 'modpack' first, then 'mod', and if neither are found, use the first one.
|
||||
// We'll prioritize 'modpack' first, and if neither are found, use the first one.
|
||||
// If there are no project types, default to 'project'
|
||||
let mut project_types = data.project_types;
|
||||
if project_types.contains(&"modpack".to_string()) {
|
||||
project_types = vec!["modpack".to_string()];
|
||||
} else if project_types.contains(&"mod".to_string()) {
|
||||
project_types = vec!["mod".to_string()];
|
||||
}
|
||||
let project_type = project_types
|
||||
|
||||
let og_project_type = project_types
|
||||
.first()
|
||||
.cloned()
|
||||
.unwrap_or("project".to_string()); // Default to 'project' if none are found
|
||||
|
||||
let mut project_type = if project_type == "datapack" || project_type == "plugin" {
|
||||
let mut project_type = if og_project_type == "datapack" || og_project_type == "plugin" {
|
||||
// These are not supported in V2, so we'll just use 'mod' instead
|
||||
"mod".to_string()
|
||||
} else {
|
||||
project_type
|
||||
og_project_type.clone()
|
||||
};
|
||||
|
||||
let mut loaders = data.loaders;
|
||||
@ -120,7 +119,8 @@ impl LegacyProject {
|
||||
.iter()
|
||||
.map(|f| (f.field_name.clone(), f.value.clone().serialize_internal()))
|
||||
.collect::<HashMap<_, _>>();
|
||||
(client_side, server_side) = v2_reroute::convert_side_types_v2(&fields);
|
||||
(client_side, server_side) =
|
||||
v2_reroute::convert_side_types_v2(&fields, Some(&*og_project_type));
|
||||
|
||||
// - if loader is mrpack, this is a modpack
|
||||
// the loaders are whatever the corresponding loader fields are
|
||||
|
||||
@ -75,24 +75,22 @@ impl LegacyResultSearchProject {
|
||||
display_categories.dedup();
|
||||
|
||||
// V2 versions only have one project type- v3 versions can rarely have multiple.
|
||||
// We'll prioritize 'modpack' first, then 'mod', and if neither are found, use the first one.
|
||||
// We'll prioritize 'modpack' first, and if neither are found, use the first one.
|
||||
// If there are no project types, default to 'project'
|
||||
let mut project_types = result_search_project.project_types;
|
||||
if project_types.contains(&"modpack".to_string()) {
|
||||
project_types = vec!["modpack".to_string()];
|
||||
} else if project_types.contains(&"mod".to_string()) {
|
||||
project_types = vec!["mod".to_string()];
|
||||
}
|
||||
let project_type = project_types
|
||||
let og_project_type = project_types
|
||||
.first()
|
||||
.cloned()
|
||||
.unwrap_or("project".to_string()); // Default to 'project' if none are found
|
||||
|
||||
let project_type = if project_type == "datapack" || project_type == "plugin" {
|
||||
let project_type = if og_project_type == "datapack" || og_project_type == "plugin" {
|
||||
// These are not supported in V2, so we'll just use 'mod' instead
|
||||
"mod".to_string()
|
||||
} else {
|
||||
project_type
|
||||
og_project_type.clone()
|
||||
};
|
||||
|
||||
let loader_fields = result_search_project.loader_fields.clone();
|
||||
@ -115,6 +113,7 @@ impl LegacyResultSearchProject {
|
||||
client_only,
|
||||
server_only,
|
||||
client_and_server,
|
||||
Some(&*og_project_type),
|
||||
);
|
||||
let client_side = client_side.to_string();
|
||||
let server_side = server_side.to_string();
|
||||
|
||||
@ -15,6 +15,8 @@ pub struct OrganizationId(pub u64);
|
||||
pub struct Organization {
|
||||
/// The id of the organization
|
||||
pub id: OrganizationId,
|
||||
/// The slug of the organization
|
||||
pub slug: String,
|
||||
/// The title (and slug) of the organization
|
||||
pub name: String,
|
||||
/// The associated team of the organization
|
||||
@ -38,6 +40,7 @@ impl Organization {
|
||||
) -> Self {
|
||||
Self {
|
||||
id: data.id.into(),
|
||||
slug: data.slug,
|
||||
name: data.name,
|
||||
team_id: data.team_id.into(),
|
||||
description: data.description,
|
||||
|
||||
@ -497,7 +497,7 @@ pub async fn project_edit(
|
||||
let version = Version::from(version);
|
||||
let mut fields = version.fields;
|
||||
let (current_client_side, current_server_side) =
|
||||
v2_reroute::convert_side_types_v2(&fields);
|
||||
v2_reroute::convert_side_types_v2(&fields, None);
|
||||
let client_side = client_side.unwrap_or(current_client_side);
|
||||
let server_side = server_side.unwrap_or(current_server_side);
|
||||
fields.extend(v2_reroute::convert_side_types_v3(client_side, server_side));
|
||||
|
||||
@ -79,16 +79,22 @@ pub async fn loader_list(
|
||||
Ok(loaders) => {
|
||||
let loaders = loaders
|
||||
.into_iter()
|
||||
.map(|l| LoaderData {
|
||||
icon: l.icon,
|
||||
name: l.name,
|
||||
.filter(|l| &*l.name != "mrpack")
|
||||
.map(|l| {
|
||||
let mut supported_project_types = l.supported_project_types;
|
||||
// Add generic 'project' type to all loaders, which is the v2 representation of
|
||||
// a project type before any versions are set.
|
||||
supported_project_types: l
|
||||
.supported_project_types
|
||||
.into_iter()
|
||||
.chain(std::iter::once("project".to_string()))
|
||||
.collect(),
|
||||
supported_project_types.push("project".to_string());
|
||||
|
||||
if ["forge", "fabric", "quilt", "neoforge"].contains(&&*l.name) {
|
||||
supported_project_types.push("modpack".to_string());
|
||||
}
|
||||
|
||||
LoaderData {
|
||||
icon: l.icon,
|
||||
name: l.name,
|
||||
supported_project_types,
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
Ok(HttpResponse::Ok().json(loaders))
|
||||
|
||||
@ -242,6 +242,7 @@ pub fn convert_side_type_facets_v3(facets: Vec<Vec<Vec<String>>>) -> Vec<Vec<Vec
|
||||
// this is not lossless. (See tests)
|
||||
pub fn convert_side_types_v2(
|
||||
side_types: &HashMap<String, Value>,
|
||||
project_type: Option<&str>,
|
||||
) -> (LegacySideType, LegacySideType) {
|
||||
let client_and_server = side_types
|
||||
.get("client_and_server")
|
||||
@ -265,6 +266,7 @@ pub fn convert_side_types_v2(
|
||||
client_only,
|
||||
server_only,
|
||||
Some(client_and_server),
|
||||
project_type,
|
||||
)
|
||||
}
|
||||
|
||||
@ -274,29 +276,38 @@ pub fn convert_side_types_v2_bools(
|
||||
client_only: bool,
|
||||
server_only: bool,
|
||||
client_and_server: Option<bool>,
|
||||
project_type: Option<&str>,
|
||||
) -> (LegacySideType, LegacySideType) {
|
||||
use LegacySideType::{Optional, Required, Unsupported};
|
||||
use LegacySideType::{Optional, Required, Unknown, Unsupported};
|
||||
|
||||
let singleplayer = singleplayer.or(client_and_server).unwrap_or(false);
|
||||
match project_type {
|
||||
Some("plugin") => (Unsupported, Required),
|
||||
Some("datapack") => (Optional, Required),
|
||||
Some("shader") => (Required, Unsupported),
|
||||
Some("resourcepack") => (Required, Unsupported),
|
||||
_ => {
|
||||
let singleplayer = singleplayer.or(client_and_server).unwrap_or(false);
|
||||
|
||||
match (singleplayer, client_only, server_only) {
|
||||
// Only singleplayer
|
||||
(true, false, false) => (Required, Required),
|
||||
match (singleplayer, client_only, server_only) {
|
||||
// Only singleplayer
|
||||
(true, false, false) => (Required, Required),
|
||||
|
||||
// Client only and not server only
|
||||
(false, true, false) => (Required, Unsupported),
|
||||
(true, true, false) => (Required, Unsupported),
|
||||
// Client only and not server only
|
||||
(false, true, false) => (Required, Unsupported),
|
||||
(true, true, false) => (Required, Unsupported),
|
||||
|
||||
// Server only and not client only
|
||||
(false, false, true) => (Unsupported, Required),
|
||||
(true, false, true) => (Unsupported, Required),
|
||||
// Server only and not client only
|
||||
(false, false, true) => (Unsupported, Required),
|
||||
(true, false, true) => (Unsupported, Required),
|
||||
|
||||
// Both server only and client only
|
||||
(true, true, true) => (Optional, Optional),
|
||||
(false, true, true) => (Optional, Optional),
|
||||
// Both server only and client only
|
||||
(true, true, true) => (Optional, Optional),
|
||||
(false, true, true) => (Optional, Optional),
|
||||
|
||||
// Bad type
|
||||
(false, false, false) => (Unsupported, Unsupported),
|
||||
// Bad type
|
||||
(false, false, false) => (Unknown, Unknown),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -321,6 +332,7 @@ mod tests {
|
||||
(Unsupported, Optional),
|
||||
(Required, Optional),
|
||||
(Optional, Required),
|
||||
(Unsupported, Unsupported),
|
||||
];
|
||||
|
||||
for client_side in [Required, Optional, Unsupported] {
|
||||
@ -329,7 +341,7 @@ mod tests {
|
||||
continue;
|
||||
}
|
||||
let side_types = convert_side_types_v3(client_side, server_side);
|
||||
let (client_side2, server_side2) = convert_side_types_v2(&side_types);
|
||||
let (client_side2, server_side2) = convert_side_types_v2(&side_types, None);
|
||||
assert_eq!(client_side, client_side2);
|
||||
assert_eq!(server_side, server_side2);
|
||||
}
|
||||
|
||||
@ -72,7 +72,7 @@ pub async fn organization_projects_get(
|
||||
"
|
||||
SELECT m.id FROM organizations o
|
||||
INNER JOIN mods m ON m.organization_id = o.id
|
||||
WHERE (o.id = $1 AND $1 IS NOT NULL) OR (o.name = $2 AND $2 IS NOT NULL)
|
||||
WHERE (o.id = $1 AND $1 IS NOT NULL) OR (o.slug = $2 AND $2 IS NOT NULL)
|
||||
",
|
||||
possible_organization_id.map(|x| x as i64),
|
||||
info
|
||||
@ -95,7 +95,9 @@ pub struct NewOrganization {
|
||||
length(min = 3, max = 64),
|
||||
regex = "crate::util::validate::RE_URL_SAFE"
|
||||
)]
|
||||
// Title of the organization, also used as slug
|
||||
pub slug: String,
|
||||
// Title of the organization
|
||||
#[validate(length(min = 3, max = 64))]
|
||||
pub name: String,
|
||||
#[validate(length(min = 3, max = 256))]
|
||||
pub description: String,
|
||||
@ -126,12 +128,12 @@ pub async fn organization_create(
|
||||
|
||||
// Try title
|
||||
let name_organization_id_option: Option<OrganizationId> =
|
||||
serde_json::from_str(&format!("\"{}\"", new_organization.name)).ok();
|
||||
serde_json::from_str(&format!("\"{}\"", new_organization.slug)).ok();
|
||||
let mut organization_strings = vec![];
|
||||
if let Some(name_organization_id) = name_organization_id_option {
|
||||
organization_strings.push(name_organization_id.to_string());
|
||||
}
|
||||
organization_strings.push(new_organization.name.clone());
|
||||
organization_strings.push(new_organization.slug.clone());
|
||||
let results = Organization::get_many(&organization_strings, &mut *transaction, &redis).await?;
|
||||
if !results.is_empty() {
|
||||
return Err(CreateError::SlugCollision);
|
||||
@ -157,6 +159,7 @@ pub async fn organization_create(
|
||||
// Create organization
|
||||
let organization = Organization {
|
||||
id: organization_id,
|
||||
slug: new_organization.slug.clone(),
|
||||
name: new_organization.name.clone(),
|
||||
description: new_organization.description.clone(),
|
||||
team_id,
|
||||
@ -336,7 +339,8 @@ pub struct OrganizationEdit {
|
||||
length(min = 3, max = 64),
|
||||
regex = "crate::util::validate::RE_URL_SAFE"
|
||||
)]
|
||||
// Title of the organization, also used as slug
|
||||
pub slug: Option<String>,
|
||||
#[validate(length(min = 3, max = 64))]
|
||||
pub name: Option<String>,
|
||||
}
|
||||
|
||||
@ -406,8 +410,28 @@ pub async fn organizations_edit(
|
||||
.to_string(),
|
||||
));
|
||||
}
|
||||
sqlx::query!(
|
||||
"
|
||||
UPDATE organizations
|
||||
SET name = $1
|
||||
WHERE (id = $2)
|
||||
",
|
||||
name,
|
||||
id as database::models::ids::OrganizationId,
|
||||
)
|
||||
.execute(&mut *transaction)
|
||||
.await?;
|
||||
}
|
||||
|
||||
let name_organization_id_option: Option<u64> = parse_base62(name).ok();
|
||||
if let Some(slug) = &new_organization.slug {
|
||||
if !perms.contains(OrganizationPermissions::EDIT_DETAILS) {
|
||||
return Err(ApiError::CustomAuthentication(
|
||||
"You do not have the permissions to edit the slug of this organization!"
|
||||
.to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
let name_organization_id_option: Option<u64> = parse_base62(slug).ok();
|
||||
if let Some(name_organization_id) = name_organization_id_option {
|
||||
let results = sqlx::query!(
|
||||
"
|
||||
@ -420,26 +444,26 @@ pub async fn organizations_edit(
|
||||
|
||||
if results.exists.unwrap_or(true) {
|
||||
return Err(ApiError::InvalidInput(
|
||||
"name collides with other organization's id!".to_string(),
|
||||
"slug collides with other organization's id!".to_string(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure the new name is different from the old one
|
||||
// We are able to unwrap here because the name is always set
|
||||
if !name.eq(&organization_item.name.clone()) {
|
||||
if !slug.eq(&organization_item.slug.clone()) {
|
||||
let results = sqlx::query!(
|
||||
"
|
||||
SELECT EXISTS(SELECT 1 FROM organizations WHERE name = LOWER($1))
|
||||
",
|
||||
name
|
||||
SELECT EXISTS(SELECT 1 FROM organizations WHERE LOWER(slug) = LOWER($1))
|
||||
",
|
||||
slug
|
||||
)
|
||||
.fetch_one(&mut *transaction)
|
||||
.await?;
|
||||
|
||||
if results.exists.unwrap_or(true) {
|
||||
return Err(ApiError::InvalidInput(
|
||||
"Name collides with other organization's id!".to_string(),
|
||||
"slug collides with other organization's id!".to_string(),
|
||||
));
|
||||
}
|
||||
}
|
||||
@ -447,10 +471,10 @@ pub async fn organizations_edit(
|
||||
sqlx::query!(
|
||||
"
|
||||
UPDATE organizations
|
||||
SET name = LOWER($1)
|
||||
SET slug = $1
|
||||
WHERE (id = $2)
|
||||
",
|
||||
Some(name),
|
||||
Some(slug),
|
||||
id as database::models::ids::OrganizationId,
|
||||
)
|
||||
.execute(&mut *transaction)
|
||||
@ -460,7 +484,7 @@ pub async fn organizations_edit(
|
||||
transaction.commit().await?;
|
||||
database::models::Organization::clear_cache(
|
||||
organization_item.id,
|
||||
Some(organization_item.name),
|
||||
Some(organization_item.slug),
|
||||
&redis,
|
||||
)
|
||||
.await?;
|
||||
@ -578,7 +602,7 @@ pub async fn organization_delete(
|
||||
|
||||
transaction.commit().await?;
|
||||
|
||||
database::models::Organization::clear_cache(organization.id, Some(organization.name), &redis)
|
||||
database::models::Organization::clear_cache(organization.id, Some(organization.slug), &redis)
|
||||
.await?;
|
||||
|
||||
for team_id in organization_project_teams {
|
||||
@ -994,7 +1018,7 @@ pub async fn organization_icon_edit(
|
||||
transaction.commit().await?;
|
||||
database::models::Organization::clear_cache(
|
||||
organization_item.id,
|
||||
Some(organization_item.name),
|
||||
Some(organization_item.slug),
|
||||
&redis,
|
||||
)
|
||||
.await?;
|
||||
@ -1079,7 +1103,7 @@ pub async fn delete_organization_icon(
|
||||
|
||||
database::models::Organization::clear_cache(
|
||||
organization_item.id,
|
||||
Some(organization_item.name),
|
||||
Some(organization_item.slug),
|
||||
&redis,
|
||||
)
|
||||
.await?;
|
||||
|
||||
@ -73,7 +73,7 @@ pub enum CreateError {
|
||||
InvalidCategory(String),
|
||||
#[error("Invalid file type for version file: {0}")]
|
||||
InvalidFileType(String),
|
||||
#[error("Slug collides with other project's id!")]
|
||||
#[error("Slug is already taken!")]
|
||||
SlugCollision,
|
||||
#[error("Authentication Error: {0}")]
|
||||
Unauthorized(#[from] AuthenticationError),
|
||||
@ -612,22 +612,22 @@ async fn project_create_inner(
|
||||
additional_categories.extend(ids.values());
|
||||
}
|
||||
|
||||
// Should only be owner if not attached to an organization
|
||||
let is_owner = project_create_data.organization_id.is_none();
|
||||
let mut members = vec![];
|
||||
|
||||
let team = models::team_item::TeamBuilder {
|
||||
members: vec![models::team_item::TeamMemberBuilder {
|
||||
if project_create_data.organization_id.is_none() {
|
||||
members.push(models::team_item::TeamMemberBuilder {
|
||||
user_id: current_user.id.into(),
|
||||
role: crate::models::teams::OWNER_ROLE.to_owned(),
|
||||
is_owner,
|
||||
// Allow all permissions for project creator, even if attached to a project
|
||||
is_owner: true,
|
||||
permissions: ProjectPermissions::all(),
|
||||
organization_permissions: None,
|
||||
accepted: true,
|
||||
payouts_split: Decimal::ONE_HUNDRED,
|
||||
ordering: 0,
|
||||
}],
|
||||
};
|
||||
})
|
||||
}
|
||||
|
||||
let team = models::team_item::TeamBuilder { members };
|
||||
|
||||
let team_id = team.insert(&mut *transaction).await?;
|
||||
|
||||
|
||||
@ -65,7 +65,7 @@ pub async fn team_members_get_project(
|
||||
}
|
||||
let members_data =
|
||||
TeamMember::get_from_team_full(project.inner.team_id, &**pool, &redis).await?;
|
||||
let users = crate::database::models::User::get_many_ids(
|
||||
let users = User::get_many_ids(
|
||||
&members_data.iter().map(|x| x.user_id).collect::<Vec<_>>(),
|
||||
&**pool,
|
||||
&redis,
|
||||
@ -73,14 +73,14 @@ pub async fn team_members_get_project(
|
||||
.await?;
|
||||
|
||||
let user_id = current_user.as_ref().map(|x| x.id.into());
|
||||
let logged_in = if let Some(user_id) = user_id {
|
||||
let (team_member, organization_team_member) =
|
||||
TeamMember::get_for_project_permissions(&project.inner, user_id, &**pool).await?;
|
||||
|
||||
let logged_in = current_user
|
||||
.and_then(|user| {
|
||||
members_data
|
||||
.iter()
|
||||
.find(|x| x.user_id == user.id.into() && x.accepted)
|
||||
})
|
||||
.is_some();
|
||||
team_member.is_some() || organization_team_member.is_some()
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
let team_members: Vec<_> = members_data
|
||||
.into_iter()
|
||||
|
||||
@ -731,7 +731,9 @@ async fn upload_file_to_version_inner(
|
||||
"At least one file must be specified".to_string(),
|
||||
));
|
||||
} else {
|
||||
VersionFileBuilder::insert_many(file_builders, version_id, &mut *transaction).await?;
|
||||
for file in file_builders {
|
||||
file.insert(version_id, &mut *transaction).await?;
|
||||
}
|
||||
}
|
||||
|
||||
// Clear version cache
|
||||
|
||||
@ -163,6 +163,9 @@ pub async fn index_local(
|
||||
})
|
||||
.unwrap_or_default();
|
||||
categories.extend(mrpack_loaders);
|
||||
if loader_fields.contains_key("mrpack_loaders") {
|
||||
categories.retain(|x| *x != "mrpack");
|
||||
}
|
||||
|
||||
let gallery = m
|
||||
.gallery_items
|
||||
|
||||
@ -11,7 +11,7 @@ use serde_json::json;
|
||||
|
||||
mod common;
|
||||
|
||||
// TODO: Revisit this with the new modify_json in the version maker
|
||||
// TODO: Revisit this wit h the new modify_json in the version maker
|
||||
// That change here should be able to simplify it vastly
|
||||
|
||||
#[actix_rt::test]
|
||||
@ -61,17 +61,13 @@ async fn search_projects() {
|
||||
),
|
||||
// Project type change
|
||||
// Modpack should still be able to search based on former loader, even though technically the loader is 'mrpack'
|
||||
(json!([["categories:mrpack"]]), vec![4]),
|
||||
// (json!([["categories:mrpack"]]), vec![4]),
|
||||
// (
|
||||
// json!([["categories:fabric"]]),
|
||||
// vec![4],
|
||||
// ),
|
||||
(
|
||||
json!([["categories:mrpack"], ["categories:fabric"]]),
|
||||
vec![4],
|
||||
),
|
||||
(
|
||||
json!([
|
||||
["categories:mrpack"],
|
||||
["categories:fabric"],
|
||||
["project_types:modpack"]
|
||||
]),
|
||||
json!([["categories:fabric"], ["project_types:modpack"]]),
|
||||
vec![4],
|
||||
),
|
||||
];
|
||||
|
||||
@ -259,14 +259,14 @@ async fn search_projects() {
|
||||
),
|
||||
// Project type change
|
||||
// Modpack should still be able to search based on former loader, even though technically the loader is 'mrpack'
|
||||
(json!([["categories:mrpack"]]), vec![4]),
|
||||
(
|
||||
json!([["categories:mrpack"], ["categories:fabric"]]),
|
||||
vec![4],
|
||||
),
|
||||
// (json!([["categories:mrpack"]]), vec![4]),
|
||||
// (
|
||||
// json!([["categories:mrpack"], ["categories:fabric"]]),
|
||||
// vec![4],
|
||||
// ),
|
||||
(
|
||||
json!([
|
||||
["categories:mrpack"],
|
||||
// ["categories:mrpack"],
|
||||
["categories:fabric"],
|
||||
["project_type:modpack"]
|
||||
]),
|
||||
|
||||
@ -46,7 +46,7 @@ async fn get_tags() {
|
||||
let loader_names = loaders.into_iter().map(|x| x.name).collect::<HashSet<_>>();
|
||||
assert_eq!(
|
||||
loader_names,
|
||||
["fabric", "forge", "mrpack", "bukkit", "waterfall"]
|
||||
["fabric", "forge", "bukkit", "waterfall"]
|
||||
.iter()
|
||||
.map(|s| s.to_string())
|
||||
.collect()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user