mirror of
https://github.com/LemmyNet/lemmy.git
synced 2025-04-09 12:34:06 +00:00
* Receive and store remote site bans (fixes #3399) * db schema changes, handly expiration * partial federation changes * add column `mod_ban.instance_id` * remove unused * wip: remove person.banned * fix down migration * fmt, keep banned status * fixes * simplify * update post removed * fix api tests * ban from local instance * banned() helpers * cleanup undo_block_user * remove order by * cache SiteView::read_local, add instance * use local instance id for PersonView * add helper function person_with_instance_actions * use exists * comments update removed * remove method is_mod_or_admin * fix tests * no unwrap * change local_instance_person_join * remove LocalSite::read * wip: home_instance_actions * add home_instance_actions to all structs * fixes * fix tests * fmt --------- Co-authored-by: Dessalines <dessalines@users.noreply.github.com>
This commit is contained in:
parent
e079a41308
commit
636811eb8e
102 changed files with 2822 additions and 4104 deletions
|
@ -29,7 +29,7 @@
|
|||
"eslint": "^9.20.0",
|
||||
"eslint-plugin-prettier": "^5.2.3",
|
||||
"jest": "^29.5.0",
|
||||
"lemmy-js-client": "1.0.0-action-structs.1",
|
||||
"lemmy-js-client": "1.0.0-site-person-ban.1",
|
||||
"prettier": "^3.5.0",
|
||||
"ts-jest": "^29.1.0",
|
||||
"tsoa": "^6.6.0",
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -40,6 +40,7 @@ import {
|
|||
getMyUser,
|
||||
listInbox,
|
||||
getModlog,
|
||||
getCommunity,
|
||||
} from "./shared";
|
||||
import { PostView } from "lemmy-js-client/dist/types/PostView";
|
||||
import { AdminBlockInstanceParams } from "lemmy-js-client/dist/types/AdminBlockInstanceParams";
|
||||
|
@ -461,7 +462,7 @@ test("Search for a post", async () => {
|
|||
expect(betaPost?.post.name).toBeDefined();
|
||||
});
|
||||
|
||||
test("Enforce site ban federation for local user", async () => {
|
||||
test.only("Enforce site ban federation for local user", async () => {
|
||||
if (!betaCommunity) {
|
||||
throw "Missing beta community";
|
||||
}
|
||||
|
@ -499,9 +500,11 @@ test("Enforce site ban federation for local user", async () => {
|
|||
// alpha ban should be federated to beta
|
||||
let alphaUserOnBeta1 = await waitUntil(
|
||||
() => resolvePerson(beta, alphaUserActorId!),
|
||||
res => res.person?.person.banned ?? false,
|
||||
res => res.person?.home_instance_actions?.received_ban != null,
|
||||
);
|
||||
expect(alphaUserOnBeta1.person?.person.banned).toBe(true);
|
||||
expect(
|
||||
alphaUserOnBeta1.person?.home_instance_actions?.received_ban,
|
||||
).toBeDefined();
|
||||
|
||||
// existing alpha post should be removed on beta
|
||||
let betaBanRes = await waitUntil(
|
||||
|
@ -557,7 +560,9 @@ test("Enforce site ban federation for federated user", async () => {
|
|||
await followBeta(alphaUserHttp);
|
||||
|
||||
let alphaUserOnBeta2 = await resolvePerson(beta, alphaUserActorId!);
|
||||
expect(alphaUserOnBeta2.person?.person.banned).toBe(false);
|
||||
expect(
|
||||
alphaUserOnBeta2.person?.instance_actions?.received_ban,
|
||||
).toBeUndefined();
|
||||
|
||||
if (!alphaUserOnBeta2.person) {
|
||||
throw "Missing alpha person";
|
||||
|
@ -577,29 +582,35 @@ test("Enforce site ban federation for federated user", async () => {
|
|||
);
|
||||
expect(banAlphaOnBeta.banned).toBe(true);
|
||||
|
||||
// The beta site ban should NOT be federated to alpha
|
||||
let alphaPerson2 = (await getMyUser(alphaUserHttp)).local_user_view.person;
|
||||
expect(alphaPerson2.banned).toBe(false);
|
||||
|
||||
// existing alpha post should be removed on beta
|
||||
let betaBanRes = await waitUntil(
|
||||
() => getPost(beta, searchBeta1.post.id),
|
||||
s => s.post_view.post.removed,
|
||||
);
|
||||
expect(betaBanRes.post_view.post.removed).toBe(true);
|
||||
let betaRemovedPost = await getPost(beta, searchBeta1.post.id);
|
||||
expect(betaRemovedPost.post_view.post.removed).toBe(true);
|
||||
|
||||
// existing alpha's post to the beta community should be removed on alpha
|
||||
let alphaPostAfterRemoveOnBeta = await waitUntil(
|
||||
// post should also be removed on alpha
|
||||
let alphaRemovedPost = await waitUntil(
|
||||
() => getPost(alpha, postRes1.post_view.post.id),
|
||||
s => s.post_view.post.removed,
|
||||
);
|
||||
expect(betaBanRes.post_view.post.removed).toBe(true);
|
||||
expect(alphaPostAfterRemoveOnBeta.post_view.post.removed).toBe(true);
|
||||
expect(alphaRemovedPost.post_view.post.removed).toBe(true);
|
||||
|
||||
// User should not be shown to be banned from alpha
|
||||
let alphaPerson2 = (await getMyUser(alphaUserHttp)).local_user_view;
|
||||
expect(alphaPerson2.instance_actions?.received_ban).toBeUndefined();
|
||||
|
||||
// but the ban should be indicated by beta community on alpha
|
||||
let communityWithBan = await getCommunity(
|
||||
alphaUserHttp,
|
||||
betaCommunity.community.id,
|
||||
);
|
||||
expect(
|
||||
alphaPostAfterRemoveOnBeta.post_view.creator_community_actions
|
||||
?.received_ban,
|
||||
communityWithBan.community_view.instance_actions?.received_ban,
|
||||
).toBeDefined();
|
||||
|
||||
// post to beta community is rejected
|
||||
await expect(
|
||||
createPost(alphaUserHttp, betaCommunity.community.id),
|
||||
).rejects.toStrictEqual(Error("site_ban"));
|
||||
|
||||
await unfollowRemotes(alpha);
|
||||
});
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ pub async fn distinguish_comment(
|
|||
.await?;
|
||||
|
||||
check_community_user_action(
|
||||
&local_user_view.person,
|
||||
&local_user_view,
|
||||
&orig_comment.community,
|
||||
&mut context.pool(),
|
||||
)
|
||||
|
@ -37,7 +37,7 @@ pub async fn distinguish_comment(
|
|||
|
||||
// Verify that only a mod or admin can distinguish a comment
|
||||
check_community_mod_action(
|
||||
&local_user_view.person,
|
||||
&local_user_view,
|
||||
&orig_comment.community,
|
||||
false,
|
||||
&mut context.pool(),
|
||||
|
|
|
@ -13,11 +13,10 @@ use lemmy_db_schema::{
|
|||
source::{
|
||||
comment::{CommentActions, CommentLikeForm},
|
||||
comment_reply::CommentReply,
|
||||
local_site::LocalSite,
|
||||
},
|
||||
traits::Likeable,
|
||||
};
|
||||
use lemmy_db_views::structs::{CommentView, LocalUserView};
|
||||
use lemmy_db_views::structs::{CommentView, LocalUserView, SiteView};
|
||||
use lemmy_utils::error::LemmyResult;
|
||||
use std::ops::Deref;
|
||||
|
||||
|
@ -26,7 +25,7 @@ pub async fn like_comment(
|
|||
context: Data<LemmyContext>,
|
||||
local_user_view: LocalUserView,
|
||||
) -> LemmyResult<Json<CommentResponse>> {
|
||||
let local_site = LocalSite::read(&mut context.pool()).await?;
|
||||
let local_site = SiteView::read_local(&mut context.pool()).await?.local_site;
|
||||
let comment_id = data.comment_id;
|
||||
|
||||
let mut recipient_ids = Vec::<LocalUserId>::new();
|
||||
|
@ -49,7 +48,7 @@ pub async fn like_comment(
|
|||
.await?;
|
||||
|
||||
check_community_user_action(
|
||||
&local_user_view.person,
|
||||
&local_user_view,
|
||||
&orig_comment.community,
|
||||
&mut context.pool(),
|
||||
)
|
||||
|
|
|
@ -22,7 +22,7 @@ pub async fn list_comment_likes(
|
|||
|
||||
is_mod_or_admin(
|
||||
&mut context.pool(),
|
||||
&local_user_view.person,
|
||||
&local_user_view,
|
||||
comment_view.community.id,
|
||||
)
|
||||
.await?;
|
||||
|
|
|
@ -24,13 +24,7 @@ pub async fn add_mod_to_community(
|
|||
) -> LemmyResult<Json<AddModToCommunityResponse>> {
|
||||
let community = Community::read(&mut context.pool(), data.community_id).await?;
|
||||
// Verify that only mods or admins can add mod
|
||||
check_community_mod_action(
|
||||
&local_user_view.person,
|
||||
&community,
|
||||
false,
|
||||
&mut context.pool(),
|
||||
)
|
||||
.await?;
|
||||
check_community_mod_action(&local_user_view, &community, false, &mut context.pool()).await?;
|
||||
|
||||
// If its a mod removal, also check that you're a higher mod.
|
||||
if !data.added {
|
||||
|
|
|
@ -31,13 +31,7 @@ pub async fn ban_from_community(
|
|||
let community = Community::read(&mut context.pool(), data.community_id).await?;
|
||||
|
||||
// Verify that only mods or admins can ban
|
||||
check_community_mod_action(
|
||||
&local_user_view.person,
|
||||
&community,
|
||||
false,
|
||||
&mut context.pool(),
|
||||
)
|
||||
.await?;
|
||||
check_community_mod_action(&local_user_view, &community, false, &mut context.pool()).await?;
|
||||
|
||||
LocalUser::is_higher_mod_or_admin_check(
|
||||
&mut context.pool(),
|
||||
|
|
|
@ -4,7 +4,7 @@ use lemmy_api_common::{
|
|||
community::{CommunityResponse, FollowCommunity},
|
||||
context::LemmyContext,
|
||||
send_activity::{ActivityChannel, SendActivityData},
|
||||
utils::{check_community_deleted_removed, check_user_valid},
|
||||
utils::{check_community_deleted_removed, check_local_user_valid},
|
||||
};
|
||||
use lemmy_db_schema::{
|
||||
source::{
|
||||
|
@ -22,7 +22,7 @@ pub async fn follow_community(
|
|||
context: Data<LemmyContext>,
|
||||
local_user_view: LocalUserView,
|
||||
) -> LemmyResult<Json<CommunityResponse>> {
|
||||
check_user_valid(&local_user_view.person)?;
|
||||
check_local_user_valid(&local_user_view)?;
|
||||
let community = Community::read(&mut context.pool(), data.community_id).await?;
|
||||
let person_id = local_user_view.person.id;
|
||||
|
||||
|
|
|
@ -16,12 +16,7 @@ pub async fn post_pending_follows_approve(
|
|||
context: Data<LemmyContext>,
|
||||
local_user_view: LocalUserView,
|
||||
) -> LemmyResult<Json<SuccessResponse>> {
|
||||
is_mod_or_admin(
|
||||
&mut context.pool(),
|
||||
&local_user_view.person,
|
||||
data.community_id,
|
||||
)
|
||||
.await?;
|
||||
is_mod_or_admin(&mut context.pool(), &local_user_view, data.community_id).await?;
|
||||
|
||||
let activity_data = if data.approve {
|
||||
CommunityActions::approve_follower(
|
||||
|
|
|
@ -12,12 +12,7 @@ pub async fn get_pending_follows_count(
|
|||
context: Data<LemmyContext>,
|
||||
local_user_view: LocalUserView,
|
||||
) -> LemmyResult<Json<GetCommunityPendingFollowsCountResponse>> {
|
||||
is_mod_or_admin(
|
||||
&mut context.pool(),
|
||||
&local_user_view.person,
|
||||
data.community_id,
|
||||
)
|
||||
.await?;
|
||||
is_mod_or_admin(&mut context.pool(), &local_user_view, data.community_id).await?;
|
||||
let count =
|
||||
CommunityFollowerView::count_approval_required(&mut context.pool(), data.community_id).await?;
|
||||
Ok(Json(GetCommunityPendingFollowsCountResponse { count }))
|
||||
|
|
|
@ -5,12 +5,8 @@ use lemmy_api_common::{
|
|||
context::LemmyContext,
|
||||
utils::{check_private_instance, is_mod_or_admin_opt},
|
||||
};
|
||||
use lemmy_db_schema::source::{
|
||||
actor_language::CommunityLanguage,
|
||||
community::Community,
|
||||
local_site::LocalSite,
|
||||
};
|
||||
use lemmy_db_views::structs::{CommunityView, LocalUserView};
|
||||
use lemmy_db_schema::source::{actor_language::CommunityLanguage, community::Community};
|
||||
use lemmy_db_views::structs::{CommunityView, LocalUserView, SiteView};
|
||||
use lemmy_utils::error::LemmyResult;
|
||||
|
||||
pub async fn get_random_community(
|
||||
|
@ -18,7 +14,7 @@ pub async fn get_random_community(
|
|||
context: Data<LemmyContext>,
|
||||
local_user_view: Option<LocalUserView>,
|
||||
) -> LemmyResult<Json<CommunityResponse>> {
|
||||
let local_site = LocalSite::read(&mut context.pool()).await?;
|
||||
let local_site = SiteView::read_local(&mut context.pool()).await?.local_site;
|
||||
|
||||
check_private_instance(&local_user_view, &local_site)?;
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ pub async fn transfer_community(
|
|||
let mut community_mods =
|
||||
CommunityModeratorView::for_community(&mut context.pool(), community.id).await?;
|
||||
|
||||
check_community_user_action(&local_user_view.person, &community, &mut context.pool()).await?;
|
||||
check_community_user_action(&local_user_view, &community, &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())
|
||||
|
|
|
@ -1,20 +1,5 @@
|
|||
use activitypub_federation::config::Data;
|
||||
use base64::{engine::general_purpose::STANDARD_NO_PAD as base64, Engine};
|
||||
use captcha::Captcha;
|
||||
use lemmy_api_common::{
|
||||
community::BanFromCommunity,
|
||||
context::LemmyContext,
|
||||
send_activity::{ActivityChannel, SendActivityData},
|
||||
utils::check_expire_time,
|
||||
};
|
||||
use lemmy_db_schema::{
|
||||
source::{
|
||||
community::{CommunityActions, CommunityPersonBanForm},
|
||||
mod_log::moderator::{ModBanFromCommunity, ModBanFromCommunityForm},
|
||||
person::Person,
|
||||
},
|
||||
traits::{Bannable, Crud, Followable},
|
||||
};
|
||||
use lemmy_db_views::structs::LocalUserView;
|
||||
use lemmy_utils::{
|
||||
error::{LemmyErrorExt, LemmyErrorType, LemmyResult},
|
||||
|
@ -132,89 +117,6 @@ fn build_totp_2fa(hostname: &str, username: &str, secret: &str) -> LemmyResult<T
|
|||
.with_lemmy_type(LemmyErrorType::CouldntGenerateTotp)
|
||||
}
|
||||
|
||||
/// Site bans are only federated for local users.
|
||||
/// This is a problem, because site-banning non-local users will still leave content
|
||||
/// they've posted to our local communities, on other servers.
|
||||
///
|
||||
/// So when doing a site ban for a non-local user, you need to federate/send a
|
||||
/// community ban for every local community they've participated in.
|
||||
/// See https://github.com/LemmyNet/lemmy/issues/4118
|
||||
pub(crate) async fn ban_nonlocal_user_from_local_communities(
|
||||
local_user_view: &LocalUserView,
|
||||
target: &Person,
|
||||
ban: bool,
|
||||
reason: &Option<String>,
|
||||
remove_or_restore_data: &Option<bool>,
|
||||
expires: &Option<i64>,
|
||||
context: &Data<LemmyContext>,
|
||||
) -> LemmyResult<()> {
|
||||
// Only run this code for federated users
|
||||
if !target.local {
|
||||
let ids = Person::list_local_community_ids(&mut context.pool(), target.id).await?;
|
||||
|
||||
for community_id in ids {
|
||||
let expires_dt = check_expire_time(*expires)?;
|
||||
|
||||
// Ban / unban them from our local communities
|
||||
let community_user_ban_form = CommunityPersonBanForm {
|
||||
ban_expires: Some(expires_dt),
|
||||
..CommunityPersonBanForm::new(community_id, target.id)
|
||||
};
|
||||
|
||||
if ban {
|
||||
// Ignore all errors for these
|
||||
CommunityActions::ban(&mut context.pool(), &community_user_ban_form)
|
||||
.await
|
||||
.ok();
|
||||
|
||||
// Also unsubscribe them from the community, if they are subscribed
|
||||
|
||||
CommunityActions::unfollow(&mut context.pool(), target.id, community_id)
|
||||
.await
|
||||
.ok();
|
||||
} else {
|
||||
CommunityActions::unban(&mut context.pool(), &community_user_ban_form)
|
||||
.await
|
||||
.ok();
|
||||
}
|
||||
|
||||
// Mod tables
|
||||
let form = ModBanFromCommunityForm {
|
||||
mod_person_id: local_user_view.person.id,
|
||||
other_person_id: target.id,
|
||||
community_id,
|
||||
reason: reason.clone(),
|
||||
banned: Some(ban),
|
||||
expires: expires_dt,
|
||||
};
|
||||
|
||||
ModBanFromCommunity::create(&mut context.pool(), &form).await?;
|
||||
|
||||
// Federate the ban from community
|
||||
let ban_from_community = BanFromCommunity {
|
||||
community_id,
|
||||
person_id: target.id,
|
||||
ban,
|
||||
reason: reason.clone(),
|
||||
remove_or_restore_data: *remove_or_restore_data,
|
||||
expires: *expires,
|
||||
};
|
||||
|
||||
ActivityChannel::submit_activity(
|
||||
SendActivityData::BanFromCommunity {
|
||||
moderator: local_user_view.person.clone(),
|
||||
community_id,
|
||||
target: target.clone(),
|
||||
data: ban_from_community,
|
||||
},
|
||||
context,
|
||||
)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ use lemmy_db_schema::{
|
|||
traits::Crud,
|
||||
};
|
||||
use lemmy_db_views::{person::person_view::PersonQuery, structs::LocalUserView};
|
||||
use lemmy_utils::error::{LemmyErrorExt, LemmyErrorType, LemmyResult};
|
||||
use lemmy_utils::error::{LemmyErrorExt, LemmyErrorExt2, LemmyErrorType, LemmyResult};
|
||||
|
||||
pub async fn add_admin(
|
||||
data: Json<AddAdmin>,
|
||||
|
@ -61,7 +61,7 @@ pub async fn add_admin(
|
|||
admins_only: Some(true),
|
||||
..Default::default()
|
||||
}
|
||||
.list(&mut context.pool())
|
||||
.list(local_user_view.person.instance_id, &mut context.pool())
|
||||
.await?;
|
||||
|
||||
Ok(Json(AddAdminResponse { admins }))
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
use crate::ban_nonlocal_user_from_local_communities;
|
||||
use activitypub_federation::config::Data;
|
||||
use actix_web::web::Json;
|
||||
use lemmy_api_common::{
|
||||
|
@ -9,16 +8,16 @@ use lemmy_api_common::{
|
|||
};
|
||||
use lemmy_db_schema::{
|
||||
source::{
|
||||
instance::{InstanceActions, InstanceBanForm},
|
||||
local_user::LocalUser,
|
||||
login_token::LoginToken,
|
||||
mod_log::moderator::{ModBan, ModBanForm},
|
||||
person::{Person, PersonUpdateForm},
|
||||
},
|
||||
traits::Crud,
|
||||
traits::{Bannable, Crud},
|
||||
};
|
||||
use lemmy_db_views::structs::{LocalUserView, PersonView};
|
||||
use lemmy_utils::{
|
||||
error::{LemmyErrorExt, LemmyErrorType, LemmyResult},
|
||||
error::{LemmyErrorExt2, LemmyErrorType, LemmyResult},
|
||||
utils::validation::is_valid_body_field,
|
||||
};
|
||||
|
||||
|
@ -44,20 +43,19 @@ pub async fn ban_from_site(
|
|||
|
||||
let expires = check_expire_time(data.expires)?;
|
||||
|
||||
let person = Person::update(
|
||||
&mut context.pool(),
|
||||
data.person_id,
|
||||
&PersonUpdateForm {
|
||||
banned: Some(data.ban),
|
||||
ban_expires: Some(expires),
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntUpdateUser)?;
|
||||
let form = InstanceBanForm::new(data.person_id, local_user_view.person.instance_id, expires);
|
||||
if data.ban {
|
||||
InstanceActions::ban(&mut context.pool(), &form)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntUpdateUser)?;
|
||||
} else {
|
||||
InstanceActions::unban(&mut context.pool(), &form)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntUpdateUser)?;
|
||||
}
|
||||
|
||||
// if its a local user, invalidate logins
|
||||
let local_user = LocalUserView::read_person(&mut context.pool(), person.id).await;
|
||||
let local_user = LocalUserView::read_person(&mut context.pool(), data.person_id).await;
|
||||
if let Ok(local_user) = local_user {
|
||||
LoginToken::invalidate_all(&mut context.pool(), local_user.local_user.id).await?;
|
||||
}
|
||||
|
@ -67,7 +65,7 @@ pub async fn ban_from_site(
|
|||
let removed = data.ban;
|
||||
remove_or_restore_user_data(
|
||||
local_user_view.person.id,
|
||||
person.id,
|
||||
data.person_id,
|
||||
removed,
|
||||
&data.reason,
|
||||
&context,
|
||||
|
@ -78,26 +76,16 @@ pub async fn ban_from_site(
|
|||
// Mod tables
|
||||
let form = ModBanForm {
|
||||
mod_person_id: local_user_view.person.id,
|
||||
other_person_id: person.id,
|
||||
other_person_id: data.person_id,
|
||||
reason: data.reason.clone(),
|
||||
banned: Some(data.ban),
|
||||
expires,
|
||||
instance_id: local_user_view.person.instance_id,
|
||||
};
|
||||
|
||||
ModBan::create(&mut context.pool(), &form).await?;
|
||||
|
||||
let person_view = PersonView::read(&mut context.pool(), person.id, false).await?;
|
||||
|
||||
ban_nonlocal_user_from_local_communities(
|
||||
&local_user_view,
|
||||
&person,
|
||||
data.ban,
|
||||
&data.reason,
|
||||
&data.remove_or_restore_data,
|
||||
&data.expires,
|
||||
&context,
|
||||
)
|
||||
.await?;
|
||||
let person_view = PersonView::read(&mut context.pool(), data.person_id, false).await?;
|
||||
|
||||
ActivityChannel::submit_activity(
|
||||
SendActivityData::BanFromSite {
|
||||
|
|
|
@ -14,14 +14,12 @@ use lemmy_api_common::{
|
|||
person::{CaptchaResponse, GetCaptchaResponse},
|
||||
LemmyErrorType,
|
||||
};
|
||||
use lemmy_db_schema::source::{
|
||||
captcha_answer::{CaptchaAnswer, CaptchaAnswerForm},
|
||||
local_site::LocalSite,
|
||||
};
|
||||
use lemmy_db_schema::source::captcha_answer::{CaptchaAnswer, CaptchaAnswerForm};
|
||||
use lemmy_db_views::structs::SiteView;
|
||||
use lemmy_utils::error::LemmyResult;
|
||||
|
||||
pub async fn get_captcha(context: Data<LemmyContext>) -> LemmyResult<HttpResponse> {
|
||||
let local_site = LocalSite::read(&mut context.pool()).await?;
|
||||
let local_site = SiteView::read_local(&mut context.pool()).await?.local_site;
|
||||
let mut res = HttpResponseBuilder::new(StatusCode::OK);
|
||||
res.insert_header(CacheControl(vec![CacheDirective::NoStore]));
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ pub async fn list_banned_users(
|
|||
limit: data.limit,
|
||||
..Default::default()
|
||||
}
|
||||
.list(&mut context.pool())
|
||||
.list(local_user_view.person.instance_id, &mut context.pool())
|
||||
.await?;
|
||||
|
||||
let next_page = banned.last().map(PaginationCursorBuilder::to_cursor);
|
||||
|
|
|
@ -8,7 +8,7 @@ use lemmy_api_common::{
|
|||
claims::Claims,
|
||||
context::LemmyContext,
|
||||
person::{Login, LoginResponse},
|
||||
utils::{check_email_verified, check_registration_application, check_user_valid},
|
||||
utils::{check_email_verified, check_local_user_valid, check_registration_application},
|
||||
};
|
||||
use lemmy_db_views::structs::{LocalUserView, SiteView};
|
||||
use lemmy_utils::error::{LemmyErrorType, LemmyResult};
|
||||
|
@ -35,7 +35,7 @@ pub async fn login(
|
|||
if !valid {
|
||||
Err(LemmyErrorType::IncorrectLogin)?
|
||||
}
|
||||
check_user_valid(&local_user_view.person)?;
|
||||
check_local_user_valid(&local_user_view)?;
|
||||
check_email_verified(&local_user_view, &site_view)?;
|
||||
|
||||
check_registration_application(&local_user_view, &site_view.local_site, &mut context.pool())
|
||||
|
|
|
@ -28,13 +28,7 @@ pub async fn feature_post(
|
|||
let orig_post = Post::read(&mut context.pool(), post_id).await?;
|
||||
|
||||
let community = Community::read(&mut context.pool(), orig_post.community_id).await?;
|
||||
check_community_mod_action(
|
||||
&local_user_view.person,
|
||||
&community,
|
||||
false,
|
||||
&mut context.pool(),
|
||||
)
|
||||
.await?;
|
||||
check_community_mod_action(&local_user_view, &community, false, &mut context.pool()).await?;
|
||||
|
||||
if data.feature_type == PostFeatureType::Local {
|
||||
is_admin(&local_user_view)?;
|
||||
|
|
|
@ -10,13 +10,10 @@ use lemmy_api_common::{
|
|||
};
|
||||
use lemmy_db_schema::{
|
||||
newtypes::PostOrCommentId,
|
||||
source::{
|
||||
local_site::LocalSite,
|
||||
post::{PostActions, PostLikeForm, PostReadForm},
|
||||
},
|
||||
source::post::{PostActions, PostLikeForm, PostReadForm},
|
||||
traits::{Likeable, Readable},
|
||||
};
|
||||
use lemmy_db_views::structs::{LocalUserView, PostView};
|
||||
use lemmy_db_views::structs::{LocalUserView, PostView, SiteView};
|
||||
use lemmy_utils::error::LemmyResult;
|
||||
use std::ops::Deref;
|
||||
|
||||
|
@ -25,7 +22,7 @@ pub async fn like_post(
|
|||
context: Data<LemmyContext>,
|
||||
local_user_view: LocalUserView,
|
||||
) -> LemmyResult<Json<PostResponse>> {
|
||||
let local_site = LocalSite::read(&mut context.pool()).await?;
|
||||
let local_site = SiteView::read_local(&mut context.pool()).await?.local_site;
|
||||
let post_id = data.post_id;
|
||||
|
||||
check_local_vote_mode(
|
||||
|
@ -41,12 +38,7 @@ pub async fn like_post(
|
|||
// Check for a community ban
|
||||
let post = PostView::read(&mut context.pool(), post_id, None, false).await?;
|
||||
|
||||
check_community_user_action(
|
||||
&local_user_view.person,
|
||||
&post.community,
|
||||
&mut context.pool(),
|
||||
)
|
||||
.await?;
|
||||
check_community_user_action(&local_user_view, &post.community, &mut context.pool()).await?;
|
||||
|
||||
let mut like_form = PostLikeForm::new(data.post_id, local_user_view.person.id, data.score);
|
||||
|
||||
|
|
|
@ -15,12 +15,7 @@ pub async fn list_post_likes(
|
|||
local_user_view: LocalUserView,
|
||||
) -> LemmyResult<Json<ListPostLikesResponse>> {
|
||||
let post = Post::read(&mut context.pool(), data.post_id).await?;
|
||||
is_mod_or_admin(
|
||||
&mut context.pool(),
|
||||
&local_user_view.person,
|
||||
post.community_id,
|
||||
)
|
||||
.await?;
|
||||
is_mod_or_admin(&mut context.pool(), &local_user_view, post.community_id).await?;
|
||||
|
||||
let post_likes =
|
||||
VoteView::list_for_post(&mut context.pool(), data.post_id, data.page, data.limit).await?;
|
||||
|
|
|
@ -26,7 +26,7 @@ pub async fn lock_post(
|
|||
let orig_post = PostView::read(&mut context.pool(), post_id, None, false).await?;
|
||||
|
||||
check_community_mod_action(
|
||||
&local_user_view.person,
|
||||
&local_user_view,
|
||||
&orig_post.community,
|
||||
false,
|
||||
&mut context.pool(),
|
||||
|
|
|
@ -13,13 +13,10 @@ use lemmy_api_common::{
|
|||
},
|
||||
};
|
||||
use lemmy_db_schema::{
|
||||
source::{
|
||||
comment_report::{CommentReport, CommentReportForm},
|
||||
local_site::LocalSite,
|
||||
},
|
||||
source::comment_report::{CommentReport, CommentReportForm},
|
||||
traits::Reportable,
|
||||
};
|
||||
use lemmy_db_views::structs::{CommentReportView, CommentView, LocalUserView};
|
||||
use lemmy_db_views::structs::{CommentReportView, CommentView, LocalUserView, SiteView};
|
||||
use lemmy_utils::error::LemmyResult;
|
||||
|
||||
/// Creates a comment report and notifies the moderators of the community
|
||||
|
@ -42,7 +39,7 @@ pub async fn create_comment_report(
|
|||
.await?;
|
||||
|
||||
check_community_user_action(
|
||||
&local_user_view.person,
|
||||
&local_user_view,
|
||||
&comment_view.community,
|
||||
&mut context.pool(),
|
||||
)
|
||||
|
@ -65,7 +62,7 @@ pub async fn create_comment_report(
|
|||
CommentReportView::read(&mut context.pool(), report.id, person_id).await?;
|
||||
|
||||
// Email the admins
|
||||
let local_site = LocalSite::read(&mut context.pool()).await?;
|
||||
let local_site = SiteView::read_local(&mut context.pool()).await?.local_site;
|
||||
if local_site.reports_email_admins {
|
||||
send_new_report_email_to_admins(
|
||||
&comment_report_view.creator.name,
|
||||
|
|
|
@ -22,7 +22,7 @@ pub async fn resolve_comment_report(
|
|||
|
||||
let person_id = local_user_view.person.id;
|
||||
check_community_mod_action(
|
||||
&local_user_view.person,
|
||||
&local_user_view,
|
||||
&report.community,
|
||||
true,
|
||||
&mut context.pool(),
|
||||
|
|
|
@ -9,11 +9,10 @@ use lemmy_db_schema::{
|
|||
source::{
|
||||
community::Community,
|
||||
community_report::{CommunityReport, CommunityReportForm},
|
||||
local_site::LocalSite,
|
||||
},
|
||||
traits::{Crud, Reportable},
|
||||
};
|
||||
use lemmy_db_views::structs::{CommunityReportView, LocalUserView};
|
||||
use lemmy_db_views::structs::{CommunityReportView, LocalUserView, SiteView};
|
||||
use lemmy_utils::error::LemmyResult;
|
||||
|
||||
pub async fn create_community_report(
|
||||
|
@ -47,7 +46,7 @@ pub async fn create_community_report(
|
|||
CommunityReportView::read(&mut context.pool(), report.id, person_id).await?;
|
||||
|
||||
// Email the admins
|
||||
let local_site = LocalSite::read(&mut context.pool()).await?;
|
||||
let local_site = SiteView::read_local(&mut context.pool()).await?.local_site;
|
||||
if local_site.reports_email_admins {
|
||||
send_new_report_email_to_admins(
|
||||
&community_report_view.creator.name,
|
||||
|
|
|
@ -13,13 +13,10 @@ use lemmy_api_common::{
|
|||
},
|
||||
};
|
||||
use lemmy_db_schema::{
|
||||
source::{
|
||||
local_site::LocalSite,
|
||||
post_report::{PostReport, PostReportForm},
|
||||
},
|
||||
source::post_report::{PostReport, PostReportForm},
|
||||
traits::Reportable,
|
||||
};
|
||||
use lemmy_db_views::structs::{LocalUserView, PostReportView, PostView};
|
||||
use lemmy_db_views::structs::{LocalUserView, PostReportView, PostView, SiteView};
|
||||
use lemmy_utils::error::LemmyResult;
|
||||
|
||||
/// Creates a post report and notifies the moderators of the community
|
||||
|
@ -36,12 +33,7 @@ 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_user_action(
|
||||
&local_user_view.person,
|
||||
&post_view.community,
|
||||
&mut context.pool(),
|
||||
)
|
||||
.await?;
|
||||
check_community_user_action(&local_user_view, &post_view.community, &mut context.pool()).await?;
|
||||
|
||||
check_post_deleted_or_removed(&post_view.post)?;
|
||||
|
||||
|
@ -60,7 +52,7 @@ pub async fn create_post_report(
|
|||
let post_report_view = PostReportView::read(&mut context.pool(), report.id, person_id).await?;
|
||||
|
||||
// Email the admins
|
||||
let local_site = LocalSite::read(&mut context.pool()).await?;
|
||||
let local_site = SiteView::read_local(&mut context.pool()).await?.local_site;
|
||||
if local_site.reports_email_admins {
|
||||
send_new_report_email_to_admins(
|
||||
&post_report_view.creator.name,
|
||||
|
|
|
@ -22,7 +22,7 @@ pub async fn resolve_post_report(
|
|||
|
||||
let person_id = local_user_view.person.id;
|
||||
check_community_mod_action(
|
||||
&local_user_view.person,
|
||||
&local_user_view,
|
||||
&report.community,
|
||||
true,
|
||||
&mut context.pool(),
|
||||
|
|
|
@ -7,13 +7,12 @@ use lemmy_api_common::{
|
|||
};
|
||||
use lemmy_db_schema::{
|
||||
source::{
|
||||
local_site::LocalSite,
|
||||
private_message::PrivateMessage,
|
||||
private_message_report::{PrivateMessageReport, PrivateMessageReportForm},
|
||||
},
|
||||
traits::{Crud, Reportable},
|
||||
};
|
||||
use lemmy_db_views::structs::{LocalUserView, PrivateMessageReportView};
|
||||
use lemmy_db_views::structs::{LocalUserView, PrivateMessageReportView, SiteView};
|
||||
use lemmy_utils::error::{LemmyErrorType, LemmyResult};
|
||||
|
||||
pub async fn create_pm_report(
|
||||
|
@ -47,7 +46,7 @@ pub async fn create_pm_report(
|
|||
PrivateMessageReportView::read(&mut context.pool(), report.id).await?;
|
||||
|
||||
// Email the admins
|
||||
let local_site = LocalSite::read(&mut context.pool()).await?;
|
||||
let local_site = SiteView::read_local(&mut context.pool()).await?.local_site;
|
||||
if local_site.reports_email_admins {
|
||||
send_new_report_email_to_admins(
|
||||
&private_message_report_view.creator.name,
|
||||
|
|
|
@ -32,7 +32,7 @@ pub async fn leave_admin(
|
|||
admins_only: Some(true),
|
||||
..Default::default()
|
||||
}
|
||||
.list(&mut context.pool())
|
||||
.list(local_user_view.person.instance_id, &mut context.pool())
|
||||
.await?;
|
||||
if admins.len() == 1 {
|
||||
Err(LemmyErrorType::CannotLeaveAdmin)?
|
||||
|
@ -67,7 +67,7 @@ pub async fn leave_admin(
|
|||
admins_only: Some(true),
|
||||
..Default::default()
|
||||
}
|
||||
.list(&mut context.pool())
|
||||
.list(site_view.instance.id, &mut context.pool())
|
||||
.await?;
|
||||
|
||||
let all_languages = Language::read_all(&mut context.pool()).await?;
|
||||
|
|
|
@ -4,10 +4,10 @@ use lemmy_api_common::{
|
|||
site::{GetModlog, GetModlogResponse},
|
||||
utils::{check_community_mod_of_any_or_admin_action, check_private_instance},
|
||||
};
|
||||
use lemmy_db_schema::{source::local_site::LocalSite, traits::PaginationCursorBuilder};
|
||||
use lemmy_db_schema::traits::PaginationCursorBuilder;
|
||||
use lemmy_db_views::{
|
||||
combined::modlog_combined_view::ModlogCombinedQuery,
|
||||
structs::{LocalUserView, ModlogCombinedView},
|
||||
structs::{LocalUserView, ModlogCombinedView, SiteView},
|
||||
};
|
||||
use lemmy_utils::error::LemmyResult;
|
||||
|
||||
|
@ -16,7 +16,7 @@ pub async fn get_mod_log(
|
|||
context: Data<LemmyContext>,
|
||||
local_user_view: Option<LocalUserView>,
|
||||
) -> LemmyResult<Json<GetModlogResponse>> {
|
||||
let local_site = LocalSite::read(&mut context.pool()).await?;
|
||||
let local_site = SiteView::read_local(&mut context.pool()).await?.local_site;
|
||||
|
||||
check_private_instance(&local_user_view, &local_site)?;
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
use crate::ban_nonlocal_user_from_local_communities;
|
||||
use activitypub_federation::config::Data;
|
||||
use actix_web::web::Json;
|
||||
use lemmy_api_common::{
|
||||
|
@ -10,11 +9,12 @@ use lemmy_api_common::{
|
|||
};
|
||||
use lemmy_db_schema::{
|
||||
source::{
|
||||
instance::{InstanceActions, InstanceBanForm},
|
||||
local_user::LocalUser,
|
||||
mod_log::admin::{AdminPurgePerson, AdminPurgePersonForm},
|
||||
person::{Person, PersonUpdateForm},
|
||||
person::Person,
|
||||
},
|
||||
traits::Crud,
|
||||
traits::{Bannable, Crud},
|
||||
};
|
||||
use lemmy_db_views::structs::LocalUserView;
|
||||
use lemmy_utils::error::LemmyResult;
|
||||
|
@ -37,28 +37,25 @@ pub async fn purge_person(
|
|||
|
||||
let person = Person::read(&mut context.pool(), data.person_id).await?;
|
||||
|
||||
ban_nonlocal_user_from_local_communities(
|
||||
&local_user_view,
|
||||
&person,
|
||||
true,
|
||||
&data.reason,
|
||||
&Some(true),
|
||||
&None,
|
||||
ActivityChannel::submit_activity(
|
||||
SendActivityData::BanFromSite {
|
||||
moderator: local_user_view.person.clone(),
|
||||
banned_user: person.clone(),
|
||||
reason: data.reason.clone(),
|
||||
remove_or_restore_data: Some(true),
|
||||
ban: true,
|
||||
expires: None,
|
||||
},
|
||||
&context,
|
||||
)
|
||||
.await?;
|
||||
)?;
|
||||
|
||||
// Clear profile data.
|
||||
purge_user_account(data.person_id, &context).await?;
|
||||
|
||||
// Keep person record, but mark as banned to prevent login or refetching from home instance.
|
||||
let person = Person::update(
|
||||
InstanceActions::ban(
|
||||
&mut context.pool(),
|
||||
data.person_id,
|
||||
&PersonUpdateForm {
|
||||
banned: Some(true),
|
||||
..Default::default()
|
||||
},
|
||||
&InstanceBanForm::new(data.person_id, local_user_view.person.instance_id, None),
|
||||
)
|
||||
.await?;
|
||||
|
||||
|
|
|
@ -5,10 +5,9 @@ use lemmy_api_common::{
|
|||
site::{ListRegistrationApplications, ListRegistrationApplicationsResponse},
|
||||
utils::is_admin,
|
||||
};
|
||||
use lemmy_db_schema::source::local_site::LocalSite;
|
||||
use lemmy_db_views::{
|
||||
registration_applications::registration_application_view::RegistrationApplicationQuery,
|
||||
structs::LocalUserView,
|
||||
structs::{LocalUserView, SiteView},
|
||||
};
|
||||
use lemmy_utils::error::LemmyResult;
|
||||
|
||||
|
@ -18,7 +17,7 @@ pub async fn list_registration_applications(
|
|||
context: Data<LemmyContext>,
|
||||
local_user_view: LocalUserView,
|
||||
) -> LemmyResult<Json<ListRegistrationApplicationsResponse>> {
|
||||
let local_site = LocalSite::read(&mut context.pool()).await?;
|
||||
let local_site = SiteView::read_local(&mut context.pool()).await?.local_site;
|
||||
|
||||
// Make sure user is an admin
|
||||
is_admin(&local_user_view)?;
|
||||
|
|
|
@ -54,8 +54,6 @@ async fn create_test_site(context: &Data<LemmyContext>) -> LemmyResult<(Instance
|
|||
)
|
||||
.await?;
|
||||
|
||||
let admin_local_user_view = LocalUserView::read_person(pool, admin_person.id).await?;
|
||||
|
||||
let site_form = SiteInsertForm::new("test site".to_string(), inserted_instance.id);
|
||||
let site = Site::create(pool, &site_form).await?;
|
||||
|
||||
|
@ -75,6 +73,8 @@ async fn create_test_site(context: &Data<LemmyContext>) -> LemmyResult<(Instance
|
|||
let rate_limit_form = LocalSiteRateLimitInsertForm::new(local_site.id);
|
||||
LocalSiteRateLimit::create(pool, &rate_limit_form).await?;
|
||||
|
||||
let admin_local_user_view = LocalUserView::read_person(pool, admin_person.id).await?;
|
||||
|
||||
Ok((inserted_instance, admin_local_user_view))
|
||||
}
|
||||
|
||||
|
|
|
@ -5,15 +5,14 @@ use lemmy_api_common::{
|
|||
site::GetUnreadRegistrationApplicationCountResponse,
|
||||
utils::is_admin,
|
||||
};
|
||||
use lemmy_db_schema::source::local_site::LocalSite;
|
||||
use lemmy_db_views::structs::{LocalUserView, RegistrationApplicationView};
|
||||
use lemmy_db_views::structs::{LocalUserView, RegistrationApplicationView, SiteView};
|
||||
use lemmy_utils::error::LemmyResult;
|
||||
|
||||
pub async fn get_unread_registration_application_count(
|
||||
context: Data<LemmyContext>,
|
||||
local_user_view: LocalUserView,
|
||||
) -> LemmyResult<Json<GetUnreadRegistrationApplicationCountResponse>> {
|
||||
let local_site = LocalSite::read(&mut context.pool()).await?;
|
||||
let local_site = SiteView::read_local(&mut context.pool()).await?.local_site;
|
||||
|
||||
// Only let admins do this
|
||||
is_admin(&local_user_view)?;
|
||||
|
|
|
@ -46,7 +46,7 @@ pub async fn build_community_response(
|
|||
local_user_view: LocalUserView,
|
||||
community_id: CommunityId,
|
||||
) -> LemmyResult<Json<CommunityResponse>> {
|
||||
let is_mod_or_admin = is_mod_or_admin(&mut context.pool(), &local_user_view.person, community_id)
|
||||
let is_mod_or_admin = is_mod_or_admin(&mut context.pool(), &local_user_view, community_id)
|
||||
.await
|
||||
.is_ok();
|
||||
let local_user = local_user_view.local_user;
|
||||
|
@ -71,10 +71,10 @@ pub async fn build_post_response(
|
|||
local_user_view: LocalUserView,
|
||||
post_id: PostId,
|
||||
) -> LemmyResult<Json<PostResponse>> {
|
||||
let local_user = local_user_view.local_user;
|
||||
let is_mod_or_admin = is_mod_or_admin(&mut context.pool(), &local_user_view.person, community_id)
|
||||
let is_mod_or_admin = is_mod_or_admin(&mut context.pool(), &local_user_view, community_id)
|
||||
.await
|
||||
.is_ok();
|
||||
let local_user = local_user_view.local_user;
|
||||
let post_view = PostView::read(
|
||||
&mut context.pool(),
|
||||
post_id,
|
||||
|
|
|
@ -52,6 +52,7 @@ use lemmy_db_views::{
|
|||
CommunityView,
|
||||
LocalImageView,
|
||||
LocalUserView,
|
||||
PersonView,
|
||||
SiteView,
|
||||
},
|
||||
};
|
||||
|
@ -84,11 +85,11 @@ pub const AUTH_COOKIE_NAME: &str = "jwt";
|
|||
|
||||
pub async fn is_mod_or_admin(
|
||||
pool: &mut DbPool<'_>,
|
||||
person: &Person,
|
||||
local_user_view: &LocalUserView,
|
||||
community_id: CommunityId,
|
||||
) -> LemmyResult<()> {
|
||||
check_user_valid(person)?;
|
||||
CommunityView::check_is_mod_or_admin(pool, person.id, community_id).await
|
||||
check_local_user_valid(local_user_view)?;
|
||||
CommunityView::check_is_mod_or_admin(pool, local_user_view.person.id, community_id).await
|
||||
}
|
||||
|
||||
pub async fn is_mod_or_admin_opt(
|
||||
|
@ -98,7 +99,7 @@ pub async fn is_mod_or_admin_opt(
|
|||
) -> LemmyResult<()> {
|
||||
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, community_id).await
|
||||
is_mod_or_admin(pool, local_user_view, community_id).await
|
||||
} else {
|
||||
is_admin(local_user_view)
|
||||
}
|
||||
|
@ -116,12 +117,12 @@ pub async fn check_community_mod_of_any_or_admin_action(
|
|||
) -> LemmyResult<()> {
|
||||
let person = &local_user_view.person;
|
||||
|
||||
check_user_valid(person)?;
|
||||
check_local_user_valid(local_user_view)?;
|
||||
CommunityView::check_is_mod_of_any_or_admin(pool, person.id).await
|
||||
}
|
||||
|
||||
pub fn is_admin(local_user_view: &LocalUserView) -> LemmyResult<()> {
|
||||
check_user_valid(&local_user_view.person)?;
|
||||
check_local_user_valid(local_user_view)?;
|
||||
if !local_user_view.local_user.admin {
|
||||
Err(LemmyErrorType::NotAnAdmin)?
|
||||
} else {
|
||||
|
@ -133,7 +134,7 @@ pub fn is_top_mod(
|
|||
local_user_view: &LocalUserView,
|
||||
community_mods: &[CommunityModeratorView],
|
||||
) -> LemmyResult<()> {
|
||||
check_user_valid(&local_user_view.person)?;
|
||||
check_local_user_valid(local_user_view)?;
|
||||
if local_user_view.person.id
|
||||
!= community_mods
|
||||
.first()
|
||||
|
@ -159,13 +160,25 @@ pub async fn update_read_comments(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn check_user_valid(person: &Person) -> LemmyResult<()> {
|
||||
pub fn check_local_user_valid(local_user_view: &LocalUserView) -> LemmyResult<()> {
|
||||
// Check for a site ban
|
||||
if person.banned {
|
||||
if local_user_view.banned() {
|
||||
Err(LemmyErrorType::SiteBan)?
|
||||
}
|
||||
// check for account deletion
|
||||
else if person.deleted {
|
||||
else if local_user_view.person.deleted {
|
||||
Err(LemmyErrorType::Deleted)?
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
pub fn check_person_valid(person_view: &PersonView) -> LemmyResult<()> {
|
||||
// Check for a site ban
|
||||
if person_view.banned() {
|
||||
Err(LemmyErrorType::SiteBan)?
|
||||
}
|
||||
// check for account deletion
|
||||
else if person_view.person.deleted {
|
||||
Err(LemmyErrorType::Deleted)?
|
||||
} else {
|
||||
Ok(())
|
||||
|
@ -217,14 +230,16 @@ pub async fn check_registration_application(
|
|||
/// 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,
|
||||
local_user_view: &LocalUserView,
|
||||
community: &Community,
|
||||
pool: &mut DbPool<'_>,
|
||||
) -> LemmyResult<()> {
|
||||
check_user_valid(person)?;
|
||||
check_local_user_valid(local_user_view)?;
|
||||
check_community_deleted_removed(community)?;
|
||||
CommunityPersonBanView::check(pool, person.id, community.id).await?;
|
||||
CommunityFollowerView::check_private_community_action(pool, person.id, community).await?;
|
||||
CommunityPersonBanView::check(pool, local_user_view.person.id, community.id).await?;
|
||||
CommunityFollowerView::check_private_community_action(pool, local_user_view.person.id, community)
|
||||
.await?;
|
||||
InstanceActions::check_ban(pool, local_user_view.person.id, community.instance_id).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -240,13 +255,13 @@ pub fn check_community_deleted_removed(community: &Community) -> LemmyResult<()>
|
|||
/// 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,
|
||||
local_user_view: &LocalUserView,
|
||||
community: &Community,
|
||||
allow_deleted: bool,
|
||||
pool: &mut DbPool<'_>,
|
||||
) -> LemmyResult<()> {
|
||||
is_mod_or_admin(pool, person, community.id).await?;
|
||||
CommunityPersonBanView::check(pool, person.id, community.id).await?;
|
||||
is_mod_or_admin(pool, local_user_view, community.id).await?;
|
||||
CommunityPersonBanView::check(pool, local_user_view.person.id, community.id).await?;
|
||||
|
||||
// it must be possible to restore deleted community
|
||||
if !allow_deleted {
|
||||
|
@ -403,7 +418,7 @@ pub async fn send_email_to_user(
|
|||
body: &str,
|
||||
settings: &Settings,
|
||||
) {
|
||||
if local_user_view.person.banned || !local_user_view.local_user.send_notifications_to_email {
|
||||
if local_user_view.banned() || !local_user_view.local_user.send_notifications_to_email {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -540,7 +555,10 @@ pub async fn slur_regex(context: &LemmyContext) -> LemmyResult<Regex> {
|
|||
Ok(
|
||||
CACHE
|
||||
.try_get_with((), async {
|
||||
let local_site = LocalSite::read(&mut context.pool()).await.ok();
|
||||
let local_site = SiteView::read_local(&mut context.pool())
|
||||
.await
|
||||
.ok()
|
||||
.map(|s| s.local_site);
|
||||
build_and_check_regex(local_site.and_then(|s| s.slur_filter_regex).as_deref())
|
||||
})
|
||||
.await
|
||||
|
@ -807,7 +825,7 @@ pub async fn remove_or_restore_user_data(
|
|||
|
||||
// Posts
|
||||
let removed_or_restored_posts =
|
||||
Post::update_removed_for_creator(pool, banned_person_id, None, removed).await?;
|
||||
Post::update_removed_for_creator(pool, banned_person_id, None, None, removed).await?;
|
||||
create_modlog_entries_for_removed_or_restored_posts(
|
||||
pool,
|
||||
mod_person_id,
|
||||
|
@ -891,7 +909,8 @@ pub async fn remove_or_restore_user_data_in_community(
|
|||
) -> LemmyResult<()> {
|
||||
// Posts
|
||||
let posts =
|
||||
Post::update_removed_for_creator(pool, banned_person_id, Some(community_id), remove).await?;
|
||||
Post::update_removed_for_creator(pool, banned_person_id, Some(community_id), None, remove)
|
||||
.await?;
|
||||
create_modlog_entries_for_removed_or_restored_posts(
|
||||
pool,
|
||||
mod_person_id,
|
||||
|
@ -1150,7 +1169,7 @@ pub 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)?;
|
||||
check_local_user_valid(&local_user_view)?;
|
||||
|
||||
Ok(local_user_view)
|
||||
}
|
||||
|
|
|
@ -59,16 +59,11 @@ pub async fn create_comment(
|
|||
let post = post_view.post;
|
||||
let community_id = post_view.community.id;
|
||||
|
||||
check_community_user_action(
|
||||
&local_user_view.person,
|
||||
&post_view.community,
|
||||
&mut context.pool(),
|
||||
)
|
||||
.await?;
|
||||
check_community_user_action(&local_user_view, &post_view.community, &mut context.pool()).await?;
|
||||
check_post_deleted_or_removed(&post)?;
|
||||
|
||||
// Check if post is locked, no new comments
|
||||
let is_mod_or_admin = is_mod_or_admin(&mut context.pool(), &local_user_view.person, community_id)
|
||||
let is_mod_or_admin = is_mod_or_admin(&mut context.pool(), &local_user_view, community_id)
|
||||
.await
|
||||
.is_ok();
|
||||
if post.locked && !is_mod_or_admin {
|
||||
|
|
|
@ -34,7 +34,7 @@ pub async fn delete_comment(
|
|||
}
|
||||
|
||||
check_community_user_action(
|
||||
&local_user_view.person,
|
||||
&local_user_view,
|
||||
&orig_comment.community,
|
||||
&mut context.pool(),
|
||||
)
|
||||
|
|
|
@ -5,8 +5,7 @@ use lemmy_api_common::{
|
|||
context::LemmyContext,
|
||||
utils::check_private_instance,
|
||||
};
|
||||
use lemmy_db_schema::source::local_site::LocalSite;
|
||||
use lemmy_db_views::structs::LocalUserView;
|
||||
use lemmy_db_views::structs::{LocalUserView, SiteView};
|
||||
use lemmy_utils::error::LemmyResult;
|
||||
|
||||
pub async fn get_comment(
|
||||
|
@ -14,7 +13,7 @@ pub async fn get_comment(
|
|||
context: Data<LemmyContext>,
|
||||
local_user_view: Option<LocalUserView>,
|
||||
) -> LemmyResult<Json<CommentResponse>> {
|
||||
let local_site = LocalSite::read(&mut context.pool()).await?;
|
||||
let local_site = SiteView::read_local(&mut context.pool()).await?.local_site;
|
||||
|
||||
check_private_instance(&local_user_view, &local_site)?;
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ pub async fn remove_comment(
|
|||
.await?;
|
||||
|
||||
check_community_mod_action(
|
||||
&local_user_view.person,
|
||||
&local_user_view,
|
||||
&orig_comment.community,
|
||||
false,
|
||||
&mut context.pool(),
|
||||
|
|
|
@ -35,7 +35,7 @@ pub async fn update_comment(
|
|||
.await?;
|
||||
|
||||
check_community_user_action(
|
||||
&local_user_view.person,
|
||||
&local_user_view,
|
||||
&orig_comment.community,
|
||||
&mut context.pool(),
|
||||
)
|
||||
|
|
|
@ -24,13 +24,7 @@ pub async fn delete_community(
|
|||
CommunityModeratorView::for_community(&mut context.pool(), data.community_id).await?;
|
||||
|
||||
let community = Community::read(&mut context.pool(), data.community_id).await?;
|
||||
check_community_mod_action(
|
||||
&local_user_view.person,
|
||||
&community,
|
||||
true,
|
||||
&mut context.pool(),
|
||||
)
|
||||
.await?;
|
||||
check_community_mod_action(&local_user_view, &community, true, &mut context.pool()).await?;
|
||||
|
||||
// Make sure deleter is the top mod
|
||||
is_top_mod(&local_user_view, &community_mods)?;
|
||||
|
|
|
@ -24,13 +24,7 @@ pub async fn remove_community(
|
|||
local_user_view: LocalUserView,
|
||||
) -> LemmyResult<Json<CommunityResponse>> {
|
||||
let community = Community::read(&mut context.pool(), data.community_id).await?;
|
||||
check_community_mod_action(
|
||||
&local_user_view.person,
|
||||
&community,
|
||||
true,
|
||||
&mut context.pool(),
|
||||
)
|
||||
.await?;
|
||||
check_community_mod_action(&local_user_view, &community, true, &mut context.pool()).await?;
|
||||
|
||||
// Verify its an admin (only an admin can remove a community)
|
||||
is_admin(&local_user_view)?;
|
||||
|
|
|
@ -19,12 +19,11 @@ use lemmy_db_schema::{
|
|||
source::{
|
||||
actor_language::{CommunityLanguage, SiteLanguage},
|
||||
community::{Community, CommunityUpdateForm},
|
||||
local_site::LocalSite,
|
||||
},
|
||||
traits::Crud,
|
||||
utils::diesel_string_update,
|
||||
};
|
||||
use lemmy_db_views::structs::LocalUserView;
|
||||
use lemmy_db_views::structs::{LocalUserView, SiteView};
|
||||
use lemmy_utils::{
|
||||
error::{LemmyErrorExt, LemmyErrorType, LemmyResult},
|
||||
utils::{slurs::check_slurs_opt, validation::is_valid_body_field},
|
||||
|
@ -35,7 +34,7 @@ pub async fn update_community(
|
|||
context: Data<LemmyContext>,
|
||||
local_user_view: LocalUserView,
|
||||
) -> LemmyResult<Json<CommunityResponse>> {
|
||||
let local_site = LocalSite::read(&mut context.pool()).await?;
|
||||
let local_site = SiteView::read_local(&mut context.pool()).await?.local_site;
|
||||
|
||||
let slur_regex = slur_regex(&context).await?;
|
||||
let url_blocklist = get_url_blocklist(&context).await?;
|
||||
|
@ -58,13 +57,7 @@ pub async fn update_community(
|
|||
let old_community = Community::read(&mut context.pool(), data.community_id).await?;
|
||||
|
||||
// Verify its a mod (only mods can edit it)
|
||||
check_community_mod_action(
|
||||
&local_user_view.person,
|
||||
&old_community,
|
||||
false,
|
||||
&mut context.pool(),
|
||||
)
|
||||
.await?;
|
||||
check_community_mod_action(&local_user_view, &old_community, false, &mut context.pool()).await?;
|
||||
|
||||
let community_id = data.community_id;
|
||||
if let Some(languages) = data.discussion_languages.clone() {
|
||||
|
|
|
@ -24,13 +24,12 @@ use lemmy_db_schema::{
|
|||
newtypes::PostOrCommentId,
|
||||
source::{
|
||||
community::Community,
|
||||
local_site::LocalSite,
|
||||
post::{Post, PostActions, PostInsertForm, PostLikeForm, PostReadForm},
|
||||
},
|
||||
traits::{Crud, Likeable, Readable},
|
||||
utils::diesel_url_create,
|
||||
};
|
||||
use lemmy_db_views::structs::{CommunityModeratorView, LocalUserView};
|
||||
use lemmy_db_views::structs::{CommunityModeratorView, LocalUserView, SiteView};
|
||||
use lemmy_utils::{
|
||||
error::{LemmyErrorExt, LemmyErrorType, LemmyResult},
|
||||
utils::{
|
||||
|
@ -52,7 +51,7 @@ pub async fn create_post(
|
|||
local_user_view: LocalUserView,
|
||||
) -> LemmyResult<Json<PostResponse>> {
|
||||
honeypot_check(&data.honeypot)?;
|
||||
let local_site = LocalSite::read(&mut context.pool()).await?;
|
||||
let local_site = SiteView::read_local(&mut context.pool()).await?.local_site;
|
||||
|
||||
let slur_regex = slur_regex(&context).await?;
|
||||
check_slurs(&data.name, &slur_regex)?;
|
||||
|
@ -83,7 +82,7 @@ pub async fn create_post(
|
|||
}
|
||||
|
||||
let community = Community::read(&mut context.pool(), data.community_id).await?;
|
||||
check_community_user_action(&local_user_view.person, &community, &mut context.pool()).await?;
|
||||
check_community_user_action(&local_user_view, &community, &mut context.pool()).await?;
|
||||
|
||||
// If its an NSFW community, then use that as a default
|
||||
let nsfw = data.nsfw.or(Some(community.nsfw));
|
||||
|
|
|
@ -31,7 +31,7 @@ pub async fn delete_post(
|
|||
}
|
||||
|
||||
let community = Community::read(&mut context.pool(), orig_post.community_id).await?;
|
||||
check_community_user_action(&local_user_view.person, &community, &mut context.pool()).await?;
|
||||
check_community_user_action(&local_user_view, &community, &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) {
|
||||
|
|
|
@ -33,13 +33,7 @@ pub async fn remove_post(
|
|||
let orig_post = Post::read(&mut context.pool(), post_id).await?;
|
||||
let community = Community::read(&mut context.pool(), orig_post.community_id).await?;
|
||||
|
||||
check_community_mod_action(
|
||||
&local_user_view.person,
|
||||
&community,
|
||||
false,
|
||||
&mut context.pool(),
|
||||
)
|
||||
.await?;
|
||||
check_community_mod_action(&local_user_view, &community, false, &mut context.pool()).await?;
|
||||
|
||||
LocalUser::is_higher_mod_or_admin_check(
|
||||
&mut context.pool(),
|
||||
|
|
|
@ -23,13 +23,12 @@ use lemmy_db_schema::{
|
|||
newtypes::PostOrCommentId,
|
||||
source::{
|
||||
community::Community,
|
||||
local_site::LocalSite,
|
||||
post::{Post, PostUpdateForm},
|
||||
},
|
||||
traits::Crud,
|
||||
utils::{diesel_string_update, diesel_url_update},
|
||||
};
|
||||
use lemmy_db_views::structs::{LocalUserView, PostView};
|
||||
use lemmy_db_views::structs::{LocalUserView, PostView, SiteView};
|
||||
use lemmy_utils::{
|
||||
error::{LemmyErrorExt, LemmyErrorType, LemmyResult},
|
||||
utils::{
|
||||
|
@ -51,7 +50,7 @@ pub async fn update_post(
|
|||
context: Data<LemmyContext>,
|
||||
local_user_view: LocalUserView,
|
||||
) -> LemmyResult<Json<PostResponse>> {
|
||||
let local_site = LocalSite::read(&mut context.pool()).await?;
|
||||
let local_site = SiteView::read_local(&mut context.pool()).await?.local_site;
|
||||
let url = diesel_url_update(data.url.as_deref())?;
|
||||
|
||||
let custom_thumbnail = diesel_url_update(data.custom_thumbnail.as_deref())?;
|
||||
|
@ -95,12 +94,7 @@ pub async fn update_post(
|
|||
let post_id = data.post_id;
|
||||
let orig_post = PostView::read(&mut context.pool(), post_id, None, false).await?;
|
||||
|
||||
check_community_user_action(
|
||||
&local_user_view.person,
|
||||
&orig_post.community,
|
||||
&mut context.pool(),
|
||||
)
|
||||
.await?;
|
||||
check_community_user_action(&local_user_view, &orig_post.community, &mut context.pool()).await?;
|
||||
|
||||
// Verify that only the creator can edit
|
||||
if !Post::is_post_creator(local_user_view.person.id, orig_post.post.creator_id) {
|
||||
|
|
|
@ -45,7 +45,7 @@ pub async fn create_site(
|
|||
context: Data<LemmyContext>,
|
||||
local_user_view: LocalUserView,
|
||||
) -> LemmyResult<Json<SiteResponse>> {
|
||||
let local_site = LocalSite::read(&mut context.pool()).await?;
|
||||
let local_site = SiteView::read_local(&mut context.pool()).await?.local_site;
|
||||
|
||||
// Make sure user is an admin; other types of users should not create site data...
|
||||
is_admin(&local_user_view)?;
|
||||
|
|
|
@ -54,7 +54,7 @@ async fn read_site(context: &LemmyContext) -> LemmyResult<GetSiteResponse> {
|
|||
admins_only: Some(true),
|
||||
..Default::default()
|
||||
}
|
||||
.list(&mut context.pool())
|
||||
.list(site_view.instance.id, &mut context.pool())
|
||||
.await?;
|
||||
let all_languages = Language::read_all(&mut context.pool()).await?;
|
||||
let discussion_languages = SiteLanguage::read_local_raw(&mut context.pool()).await?;
|
||||
|
|
|
@ -8,8 +8,8 @@ use lemmy_api_common::{
|
|||
person::{LoginResponse, Register},
|
||||
utils::{
|
||||
check_email_verified,
|
||||
check_local_user_valid,
|
||||
check_registration_application,
|
||||
check_user_valid,
|
||||
generate_inbox_url,
|
||||
honeypot_check,
|
||||
password_length_check,
|
||||
|
@ -281,7 +281,7 @@ pub async fn authenticate_with_oauth(
|
|||
// user found by oauth_user_id => Login user
|
||||
let local_user = user_view.clone().local_user;
|
||||
|
||||
check_user_valid(&user_view.person)?;
|
||||
check_local_user_valid(&user_view)?;
|
||||
check_email_verified(&user_view, &site_view)?;
|
||||
check_registration_application(&user_view, &site_view.local_site, pool).await?;
|
||||
local_user
|
||||
|
@ -318,7 +318,7 @@ pub async fn authenticate_with_oauth(
|
|||
// users who signed up before the switch could have accounts with unverified emails falsely
|
||||
// marked as verified.
|
||||
|
||||
check_user_valid(&user_view.person)?;
|
||||
check_local_user_valid(&user_view)?;
|
||||
check_email_verified(&user_view, &site_view)?;
|
||||
check_registration_application(&user_view, &site_view.local_site, pool).await?;
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use actix_web::web::{Data, Json};
|
||||
use lemmy_api_common::{context::LemmyContext, site::MyUserInfo, utils::check_user_valid};
|
||||
use lemmy_api_common::{context::LemmyContext, site::MyUserInfo, utils::check_local_user_valid};
|
||||
use lemmy_db_schema::{
|
||||
source::{
|
||||
actor_language::LocalUserLanguage,
|
||||
|
@ -16,7 +16,7 @@ pub async fn get_my_user(
|
|||
local_user_view: LocalUserView,
|
||||
context: Data<LemmyContext>,
|
||||
) -> LemmyResult<Json<MyUserInfo>> {
|
||||
check_user_valid(&local_user_view.person)?;
|
||||
check_local_user_valid(&local_user_view)?;
|
||||
|
||||
// Build the local user with parallel queries and add it to site response
|
||||
let person_id = local_user_view.person.id;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use super::to;
|
||||
use super::{to, update_removed_for_instance};
|
||||
use crate::{
|
||||
activities::{
|
||||
block::{generate_cc, SiteOrCommunity},
|
||||
|
@ -18,10 +18,8 @@ use crate::{
|
|||
use activitypub_federation::{
|
||||
config::Data,
|
||||
kinds::activity::BlockType,
|
||||
protocol::verification::verify_domains_match,
|
||||
traits::{ActivityHandler, Actor},
|
||||
};
|
||||
use anyhow::anyhow;
|
||||
use chrono::{DateTime, Utc};
|
||||
use lemmy_api_common::{
|
||||
context::LemmyContext,
|
||||
|
@ -31,12 +29,12 @@ use lemmy_db_schema::{
|
|||
source::{
|
||||
activity::ActivitySendTargets,
|
||||
community::{CommunityActions, CommunityPersonBanForm},
|
||||
instance::{InstanceActions, InstanceBanForm},
|
||||
mod_log::moderator::{ModBan, ModBanForm, ModBanFromCommunity, ModBanFromCommunityForm},
|
||||
person::{Person, PersonUpdateForm},
|
||||
},
|
||||
traits::{Bannable, Crud},
|
||||
};
|
||||
use lemmy_utils::error::{FederationError, LemmyError, LemmyResult};
|
||||
use lemmy_utils::error::{LemmyError, LemmyResult};
|
||||
use url::Url;
|
||||
|
||||
impl BlockUser {
|
||||
|
@ -116,21 +114,8 @@ impl ActivityHandler for BlockUser {
|
|||
|
||||
async fn verify(&self, context: &Data<LemmyContext>) -> LemmyResult<()> {
|
||||
match self.target.dereference(context).await? {
|
||||
SiteOrCommunity::Site(site) => {
|
||||
SiteOrCommunity::Site(_site) => {
|
||||
verify_is_public(&self.to, &self.cc)?;
|
||||
let domain = self
|
||||
.object
|
||||
.inner()
|
||||
.domain()
|
||||
.ok_or(FederationError::UrlWithoutDomain)?;
|
||||
if context.settings().hostname == domain {
|
||||
return Err(
|
||||
anyhow!("Site bans from remote instance can't affect user's home instance").into(),
|
||||
);
|
||||
}
|
||||
// site ban can only target a user who is on the same instance as the actor (admin)
|
||||
verify_domains_match(&site.id(), self.actor.inner())?;
|
||||
verify_domains_match(&site.id(), self.object.inner())?;
|
||||
}
|
||||
SiteOrCommunity::Community(community) => {
|
||||
verify_visibility(&self.to, &self.cc, &community)?;
|
||||
|
@ -148,21 +133,20 @@ impl ActivityHandler for BlockUser {
|
|||
let blocked_person = self.object.dereference(context).await?;
|
||||
let target = self.target.dereference(context).await?;
|
||||
let reason = self.summary;
|
||||
let pool = &mut context.pool();
|
||||
match target {
|
||||
SiteOrCommunity::Site(_site) => {
|
||||
let blocked_person = Person::update(
|
||||
&mut context.pool(),
|
||||
blocked_person.id,
|
||||
&PersonUpdateForm {
|
||||
banned: Some(true),
|
||||
ban_expires: Some(expires),
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
SiteOrCommunity::Site(site) => {
|
||||
let form = InstanceBanForm::new(blocked_person.id, site.instance_id, expires);
|
||||
InstanceActions::ban(pool, &form).await?;
|
||||
|
||||
if self.remove_data.unwrap_or(false) {
|
||||
remove_or_restore_user_data(mod_person.id, blocked_person.id, true, &reason, context)
|
||||
.await?;
|
||||
if blocked_person.instance_id == site.instance_id {
|
||||
// user banned from home instance, remove all content
|
||||
remove_or_restore_user_data(mod_person.id, blocked_person.id, true, &reason, context)
|
||||
.await?;
|
||||
} else {
|
||||
update_removed_for_instance(&blocked_person, &site, true, pool).await?;
|
||||
}
|
||||
}
|
||||
|
||||
// write mod log
|
||||
|
@ -172,6 +156,7 @@ impl ActivityHandler for BlockUser {
|
|||
reason,
|
||||
banned: Some(true),
|
||||
expires,
|
||||
instance_id: site.instance_id,
|
||||
};
|
||||
ModBan::create(&mut context.pool(), &form).await?;
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ use lemmy_api_common::{
|
|||
};
|
||||
use lemmy_db_schema::{
|
||||
newtypes::CommunityId,
|
||||
source::{community::Community, person::Person, site::Site},
|
||||
source::{comment::Comment, community::Community, person::Person, post::Post, site::Site},
|
||||
traits::Crud,
|
||||
utils::DbPool,
|
||||
};
|
||||
|
@ -139,32 +139,27 @@ pub(crate) async fn send_ban_from_site(
|
|||
let site = SiteOrCommunity::Site(Site::read_local(&mut context.pool()).await?.into());
|
||||
let expires = check_expire_time(expires)?;
|
||||
|
||||
// if the action affects a local user, federate to other instances
|
||||
if banned_user.local {
|
||||
if ban {
|
||||
BlockUser::send(
|
||||
&site,
|
||||
&banned_user.into(),
|
||||
&moderator.into(),
|
||||
remove_or_restore_data.unwrap_or(false),
|
||||
reason.clone(),
|
||||
expires,
|
||||
&context,
|
||||
)
|
||||
.await
|
||||
} else {
|
||||
UndoBlockUser::send(
|
||||
&site,
|
||||
&banned_user.into(),
|
||||
&moderator.into(),
|
||||
remove_or_restore_data.unwrap_or(false),
|
||||
reason.clone(),
|
||||
&context,
|
||||
)
|
||||
.await
|
||||
}
|
||||
if ban {
|
||||
BlockUser::send(
|
||||
&site,
|
||||
&banned_user.into(),
|
||||
&moderator.into(),
|
||||
remove_or_restore_data.unwrap_or(false),
|
||||
reason.clone(),
|
||||
expires,
|
||||
&context,
|
||||
)
|
||||
.await
|
||||
} else {
|
||||
Ok(())
|
||||
UndoBlockUser::send(
|
||||
&site,
|
||||
&banned_user.into(),
|
||||
&moderator.into(),
|
||||
remove_or_restore_data.unwrap_or(false),
|
||||
reason.clone(),
|
||||
&context,
|
||||
)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -211,3 +206,29 @@ fn to(target: &SiteOrCommunity) -> LemmyResult<Vec<Url>> {
|
|||
vec![public()]
|
||||
})
|
||||
}
|
||||
|
||||
// user banned from remote instance, remove content only in communities from that
|
||||
// instance
|
||||
async fn update_removed_for_instance(
|
||||
blocked_person: &Person,
|
||||
site: &ApubSite,
|
||||
removed: bool,
|
||||
pool: &mut DbPool<'_>,
|
||||
) -> LemmyResult<()> {
|
||||
Post::update_removed_for_creator(
|
||||
pool,
|
||||
blocked_person.id,
|
||||
None,
|
||||
Some(site.instance_id),
|
||||
removed,
|
||||
)
|
||||
.await?;
|
||||
Comment::update_removed_for_creator_and_instance(
|
||||
pool,
|
||||
blocked_person.id,
|
||||
site.instance_id,
|
||||
removed,
|
||||
)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use super::to;
|
||||
use super::{to, update_removed_for_instance};
|
||||
use crate::{
|
||||
activities::{
|
||||
block::{generate_cc, SiteOrCommunity},
|
||||
|
@ -27,8 +27,8 @@ use lemmy_db_schema::{
|
|||
source::{
|
||||
activity::ActivitySendTargets,
|
||||
community::{CommunityActions, CommunityPersonBanForm},
|
||||
instance::{InstanceActions, InstanceBanForm},
|
||||
mod_log::moderator::{ModBan, ModBanForm, ModBanFromCommunity, ModBanFromCommunityForm},
|
||||
person::{Person, PersonUpdateForm},
|
||||
},
|
||||
traits::{Bannable, Crud},
|
||||
};
|
||||
|
@ -99,23 +99,21 @@ impl ActivityHandler for UndoBlockUser {
|
|||
let expires = self.object.end_time;
|
||||
let mod_person = self.actor.dereference(context).await?;
|
||||
let blocked_person = self.object.object.dereference(context).await?;
|
||||
let pool = &mut context.pool();
|
||||
match self.object.target.dereference(context).await? {
|
||||
SiteOrCommunity::Site(_site) => {
|
||||
SiteOrCommunity::Site(site) => {
|
||||
verify_is_public(&self.to, &self.cc)?;
|
||||
let blocked_person = Person::update(
|
||||
&mut context.pool(),
|
||||
blocked_person.id,
|
||||
&PersonUpdateForm {
|
||||
banned: Some(false),
|
||||
ban_expires: Some(expires),
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
let form = InstanceBanForm::new(blocked_person.id, site.instance_id, expires);
|
||||
InstanceActions::unban(pool, &form).await?;
|
||||
|
||||
if self.restore_data.unwrap_or(false) {
|
||||
remove_or_restore_user_data(mod_person.id, blocked_person.id, false, &None, context)
|
||||
.await?;
|
||||
if blocked_person.instance_id == site.instance_id {
|
||||
// user unbanned from home instance, restore all content
|
||||
remove_or_restore_user_data(mod_person.id, blocked_person.id, false, &None, context)
|
||||
.await?;
|
||||
} else {
|
||||
update_removed_for_instance(&blocked_person, &site, false, pool).await?;
|
||||
}
|
||||
}
|
||||
|
||||
// write mod log
|
||||
|
@ -125,6 +123,7 @@ impl ActivityHandler for UndoBlockUser {
|
|||
reason: self.object.summary,
|
||||
banned: Some(false),
|
||||
expires,
|
||||
instance_id: site.instance_id,
|
||||
};
|
||||
ModBan::create(&mut context.pool(), &form).await?;
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ use activitypub_federation::{
|
|||
use lemmy_api_common::{
|
||||
build_response::send_local_notifs,
|
||||
context::LemmyContext,
|
||||
utils::{check_post_deleted_or_removed, is_mod_or_admin},
|
||||
utils::check_post_deleted_or_removed,
|
||||
};
|
||||
use lemmy_db_schema::{
|
||||
newtypes::{PersonId, PostOrCommentId},
|
||||
|
@ -38,6 +38,7 @@ use lemmy_db_schema::{
|
|||
},
|
||||
traits::{Crud, Likeable},
|
||||
};
|
||||
use lemmy_db_views::structs::CommunityView;
|
||||
use lemmy_utils::{
|
||||
error::{LemmyError, LemmyResult},
|
||||
utils::mention::scrape_text_for_mentions,
|
||||
|
@ -144,7 +145,8 @@ 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, post.community_id).await?;
|
||||
CommunityView::check_is_mod_or_admin(&mut context.pool(), creator.id, post.community_id)
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ use lemmy_db_schema::{
|
|||
source::{
|
||||
activity::{ActivitySendTargets, ActorType, SentActivity, SentActivityForm},
|
||||
community::Community,
|
||||
instance::InstanceActions,
|
||||
},
|
||||
traits::Crud,
|
||||
CommunityVisibility,
|
||||
|
@ -63,11 +64,8 @@ async fn verify_person(
|
|||
context: &Data<LemmyContext>,
|
||||
) -> LemmyResult<()> {
|
||||
let person = person_id.dereference(context).await?;
|
||||
if person.banned {
|
||||
Err(FederationError::PersonIsBannedFromSite(person.ap_id.to_string()).into())
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
InstanceActions::check_ban(&mut context.pool(), person.id, person.instance_id).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Fetches the person and community to verify their type, then checks if person is banned from site
|
||||
|
@ -78,11 +76,7 @@ pub(crate) async fn verify_person_in_community(
|
|||
context: &Data<LemmyContext>,
|
||||
) -> LemmyResult<()> {
|
||||
let person = person_id.dereference(context).await?;
|
||||
if person.banned {
|
||||
Err(FederationError::PersonIsBannedFromSite(
|
||||
person.ap_id.to_string(),
|
||||
))?
|
||||
}
|
||||
InstanceActions::check_ban(&mut context.pool(), person.id, person.instance_id).await?;
|
||||
let person_id = person.id;
|
||||
let community_id = community.id;
|
||||
CommunityPersonBanView::check(&mut context.pool(), person_id, community_id).await
|
||||
|
|
|
@ -18,7 +18,8 @@ use activitypub_federation::{
|
|||
traits::{ActivityHandler, Actor},
|
||||
};
|
||||
use lemmy_api_common::{context::LemmyContext, utils::check_bot_account};
|
||||
use lemmy_db_schema::{source::local_site::LocalSite, FederationMode};
|
||||
use lemmy_db_schema::FederationMode;
|
||||
use lemmy_db_views::structs::SiteView;
|
||||
use lemmy_utils::error::{LemmyError, LemmyResult};
|
||||
use url::Url;
|
||||
|
||||
|
@ -65,8 +66,9 @@ impl ActivityHandler for Vote {
|
|||
check_bot_account(&actor.0)?;
|
||||
|
||||
// Check for enabled federation votes
|
||||
let local_site = LocalSite::read(&mut context.pool())
|
||||
let local_site = SiteView::read_local(&mut context.pool())
|
||||
.await
|
||||
.map(|s| s.local_site)
|
||||
.unwrap_or_default();
|
||||
|
||||
let (downvote_setting, upvote_setting) = match object {
|
||||
|
|
|
@ -6,12 +6,8 @@ use lemmy_api_common::{
|
|||
context::LemmyContext,
|
||||
utils::{check_private_instance, is_mod_or_admin_opt, read_site_for_actor},
|
||||
};
|
||||
use lemmy_db_schema::source::{
|
||||
actor_language::CommunityLanguage,
|
||||
community::Community,
|
||||
local_site::LocalSite,
|
||||
};
|
||||
use lemmy_db_views::structs::{CommunityModeratorView, CommunityView, LocalUserView};
|
||||
use lemmy_db_schema::source::{actor_language::CommunityLanguage, community::Community};
|
||||
use lemmy_db_views::structs::{CommunityModeratorView, CommunityView, LocalUserView, SiteView};
|
||||
use lemmy_utils::error::{LemmyErrorType, LemmyResult};
|
||||
|
||||
pub async fn get_community(
|
||||
|
@ -19,7 +15,7 @@ pub async fn get_community(
|
|||
context: Data<LemmyContext>,
|
||||
local_user_view: Option<LocalUserView>,
|
||||
) -> LemmyResult<Json<GetCommunityResponse>> {
|
||||
let local_site = LocalSite::read(&mut context.pool()).await?;
|
||||
let local_site = SiteView::read_local(&mut context.pool()).await?.local_site;
|
||||
|
||||
if data.name.is_none() && data.id.is_none() {
|
||||
Err(LemmyErrorType::NoIdGiven)?
|
||||
|
|
|
@ -10,8 +10,15 @@ use lemmy_api_common::{
|
|||
site::{ResolveObject, ResolveObjectResponse},
|
||||
utils::check_private_instance,
|
||||
};
|
||||
use lemmy_db_schema::{source::local_site::LocalSite, utils::DbPool};
|
||||
use lemmy_db_views::structs::{CommentView, CommunityView, LocalUserView, PersonView, PostView};
|
||||
use lemmy_db_schema::utils::DbPool;
|
||||
use lemmy_db_views::structs::{
|
||||
CommentView,
|
||||
CommunityView,
|
||||
LocalUserView,
|
||||
PersonView,
|
||||
PostView,
|
||||
SiteView,
|
||||
};
|
||||
use lemmy_utils::error::{LemmyErrorExt2, LemmyErrorType, LemmyResult};
|
||||
|
||||
pub async fn resolve_object(
|
||||
|
@ -19,7 +26,7 @@ pub async fn resolve_object(
|
|||
context: Data<LemmyContext>,
|
||||
local_user_view: Option<LocalUserView>,
|
||||
) -> LemmyResult<Json<ResolveObjectResponse>> {
|
||||
let local_site = LocalSite::read(&mut context.pool()).await?;
|
||||
let local_site = SiteView::read_local(&mut context.pool()).await?.local_site;
|
||||
check_private_instance(&local_user_view, &local_site)?;
|
||||
// If we get a valid personId back we can safely assume that the user is authenticated,
|
||||
// if there's no personId then the JWT was missing or invalid.
|
||||
|
@ -77,13 +84,12 @@ mod tests {
|
|||
source::{
|
||||
community::{Community, CommunityInsertForm},
|
||||
instance::Instance,
|
||||
local_site::{LocalSite, LocalSiteInsertForm},
|
||||
local_site::LocalSite,
|
||||
post::{Post, PostInsertForm, PostUpdateForm},
|
||||
site::{Site, SiteInsertForm},
|
||||
},
|
||||
traits::Crud,
|
||||
};
|
||||
use lemmy_db_views::structs::LocalUserView;
|
||||
use lemmy_db_views::{site::site_view::create_test_instance, structs::LocalUserView};
|
||||
use lemmy_utils::error::{LemmyErrorType, LemmyResult};
|
||||
use serial_test::serial;
|
||||
|
||||
|
@ -93,6 +99,7 @@ mod tests {
|
|||
async fn test_object_visibility() -> LemmyResult<()> {
|
||||
let context = LemmyContext::init_test_context().await;
|
||||
let pool = &mut context.pool();
|
||||
let instance = create_test_instance(pool).await?;
|
||||
|
||||
let name = "test_local_user_name";
|
||||
let bio = "test_local_user_bio";
|
||||
|
@ -101,21 +108,10 @@ mod tests {
|
|||
let regular_user = LocalUserView::create_test_user(pool, name, bio, false).await?;
|
||||
let admin_user = LocalUserView::create_test_user(pool, name, bio, true).await?;
|
||||
|
||||
let instance_id = creator.person.instance_id;
|
||||
let site_form = SiteInsertForm::new("test site".to_string(), instance_id);
|
||||
let site = Site::create(pool, &site_form).await?;
|
||||
|
||||
let local_site_form = LocalSiteInsertForm {
|
||||
site_setup: Some(true),
|
||||
private_instance: Some(false),
|
||||
..LocalSiteInsertForm::new(site.id)
|
||||
};
|
||||
LocalSite::create(pool, &local_site_form).await?;
|
||||
|
||||
let community = Community::create(
|
||||
pool,
|
||||
&CommunityInsertForm::new(
|
||||
instance_id,
|
||||
instance.id,
|
||||
"test".to_string(),
|
||||
"test".to_string(),
|
||||
"pubkey".to_string(),
|
||||
|
@ -180,8 +176,7 @@ mod tests {
|
|||
assert_eq!(res.post.as_ref().unwrap().post.ap_id, post.ap_id);
|
||||
|
||||
LocalSite::delete(pool).await?;
|
||||
Site::delete(pool, site.id).await?;
|
||||
Instance::delete(pool, instance_id).await?;
|
||||
Instance::delete(pool, instance.id).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -288,11 +288,15 @@ pub(crate) mod tests {
|
|||
CommunityFollowerState,
|
||||
CommunityInsertForm,
|
||||
},
|
||||
instance::Instance,
|
||||
person::Person,
|
||||
},
|
||||
traits::{Crud, Followable},
|
||||
};
|
||||
use lemmy_db_views::structs::{CommunityFollowerView, LocalUserView};
|
||||
use lemmy_db_views::{
|
||||
site::site_view::create_test_instance,
|
||||
structs::{CommunityFollowerView, LocalUserView},
|
||||
};
|
||||
use lemmy_utils::error::{LemmyErrorType, LemmyResult};
|
||||
use serial_test::serial;
|
||||
use std::time::Duration;
|
||||
|
@ -303,6 +307,7 @@ pub(crate) mod tests {
|
|||
async fn test_settings_export_import() -> LemmyResult<()> {
|
||||
let context = LemmyContext::init_test_context().await;
|
||||
let pool = &mut context.pool();
|
||||
let instance = create_test_instance(pool).await?;
|
||||
|
||||
let export_user = LocalUserView::create_test_user(pool, "hanna", "my bio", false).await?;
|
||||
|
||||
|
@ -344,6 +349,7 @@ pub(crate) mod tests {
|
|||
|
||||
Person::delete(pool, export_user.person.id).await?;
|
||||
Person::delete(pool, import_user.person.id).await?;
|
||||
Instance::delete(&mut context.pool(), instance.id).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -352,6 +358,7 @@ pub(crate) mod tests {
|
|||
async fn disallow_large_backup() -> LemmyResult<()> {
|
||||
let context = LemmyContext::init_test_context().await;
|
||||
let pool = &mut context.pool();
|
||||
let instance = create_test_instance(pool).await?;
|
||||
|
||||
let export_user = LocalUserView::create_test_user(pool, "harry", "harry bio", false).await?;
|
||||
|
||||
|
@ -380,6 +387,7 @@ pub(crate) mod tests {
|
|||
|
||||
Person::delete(pool, export_user.person.id).await?;
|
||||
Person::delete(pool, import_user.person.id).await?;
|
||||
Instance::delete(&mut context.pool(), instance.id).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -388,6 +396,7 @@ pub(crate) mod tests {
|
|||
async fn import_partial_backup() -> LemmyResult<()> {
|
||||
let context = LemmyContext::init_test_context().await;
|
||||
let pool = &mut context.pool();
|
||||
let instance = create_test_instance(pool).await?;
|
||||
|
||||
let import_user = LocalUserView::create_test_user(pool, "larry", "larry bio", false).await?;
|
||||
|
||||
|
@ -408,6 +417,7 @@ pub(crate) mod tests {
|
|||
// local_user can be deserialized without id/person_id fields
|
||||
assert_eq!("my_theme", import_user_updated.local_user.theme);
|
||||
|
||||
Instance::delete(&mut context.pool(), instance.id).await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -105,7 +105,7 @@ mod tests {
|
|||
},
|
||||
traits::Crud,
|
||||
};
|
||||
use lemmy_db_views::structs::LocalUserView;
|
||||
use lemmy_db_views::{site::site_view::create_test_instance, structs::LocalUserView};
|
||||
use pretty_assertions::assert_eq;
|
||||
use serial_test::serial;
|
||||
|
||||
|
@ -113,7 +113,7 @@ mod tests {
|
|||
#[tokio::test]
|
||||
async fn test_markdown_rewrite_remote_links() -> LemmyResult<()> {
|
||||
let context = LemmyContext::init_test_context().await;
|
||||
let instance = Instance::read_or_create(&mut context.pool(), "example.com".to_string()).await?;
|
||||
let instance = create_test_instance(&mut context.pool()).await?;
|
||||
let community = Community::create(
|
||||
&mut context.pool(),
|
||||
&CommunityInsertForm::new(
|
||||
|
|
|
@ -9,6 +9,7 @@ use lemmy_db_schema::{
|
|||
source::{activity::ReceivedActivity, instance::Instance, local_site::LocalSite},
|
||||
utils::{ActualDbPool, DbPool},
|
||||
};
|
||||
use lemmy_db_views::structs::SiteView;
|
||||
use lemmy_utils::{
|
||||
error::{FederationError, LemmyError, LemmyErrorType, LemmyResult},
|
||||
CacheLock,
|
||||
|
@ -153,7 +154,7 @@ pub(crate) async fn local_site_data_cached(
|
|||
lemmy_db_schema::try_join_with_pool!(pool => (
|
||||
// LocalSite may be missing
|
||||
|pool| async {
|
||||
Ok(LocalSite::read(pool).await.ok())
|
||||
Ok(SiteView::read_local(pool).await.ok().map(|s| s.local_site))
|
||||
},
|
||||
Instance::allowlist,
|
||||
Instance::blocklist
|
||||
|
|
|
@ -23,7 +23,7 @@ use chrono::{DateTime, Utc};
|
|||
use lemmy_api_common::{
|
||||
context::LemmyContext,
|
||||
plugins::{plugin_hook_after, plugin_hook_before},
|
||||
utils::{get_url_blocklist, is_mod_or_admin, process_markdown, slur_regex},
|
||||
utils::{get_url_blocklist, process_markdown, slur_regex},
|
||||
};
|
||||
use lemmy_db_schema::{
|
||||
source::{
|
||||
|
@ -34,6 +34,7 @@ use lemmy_db_schema::{
|
|||
},
|
||||
traits::Crud,
|
||||
};
|
||||
use lemmy_db_views::structs::CommunityView;
|
||||
use lemmy_utils::{
|
||||
error::{FederationError, LemmyError, LemmyResult},
|
||||
utils::markdown::markdown_to_html,
|
||||
|
@ -161,9 +162,10 @@ impl Object for ApubComment {
|
|||
|
||||
let (post, _) = Box::pin(note.get_parents(context)).await?;
|
||||
let creator = Box::pin(note.attributed_to.dereference(context)).await?;
|
||||
let is_mod_or_admin = is_mod_or_admin(&mut context.pool(), &creator, community.id)
|
||||
.await
|
||||
.is_ok();
|
||||
let is_mod_or_admin =
|
||||
CommunityView::check_is_mod_or_admin(&mut context.pool(), creator.id, community.id)
|
||||
.await
|
||||
.is_ok();
|
||||
if post.locked && !is_mod_or_admin {
|
||||
Err(FederationError::PostIsLocked)?
|
||||
} else {
|
||||
|
@ -233,7 +235,8 @@ pub(crate) mod tests {
|
|||
};
|
||||
use assert_json_diff::assert_json_include;
|
||||
use html2md::parse_html;
|
||||
use lemmy_db_schema::source::{local_site::LocalSite, site::Site};
|
||||
use lemmy_db_schema::source::{instance::Instance, local_site::LocalSite, site::Site};
|
||||
use lemmy_db_views::site::site_view::create_test_instance;
|
||||
use pretty_assertions::assert_eq;
|
||||
use serial_test::serial;
|
||||
|
||||
|
@ -267,6 +270,7 @@ pub(crate) mod tests {
|
|||
#[serial]
|
||||
pub(crate) async fn test_parse_lemmy_comment() -> LemmyResult<()> {
|
||||
let context = LemmyContext::init_test_context().await;
|
||||
let instance = create_test_instance(&mut context.pool()).await?;
|
||||
let url = Url::parse("https://enterprise.lemmy.ml/comment/38741")?;
|
||||
let data = prepare_comment_test(&url, &context).await?;
|
||||
|
||||
|
@ -285,6 +289,7 @@ pub(crate) mod tests {
|
|||
|
||||
Comment::delete(&mut context.pool(), comment_id).await?;
|
||||
cleanup(data, &context).await?;
|
||||
Instance::delete(&mut context.pool(), instance.id).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -292,6 +297,7 @@ pub(crate) mod tests {
|
|||
#[serial]
|
||||
async fn test_parse_pleroma_comment() -> LemmyResult<()> {
|
||||
let context = LemmyContext::init_test_context().await;
|
||||
let instance = create_test_instance(&mut context.pool()).await?;
|
||||
let url = Url::parse("https://enterprise.lemmy.ml/comment/38741")?;
|
||||
let data = prepare_comment_test(&url, &context).await?;
|
||||
|
||||
|
@ -311,6 +317,7 @@ pub(crate) mod tests {
|
|||
|
||||
Comment::delete(&mut context.pool(), comment.id).await?;
|
||||
cleanup(data, &context).await?;
|
||||
Instance::delete(&mut context.pool(), instance.id).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
@ -39,11 +39,11 @@ use lemmy_db_schema::{
|
|||
activity::ActorType,
|
||||
actor_language::CommunityLanguage,
|
||||
community::{Community, CommunityInsertForm, CommunityUpdateForm},
|
||||
local_site::LocalSite,
|
||||
},
|
||||
traits::{ApubActor, Crud},
|
||||
CommunityVisibility,
|
||||
};
|
||||
use lemmy_db_views::structs::SiteView;
|
||||
use lemmy_utils::{
|
||||
error::{LemmyError, LemmyResult},
|
||||
spawn_try_task,
|
||||
|
@ -144,7 +144,10 @@ impl Object for ApubCommunity {
|
|||
|
||||
/// Converts a `Group` to `Community`, inserts it into the database and updates moderators.
|
||||
async fn from_json(group: Group, context: &Data<Self::DataType>) -> LemmyResult<ApubCommunity> {
|
||||
let local_site = LocalSite::read(&mut context.pool()).await.ok();
|
||||
let local_site = SiteView::read_local(&mut context.pool())
|
||||
.await
|
||||
.ok()
|
||||
.map(|s| s.local_site);
|
||||
let instance_id = fetch_instance_actor_for_object(&group.id, context).await?;
|
||||
|
||||
let slur_regex = slur_regex(context).await?;
|
||||
|
|
|
@ -152,8 +152,6 @@ impl Object for ApubPerson {
|
|||
let person_form = PersonInsertForm {
|
||||
name: person.preferred_username,
|
||||
display_name,
|
||||
banned: None,
|
||||
ban_expires: None,
|
||||
deleted: Some(false),
|
||||
avatar,
|
||||
banner,
|
||||
|
|
|
@ -40,13 +40,12 @@ use lemmy_api_common::{
|
|||
use lemmy_db_schema::{
|
||||
source::{
|
||||
community::Community,
|
||||
local_site::LocalSite,
|
||||
person::Person,
|
||||
post::{Post, PostInsertForm, PostUpdateForm},
|
||||
},
|
||||
traits::Crud,
|
||||
};
|
||||
use lemmy_db_views::structs::CommunityModeratorView;
|
||||
use lemmy_db_views::structs::{CommunityModeratorView, SiteView};
|
||||
use lemmy_utils::{
|
||||
error::{LemmyError, LemmyResult},
|
||||
spawn_try_task,
|
||||
|
@ -185,7 +184,10 @@ impl Object for ApubPost {
|
|||
}
|
||||
|
||||
async fn from_json(page: Page, context: &Data<Self::DataType>) -> LemmyResult<ApubPost> {
|
||||
let local_site = LocalSite::read(&mut context.pool()).await.ok();
|
||||
let local_site = SiteView::read_local(&mut context.pool())
|
||||
.await
|
||||
.ok()
|
||||
.map(|s| s.local_site);
|
||||
let creator = page.creator()?.dereference(context).await?;
|
||||
let community = page.community(context).await?;
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ use lemmy_api_common::{
|
|||
};
|
||||
use lemmy_db_schema::{
|
||||
source::{
|
||||
instance::Instance,
|
||||
instance::{Instance, InstanceActions},
|
||||
person::{Person, PersonActions},
|
||||
private_message::{PrivateMessage as DbPrivateMessage, PrivateMessageInsertForm},
|
||||
},
|
||||
|
@ -31,7 +31,7 @@ use lemmy_db_schema::{
|
|||
};
|
||||
use lemmy_db_views::structs::LocalUserView;
|
||||
use lemmy_utils::{
|
||||
error::{FederationError, LemmyError, LemmyErrorType, LemmyResult},
|
||||
error::{LemmyError, LemmyErrorType, LemmyResult},
|
||||
utils::markdown::markdown_to_html,
|
||||
};
|
||||
use semver::{Version, VersionReq};
|
||||
|
@ -123,13 +123,8 @@ impl Object for ApubPrivateMessage {
|
|||
|
||||
check_apub_id_valid_with_strictness(note.id.inner(), false, context).await?;
|
||||
let person = note.attributed_to.dereference(context).await?;
|
||||
if person.banned {
|
||||
Err(FederationError::PersonIsBannedFromSite(
|
||||
person.ap_id.to_string(),
|
||||
))?
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
InstanceActions::check_ban(&mut context.pool(), person.id, person.instance_id).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn from_json(
|
||||
|
@ -184,6 +179,7 @@ mod tests {
|
|||
};
|
||||
use assert_json_diff::assert_json_include;
|
||||
use lemmy_db_schema::source::site::Site;
|
||||
use lemmy_db_views::site::site_view::create_test_instance;
|
||||
use pretty_assertions::assert_eq;
|
||||
use serial_test::serial;
|
||||
|
||||
|
@ -217,6 +213,7 @@ mod tests {
|
|||
#[serial]
|
||||
async fn test_parse_lemmy_pm() -> LemmyResult<()> {
|
||||
let context = LemmyContext::init_test_context().await;
|
||||
let instance = create_test_instance(&mut context.pool()).await?;
|
||||
let url = Url::parse("https://enterprise.lemmy.ml/private_message/1621")?;
|
||||
let data = prepare_comment_test(&url, &context).await?;
|
||||
let json: PrivateMessage = file_to_json_object("assets/lemmy/objects/private_message.json")?;
|
||||
|
@ -233,6 +230,7 @@ mod tests {
|
|||
|
||||
DbPrivateMessage::delete(&mut context.pool(), pm_id).await?;
|
||||
cleanup(data, &context).await?;
|
||||
Instance::delete(&mut context.pool(), instance.id).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -240,6 +238,7 @@ mod tests {
|
|||
#[serial]
|
||||
async fn test_parse_pleroma_pm() -> LemmyResult<()> {
|
||||
let context = LemmyContext::init_test_context().await;
|
||||
let instance = create_test_instance(&mut context.pool()).await?;
|
||||
let url = Url::parse("https://enterprise.lemmy.ml/private_message/1621")?;
|
||||
let data = prepare_comment_test(&url, &context).await?;
|
||||
let pleroma_url = Url::parse("https://queer.hacktivis.me/objects/2")?;
|
||||
|
@ -253,6 +252,7 @@ mod tests {
|
|||
|
||||
DbPrivateMessage::delete(&mut context.pool(), pm.id).await?;
|
||||
cleanup(data, &context).await?;
|
||||
Instance::delete(&mut context.pool(), instance.id).await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::{
|
||||
diesel::{DecoratableTarget, OptionalExtension},
|
||||
newtypes::{CommentId, DbUrl, PersonId},
|
||||
schema::{comment, comment_actions},
|
||||
newtypes::{CommentId, DbUrl, InstanceId, PersonId},
|
||||
schema::{comment, comment_actions, post},
|
||||
source::comment::{
|
||||
Comment,
|
||||
CommentActions,
|
||||
|
@ -24,6 +24,7 @@ use diesel::{
|
|||
dsl::insert_into,
|
||||
expression::SelectableHelper,
|
||||
result::Error,
|
||||
update,
|
||||
ExpressionMethods,
|
||||
QueryDsl,
|
||||
};
|
||||
|
@ -67,6 +68,35 @@ impl Comment {
|
|||
.await
|
||||
}
|
||||
|
||||
pub async fn update_removed_for_creator_and_instance(
|
||||
pool: &mut DbPool<'_>,
|
||||
creator_id: PersonId,
|
||||
instance_id: InstanceId,
|
||||
removed: bool,
|
||||
) -> Result<Vec<CommentId>, Error> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
// Diesel can't update from join unfortunately, so you'll need to loop over these
|
||||
let comment_ids = comment::table
|
||||
.inner_join(post::table)
|
||||
.filter(comment::creator_id.eq(creator_id))
|
||||
.filter(post::instance_id.eq(instance_id))
|
||||
.select(comment::id)
|
||||
.load::<CommentId>(conn)
|
||||
.await?;
|
||||
|
||||
let form = &CommentUpdateForm {
|
||||
removed: Some(removed),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
update(comment::table)
|
||||
.filter(comment::id.eq_any(comment_ids.clone()))
|
||||
.set(form)
|
||||
.execute(conn)
|
||||
.await?;
|
||||
Ok(comment_ids)
|
||||
}
|
||||
|
||||
pub async fn create(
|
||||
pool: &mut DbPool<'_>,
|
||||
comment_form: &CommentInsertForm,
|
||||
|
|
|
@ -12,9 +12,9 @@ use crate::{
|
|||
},
|
||||
source::{
|
||||
federation_queue_state::FederationQueueState,
|
||||
instance::{Instance, InstanceActions, InstanceBlockForm, InstanceForm},
|
||||
instance::{Instance, InstanceActions, InstanceBanForm, InstanceBlockForm, InstanceForm},
|
||||
},
|
||||
traits::Blockable,
|
||||
traits::{Bannable, Blockable},
|
||||
utils::{
|
||||
functions::{coalesce, lower},
|
||||
get_conn,
|
||||
|
@ -249,3 +249,53 @@ impl Blockable for InstanceActions {
|
|||
.await
|
||||
}
|
||||
}
|
||||
|
||||
impl InstanceActions {
|
||||
pub async fn check_ban(
|
||||
pool: &mut DbPool<'_>,
|
||||
person_id: PersonId,
|
||||
instance_id: InstanceId,
|
||||
) -> LemmyResult<()> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
let ban_exists = select(exists(
|
||||
instance_actions::table
|
||||
.filter(instance_actions::person_id.eq(person_id))
|
||||
.filter(instance_actions::instance_id.eq(instance_id))
|
||||
.filter(instance_actions::received_ban.is_not_null()),
|
||||
))
|
||||
.get_result::<bool>(conn)
|
||||
.await?;
|
||||
|
||||
if ban_exists {
|
||||
return Err(LemmyErrorType::SiteBan.into());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Bannable for InstanceActions {
|
||||
type Form = InstanceBanForm;
|
||||
async fn ban(pool: &mut DbPool<'_>, form: &Self::Form) -> LemmyResult<Self> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
Ok(
|
||||
insert_into(instance_actions::table)
|
||||
.values(form)
|
||||
.on_conflict((instance_actions::person_id, instance_actions::instance_id))
|
||||
.do_update()
|
||||
.set(form)
|
||||
.returning(Self::as_select())
|
||||
.get_result::<Self>(conn)
|
||||
.await?,
|
||||
)
|
||||
}
|
||||
async fn unban(pool: &mut DbPool<'_>, form: &Self::Form) -> LemmyResult<uplete::Count> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
Ok(
|
||||
uplete::new(instance_actions::table.find((form.person_id, form.instance_id)))
|
||||
.set_null(instance_actions::received_ban)
|
||||
.set_null(instance_actions::ban_expires)
|
||||
.get_result(conn)
|
||||
.await?,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,8 +5,6 @@ use crate::{
|
|||
};
|
||||
use diesel::{dsl::insert_into, result::Error};
|
||||
use diesel_async::RunQueryDsl;
|
||||
use lemmy_utils::{build_cache, error::LemmyResult, CacheLock};
|
||||
use std::sync::LazyLock;
|
||||
|
||||
impl LocalSite {
|
||||
pub async fn create(pool: &mut DbPool<'_>, form: &LocalSiteInsertForm) -> Result<Self, Error> {
|
||||
|
@ -16,17 +14,14 @@ impl LocalSite {
|
|||
.get_result::<Self>(conn)
|
||||
.await
|
||||
}
|
||||
pub async fn read(pool: &mut DbPool<'_>) -> LemmyResult<Self> {
|
||||
static CACHE: CacheLock<LocalSite> = LazyLock::new(build_cache);
|
||||
Ok(
|
||||
CACHE
|
||||
.try_get_with((), async {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
local_site::table.first(conn).await
|
||||
})
|
||||
.await?,
|
||||
)
|
||||
|
||||
/// Only used for tests
|
||||
#[cfg(test)]
|
||||
async fn read(pool: &mut DbPool<'_>) -> Result<Self, Error> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
local_site::table.first(conn).await
|
||||
}
|
||||
|
||||
pub async fn update(pool: &mut DbPool<'_>, form: &LocalSiteUpdateForm) -> Result<Self, Error> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
diesel::update(local_site::table)
|
||||
|
@ -56,6 +51,7 @@ mod tests {
|
|||
traits::Crud,
|
||||
utils::{build_db_pool_for_tests, DbPool},
|
||||
};
|
||||
use lemmy_utils::error::LemmyResult;
|
||||
use pretty_assertions::assert_eq;
|
||||
use serial_test::serial;
|
||||
|
||||
|
|
|
@ -554,6 +554,7 @@ mod tests {
|
|||
reason: None,
|
||||
banned: None,
|
||||
expires: None,
|
||||
instance_id: inserted_instance.id,
|
||||
};
|
||||
let inserted_mod_ban = ModBan::create(pool, &mod_ban_form).await?;
|
||||
let read_mod_ban = ModBan::read(pool, inserted_mod_ban.id).await?;
|
||||
|
@ -565,6 +566,7 @@ mod tests {
|
|||
banned: true,
|
||||
expires: None,
|
||||
published: inserted_mod_ban.published,
|
||||
instance_id: inserted_instance.id,
|
||||
};
|
||||
|
||||
// mod add community
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::{
|
||||
diesel::OptionalExtension,
|
||||
newtypes::{CommunityId, DbUrl, InstanceId, PersonId},
|
||||
schema::{comment, community, instance, local_user, person, person_actions, post},
|
||||
schema::{instance, local_user, person, person_actions},
|
||||
source::person::{
|
||||
Person,
|
||||
PersonActions,
|
||||
|
@ -18,7 +18,6 @@ use diesel::{
|
|||
dsl::{exists, insert_into, not, select},
|
||||
expression::SelectableHelper,
|
||||
result::Error,
|
||||
CombineDsl,
|
||||
ExpressionMethods,
|
||||
JoinOnDsl,
|
||||
QueryDsl,
|
||||
|
@ -103,31 +102,6 @@ impl Person {
|
|||
.await
|
||||
}
|
||||
|
||||
/// Lists local community ids for all posts and comments for a given creator.
|
||||
pub async fn list_local_community_ids(
|
||||
pool: &mut DbPool<'_>,
|
||||
for_creator_id: PersonId,
|
||||
) -> Result<Vec<CommunityId>, Error> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
comment::table
|
||||
.inner_join(post::table)
|
||||
.inner_join(community::table.on(post::community_id.eq(community::id)))
|
||||
.filter(community::local.eq(true))
|
||||
.filter(not(community::deleted))
|
||||
.filter(not(community::removed))
|
||||
.filter(comment::creator_id.eq(for_creator_id))
|
||||
.select(community::id)
|
||||
.union(
|
||||
post::table
|
||||
.inner_join(community::table)
|
||||
.filter(community::local.eq(true))
|
||||
.filter(post::creator_id.eq(for_creator_id))
|
||||
.select(community::id),
|
||||
)
|
||||
.load::<CommunityId>(conn)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn check_username_taken(pool: &mut DbPool<'_>, username: &str) -> LemmyResult<()> {
|
||||
use diesel::dsl::{exists, select};
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
|
@ -357,7 +331,6 @@ mod tests {
|
|||
display_name: None,
|
||||
avatar: None,
|
||||
banner: None,
|
||||
banned: false,
|
||||
deleted: false,
|
||||
published: inserted_person.published,
|
||||
updated: None,
|
||||
|
@ -370,7 +343,6 @@ mod tests {
|
|||
last_refreshed_at: inserted_person.published,
|
||||
inbox_url: inserted_person.inbox_url.clone(),
|
||||
matrix_user_id: None,
|
||||
ban_expires: None,
|
||||
instance_id: inserted_instance.id,
|
||||
post_count: 0,
|
||||
post_score: 0,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::{
|
||||
newtypes::{CommunityId, DbUrl, PersonId, PostId},
|
||||
newtypes::{CommunityId, DbUrl, InstanceId, PersonId, PostId},
|
||||
schema::{community, person, post, post_actions},
|
||||
source::post::{
|
||||
Post,
|
||||
|
@ -149,6 +149,7 @@ impl Post {
|
|||
pool: &mut DbPool<'_>,
|
||||
for_creator_id: PersonId,
|
||||
for_community_id: Option<CommunityId>,
|
||||
for_instance_id: Option<InstanceId>,
|
||||
removed: bool,
|
||||
) -> Result<Vec<Self>, Error> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
|
@ -160,6 +161,10 @@ impl Post {
|
|||
update = update.filter(post::community_id.eq(for_community_id));
|
||||
}
|
||||
|
||||
if let Some(for_instance_id) = for_instance_id {
|
||||
update = update.filter(post::instance_id.eq(for_instance_id));
|
||||
}
|
||||
|
||||
update
|
||||
.set((post::removed.eq(removed), post::updated.eq(Utc::now())))
|
||||
.get_results::<Self>(conn)
|
||||
|
|
|
@ -18,9 +18,10 @@ pub mod sensitive;
|
|||
pub mod schema;
|
||||
#[cfg(feature = "full")]
|
||||
pub mod aliases {
|
||||
use crate::schema::{community_actions, local_user, person};
|
||||
use crate::schema::{community_actions, instance_actions, local_user, person};
|
||||
diesel::alias!(
|
||||
community_actions as creator_community_actions: CreatorCommunityActions,
|
||||
instance_actions as home_instance_actions: HomeInstanceActions,
|
||||
local_user as creator_local_user: CreatorLocalUser,
|
||||
person as person1: Person1,
|
||||
person as person2: Person2,
|
||||
|
@ -40,7 +41,7 @@ use strum::{Display, EnumString};
|
|||
#[cfg(feature = "full")]
|
||||
use {
|
||||
diesel::query_source::AliasedField,
|
||||
schema::{community_actions, person},
|
||||
schema::{community_actions, instance_actions, person},
|
||||
ts_rs::TS,
|
||||
};
|
||||
|
||||
|
@ -329,7 +330,6 @@ pub type Person1AliasAllColumnsTuple = (
|
|||
AliasedField<aliases::Person1, person::name>,
|
||||
AliasedField<aliases::Person1, person::display_name>,
|
||||
AliasedField<aliases::Person1, person::avatar>,
|
||||
AliasedField<aliases::Person1, person::banned>,
|
||||
AliasedField<aliases::Person1, person::published>,
|
||||
AliasedField<aliases::Person1, person::updated>,
|
||||
AliasedField<aliases::Person1, person::ap_id>,
|
||||
|
@ -343,7 +343,6 @@ pub type Person1AliasAllColumnsTuple = (
|
|||
AliasedField<aliases::Person1, person::inbox_url>,
|
||||
AliasedField<aliases::Person1, person::matrix_user_id>,
|
||||
AliasedField<aliases::Person1, person::bot_account>,
|
||||
AliasedField<aliases::Person1, person::ban_expires>,
|
||||
AliasedField<aliases::Person1, person::instance_id>,
|
||||
AliasedField<aliases::Person1, person::post_count>,
|
||||
AliasedField<aliases::Person1, person::post_score>,
|
||||
|
@ -358,7 +357,6 @@ pub type Person2AliasAllColumnsTuple = (
|
|||
AliasedField<aliases::Person2, person::name>,
|
||||
AliasedField<aliases::Person2, person::display_name>,
|
||||
AliasedField<aliases::Person2, person::avatar>,
|
||||
AliasedField<aliases::Person2, person::banned>,
|
||||
AliasedField<aliases::Person2, person::published>,
|
||||
AliasedField<aliases::Person2, person::updated>,
|
||||
AliasedField<aliases::Person2, person::ap_id>,
|
||||
|
@ -372,7 +370,6 @@ pub type Person2AliasAllColumnsTuple = (
|
|||
AliasedField<aliases::Person2, person::inbox_url>,
|
||||
AliasedField<aliases::Person2, person::matrix_user_id>,
|
||||
AliasedField<aliases::Person2, person::bot_account>,
|
||||
AliasedField<aliases::Person2, person::ban_expires>,
|
||||
AliasedField<aliases::Person2, person::instance_id>,
|
||||
AliasedField<aliases::Person2, person::post_count>,
|
||||
AliasedField<aliases::Person2, person::post_score>,
|
||||
|
@ -393,3 +390,13 @@ pub type CreatorCommunityActionsAllColumnsTuple = (
|
|||
AliasedField<aliases::CreatorCommunityActions, community_actions::received_ban>,
|
||||
AliasedField<aliases::CreatorCommunityActions, community_actions::ban_expires>,
|
||||
);
|
||||
|
||||
#[cfg(feature = "full")]
|
||||
/// A helper tuple for creator community actions
|
||||
pub type HomeInstanceActionsAllColumnsTuple = (
|
||||
AliasedField<aliases::HomeInstanceActions, instance_actions::person_id>,
|
||||
AliasedField<aliases::HomeInstanceActions, instance_actions::instance_id>,
|
||||
AliasedField<aliases::HomeInstanceActions, instance_actions::blocked>,
|
||||
AliasedField<aliases::HomeInstanceActions, instance_actions::received_ban>,
|
||||
AliasedField<aliases::HomeInstanceActions, instance_actions::ban_expires>,
|
||||
);
|
||||
|
|
|
@ -373,6 +373,8 @@ diesel::table! {
|
|||
person_id -> Int4,
|
||||
instance_id -> Int4,
|
||||
blocked -> Nullable<Timestamptz>,
|
||||
received_ban -> Nullable<Timestamptz>,
|
||||
ban_expires -> Nullable<Timestamptz>,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -573,6 +575,7 @@ diesel::table! {
|
|||
banned -> Bool,
|
||||
expires -> Nullable<Timestamptz>,
|
||||
published -> Timestamptz,
|
||||
instance_id -> Int4,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -739,7 +742,6 @@ diesel::table! {
|
|||
#[max_length = 255]
|
||||
display_name -> Nullable<Varchar>,
|
||||
avatar -> Nullable<Text>,
|
||||
banned -> Bool,
|
||||
published -> Timestamptz,
|
||||
updated -> Nullable<Timestamptz>,
|
||||
#[max_length = 255]
|
||||
|
@ -755,7 +757,6 @@ diesel::table! {
|
|||
inbox_url -> Varchar,
|
||||
matrix_user_id -> Nullable<Text>,
|
||||
bot_account -> Bool,
|
||||
ban_expires -> Nullable<Timestamptz>,
|
||||
instance_id -> Int4,
|
||||
post_count -> Int8,
|
||||
post_score -> Int8,
|
||||
|
@ -1180,77 +1181,77 @@ diesel::joinable!(site_language -> site (site_id));
|
|||
diesel::joinable!(tag -> community (community_id));
|
||||
|
||||
diesel::allow_tables_to_appear_in_same_query!(
|
||||
admin_allow_instance,
|
||||
admin_block_instance,
|
||||
admin_purge_comment,
|
||||
admin_purge_community,
|
||||
admin_purge_person,
|
||||
admin_purge_post,
|
||||
captcha_answer,
|
||||
comment,
|
||||
comment_actions,
|
||||
comment_reply,
|
||||
comment_report,
|
||||
community,
|
||||
community_actions,
|
||||
community_language,
|
||||
community_report,
|
||||
custom_emoji,
|
||||
custom_emoji_keyword,
|
||||
email_verification,
|
||||
federation_allowlist,
|
||||
federation_blocklist,
|
||||
federation_queue_state,
|
||||
image_details,
|
||||
inbox_combined,
|
||||
instance,
|
||||
instance_actions,
|
||||
language,
|
||||
local_image,
|
||||
local_site,
|
||||
local_site_rate_limit,
|
||||
local_site_url_blocklist,
|
||||
local_user,
|
||||
local_user_language,
|
||||
login_token,
|
||||
mod_add,
|
||||
mod_add_community,
|
||||
mod_ban,
|
||||
mod_ban_from_community,
|
||||
mod_change_community_visibility,
|
||||
mod_feature_post,
|
||||
mod_lock_post,
|
||||
mod_remove_comment,
|
||||
mod_remove_community,
|
||||
mod_remove_post,
|
||||
mod_transfer_community,
|
||||
modlog_combined,
|
||||
oauth_account,
|
||||
oauth_provider,
|
||||
password_reset_request,
|
||||
person,
|
||||
person_actions,
|
||||
person_ban,
|
||||
person_comment_mention,
|
||||
person_content_combined,
|
||||
person_post_mention,
|
||||
person_saved_combined,
|
||||
post,
|
||||
post_actions,
|
||||
post_report,
|
||||
post_tag,
|
||||
previously_run_sql,
|
||||
private_message,
|
||||
private_message_report,
|
||||
received_activity,
|
||||
registration_application,
|
||||
remote_image,
|
||||
report_combined,
|
||||
search_combined,
|
||||
secret,
|
||||
sent_activity,
|
||||
site,
|
||||
site_language,
|
||||
tag,
|
||||
tagline,
|
||||
admin_allow_instance,
|
||||
admin_block_instance,
|
||||
admin_purge_comment,
|
||||
admin_purge_community,
|
||||
admin_purge_person,
|
||||
admin_purge_post,
|
||||
captcha_answer,
|
||||
comment,
|
||||
comment_actions,
|
||||
comment_reply,
|
||||
comment_report,
|
||||
community,
|
||||
community_actions,
|
||||
community_language,
|
||||
community_report,
|
||||
custom_emoji,
|
||||
custom_emoji_keyword,
|
||||
email_verification,
|
||||
federation_allowlist,
|
||||
federation_blocklist,
|
||||
federation_queue_state,
|
||||
image_details,
|
||||
inbox_combined,
|
||||
instance,
|
||||
instance_actions,
|
||||
language,
|
||||
local_image,
|
||||
local_site,
|
||||
local_site_rate_limit,
|
||||
local_site_url_blocklist,
|
||||
local_user,
|
||||
local_user_language,
|
||||
login_token,
|
||||
mod_add,
|
||||
mod_add_community,
|
||||
mod_ban,
|
||||
mod_ban_from_community,
|
||||
mod_change_community_visibility,
|
||||
mod_feature_post,
|
||||
mod_lock_post,
|
||||
mod_remove_comment,
|
||||
mod_remove_community,
|
||||
mod_remove_post,
|
||||
mod_transfer_community,
|
||||
modlog_combined,
|
||||
oauth_account,
|
||||
oauth_provider,
|
||||
password_reset_request,
|
||||
person,
|
||||
person_actions,
|
||||
person_ban,
|
||||
person_comment_mention,
|
||||
person_content_combined,
|
||||
person_post_mention,
|
||||
person_saved_combined,
|
||||
post,
|
||||
post_actions,
|
||||
post_report,
|
||||
post_tag,
|
||||
previously_run_sql,
|
||||
private_message,
|
||||
private_message_report,
|
||||
received_activity,
|
||||
registration_application,
|
||||
remote_image,
|
||||
report_combined,
|
||||
search_combined,
|
||||
secret,
|
||||
sent_activity,
|
||||
site,
|
||||
site_language,
|
||||
tag,
|
||||
tagline,
|
||||
);
|
||||
|
|
|
@ -62,6 +62,12 @@ pub struct InstanceActions {
|
|||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
/// When the instance was blocked.
|
||||
pub blocked: Option<DateTime<Utc>>,
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
/// When this user received a site ban.
|
||||
pub received_ban: Option<DateTime<Utc>>,
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
/// When their ban expires.
|
||||
pub ban_expires: Option<DateTime<Utc>>,
|
||||
}
|
||||
|
||||
#[derive(derive_new::new)]
|
||||
|
@ -73,3 +79,14 @@ pub struct InstanceBlockForm {
|
|||
#[new(value = "Utc::now()")]
|
||||
pub blocked: DateTime<Utc>,
|
||||
}
|
||||
|
||||
#[derive(derive_new::new)]
|
||||
#[cfg_attr(feature = "full", derive(Insertable, AsChangeset))]
|
||||
#[cfg_attr(feature = "full", diesel(table_name = instance_actions))]
|
||||
pub struct InstanceBanForm {
|
||||
pub person_id: PersonId,
|
||||
pub instance_id: InstanceId,
|
||||
#[new(value = "Utc::now()")]
|
||||
pub received_ban: DateTime<Utc>,
|
||||
pub ban_expires: Option<DateTime<Utc>>,
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ use crate::{
|
|||
newtypes::{
|
||||
CommentId,
|
||||
CommunityId,
|
||||
InstanceId,
|
||||
ModAddCommunityId,
|
||||
ModAddId,
|
||||
ModBanFromCommunityId,
|
||||
|
@ -210,6 +211,7 @@ pub struct ModBan {
|
|||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
pub expires: Option<DateTime<Utc>>,
|
||||
pub published: DateTime<Utc>,
|
||||
pub instance_id: InstanceId,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "full", derive(Insertable, AsChangeset))]
|
||||
|
@ -245,6 +247,7 @@ pub struct ModBanForm {
|
|||
pub reason: Option<String>,
|
||||
pub banned: Option<bool>,
|
||||
pub expires: Option<DateTime<Utc>>,
|
||||
pub instance_id: InstanceId,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
|
||||
|
|
|
@ -33,8 +33,6 @@ pub struct Person {
|
|||
/// A URL for an avatar.
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
pub avatar: Option<DbUrl>,
|
||||
/// Whether the person is banned.
|
||||
pub banned: bool,
|
||||
pub published: DateTime<Utc>,
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
pub updated: Option<DateTime<Utc>>,
|
||||
|
@ -64,9 +62,6 @@ pub struct Person {
|
|||
pub matrix_user_id: Option<String>,
|
||||
/// Whether the person is a bot account.
|
||||
pub bot_account: bool,
|
||||
/// When their ban, if it exists, expires, if at all.
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
pub ban_expires: Option<DateTime<Utc>>,
|
||||
pub instance_id: InstanceId,
|
||||
pub post_count: i64,
|
||||
#[serde(skip)]
|
||||
|
@ -88,8 +83,6 @@ pub struct PersonInsertForm {
|
|||
#[new(default)]
|
||||
pub avatar: Option<DbUrl>,
|
||||
#[new(default)]
|
||||
pub banned: Option<bool>,
|
||||
#[new(default)]
|
||||
pub published: Option<DateTime<Utc>>,
|
||||
#[new(default)]
|
||||
pub updated: Option<DateTime<Utc>>,
|
||||
|
@ -113,8 +106,6 @@ pub struct PersonInsertForm {
|
|||
pub matrix_user_id: Option<String>,
|
||||
#[new(default)]
|
||||
pub bot_account: Option<bool>,
|
||||
#[new(default)]
|
||||
pub ban_expires: Option<DateTime<Utc>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
|
@ -123,7 +114,6 @@ pub struct PersonInsertForm {
|
|||
pub struct PersonUpdateForm {
|
||||
pub display_name: Option<Option<String>>,
|
||||
pub avatar: Option<Option<DbUrl>>,
|
||||
pub banned: Option<bool>,
|
||||
pub updated: Option<Option<DateTime<Utc>>>,
|
||||
pub ap_id: Option<DbUrl>,
|
||||
pub bio: Option<Option<String>>,
|
||||
|
@ -136,7 +126,6 @@ pub struct PersonUpdateForm {
|
|||
pub inbox_url: Option<DbUrl>,
|
||||
pub matrix_user_id: Option<Option<String>>,
|
||||
pub bot_account: Option<bool>,
|
||||
pub ban_expires: Option<Option<DateTime<Utc>>>,
|
||||
}
|
||||
|
||||
#[skip_serializing_none]
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
use crate::structs::{
|
||||
CommentReplyView,
|
||||
InboxCombinedView,
|
||||
InboxCombinedViewInternal,
|
||||
PersonCommentMentionView,
|
||||
PersonPostMentionView,
|
||||
PrivateMessageView,
|
||||
use crate::{
|
||||
structs::{
|
||||
CommentReplyView,
|
||||
InboxCombinedView,
|
||||
InboxCombinedViewInternal,
|
||||
PersonCommentMentionView,
|
||||
PersonPostMentionView,
|
||||
PrivateMessageView,
|
||||
},
|
||||
utils::home_instance_person_join,
|
||||
};
|
||||
use diesel::{
|
||||
dsl::not,
|
||||
|
@ -52,16 +55,18 @@ impl InboxCombinedViewInternal {
|
|||
let item_creator = person::id;
|
||||
let recipient_person = aliases::person1.field(person::id);
|
||||
|
||||
let item_creator_join = person::table.on(
|
||||
comment::creator_id
|
||||
.eq(item_creator)
|
||||
.or(
|
||||
inbox_combined::person_post_mention_id
|
||||
.is_not_null()
|
||||
.and(post::creator_id.eq(item_creator)),
|
||||
)
|
||||
.or(private_message::creator_id.eq(item_creator)),
|
||||
);
|
||||
let item_creator_join = person::table
|
||||
.on(
|
||||
comment::creator_id
|
||||
.eq(item_creator)
|
||||
.or(
|
||||
inbox_combined::person_post_mention_id
|
||||
.is_not_null()
|
||||
.and(post::creator_id.eq(item_creator)),
|
||||
)
|
||||
.or(private_message::creator_id.eq(item_creator)),
|
||||
)
|
||||
.left_join(home_instance_person_join());
|
||||
|
||||
let recipient_join = aliases::person1.on(
|
||||
comment_reply::recipient_id
|
||||
|
@ -390,6 +395,7 @@ impl InternalToCombinedView for InboxCombinedViewInternal {
|
|||
comment_actions: v.comment_actions,
|
||||
person_actions: v.person_actions,
|
||||
instance_actions: v.instance_actions,
|
||||
home_instance_actions: v.home_instance_actions,
|
||||
creator_community_actions: v.creator_community_actions,
|
||||
creator_is_admin: v.item_creator_is_admin,
|
||||
can_mod: v.can_mod,
|
||||
|
@ -412,6 +418,7 @@ impl InternalToCombinedView for InboxCombinedViewInternal {
|
|||
comment_actions: v.comment_actions,
|
||||
person_actions: v.person_actions,
|
||||
instance_actions: v.instance_actions,
|
||||
home_instance_actions: v.home_instance_actions,
|
||||
creator_community_actions: v.creator_community_actions,
|
||||
creator_is_admin: v.item_creator_is_admin,
|
||||
can_mod: v.can_mod,
|
||||
|
@ -429,6 +436,7 @@ impl InternalToCombinedView for InboxCombinedViewInternal {
|
|||
community_actions: v.community_actions,
|
||||
person_actions: v.person_actions,
|
||||
instance_actions: v.instance_actions,
|
||||
home_instance_actions: v.home_instance_actions,
|
||||
post_actions: v.post_actions,
|
||||
image_details: v.image_details,
|
||||
creator_community_actions: v.creator_community_actions,
|
||||
|
|
|
@ -990,6 +990,7 @@ mod tests {
|
|||
banned: Some(true),
|
||||
reason: None,
|
||||
expires: None,
|
||||
instance_id: data.instance.id,
|
||||
};
|
||||
ModBan::create(pool, &form).await?;
|
||||
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
use crate::structs::{
|
||||
CommentView,
|
||||
LocalUserView,
|
||||
PersonContentCombinedView,
|
||||
PersonContentCombinedViewInternal,
|
||||
PostView,
|
||||
use crate::{
|
||||
structs::{
|
||||
CommentView,
|
||||
LocalUserView,
|
||||
PersonContentCombinedView,
|
||||
PersonContentCombinedViewInternal,
|
||||
PostView,
|
||||
},
|
||||
utils::home_instance_person_join,
|
||||
};
|
||||
use diesel::{
|
||||
BoolExpressionMethods,
|
||||
|
@ -54,17 +57,19 @@ impl PersonContentCombinedViewInternal {
|
|||
.or(comment::post_id.eq(post::id)),
|
||||
);
|
||||
|
||||
let item_creator_join = person::table.on(
|
||||
comment::creator_id
|
||||
.eq(item_creator)
|
||||
// Need to filter out the post rows where the post_id given is null
|
||||
// Otherwise you'll get duped post rows
|
||||
.or(
|
||||
post::creator_id
|
||||
.eq(item_creator)
|
||||
.and(person_content_combined::post_id.is_not_null()),
|
||||
),
|
||||
);
|
||||
let item_creator_join = person::table
|
||||
.on(
|
||||
comment::creator_id
|
||||
.eq(item_creator)
|
||||
// Need to filter out the post rows where the post_id given is null
|
||||
// Otherwise you'll get duped post rows
|
||||
.or(
|
||||
post::creator_id
|
||||
.eq(item_creator)
|
||||
.and(person_content_combined::post_id.is_not_null()),
|
||||
),
|
||||
)
|
||||
.left_join(home_instance_person_join());
|
||||
|
||||
let community_join = community::table.on(post::community_id.eq(community::id));
|
||||
|
||||
|
@ -257,6 +262,7 @@ impl InternalToCombinedView for PersonContentCombinedViewInternal {
|
|||
comment_actions: v.comment_actions,
|
||||
person_actions: v.person_actions,
|
||||
instance_actions: v.instance_actions,
|
||||
home_instance_actions: v.home_instance_actions,
|
||||
creator_community_actions: v.creator_community_actions,
|
||||
creator_is_admin: v.item_creator_is_admin,
|
||||
can_mod: v.can_mod,
|
||||
|
@ -271,6 +277,7 @@ impl InternalToCombinedView for PersonContentCombinedViewInternal {
|
|||
post_actions: v.post_actions,
|
||||
person_actions: v.person_actions,
|
||||
instance_actions: v.instance_actions,
|
||||
home_instance_actions: v.home_instance_actions,
|
||||
creator_community_actions: v.creator_community_actions,
|
||||
creator_is_admin: v.item_creator_is_admin,
|
||||
can_mod: v.can_mod,
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
use crate::structs::{
|
||||
CommentView,
|
||||
LocalUserView,
|
||||
PersonSavedCombinedView,
|
||||
PersonSavedCombinedViewInternal,
|
||||
PostView,
|
||||
use crate::{
|
||||
structs::{
|
||||
CommentView,
|
||||
LocalUserView,
|
||||
PersonSavedCombinedView,
|
||||
PersonSavedCombinedViewInternal,
|
||||
PostView,
|
||||
},
|
||||
utils::home_instance_person_join,
|
||||
};
|
||||
use diesel::{
|
||||
BoolExpressionMethods,
|
||||
|
@ -93,17 +96,19 @@ impl PersonSavedCombinedViewInternal {
|
|||
.or(comment::post_id.eq(post::id)),
|
||||
);
|
||||
|
||||
let item_creator_join = person::table.on(
|
||||
comment::creator_id
|
||||
.eq(item_creator)
|
||||
// Need to filter out the post rows where the post_id given is null
|
||||
// Otherwise you'll get duped post rows
|
||||
.or(
|
||||
post::creator_id
|
||||
.eq(item_creator)
|
||||
.and(person_saved_combined::post_id.is_not_null()),
|
||||
),
|
||||
);
|
||||
let item_creator_join = person::table
|
||||
.on(
|
||||
comment::creator_id
|
||||
.eq(item_creator)
|
||||
// Need to filter out the post rows where the post_id given is null
|
||||
// Otherwise you'll get duped post rows
|
||||
.or(
|
||||
post::creator_id
|
||||
.eq(item_creator)
|
||||
.and(person_saved_combined::post_id.is_not_null()),
|
||||
),
|
||||
)
|
||||
.left_join(home_instance_person_join());
|
||||
|
||||
let community_join = community::table.on(post::community_id.eq(community::id));
|
||||
|
||||
|
@ -244,6 +249,7 @@ impl InternalToCombinedView for PersonSavedCombinedViewInternal {
|
|||
comment_actions: v.comment_actions,
|
||||
person_actions: v.person_actions,
|
||||
instance_actions: v.instance_actions,
|
||||
home_instance_actions: v.home_instance_actions,
|
||||
creator_community_actions: v.creator_community_actions,
|
||||
creator_is_admin: v.item_creator_is_admin,
|
||||
can_mod: v.can_mod,
|
||||
|
@ -258,6 +264,7 @@ impl InternalToCombinedView for PersonSavedCombinedViewInternal {
|
|||
post_actions: v.post_actions,
|
||||
person_actions: v.person_actions,
|
||||
instance_actions: v.instance_actions,
|
||||
home_instance_actions: v.home_instance_actions,
|
||||
creator_community_actions: v.creator_community_actions,
|
||||
creator_is_admin: v.item_creator_is_admin,
|
||||
can_mod: v.can_mod,
|
||||
|
@ -310,6 +317,7 @@ mod tests {
|
|||
let timmy_view = LocalUserView {
|
||||
local_user: timmy_local_user,
|
||||
person: timmy.clone(),
|
||||
instance_actions: None,
|
||||
};
|
||||
|
||||
let sara_form = PersonInsertForm::test_form(instance.id, "sara_pcv");
|
||||
|
|
|
@ -513,6 +513,7 @@ mod tests {
|
|||
let timmy_view = LocalUserView {
|
||||
local_user: timmy_local_user,
|
||||
person: inserted_timmy.clone(),
|
||||
instance_actions: None,
|
||||
};
|
||||
|
||||
// Make an admin, to be able to see private message reports.
|
||||
|
@ -523,6 +524,7 @@ mod tests {
|
|||
let admin_view = LocalUserView {
|
||||
local_user: admin_local_user,
|
||||
person: inserted_admin.clone(),
|
||||
instance_actions: None,
|
||||
};
|
||||
|
||||
let sara_form = PersonInsertForm::test_form(inserted_instance.id, "sara_rcv");
|
||||
|
|
|
@ -8,7 +8,7 @@ use crate::{
|
|||
SearchCombinedView,
|
||||
SearchCombinedViewInternal,
|
||||
},
|
||||
utils::{filter_is_subscribed, filter_not_unlisted_or_is_subscribed},
|
||||
utils::{filter_is_subscribed, filter_not_unlisted_or_is_subscribed, home_instance_person_join},
|
||||
};
|
||||
use diesel::{
|
||||
dsl::not,
|
||||
|
@ -54,21 +54,23 @@ impl SearchCombinedViewInternal {
|
|||
fn joins(my_person_id: Option<PersonId>) -> _ {
|
||||
let item_creator = person::id;
|
||||
|
||||
let item_creator_join = person::table.on(
|
||||
search_combined::person_id
|
||||
.eq(item_creator.nullable())
|
||||
.or(
|
||||
search_combined::comment_id
|
||||
.is_not_null()
|
||||
.and(comment::creator_id.eq(item_creator)),
|
||||
)
|
||||
.or(
|
||||
search_combined::post_id
|
||||
.is_not_null()
|
||||
.and(post::creator_id.eq(item_creator)),
|
||||
)
|
||||
.and(not(person::deleted)),
|
||||
);
|
||||
let item_creator_join = person::table
|
||||
.on(
|
||||
search_combined::person_id
|
||||
.eq(item_creator.nullable())
|
||||
.or(
|
||||
search_combined::comment_id
|
||||
.is_not_null()
|
||||
.and(comment::creator_id.eq(item_creator)),
|
||||
)
|
||||
.or(
|
||||
search_combined::post_id
|
||||
.is_not_null()
|
||||
.and(post::creator_id.eq(item_creator)),
|
||||
)
|
||||
.and(not(person::deleted)),
|
||||
)
|
||||
.left_join(home_instance_person_join());
|
||||
|
||||
let comment_join = comment::table.on(
|
||||
search_combined::comment_id
|
||||
|
@ -381,6 +383,7 @@ impl InternalToCombinedView for SearchCombinedViewInternal {
|
|||
creator,
|
||||
community_actions: v.community_actions,
|
||||
instance_actions: v.instance_actions,
|
||||
home_instance_actions: v.home_instance_actions,
|
||||
creator_community_actions: v.creator_community_actions,
|
||||
person_actions: v.person_actions,
|
||||
comment_actions: v.comment_actions,
|
||||
|
@ -398,6 +401,7 @@ impl InternalToCombinedView for SearchCombinedViewInternal {
|
|||
image_details: v.image_details,
|
||||
community_actions: v.community_actions,
|
||||
instance_actions: v.instance_actions,
|
||||
home_instance_actions: v.home_instance_actions,
|
||||
creator_community_actions: v.creator_community_actions,
|
||||
person_actions: v.person_actions,
|
||||
post_actions: v.post_actions,
|
||||
|
@ -414,6 +418,8 @@ impl InternalToCombinedView for SearchCombinedViewInternal {
|
|||
Some(SearchCombinedView::Person(PersonView {
|
||||
person,
|
||||
is_admin: v.item_creator_is_admin,
|
||||
instance_actions: v.instance_actions,
|
||||
home_instance_actions: v.home_instance_actions,
|
||||
}))
|
||||
} else {
|
||||
None
|
||||
|
@ -477,6 +483,7 @@ mod tests {
|
|||
let timmy_view = LocalUserView {
|
||||
local_user: timmy_local_user,
|
||||
person: timmy.clone(),
|
||||
instance_actions: None,
|
||||
};
|
||||
|
||||
let community_form = CommunityInsertForm {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::{
|
||||
structs::{CommentSlimView, CommentView},
|
||||
utils::filter_blocked,
|
||||
utils::{filter_blocked, home_instance_person_join},
|
||||
};
|
||||
use diesel::{
|
||||
dsl::exists,
|
||||
|
@ -79,8 +79,10 @@ impl CommentView {
|
|||
|
||||
let local_user_join = local_user::table.on(local_user::person_id.nullable().eq(my_person_id));
|
||||
|
||||
let person_join = person::table.left_join(home_instance_person_join());
|
||||
|
||||
comment::table
|
||||
.inner_join(person::table)
|
||||
.inner_join(person_join)
|
||||
.inner_join(post::table)
|
||||
.inner_join(community_join)
|
||||
.left_join(community_actions_join)
|
||||
|
@ -128,6 +130,7 @@ impl CommentView {
|
|||
creator_community_actions: self.creator_community_actions,
|
||||
person_actions: self.person_actions,
|
||||
instance_actions: self.instance_actions,
|
||||
home_instance_actions: self.home_instance_actions,
|
||||
creator_is_admin: self.creator_is_admin,
|
||||
can_mod: self.can_mod,
|
||||
}
|
||||
|
@ -488,6 +491,7 @@ mod tests {
|
|||
let timmy_local_user_view = LocalUserView {
|
||||
local_user: inserted_timmy_local_user.clone(),
|
||||
person: inserted_timmy_person.clone(),
|
||||
instance_actions: None,
|
||||
};
|
||||
let site_form = SiteInsertForm::new("test site".to_string(), inserted_instance.id);
|
||||
let site = Site::create(pool, &site_form).await?;
|
||||
|
|
|
@ -31,6 +31,7 @@ impl CommunityView {
|
|||
.and(community_actions::person_id.nullable().eq(person_id)),
|
||||
);
|
||||
|
||||
// join with instance actions for community instance
|
||||
let instance_actions_join = instance_actions::table.on(
|
||||
instance_actions::instance_id
|
||||
.eq(community::instance_id)
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
use crate::structs::LocalUserView;
|
||||
use crate::{
|
||||
structs::{LocalUserView, SiteView},
|
||||
utils::local_instance_person_join,
|
||||
};
|
||||
use actix_web::{dev::Payload, FromRequest, HttpMessage, HttpRequest};
|
||||
use diesel::{result::Error, BoolExpressionMethods, ExpressionMethods, QueryDsl, SelectableHelper};
|
||||
use diesel::{BoolExpressionMethods, ExpressionMethods, QueryDsl, SelectableHelper};
|
||||
use diesel_async::RunQueryDsl;
|
||||
use lemmy_db_schema::{
|
||||
newtypes::{LocalUserId, OAuthProviderId, PersonId},
|
||||
newtypes::{InstanceId, LocalUserId, OAuthProviderId, PersonId},
|
||||
schema::{local_user, oauth_account, person},
|
||||
source::{
|
||||
instance::Instance,
|
||||
|
@ -17,90 +20,112 @@ use lemmy_db_schema::{
|
|||
DbPool,
|
||||
},
|
||||
};
|
||||
use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType, LemmyResult};
|
||||
use lemmy_utils::error::{LemmyError, LemmyErrorExt2, LemmyErrorType, LemmyResult};
|
||||
use std::future::{ready, Ready};
|
||||
|
||||
impl LocalUserView {
|
||||
#[diesel::dsl::auto_type(no_type_alias)]
|
||||
fn joins() -> _ {
|
||||
local_user::table.inner_join(person::table)
|
||||
fn joins(local_instance_id: InstanceId) -> _ {
|
||||
let p: local_instance_person_join = local_instance_person_join(local_instance_id);
|
||||
local_user::table.inner_join(person::table.left_join(p))
|
||||
}
|
||||
|
||||
pub async fn read(pool: &mut DbPool<'_>, local_user_id: LocalUserId) -> Result<Self, Error> {
|
||||
pub async fn read(pool: &mut DbPool<'_>, local_user_id: LocalUserId) -> LemmyResult<Self> {
|
||||
let local_instance_id = SiteView::read_local(pool).await?.instance.id;
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
Self::joins()
|
||||
.filter(local_user::id.eq(local_user_id))
|
||||
.select(Self::as_select())
|
||||
.first(conn)
|
||||
.await
|
||||
Ok(
|
||||
Self::joins(local_instance_id)
|
||||
.filter(local_user::id.eq(local_user_id))
|
||||
.select(Self::as_select())
|
||||
.first(conn)
|
||||
.await?,
|
||||
)
|
||||
}
|
||||
|
||||
pub async fn read_person(pool: &mut DbPool<'_>, person_id: PersonId) -> Result<Self, Error> {
|
||||
pub async fn read_person(pool: &mut DbPool<'_>, person_id: PersonId) -> LemmyResult<Self> {
|
||||
let local_instance_id = SiteView::read_local(pool).await?.instance.id;
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
Self::joins()
|
||||
.filter(person::id.eq(person_id))
|
||||
.select(Self::as_select())
|
||||
.first(conn)
|
||||
.await
|
||||
Ok(
|
||||
Self::joins(local_instance_id)
|
||||
.filter(person::id.eq(person_id))
|
||||
.select(Self::as_select())
|
||||
.first(conn)
|
||||
.await?,
|
||||
)
|
||||
}
|
||||
|
||||
pub async fn read_from_name(pool: &mut DbPool<'_>, name: &str) -> Result<Self, Error> {
|
||||
pub async fn read_from_name(pool: &mut DbPool<'_>, name: &str) -> LemmyResult<Self> {
|
||||
let local_instance_id = SiteView::read_local(pool).await?.instance.id;
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
Self::joins()
|
||||
.filter(lower(person::name).eq(name.to_lowercase()))
|
||||
.select(Self::as_select())
|
||||
.first(conn)
|
||||
.await
|
||||
Ok(
|
||||
Self::joins(local_instance_id)
|
||||
.filter(lower(person::name).eq(name.to_lowercase()))
|
||||
.select(Self::as_select())
|
||||
.first(conn)
|
||||
.await?,
|
||||
)
|
||||
}
|
||||
|
||||
pub async fn find_by_email_or_name(
|
||||
pool: &mut DbPool<'_>,
|
||||
name_or_email: &str,
|
||||
) -> Result<Self, Error> {
|
||||
) -> LemmyResult<Self> {
|
||||
let local_instance_id = SiteView::read_local(pool).await?.instance.id;
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
Self::joins()
|
||||
.filter(
|
||||
lower(person::name)
|
||||
.eq(lower(name_or_email.to_lowercase()))
|
||||
.or(lower(coalesce(local_user::email, "")).eq(name_or_email.to_lowercase())),
|
||||
)
|
||||
.select(Self::as_select())
|
||||
.first(conn)
|
||||
.await
|
||||
Ok(
|
||||
Self::joins(local_instance_id)
|
||||
.filter(
|
||||
lower(person::name)
|
||||
.eq(lower(name_or_email.to_lowercase()))
|
||||
.or(lower(coalesce(local_user::email, "")).eq(name_or_email.to_lowercase())),
|
||||
)
|
||||
.select(Self::as_select())
|
||||
.first(conn)
|
||||
.await?,
|
||||
)
|
||||
}
|
||||
|
||||
pub async fn find_by_email(pool: &mut DbPool<'_>, from_email: &str) -> Result<Self, Error> {
|
||||
pub async fn find_by_email(pool: &mut DbPool<'_>, from_email: &str) -> LemmyResult<Self> {
|
||||
let local_instance_id = SiteView::read_local(pool).await?.instance.id;
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
Self::joins()
|
||||
.filter(lower(coalesce(local_user::email, "")).eq(from_email.to_lowercase()))
|
||||
.select(Self::as_select())
|
||||
.first(conn)
|
||||
.await
|
||||
Ok(
|
||||
Self::joins(local_instance_id)
|
||||
.filter(lower(coalesce(local_user::email, "")).eq(from_email.to_lowercase()))
|
||||
.select(Self::as_select())
|
||||
.first(conn)
|
||||
.await?,
|
||||
)
|
||||
}
|
||||
|
||||
pub async fn find_by_oauth_id(
|
||||
pool: &mut DbPool<'_>,
|
||||
oauth_provider_id: OAuthProviderId,
|
||||
oauth_user_id: &str,
|
||||
) -> Result<Self, Error> {
|
||||
) -> LemmyResult<Self> {
|
||||
let local_instance_id = SiteView::read_local(pool).await?.instance.id;
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
Self::joins()
|
||||
.inner_join(oauth_account::table)
|
||||
.filter(oauth_account::oauth_provider_id.eq(oauth_provider_id))
|
||||
.filter(oauth_account::oauth_user_id.eq(oauth_user_id))
|
||||
.select(Self::as_select())
|
||||
.first(conn)
|
||||
.await
|
||||
Ok(
|
||||
Self::joins(local_instance_id)
|
||||
.inner_join(oauth_account::table)
|
||||
.filter(oauth_account::oauth_provider_id.eq(oauth_provider_id))
|
||||
.filter(oauth_account::oauth_user_id.eq(oauth_user_id))
|
||||
.select(Self::as_select())
|
||||
.first(conn)
|
||||
.await?,
|
||||
)
|
||||
}
|
||||
|
||||
pub async fn list_admins_with_emails(pool: &mut DbPool<'_>) -> Result<Vec<Self>, Error> {
|
||||
pub async fn list_admins_with_emails(pool: &mut DbPool<'_>) -> LemmyResult<Vec<Self>> {
|
||||
let local_instance_id = SiteView::read_local(pool).await?.instance.id;
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
Self::joins()
|
||||
.filter(local_user::email.is_not_null())
|
||||
.filter(local_user::admin.eq(true))
|
||||
.select(Self::as_select())
|
||||
.load::<Self>(conn)
|
||||
.await
|
||||
Ok(
|
||||
Self::joins(local_instance_id)
|
||||
.filter(local_user::email.is_not_null())
|
||||
.filter(local_user::admin.eq(true))
|
||||
.select(Self::as_select())
|
||||
.load::<Self>(conn)
|
||||
.await?,
|
||||
)
|
||||
}
|
||||
|
||||
pub async fn create_test_user(
|
||||
|
@ -129,6 +154,13 @@ impl LocalUserView {
|
|||
.await
|
||||
.with_lemmy_type(LemmyErrorType::NotFound)
|
||||
}
|
||||
|
||||
pub fn banned(&self) -> bool {
|
||||
self
|
||||
.instance_actions
|
||||
.as_ref()
|
||||
.is_some_and(|i| i.received_ban.is_some())
|
||||
}
|
||||
}
|
||||
|
||||
impl FromRequest for LocalUserView {
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
use crate::structs::PersonView;
|
||||
use crate::{
|
||||
structs::{PersonView, SiteView},
|
||||
utils::{home_instance_person_join, local_instance_person_join},
|
||||
};
|
||||
use diesel::{
|
||||
result::Error,
|
||||
BoolExpressionMethods,
|
||||
ExpressionMethods,
|
||||
NullableExpressionMethods,
|
||||
|
@ -10,8 +12,8 @@ use diesel::{
|
|||
use diesel_async::RunQueryDsl;
|
||||
use i_love_jesus::PaginatedQueryBuilder;
|
||||
use lemmy_db_schema::{
|
||||
newtypes::{PaginationCursor, PersonId},
|
||||
schema::{local_user, person},
|
||||
newtypes::{InstanceId, PaginationCursor, PersonId},
|
||||
schema::{instance_actions, local_user, person},
|
||||
source::person::{person_keys as key, Person},
|
||||
traits::PaginationCursorBuilder,
|
||||
utils::{get_conn, limit_fetch, now, DbPool},
|
||||
|
@ -44,17 +46,22 @@ impl PaginationCursorBuilder for PersonView {
|
|||
|
||||
impl PersonView {
|
||||
#[diesel::dsl::auto_type(no_type_alias)]
|
||||
fn joins() -> _ {
|
||||
person::table.left_join(local_user::table)
|
||||
fn joins(local_instance_id: InstanceId) -> _ {
|
||||
let p: local_instance_person_join = local_instance_person_join(local_instance_id);
|
||||
person::table
|
||||
.left_join(p)
|
||||
.left_join(local_user::table)
|
||||
.left_join(home_instance_person_join())
|
||||
}
|
||||
|
||||
pub async fn read(
|
||||
pool: &mut DbPool<'_>,
|
||||
person_id: PersonId,
|
||||
is_admin: bool,
|
||||
) -> Result<Self, Error> {
|
||||
) -> LemmyResult<Self> {
|
||||
let local_instance_id = SiteView::read_local(pool).await?.instance.id;
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
let mut query = Self::joins()
|
||||
let mut query = Self::joins(local_instance_id)
|
||||
.filter(person::id.eq(person_id))
|
||||
.select(Self::as_select())
|
||||
.into_boxed();
|
||||
|
@ -63,7 +70,14 @@ impl PersonView {
|
|||
query = query.filter(person::deleted.eq(false))
|
||||
}
|
||||
|
||||
query.first(conn).await
|
||||
Ok(query.first(conn).await?)
|
||||
}
|
||||
|
||||
pub fn banned(&self) -> bool {
|
||||
self
|
||||
.instance_actions
|
||||
.as_ref()
|
||||
.is_some_and(|i| i.received_ban.is_some())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -77,10 +91,13 @@ pub struct PersonQuery {
|
|||
}
|
||||
|
||||
impl PersonQuery {
|
||||
pub async fn list(self, pool: &mut DbPool<'_>) -> Result<Vec<PersonView>, Error> {
|
||||
pub async fn list(
|
||||
self,
|
||||
local_instance_id: InstanceId,
|
||||
pool: &mut DbPool<'_>,
|
||||
) -> LemmyResult<Vec<PersonView>> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
|
||||
let mut query = PersonView::joins()
|
||||
let mut query = PersonView::joins(local_instance_id)
|
||||
.filter(person::deleted.eq(false))
|
||||
.select(PersonView::as_select())
|
||||
.into_boxed();
|
||||
|
@ -88,11 +105,13 @@ impl PersonQuery {
|
|||
// Filters
|
||||
if self.banned_only.unwrap_or_default() {
|
||||
query = query.filter(
|
||||
person::local.and(person::banned).and(
|
||||
person::ban_expires
|
||||
.is_null()
|
||||
.or(person::ban_expires.gt(now().nullable())),
|
||||
),
|
||||
person::local
|
||||
.and(instance_actions::received_ban.is_not_null())
|
||||
.and(
|
||||
instance_actions::ban_expires
|
||||
.is_null()
|
||||
.or(instance_actions::ban_expires.gt(now().nullable())),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -128,14 +147,15 @@ impl PersonQuery {
|
|||
mod tests {
|
||||
|
||||
use super::*;
|
||||
use crate::site::site_view::create_test_instance;
|
||||
use lemmy_db_schema::{
|
||||
assert_length,
|
||||
source::{
|
||||
instance::Instance,
|
||||
instance::{Instance, InstanceActions, InstanceBanForm},
|
||||
local_user::{LocalUser, LocalUserInsertForm, LocalUserUpdateForm},
|
||||
person::{Person, PersonInsertForm, PersonUpdateForm},
|
||||
},
|
||||
traits::Crud,
|
||||
traits::{Bannable, Crud},
|
||||
utils::build_db_pool_for_tests,
|
||||
};
|
||||
use lemmy_utils::error::LemmyResult;
|
||||
|
@ -150,11 +170,11 @@ mod tests {
|
|||
}
|
||||
|
||||
async fn init_data(pool: &mut DbPool<'_>) -> LemmyResult<Data> {
|
||||
let inserted_instance = Instance::read_or_create(pool, "my_domain.tld".to_string()).await?;
|
||||
let instance = create_test_instance(pool).await?;
|
||||
|
||||
let alice_form = PersonInsertForm {
|
||||
local: Some(true),
|
||||
..PersonInsertForm::test_form(inserted_instance.id, "alice")
|
||||
..PersonInsertForm::test_form(instance.id, "alice")
|
||||
};
|
||||
let alice = Person::create(pool, &alice_form).await?;
|
||||
let alice_local_user_form = LocalUserInsertForm::test_form(alice.id);
|
||||
|
@ -163,7 +183,7 @@ mod tests {
|
|||
let bob_form = PersonInsertForm {
|
||||
bot_account: Some(true),
|
||||
local: Some(false),
|
||||
..PersonInsertForm::test_form(inserted_instance.id, "bob")
|
||||
..PersonInsertForm::test_form(instance.id, "bob")
|
||||
};
|
||||
let bob = Person::create(pool, &bob_form).await?;
|
||||
let bob_local_user_form = LocalUserInsertForm::test_form(bob.id);
|
||||
|
@ -220,13 +240,9 @@ mod tests {
|
|||
let pool = &mut pool.into();
|
||||
let data = init_data(pool).await?;
|
||||
|
||||
Person::update(
|
||||
InstanceActions::ban(
|
||||
pool,
|
||||
data.alice.id,
|
||||
&PersonUpdateForm {
|
||||
banned: Some(true),
|
||||
..Default::default()
|
||||
},
|
||||
&InstanceBanForm::new(data.alice.id, data.alice.instance_id, None),
|
||||
)
|
||||
.await?;
|
||||
|
||||
|
@ -234,7 +250,7 @@ mod tests {
|
|||
banned_only: Some(true),
|
||||
..Default::default()
|
||||
}
|
||||
.list(pool)
|
||||
.list(data.alice.instance_id, pool)
|
||||
.await?;
|
||||
assert_length!(1, list);
|
||||
assert_eq!(list[0].person.id, data.alice.id);
|
||||
|
@ -263,7 +279,7 @@ mod tests {
|
|||
admins_only: Some(true),
|
||||
..Default::default()
|
||||
}
|
||||
.list(pool)
|
||||
.list(data.alice.instance_id, pool)
|
||||
.await?;
|
||||
assert_length!(1, list);
|
||||
assert_eq!(list[0].person.id, data.alice.id);
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
use crate::{
|
||||
structs::{PostPaginationCursor, PostView},
|
||||
utils::{filter_blocked, filter_is_subscribed, filter_not_unlisted_or_is_subscribed},
|
||||
utils::{
|
||||
filter_blocked,
|
||||
filter_is_subscribed,
|
||||
filter_not_unlisted_or_is_subscribed,
|
||||
home_instance_person_join,
|
||||
},
|
||||
};
|
||||
use diesel::{
|
||||
debug_query,
|
||||
|
@ -107,8 +112,10 @@ impl PostView {
|
|||
|
||||
let local_user_join = local_user::table.on(local_user::person_id.nullable().eq(my_person_id));
|
||||
|
||||
let person_join = person::table.left_join(home_instance_person_join());
|
||||
|
||||
post::table
|
||||
.inner_join(person::table)
|
||||
.inner_join(person_join)
|
||||
.inner_join(community::table)
|
||||
.left_join(image_details_join)
|
||||
.left_join(community_actions_join)
|
||||
|
@ -787,15 +794,18 @@ mod tests {
|
|||
let tegan_local_user_view = LocalUserView {
|
||||
local_user: inserted_tegan_local_user,
|
||||
person: inserted_tegan_person,
|
||||
instance_actions: None,
|
||||
};
|
||||
let john_local_user_view = LocalUserView {
|
||||
local_user: inserted_john_local_user,
|
||||
person: inserted_john_person,
|
||||
instance_actions: None,
|
||||
};
|
||||
|
||||
let bot_local_user_view = LocalUserView {
|
||||
local_user: inserted_bot_local_user,
|
||||
person: inserted_bot_person,
|
||||
instance_actions: None,
|
||||
};
|
||||
|
||||
let site = Site {
|
||||
|
|
|
@ -233,8 +233,6 @@ mod tests {
|
|||
avatar: None,
|
||||
ap_id: sara_person.ap_id.clone(),
|
||||
local: true,
|
||||
banned: false,
|
||||
ban_expires: None,
|
||||
deleted: false,
|
||||
bot_account: false,
|
||||
bio: None,
|
||||
|
@ -306,8 +304,6 @@ mod tests {
|
|||
avatar: None,
|
||||
ap_id: timmy_person.ap_id.clone(),
|
||||
local: true,
|
||||
banned: false,
|
||||
ban_expires: None,
|
||||
deleted: false,
|
||||
bot_account: false,
|
||||
bio: None,
|
||||
|
|
|
@ -2,25 +2,52 @@ use crate::structs::SiteView;
|
|||
use diesel::{ExpressionMethods, JoinOnDsl, OptionalExtension, QueryDsl, SelectableHelper};
|
||||
use diesel_async::RunQueryDsl;
|
||||
use lemmy_db_schema::{
|
||||
schema::{local_site, local_site_rate_limit, site},
|
||||
schema::{instance, local_site, local_site_rate_limit, site},
|
||||
source::{
|
||||
instance::Instance,
|
||||
local_site::{LocalSite, LocalSiteInsertForm},
|
||||
local_site_rate_limit::{LocalSiteRateLimit, LocalSiteRateLimitInsertForm},
|
||||
site::{Site, SiteInsertForm},
|
||||
},
|
||||
traits::Crud,
|
||||
utils::{get_conn, DbPool},
|
||||
};
|
||||
use lemmy_utils::error::{LemmyErrorType, LemmyResult};
|
||||
use lemmy_utils::{
|
||||
build_cache,
|
||||
error::{LemmyError, LemmyErrorType, LemmyResult},
|
||||
CacheLock,
|
||||
};
|
||||
use std::sync::{Arc, LazyLock};
|
||||
|
||||
impl SiteView {
|
||||
pub async fn read_local(pool: &mut DbPool<'_>) -> LemmyResult<Self> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
Ok(
|
||||
site::table
|
||||
.inner_join(local_site::table)
|
||||
.inner_join(
|
||||
local_site_rate_limit::table.on(local_site::id.eq(local_site_rate_limit::local_site_id)),
|
||||
)
|
||||
.select(Self::as_select())
|
||||
.first(conn)
|
||||
.await
|
||||
.optional()?
|
||||
.ok_or(LemmyErrorType::LocalSiteNotSetup)?,
|
||||
)
|
||||
static CACHE: CacheLock<SiteView> = LazyLock::new(build_cache);
|
||||
CACHE
|
||||
.try_get_with((), async move {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
let local_site = site::table
|
||||
.inner_join(local_site::table)
|
||||
.inner_join(instance::table)
|
||||
.inner_join(
|
||||
local_site_rate_limit::table
|
||||
.on(local_site::id.eq(local_site_rate_limit::local_site_id)),
|
||||
)
|
||||
.select(Self::as_select())
|
||||
.first(conn)
|
||||
.await
|
||||
.optional()?
|
||||
.ok_or(LemmyErrorType::LocalSiteNotSetup)?;
|
||||
Ok(local_site)
|
||||
})
|
||||
.await
|
||||
.map_err(|_e: Arc<LemmyError>| LemmyErrorType::LocalSiteNotSetup.into())
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn create_test_instance(pool: &mut DbPool<'_>) -> LemmyResult<Instance> {
|
||||
let instance = Instance::read_or_create(pool, "example.com".to_string()).await?;
|
||||
let site = Site::create(pool, &SiteInsertForm::new("name".to_string(), instance.id)).await?;
|
||||
let local_site = LocalSite::create(pool, &LocalSiteInsertForm::new(site.id)).await?;
|
||||
LocalSiteRateLimit::create(pool, &LocalSiteRateLimitInsertForm::new(local_site.id)).await?;
|
||||
Ok(instance)
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ use crate::utils::{
|
|||
comment_select_remove_deletes,
|
||||
creator_community_actions_select,
|
||||
creator_is_admin,
|
||||
home_instance_actions_select,
|
||||
local_user_can_mod,
|
||||
local_user_community_can_mod,
|
||||
local_user_is_admin,
|
||||
|
@ -80,6 +81,7 @@ use lemmy_db_schema::{
|
|||
schema::local_user,
|
||||
utils::functions::coalesce,
|
||||
CreatorCommunityActionsAllColumnsTuple,
|
||||
HomeInstanceActionsAllColumnsTuple,
|
||||
Person1AliasAllColumnsTuple,
|
||||
Person2AliasAllColumnsTuple,
|
||||
};
|
||||
|
@ -177,6 +179,11 @@ pub struct CommentView {
|
|||
#[cfg_attr(feature = "full", diesel(embed))]
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
pub instance_actions: Option<InstanceActions>,
|
||||
#[cfg_attr(feature = "full", diesel(
|
||||
select_expression_type = Nullable<HomeInstanceActionsAllColumnsTuple>,
|
||||
select_expression = home_instance_actions_select()))]
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
pub home_instance_actions: Option<InstanceActions>,
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
#[cfg_attr(feature = "full",
|
||||
diesel(
|
||||
|
@ -216,6 +223,11 @@ pub struct CommentSlimView {
|
|||
pub creator_community_actions: Option<CommunityActions>,
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
pub instance_actions: Option<InstanceActions>,
|
||||
#[cfg_attr(feature = "full", diesel(
|
||||
select_expression_type = Nullable<HomeInstanceActionsAllColumnsTuple>,
|
||||
select_expression = home_instance_actions_select()))]
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
pub home_instance_actions: Option<InstanceActions>,
|
||||
pub creator_is_admin: bool,
|
||||
pub can_mod: bool,
|
||||
}
|
||||
|
@ -253,6 +265,9 @@ pub struct LocalUserView {
|
|||
pub local_user: LocalUser,
|
||||
#[cfg_attr(feature = "full", diesel(embed))]
|
||||
pub person: Person,
|
||||
#[cfg_attr(feature = "full", diesel(embed))]
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
pub instance_actions: Option<InstanceActions>,
|
||||
}
|
||||
|
||||
#[skip_serializing_none]
|
||||
|
@ -348,6 +363,11 @@ pub struct PostView {
|
|||
#[cfg_attr(feature = "full", diesel(embed))]
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
pub instance_actions: Option<InstanceActions>,
|
||||
#[cfg_attr(feature = "full", diesel(
|
||||
select_expression_type = Nullable<HomeInstanceActionsAllColumnsTuple>,
|
||||
select_expression = home_instance_actions_select()))]
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
pub home_instance_actions: Option<InstanceActions>,
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
#[cfg_attr(feature = "full",
|
||||
diesel(
|
||||
|
@ -435,6 +455,8 @@ pub struct SiteView {
|
|||
pub local_site: LocalSite,
|
||||
#[cfg_attr(feature = "full", diesel(embed))]
|
||||
pub local_site_rate_limit: LocalSiteRateLimit,
|
||||
#[cfg_attr(feature = "full", diesel(embed))]
|
||||
pub instance: Instance,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
|
@ -572,6 +594,10 @@ pub(crate) struct PersonContentCombinedViewInternal {
|
|||
pub community_actions: Option<CommunityActions>,
|
||||
#[cfg_attr(feature = "full", diesel(embed))]
|
||||
pub instance_actions: Option<InstanceActions>,
|
||||
#[cfg_attr(feature = "full", diesel(
|
||||
select_expression_type = Nullable<HomeInstanceActionsAllColumnsTuple>,
|
||||
select_expression = home_instance_actions_select()))]
|
||||
pub home_instance_actions: Option<InstanceActions>,
|
||||
#[cfg_attr(feature = "full", diesel(embed))]
|
||||
pub post_actions: Option<PostActions>,
|
||||
#[cfg_attr(feature = "full", diesel(embed))]
|
||||
|
@ -630,6 +656,10 @@ pub(crate) struct PersonSavedCombinedViewInternal {
|
|||
pub community_actions: Option<CommunityActions>,
|
||||
#[cfg_attr(feature = "full", diesel(embed))]
|
||||
pub instance_actions: Option<InstanceActions>,
|
||||
#[cfg_attr(feature = "full", diesel(
|
||||
select_expression_type = Nullable<HomeInstanceActionsAllColumnsTuple>,
|
||||
select_expression = home_instance_actions_select()))]
|
||||
pub home_instance_actions: Option<InstanceActions>,
|
||||
#[cfg_attr(feature = "full", diesel(embed))]
|
||||
pub post_actions: Option<PostActions>,
|
||||
#[cfg_attr(feature = "full", diesel(embed))]
|
||||
|
@ -761,6 +791,11 @@ pub struct PersonCommentMentionView {
|
|||
pub person_actions: Option<PersonActions>,
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
pub instance_actions: Option<InstanceActions>,
|
||||
#[cfg_attr(feature = "full", diesel(
|
||||
select_expression_type = Nullable<HomeInstanceActionsAllColumnsTuple>,
|
||||
select_expression = home_instance_actions_select()))]
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
pub home_instance_actions: Option<InstanceActions>,
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
pub creator_community_actions: Option<CommunityActions>,
|
||||
pub creator_is_admin: bool,
|
||||
|
@ -789,6 +824,11 @@ pub struct PersonPostMentionView {
|
|||
pub post_actions: Option<PostActions>,
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
pub instance_actions: Option<InstanceActions>,
|
||||
#[cfg_attr(feature = "full", diesel(
|
||||
select_expression_type = Nullable<HomeInstanceActionsAllColumnsTuple>,
|
||||
select_expression = home_instance_actions_select()))]
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
pub home_instance_actions: Option<InstanceActions>,
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
pub creator_community_actions: Option<CommunityActions>,
|
||||
pub creator_is_admin: bool,
|
||||
|
@ -816,6 +856,11 @@ pub struct CommentReplyView {
|
|||
pub person_actions: Option<PersonActions>,
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
pub instance_actions: Option<InstanceActions>,
|
||||
#[cfg_attr(feature = "full", diesel(
|
||||
select_expression_type = Nullable<HomeInstanceActionsAllColumnsTuple>,
|
||||
select_expression = home_instance_actions_select()))]
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
pub home_instance_actions: Option<InstanceActions>,
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
pub creator_community_actions: Option<CommunityActions>,
|
||||
pub creator_is_admin: bool,
|
||||
|
@ -837,6 +882,14 @@ pub struct PersonView {
|
|||
)
|
||||
)]
|
||||
pub is_admin: bool,
|
||||
#[cfg_attr(feature = "full", diesel(embed))]
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
pub instance_actions: Option<InstanceActions>,
|
||||
#[cfg_attr(feature = "full", diesel(
|
||||
select_expression_type = Nullable<HomeInstanceActionsAllColumnsTuple>,
|
||||
select_expression = home_instance_actions_select()))]
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
pub home_instance_actions: Option<InstanceActions>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
|
@ -913,6 +966,10 @@ pub struct InboxCombinedViewInternal {
|
|||
pub community_actions: Option<CommunityActions>,
|
||||
#[cfg_attr(feature = "full", diesel(embed))]
|
||||
pub instance_actions: Option<InstanceActions>,
|
||||
#[cfg_attr(feature = "full", diesel(
|
||||
select_expression_type = Nullable<HomeInstanceActionsAllColumnsTuple>,
|
||||
select_expression = home_instance_actions_select()))]
|
||||
pub home_instance_actions: Option<InstanceActions>,
|
||||
#[cfg_attr(feature = "full", diesel(embed))]
|
||||
pub post_actions: Option<PostActions>,
|
||||
#[cfg_attr(feature = "full", diesel(embed))]
|
||||
|
@ -1288,6 +1345,10 @@ pub(crate) struct SearchCombinedViewInternal {
|
|||
pub community_actions: Option<CommunityActions>,
|
||||
#[cfg_attr(feature = "full", diesel(embed))]
|
||||
pub instance_actions: Option<InstanceActions>,
|
||||
#[cfg_attr(feature = "full", diesel(
|
||||
select_expression_type = Nullable<HomeInstanceActionsAllColumnsTuple>,
|
||||
select_expression = home_instance_actions_select()))]
|
||||
pub home_instance_actions: Option<InstanceActions>,
|
||||
#[cfg_attr(feature = "full", diesel(embed))]
|
||||
pub post_actions: Option<PostActions>,
|
||||
#[cfg_attr(feature = "full", diesel(embed))]
|
||||
|
|
|
@ -1,14 +1,22 @@
|
|||
use diesel::{
|
||||
dsl::{case_when, exists, not},
|
||||
dsl::{case_when, exists, not, Nullable},
|
||||
helper_types::{Eq, NotEq},
|
||||
BoolExpressionMethods,
|
||||
ExpressionMethods,
|
||||
JoinOnDsl,
|
||||
NullableExpressionMethods,
|
||||
PgExpressionMethods,
|
||||
QueryDsl,
|
||||
};
|
||||
use lemmy_db_schema::{
|
||||
aliases::{creator_community_actions, creator_local_user, person1, person2},
|
||||
aliases::{
|
||||
creator_community_actions,
|
||||
creator_local_user,
|
||||
home_instance_actions,
|
||||
person1,
|
||||
person2,
|
||||
},
|
||||
newtypes::InstanceId,
|
||||
schema::{
|
||||
comment,
|
||||
community,
|
||||
|
@ -22,6 +30,7 @@ use lemmy_db_schema::{
|
|||
source::community::CommunityFollowerState,
|
||||
CommunityVisibility,
|
||||
CreatorCommunityActionsAllColumnsTuple,
|
||||
HomeInstanceActionsAllColumnsTuple,
|
||||
Person1AliasAllColumnsTuple,
|
||||
Person2AliasAllColumnsTuple,
|
||||
};
|
||||
|
@ -154,6 +163,12 @@ pub(crate) fn creator_community_actions_select() -> CreatorCommunityActionsAllCo
|
|||
creator_community_actions.fields(community_actions::all_columns)
|
||||
}
|
||||
|
||||
pub(crate) fn home_instance_actions_select() -> Nullable<HomeInstanceActionsAllColumnsTuple> {
|
||||
home_instance_actions
|
||||
.fields(instance_actions::all_columns)
|
||||
.nullable()
|
||||
}
|
||||
|
||||
type IsSubscribedType =
|
||||
Eq<lemmy_db_schema::schema::community_actions::follow_state, Option<CommunityFollowerState>>;
|
||||
|
||||
|
@ -169,3 +184,29 @@ pub(crate) fn filter_not_unlisted_or_is_subscribed() -> _ {
|
|||
let is_subscribed: IsSubscribedType = filter_is_subscribed();
|
||||
not_unlisted.or(is_subscribed)
|
||||
}
|
||||
|
||||
/// join with instance actions for local instance
|
||||
///
|
||||
/// Requires annotation for return type, see https://docs.diesel.rs/2.2.x/diesel/dsl/attr.auto_type.html#annotating-types
|
||||
#[diesel::dsl::auto_type]
|
||||
pub fn local_instance_person_join(local_instance_id: InstanceId) -> _ {
|
||||
instance_actions::table.on(
|
||||
instance_actions::instance_id
|
||||
.eq(local_instance_id)
|
||||
.and(instance_actions::person_id.eq(person::id)),
|
||||
)
|
||||
}
|
||||
|
||||
#[diesel::dsl::auto_type]
|
||||
pub fn home_instance_person_join() -> _ {
|
||||
home_instance_actions.on(
|
||||
home_instance_actions
|
||||
.field(instance_actions::instance_id)
|
||||
.eq(person::instance_id)
|
||||
.and(
|
||||
home_instance_actions
|
||||
.field(instance_actions::person_id)
|
||||
.eq(person::id),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -60,7 +60,7 @@ pub async fn delete_community_icon(
|
|||
local_user_view: LocalUserView,
|
||||
) -> LemmyResult<Json<SuccessResponse>> {
|
||||
let community = Community::read(&mut context.pool(), data.id).await?;
|
||||
is_mod_or_admin(&mut context.pool(), &local_user_view.person, community.id).await?;
|
||||
is_mod_or_admin(&mut context.pool(), &local_user_view, community.id).await?;
|
||||
|
||||
delete_old_image(&community.icon, &context).await?;
|
||||
|
||||
|
@ -79,7 +79,7 @@ pub async fn delete_community_banner(
|
|||
local_user_view: LocalUserView,
|
||||
) -> LemmyResult<Json<SuccessResponse>> {
|
||||
let community = Community::read(&mut context.pool(), data.id).await?;
|
||||
is_mod_or_admin(&mut context.pool(), &local_user_view.person, community.id).await?;
|
||||
is_mod_or_admin(&mut context.pool(), &local_user_view, community.id).await?;
|
||||
|
||||
delete_old_image(&community.icon, &context).await?;
|
||||
|
||||
|
|
|
@ -11,8 +11,8 @@ use lemmy_api_common::{
|
|||
context::LemmyContext,
|
||||
image::{ImageGetParams, ImageProxyParams},
|
||||
};
|
||||
use lemmy_db_schema::source::{images::RemoteImage, local_site::LocalSite};
|
||||
use lemmy_db_views::structs::LocalUserView;
|
||||
use lemmy_db_schema::source::images::RemoteImage;
|
||||
use lemmy_db_views::structs::{LocalUserView, SiteView};
|
||||
use lemmy_utils::error::LemmyResult;
|
||||
use url::Url;
|
||||
|
||||
|
@ -25,7 +25,7 @@ pub async fn get_image(
|
|||
) -> LemmyResult<HttpResponse> {
|
||||
// block access to images if instance is private
|
||||
if local_user_view.is_none() {
|
||||
let local_site = LocalSite::read(&mut context.pool()).await?;
|
||||
let local_site = SiteView::read_local(&mut context.pool()).await?.local_site;
|
||||
if local_site.private_instance {
|
||||
return Ok(HttpResponse::Unauthorized().finish());
|
||||
}
|
||||
|
|
|
@ -87,7 +87,7 @@ pub async fn upload_community_icon(
|
|||
context: Data<LemmyContext>,
|
||||
) -> LemmyResult<Json<UploadImageResponse>> {
|
||||
let community: Community = Community::read(&mut context.pool(), query.id).await?;
|
||||
is_mod_or_admin(&mut context.pool(), &local_user_view.person, community.id).await?;
|
||||
is_mod_or_admin(&mut context.pool(), &local_user_view, community.id).await?;
|
||||
|
||||
let image = do_upload_image(req, body, Avatar, &local_user_view, &context).await?;
|
||||
delete_old_image(&community.icon, &context).await?;
|
||||
|
@ -109,7 +109,7 @@ pub async fn upload_community_banner(
|
|||
context: Data<LemmyContext>,
|
||||
) -> LemmyResult<Json<UploadImageResponse>> {
|
||||
let community: Community = Community::read(&mut context.pool(), query.id).await?;
|
||||
is_mod_or_admin(&mut context.pool(), &local_user_view.person, community.id).await?;
|
||||
is_mod_or_admin(&mut context.pool(), &local_user_view, community.id).await?;
|
||||
|
||||
let image = do_upload_image(req, body, Banner, &local_user_view, &context).await?;
|
||||
delete_old_image(&community.banner, &context).await?;
|
||||
|
|
|
@ -388,7 +388,7 @@ async fn initialize_local_site_2022_10_10(
|
|||
info!("Running initialize_local_site_2022_10_10");
|
||||
|
||||
// Check to see if local_site exists
|
||||
if LocalSite::read(pool).await.is_ok() {
|
||||
if SiteView::read_local(pool).await.is_ok() {
|
||||
return Ok(());
|
||||
}
|
||||
info!("No Local Site found, creating it.");
|
||||
|
|
|
@ -27,6 +27,7 @@ use lemmy_db_schema::{
|
|||
community_actions,
|
||||
federation_blocklist,
|
||||
instance,
|
||||
instance_actions,
|
||||
person,
|
||||
post,
|
||||
received_activity,
|
||||
|
@ -41,6 +42,7 @@ use lemmy_db_schema::{
|
|||
traits::Crud,
|
||||
utils::{functions::coalesce, get_conn, now, uplete, DbPool, DELETED_REPLACEMENT_TEXT},
|
||||
};
|
||||
use lemmy_db_views::{structs::SiteView, utils::local_instance_person_join};
|
||||
use lemmy_utils::error::{LemmyErrorType, LemmyResult};
|
||||
use reqwest_middleware::ClientWithMiddleware;
|
||||
use std::time::Duration;
|
||||
|
@ -389,21 +391,19 @@ async fn update_banned_when_expired(pool: &mut DbPool<'_>) -> LemmyResult<()> {
|
|||
info!("Updating banned column if it expires ...");
|
||||
let mut conn = get_conn(pool).await?;
|
||||
|
||||
diesel::update(
|
||||
person::table
|
||||
.filter(person::banned.eq(true))
|
||||
.filter(person::ban_expires.lt(now().nullable())),
|
||||
)
|
||||
.set(person::banned.eq(false))
|
||||
.execute(&mut conn)
|
||||
.await?;
|
||||
|
||||
uplete::new(community_actions::table.filter(community_actions::ban_expires.lt(now().nullable())))
|
||||
.set_null(community_actions::received_ban)
|
||||
.set_null(community_actions::ban_expires)
|
||||
.as_query()
|
||||
.execute(&mut conn)
|
||||
.await?;
|
||||
|
||||
uplete::new(instance_actions::table.filter(instance_actions::ban_expires.lt(now().nullable())))
|
||||
.set_null(instance_actions::received_ban)
|
||||
.set_null(instance_actions::ban_expires)
|
||||
.as_query()
|
||||
.execute(&mut conn)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -423,6 +423,7 @@ async fn delete_instance_block_when_expired(pool: &mut DbPool<'_>) -> LemmyResul
|
|||
/// Find all unpublished posts with scheduled date in the future, and publish them.
|
||||
async fn publish_scheduled_posts(context: &Data<LemmyContext>) -> LemmyResult<()> {
|
||||
let pool = &mut context.pool();
|
||||
let local_instance_id = SiteView::read_local(pool).await?.instance.id;
|
||||
let mut conn = get_conn(pool).await?;
|
||||
|
||||
let not_banned_action = community_actions::table
|
||||
|
@ -431,13 +432,14 @@ async fn publish_scheduled_posts(context: &Data<LemmyContext>) -> LemmyResult<()
|
|||
|
||||
let scheduled_posts: Vec<_> = post::table
|
||||
.inner_join(community::table)
|
||||
.inner_join(person::table)
|
||||
.inner_join(person::table.left_join(local_instance_person_join(local_instance_id)))
|
||||
// find all posts which have scheduled_publish_time that is in the past
|
||||
.filter(post::scheduled_publish_time.is_not_null())
|
||||
.filter(coalesce(post::scheduled_publish_time, now()).lt(now()))
|
||||
// make sure the post, person and community are still around
|
||||
.filter(not(post::deleted.or(post::removed)))
|
||||
.filter(not(person::banned.or(person::deleted)))
|
||||
.filter(not(person::deleted))
|
||||
.filter(instance_actions::received_ban.is_null())
|
||||
.filter(not(community::removed.or(community::deleted)))
|
||||
// ensure that user isnt banned from community
|
||||
.filter(not(exists(not_banned_action)))
|
||||
|
@ -555,6 +557,7 @@ mod tests {
|
|||
|
||||
use super::*;
|
||||
use lemmy_api_common::request::client_builder;
|
||||
use lemmy_db_views::site::site_view::create_test_instance;
|
||||
use lemmy_utils::{
|
||||
error::{LemmyErrorType, LemmyResult},
|
||||
settings::structs::Settings,
|
||||
|
@ -587,11 +590,13 @@ mod tests {
|
|||
#[serial]
|
||||
async fn test_scheduled_tasks_no_errors() -> LemmyResult<()> {
|
||||
let context = LemmyContext::init_test_context().await;
|
||||
let instance = create_test_instance(&mut context.pool()).await?;
|
||||
|
||||
startup_jobs(&mut context.pool()).await?;
|
||||
update_instance_software(&mut context.pool(), context.client()).await?;
|
||||
delete_expired_captcha_answers(&mut context.pool()).await?;
|
||||
publish_scheduled_posts(&context).await?;
|
||||
Instance::delete(&mut context.pool(), instance.id).await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue