Cleanup checks for community actions (fixes #2858, fixes #2868) (#4028)

* Cleanup checks for community actions (fixes #2858, fixes #2868)

* allow restoring deleted community

* review changes

* remove unneeded sql

* remove joins

* change mod log check
This commit is contained in:
Nutomic 2023-10-13 15:48:18 +02:00 committed by GitHub
parent 608bb6b1b4
commit 9e099726e6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
38 changed files with 273 additions and 231 deletions

View file

@ -2,7 +2,7 @@ use actix_web::web::{Data, Json};
use lemmy_api_common::{
comment::{CommentResponse, DistinguishComment},
context::LemmyContext,
utils::{check_community_ban, is_mod_or_admin},
utils::{check_community_mod_action, check_community_user_action},
};
use lemmy_db_schema::{
source::comment::{Comment, CommentUpdateForm},
@ -19,18 +19,19 @@ pub async fn distinguish_comment(
) -> Result<Json<CommentResponse>, LemmyError> {
let orig_comment = CommentView::read(&mut context.pool(), data.comment_id, None).await?;
check_community_ban(
local_user_view.person.id,
check_community_user_action(
&local_user_view.person,
orig_comment.community.id,
&mut context.pool(),
)
.await?;
// Verify that only a mod or admin can distinguish a comment
is_mod_or_admin(
&mut context.pool(),
local_user_view.person.id,
check_community_mod_action(
&local_user_view.person,
orig_comment.community.id,
false,
&mut context.pool(),
)
.await?;

View file

@ -5,7 +5,7 @@ use lemmy_api_common::{
comment::{CommentResponse, CreateCommentLike},
context::LemmyContext,
send_activity::{ActivityChannel, SendActivityData},
utils::{check_community_ban, check_downvotes_enabled},
utils::{check_community_user_action, check_downvotes_enabled},
};
use lemmy_db_schema::{
newtypes::LocalUserId,
@ -36,8 +36,8 @@ pub async fn like_comment(
let comment_id = data.comment_id;
let orig_comment = CommentView::read(&mut context.pool(), comment_id, None).await?;
check_community_ban(
local_user_view.person.id,
check_community_user_action(
&local_user_view.person,
orig_comment.community.id,
&mut context.pool(),
)

View file

@ -5,7 +5,7 @@ use lemmy_api_common::{
comment::{CommentReportResponse, CreateCommentReport},
context::LemmyContext,
send_activity::{ActivityChannel, SendActivityData},
utils::{check_community_ban, send_new_report_email_to_admins},
utils::{check_community_user_action, send_new_report_email_to_admins},
};
use lemmy_db_schema::{
source::{
@ -33,7 +33,12 @@ pub async fn create_comment_report(
let comment_id = data.comment_id;
let comment_view = CommentView::read(&mut context.pool(), comment_id, None).await?;
check_community_ban(person_id, comment_view.community.id, &mut context.pool()).await?;
check_community_user_action(
&local_user_view.person,
comment_view.community.id,
&mut context.pool(),
)
.await?;
let report_form = CommentReportForm {
creator_id: person_id,

View file

@ -2,6 +2,7 @@ use actix_web::web::{Data, Json, Query};
use lemmy_api_common::{
comment::{ListCommentReports, ListCommentReportsResponse},
context::LemmyContext,
utils::check_community_mod_action_opt,
};
use lemmy_db_views::{comment_report_view::CommentReportQuery, structs::LocalUserView};
use lemmy_utils::error::LemmyError;
@ -17,6 +18,8 @@ pub async fn list_comment_reports(
let community_id = data.community_id;
let unresolved_only = data.unresolved_only.unwrap_or_default();
check_community_mod_action_opt(&local_user_view, community_id, &mut context.pool()).await?;
let page = data.page;
let limit = data.limit;
let comment_reports = CommentReportQuery {

View file

@ -2,7 +2,7 @@ use actix_web::web::{Data, Json};
use lemmy_api_common::{
comment::{CommentReportResponse, ResolveCommentReport},
context::LemmyContext,
utils::is_mod_or_admin,
utils::check_community_mod_action,
};
use lemmy_db_schema::{source::comment_report::CommentReport, traits::Reportable};
use lemmy_db_views::structs::{CommentReportView, LocalUserView};
@ -20,7 +20,13 @@ pub async fn resolve_comment_report(
let report = CommentReportView::read(&mut context.pool(), report_id, person_id).await?;
let person_id = local_user_view.person.id;
is_mod_or_admin(&mut context.pool(), person_id, report.community.id).await?;
check_community_mod_action(
&local_user_view.person,
report.community.id,
false,
&mut context.pool(),
)
.await?;
if data.resolved {
CommentReport::resolve(&mut context.pool(), report_id, person_id)

View file

@ -4,7 +4,7 @@ use lemmy_api_common::{
community::{AddModToCommunity, AddModToCommunityResponse},
context::LemmyContext,
send_activity::{ActivityChannel, SendActivityData},
utils::is_mod_or_admin,
utils::check_community_mod_action,
};
use lemmy_db_schema::{
source::{
@ -26,7 +26,13 @@ pub async fn add_mod_to_community(
let community_id = data.community_id;
// Verify that only mods or admins can add mod
is_mod_or_admin(&mut context.pool(), local_user_view.person.id, community_id).await?;
check_community_mod_action(
&local_user_view.person,
community_id,
false,
&mut context.pool(),
)
.await?;
let community = Community::read(&mut context.pool(), community_id).await?;
if local_user_view.local_user.admin && !community.local {
Err(LemmyErrorType::NotAModerator)?

View file

@ -4,7 +4,7 @@ use lemmy_api_common::{
community::{BanFromCommunity, BanFromCommunityResponse},
context::LemmyContext,
send_activity::{ActivityChannel, SendActivityData},
utils::{is_mod_or_admin, remove_user_data_in_community},
utils::{check_community_mod_action, remove_user_data_in_community},
};
use lemmy_db_schema::{
source::{
@ -36,10 +36,11 @@ pub async fn ban_from_community(
let expires = data.expires.map(naive_from_unix);
// Verify that only mods or admins can ban
is_mod_or_admin(
&mut context.pool(),
local_user_view.person.id,
check_community_mod_action(
&local_user_view.person,
data.community_id,
false,
&mut context.pool(),
)
.await?;
is_valid_body_field(&data.reason, false)?;

View file

@ -4,7 +4,7 @@ use lemmy_api_common::{
community::{CommunityResponse, FollowCommunity},
context::LemmyContext,
send_activity::{ActivityChannel, SendActivityData},
utils::{check_community_ban, check_community_deleted_or_removed},
utils::check_community_user_action,
};
use lemmy_db_schema::{
source::{
@ -32,8 +32,8 @@ pub async fn follow_community(
if data.follow {
if community.local {
check_community_ban(local_user_view.person.id, community.id, &mut context.pool()).await?;
check_community_deleted_or_removed(community.id, &mut context.pool()).await?;
check_community_user_action(&local_user_view.person, community.id, &mut context.pool())
.await?;
CommunityFollower::follow(&mut context.pool(), &community_follower_form)
.await

View file

@ -3,7 +3,7 @@ use anyhow::Context;
use lemmy_api_common::{
community::{GetCommunityResponse, TransferCommunity},
context::LemmyContext,
utils::{is_admin, is_top_mod},
utils::{check_community_user_action, is_admin, is_top_mod},
};
use lemmy_db_schema::{
source::{
@ -27,11 +27,12 @@ pub async fn transfer_community(
context: Data<LemmyContext>,
local_user_view: LocalUserView,
) -> Result<Json<GetCommunityResponse>, LemmyError> {
// Fetch the community mods
let community_id = data.community_id;
let mut community_mods =
CommunityModeratorView::for_community(&mut context.pool(), community_id).await?;
check_community_user_action(&local_user_view.person, community_id, &mut context.pool()).await?;
// Make sure transferrer is either the top community mod, or an admin
if !(is_top_mod(&local_user_view, &community_mods).is_ok() || is_admin(&local_user_view).is_ok())
{

View file

@ -44,11 +44,7 @@ pub async fn login(
if !valid {
Err(LemmyErrorType::IncorrectLogin)?
}
check_user_valid(
local_user_view.person.banned,
local_user_view.person.ban_expires,
local_user_view.person.deleted,
)?;
check_user_valid(&local_user_view.person)?;
// Check if the user's email is verified if email verification is turned on
// However, skip checking verification if the user is an admin

View file

@ -2,6 +2,7 @@ use actix_web::web::{Data, Json};
use lemmy_api_common::{
context::LemmyContext,
person::{GetReportCount, GetReportCountResponse},
utils::check_community_mod_action_opt,
};
use lemmy_db_views::structs::{
CommentReportView,
@ -21,6 +22,8 @@ pub async fn report_count(
let admin = local_user_view.local_user.admin;
let community_id = data.community_id;
check_community_mod_action_opt(&local_user_view, community_id, &mut context.pool()).await?;
let comment_reports =
CommentReportView::get_report_count(&mut context.pool(), person_id, admin, community_id)
.await?;

View file

@ -5,7 +5,7 @@ use lemmy_api_common::{
context::LemmyContext,
post::{FeaturePost, PostResponse},
send_activity::{ActivityChannel, SendActivityData},
utils::{check_community_ban, check_community_deleted_or_removed, is_admin, is_mod_or_admin},
utils::{check_community_mod_action, is_admin},
};
use lemmy_db_schema::{
source::{
@ -27,23 +27,15 @@ pub async fn feature_post(
let post_id = data.post_id;
let orig_post = Post::read(&mut context.pool(), post_id).await?;
check_community_ban(
local_user_view.person.id,
check_community_mod_action(
&local_user_view.person,
orig_post.community_id,
false,
&mut context.pool(),
)
.await?;
check_community_deleted_or_removed(orig_post.community_id, &mut context.pool()).await?;
if data.feature_type == PostFeatureType::Community {
// Verify that only the mods can feature in community
is_mod_or_admin(
&mut context.pool(),
local_user_view.person.id,
orig_post.community_id,
)
.await?;
} else {
if data.feature_type == PostFeatureType::Local {
is_admin(&local_user_view)?;
}
@ -72,12 +64,17 @@ pub async fn feature_post(
ModFeaturePost::create(&mut context.pool(), &form).await?;
let person_id = local_user_view.person.id;
ActivityChannel::submit_activity(
SendActivityData::FeaturePost(post, local_user_view.person, data.featured),
SendActivityData::FeaturePost(post, local_user_view.person.clone(), data.featured),
&context,
)
.await?;
build_post_response(&context, orig_post.community_id, person_id, post_id).await
build_post_response(
&context,
orig_post.community_id,
&local_user_view.person,
post_id,
)
.await
}

View file

@ -5,12 +5,7 @@ use lemmy_api_common::{
context::LemmyContext,
post::{CreatePostLike, PostResponse},
send_activity::{ActivityChannel, SendActivityData},
utils::{
check_community_ban,
check_community_deleted_or_removed,
check_downvotes_enabled,
mark_post_as_read,
},
utils::{check_community_user_action, check_downvotes_enabled, mark_post_as_read},
};
use lemmy_db_schema::{
source::{
@ -39,13 +34,12 @@ pub async fn like_post(
let post_id = data.post_id;
let post = Post::read(&mut context.pool(), post_id).await?;
check_community_ban(
local_user_view.person.id,
check_community_user_action(
&local_user_view.person,
post.community_id,
&mut context.pool(),
)
.await?;
check_community_deleted_or_removed(post.community_id, &mut context.pool()).await?;
let like_form = PostLikeForm {
post_id: data.post_id,
@ -83,7 +77,7 @@ pub async fn like_post(
build_post_response(
context.deref(),
post.community_id,
local_user_view.person.id,
&local_user_view.person,
post_id,
)
.await

View file

@ -5,7 +5,7 @@ use lemmy_api_common::{
context::LemmyContext,
post::{LockPost, PostResponse},
send_activity::{ActivityChannel, SendActivityData},
utils::{check_community_ban, check_community_deleted_or_removed, is_mod_or_admin},
utils::check_community_mod_action,
};
use lemmy_db_schema::{
source::{
@ -26,21 +26,13 @@ pub async fn lock_post(
let post_id = data.post_id;
let orig_post = Post::read(&mut context.pool(), post_id).await?;
check_community_ban(
local_user_view.person.id,
check_community_mod_action(
&local_user_view.person,
orig_post.community_id,
false,
&mut context.pool(),
)
.await?;
check_community_deleted_or_removed(orig_post.community_id, &mut context.pool()).await?;
// Verify that only the mods can lock
is_mod_or_admin(
&mut context.pool(),
local_user_view.person.id,
orig_post.community_id,
)
.await?;
// Update the post
let post_id = data.post_id;
@ -63,12 +55,17 @@ pub async fn lock_post(
};
ModLockPost::create(&mut context.pool(), &form).await?;
let person_id = local_user_view.person.id;
ActivityChannel::submit_activity(
SendActivityData::LockPost(post, local_user_view.person, data.locked),
SendActivityData::LockPost(post, local_user_view.person.clone(), data.locked),
&context,
)
.await?;
build_post_response(&context, orig_post.community_id, person_id, post_id).await
build_post_response(
&context,
orig_post.community_id,
&local_user_view.person,
post_id,
)
.await
}

View file

@ -5,7 +5,7 @@ use lemmy_api_common::{
context::LemmyContext,
post::{CreatePostReport, PostReportResponse},
send_activity::{ActivityChannel, SendActivityData},
utils::{check_community_ban, send_new_report_email_to_admins},
utils::{check_community_user_action, send_new_report_email_to_admins},
};
use lemmy_db_schema::{
source::{
@ -33,7 +33,12 @@ pub async fn create_post_report(
let post_id = data.post_id;
let post_view = PostView::read(&mut context.pool(), post_id, None, false).await?;
check_community_ban(person_id, post_view.community.id, &mut context.pool()).await?;
check_community_user_action(
&local_user_view.person,
post_view.community.id,
&mut context.pool(),
)
.await?;
let report_form = PostReportForm {
creator_id: person_id,

View file

@ -2,6 +2,7 @@ use actix_web::web::{Data, Json, Query};
use lemmy_api_common::{
context::LemmyContext,
post::{ListPostReports, ListPostReportsResponse},
utils::check_community_mod_action_opt,
};
use lemmy_db_views::{post_report_view::PostReportQuery, structs::LocalUserView};
use lemmy_utils::error::LemmyError;
@ -17,6 +18,8 @@ pub async fn list_post_reports(
let community_id = data.community_id;
let unresolved_only = data.unresolved_only.unwrap_or_default();
check_community_mod_action_opt(&local_user_view, community_id, &mut context.pool()).await?;
let page = data.page;
let limit = data.limit;
let post_reports = PostReportQuery {

View file

@ -2,7 +2,7 @@ use actix_web::web::{Data, Json};
use lemmy_api_common::{
context::LemmyContext,
post::{PostReportResponse, ResolvePostReport},
utils::is_mod_or_admin,
utils::check_community_mod_action,
};
use lemmy_db_schema::{source::post_report::PostReport, traits::Reportable};
use lemmy_db_views::structs::{LocalUserView, PostReportView};
@ -20,7 +20,13 @@ pub async fn resolve_post_report(
let report = PostReportView::read(&mut context.pool(), report_id, person_id).await?;
let person_id = local_user_view.person.id;
is_mod_or_admin(&mut context.pool(), person_id, report.community.id).await?;
check_community_mod_action(
&local_user_view.person,
report.community.id,
false,
&mut context.pool(),
)
.await?;
if data.resolved {
PostReport::resolve(&mut context.pool(), report_id, person_id)

View file

@ -2,13 +2,9 @@ use actix_web::web::{Data, Json, Query};
use lemmy_api_common::{
context::LemmyContext,
site::{GetModlog, GetModlogResponse},
utils::{check_private_instance, is_admin, is_mod_or_admin},
};
use lemmy_db_schema::{
newtypes::{CommunityId, PersonId},
source::local_site::LocalSite,
ModlogActionType,
utils::{check_community_mod_action_opt, check_private_instance, is_admin},
};
use lemmy_db_schema::{source::local_site::LocalSite, ModlogActionType};
use lemmy_db_views::structs::LocalUserView;
use lemmy_db_views_moderator::structs::{
AdminPurgeCommentView,
@ -44,19 +40,16 @@ pub async fn get_mod_log(
let type_ = data.type_.unwrap_or(All);
let community_id = data.community_id;
let (local_person_id, is_admin) = match local_user_view {
Some(s) => (s.person.id, is_admin(&s).is_ok()),
None => (PersonId(-1), false),
};
let community_id_value = match community_id {
Some(s) => s,
None => CommunityId(-1),
};
let is_mod_of_community = data.community_id.is_some()
&& is_mod_or_admin(&mut context.pool(), local_person_id, community_id_value)
let is_mod_or_admin = if let Some(local_user_view) = local_user_view {
let is_mod = community_id.is_some()
&& check_community_mod_action_opt(&local_user_view, community_id, &mut context.pool())
.await
.is_ok();
let hide_modlog_names = local_site.hide_modlog_mod_names && !is_mod_of_community && !is_admin;
is_mod || is_admin(&local_user_view).is_ok()
} else {
false
};
let hide_modlog_names = local_site.hide_modlog_mod_names && !is_mod_or_admin;
let mod_person_id = if hide_modlog_names {
None

View file

@ -7,7 +7,7 @@ use crate::{
};
use actix_web::web::Json;
use lemmy_db_schema::{
newtypes::{CommentId, CommunityId, LocalUserId, PersonId, PostId},
newtypes::{CommentId, CommunityId, LocalUserId, PostId},
source::{
actor_language::CommunityLanguage,
comment::Comment,
@ -44,8 +44,7 @@ pub async fn build_community_response(
local_user_view: LocalUserView,
community_id: CommunityId,
) -> Result<Json<CommunityResponse>, LemmyError> {
let is_mod_or_admin =
is_mod_or_admin(&mut context.pool(), local_user_view.person.id, community_id)
let is_mod_or_admin = is_mod_or_admin(&mut context.pool(), &local_user_view.person, community_id)
.await
.is_ok();
let person_id = local_user_view.person.id;
@ -67,16 +66,16 @@ pub async fn build_community_response(
pub async fn build_post_response(
context: &LemmyContext,
community_id: CommunityId,
person_id: PersonId,
person: &Person,
post_id: PostId,
) -> Result<Json<PostResponse>, LemmyError> {
let is_mod_or_admin = is_mod_or_admin(&mut context.pool(), person_id, community_id)
let is_mod_or_admin = is_mod_or_admin(&mut context.pool(), person, community_id)
.await
.is_ok();
let post_view = PostView::read(
&mut context.pool(),
post_id,
Some(person_id),
Some(person.id),
is_mod_or_admin,
)
.await?;

View file

@ -6,9 +6,7 @@ use crate::{
};
use actix_web::cookie::{Cookie, SameSite};
use anyhow::Context;
use chrono::{DateTime, Utc};
use lemmy_db_schema::{
impls::person::is_banned,
newtypes::{CommunityId, DbUrl, PersonId, PostId},
source::{
comment::{Comment, CommentUpdateForm},
@ -33,7 +31,7 @@ use lemmy_db_views_actor::structs::{
};
use lemmy_utils::{
email::{send_email, translations::Lang},
error::{LemmyError, LemmyErrorExt, LemmyErrorType},
error::{LemmyError, LemmyErrorExt, LemmyErrorType, LemmyResult},
location_info,
rate_limit::RateLimitConfig,
settings::structs::Settings,
@ -49,10 +47,12 @@ pub static AUTH_COOKIE_NAME: &str = "auth";
#[tracing::instrument(skip_all)]
pub async fn is_mod_or_admin(
pool: &mut DbPool<'_>,
person_id: PersonId,
person: &Person,
community_id: CommunityId,
) -> Result<(), LemmyError> {
let is_mod_or_admin = CommunityView::is_mod_or_admin(pool, person_id, community_id).await?;
check_user_valid(person)?;
let is_mod_or_admin = CommunityView::is_mod_or_admin(pool, person.id, community_id).await?;
if !is_mod_or_admin {
Err(LemmyErrorType::NotAModOrAdmin)?
} else {
@ -68,7 +68,7 @@ pub async fn is_mod_or_admin_opt(
) -> Result<(), LemmyError> {
if let Some(local_user_view) = local_user_view {
if let Some(community_id) = community_id {
is_mod_or_admin(pool, local_user_view.person.id, community_id).await
is_mod_or_admin(pool, &local_user_view.person, community_id).await
} else {
is_admin(local_user_view)
}
@ -78,8 +78,11 @@ pub async fn is_mod_or_admin_opt(
}
pub fn is_admin(local_user_view: &LocalUserView) -> Result<(), LemmyError> {
check_user_valid(&local_user_view.person)?;
if !local_user_view.local_user.admin {
Err(LemmyErrorType::NotAnAdmin)?
} else if local_user_view.person.banned {
Err(LemmyErrorType::Banned)?
} else {
Ok(())
}
@ -89,6 +92,7 @@ pub fn is_top_mod(
local_user_view: &LocalUserView,
community_mods: &[CommunityModeratorView],
) -> Result<(), LemmyError> {
check_user_valid(&local_user_view.person)?;
if local_user_view.person.id
!= community_mods
.first()
@ -134,52 +138,91 @@ pub async fn mark_post_as_unread(
.with_lemmy_type(LemmyErrorType::CouldntMarkPostAsRead)
}
pub fn check_user_valid(
banned: bool,
ban_expires: Option<DateTime<Utc>>,
deleted: bool,
) -> Result<(), LemmyError> {
pub fn check_user_valid(person: &Person) -> Result<(), LemmyError> {
// Check for a site ban
if is_banned(banned, ban_expires) {
if person.banned {
Err(LemmyErrorType::SiteBan)?
}
// check for account deletion
else if deleted {
else if person.deleted {
Err(LemmyErrorType::Deleted)?
} else {
Ok(())
}
}
#[tracing::instrument(skip_all)]
pub async fn check_community_ban(
person_id: PersonId,
/// Checks that a normal user action (eg posting or voting) is allowed in a given community.
///
/// In particular it checks that neither the user nor community are banned or deleted, and that
/// the user isn't banned.
pub async fn check_community_user_action(
person: &Person,
community_id: CommunityId,
pool: &mut DbPool<'_>,
) -> Result<(), LemmyError> {
let is_banned = CommunityPersonBanView::get(pool, person_id, community_id)
.await
.is_ok();
if is_banned {
Err(LemmyErrorType::BannedFromCommunity)?
} else {
) -> LemmyResult<()> {
check_user_valid(person)?;
check_community_deleted_removed(community_id, pool).await?;
check_community_ban(person, community_id, pool).await?;
Ok(())
}
}
#[tracing::instrument(skip_all)]
pub async fn check_community_deleted_or_removed(
async fn check_community_deleted_removed(
community_id: CommunityId,
pool: &mut DbPool<'_>,
) -> Result<(), LemmyError> {
) -> LemmyResult<()> {
let community = Community::read(pool, community_id)
.await
.with_lemmy_type(LemmyErrorType::CouldntFindCommunity)?;
if community.deleted || community.removed {
Err(LemmyErrorType::Deleted)?
} else {
}
Ok(())
}
async fn check_community_ban(
person: &Person,
community_id: CommunityId,
pool: &mut DbPool<'_>,
) -> LemmyResult<()> {
// check if user was banned from site or community
let is_banned = CommunityPersonBanView::get(pool, person.id, community_id).await?;
if is_banned {
Err(LemmyErrorType::BannedFromCommunity)?
}
Ok(())
}
/// Check that the given user can perform a mod action in the community.
///
/// In particular it checks that he is an admin or mod, wasn't banned and the community isn't
/// removed/deleted.
pub async fn check_community_mod_action(
person: &Person,
community_id: CommunityId,
allow_deleted: bool,
pool: &mut DbPool<'_>,
) -> LemmyResult<()> {
is_mod_or_admin(pool, person, community_id).await?;
check_community_ban(person, community_id, pool).await?;
// it must be possible to restore deleted community
if !allow_deleted {
check_community_deleted_removed(community_id, pool).await?;
}
Ok(())
}
pub async fn check_community_mod_action_opt(
local_user_view: &LocalUserView,
community_id: Option<CommunityId>,
pool: &mut DbPool<'_>,
) -> LemmyResult<()> {
if let Some(community_id) = community_id {
check_community_mod_action(&local_user_view.person, community_id, false, pool).await?;
} else {
is_admin(local_user_view)?;
}
Ok(())
}
pub fn check_post_deleted_or_removed(post: &Post) -> Result<(), LemmyError> {

View file

@ -6,8 +6,7 @@ use lemmy_api_common::{
context::LemmyContext,
send_activity::{ActivityChannel, SendActivityData},
utils::{
check_community_ban,
check_community_deleted_or_removed,
check_community_user_action,
check_post_deleted_or_removed,
generate_local_apub_endpoint,
get_post,
@ -57,8 +56,7 @@ pub async fn create_comment(
let post = get_post(post_id, &mut context.pool()).await?;
let community_id = post.community_id;
check_community_ban(local_user_view.person.id, community_id, &mut context.pool()).await?;
check_community_deleted_or_removed(community_id, &mut context.pool()).await?;
check_community_user_action(&local_user_view.person, community_id, &mut context.pool()).await?;
check_post_deleted_or_removed(&post)?;
// Check if post is locked, no new comments

View file

@ -5,7 +5,7 @@ use lemmy_api_common::{
comment::{CommentResponse, DeleteComment},
context::LemmyContext,
send_activity::{ActivityChannel, SendActivityData},
utils::check_community_ban,
utils::check_community_user_action,
};
use lemmy_db_schema::{
source::{
@ -31,8 +31,8 @@ pub async fn delete_comment(
Err(LemmyErrorType::CouldntUpdateComment)?
}
check_community_ban(
local_user_view.person.id,
check_community_user_action(
&local_user_view.person,
orig_comment.community.id,
&mut context.pool(),
)

View file

@ -5,7 +5,7 @@ use lemmy_api_common::{
comment::{CommentResponse, RemoveComment},
context::LemmyContext,
send_activity::{ActivityChannel, SendActivityData},
utils::{check_community_ban, is_mod_or_admin},
utils::check_community_mod_action,
};
use lemmy_db_schema::{
source::{
@ -27,21 +27,14 @@ pub async fn remove_comment(
let comment_id = data.comment_id;
let orig_comment = CommentView::read(&mut context.pool(), comment_id, None).await?;
check_community_ban(
local_user_view.person.id,
check_community_mod_action(
&local_user_view.person,
orig_comment.community.id,
false,
&mut context.pool(),
)
.await?;
// Verify that only a mod or admin can remove
is_mod_or_admin(
&mut context.pool(),
local_user_view.person.id,
orig_comment.community.id,
)
.await?;
// Do the remove
let removed = data.removed;
let updated_comment = Comment::update(

View file

@ -5,7 +5,7 @@ use lemmy_api_common::{
comment::{CommentResponse, EditComment},
context::LemmyContext,
send_activity::{ActivityChannel, SendActivityData},
utils::{check_community_ban, local_site_to_slur_regex},
utils::{check_community_user_action, local_site_to_slur_regex},
};
use lemmy_db_schema::{
source::{
@ -37,8 +37,8 @@ pub async fn update_comment(
let comment_id = data.comment_id;
let orig_comment = CommentView::read(&mut context.pool(), comment_id, None).await?;
check_community_ban(
local_user_view.person.id,
check_community_user_action(
&local_user_view.person,
orig_comment.community.id,
&mut context.pool(),
)

View file

@ -5,7 +5,7 @@ use lemmy_api_common::{
community::{CommunityResponse, DeleteCommunity},
context::LemmyContext,
send_activity::{ActivityChannel, SendActivityData},
utils::is_top_mod,
utils::{check_community_mod_action, is_top_mod},
};
use lemmy_db_schema::{
source::community::{Community, CommunityUpdateForm},
@ -26,6 +26,14 @@ pub async fn delete_community(
let community_mods =
CommunityModeratorView::for_community(&mut context.pool(), community_id).await?;
check_community_mod_action(
&local_user_view.person,
community_id,
true,
&mut context.pool(),
)
.await?;
// Make sure deleter is the top mod
is_top_mod(&local_user_view, &community_mods)?;

View file

@ -5,7 +5,7 @@ use lemmy_api_common::{
community::{CommunityResponse, RemoveCommunity},
context::LemmyContext,
send_activity::{ActivityChannel, SendActivityData},
utils::is_admin,
utils::{check_community_mod_action, is_admin},
};
use lemmy_db_schema::{
source::{
@ -26,6 +26,14 @@ pub async fn remove_community(
context: Data<LemmyContext>,
local_user_view: LocalUserView,
) -> Result<Json<CommunityResponse>, LemmyError> {
check_community_mod_action(
&local_user_view.person,
data.community_id,
true,
&mut context.pool(),
)
.await?;
// Verify its an admin (only an admin can remove a community)
is_admin(&local_user_view)?;

View file

@ -5,10 +5,9 @@ use lemmy_api_common::{
community::{CommunityResponse, EditCommunity},
context::LemmyContext,
send_activity::{ActivityChannel, SendActivityData},
utils::local_site_to_slur_regex,
utils::{check_community_mod_action, local_site_to_slur_regex},
};
use lemmy_db_schema::{
newtypes::PersonId,
source::{
actor_language::{CommunityLanguage, SiteLanguage},
community::{Community, CommunityUpdateForm},
@ -18,7 +17,6 @@ use lemmy_db_schema::{
utils::{diesel_option_overwrite, diesel_option_overwrite_to_url, naive_now},
};
use lemmy_db_views::structs::LocalUserView;
use lemmy_db_views_actor::structs::CommunityModeratorView;
use lemmy_utils::{
error::{LemmyError, LemmyErrorExt, LemmyErrorType},
utils::{slurs::check_slurs_opt, validation::is_valid_body_field},
@ -42,14 +40,13 @@ pub async fn update_community(
let description = diesel_option_overwrite(data.description.clone());
// Verify its a mod (only mods can edit it)
let community_id = data.community_id;
let mods: Vec<PersonId> =
CommunityModeratorView::for_community(&mut context.pool(), community_id)
.await
.map(|v| v.into_iter().map(|m| m.moderator.id).collect())?;
if !mods.contains(&local_user_view.person.id) {
Err(LemmyErrorType::NotAModerator)?
}
check_community_mod_action(
&local_user_view.person,
data.community_id,
false,
&mut context.pool(),
)
.await?;
let community_id = data.community_id;
if let Some(languages) = data.discussion_languages.clone() {

View file

@ -7,8 +7,7 @@ use lemmy_api_common::{
request::fetch_site_data,
send_activity::{ActivityChannel, SendActivityData},
utils::{
check_community_ban,
check_community_deleted_or_removed,
check_community_user_action,
generate_local_apub_endpoint,
honeypot_check,
local_site_to_slur_regex,
@ -60,13 +59,12 @@ pub async fn create_post(
is_valid_body_field(&data.body, true)?;
check_url_scheme(&data.url)?;
check_community_ban(
local_user_view.person.id,
check_community_user_action(
&local_user_view.person,
data.community_id,
&mut context.pool(),
)
.await?;
check_community_deleted_or_removed(data.community_id, &mut context.pool()).await?;
let community_id = data.community_id;
let community = Community::read(&mut context.pool(), community_id).await?;
@ -184,5 +182,5 @@ pub async fn create_post(
});
};
build_post_response(&context, community_id, person_id, post_id).await
build_post_response(&context, community_id, &local_user_view.person, post_id).await
}

View file

@ -5,7 +5,7 @@ use lemmy_api_common::{
context::LemmyContext,
post::{DeletePost, PostResponse},
send_activity::{ActivityChannel, SendActivityData},
utils::{check_community_ban, check_community_deleted_or_removed},
utils::check_community_user_action,
};
use lemmy_db_schema::{
source::post::{Post, PostUpdateForm},
@ -28,13 +28,12 @@ pub async fn delete_post(
Err(LemmyErrorType::CouldntUpdatePost)?
}
check_community_ban(
local_user_view.person.id,
check_community_user_action(
&local_user_view.person,
orig_post.community_id,
&mut context.pool(),
)
.await?;
check_community_deleted_or_removed(orig_post.community_id, &mut context.pool()).await?;
// Verify that only the creator can delete
if !Post::is_post_creator(local_user_view.person.id, orig_post.creator_id) {
@ -52,12 +51,17 @@ pub async fn delete_post(
)
.await?;
let person_id = local_user_view.person.id;
ActivityChannel::submit_activity(
SendActivityData::DeletePost(post, local_user_view.person, data.0.clone()),
SendActivityData::DeletePost(post, local_user_view.person.clone(), data.0.clone()),
&context,
)
.await?;
build_post_response(&context, orig_post.community_id, person_id, data.post_id).await
build_post_response(
&context,
orig_post.community_id,
&local_user_view.person,
data.post_id,
)
.await
}

View file

@ -5,7 +5,7 @@ use lemmy_api_common::{
context::LemmyContext,
post::{PostResponse, RemovePost},
send_activity::{ActivityChannel, SendActivityData},
utils::{check_community_ban, is_mod_or_admin},
utils::check_community_mod_action,
};
use lemmy_db_schema::{
source::{
@ -26,21 +26,14 @@ pub async fn remove_post(
let post_id = data.post_id;
let orig_post = Post::read(&mut context.pool(), post_id).await?;
check_community_ban(
local_user_view.person.id,
check_community_mod_action(
&local_user_view.person,
orig_post.community_id,
false,
&mut context.pool(),
)
.await?;
// Verify that only the mods can remove
is_mod_or_admin(
&mut context.pool(),
local_user_view.person.id,
orig_post.community_id,
)
.await?;
// Update the post
let post_id = data.post_id;
let removed = data.removed;
@ -63,12 +56,17 @@ pub async fn remove_post(
};
ModRemovePost::create(&mut context.pool(), &form).await?;
let person_id = local_user_view.person.id;
ActivityChannel::submit_activity(
SendActivityData::RemovePost(post, local_user_view.person, data.0),
SendActivityData::RemovePost(post, local_user_view.person.clone(), data.0),
&context,
)
.await?;
build_post_response(&context, orig_post.community_id, person_id, post_id).await
build_post_response(
&context,
orig_post.community_id,
&local_user_view.person,
post_id,
)
.await
}

View file

@ -6,7 +6,7 @@ use lemmy_api_common::{
post::{EditPost, PostResponse},
request::fetch_site_data,
send_activity::{ActivityChannel, SendActivityData},
utils::{check_community_ban, local_site_to_slur_regex},
utils::{check_community_user_action, local_site_to_slur_regex},
};
use lemmy_db_schema::{
source::{
@ -55,8 +55,8 @@ pub async fn update_post(
let post_id = data.post_id;
let orig_post = Post::read(&mut context.pool(), post_id).await?;
check_community_ban(
local_user_view.person.id,
check_community_user_action(
&local_user_view.person,
orig_post.community_id,
&mut context.pool(),
)
@ -107,7 +107,7 @@ pub async fn update_post(
build_post_response(
context.deref(),
orig_post.community_id,
local_user_view.person.id,
&local_user_view.person,
post_id,
)
.await

View file

@ -140,7 +140,7 @@ impl ActivityHandler for CreateOrUpdateNote {
if distinguished != existing_comment.distinguished {
let creator = self.actor.dereference(context).await?;
let (post, _) = self.object.get_parents(context).await?;
is_mod_or_admin(&mut context.pool(), creator.id, post.community_id).await?;
is_mod_or_admin(&mut context.pool(), &creator, post.community_id).await?;
}
}

View file

@ -92,9 +92,7 @@ pub(crate) async fn verify_person_in_community(
}
let person_id = person.id;
let community_id = community.id;
let is_banned = CommunityPersonBanView::get(&mut context.pool(), person_id, community_id)
.await
.is_ok();
let is_banned = CommunityPersonBanView::get(&mut context.pool(), person_id, community_id).await?;
if is_banned {
Err(LemmyErrorType::PersonIsBannedFromCommunity)?
} else {

View file

@ -166,7 +166,7 @@ impl Object for ApubPost {
let creator = page.creator()?.dereference(context).await?;
let community = page.community(context).await?;
if community.posting_restricted_to_mods {
is_mod_or_admin(&mut context.pool(), creator.id, community.id).await?;
is_mod_or_admin(&mut context.pool(), &creator, community.id).await?;
}
let mut name = page
.name

View file

@ -11,7 +11,6 @@ use crate::{
traits::{ApubActor, Crud, Followable},
utils::{functions::lower, get_conn, naive_now, DbPool},
};
use chrono::{DateTime, Utc};
use diesel::{dsl::insert_into, result::Error, ExpressionMethods, JoinOnDsl, QueryDsl};
use diesel_async::RunQueryDsl;
@ -87,14 +86,6 @@ impl Person {
}
}
pub fn is_banned(banned_: bool, expires: Option<DateTime<Utc>>) -> bool {
if let Some(expires) = expires {
banned_ && expires.gt(&naive_now())
} else {
banned_
}
}
#[async_trait]
impl ApubActor for Person {
async fn read_from_apub_id(

View file

@ -1,9 +1,9 @@
use crate::structs::CommunityPersonBanView;
use diesel::{result::Error, ExpressionMethods, QueryDsl};
use diesel::{dsl::exists, result::Error, select, ExpressionMethods, QueryDsl};
use diesel_async::RunQueryDsl;
use lemmy_db_schema::{
newtypes::{CommunityId, PersonId},
schema::{community, community_person_ban, person},
schema::community_person_ban,
utils::{get_conn, DbPool},
};
@ -12,16 +12,14 @@ impl CommunityPersonBanView {
pool: &mut DbPool<'_>,
from_person_id: PersonId,
from_community_id: CommunityId,
) -> Result<Self, Error> {
) -> Result<bool, Error> {
let conn = &mut get_conn(pool).await?;
select(exists(
community_person_ban::table
.inner_join(community::table)
.inner_join(person::table)
.select((community::all_columns, person::all_columns))
.filter(community_person_ban::community_id.eq(from_community_id))
.filter(community_person_ban::person_id.eq(from_person_id))
.order_by(community_person_ban::published)
.first::<CommunityPersonBanView>(conn)
.filter(community_person_ban::person_id.eq(from_person_id)),
))
.get_result::<bool>(conn)
.await
}
}

View file

@ -14,11 +14,7 @@ async fn local_user_view_from_jwt(
) -> Result<LocalUserView, LemmyError> {
let local_user_id = Claims::validate(jwt, context).await?;
let local_user_view = LocalUserView::read(&mut context.pool(), local_user_id).await?;
check_user_valid(
local_user_view.person.banned,
local_user_view.person.ban_expires,
local_user_view.person.deleted,
)?;
check_user_valid(&local_user_view.person)?;
Ok(local_user_view)
}

View file

@ -109,11 +109,7 @@ async fn local_user_view_from_jwt(
.await
.with_lemmy_type(LemmyErrorType::NotLoggedIn)?;
let local_user_view = LocalUserView::read(&mut context.pool(), local_user_id).await?;
check_user_valid(
local_user_view.person.banned,
local_user_view.person.ban_expires,
local_user_view.person.deleted,
)?;
check_user_valid(&local_user_view.person)?;
Ok(local_user_view)
}