Prevent interactions with reposts

This commit is contained in:
silverpill 2022-04-13 21:18:33 +00:00
parent 2fda205dbf
commit 78d66f8a06
4 changed files with 33 additions and 14 deletions

View file

@ -283,7 +283,8 @@ pub async fn object_view(
internal_object_id: web::Path<Uuid>, internal_object_id: web::Path<Uuid>,
) -> Result<HttpResponse, HttpError> { ) -> Result<HttpResponse, HttpError> {
let db_client = &**get_database_client(&db_pool).await?; let db_client = &**get_database_client(&db_pool).await?;
// Try to find local post by ID, return 404 if not found // Try to find local post by ID,
// return 404 if not found or if repost is found
let internal_object_id = internal_object_id.into_inner(); let internal_object_id = internal_object_id.into_inner();
let thread = get_thread(db_client, &internal_object_id, None).await?; let thread = get_thread(db_client, &internal_object_id, None).await?;
let mut post = thread.iter() let mut post = thread.iter()

View file

@ -95,6 +95,9 @@ async fn create_status(
}, },
Err(other_error) => return Err(other_error.into()), Err(other_error) => return Err(other_error.into()),
}; };
if in_reply_to.repost_of_id.is_some() {
return Err(ValidationError("can't reply to repost").into());
};
if in_reply_to.visibility != Visibility::Public && if in_reply_to.visibility != Visibility::Public &&
post_data.visibility != Visibility::Direct { post_data.visibility != Visibility::Direct {
return Err(ValidationError("reply must have direct visibility").into()); return Err(ValidationError("reply must have direct visibility").into());
@ -224,7 +227,7 @@ async fn favourite(
let db_client = &mut **get_database_client(&db_pool).await?; let db_client = &mut **get_database_client(&db_pool).await?;
let current_user = get_current_user(db_client, auth.token()).await?; let current_user = get_current_user(db_client, auth.token()).await?;
let mut post = get_post_by_id(db_client, &status_id).await?; let mut post = get_post_by_id(db_client, &status_id).await?;
if !post.is_public() { if !post.is_public() || post.repost_of_id.is_some() {
return Err(HttpError::NotFoundError("post")); return Err(HttpError::NotFoundError("post"));
}; };
let maybe_reaction_created = match create_reaction( let maybe_reaction_created = match create_reaction(
@ -309,7 +312,7 @@ async fn reblog(
let db_client = &mut **get_database_client(&db_pool).await?; let db_client = &mut **get_database_client(&db_pool).await?;
let current_user = get_current_user(db_client, auth.token()).await?; let current_user = get_current_user(db_client, auth.token()).await?;
let mut post = get_post_by_id(db_client, &status_id).await?; let mut post = get_post_by_id(db_client, &status_id).await?;
if !post.is_public() { if !post.is_public() || post.repost_of_id.is_some() {
return Err(HttpError::NotFoundError("post")); return Err(HttpError::NotFoundError("post"));
}; };
let repost_data = PostCreateData { let repost_data = PostCreateData {
@ -386,7 +389,7 @@ async fn make_permanent(
if post.ipfs_cid.is_some() { if post.ipfs_cid.is_some() {
return Err(HttpError::OperationError("post already saved to IPFS")); return Err(HttpError::OperationError("post already saved to IPFS"));
}; };
if post.author.id != current_user.id || !post.is_public() { if post.author.id != current_user.id || !post.is_public() || post.repost_of_id.is_some() {
// Users can only archive their own public posts // Users can only archive their own public posts
return Err(HttpError::PermissionError); return Err(HttpError::PermissionError);
}; };
@ -443,7 +446,7 @@ async fn get_signature(
let wallet_address = current_user.wallet_address let wallet_address = current_user.wallet_address
.ok_or(HttpError::PermissionError)?; .ok_or(HttpError::PermissionError)?;
let post = get_post_by_id(db_client, &status_id).await?; let post = get_post_by_id(db_client, &status_id).await?;
if post.author.id != current_user.id || !post.is_public() { if post.author.id != current_user.id || !post.is_public() || post.repost_of_id.is_some() {
// Users can only tokenize their own public posts // Users can only tokenize their own public posts
return Err(HttpError::PermissionError); return Err(HttpError::PermissionError);
}; };
@ -473,7 +476,7 @@ async fn token_minted(
if post.token_tx_id.is_some() { if post.token_tx_id.is_some() {
return Err(HttpError::OperationError("transaction is already registered")); return Err(HttpError::OperationError("transaction is already registered"));
}; };
if post.author.id != current_user.id || !post.is_public() { if post.author.id != current_user.id || !post.is_public() || post.repost_of_id.is_some() {
return Err(HttpError::PermissionError); return Err(HttpError::PermissionError);
}; };
post.token_tx_id = Some(transaction_data.into_inner().transaction_id); post.token_tx_id = Some(transaction_data.into_inner().transaction_id);

View file

@ -32,6 +32,7 @@ pub async fn create_post(
let transaction = db_client.transaction().await?; let transaction = db_client.transaction().await?;
let post_id = new_uuid(); let post_id = new_uuid();
let created_at = data.created_at.unwrap_or(Utc::now()); let created_at = data.created_at.unwrap_or(Utc::now());
// Replying to reposts is not allowed
// Reposting of other reposts or non-public posts is not allowed // Reposting of other reposts or non-public posts is not allowed
let insert_statement = format!( let insert_statement = format!(
" "
@ -44,7 +45,12 @@ pub async fn create_post(
created_at created_at
) )
SELECT $1, $2, $3, $4, $5, $6, $7, $8 SELECT $1, $2, $3, $4, $5, $6, $7, $8
WHERE NOT EXISTS ( WHERE
NOT EXISTS (
SELECT 1 FROM post
WHERE post.id = $4 AND post.repost_of_id IS NOT NULL
)
AND NOT EXISTS (
SELECT 1 FROM post SELECT 1 FROM post
WHERE post.id = $5 AND ( WHERE post.id = $5 AND (
post.repost_of_id IS NOT NULL post.repost_of_id IS NOT NULL
@ -505,7 +511,9 @@ pub async fn get_thread(
WITH RECURSIVE WITH RECURSIVE
ancestors (id, in_reply_to_id) AS ( ancestors (id, in_reply_to_id) AS (
SELECT post.id, post.in_reply_to_id FROM post SELECT post.id, post.in_reply_to_id FROM post
WHERE post.id = $post_id AND {visibility_filter} WHERE post.id = $post_id
AND post.repost_of_id IS NULL
AND {visibility_filter}
UNION ALL UNION ALL
SELECT post.id, post.in_reply_to_id FROM post SELECT post.id, post.in_reply_to_id FROM post
JOIN ancestors ON post.id = ancestors.in_reply_to_id JOIN ancestors ON post.id = ancestors.in_reply_to_id
@ -610,6 +618,7 @@ pub async fn update_post(
db_client: &impl GenericClient, db_client: &impl GenericClient,
post: &Post, post: &Post,
) -> Result<(), DatabaseError> { ) -> Result<(), DatabaseError> {
// Reposts can't be updated
let updated_count = db_client.execute( let updated_count = db_client.execute(
" "
UPDATE post UPDATE post
@ -618,7 +627,7 @@ pub async fn update_post(
ipfs_cid = $2, ipfs_cid = $2,
token_id = $3, token_id = $3,
token_tx_id = $4 token_tx_id = $4
WHERE id = $5 WHERE id = $5 AND repost_of_id IS NULL
", ",
&[ &[
&post.content, &post.content,
@ -643,7 +652,7 @@ pub async fn update_reply_count(
" "
UPDATE post UPDATE post
SET reply_count = reply_count + $1 SET reply_count = reply_count + $1
WHERE id = $2 WHERE id = $2 AND repost_of_id IS NULL
", ",
&[&change, &post_id], &[&change, &post_id],
).await?; ).await?;
@ -662,7 +671,7 @@ pub async fn update_reaction_count(
" "
UPDATE post UPDATE post
SET reaction_count = reaction_count + $1 SET reaction_count = reaction_count + $1
WHERE id = $2 WHERE id = $2 AND repost_of_id IS NULL
", ",
&[&change, &post_id], &[&change, &post_id],
).await?; ).await?;
@ -681,7 +690,7 @@ pub async fn update_repost_count(
" "
UPDATE post UPDATE post
SET repost_count = repost_count + $1 SET repost_count = repost_count + $1
WHERE id = $2 WHERE id = $2 AND repost_of_id IS NULL
", ",
&[&change, &post_id], &[&change, &post_id],
).await?; ).await?;

View file

@ -19,14 +19,20 @@ pub async fn create_reaction(
) -> Result<DbReaction, DatabaseError> { ) -> Result<DbReaction, DatabaseError> {
let transaction = db_client.transaction().await?; let transaction = db_client.transaction().await?;
let reaction_id = new_uuid(); let reaction_id = new_uuid();
let row = transaction.query_one( // Reactions to reposts are not allowed
let maybe_row = transaction.query_opt(
" "
INSERT INTO post_reaction (id, author_id, post_id, activity_id) INSERT INTO post_reaction (id, author_id, post_id, activity_id)
VALUES ($1, $2, $3, $4) SELECT $1, $2, $3, $4
WHERE NOT EXISTS (
SELECT 1 FROM post
WHERE post.id = $3 AND post.repost_of_id IS NOT NULL
)
RETURNING post_reaction RETURNING post_reaction
", ",
&[&reaction_id, &author_id, &post_id, &activity_id], &[&reaction_id, &author_id, &post_id, &activity_id],
).await.map_err(catch_unique_violation("reaction"))?; ).await.map_err(catch_unique_violation("reaction"))?;
let row = maybe_row.ok_or(DatabaseError::NotFound("post"))?;
let reaction: DbReaction = row.try_get("post_reaction")?; let reaction: DbReaction = row.try_get("post_reaction")?;
update_reaction_count(&transaction, post_id, 1).await?; update_reaction_count(&transaction, post_id, 1).await?;
let post_author = get_post_author(&transaction, post_id).await?; let post_author = get_post_author(&transaction, post_id).await?;