Compare commits

...

5 Commits

Author SHA1 Message Date
Dessalines 185105b031 Adding admin/mod checks for ban and comment removal. 2024-06-21 18:10:48 -04:00
Dessalines 3ae8e98f3c Merge remote-tracking branch 'origin/main' into mod_admin_ordering 2024-06-21 17:53:38 -04:00
Dessalines d09854a722
Adding a show_read override to GetPosts. (#4846)
* Adding a show_read override to GetPosts.

- If show_read is true, it overrides the local user show_read
  setting.
- Fixes #4124

* Addressing PR comments.

* Update crates/db_views/src/post_view.rs

Co-authored-by: dullbananas <dull.bananas0@gmail.com>

* Fixing formatting.

---------

Co-authored-by: dullbananas <dull.bananas0@gmail.com>
2024-06-21 17:39:40 -04:00
Dessalines c8d155102a
Removing renovate from git cliff (#4858)
* Removing renovate from git cliff

* Formatting.
2024-06-21 17:38:44 -04:00
dullbananas 36e6f7ec78
Fix order in `CommunityModeratorView::get_community_first_mods` (#4859)
* Fix order in `CommunityModeratorView::get_community_first_mods`

* Update community_moderator_view.rs

* Update community_moderator_view.rs
2024-06-21 13:44:55 -04:00
14 changed files with 124 additions and 50 deletions

View File

@ -26,6 +26,7 @@ body = """
{%- endif %}
{%- endfor -%}
{%- if github -%}
{% if github.contributors | filter(attribute="is_first_time", value=true) | length != 0 %}
{% raw %}\n{% endraw -%}
## New Contributors
@ -36,6 +37,7 @@ body = """
[#{{ contributor.pr_number }}]({{ self::remote_url() }}/pull/{{ contributor.pr_number }}) \
{%- endif %}
{%- endfor -%}
{%- endif -%}
{% if version %}
{% if previous.version %}
@ -70,6 +72,7 @@ commit_preprocessors = [
# remove issue numbers from commits
{ pattern = '\((\w+\s)?#([0-9]+)\)', replace = "" },
]
commit_parsers = [{ field = "author.name", pattern = "renovate", skip = true }]
# protect breaking changes from being skipped due to matching a skipping commit_parser
protect_breaking_commits = false
# filter out the commits that are not matched by commit parsers

View File

@ -4,7 +4,12 @@ use lemmy_api_common::{
community::{BanFromCommunity, BanFromCommunityResponse},
context::LemmyContext,
send_activity::{ActivityChannel, SendActivityData},
utils::{check_community_mod_action, check_expire_time, remove_user_data_in_community},
utils::{
check_community_mod_action,
check_expire_time,
check_is_higher_mod,
remove_user_data_in_community,
},
};
use lemmy_db_schema::{
source::{
@ -44,6 +49,14 @@ pub async fn ban_from_community(
)
.await?;
check_is_higher_mod(
&mut context.pool(),
&local_user_view,
data.community_id,
&[data.person_id],
)
.await?;
if let Some(reason) = &data.reason {
is_valid_body_field(reason, false)?;
}

View File

@ -5,7 +5,7 @@ use lemmy_api_common::{
context::LemmyContext,
person::{BanPerson, BanPersonResponse},
send_activity::{ActivityChannel, SendActivityData},
utils::{check_expire_time, is_admin, remove_user_data},
utils::{check_expire_time, check_is_higher_admin, is_admin, remove_user_data},
};
use lemmy_db_schema::{
source::{
@ -31,6 +31,9 @@ pub async fn ban_from_site(
// Make sure user is an admin
is_admin(&local_user_view)?;
// Also make sure you're a higher admin than the target
check_is_higher_admin(&mut context.pool(), &local_user_view, &[data.person_id]).await?;
if let Some(reason) = &data.reason {
is_valid_body_field(reason, false)?;
}

View File

@ -79,6 +79,8 @@ pub struct GetPosts {
pub liked_only: Option<bool>,
pub disliked_only: Option<bool>,
pub show_hidden: Option<bool>,
/// If true, then show the read posts (even if your user setting is to hide them)
pub show_read: Option<bool>,
pub page_cursor: Option<PaginationCursor>,
}

View File

@ -178,6 +178,25 @@ pub async fn check_is_higher_admin(
Ok(())
}
/// Checks to make sure the acting admin is higher than the target admin.
/// This needs to be done on admin removals, and all purge functions
pub async fn check_is_higher_mod_or_admin(
pool: &mut DbPool<'_>,
local_user_view: &LocalUserView,
community_id: CommunityId,
target_person_ids: &[PersonId],
) -> LemmyResult<()> {
let higher_admin_check = check_is_higher_admin(pool, local_user_view, target_person_ids).await;
let higher_mod_check =
check_is_higher_mod(pool, local_user_view, community_id, target_person_ids).await;
if higher_mod_check.is_ok() || higher_admin_check.is_ok() {
Ok(())
} else {
Err(LemmyErrorType::NotHigherMod)?
}
}
/// Marks a post as read for a given person.
#[tracing::instrument(skip_all)]
pub async fn mark_post_as_read(

View File

@ -5,7 +5,7 @@ use lemmy_api_common::{
comment::{CommentResponse, RemoveComment},
context::LemmyContext,
send_activity::{ActivityChannel, SendActivityData},
utils::check_community_mod_action,
utils::{check_community_mod_action, check_is_higher_mod_or_admin},
};
use lemmy_db_schema::{
source::{
@ -37,6 +37,14 @@ pub async fn remove_comment(
)
.await?;
check_is_higher_mod_or_admin(
&mut context.pool(),
&local_user_view,
orig_comment.community.id,
&[orig_comment.creator.id],
)
.await?;
// Don't allow removing or restoring comment which was deleted by user, as it would reveal
// the comment text in mod log.
if orig_comment.comment.deleted {

View File

@ -37,11 +37,11 @@ pub async fn list_comments(
};
let sort = data.sort;
let max_depth = data.max_depth;
let saved_only = data.saved_only.unwrap_or_default();
let saved_only = data.saved_only;
let liked_only = data.liked_only.unwrap_or_default();
let disliked_only = data.disliked_only.unwrap_or_default();
if liked_only && disliked_only {
let liked_only = data.liked_only;
let disliked_only = data.disliked_only;
if liked_only.unwrap_or_default() && disliked_only.unwrap_or_default() {
return Err(LemmyError::from(LemmyErrorType::ContradictingFilters));
}

View File

@ -40,12 +40,13 @@ pub async fn list_posts(
} else {
data.community_id
};
let saved_only = data.saved_only.unwrap_or_default();
let show_hidden = data.show_hidden.unwrap_or_default();
let saved_only = data.saved_only;
let show_hidden = data.show_hidden;
let show_read = data.show_read;
let liked_only = data.liked_only.unwrap_or_default();
let disliked_only = data.disliked_only.unwrap_or_default();
if liked_only && disliked_only {
let liked_only = data.liked_only;
let disliked_only = data.disliked_only;
if liked_only.unwrap_or_default() && disliked_only.unwrap_or_default() {
return Err(LemmyError::from(LemmyErrorType::ContradictingFilters));
}
@ -82,6 +83,7 @@ pub async fn list_posts(
page_after,
limit,
show_hidden,
show_read,
..Default::default()
}
.list(&local_site.site, &mut context.pool())

View File

@ -55,11 +55,11 @@ pub async fn read_person(
let sort = data.sort;
let page = data.page;
let limit = data.limit;
let saved_only = data.saved_only.unwrap_or_default();
let saved_only = data.saved_only;
let community_id = data.community_id;
// If its saved only, you don't care what creator it was
// Or, if its not saved, then you only want it for that specific creator
let creator_id = if !saved_only {
let creator_id = if !saved_only.unwrap_or_default() {
Some(person_details_id)
} else {
None

View File

@ -241,7 +241,7 @@ impl CommunityModerator {
for_community_id: CommunityId,
mod_person_id: PersonId,
target_person_ids: &[PersonId],
) -> Result<bool, Error> {
) -> Result<(), Error> {
let conn = &mut get_conn(pool).await?;
// Build the list of persons
@ -259,7 +259,7 @@ impl CommunityModerator {
// If the first result sorted by published is the acting mod
if res.person_id == mod_person_id {
Ok(true)
Ok(())
} else {
Err(diesel::result::Error::NotFound)
}
@ -554,8 +554,8 @@ mod tests {
inserted_bobby.id,
&moderator_person_ids,
)
.await?;
assert!(bobby_higher_check);
.await;
assert!(bobby_higher_check.is_ok());
// This should throw an error, since artemis was added later
let artemis_higher_check = CommunityModerator::is_higher_mod_check(

View File

@ -221,7 +221,7 @@ impl LocalUser {
pool: &mut DbPool<'_>,
admin_person_id: PersonId,
target_person_ids: &[PersonId],
) -> Result<bool, Error> {
) -> Result<(), Error> {
let conn = &mut get_conn(pool).await?;
// Build the list of persons
@ -239,7 +239,7 @@ impl LocalUser {
// If the first result sorted by published is the acting mod
if res.person_id == admin_person_id {
Ok(true)
Ok(())
} else {
Err(diesel::result::Error::NotFound)
}
@ -346,8 +346,8 @@ mod tests {
// Make sure fiona is marked as a higher admin than delores, and vice versa
let fiona_higher_check =
LocalUser::is_higher_admin_check(pool, inserted_fiona_person.id, &admin_person_ids).await?;
assert!(fiona_higher_check);
LocalUser::is_higher_admin_check(pool, inserted_fiona_person.id, &admin_person_ids).await;
assert!(fiona_higher_check.is_ok());
// This should throw an error, since delores was added later
let delores_higher_check =

View File

@ -252,7 +252,7 @@ fn queries<'a>() -> Queries<
}
// If its saved only, then filter, and order by the saved time, not the comment creation time.
if options.saved_only {
if options.saved_only.unwrap_or_default() {
query = query
.filter(comment_saved::person_id.is_not_null())
.then_order_by(comment_saved::published.desc());
@ -260,9 +260,9 @@ fn queries<'a>() -> Queries<
if let Some(my_id) = options.local_user.person_id() {
let not_creator_filter = comment::creator_id.ne(my_id);
if options.liked_only {
if options.liked_only.unwrap_or_default() {
query = query.filter(not_creator_filter).filter(score(my_id).eq(1));
} else if options.disliked_only {
} else if options.disliked_only.unwrap_or_default() {
query = query.filter(not_creator_filter).filter(score(my_id).eq(-1));
}
}
@ -398,9 +398,9 @@ pub struct CommentQuery<'a> {
pub creator_id: Option<PersonId>,
pub local_user: Option<&'a LocalUser>,
pub search_term: Option<String>,
pub saved_only: bool,
pub liked_only: bool,
pub disliked_only: bool,
pub saved_only: Option<bool>,
pub liked_only: Option<bool>,
pub disliked_only: Option<bool>,
pub page: Option<i64>,
pub limit: Option<i64>,
pub max_depth: Option<i32>,
@ -708,8 +708,8 @@ mod tests {
CommentLike::like(pool, &comment_like_form).await?;
let read_liked_comment_views = CommentQuery {
local_user: (Some(&data.timmy_local_user_view.local_user)),
liked_only: (true),
local_user: Some(&data.timmy_local_user_view.local_user),
liked_only: Some(true),
..Default::default()
}
.list(pool)
@ -724,8 +724,8 @@ mod tests {
assert_length!(1, read_liked_comment_views);
let read_disliked_comment_views: Vec<CommentView> = CommentQuery {
local_user: (Some(&data.timmy_local_user_view.local_user)),
disliked_only: (true),
local_user: Some(&data.timmy_local_user_view.local_user),
disliked_only: Some(true),
..Default::default()
}
.list(pool)
@ -977,7 +977,7 @@ mod tests {
// Fetch the saved comments
let comments = CommentQuery {
local_user: Some(&data.timmy_local_user_view.local_user),
saved_only: true,
saved_only: Some(true),
..Default::default()
}
.list(pool)

View File

@ -403,14 +403,17 @@ fn queries<'a>() -> Queries<
};
// If its saved only, then filter, and order by the saved time, not the comment creation time.
if options.saved_only {
if options.saved_only.unwrap_or_default() {
query = query
.filter(post_saved::person_id.is_not_null())
.then_order_by(post_saved::published.desc());
}
// Only hide the read posts, if the saved_only is false. Otherwise ppl with the hide_read
// setting wont be able to see saved posts.
else if !options.local_user.show_read_posts() {
else if !options
.show_read
.unwrap_or(options.local_user.show_read_posts())
{
// Do not hide read posts when it is a user profile view
// Or, only hide read posts on non-profile views
if let (None, Some(person_id)) = (options.creator_id, options.local_user.person_id()) {
@ -418,7 +421,7 @@ fn queries<'a>() -> Queries<
}
}
if !options.show_hidden {
if !options.show_hidden.unwrap_or_default() {
// If a creator id isn't given (IE its on home or community pages), hide the hidden posts
if let (None, Some(person_id)) = (options.creator_id, options.local_user.person_id()) {
query = query.filter(not(is_hidden(person_id)));
@ -427,9 +430,9 @@ fn queries<'a>() -> Queries<
if let Some(my_id) = options.local_user.person_id() {
let not_creator_filter = post_aggregates::creator_id.ne(my_id);
if options.liked_only {
if options.liked_only.unwrap_or_default() {
query = query.filter(not_creator_filter).filter(score(my_id).eq(1));
} else if options.disliked_only {
} else if options.disliked_only.unwrap_or_default() {
query = query.filter(not_creator_filter).filter(score(my_id).eq(-1));
}
};
@ -476,7 +479,7 @@ fn queries<'a>() -> Queries<
let page_after = options.page_after.map(|c| c.0);
let page_before_or_equal = options.page_before_or_equal.map(|c| c.0);
if options.page_back {
if options.page_back.unwrap_or_default() {
query = query
.before(page_after)
.after_or_equal(page_before_or_equal)
@ -604,15 +607,16 @@ pub struct PostQuery<'a> {
pub local_user: Option<&'a LocalUser>,
pub search_term: Option<String>,
pub url_search: Option<String>,
pub saved_only: bool,
pub liked_only: bool,
pub disliked_only: bool,
pub saved_only: Option<bool>,
pub liked_only: Option<bool>,
pub disliked_only: Option<bool>,
pub page: Option<i64>,
pub limit: Option<i64>,
pub page_after: Option<PaginationCursorData>,
pub page_before_or_equal: Option<PaginationCursorData>,
pub page_back: bool,
pub show_hidden: bool,
pub page_back: Option<bool>,
pub show_hidden: Option<bool>,
pub show_read: Option<bool>,
}
impl<'a> PostQuery<'a> {
@ -683,7 +687,7 @@ impl<'a> PostQuery<'a> {
if (v.len() as i64) < limit {
Ok(Some(self.clone()))
} else {
let item = if self.page_back {
let item = if self.page_back.unwrap_or_default() {
// for backward pagination, get first element instead
v.into_iter().next()
} else {
@ -1122,7 +1126,7 @@ mod tests {
// Read the liked only
let read_liked_post_listing = PostQuery {
community_id: Some(data.inserted_community.id),
liked_only: true,
liked_only: Some(true),
..data.default_post_query()
}
.list(&data.site, pool)
@ -1133,7 +1137,7 @@ mod tests {
let read_disliked_post_listing = PostQuery {
community_id: Some(data.inserted_community.id),
disliked_only: true,
disliked_only: Some(true),
..data.default_post_query()
}
.list(&data.site, pool)
@ -1459,7 +1463,7 @@ mod tests {
loop {
let post_listings = PostQuery {
page_after: page_before,
page_back: true,
page_back: Some(true),
..options.clone()
}
.list(&data.site, pool)
@ -1517,6 +1521,26 @@ mod tests {
let post_listings_hide_read = data.default_post_query().list(&data.site, pool).await?;
assert_eq!(vec![POST], names(&post_listings_hide_read));
// Test with the show_read override as true
let post_listings_show_read_true = PostQuery {
show_read: Some(true),
..data.default_post_query()
}
.list(&data.site, pool)
.await?;
assert_eq!(
vec![POST_BY_BOT, POST],
names(&post_listings_show_read_true)
);
// Test with the show_read override as false
let post_listings_show_read_false = PostQuery {
show_read: Some(false),
..data.default_post_query()
}
.list(&data.site, pool)
.await?;
assert_eq!(vec![POST], names(&post_listings_show_read_false));
cleanup(data, pool).await
}
@ -1543,7 +1567,7 @@ mod tests {
let post_listings_show_hidden = PostQuery {
sort: Some(SortType::New),
local_user: Some(&data.local_user_view.local_user),
show_hidden: true,
show_hidden: Some(true),
..Default::default()
}
.list(&data.site, pool)

View File

@ -90,7 +90,7 @@ impl CommunityModeratorView {
.distinct_on(community_moderator::community_id)
.order_by((
community_moderator::community_id,
community_moderator::person_id,
community_moderator::published,
))
.load::<CommunityModeratorView>(conn)
.await