Hide private posts from threads

This commit is contained in:
silverpill 2021-11-19 23:17:04 +00:00
parent 294e2f201b
commit c578d8536f
3 changed files with 30 additions and 4 deletions

View file

@ -170,7 +170,7 @@ pub async fn object_view(
) -> 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
let thread = get_thread(db_client, &object_id).await?; let thread = get_thread(db_client, &object_id, None).await?;
let post = thread.iter() let post = thread.iter()
.find(|post| post.id == object_id && post.author.is_local()) .find(|post| post.id == object_id && post.author.is_local())
.ok_or(HttpError::NotFoundError("post"))?; .ok_or(HttpError::NotFoundError("post"))?;

View file

@ -139,7 +139,11 @@ async fn get_context(
Some(auth) => Some(get_current_user(db_client, auth.token()).await?), Some(auth) => Some(get_current_user(db_client, auth.token()).await?),
None => None, None => None,
}; };
let mut posts = get_thread(db_client, &status_id).await?; let mut posts = get_thread(
db_client,
&status_id,
maybe_current_user.as_ref().map(|user| &user.id),
).await?;
if let Some(user) = maybe_current_user { if let Some(user) = maybe_current_user {
get_actions_for_posts( get_actions_for_posts(
db_client, db_client,

View file

@ -1,6 +1,7 @@
use std::convert::TryFrom; use std::convert::TryFrom;
use chrono::Utc; use chrono::Utc;
use postgres_types::ToSql;
use tokio_postgres::GenericClient; use tokio_postgres::GenericClient;
use uuid::Uuid; use uuid::Uuid;
@ -237,14 +238,33 @@ pub async fn get_post_by_id(
pub async fn get_thread( pub async fn get_thread(
db_client: &impl GenericClient, db_client: &impl GenericClient,
post_id: &Uuid, post_id: &Uuid,
current_user_id: Option<&Uuid>,
) -> Result<Vec<Post>, DatabaseError> { ) -> Result<Vec<Post>, DatabaseError> {
let mut condition = format!(
"post.visibility = {visibility_public}",
visibility_public=i16::from(&Visibility::Public),
);
// Create mutable params array
// https://github.com/sfackler/rust-postgres/issues/712
let mut parameters: Vec<&(dyn ToSql + Sync)> = vec![post_id];
if let Some(current_user_id) = current_user_id {
condition.push_str(
"
OR EXISTS (
SELECT 1 FROM mention
WHERE post_id = post.id AND profile_id = $2
)
",
);
parameters.push(current_user_id);
};
// TODO: limit recursion depth // TODO: limit recursion depth
let statement = format!( let statement = format!(
" "
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 = $1 WHERE post.id = $1 AND {condition}
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
@ -263,14 +283,16 @@ pub async fn get_thread(
FROM post FROM post
JOIN context ON post.id = context.id JOIN context ON post.id = context.id
JOIN actor_profile ON post.author_id = actor_profile.id JOIN actor_profile ON post.author_id = actor_profile.id
WHERE {condition}
ORDER BY context.path ORDER BY context.path
", ",
related_attachments=RELATED_ATTACHMENTS, related_attachments=RELATED_ATTACHMENTS,
related_mentions=RELATED_MENTIONS, related_mentions=RELATED_MENTIONS,
condition=condition,
); );
let rows = db_client.query( let rows = db_client.query(
statement.as_str(), statement.as_str(),
&[&post_id], &parameters,
).await?; ).await?;
let posts: Vec<Post> = rows.iter() let posts: Vec<Post> = rows.iter()
.map(Post::try_from) .map(Post::try_from)