You've already forked AstralRinth
forked from didirus/AstralRinth
Move descriptions to database, switch to SHA-512 hashes, fix declining invites not working, allow user deletion, fix broken permission checks for many things, security fixes
This commit is contained in:
@@ -36,7 +36,7 @@ pub struct ModBuilder {
|
||||
pub team_id: TeamId,
|
||||
pub title: String,
|
||||
pub description: String,
|
||||
pub body_url: String,
|
||||
pub body: String,
|
||||
pub icon_url: Option<String>,
|
||||
pub issues_url: Option<String>,
|
||||
pub source_url: Option<String>,
|
||||
@@ -63,7 +63,8 @@ impl ModBuilder {
|
||||
team_id: self.team_id,
|
||||
title: self.title,
|
||||
description: self.description,
|
||||
body_url: self.body_url,
|
||||
body: self.body,
|
||||
body_url: None,
|
||||
published: chrono::Utc::now(),
|
||||
updated: chrono::Utc::now(),
|
||||
status: self.status,
|
||||
@@ -113,7 +114,8 @@ pub struct Mod {
|
||||
pub team_id: TeamId,
|
||||
pub title: String,
|
||||
pub description: String,
|
||||
pub body_url: String,
|
||||
pub body: String,
|
||||
pub body_url: Option<String>,
|
||||
pub published: chrono::DateTime<chrono::Utc>,
|
||||
pub updated: chrono::DateTime<chrono::Utc>,
|
||||
pub status: StatusId,
|
||||
@@ -138,7 +140,7 @@ impl Mod {
|
||||
sqlx::query!(
|
||||
"
|
||||
INSERT INTO mods (
|
||||
id, team_id, title, description, body_url,
|
||||
id, team_id, title, description, body,
|
||||
published, downloads, icon_url, issues_url,
|
||||
source_url, wiki_url, status, discord_url,
|
||||
client_side, server_side, license_url, license,
|
||||
@@ -156,7 +158,7 @@ impl Mod {
|
||||
self.team_id as TeamId,
|
||||
&self.title,
|
||||
&self.description,
|
||||
&self.body_url,
|
||||
&self.body,
|
||||
self.published,
|
||||
self.downloads,
|
||||
self.icon_url.as_ref(),
|
||||
@@ -184,7 +186,7 @@ impl Mod {
|
||||
let result = sqlx::query!(
|
||||
"
|
||||
SELECT title, description, downloads,
|
||||
icon_url, body_url, published,
|
||||
icon_url, body, body_url, published,
|
||||
updated, status,
|
||||
issues_url, source_url, wiki_url, discord_url, license_url,
|
||||
team_id, client_side, server_side, license, slug
|
||||
@@ -217,6 +219,7 @@ impl Mod {
|
||||
server_side: SideTypeId(row.server_side),
|
||||
license: LicenseId(row.license),
|
||||
slug: row.slug,
|
||||
body: row.body,
|
||||
}))
|
||||
} else {
|
||||
Ok(None)
|
||||
@@ -233,7 +236,7 @@ impl Mod {
|
||||
let mods = sqlx::query!(
|
||||
"
|
||||
SELECT id, title, description, downloads,
|
||||
icon_url, body_url, published,
|
||||
icon_url, body, body_url, published,
|
||||
updated, status,
|
||||
issues_url, source_url, wiki_url, discord_url, license_url,
|
||||
team_id, client_side, server_side, license, slug
|
||||
@@ -264,6 +267,7 @@ impl Mod {
|
||||
server_side: SideTypeId(m.server_side),
|
||||
license: LicenseId(m.license),
|
||||
slug: m.slug,
|
||||
body: m.body,
|
||||
}))
|
||||
})
|
||||
.try_collect::<Vec<Mod>>()
|
||||
|
||||
@@ -411,4 +411,75 @@ impl TeamMember {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn get_from_user_id_mod<'a, 'b, E>(
|
||||
id: ModId,
|
||||
user_id: UserId,
|
||||
executor: E,
|
||||
) -> Result<Option<Self>, super::DatabaseError>
|
||||
where
|
||||
E: sqlx::Executor<'a, Database = sqlx::Postgres>,
|
||||
{
|
||||
let result = sqlx::query!(
|
||||
"
|
||||
SELECT tm.id, tm.team_id, tm.user_id, tm.role, tm.permissions, tm.accepted FROM mods m
|
||||
INNER JOIN team_members tm ON tm.team_id = m.team_id AND user_id = $2 AND accepted = TRUE
|
||||
WHERE m.id = $1
|
||||
",
|
||||
id as ModId,
|
||||
user_id as UserId
|
||||
)
|
||||
.fetch_optional(executor)
|
||||
.await?;
|
||||
|
||||
if let Some(m) = result {
|
||||
Ok(Some(TeamMember {
|
||||
id: TeamMemberId(m.id),
|
||||
team_id: TeamId(m.team_id),
|
||||
user_id,
|
||||
role: m.role,
|
||||
permissions: Permissions::from_bits(m.permissions as u64)
|
||||
.ok_or(super::DatabaseError::BitflagError)?,
|
||||
accepted: m.accepted,
|
||||
}))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_from_user_id_version<'a, 'b, E>(
|
||||
id: VersionId,
|
||||
user_id: UserId,
|
||||
executor: E,
|
||||
) -> Result<Option<Self>, super::DatabaseError>
|
||||
where
|
||||
E: sqlx::Executor<'a, Database = sqlx::Postgres>,
|
||||
{
|
||||
let result = sqlx::query!(
|
||||
"
|
||||
SELECT tm.id, tm.team_id, tm.user_id, tm.role, tm.permissions, tm.accepted FROM versions v
|
||||
INNER JOIN mods m ON m.id = v.mod_id
|
||||
INNER JOIN team_members tm ON tm.team_id = m.team_id AND tm.user_id = $2 AND tm.accepted = TRUE
|
||||
WHERE v.id = $1
|
||||
",
|
||||
id as VersionId,
|
||||
user_id as UserId
|
||||
)
|
||||
.fetch_optional(executor)
|
||||
.await?;
|
||||
|
||||
if let Some(m) = result {
|
||||
Ok(Some(TeamMember {
|
||||
id: TeamMemberId(m.id),
|
||||
team_id: TeamId(m.team_id),
|
||||
user_id,
|
||||
role: m.role,
|
||||
permissions: Permissions::from_bits(m.permissions as u64)
|
||||
.ok_or(super::DatabaseError::BitflagError)?,
|
||||
accepted: m.accepted,
|
||||
}))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,4 +207,121 @@ impl User {
|
||||
|
||||
Ok(mods)
|
||||
}
|
||||
|
||||
pub async fn remove<'a, 'b, E>(id: UserId, exec: E) -> Result<Option<()>, sqlx::error::Error>
|
||||
where
|
||||
E: sqlx::Executor<'a, Database = sqlx::Postgres> + Copy,
|
||||
{
|
||||
let deleted_user: UserId = crate::models::users::DELETED_USER.into();
|
||||
|
||||
sqlx::query!(
|
||||
"
|
||||
UPDATE team_members
|
||||
SET user_id = $1
|
||||
WHERE (user_id = $2 AND role = $3)
|
||||
",
|
||||
deleted_user as UserId,
|
||||
id as UserId,
|
||||
crate::models::teams::OWNER_ROLE
|
||||
)
|
||||
.execute(exec)
|
||||
.await?;
|
||||
|
||||
sqlx::query!(
|
||||
"
|
||||
UPDATE versions
|
||||
SET author_id = $1
|
||||
WHERE (author_id = $2)
|
||||
",
|
||||
deleted_user as UserId,
|
||||
id as UserId,
|
||||
)
|
||||
.execute(exec)
|
||||
.await?;
|
||||
|
||||
sqlx::query!(
|
||||
"
|
||||
DELETE FROM team_members
|
||||
WHERE user_id = $1
|
||||
",
|
||||
id as UserId,
|
||||
)
|
||||
.execute(exec)
|
||||
.await?;
|
||||
|
||||
sqlx::query!(
|
||||
"
|
||||
DELETE FROM users
|
||||
WHERE id = $1
|
||||
",
|
||||
id as UserId,
|
||||
)
|
||||
.execute(exec)
|
||||
.await?;
|
||||
|
||||
Ok(Some(()))
|
||||
}
|
||||
|
||||
pub async fn remove_full<'a, 'b, E>(
|
||||
id: UserId,
|
||||
exec: E,
|
||||
) -> Result<Option<()>, sqlx::error::Error>
|
||||
where
|
||||
E: sqlx::Executor<'a, Database = sqlx::Postgres> + Copy,
|
||||
{
|
||||
use futures::TryStreamExt;
|
||||
let mods: Vec<ModId> = sqlx::query!(
|
||||
"
|
||||
SELECT m.id FROM mods m
|
||||
INNER JOIN team_members tm ON tm.team_id = m.team_id
|
||||
WHERE tm.user_id = $1 AND tm.role = $2
|
||||
",
|
||||
id as UserId,
|
||||
crate::models::teams::OWNER_ROLE
|
||||
)
|
||||
.fetch_many(exec)
|
||||
.try_filter_map(|e| async { Ok(e.right().map(|m| ModId(m.id))) })
|
||||
.try_collect::<Vec<ModId>>()
|
||||
.await?;
|
||||
|
||||
for mod_id in mods {
|
||||
let _result = super::mod_item::Mod::remove_full(mod_id, exec).await?;
|
||||
}
|
||||
|
||||
let deleted_user: UserId = crate::models::users::DELETED_USER.into();
|
||||
|
||||
sqlx::query!(
|
||||
"
|
||||
UPDATE versions
|
||||
SET author_id = $1
|
||||
WHERE (author_id = $2)
|
||||
",
|
||||
deleted_user as UserId,
|
||||
id as UserId,
|
||||
)
|
||||
.execute(exec)
|
||||
.await?;
|
||||
|
||||
sqlx::query!(
|
||||
"
|
||||
DELETE FROM team_members
|
||||
WHERE user_id = $1
|
||||
",
|
||||
id as UserId,
|
||||
)
|
||||
.execute(exec)
|
||||
.await?;
|
||||
|
||||
sqlx::query!(
|
||||
"
|
||||
DELETE FROM users
|
||||
WHERE id = $1
|
||||
",
|
||||
id as UserId,
|
||||
)
|
||||
.execute(exec)
|
||||
.await?;
|
||||
|
||||
Ok(Some(()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ pub struct VersionBuilder {
|
||||
pub author_id: UserId,
|
||||
pub name: String,
|
||||
pub version_number: String,
|
||||
pub changelog_url: Option<String>,
|
||||
pub changelog: String,
|
||||
pub files: Vec<VersionFileBuilder>,
|
||||
pub dependencies: Vec<VersionId>,
|
||||
pub game_versions: Vec<GameVersionId>,
|
||||
@@ -78,7 +78,8 @@ impl VersionBuilder {
|
||||
author_id: self.author_id,
|
||||
name: self.name,
|
||||
version_number: self.version_number,
|
||||
changelog_url: self.changelog_url,
|
||||
changelog: self.changelog,
|
||||
changelog_url: None,
|
||||
date_published: chrono::Utc::now(),
|
||||
downloads: 0,
|
||||
release_channel: self.release_channel,
|
||||
@@ -152,6 +153,7 @@ pub struct Version {
|
||||
pub author_id: UserId,
|
||||
pub name: String,
|
||||
pub version_number: String,
|
||||
pub changelog: String,
|
||||
pub changelog_url: Option<String>,
|
||||
pub date_published: chrono::DateTime<chrono::Utc>,
|
||||
pub downloads: i32,
|
||||
@@ -382,7 +384,7 @@ impl Version {
|
||||
let result = sqlx::query!(
|
||||
"
|
||||
SELECT v.mod_id, v.author_id, v.name, v.version_number,
|
||||
v.changelog_url, v.date_published, v.downloads,
|
||||
v.changelog, v.changelog_url, v.date_published, v.downloads,
|
||||
v.release_channel, v.accepted, v.featured
|
||||
FROM versions v
|
||||
WHERE v.id = $1
|
||||
@@ -399,6 +401,7 @@ impl Version {
|
||||
author_id: UserId(row.author_id),
|
||||
name: row.name,
|
||||
version_number: row.version_number,
|
||||
changelog: row.changelog,
|
||||
changelog_url: row.changelog_url,
|
||||
date_published: row.date_published,
|
||||
downloads: row.downloads,
|
||||
@@ -424,7 +427,7 @@ impl Version {
|
||||
let versions = sqlx::query!(
|
||||
"
|
||||
SELECT v.id, v.mod_id, v.author_id, v.name, v.version_number,
|
||||
v.changelog_url, v.date_published, v.downloads,
|
||||
v.changelog, v.changelog_url, v.date_published, v.downloads,
|
||||
v.release_channel, v.accepted, v.featured
|
||||
FROM versions v
|
||||
WHERE v.id IN (SELECT * FROM UNNEST($1::bigint[]))
|
||||
@@ -439,6 +442,7 @@ impl Version {
|
||||
author_id: UserId(v.author_id),
|
||||
name: v.name,
|
||||
version_number: v.version_number,
|
||||
changelog: v.changelog,
|
||||
changelog_url: v.changelog_url,
|
||||
date_published: v.date_published,
|
||||
downloads: v.downloads,
|
||||
@@ -463,7 +467,7 @@ impl Version {
|
||||
let result = sqlx::query!(
|
||||
"
|
||||
SELECT v.mod_id, v.author_id, v.name, v.version_number,
|
||||
v.changelog_url, v.date_published, v.downloads,
|
||||
v.changelog, v.changelog_url, v.date_published, v.downloads,
|
||||
release_channels.channel, v.accepted, v.featured
|
||||
FROM versions v
|
||||
INNER JOIN release_channels ON v.release_channel = release_channels.id
|
||||
@@ -545,6 +549,7 @@ impl Version {
|
||||
author_id: UserId(row.author_id),
|
||||
name: row.name,
|
||||
version_number: row.version_number,
|
||||
changelog: row.changelog,
|
||||
changelog_url: row.changelog_url,
|
||||
date_published: row.date_published,
|
||||
downloads: row.downloads,
|
||||
@@ -599,6 +604,7 @@ pub struct QueryVersion {
|
||||
pub author_id: UserId,
|
||||
pub name: String,
|
||||
pub version_number: String,
|
||||
pub changelog: String,
|
||||
pub changelog_url: Option<String>,
|
||||
pub date_published: chrono::DateTime<chrono::Utc>,
|
||||
pub downloads: i32,
|
||||
|
||||
Reference in New Issue
Block a user