Adding creator_is_admin to PersonView, CommentView, and PostView. (#4165)

* Adding creator_is_admin to PersonView, CommentView, and PostView.

* Removing left joins from comment_view.

* Removing joins from person_mention and comment_reply views.

* Removing extra left join from person_view.

* Reverting some changes in post_view.

* Fixing compile error.
This commit is contained in:
Dessalines 2023-11-21 11:20:24 -05:00 committed by GitHub
parent 28d779a960
commit 3e1f7f2efa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 576 additions and 347 deletions

View file

@ -1,9 +1,13 @@
use crate::structs::{CommentView, LocalUserView}; use crate::structs::{CommentView, LocalUserView};
use diesel::{ use diesel::{
dsl::{exists, not},
pg::Pg, pg::Pg,
result::Error, result::Error,
sql_types,
BoolExpressionMethods, BoolExpressionMethods,
BoxableExpression,
ExpressionMethods, ExpressionMethods,
IntoSql,
JoinOnDsl, JoinOnDsl,
NullableExpressionMethods, NullableExpressionMethods,
PgTextExpressionMethods, PgTextExpressionMethods,
@ -12,7 +16,6 @@ use diesel::{
use diesel_async::RunQueryDsl; use diesel_async::RunQueryDsl;
use diesel_ltree::{nlevel, subpath, Ltree, LtreeExtensions}; use diesel_ltree::{nlevel, subpath, Ltree, LtreeExtensions};
use lemmy_db_schema::{ use lemmy_db_schema::{
aliases,
newtypes::{CommentId, CommunityId, LocalUserId, PersonId, PostId}, newtypes::{CommentId, CommunityId, LocalUserId, PersonId, PostId},
schema::{ schema::{
comment, comment,
@ -25,12 +28,12 @@ use lemmy_db_schema::{
community_moderator, community_moderator,
community_person_ban, community_person_ban,
instance_block, instance_block,
local_user,
local_user_language, local_user_language,
person, person,
person_block, person_block,
post, post,
}, },
source::community::CommunityFollower,
utils::{fuzzy_search, limit_and_offset, DbConn, DbPool, ListFn, Queries, ReadFn}, utils::{fuzzy_search, limit_and_offset, DbConn, DbPool, ListFn, Queries, ReadFn},
CommentSortType, CommentSortType,
ListingType, ListingType,
@ -40,91 +43,135 @@ fn queries<'a>() -> Queries<
impl ReadFn<'a, CommentView, (CommentId, Option<PersonId>)>, impl ReadFn<'a, CommentView, (CommentId, Option<PersonId>)>,
impl ListFn<'a, CommentView, CommentQuery<'a>>, impl ListFn<'a, CommentView, CommentQuery<'a>>,
> { > {
let all_joins = |query: comment::BoxedQuery<'a, Pg>, my_person_id: Option<PersonId>| { let is_creator_banned_from_community = exists(
// The left join below will return None in this case community_person_ban::table.filter(
let person_id_join = my_person_id.unwrap_or(PersonId(-1)); community::id
.eq(community_person_ban::community_id)
.and(community_person_ban::person_id.eq(comment::creator_id)),
),
);
let is_saved = |person_id| {
exists(
comment_saved::table.filter(
comment::id
.eq(comment_saved::comment_id)
.and(comment_saved::person_id.eq(person_id)),
),
)
};
let is_community_followed = |person_id| {
community_follower::table
.filter(
post::community_id
.eq(community_follower::community_id)
.and(community_follower::person_id.eq(person_id)),
)
.select(community_follower::pending.nullable())
.single_value()
};
let is_creator_blocked = |person_id| {
exists(
person_block::table.filter(
comment::creator_id
.eq(person_block::target_id)
.and(person_block::person_id.eq(person_id)),
),
)
};
let score = |person_id| {
comment_like::table
.filter(
comment::id
.eq(comment_like::comment_id)
.and(comment_like::person_id.eq(person_id)),
)
.select(comment_like::score.nullable())
.single_value()
};
let creator_is_moderator = exists(
community_moderator::table.filter(
community::id
.eq(community_moderator::community_id)
.and(community_moderator::person_id.eq(comment::creator_id)),
),
);
let creator_is_admin = exists(
local_user::table.filter(
comment::creator_id
.eq(local_user::person_id)
.and(local_user::admin.eq(true)),
),
);
let all_joins = move |query: comment::BoxedQuery<'a, Pg>,
my_person_id: Option<PersonId>,
saved_only: bool| {
let score_selection: Box<
dyn BoxableExpression<_, Pg, SqlType = sql_types::Nullable<sql_types::SmallInt>>,
> = if let Some(person_id) = my_person_id {
Box::new(score(person_id))
} else {
Box::new(None::<i16>.into_sql::<sql_types::Nullable<sql_types::SmallInt>>())
};
let subscribed_type_selection: Box<
dyn BoxableExpression<_, Pg, SqlType = sql_types::Nullable<sql_types::Bool>>,
> = if let Some(person_id) = my_person_id {
Box::new(is_community_followed(person_id))
} else {
Box::new(None::<bool>.into_sql::<sql_types::Nullable<sql_types::Bool>>())
};
let is_saved_selection: Box<dyn BoxableExpression<_, Pg, SqlType = sql_types::Bool>> =
if saved_only {
Box::new(true.into_sql::<sql_types::Bool>())
} else if let Some(person_id) = my_person_id {
Box::new(is_saved(person_id))
} else {
Box::new(false.into_sql::<sql_types::Bool>())
};
let is_creator_blocked_selection: Box<dyn BoxableExpression<_, Pg, SqlType = sql_types::Bool>> =
if let Some(person_id) = my_person_id {
Box::new(is_creator_blocked(person_id))
} else {
Box::new(false.into_sql::<sql_types::Bool>())
};
query query
.inner_join(person::table) .inner_join(person::table)
.inner_join(post::table) .inner_join(post::table)
.inner_join(community::table.on(post::community_id.eq(community::id))) .inner_join(community::table.on(post::community_id.eq(community::id)))
.inner_join(comment_aggregates::table) .inner_join(comment_aggregates::table)
.left_join( .select((
community_person_ban::table.on(
community::id
.eq(community_person_ban::community_id)
.and(community_person_ban::person_id.eq(comment::creator_id)),
),
)
.left_join(
community_follower::table.on(
post::community_id
.eq(community_follower::community_id)
.and(community_follower::person_id.eq(person_id_join)),
),
)
.left_join(
comment_saved::table.on(
comment::id
.eq(comment_saved::comment_id)
.and(comment_saved::person_id.eq(person_id_join)),
),
)
.left_join(
person_block::table.on(
comment::creator_id
.eq(person_block::target_id)
.and(person_block::person_id.eq(person_id_join)),
),
)
.left_join(
comment_like::table.on(
comment::id
.eq(comment_like::comment_id)
.and(comment_like::person_id.eq(person_id_join)),
),
)
.left_join(
community_moderator::table.on(
post::id
.eq(comment::post_id)
.and(post::community_id.eq(community_moderator::community_id))
.and(community_moderator::person_id.eq(person_id_join)),
),
)
.left_join(
aliases::community_moderator1.on(
community::id
.eq(aliases::community_moderator1.field(community_moderator::community_id))
.and(
aliases::community_moderator1
.field(community_moderator::person_id)
.eq(comment::creator_id),
),
),
)
};
let selection = (
comment::all_columns, comment::all_columns,
person::all_columns, person::all_columns,
post::all_columns, post::all_columns,
community::all_columns, community::all_columns,
comment_aggregates::all_columns, comment_aggregates::all_columns,
community_person_ban::community_id.nullable().is_not_null(), is_creator_banned_from_community,
aliases::community_moderator1 creator_is_moderator,
.field(community_moderator::community_id) creator_is_admin,
.nullable() subscribed_type_selection,
.is_not_null(), is_saved_selection,
CommunityFollower::select_subscribed_type(), is_creator_blocked_selection,
comment_saved::comment_id.nullable().is_not_null(), score_selection,
person_block::person_id.nullable().is_not_null(), ))
comment_like::score.nullable(), };
);
let read = move |mut conn: DbConn<'a>, let read = move |mut conn: DbConn<'a>,
(comment_id, my_person_id): (CommentId, Option<PersonId>)| async move { (comment_id, my_person_id): (CommentId, Option<PersonId>)| async move {
all_joins(comment::table.find(comment_id).into_boxed(), my_person_id) all_joins(
.select(selection) comment::table.find(comment_id).into_boxed(),
my_person_id,
false,
)
.first::<CommentView>(&mut conn) .first::<CommentView>(&mut conn)
.await .await
}; };
@ -137,29 +184,7 @@ fn queries<'a>() -> Queries<
let person_id_join = person_id.unwrap_or(PersonId(-1)); let person_id_join = person_id.unwrap_or(PersonId(-1));
let local_user_id_join = local_user_id.unwrap_or(LocalUserId(-1)); let local_user_id_join = local_user_id.unwrap_or(LocalUserId(-1));
let mut query = all_joins(comment::table.into_boxed(), person_id) let mut query = all_joins(comment::table.into_boxed(), person_id, options.saved_only);
.left_join(
instance_block::table.on(
community::instance_id
.eq(instance_block::instance_id)
.and(instance_block::person_id.eq(person_id_join)),
),
)
.left_join(
community_block::table.on(
community::id
.eq(community_block::community_id)
.and(community_block::person_id.eq(person_id_join)),
),
)
.left_join(
local_user_language::table.on(
comment::language_id
.eq(local_user_language::language_id)
.and(local_user_language::local_user_id.eq(local_user_id_join)),
),
)
.select(selection);
if let Some(creator_id) = options.creator_id { if let Some(creator_id) = options.creator_id {
query = query.filter(comment::creator_id.eq(creator_id)); query = query.filter(comment::creator_id.eq(creator_id));
@ -182,36 +207,42 @@ fn queries<'a>() -> Queries<
} }
if let Some(listing_type) = options.listing_type { if let Some(listing_type) = options.listing_type {
let is_subscribed = exists(
community_follower::table.filter(
post::community_id
.eq(community_follower::community_id)
.and(community_follower::person_id.eq(person_id_join)),
),
);
match listing_type { match listing_type {
ListingType::Subscribed => query = query.filter(community_follower::pending.is_not_null()), // TODO could be this: and(community_follower::person_id.eq(person_id_join)), ListingType::Subscribed => query = query.filter(is_subscribed), // TODO could be this: and(community_follower::person_id.eq(person_id_join)),
ListingType::Local => { ListingType::Local => {
query = query.filter(community::local.eq(true)).filter( query = query
community::hidden .filter(community::local.eq(true))
.eq(false) .filter(community::hidden.eq(false).or(is_subscribed))
.or(community_follower::person_id.eq(person_id_join)),
)
}
ListingType::All => {
query = query.filter(
community::hidden
.eq(false)
.or(community_follower::person_id.eq(person_id_join)),
)
} }
ListingType::All => query = query.filter(community::hidden.eq(false).or(is_subscribed)),
ListingType::ModeratorView => { ListingType::ModeratorView => {
query = query.filter(community_moderator::person_id.is_not_null()); query = query.filter(exists(
community_moderator::table.filter(
post::community_id
.eq(community_moderator::community_id)
.and(community_moderator::person_id.eq(person_id_join)),
),
));
} }
} }
} }
if options.saved_only { if options.saved_only {
query = query.filter(comment_saved::comment_id.is_not_null()); query = query.filter(is_saved(person_id_join));
} }
if options.liked_only { if options.liked_only {
query = query.filter(comment_like::score.eq(1)); query = query.filter(score(person_id_join).eq(1));
} else if options.disliked_only { } else if options.disliked_only {
query = query.filter(comment_like::score.eq(-1)); query = query.filter(score(person_id_join).eq(-1));
} }
if !options if !options
@ -226,15 +257,31 @@ fn queries<'a>() -> Queries<
&& options.listing_type.unwrap_or_default() != ListingType::ModeratorView && options.listing_type.unwrap_or_default() != ListingType::ModeratorView
{ {
// Filter out the rows with missing languages // Filter out the rows with missing languages
query = query.filter(local_user_language::language_id.is_not_null()); query = query.filter(exists(
local_user_language::table.filter(
comment::language_id
.eq(local_user_language::language_id)
.and(local_user_language::local_user_id.eq(local_user_id_join)),
),
));
// Don't show blocked communities or persons // Don't show blocked communities or persons
if options.post_id.is_none() { query = query.filter(not(exists(
query = query.filter(instance_block::person_id.is_null()); instance_block::table.filter(
query = query.filter(community_block::person_id.is_null()); community::instance_id
} .eq(instance_block::instance_id)
query = query.filter(person_block::person_id.is_null()); .and(instance_block::person_id.eq(person_id_join)),
} ),
)));
query = query.filter(not(exists(
community_block::table.filter(
community::id
.eq(community_block::community_id)
.and(community_block::person_id.eq(person_id_join)),
),
)));
query = query.filter(not(is_creator_blocked(person_id_join)));
};
// A Max depth given means its a tree fetch // A Max depth given means its a tree fetch
let (limit, offset) = if let Some(max_depth) = options.max_depth { let (limit, offset) = if let Some(max_depth) = options.max_depth {
@ -374,8 +421,8 @@ mod tests {
inserted_comment_1: Comment, inserted_comment_1: Comment,
inserted_comment_2: Comment, inserted_comment_2: Comment,
inserted_post: Post, inserted_post: Post,
local_user_view: LocalUserView, timmy_local_user_view: LocalUserView,
inserted_person_2: Person, inserted_sara_person: Person,
inserted_community: Community, inserted_community: Community,
} }
@ -384,24 +431,27 @@ mod tests {
.await .await
.unwrap(); .unwrap();
let new_person = PersonInsertForm::builder() let timmy_person_form = PersonInsertForm::builder()
.name("timmy".into()) .name("timmy".into())
.public_key("pubkey".to_string()) .public_key("pubkey".to_string())
.instance_id(inserted_instance.id) .instance_id(inserted_instance.id)
.build(); .build();
let inserted_person = Person::create(pool, &new_person).await.unwrap(); let inserted_timmy_person = Person::create(pool, &timmy_person_form).await.unwrap();
let local_user_form = LocalUserInsertForm::builder() let timmy_local_user_form = LocalUserInsertForm::builder()
.person_id(inserted_person.id) .person_id(inserted_timmy_person.id)
.admin(Some(true))
.password_encrypted(String::new()) .password_encrypted(String::new())
.build(); .build();
let inserted_local_user = LocalUser::create(pool, &local_user_form).await.unwrap(); let inserted_timmy_local_user = LocalUser::create(pool, &timmy_local_user_form)
.await
.unwrap();
let new_person_2 = PersonInsertForm::builder() let sara_person_form = PersonInsertForm::builder()
.name("sara".into()) .name("sara".into())
.public_key("pubkey".to_string()) .public_key("pubkey".to_string())
.instance_id(inserted_instance.id) .instance_id(inserted_instance.id)
.build(); .build();
let inserted_person_2 = Person::create(pool, &new_person_2).await.unwrap(); let inserted_sara_person = Person::create(pool, &sara_person_form).await.unwrap();
let new_community = CommunityInsertForm::builder() let new_community = CommunityInsertForm::builder()
.name("test community 5".to_string()) .name("test community 5".to_string())
@ -414,7 +464,7 @@ mod tests {
let new_post = PostInsertForm::builder() let new_post = PostInsertForm::builder()
.name("A test post 2".into()) .name("A test post 2".into())
.creator_id(inserted_person.id) .creator_id(inserted_timmy_person.id)
.community_id(inserted_community.id) .community_id(inserted_community.id)
.build(); .build();
@ -431,7 +481,7 @@ mod tests {
// 5 // 5
let comment_form_0 = CommentInsertForm::builder() let comment_form_0 = CommentInsertForm::builder()
.content("Comment 0".into()) .content("Comment 0".into())
.creator_id(inserted_person.id) .creator_id(inserted_timmy_person.id)
.post_id(inserted_post.id) .post_id(inserted_post.id)
.language_id(english_id) .language_id(english_id)
.build(); .build();
@ -440,7 +490,7 @@ mod tests {
let comment_form_1 = CommentInsertForm::builder() let comment_form_1 = CommentInsertForm::builder()
.content("Comment 1, A test blocked comment".into()) .content("Comment 1, A test blocked comment".into())
.creator_id(inserted_person_2.id) .creator_id(inserted_sara_person.id)
.post_id(inserted_post.id) .post_id(inserted_post.id)
.language_id(english_id) .language_id(english_id)
.build(); .build();
@ -452,7 +502,7 @@ mod tests {
let finnish_id = Language::read_id_from_code(pool, Some("fi")).await.unwrap(); let finnish_id = Language::read_id_from_code(pool, Some("fi")).await.unwrap();
let comment_form_2 = CommentInsertForm::builder() let comment_form_2 = CommentInsertForm::builder()
.content("Comment 2".into()) .content("Comment 2".into())
.creator_id(inserted_person.id) .creator_id(inserted_timmy_person.id)
.post_id(inserted_post.id) .post_id(inserted_post.id)
.language_id(finnish_id) .language_id(finnish_id)
.build(); .build();
@ -463,7 +513,7 @@ mod tests {
let comment_form_3 = CommentInsertForm::builder() let comment_form_3 = CommentInsertForm::builder()
.content("Comment 3".into()) .content("Comment 3".into())
.creator_id(inserted_person.id) .creator_id(inserted_timmy_person.id)
.post_id(inserted_post.id) .post_id(inserted_post.id)
.language_id(english_id) .language_id(english_id)
.build(); .build();
@ -479,7 +529,7 @@ mod tests {
.unwrap(); .unwrap();
let comment_form_4 = CommentInsertForm::builder() let comment_form_4 = CommentInsertForm::builder()
.content("Comment 4".into()) .content("Comment 4".into())
.creator_id(inserted_person.id) .creator_id(inserted_timmy_person.id)
.post_id(inserted_post.id) .post_id(inserted_post.id)
.language_id(Some(polish_id)) .language_id(Some(polish_id))
.build(); .build();
@ -490,7 +540,7 @@ mod tests {
let comment_form_5 = CommentInsertForm::builder() let comment_form_5 = CommentInsertForm::builder()
.content("Comment 5".into()) .content("Comment 5".into())
.creator_id(inserted_person.id) .creator_id(inserted_timmy_person.id)
.post_id(inserted_post.id) .post_id(inserted_post.id)
.build(); .build();
@ -500,8 +550,8 @@ mod tests {
.unwrap(); .unwrap();
let timmy_blocks_sara_form = PersonBlockForm { let timmy_blocks_sara_form = PersonBlockForm {
person_id: inserted_person.id, person_id: inserted_timmy_person.id,
target_id: inserted_person_2.id, target_id: inserted_sara_person.id,
}; };
let inserted_block = PersonBlock::block(pool, &timmy_blocks_sara_form) let inserted_block = PersonBlock::block(pool, &timmy_blocks_sara_form)
@ -509,8 +559,8 @@ mod tests {
.unwrap(); .unwrap();
let expected_block = PersonBlock { let expected_block = PersonBlock {
person_id: inserted_person.id, person_id: inserted_timmy_person.id,
target_id: inserted_person_2.id, target_id: inserted_sara_person.id,
published: inserted_block.published, published: inserted_block.published,
}; };
assert_eq!(expected_block, inserted_block); assert_eq!(expected_block, inserted_block);
@ -518,15 +568,15 @@ mod tests {
let comment_like_form = CommentLikeForm { let comment_like_form = CommentLikeForm {
comment_id: inserted_comment_0.id, comment_id: inserted_comment_0.id,
post_id: inserted_post.id, post_id: inserted_post.id,
person_id: inserted_person.id, person_id: inserted_timmy_person.id,
score: 1, score: 1,
}; };
let _inserted_comment_like = CommentLike::like(pool, &comment_like_form).await.unwrap(); let _inserted_comment_like = CommentLike::like(pool, &comment_like_form).await.unwrap();
let local_user_view = LocalUserView { let timmy_local_user_view = LocalUserView {
local_user: inserted_local_user.clone(), local_user: inserted_timmy_local_user.clone(),
person: inserted_person.clone(), person: inserted_timmy_person.clone(),
counts: Default::default(), counts: Default::default(),
}; };
Data { Data {
@ -535,8 +585,8 @@ mod tests {
inserted_comment_1, inserted_comment_1,
inserted_comment_2, inserted_comment_2,
inserted_post, inserted_post,
local_user_view, timmy_local_user_view,
inserted_person_2, inserted_sara_person,
inserted_community, inserted_community,
} }
} }
@ -570,7 +620,7 @@ mod tests {
let read_comment_views_with_person = CommentQuery { let read_comment_views_with_person = CommentQuery {
sort: (Some(CommentSortType::Old)), sort: (Some(CommentSortType::Old)),
post_id: (Some(data.inserted_post.id)), post_id: (Some(data.inserted_post.id)),
local_user: (Some(&data.local_user_view)), local_user: (Some(&data.timmy_local_user_view)),
..Default::default() ..Default::default()
} }
.list(pool) .list(pool)
@ -588,7 +638,7 @@ mod tests {
let read_comment_from_blocked_person = CommentView::read( let read_comment_from_blocked_person = CommentView::read(
pool, pool,
data.inserted_comment_1.id, data.inserted_comment_1.id,
Some(data.local_user_view.person.id), Some(data.timmy_local_user_view.person.id),
) )
.await .await
.unwrap(); .unwrap();
@ -597,7 +647,7 @@ mod tests {
assert!(read_comment_from_blocked_person.creator_blocked); assert!(read_comment_from_blocked_person.creator_blocked);
let read_liked_comment_views = CommentQuery { let read_liked_comment_views = CommentQuery {
local_user: (Some(&data.local_user_view)), local_user: (Some(&data.timmy_local_user_view)),
liked_only: (true), liked_only: (true),
..Default::default() ..Default::default()
} }
@ -613,7 +663,7 @@ mod tests {
assert_eq!(1, read_liked_comment_views.len()); assert_eq!(1, read_liked_comment_views.len());
let read_disliked_comment_views: Vec<CommentView> = CommentQuery { let read_disliked_comment_views: Vec<CommentView> = CommentQuery {
local_user: (Some(&data.local_user_view)), local_user: (Some(&data.timmy_local_user_view)),
disliked_only: (true), disliked_only: (true),
..Default::default() ..Default::default()
} }
@ -713,7 +763,7 @@ mod tests {
// by default, user has all languages enabled and should see all comments // by default, user has all languages enabled and should see all comments
// (except from blocked user) // (except from blocked user)
let all_languages = CommentQuery { let all_languages = CommentQuery {
local_user: (Some(&data.local_user_view)), local_user: (Some(&data.timmy_local_user_view)),
..Default::default() ..Default::default()
} }
.list(pool) .list(pool)
@ -726,11 +776,15 @@ mod tests {
.await .await
.unwrap() .unwrap()
.unwrap(); .unwrap();
LocalUserLanguage::update(pool, vec![finnish_id], data.local_user_view.local_user.id) LocalUserLanguage::update(
pool,
vec![finnish_id],
data.timmy_local_user_view.local_user.id,
)
.await .await
.unwrap(); .unwrap();
let finnish_comments = CommentQuery { let finnish_comments = CommentQuery {
local_user: (Some(&data.local_user_view)), local_user: (Some(&data.timmy_local_user_view)),
..Default::default() ..Default::default()
} }
.list(pool) .list(pool)
@ -750,12 +804,12 @@ mod tests {
LocalUserLanguage::update( LocalUserLanguage::update(
pool, pool,
vec![UNDETERMINED_ID], vec![UNDETERMINED_ID],
data.local_user_view.local_user.id, data.timmy_local_user_view.local_user.id,
) )
.await .await
.unwrap(); .unwrap();
let undetermined_comment = CommentQuery { let undetermined_comment = CommentQuery {
local_user: (Some(&data.local_user_view)), local_user: (Some(&data.timmy_local_user_view)),
..Default::default() ..Default::default()
} }
.list(pool) .list(pool)
@ -802,7 +856,7 @@ mod tests {
let data = init_data(pool).await; let data = init_data(pool).await;
// Make one of the inserted persons a moderator // Make one of the inserted persons a moderator
let person_id = data.inserted_person_2.id; let person_id = data.inserted_sara_person.id;
let community_id = data.inserted_community.id; let community_id = data.inserted_community.id;
let form = CommunityModeratorForm { let form = CommunityModeratorForm {
community_id, community_id,
@ -812,16 +866,42 @@ mod tests {
// Make sure that they come back as a mod in the list // Make sure that they come back as a mod in the list
let comments = CommentQuery { let comments = CommentQuery {
sort: Some(CommentSortType::New), sort: (Some(CommentSortType::Old)),
..Default::default() ..Default::default()
} }
.list(pool) .list(pool)
.await .await
.unwrap(); .unwrap();
assert_eq!(comments[1].creator.name, "sara");
assert!(comments[1].creator_is_moderator);
assert!(!comments[0].creator_is_moderator); assert!(!comments[0].creator_is_moderator);
assert!(!comments[1].creator_is_moderator);
assert!(comments[4].creator_is_moderator); cleanup(data, pool).await;
}
#[tokio::test]
#[serial]
async fn test_creator_is_admin() {
let pool = &build_db_pool_for_tests().await;
let pool = &mut pool.into();
let data = init_data(pool).await;
let comments = CommentQuery {
sort: (Some(CommentSortType::Old)),
..Default::default()
}
.list(pool)
.await
.unwrap();
// Timmy is an admin, and make sure that field is true
assert_eq!(comments[0].creator.name, "timmy");
assert!(comments[0].creator_is_admin);
// Sara isn't, make sure its false
assert_eq!(comments[1].creator.name, "sara");
assert!(!comments[1].creator_is_admin);
cleanup(data, pool).await; cleanup(data, pool).await;
} }
@ -829,7 +909,7 @@ mod tests {
async fn cleanup(data: Data, pool: &mut DbPool<'_>) { async fn cleanup(data: Data, pool: &mut DbPool<'_>) {
CommentLike::remove( CommentLike::remove(
pool, pool,
data.local_user_view.person.id, data.timmy_local_user_view.person.id,
data.inserted_comment_0.id, data.inserted_comment_0.id,
) )
.await .await
@ -844,10 +924,13 @@ mod tests {
Community::delete(pool, data.inserted_community.id) Community::delete(pool, data.inserted_community.id)
.await .await
.unwrap(); .unwrap();
Person::delete(pool, data.local_user_view.person.id) Person::delete(pool, data.timmy_local_user_view.person.id)
.await .await
.unwrap(); .unwrap();
Person::delete(pool, data.inserted_person_2.id) LocalUser::delete(pool, data.timmy_local_user_view.local_user.id)
.await
.unwrap();
Person::delete(pool, data.inserted_sara_person.id)
.await .await
.unwrap(); .unwrap();
Instance::delete(pool, data.inserted_instance.id) Instance::delete(pool, data.inserted_instance.id)
@ -862,6 +945,7 @@ mod tests {
CommentView { CommentView {
creator_banned_from_community: false, creator_banned_from_community: false,
creator_is_moderator: false, creator_is_moderator: false,
creator_is_admin: true,
my_vote: None, my_vote: None,
subscribed: SubscribedType::NotSubscribed, subscribed: SubscribedType::NotSubscribed,
saved: false, saved: false,
@ -869,7 +953,7 @@ mod tests {
comment: Comment { comment: Comment {
id: data.inserted_comment_0.id, id: data.inserted_comment_0.id,
content: "Comment 0".into(), content: "Comment 0".into(),
creator_id: data.local_user_view.person.id, creator_id: data.timmy_local_user_view.person.id,
post_id: data.inserted_post.id, post_id: data.inserted_post.id,
removed: false, removed: false,
deleted: false, deleted: false,
@ -882,12 +966,12 @@ mod tests {
language_id: LanguageId(37), language_id: LanguageId(37),
}, },
creator: Person { creator: Person {
id: data.local_user_view.person.id, id: data.timmy_local_user_view.person.id,
name: "timmy".into(), name: "timmy".into(),
display_name: None, display_name: None,
published: data.local_user_view.person.published, published: data.timmy_local_user_view.person.published,
avatar: None, avatar: None,
actor_id: data.local_user_view.person.actor_id.clone(), actor_id: data.timmy_local_user_view.person.actor_id.clone(),
local: true, local: true,
banned: false, banned: false,
deleted: false, deleted: false,
@ -895,19 +979,19 @@ mod tests {
bio: None, bio: None,
banner: None, banner: None,
updated: None, updated: None,
inbox_url: data.local_user_view.person.inbox_url.clone(), inbox_url: data.timmy_local_user_view.person.inbox_url.clone(),
shared_inbox_url: None, shared_inbox_url: None,
matrix_user_id: None, matrix_user_id: None,
ban_expires: None, ban_expires: None,
instance_id: data.inserted_instance.id, instance_id: data.inserted_instance.id,
private_key: data.local_user_view.person.private_key.clone(), private_key: data.timmy_local_user_view.person.private_key.clone(),
public_key: data.local_user_view.person.public_key.clone(), public_key: data.timmy_local_user_view.person.public_key.clone(),
last_refreshed_at: data.local_user_view.person.last_refreshed_at, last_refreshed_at: data.timmy_local_user_view.person.last_refreshed_at,
}, },
post: Post { post: Post {
id: data.inserted_post.id, id: data.inserted_post.id,
name: data.inserted_post.name.clone(), name: data.inserted_post.name.clone(),
creator_id: data.local_user_view.person.id, creator_id: data.timmy_local_user_view.person.id,
url: None, url: None,
body: None, body: None,
published: data.inserted_post.published, published: data.inserted_post.published,

View file

@ -29,6 +29,7 @@ use lemmy_db_schema::{
community_moderator, community_moderator,
community_person_ban, community_person_ban,
instance_block, instance_block,
local_user,
local_user_language, local_user_language,
person, person,
person_block, person_block,
@ -115,6 +116,14 @@ fn queries<'a>() -> Queries<
), ),
); );
let creator_is_admin = exists(
local_user::table.filter(
post_aggregates::creator_id
.eq(local_user::person_id)
.and(local_user::admin.eq(true)),
),
);
let is_saved = |person_id| { let is_saved = |person_id| {
exists( exists(
post_saved::table.filter( post_saved::table.filter(
@ -234,6 +243,7 @@ fn queries<'a>() -> Queries<
community::all_columns, community::all_columns,
is_creator_banned_from_community, is_creator_banned_from_community,
creator_is_moderator, creator_is_moderator,
creator_is_admin,
post_aggregates::all_columns, post_aggregates::all_columns,
subscribed_type_selection, subscribed_type_selection,
is_saved_selection, is_saved_selection,
@ -758,6 +768,7 @@ mod tests {
let local_user_form = LocalUserInsertForm::builder() let local_user_form = LocalUserInsertForm::builder()
.person_id(inserted_person.id) .person_id(inserted_person.id)
.admin(Some(true))
.password_encrypted(String::new()) .password_encrypted(String::new())
.build(); .build();
let inserted_local_user = LocalUser::create(pool, &local_user_form).await.unwrap(); let inserted_local_user = LocalUser::create(pool, &local_user_form).await.unwrap();
@ -1089,7 +1100,7 @@ mod tests {
CommunityModerator::join(pool, &form).await.unwrap(); CommunityModerator::join(pool, &form).await.unwrap();
let post_listing = PostQuery { let post_listing = PostQuery {
sort: (Some(SortType::New)), sort: (Some(SortType::Old)),
community_id: (Some(data.inserted_community.id)), community_id: (Some(data.inserted_community.id)),
local_user: (Some(&data.local_user_view)), local_user: (Some(&data.local_user_view)),
..Default::default() ..Default::default()
@ -1098,7 +1109,38 @@ mod tests {
.await .await
.unwrap(); .unwrap();
assert!(post_listing[1].creator_is_moderator); assert_eq!(post_listing[0].creator.name, "tegan");
assert!(post_listing[0].creator_is_moderator);
assert_eq!(post_listing[1].creator.name, "mybot");
assert!(!post_listing[1].creator_is_moderator);
cleanup(data, pool).await;
}
#[tokio::test]
#[serial]
async fn creator_is_admin() {
let pool = &build_db_pool_for_tests().await;
let pool = &mut pool.into();
let data = init_data(pool).await;
let post_listing = PostQuery {
sort: (Some(SortType::Old)),
community_id: (Some(data.inserted_community.id)),
local_user: (Some(&data.local_user_view)),
..Default::default()
}
.list(pool)
.await
.unwrap();
assert_eq!(post_listing[0].creator.name, "tegan");
assert!(post_listing[0].creator_is_admin);
assert_eq!(post_listing[1].creator.name, "mybot");
assert!(!post_listing[1].creator_is_admin);
cleanup(data, pool).await; cleanup(data, pool).await;
} }
@ -1436,6 +1478,7 @@ mod tests {
}, },
creator_banned_from_community: false, creator_banned_from_community: false,
creator_is_moderator: false, creator_is_moderator: false,
creator_is_admin: true,
community: Community { community: Community {
id: inserted_community.id, id: inserted_community.id,
name: inserted_community.name.clone(), name: inserted_community.name.clone(),

View file

@ -59,6 +59,7 @@ pub struct CommentView {
pub counts: CommentAggregates, pub counts: CommentAggregates,
pub creator_banned_from_community: bool, pub creator_banned_from_community: bool,
pub creator_is_moderator: bool, pub creator_is_moderator: bool,
pub creator_is_admin: bool,
pub subscribed: SubscribedType, pub subscribed: SubscribedType,
pub saved: bool, pub saved: bool,
pub creator_blocked: bool, pub creator_blocked: bool,
@ -114,6 +115,7 @@ pub struct PostView {
pub community: Community, pub community: Community,
pub creator_banned_from_community: bool, pub creator_banned_from_community: bool,
pub creator_is_moderator: bool, pub creator_is_moderator: bool,
pub creator_is_admin: bool,
pub counts: PostAggregates, pub counts: PostAggregates,
pub subscribed: SubscribedType, pub subscribed: SubscribedType,
pub saved: bool, pub saved: bool,

View file

@ -1,9 +1,13 @@
use crate::structs::CommentReplyView; use crate::structs::CommentReplyView;
use diesel::{ use diesel::{
dsl::exists,
pg::Pg, pg::Pg,
result::Error, result::Error,
sql_types,
BoolExpressionMethods, BoolExpressionMethods,
BoxableExpression,
ExpressionMethods, ExpressionMethods,
IntoSql,
JoinOnDsl, JoinOnDsl,
NullableExpressionMethods, NullableExpressionMethods,
QueryDsl, QueryDsl,
@ -22,11 +26,11 @@ use lemmy_db_schema::{
community_follower, community_follower,
community_moderator, community_moderator,
community_person_ban, community_person_ban,
local_user,
person, person,
person_block, person_block,
post, post,
}, },
source::community::CommunityFollower,
utils::{get_conn, limit_and_offset, DbConn, DbPool, ListFn, Queries, ReadFn}, utils::{get_conn, limit_and_offset, DbConn, DbPool, ListFn, Queries, ReadFn},
CommentSortType, CommentSortType,
}; };
@ -35,9 +39,103 @@ fn queries<'a>() -> Queries<
impl ReadFn<'a, CommentReplyView, (CommentReplyId, Option<PersonId>)>, impl ReadFn<'a, CommentReplyView, (CommentReplyId, Option<PersonId>)>,
impl ListFn<'a, CommentReplyView, CommentReplyQuery>, impl ListFn<'a, CommentReplyView, CommentReplyQuery>,
> { > {
let all_joins = |query: comment_reply::BoxedQuery<'a, Pg>, my_person_id: Option<PersonId>| { let is_creator_banned_from_community = exists(
// The left join below will return None in this case community_person_ban::table.filter(
let person_id_join = my_person_id.unwrap_or(PersonId(-1)); community::id
.eq(community_person_ban::community_id)
.and(community_person_ban::person_id.eq(comment::creator_id)),
),
);
let is_saved = |person_id| {
exists(
comment_saved::table.filter(
comment::id
.eq(comment_saved::comment_id)
.and(comment_saved::person_id.eq(person_id)),
),
)
};
let is_community_followed = |person_id| {
community_follower::table
.filter(
post::community_id
.eq(community_follower::community_id)
.and(community_follower::person_id.eq(person_id)),
)
.select(community_follower::pending.nullable())
.single_value()
};
let is_creator_blocked = |person_id| {
exists(
person_block::table.filter(
comment::creator_id
.eq(person_block::target_id)
.and(person_block::person_id.eq(person_id)),
),
)
};
let score = |person_id| {
comment_like::table
.filter(
comment::id
.eq(comment_like::comment_id)
.and(comment_like::person_id.eq(person_id)),
)
.select(comment_like::score.nullable())
.single_value()
};
let creator_is_moderator = exists(
community_moderator::table.filter(
community::id
.eq(community_moderator::community_id)
.and(community_moderator::person_id.eq(comment::creator_id)),
),
);
let creator_is_admin = exists(
local_user::table.filter(
comment::creator_id
.eq(local_user::person_id)
.and(local_user::admin.eq(true)),
),
);
let all_joins = move |query: comment_reply::BoxedQuery<'a, Pg>,
my_person_id: Option<PersonId>| {
let score_selection: Box<
dyn BoxableExpression<_, Pg, SqlType = sql_types::Nullable<sql_types::SmallInt>>,
> = if let Some(person_id) = my_person_id {
Box::new(score(person_id))
} else {
Box::new(None::<i16>.into_sql::<sql_types::Nullable<sql_types::SmallInt>>())
};
let subscribed_type_selection: Box<
dyn BoxableExpression<_, Pg, SqlType = sql_types::Nullable<sql_types::Bool>>,
> = if let Some(person_id) = my_person_id {
Box::new(is_community_followed(person_id))
} else {
Box::new(None::<bool>.into_sql::<sql_types::Nullable<sql_types::Bool>>())
};
let is_saved_selection: Box<dyn BoxableExpression<_, Pg, SqlType = sql_types::Bool>> =
if let Some(person_id) = my_person_id {
Box::new(is_saved(person_id))
} else {
Box::new(false.into_sql::<sql_types::Bool>())
};
let is_creator_blocked_selection: Box<dyn BoxableExpression<_, Pg, SqlType = sql_types::Bool>> =
if let Some(person_id) = my_person_id {
Box::new(is_creator_blocked(person_id))
} else {
Box::new(false.into_sql::<sql_types::Bool>())
};
query query
.inner_join(comment::table) .inner_join(comment::table)
@ -46,48 +144,6 @@ fn queries<'a>() -> Queries<
.inner_join(community::table.on(post::community_id.eq(community::id))) .inner_join(community::table.on(post::community_id.eq(community::id)))
.inner_join(aliases::person1) .inner_join(aliases::person1)
.inner_join(comment_aggregates::table.on(comment::id.eq(comment_aggregates::comment_id))) .inner_join(comment_aggregates::table.on(comment::id.eq(comment_aggregates::comment_id)))
.left_join(
community_person_ban::table.on(
community::id
.eq(community_person_ban::community_id)
.and(community_person_ban::person_id.eq(comment::creator_id)),
),
)
.left_join(
community_follower::table.on(
post::community_id
.eq(community_follower::community_id)
.and(community_follower::person_id.eq(person_id_join)),
),
)
.left_join(
comment_saved::table.on(
comment::id
.eq(comment_saved::comment_id)
.and(comment_saved::person_id.eq(person_id_join)),
),
)
.left_join(
person_block::table.on(
comment::creator_id
.eq(person_block::target_id)
.and(person_block::person_id.eq(person_id_join)),
),
)
.left_join(
comment_like::table.on(
comment::id
.eq(comment_like::comment_id)
.and(comment_like::person_id.eq(person_id_join)),
),
)
.left_join(
community_moderator::table.on(
community::id
.eq(community_moderator::community_id)
.and(community_moderator::person_id.eq(comment::creator_id)),
),
)
.select(( .select((
comment_reply::all_columns, comment_reply::all_columns,
comment::all_columns, comment::all_columns,
@ -96,12 +152,13 @@ fn queries<'a>() -> Queries<
community::all_columns, community::all_columns,
aliases::person1.fields(person::all_columns), aliases::person1.fields(person::all_columns),
comment_aggregates::all_columns, comment_aggregates::all_columns,
community_person_ban::community_id.nullable().is_not_null(), is_creator_banned_from_community,
community_moderator::community_id.nullable().is_not_null(), creator_is_moderator,
CommunityFollower::select_subscribed_type(), creator_is_admin,
comment_saved::comment_id.nullable().is_not_null(), subscribed_type_selection,
person_block::person_id.nullable().is_not_null(), is_saved_selection,
comment_like::score.nullable(), is_creator_blocked_selection,
score_selection,
)) ))
}; };

View file

@ -189,10 +189,11 @@ impl CommunityView {
let is_mod = let is_mod =
CommunityModeratorView::is_community_moderator(pool, community_id, person_id).await?; CommunityModeratorView::is_community_moderator(pool, community_id, person_id).await?;
if is_mod { if is_mod {
return Ok(true); Ok(true)
} else {
let is_admin = PersonView::read(pool, person_id).await?.is_admin;
Ok(is_admin)
} }
PersonView::is_admin(pool, person_id).await
} }
/// Checks if a person is an admin, or moderator of any community. /// Checks if a person is an admin, or moderator of any community.
@ -206,7 +207,8 @@ impl CommunityView {
return Ok(true); return Ok(true);
} }
PersonView::is_admin(pool, person_id).await let is_admin = PersonView::read(pool, person_id).await?.is_admin;
Ok(is_admin)
} }
} }

View file

@ -1,10 +1,13 @@
use crate::structs::PersonMentionView; use crate::structs::PersonMentionView;
use diesel::{ use diesel::{
dsl::now, dsl::exists,
pg::Pg, pg::Pg,
result::Error, result::Error,
sql_types,
BoolExpressionMethods, BoolExpressionMethods,
BoxableExpression,
ExpressionMethods, ExpressionMethods,
IntoSql,
JoinOnDsl, JoinOnDsl,
NullableExpressionMethods, NullableExpressionMethods,
QueryDsl, QueryDsl,
@ -22,12 +25,12 @@ use lemmy_db_schema::{
community_follower, community_follower,
community_moderator, community_moderator,
community_person_ban, community_person_ban,
local_user,
person, person,
person_block, person_block,
person_mention, person_mention,
post, post,
}, },
source::community::CommunityFollower,
utils::{get_conn, limit_and_offset, DbConn, DbPool, ListFn, Queries, ReadFn}, utils::{get_conn, limit_and_offset, DbConn, DbPool, ListFn, Queries, ReadFn},
CommentSortType, CommentSortType,
}; };
@ -36,9 +39,103 @@ fn queries<'a>() -> Queries<
impl ReadFn<'a, PersonMentionView, (PersonMentionId, Option<PersonId>)>, impl ReadFn<'a, PersonMentionView, (PersonMentionId, Option<PersonId>)>,
impl ListFn<'a, PersonMentionView, PersonMentionQuery>, impl ListFn<'a, PersonMentionView, PersonMentionQuery>,
> { > {
let all_joins = |query: person_mention::BoxedQuery<'a, Pg>, my_person_id: Option<PersonId>| { let is_creator_banned_from_community = exists(
// The left join below will return None in this case community_person_ban::table.filter(
let person_id_join = my_person_id.unwrap_or(PersonId(-1)); community::id
.eq(community_person_ban::community_id)
.and(community_person_ban::person_id.eq(comment::creator_id)),
),
);
let is_saved = |person_id| {
exists(
comment_saved::table.filter(
comment::id
.eq(comment_saved::comment_id)
.and(comment_saved::person_id.eq(person_id)),
),
)
};
let is_community_followed = |person_id| {
community_follower::table
.filter(
post::community_id
.eq(community_follower::community_id)
.and(community_follower::person_id.eq(person_id)),
)
.select(community_follower::pending.nullable())
.single_value()
};
let is_creator_blocked = |person_id| {
exists(
person_block::table.filter(
comment::creator_id
.eq(person_block::target_id)
.and(person_block::person_id.eq(person_id)),
),
)
};
let score = |person_id| {
comment_like::table
.filter(
comment::id
.eq(comment_like::comment_id)
.and(comment_like::person_id.eq(person_id)),
)
.select(comment_like::score.nullable())
.single_value()
};
let creator_is_moderator = exists(
community_moderator::table.filter(
community::id
.eq(community_moderator::community_id)
.and(community_moderator::person_id.eq(comment::creator_id)),
),
);
let creator_is_admin = exists(
local_user::table.filter(
comment::creator_id
.eq(local_user::person_id)
.and(local_user::admin.eq(true)),
),
);
let all_joins = move |query: person_mention::BoxedQuery<'a, Pg>,
my_person_id: Option<PersonId>| {
let score_selection: Box<
dyn BoxableExpression<_, Pg, SqlType = sql_types::Nullable<sql_types::SmallInt>>,
> = if let Some(person_id) = my_person_id {
Box::new(score(person_id))
} else {
Box::new(None::<i16>.into_sql::<sql_types::Nullable<sql_types::SmallInt>>())
};
let subscribed_type_selection: Box<
dyn BoxableExpression<_, Pg, SqlType = sql_types::Nullable<sql_types::Bool>>,
> = if let Some(person_id) = my_person_id {
Box::new(is_community_followed(person_id))
} else {
Box::new(None::<bool>.into_sql::<sql_types::Nullable<sql_types::Bool>>())
};
let is_saved_selection: Box<dyn BoxableExpression<_, Pg, SqlType = sql_types::Bool>> =
if let Some(person_id) = my_person_id {
Box::new(is_saved(person_id))
} else {
Box::new(false.into_sql::<sql_types::Bool>())
};
let is_creator_blocked_selection: Box<dyn BoxableExpression<_, Pg, SqlType = sql_types::Bool>> =
if let Some(person_id) = my_person_id {
Box::new(is_creator_blocked(person_id))
} else {
Box::new(false.into_sql::<sql_types::Bool>())
};
query query
.inner_join(comment::table) .inner_join(comment::table)
@ -47,37 +144,7 @@ fn queries<'a>() -> Queries<
.inner_join(community::table.on(post::community_id.eq(community::id))) .inner_join(community::table.on(post::community_id.eq(community::id)))
.inner_join(aliases::person1) .inner_join(aliases::person1)
.inner_join(comment_aggregates::table.on(comment::id.eq(comment_aggregates::comment_id))) .inner_join(comment_aggregates::table.on(comment::id.eq(comment_aggregates::comment_id)))
.left_join( .select((
community_follower::table.on(
post::community_id
.eq(community_follower::community_id)
.and(community_follower::person_id.eq(person_id_join)),
),
)
.left_join(
comment_saved::table.on(
comment::id
.eq(comment_saved::comment_id)
.and(comment_saved::person_id.eq(person_id_join)),
),
)
.left_join(
person_block::table.on(
comment::creator_id
.eq(person_block::target_id)
.and(person_block::person_id.eq(person_id_join)),
),
)
.left_join(
comment_like::table.on(
comment::id
.eq(comment_like::comment_id)
.and(comment_like::person_id.eq(person_id_join)),
),
)
};
let selection = (
person_mention::all_columns, person_mention::all_columns,
comment::all_columns, comment::all_columns,
person::all_columns, person::all_columns,
@ -85,13 +152,15 @@ fn queries<'a>() -> Queries<
community::all_columns, community::all_columns,
aliases::person1.fields(person::all_columns), aliases::person1.fields(person::all_columns),
comment_aggregates::all_columns, comment_aggregates::all_columns,
community_person_ban::community_id.nullable().is_not_null(), is_creator_banned_from_community,
community_moderator::community_id.nullable().is_not_null(), creator_is_moderator,
CommunityFollower::select_subscribed_type(), creator_is_admin,
comment_saved::comment_id.nullable().is_not_null(), subscribed_type_selection,
person_block::person_id.nullable().is_not_null(), is_saved_selection,
comment_like::score.nullable(), is_creator_blocked_selection,
); score_selection,
))
};
let read = let read =
move |mut conn: DbConn<'a>, move |mut conn: DbConn<'a>,
@ -100,47 +169,12 @@ fn queries<'a>() -> Queries<
person_mention::table.find(person_mention_id).into_boxed(), person_mention::table.find(person_mention_id).into_boxed(),
my_person_id, my_person_id,
) )
.left_join(
community_person_ban::table.on(
community::id
.eq(community_person_ban::community_id)
.and(community_person_ban::person_id.eq(comment::creator_id)),
),
)
.left_join(
community_moderator::table.on(
community::id
.eq(community_moderator::community_id)
.and(community_moderator::person_id.eq(comment::creator_id)),
),
)
.select(selection)
.first::<PersonMentionView>(&mut conn) .first::<PersonMentionView>(&mut conn)
.await .await
}; };
let list = move |mut conn: DbConn<'a>, options: PersonMentionQuery| async move { let list = move |mut conn: DbConn<'a>, options: PersonMentionQuery| async move {
let mut query = all_joins(person_mention::table.into_boxed(), options.my_person_id) let mut query = all_joins(person_mention::table.into_boxed(), options.my_person_id);
.left_join(
community_person_ban::table.on(
community::id
.eq(community_person_ban::community_id)
.and(community_person_ban::person_id.eq(comment::creator_id))
.and(
community_person_ban::expires
.is_null()
.or(community_person_ban::expires.gt(now)),
),
),
)
.left_join(
community_moderator::table.on(
community::id
.eq(community_moderator::community_id)
.and(community_moderator::person_id.eq(comment::creator_id)),
),
)
.select(selection);
if let Some(recipient_id) = options.recipient_id { if let Some(recipient_id) = options.recipient_id {
query = query.filter(person_mention::recipient_id.eq(recipient_id)); query = query.filter(person_mention::recipient_id.eq(recipient_id));

View file

@ -1,5 +1,6 @@
use crate::structs::PersonView; use crate::structs::PersonView;
use diesel::{ use diesel::{
dsl::exists,
pg::Pg, pg::Pg,
result::Error, result::Error,
BoolExpressionMethods, BoolExpressionMethods,
@ -11,9 +12,8 @@ use diesel::{
use diesel_async::RunQueryDsl; use diesel_async::RunQueryDsl;
use lemmy_db_schema::{ use lemmy_db_schema::{
newtypes::PersonId, newtypes::PersonId,
schema,
schema::{local_user, person, person_aggregates}, schema::{local_user, person, person_aggregates},
utils::{fuzzy_search, get_conn, limit_and_offset, now, DbConn, DbPool, ListFn, Queries, ReadFn}, utils::{fuzzy_search, limit_and_offset, now, DbConn, DbPool, ListFn, Queries, ReadFn},
SortType, SortType,
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -48,12 +48,22 @@ fn post_to_person_sort_type(sort: SortType) -> PersonSortType {
fn queries<'a>( fn queries<'a>(
) -> Queries<impl ReadFn<'a, PersonView, PersonId>, impl ListFn<'a, PersonView, ListMode>> { ) -> Queries<impl ReadFn<'a, PersonView, PersonId>, impl ListFn<'a, PersonView, ListMode>> {
let all_joins = |query: person::BoxedQuery<'a, Pg>| { let creator_is_admin = exists(
local_user::table.filter(
person::id
.eq(local_user::person_id)
.and(local_user::admin.eq(true)),
),
);
let all_joins = move |query: person::BoxedQuery<'a, Pg>| {
query query
.inner_join(person_aggregates::table) .inner_join(person_aggregates::table)
.left_join(local_user::table)
.filter(person::deleted.eq(false)) .filter(person::deleted.eq(false))
.select((person::all_columns, person_aggregates::all_columns)) .select((
person::all_columns,
person_aggregates::all_columns,
creator_is_admin,
))
}; };
let read = move |mut conn: DbConn<'a>, person_id: PersonId| async move { let read = move |mut conn: DbConn<'a>, person_id: PersonId| async move {
@ -67,7 +77,7 @@ fn queries<'a>(
match mode { match mode {
ListMode::Admins => { ListMode::Admins => {
query = query query = query
.filter(local_user::admin.eq(true)) .filter(creator_is_admin.eq(true))
.filter(person::deleted.eq(false)) .filter(person::deleted.eq(false))
.order_by(person::published); .order_by(person::published);
} }
@ -115,21 +125,6 @@ impl PersonView {
queries().read(pool, person_id).await queries().read(pool, person_id).await
} }
pub async fn is_admin(pool: &mut DbPool<'_>, person_id: PersonId) -> Result<bool, Error> {
use schema::{
local_user::dsl::admin,
person::dsl::{id, person},
};
let conn = &mut get_conn(pool).await?;
let is_admin = person
.inner_join(local_user::table)
.filter(id.eq(person_id))
.select(admin)
.first::<bool>(conn)
.await?;
Ok(is_admin)
}
pub async fn admins(pool: &mut DbPool<'_>) -> Result<Vec<Self>, Error> { pub async fn admins(pool: &mut DbPool<'_>) -> Result<Vec<Self>, Error> {
queries().list(pool, ListMode::Admins).await queries().list(pool, ListMode::Admins).await
} }
@ -251,7 +246,13 @@ mod tests {
let read = PersonView::read(pool, data.alice.id).await; let read = PersonView::read(pool, data.alice.id).await;
assert_eq!(read.err(), Some(NotFound)); assert_eq!(read.err(), Some(NotFound));
let list = PersonQuery::default().list(pool).await.unwrap(); let list = PersonQuery {
sort: Some(SortType::New),
..Default::default()
}
.list(pool)
.await
.unwrap();
assert_eq!(list.len(), 1); assert_eq!(list.len(), 1);
assert_eq!(list[0].person.id, data.bob.id); assert_eq!(list[0].person.id, data.bob.id);
@ -305,10 +306,13 @@ mod tests {
assert_eq!(list.len(), 1); assert_eq!(list.len(), 1);
assert_eq!(list[0].person.id, data.alice.id); assert_eq!(list[0].person.id, data.alice.id);
let is_admin = PersonView::is_admin(pool, data.alice.id).await.unwrap(); let is_admin = PersonView::read(pool, data.alice.id)
.await
.unwrap()
.is_admin;
assert!(is_admin); assert!(is_admin);
let is_admin = PersonView::is_admin(pool, data.bob.id).await.unwrap(); let is_admin = PersonView::read(pool, data.bob.id).await.unwrap().is_admin;
assert!(!is_admin); assert!(!is_admin);
cleanup(data, pool).await; cleanup(data, pool).await;

View file

@ -108,6 +108,7 @@ pub struct PersonMentionView {
pub counts: CommentAggregates, pub counts: CommentAggregates,
pub creator_banned_from_community: bool, pub creator_banned_from_community: bool,
pub creator_is_moderator: bool, pub creator_is_moderator: bool,
pub creator_is_admin: bool,
pub subscribed: SubscribedType, pub subscribed: SubscribedType,
pub saved: bool, pub saved: bool,
pub creator_blocked: bool, pub creator_blocked: bool,
@ -130,6 +131,7 @@ pub struct CommentReplyView {
pub counts: CommentAggregates, pub counts: CommentAggregates,
pub creator_banned_from_community: bool, pub creator_banned_from_community: bool,
pub creator_is_moderator: bool, pub creator_is_moderator: bool,
pub creator_is_admin: bool,
pub subscribed: SubscribedType, pub subscribed: SubscribedType,
pub saved: bool, pub saved: bool,
pub creator_blocked: bool, pub creator_blocked: bool,
@ -144,4 +146,5 @@ pub struct CommentReplyView {
pub struct PersonView { pub struct PersonView {
pub person: Person, pub person: Person,
pub counts: PersonAggregates, pub counts: PersonAggregates,
pub is_admin: bool,
} }