Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement instance actor #1798

Merged
merged 8 commits into from
Feb 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 56 additions & 28 deletions api_tests/src/post.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ import {
reportPost,
listPostReports,
randomString,
registerUser,
API,
getSite
} from './shared';
import { PostView, CommunityView } from 'lemmy-js-client';

Expand Down Expand Up @@ -297,63 +300,88 @@ test('A and G subscribe to B (center) A posts, it gets announced to G', async ()
});

test('Enforce site ban for federated user', async () => {
let alphaShortname = `@lemmy_alpha@lemmy-alpha:8541`;
let alphaPerson = (await resolvePerson(beta, alphaShortname)).person;
// create a test user
let alphaUserJwt = await registerUser(alpha);
expect(alphaUserJwt).toBeDefined();
let alphaUser: API = {
client: alpha.client,
auth: alphaUserJwt.jwt,
};
let alphaUserActorId = (await getSite(alphaUser)).my_user.local_user_view.person.actor_id;
expect(alphaUserActorId).toBeDefined();
let alphaPerson = (await resolvePerson(alphaUser, alphaUserActorId)).person;
expect(alphaPerson).toBeDefined();

// ban alpha from beta site
let banAlpha = await banPersonFromSite(beta, alphaPerson.person.id, true);
// alpha makes post in beta community, it federates to beta instance
let postRes1 = await createPost(alphaUser, betaCommunity.community.id);
let searchBeta1 = await searchPostLocal(beta, postRes1.post_view.post);
expect(searchBeta1.posts[0]).toBeDefined();

// ban alpha from its instance
let banAlpha = await banPersonFromSite(alpha, alphaPerson.person.id, true, true);
expect(banAlpha.banned).toBe(true);

// Alpha makes post on beta
let postRes = await createPost(alpha, betaCommunity.community.id);
expect(postRes.post_view.post).toBeDefined();
expect(postRes.post_view.community.local).toBe(false);
expect(postRes.post_view.creator.local).toBe(true);
expect(postRes.post_view.counts.score).toBe(1);
// alpha ban should be federated to beta
let alphaUserOnBeta1 = await resolvePerson(beta, alphaUserActorId);
expect(alphaUserOnBeta1.person.person.banned).toBe(true);

// Make sure that post doesn't make it to beta
let searchBeta = await searchPostLocal(beta, postRes.post_view.post);
let betaPost = searchBeta.posts[0];
expect(betaPost).toBeUndefined();
// existing alpha post should be removed on beta
let searchBeta2 = await searchPostLocal(beta, postRes1.post_view.post);
expect(searchBeta2.posts[0]).toBeUndefined();

// Unban alpha
let unBanAlpha = await banPersonFromSite(beta, alphaPerson.person.id, false);
let unBanAlpha = await banPersonFromSite(alpha, alphaPerson.person.id, false, false);
expect(unBanAlpha.banned).toBe(false);

// alpha makes new post in beta community, it federates
let postRes2 = await createPost(alphaUser, betaCommunity.community.id);
let searchBeta3 = await searchPostLocal(beta, postRes2.post_view.post);
expect(searchBeta3.posts[0]).toBeDefined();

let alphaUserOnBeta2 = await resolvePerson(beta, alphaUserActorId)
expect(alphaUserOnBeta2.person.person.banned).toBe(false);
});

test('Enforce community ban for federated user', async () => {
let alphaShortname = `@lemmy_alpha@lemmy-alpha:8541`;
let alphaPerson = (await resolvePerson(beta, alphaShortname)).person;
expect(alphaPerson).toBeDefined();

// ban alpha from beta site
await banPersonFromCommunity(beta, alphaPerson.person.id, 2, false);
let banAlpha = await banPersonFromCommunity(beta, alphaPerson.person.id, 2, true);
// make a post in beta, it goes through
let postRes1 = await createPost(alpha, betaCommunity.community.id);
let searchBeta1 = await searchPostLocal(beta, postRes1.post_view.post);
expect(searchBeta1.posts[0]).toBeDefined();

// ban alpha from beta community
let banAlpha = await banPersonFromCommunity(beta, alphaPerson.person.id, 2, true, true);
expect(banAlpha.banned).toBe(true);

// ensure that the post by alpha got removed
let searchAlpha1 = await searchPostLocal(alpha, postRes1.post_view.post);
expect(searchAlpha1.posts[0]).toBeUndefined();

// Alpha tries to make post on beta, but it fails because of ban
let postRes = await createPost(alpha, betaCommunity.community.id);
expect(postRes.post_view).toBeUndefined();
let postRes2 = await createPost(alpha, betaCommunity.community.id);
expect(postRes2.post_view).toBeUndefined();

// Unban alpha
let unBanAlpha = await banPersonFromCommunity(
beta,
alphaPerson.person.id,
2,
false,
false
);
expect(unBanAlpha.banned).toBe(false);
let postRes2 = await createPost(alpha, betaCommunity.community.id);
expect(postRes2.post_view.post).toBeDefined();
expect(postRes2.post_view.community.local).toBe(false);
expect(postRes2.post_view.creator.local).toBe(true);
expect(postRes2.post_view.counts.score).toBe(1);
let postRes3 = await createPost(alpha, betaCommunity.community.id);
expect(postRes3.post_view.post).toBeDefined();
expect(postRes3.post_view.community.local).toBe(false);
expect(postRes3.post_view.creator.local).toBe(true);
expect(postRes3.post_view.counts.score).toBe(1);

// Make sure that post makes it to beta community
let searchBeta = await searchPostLocal(beta, postRes2.post_view.post);
let betaPost = searchBeta.posts[0];
expect(betaPost).toBeDefined();
let searchBeta2 = await searchPostLocal(beta, postRes3.post_view.post);
expect(searchBeta2.posts[0]).toBeDefined();
});

test('Report a post', async () => {
Expand Down
19 changes: 10 additions & 9 deletions api_tests/src/shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,23 +66,23 @@ export interface API {
}

export let alpha: API = {
client: new LemmyHttp('http://localhost:8541'),
client: new LemmyHttp('http://127.0.0.1:8541'),
dessalines marked this conversation as resolved.
Show resolved Hide resolved
};

export let beta: API = {
client: new LemmyHttp('http://localhost:8551'),
client: new LemmyHttp('http://127.0.0.1:8551'),
};

export let gamma: API = {
client: new LemmyHttp('http://localhost:8561'),
client: new LemmyHttp('http://127.0.0.1:8561'),
};

export let delta: API = {
client: new LemmyHttp('http://localhost:8571'),
client: new LemmyHttp('http://127.0.0.1:8571'),
};

export let epsilon: API = {
client: new LemmyHttp('http://localhost:8581'),
client: new LemmyHttp('http://127.0.0.1:8581'),
};

const password = 'lemmylemmy'
Expand Down Expand Up @@ -289,13 +289,14 @@ export async function resolvePerson(
export async function banPersonFromSite(
api: API,
person_id: number,
ban: boolean
ban: boolean,
remove_data: boolean,
): Promise<BanPersonResponse> {
// Make sure lemmy-beta/c/main is cached on lemmy_alpha
let form: BanPerson = {
person_id,
ban,
remove_data: false,
remove_data,
auth: api.auth,
};
return api.client.banPerson(form);
Expand All @@ -305,13 +306,13 @@ export async function banPersonFromCommunity(
api: API,
person_id: number,
community_id: number,
remove_data: boolean,
ban: boolean
): Promise<BanFromCommunityResponse> {
// Make sure lemmy-beta/c/main is cached on lemmy_alpha
let form: BanFromCommunity = {
person_id,
community_id,
remove_data: false,
remove_data,
ban,
auth: api.auth,
};
Expand Down
52 changes: 14 additions & 38 deletions crates/api/src/community.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,19 @@ use lemmy_api_common::{
community::*,
get_local_user_view_from_jwt,
is_mod_or_admin,
remove_user_data_in_community,
};
use lemmy_apub::{
activities::block::SiteOrCommunity,
objects::{community::ApubCommunity, person::ApubPerson},
protocol::activities::{
community::{
add_mod::AddMod,
block_user::BlockUserFromCommunity,
remove_mod::RemoveMod,
undo_block_user::UndoBlockUserFromCommunity,
},
block::{block_user::BlockUser, undo_block_user::UndoBlockUser},
community::{add_mod::AddMod, remove_mod::RemoveMod},
following::{follow::FollowCommunity as FollowCommunityApub, undo_follow::UndoFollowCommunity},
},
};
use lemmy_db_schema::{
source::{
comment::Comment,
community::{
Community,
CommunityFollower,
Expand All @@ -43,11 +40,9 @@ use lemmy_db_schema::{
ModTransferCommunityForm,
},
person::Person,
post::Post,
},
traits::{Bannable, Blockable, Crud, Followable, Joinable},
};
use lemmy_db_views::comment_view::CommentQueryBuilder;
use lemmy_db_views_actor::{
community_moderator_view::CommunityModeratorView,
community_view::CommunityView,
Expand Down Expand Up @@ -213,6 +208,7 @@ impl Perform for BanFromCommunity {

let community_id = data.community_id;
let banned_person_id = data.person_id;
let remove_data = data.remove_data.unwrap_or(false);
let expires = data.expires.map(naive_from_unix);

// Verify that only mods or admins can ban
Expand Down Expand Up @@ -254,10 +250,12 @@ impl Perform for BanFromCommunity {
.await?
.ok();

BlockUserFromCommunity::send(
&community,
BlockUser::send(
&SiteOrCommunity::Community(community),
&banned_person,
&local_user_view.person.clone().into(),
remove_data,
data.reason.clone(),
expires,
context,
)
Expand All @@ -268,41 +266,19 @@ impl Perform for BanFromCommunity {
.await?
.map_err(LemmyError::from)
.map_err(|e| e.with_message("community_user_already_banned"))?;
UndoBlockUserFromCommunity::send(
&community,
UndoBlockUser::send(
&SiteOrCommunity::Community(community),
&banned_person,
&local_user_view.person.clone().into(),
data.reason.clone(),
context,
)
.await?;
}

// Remove/Restore their data if that's desired
if data.remove_data.unwrap_or(false) {
// Posts
blocking(context.pool(), move |conn: &'_ _| {
Post::update_removed_for_creator(conn, banned_person_id, Some(community_id), true)
})
.await??;

// Comments
// TODO Diesel doesn't allow updates with joins, so this has to be a loop
let comments = blocking(context.pool(), move |conn| {
CommentQueryBuilder::create(conn)
.creator_id(banned_person_id)
.community_id(community_id)
.limit(std::i64::MAX)
.list()
})
.await??;

for comment_view in &comments {
let comment_id = comment_view.comment.id;
blocking(context.pool(), move |conn: &'_ _| {
Comment::update_removed(conn, comment_id, true)
})
.await??;
}
if remove_data {
remove_user_data_in_community(community_id, banned_person_id, context.pool()).await?;
}

// Mod tables
Expand Down
Loading