Merge branch 'move_blocklist_to_db' into diesel_async_1

This commit is contained in:
Dessalines 2022-10-21 21:16:01 -04:00
commit 3254fc0fb4
38 changed files with 843 additions and 1753 deletions

View file

@ -4,11 +4,11 @@
"browser": true
},
"plugins": [
"jane"
"@typescript-eslint"
],
"extends": [
"plugin:jane/recommended",
"plugin:jane/typescript"
"eslint:recommended",
"plugin:@typescript-eslint/recommended"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {

View file

@ -1,4 +1,4 @@
module.exports = Object.assign(require('eslint-plugin-jane/prettier-ts'), {
arrowParens: 'avoid',
module.exports = Object.assign(require("eslint-plugin-prettier"), {
arrowParens: "avoid",
semi: true,
});

View file

@ -14,15 +14,17 @@
"devDependencies": {
"@sniptt/monads": "^0.5.10",
"@types/jest": "^26.0.23",
"@typescript-eslint/eslint-plugin": "^5.21.0",
"@typescript-eslint/parser": "^5.21.0",
"class-transformer": "^0.5.1",
"eslint": "^8.20.0",
"eslint-plugin-jane": "^11.2.2",
"eslint": "^8.25.0",
"eslint-plugin-prettier": "^4.0.0",
"jest": "^27.0.6",
"lemmy-js-client": "0.17.0-rc.37",
"lemmy-js-client": "0.17.0-rc.47",
"node-fetch": "^2.6.1",
"prettier": "^2.7.1",
"reflect-metadata": "^0.1.13",
"ts-jest": "^27.0.3",
"typescript": "^4.6.4"
"typescript": "^4.8.4"
}
}

View file

@ -1,7 +1,7 @@
jest.setTimeout(180000);
import {None, Some} from '@sniptt/monads';
import { CommentView } from 'lemmy-js-client';
import { PostResponse } from 'lemmy-js-client';
import { None, Some } from "@sniptt/monads";
import { CommentView } from "lemmy-js-client";
import { PostResponse } from "lemmy-js-client";
import {
alpha,
@ -31,7 +31,7 @@ import {
getComments,
getCommentParentId,
resolveCommunity,
} from './shared';
} from "./shared";
let postRes: PostResponse;
@ -41,10 +41,7 @@ beforeAll(async () => {
await followBeta(alpha);
await followBeta(gamma);
let betaCommunity = (await resolveBetaCommunity(alpha)).community;
postRes = await createPost(
alpha,
betaCommunity.unwrap().community.id
);
postRes = await createPost(alpha, betaCommunity.unwrap().community.id);
});
afterAll(async () => {
@ -65,7 +62,7 @@ function assertCommentFederation(
expect(commentOne.comment.removed).toBe(commentOne.comment.removed);
}
test('Create a comment', async () => {
test("Create a comment", async () => {
let commentRes = await createComment(alpha, postRes.post_view.post.id, None);
expect(commentRes.comment_view.comment.content).toBeDefined();
expect(commentRes.comment_view.community.local).toBe(false);
@ -73,7 +70,9 @@ test('Create a comment', async () => {
expect(commentRes.comment_view.counts.score).toBe(1);
// Make sure that comment is liked on beta
let betaComment = (await resolveComment(beta, commentRes.comment_view.comment)).comment.unwrap();
let betaComment = (
await resolveComment(beta, commentRes.comment_view.comment)
).comment.unwrap();
expect(betaComment).toBeDefined();
expect(betaComment.community.local).toBe(true);
expect(betaComment.creator.local).toBe(false);
@ -81,15 +80,17 @@ test('Create a comment', async () => {
assertCommentFederation(betaComment, commentRes.comment_view);
});
test('Create a comment in a non-existent post', async () => {
let commentRes = await createComment(alpha, -1, None) as any;
expect(commentRes.error).toBe('couldnt_find_post');
test("Create a comment in a non-existent post", async () => {
let commentRes = (await createComment(alpha, -1, None)) as any;
expect(commentRes.error).toBe("couldnt_find_post");
});
test('Update a comment', async () => {
test("Update a comment", async () => {
let commentRes = await createComment(alpha, postRes.post_view.post.id, None);
// Federate the comment first
let betaComment = (await resolveComment(beta, commentRes.comment_view.comment)).comment;
let betaComment = (
await resolveComment(beta, commentRes.comment_view.comment)
).comment;
assertCommentFederation(betaComment.unwrap(), commentRes.comment_view);
let updateCommentRes = await editComment(
@ -97,23 +98,19 @@ test('Update a comment', async () => {
commentRes.comment_view.comment.id
);
expect(updateCommentRes.comment_view.comment.content).toBe(
'A jest test federated comment update'
"A jest test federated comment update"
);
expect(updateCommentRes.comment_view.community.local).toBe(false);
expect(updateCommentRes.comment_view.creator.local).toBe(true);
// Make sure that post is updated on beta
let betaCommentUpdated = (await resolveComment(
beta,
commentRes.comment_view.comment
)).comment.unwrap();
assertCommentFederation(
betaCommentUpdated,
updateCommentRes.comment_view
);
let betaCommentUpdated = (
await resolveComment(beta, commentRes.comment_view.comment)
).comment.unwrap();
assertCommentFederation(betaCommentUpdated, updateCommentRes.comment_view);
});
test('Delete a comment', async () => {
test("Delete a comment", async () => {
let commentRes = await createComment(alpha, postRes.post_view.post.id, None);
let deleteCommentRes = await deleteComment(
@ -125,8 +122,11 @@ test('Delete a comment', async () => {
expect(deleteCommentRes.comment_view.comment.content).toBe("");
// Make sure that comment is undefined on beta
let betaCommentRes = await resolveComment(beta, commentRes.comment_view.comment) as any;
expect(betaCommentRes.error).toBe('couldnt_find_object');
let betaCommentRes = (await resolveComment(
beta,
commentRes.comment_view.comment
)) as any;
expect(betaCommentRes.error).toBe("couldnt_find_object");
let undeleteCommentRes = await deleteComment(
alpha,
@ -136,15 +136,14 @@ test('Delete a comment', async () => {
expect(undeleteCommentRes.comment_view.comment.deleted).toBe(false);
// Make sure that comment is undeleted on beta
let betaComment2 = (await resolveComment(beta, commentRes.comment_view.comment)).comment.unwrap();
let betaComment2 = (
await resolveComment(beta, commentRes.comment_view.comment)
).comment.unwrap();
expect(betaComment2.comment.deleted).toBe(false);
assertCommentFederation(
betaComment2,
undeleteCommentRes.comment_view
);
assertCommentFederation(betaComment2, undeleteCommentRes.comment_view);
});
test('Remove a comment from admin and community on the same instance', async () => {
test("Remove a comment from admin and community on the same instance", async () => {
let commentRes = await createComment(alpha, postRes.post_view.post.id, None);
// Get the id for beta
@ -158,14 +157,20 @@ test('Remove a comment from admin and community on the same instance', async ()
expect(removeCommentRes.comment_view.comment.content).toBe("");
// Make sure that comment is removed on alpha (it gets pushed since an admin from beta removed it)
let refetchedPostComments = await getComments(alpha, postRes.post_view.post.id);
let refetchedPostComments = await getComments(
alpha,
postRes.post_view.post.id
);
expect(refetchedPostComments.comments[0].comment.removed).toBe(true);
let unremoveCommentRes = await removeComment(beta, false, betaCommentId);
expect(unremoveCommentRes.comment_view.comment.removed).toBe(false);
// Make sure that comment is unremoved on beta
let refetchedPostComments2 = await getComments(alpha, postRes.post_view.post.id);
let refetchedPostComments2 = await getComments(
alpha,
postRes.post_view.post.id
);
expect(refetchedPostComments2.comments[0].comment.removed).toBe(false);
assertCommentFederation(
refetchedPostComments2.comments[0],
@ -173,7 +178,7 @@ test('Remove a comment from admin and community on the same instance', async ()
);
});
test('Remove a comment from admin and community on different instance', async () => {
test("Remove a comment from admin and community on different instance", async () => {
let alpha_user = await registerUser(alpha);
let newAlphaApi: API = {
client: alpha.client,
@ -186,11 +191,17 @@ test('Remove a comment from admin and community on different instance', async ()
newAlphaApi,
newCommunity.community_view.community.id
);
let commentRes = await createComment(newAlphaApi, newPost.post_view.post.id, None);
let commentRes = await createComment(
newAlphaApi,
newPost.post_view.post.id,
None
);
expect(commentRes.comment_view.comment.content).toBeDefined();
// Beta searches that to cache it, then removes it
let betaComment = (await resolveComment(beta, commentRes.comment_view.comment)).comment.unwrap();
let betaComment = (
await resolveComment(beta, commentRes.comment_view.comment)
).comment.unwrap();
let removeCommentRes = await removeComment(
beta,
true,
@ -199,29 +210,39 @@ test('Remove a comment from admin and community on different instance', async ()
expect(removeCommentRes.comment_view.comment.removed).toBe(true);
// Make sure its not removed on alpha
let refetchedPostComments = await getComments(alpha, newPost.post_view.post.id);
let refetchedPostComments = await getComments(
alpha,
newPost.post_view.post.id
);
expect(refetchedPostComments.comments[0].comment.removed).toBe(false);
assertCommentFederation(refetchedPostComments.comments[0], commentRes.comment_view);
assertCommentFederation(
refetchedPostComments.comments[0],
commentRes.comment_view
);
});
test('Unlike a comment', async () => {
test("Unlike a comment", async () => {
let commentRes = await createComment(alpha, postRes.post_view.post.id, None);
let unlike = await likeComment(alpha, 0, commentRes.comment_view.comment);
expect(unlike.comment_view.counts.score).toBe(0);
// Make sure that post is unliked on beta
let betaComment = (await resolveComment(beta, commentRes.comment_view.comment)).comment.unwrap();
let betaComment = (
await resolveComment(beta, commentRes.comment_view.comment)
).comment.unwrap();
expect(betaComment).toBeDefined();
expect(betaComment.community.local).toBe(true);
expect(betaComment.creator.local).toBe(false);
expect(betaComment.counts.score).toBe(0);
});
test('Federated comment like', async () => {
test("Federated comment like", async () => {
let commentRes = await createComment(alpha, postRes.post_view.post.id, None);
// Find the comment on beta
let betaComment = (await resolveComment(beta, commentRes.comment_view.comment)).comment.unwrap();
let betaComment = (
await resolveComment(beta, commentRes.comment_view.comment)
).comment.unwrap();
let like = await likeComment(beta, 1, betaComment.comment);
expect(like.comment_view.counts.score).toBe(2);
@ -231,10 +252,12 @@ test('Federated comment like', async () => {
expect(postComments.comments[0].counts.score).toBe(2);
});
test('Reply to a comment', async () => {
test("Reply to a comment", async () => {
// Create a comment on alpha, find it on beta
let commentRes = await createComment(alpha, postRes.post_view.post.id, None);
let betaComment = (await resolveComment(beta, commentRes.comment_view.comment)).comment.unwrap();
let betaComment = (
await resolveComment(beta, commentRes.comment_view.comment)
).comment.unwrap();
// find that comment id on beta
@ -247,7 +270,9 @@ test('Reply to a comment', async () => {
expect(replyRes.comment_view.comment.content).toBeDefined();
expect(replyRes.comment_view.community.local).toBe(true);
expect(replyRes.comment_view.creator.local).toBe(true);
expect(getCommentParentId(replyRes.comment_view.comment).unwrap()).toBe(betaComment.comment.id);
expect(getCommentParentId(replyRes.comment_view.comment).unwrap()).toBe(
betaComment.comment.id
);
expect(replyRes.comment_view.counts.score).toBe(1);
// Make sure that comment is seen on alpha
@ -257,16 +282,18 @@ test('Reply to a comment', async () => {
let postComments = await getComments(alpha, postRes.post_view.post.id);
let alphaComment = postComments.comments[0];
expect(alphaComment.comment.content).toBeDefined();
expect(getCommentParentId(alphaComment.comment).unwrap()).toBe(postComments.comments[1].comment.id);
expect(getCommentParentId(alphaComment.comment).unwrap()).toBe(
postComments.comments[1].comment.id
);
expect(alphaComment.community.local).toBe(false);
expect(alphaComment.creator.local).toBe(false);
expect(alphaComment.counts.score).toBe(1);
assertCommentFederation(alphaComment, replyRes.comment_view);
});
test('Mention beta', async () => {
test("Mention beta", async () => {
// Create a mention on alpha
let mentionContent = 'A test mention of @lemmy_beta@lemmy-beta:8551';
let mentionContent = "A test mention of @lemmy_beta@lemmy-beta:8551";
let commentRes = await createComment(alpha, postRes.post_view.post.id, None);
let mentionRes = await createComment(
alpha,
@ -286,23 +313,29 @@ test('Mention beta', async () => {
expect(mentionsRes.mentions[0].counts.score).toBe(1);
});
test('Comment Search', async () => {
test("Comment Search", async () => {
let commentRes = await createComment(alpha, postRes.post_view.post.id, None);
let betaComment = (await resolveComment(beta, commentRes.comment_view.comment)).comment.unwrap();
let betaComment = (
await resolveComment(beta, commentRes.comment_view.comment)
).comment.unwrap();
assertCommentFederation(betaComment, commentRes.comment_view);
});
test('A and G subscribe to B (center) A posts, G mentions B, it gets announced to A', async () => {
test("A and G subscribe to B (center) A posts, G mentions B, it gets announced to A", async () => {
// Create a local post
let alphaCommunity = (await resolveCommunity(alpha, "!main@lemmy-alpha:8541")).community.unwrap();
let alphaCommunity = (
await resolveCommunity(alpha, "!main@lemmy-alpha:8541")
).community.unwrap();
let alphaPost = await createPost(alpha, alphaCommunity.community.id);
expect(alphaPost.post_view.community.local).toBe(true);
// Make sure gamma sees it
let gammaPost = (await resolvePost(gamma, alphaPost.post_view.post)).post.unwrap();
let gammaPost = (
await resolvePost(gamma, alphaPost.post_view.post)
).post.unwrap();
let commentContent =
'A jest test federated comment announce, lets mention @lemmy_beta@lemmy-beta:8551';
"A jest test federated comment announce, lets mention @lemmy_beta@lemmy-beta:8551";
let commentRes = await createComment(
gamma,
gammaPost.post.id,
@ -315,12 +348,18 @@ test('A and G subscribe to B (center) A posts, G mentions B, it gets announced t
expect(commentRes.comment_view.counts.score).toBe(1);
// Make sure alpha sees it
let alphaPostComments2 = await getComments(alpha, alphaPost.post_view.post.id);
let alphaPostComments2 = await getComments(
alpha,
alphaPost.post_view.post.id
);
expect(alphaPostComments2.comments[0].comment.content).toBe(commentContent);
expect(alphaPostComments2.comments[0].community.local).toBe(true);
expect(alphaPostComments2.comments[0].creator.local).toBe(false);
expect(alphaPostComments2.comments[0].counts.score).toBe(1);
assertCommentFederation(alphaPostComments2.comments[0], commentRes.comment_view);
assertCommentFederation(
alphaPostComments2.comments[0],
commentRes.comment_view
);
// Make sure beta has mentions
let mentionsRes = await getMentions(beta);
@ -331,28 +370,32 @@ test('A and G subscribe to B (center) A posts, G mentions B, it gets announced t
// expect(mentionsRes.mentions[0].score).toBe(1);
});
test('Check that activity from another instance is sent to third instance', async () => {
test("Check that activity from another instance is sent to third instance", async () => {
// Alpha and gamma users follow beta community
let alphaFollow = await followBeta(alpha);
expect(alphaFollow.community_view.community.local).toBe(false);
expect(alphaFollow.community_view.community.name).toBe('main');
expect(alphaFollow.community_view.community.name).toBe("main");
let gammaFollow = await followBeta(gamma);
expect(gammaFollow.community_view.community.local).toBe(false);
expect(gammaFollow.community_view.community.name).toBe('main');
expect(gammaFollow.community_view.community.name).toBe("main");
// Create a post on beta
let betaPost = await createPost(beta, 2);
expect(betaPost.post_view.community.local).toBe(true);
// Make sure gamma and alpha see it
let gammaPost = (await resolvePost(gamma, betaPost.post_view.post)).post.unwrap();
let gammaPost = (
await resolvePost(gamma, betaPost.post_view.post)
).post.unwrap();
expect(gammaPost.post).toBeDefined();
let alphaPost = (await resolvePost(alpha, betaPost.post_view.post)).post.unwrap();
let alphaPost = (
await resolvePost(alpha, betaPost.post_view.post)
).post.unwrap();
expect(alphaPost.post).toBeDefined();
// The bug: gamma comments, and alpha should see it.
let commentContent = 'Comment from gamma';
let commentContent = "Comment from gamma";
let commentRes = await createComment(
gamma,
gammaPost.post.id,
@ -370,13 +413,16 @@ test('Check that activity from another instance is sent to third instance', asyn
expect(alphaPostComments2.comments[0].community.local).toBe(false);
expect(alphaPostComments2.comments[0].creator.local).toBe(false);
expect(alphaPostComments2.comments[0].counts.score).toBe(1);
assertCommentFederation(alphaPostComments2.comments[0], commentRes.comment_view);
assertCommentFederation(
alphaPostComments2.comments[0],
commentRes.comment_view
);
await unfollowRemotes(alpha);
await unfollowRemotes(gamma);
});
test('Fetch in_reply_tos: A is unsubbed from B, B makes a post, and some embedded comments, A subs to B, B updates the lowest level comment, A fetches both the post and all the inreplyto comments for that post.', async () => {
test("Fetch in_reply_tos: A is unsubbed from B, B makes a post, and some embedded comments, A subs to B, B updates the lowest level comment, A fetches both the post and all the inreplyto comments for that post.", async () => {
// Unfollow all remote communities
let site = await unfollowRemotes(alpha);
expect(
@ -387,7 +433,7 @@ test('Fetch in_reply_tos: A is unsubbed from B, B makes a post, and some embedde
let postRes = await createPost(beta, 2);
expect(postRes.post_view.post.name).toBeDefined();
let parentCommentContent = 'An invisible top level comment from beta';
let parentCommentContent = "An invisible top level comment from beta";
let parentCommentRes = await createComment(
beta,
postRes.post_view.post.id,
@ -399,7 +445,7 @@ test('Fetch in_reply_tos: A is unsubbed from B, B makes a post, and some embedde
);
// B creates a comment, then a child one of that.
let childCommentContent = 'An invisible child comment from beta';
let childCommentContent = "An invisible child comment from beta";
let childCommentRes = await createComment(
beta,
postRes.post_view.post.id,
@ -413,50 +459,62 @@ test('Fetch in_reply_tos: A is unsubbed from B, B makes a post, and some embedde
// Follow beta again
let follow = await followBeta(alpha);
expect(follow.community_view.community.local).toBe(false);
expect(follow.community_view.community.name).toBe('main');
expect(follow.community_view.community.name).toBe("main");
// An update to the child comment on beta, should push the post, parent, and child to alpha now
let updatedCommentContent = 'An update child comment from beta';
let updatedCommentContent = Some("An update child comment from beta");
let updateRes = await editComment(
beta,
childCommentRes.comment_view.comment.id,
updatedCommentContent
);
expect(updateRes.comment_view.comment.content).toBe(updatedCommentContent);
expect(updateRes.comment_view.comment.content).toBe(
updatedCommentContent.unwrap()
);
// Get the post from alpha
let alphaPostB = (await resolvePost(alpha, postRes.post_view.post)).post.unwrap();
let alphaPostB = (
await resolvePost(alpha, postRes.post_view.post)
).post.unwrap();
let alphaPost = await getPost(alpha, alphaPostB.post.id);
let alphaPostComments = await getComments(alpha, alphaPostB.post.id);
expect(alphaPost.post_view.post.name).toBeDefined();
assertCommentFederation(alphaPostComments.comments[1], parentCommentRes.comment_view);
assertCommentFederation(alphaPostComments.comments[0], updateRes.comment_view);
assertCommentFederation(
alphaPostComments.comments[1],
parentCommentRes.comment_view
);
assertCommentFederation(
alphaPostComments.comments[0],
updateRes.comment_view
);
expect(alphaPost.post_view.community.local).toBe(false);
expect(alphaPost.post_view.creator.local).toBe(false);
await unfollowRemotes(alpha);
});
test('Report a comment', async () => {
test("Report a comment", async () => {
let betaCommunity = (await resolveBetaCommunity(beta)).community.unwrap();
let postRes = (await createPost(beta, betaCommunity.community.id)).post_view.post;
let postRes = (await createPost(beta, betaCommunity.community.id)).post_view
.post;
expect(postRes).toBeDefined();
let commentRes = (await createComment(beta, postRes.id, None)).comment_view.comment;
let commentRes = (await createComment(beta, postRes.id, None)).comment_view
.comment;
expect(commentRes).toBeDefined();
let alphaComment = (await resolveComment(alpha, commentRes)).comment.unwrap().comment;
let alphaReport = (await reportComment(alpha, alphaComment.id, randomString(10)))
.comment_report_view.comment_report;
let alphaComment = (await resolveComment(alpha, commentRes)).comment.unwrap()
.comment;
let alphaReport = (
await reportComment(alpha, alphaComment.id, randomString(10))
).comment_report_view.comment_report;
let betaReport = (await listCommentReports(beta)).comment_reports[0].comment_report;
let betaReport = (await listCommentReports(beta)).comment_reports[0]
.comment_report;
expect(betaReport).toBeDefined();
expect(betaReport.resolved).toBe(false);
expect(betaReport.original_comment_text).toBe(alphaReport.original_comment_text);
expect(betaReport.original_comment_text).toBe(
alphaReport.original_comment_text
);
expect(betaReport.reason).toBe(alphaReport.reason);
});
function N(gamma: API, id: number, N: any, commentContent: string) {
throw new Error('Function not implemented.');
}

View file

@ -1,5 +1,5 @@
jest.setTimeout(120000);
import { CommunityView } from 'lemmy-js-client';
import { CommunityView } from "lemmy-js-client";
import {
alpha,
@ -18,7 +18,7 @@ import {
createPost,
getPost,
resolvePost,
} from './shared';
} from "./shared";
beforeAll(async () => {
await setupLogins();
@ -34,8 +34,12 @@ function assertCommunityFederation(
expect(communityOne.community.description.unwrapOr("none")).toBe(
communityTwo.community.description.unwrapOr("none")
);
expect(communityOne.community.icon.unwrapOr("none")).toBe(communityTwo.community.icon.unwrapOr("none"));
expect(communityOne.community.banner.unwrapOr("none")).toBe(communityTwo.community.banner.unwrapOr("none"));
expect(communityOne.community.icon.unwrapOr("none")).toBe(
communityTwo.community.icon.unwrapOr("none")
);
expect(communityOne.community.banner.unwrapOr("none")).toBe(
communityTwo.community.banner.unwrapOr("none")
);
expect(communityOne.community.published).toBe(
communityTwo.community.published
);
@ -44,35 +48,35 @@ function assertCommunityFederation(
expect(communityOne.community.deleted).toBe(communityTwo.community.deleted);
}
test('Create community', async () => {
test("Create community", async () => {
let communityRes = await createCommunity(alpha);
expect(communityRes.community_view.community.name).toBeDefined();
// A dupe check
let prevName = communityRes.community_view.community.name;
let communityRes2: any = await createCommunity(alpha, prevName);
expect(communityRes2['error']).toBe('community_already_exists');
expect(communityRes2["error"]).toBe("community_already_exists");
// Cache the community on beta, make sure it has the other fields
let searchShort = `!${prevName}@lemmy-alpha:8541`;
let betaCommunity = (await resolveCommunity(beta, searchShort)).community.unwrap();
let betaCommunity = (
await resolveCommunity(beta, searchShort)
).community.unwrap();
assertCommunityFederation(betaCommunity, communityRes.community_view);
});
test('Delete community', async () => {
test("Delete community", async () => {
let communityRes = await createCommunity(beta);
// Cache the community on Alpha
let searchShort = `!${communityRes.community_view.community.name}@lemmy-beta:8551`;
let alphaCommunity = (await resolveCommunity(alpha, searchShort)).community.unwrap();
let alphaCommunity = (
await resolveCommunity(alpha, searchShort)
).community.unwrap();
assertCommunityFederation(alphaCommunity, communityRes.community_view);
// Follow the community from alpha
let follow = await followCommunity(
alpha,
true,
alphaCommunity.community.id
);
let follow = await followCommunity(alpha, true, alphaCommunity.community.id);
// Make sure the follow response went through
expect(follow.community_view.community.local).toBe(false);
@ -83,7 +87,9 @@ test('Delete community', async () => {
communityRes.community_view.community.id
);
expect(deleteCommunityRes.community_view.community.deleted).toBe(true);
expect(deleteCommunityRes.community_view.community.title).toBe(communityRes.community_view.community.title);
expect(deleteCommunityRes.community_view.community.title).toBe(
communityRes.community_view.community.title
);
// Make sure it got deleted on A
let communityOnAlphaDeleted = await getCommunity(
@ -110,20 +116,18 @@ test('Delete community', async () => {
);
});
test('Remove community', async () => {
test("Remove community", async () => {
let communityRes = await createCommunity(beta);
// Cache the community on Alpha
let searchShort = `!${communityRes.community_view.community.name}@lemmy-beta:8551`;
let alphaCommunity = (await resolveCommunity(alpha, searchShort)).community.unwrap();
let alphaCommunity = (
await resolveCommunity(alpha, searchShort)
).community.unwrap();
assertCommunityFederation(alphaCommunity, communityRes.community_view);
// Follow the community from alpha
let follow = await followCommunity(
alpha,
true,
alphaCommunity.community.id
);
let follow = await followCommunity(alpha, true, alphaCommunity.community.id);
// Make sure the follow response went through
expect(follow.community_view.community.local).toBe(false);
@ -134,7 +138,9 @@ test('Remove community', async () => {
communityRes.community_view.community.id
);
expect(removeCommunityRes.community_view.community.removed).toBe(true);
expect(removeCommunityRes.community_view.community.title).toBe(communityRes.community_view.community.title);
expect(removeCommunityRes.community_view.community.title).toBe(
communityRes.community_view.community.title
);
// Make sure it got Removed on A
let communityOnAlphaRemoved = await getCommunity(
@ -161,34 +167,53 @@ test('Remove community', async () => {
);
});
test('Search for beta community', async () => {
test("Search for beta community", async () => {
let communityRes = await createCommunity(beta);
expect(communityRes.community_view.community.name).toBeDefined();
let searchShort = `!${communityRes.community_view.community.name}@lemmy-beta:8551`;
let alphaCommunity = (await resolveCommunity(alpha, searchShort)).community.unwrap();
let alphaCommunity = (
await resolveCommunity(alpha, searchShort)
).community.unwrap();
assertCommunityFederation(alphaCommunity, communityRes.community_view);
});
test('Admin actions in remote community are not federated to origin', async () => {
test("Admin actions in remote community are not federated to origin", async () => {
// create a community on alpha
let communityRes = (await createCommunity(alpha)).community_view;
expect(communityRes.community.name).toBeDefined();
// gamma follows community and posts in it
let gammaCommunity = (await resolveCommunity(gamma, communityRes.community.actor_id)).community.unwrap();
let gammaFollow = (await followCommunity(gamma, true, gammaCommunity.community.id));
let gammaCommunity = (
await resolveCommunity(gamma, communityRes.community.actor_id)
).community.unwrap();
let gammaFollow = await followCommunity(
gamma,
true,
gammaCommunity.community.id
);
expect(gammaFollow.community_view.subscribed).toBe("Subscribed");
let gammaPost = (await createPost(gamma, gammaCommunity.community.id)).post_view;
let gammaPost = (await createPost(gamma, gammaCommunity.community.id))
.post_view;
expect(gammaPost.post.id).toBeDefined();
expect(gammaPost.creator_banned_from_community).toBe(false);
// admin of beta decides to ban gamma from community
let betaCommunity = (await resolveCommunity(beta, communityRes.community.actor_id)).community.unwrap();
let bannedUserInfo1 = (await getSite(gamma)).my_user.unwrap().local_user_view.person;
let bannedUserInfo2 = (await resolvePerson(beta, bannedUserInfo1.actor_id)).person.unwrap();
let banRes = (await banPersonFromCommunity(beta, bannedUserInfo2.person.id, betaCommunity.community.id, true, true));
console.log(banRes);
let betaCommunity = (
await resolveCommunity(beta, communityRes.community.actor_id)
).community.unwrap();
let bannedUserInfo1 = (await getSite(gamma)).my_user.unwrap().local_user_view
.person;
let bannedUserInfo2 = (
await resolvePerson(beta, bannedUserInfo1.actor_id)
).person.unwrap();
let banRes = await banPersonFromCommunity(
beta,
bannedUserInfo2.person.id,
betaCommunity.community.id,
true,
true
);
expect(banRes.banned).toBe(true);
// ban doesnt federate to community's origin instance alpha
@ -196,6 +221,6 @@ test('Admin actions in remote community are not federated to origin', async () =
expect(alphaPost.creator_banned_from_community).toBe(false);
// and neither to gamma
let gammaPost2 = (await getPost(gamma, gammaPost.post.id));
let gammaPost2 = await getPost(gamma, gammaPost.post.id);
expect(gammaPost2.post_view.creator_banned_from_community).toBe(false);
});

View file

@ -1,5 +1,6 @@
jest.setTimeout(120000);
import {SubscribedType} from 'lemmy-js-client';
import { SubscribedType } from "lemmy-js-client";
import {
alpha,
setupLogins,
@ -7,8 +8,7 @@ import {
followCommunity,
unfollowRemotes,
getSite,
delay,
} from './shared';
} from "./shared";
beforeAll(async () => {
await setupLogins();
@ -18,24 +18,20 @@ afterAll(async () => {
await unfollowRemotes(alpha);
});
test('Follow federated community', async () => {
test("Follow federated community", async () => {
let betaCommunity = (await resolveBetaCommunity(alpha)).community.unwrap();
let follow = await followCommunity(
alpha,
true,
betaCommunity.community.id
);
let follow = await followCommunity(alpha, true, betaCommunity.community.id);
// Make sure the follow response went through
expect(follow.community_view.community.local).toBe(false);
expect(follow.community_view.community.name).toBe('main');
expect(follow.community_view.community.name).toBe("main");
expect(follow.community_view.subscribed).toBe(SubscribedType.Subscribed);
// Check it from local
let site = await getSite(alpha);
let remoteCommunityId = site.my_user.unwrap().follows.find(
c => c.community.local == false
).community.id;
let remoteCommunityId = site.my_user
.unwrap()
.follows.find(c => c.community.local == false).community.id;
expect(remoteCommunityId).toBeDefined();
expect(site.my_user.unwrap().follows.length).toBe(2);

View file

@ -1,6 +1,7 @@
jest.setTimeout(120000);
import {None} from '@sniptt/monads';
import { PostView, CommunityView } from 'lemmy-js-client';
import { None } from "@sniptt/monads";
import { PostView, CommunityView } from "lemmy-js-client";
import {
alpha,
beta,
@ -33,8 +34,8 @@ import {
API,
getSite,
unfollows,
resolveCommunity
} from './shared';
resolveCommunity,
} from "./shared";
let betaCommunity: CommunityView;
@ -52,12 +53,22 @@ afterAll(async () => {
function assertPostFederation(postOne: PostView, postTwo: PostView) {
expect(postOne.post.ap_id).toBe(postTwo.post.ap_id);
expect(postOne.post.name).toBe(postTwo.post.name);
expect(postOne.post.body.unwrapOr("none")).toBe(postTwo.post.body.unwrapOr("none"));
expect(postOne.post.url.unwrapOr("none")).toBe(postTwo.post.url.unwrapOr("none"));
expect(postOne.post.body.unwrapOr("none")).toBe(
postTwo.post.body.unwrapOr("none")
);
expect(postOne.post.url.unwrapOr("https://google.com/")).toBe(
postTwo.post.url.unwrapOr("https://google.com/")
);
expect(postOne.post.nsfw).toBe(postTwo.post.nsfw);
expect(postOne.post.embed_title.unwrapOr("none")).toBe(postTwo.post.embed_title.unwrapOr("none"));
expect(postOne.post.embed_description.unwrapOr("none")).toBe(postTwo.post.embed_description.unwrapOr("none"));
expect(postOne.post.embed_html.unwrapOr("none")).toBe(postTwo.post.embed_html.unwrapOr("none"));
expect(postOne.post.embed_title.unwrapOr("none")).toBe(
postTwo.post.embed_title.unwrapOr("none")
);
expect(postOne.post.embed_description.unwrapOr("none")).toBe(
postTwo.post.embed_description.unwrapOr("none")
);
expect(postOne.post.embed_video_url.unwrapOr("none")).toBe(
postTwo.post.embed_video_url.unwrapOr("none")
);
expect(postOne.post.published).toBe(postTwo.post.published);
expect(postOne.community.actor_id).toBe(postTwo.community.actor_id);
expect(postOne.post.locked).toBe(postTwo.post.locked);
@ -65,7 +76,7 @@ function assertPostFederation(postOne: PostView, postTwo: PostView) {
expect(postOne.post.deleted).toBe(postTwo.post.deleted);
}
test('Create a post', async () => {
test("Create a post", async () => {
let postRes = await createPost(alpha, betaCommunity.community.id);
expect(postRes.post_view.post).toBeDefined();
expect(postRes.post_view.community.local).toBe(false);
@ -73,7 +84,9 @@ test('Create a post', async () => {
expect(postRes.post_view.counts.score).toBe(1);
// Make sure that post is liked on beta
let betaPost = (await resolvePost(beta, postRes.post_view.post)).post.unwrap();
let betaPost = (
await resolvePost(beta, postRes.post_view.post)
).post.unwrap();
expect(betaPost).toBeDefined();
expect(betaPost.community.local).toBe(true);
@ -83,19 +96,19 @@ test('Create a post', async () => {
// Delta only follows beta, so it should not see an alpha ap_id
let deltaPost = (await resolvePost(delta, postRes.post_view.post)).post;
expect(deltaPost.isNone()).toBe(true)
expect(deltaPost.isNone()).toBe(true);
// Epsilon has alpha blocked, it should not see the alpha post
let epsilonPost = (await resolvePost(epsilon, postRes.post_view.post)).post;
expect(epsilonPost.isNone()).toBe(true);
});
test('Create a post in a non-existent community', async () => {
let postRes = await createPost(alpha, -2) as any;
expect(postRes.error).toBe('couldnt_find_community');
test("Create a post in a non-existent community", async () => {
let postRes = (await createPost(alpha, -2)) as any;
expect(postRes.error).toBe("couldnt_find_community");
});
test('Unlike a post', async () => {
test("Unlike a post", async () => {
let postRes = await createPost(alpha, betaCommunity.community.id);
let unlike = await likePost(alpha, 0, postRes.post_view.post);
expect(unlike.post_view.counts.score).toBe(0);
@ -105,7 +118,9 @@ test('Unlike a post', async () => {
expect(unlike2.post_view.counts.score).toBe(0);
// Make sure that post is unliked on beta
let betaPost = (await resolvePost(beta, postRes.post_view.post)).post.unwrap();
let betaPost = (
await resolvePost(beta, postRes.post_view.post)
).post.unwrap();
expect(betaPost).toBeDefined();
expect(betaPost.community.local).toBe(true);
expect(betaPost.creator.local).toBe(false);
@ -113,36 +128,42 @@ test('Unlike a post', async () => {
assertPostFederation(betaPost, postRes.post_view);
});
test('Update a post', async () => {
test("Update a post", async () => {
let postRes = await createPost(alpha, betaCommunity.community.id);
let updatedName = 'A jest test federated post, updated';
let updatedName = "A jest test federated post, updated";
let updatedPost = await editPost(alpha, postRes.post_view.post);
expect(updatedPost.post_view.post.name).toBe(updatedName);
expect(updatedPost.post_view.community.local).toBe(false);
expect(updatedPost.post_view.creator.local).toBe(true);
// Make sure that post is updated on beta
let betaPost = (await resolvePost(beta, postRes.post_view.post)).post.unwrap();
let betaPost = (
await resolvePost(beta, postRes.post_view.post)
).post.unwrap();
expect(betaPost.community.local).toBe(true);
expect(betaPost.creator.local).toBe(false);
expect(betaPost.post.name).toBe(updatedName);
assertPostFederation(betaPost, updatedPost.post_view);
// Make sure lemmy beta cannot update the post
let updatedPostBeta = await editPost(beta, betaPost.post) as any;
expect(updatedPostBeta.error).toBe('no_post_edit_allowed');
let updatedPostBeta = (await editPost(beta, betaPost.post)) as any;
expect(updatedPostBeta.error).toBe("no_post_edit_allowed");
});
test('Sticky a post', async () => {
test("Sticky a post", async () => {
let postRes = await createPost(alpha, betaCommunity.community.id);
let betaPost1 = (await resolvePost(beta, postRes.post_view.post)).post.unwrap();
let betaPost1 = (
await resolvePost(beta, postRes.post_view.post)
).post.unwrap();
let stickiedPostRes = await stickyPost(beta, true, betaPost1.post);
expect(stickiedPostRes.post_view.post.stickied).toBe(true);
// Make sure that post is stickied on beta
let betaPost = (await resolvePost(beta, postRes.post_view.post)).post.unwrap();
let betaPost = (
await resolvePost(beta, postRes.post_view.post)
).post.unwrap();
expect(betaPost.community.local).toBe(true);
expect(betaPost.creator.local).toBe(false);
expect(betaPost.post.stickied).toBe(true);
@ -152,25 +173,33 @@ test('Sticky a post', async () => {
expect(unstickiedPost.post_view.post.stickied).toBe(false);
// Make sure that post is unstickied on beta
let betaPost2 = (await resolvePost(beta, postRes.post_view.post)).post.unwrap();
let betaPost2 = (
await resolvePost(beta, postRes.post_view.post)
).post.unwrap();
expect(betaPost2.community.local).toBe(true);
expect(betaPost2.creator.local).toBe(false);
expect(betaPost2.post.stickied).toBe(false);
// Make sure that gamma cannot sticky the post on beta
let gammaPost = (await resolvePost(gamma, postRes.post_view.post)).post.unwrap();
let gammaPost = (
await resolvePost(gamma, postRes.post_view.post)
).post.unwrap();
let gammaTrySticky = await stickyPost(gamma, true, gammaPost.post);
let betaPost3 = (await resolvePost(beta, postRes.post_view.post)).post.unwrap();
let betaPost3 = (
await resolvePost(beta, postRes.post_view.post)
).post.unwrap();
expect(gammaTrySticky.post_view.post.stickied).toBe(true);
expect(betaPost3.post.stickied).toBe(false);
});
test('Lock a post', async () => {
test("Lock a post", async () => {
await followCommunity(alpha, true, betaCommunity.community.id);
let postRes = await createPost(alpha, betaCommunity.community.id);
// Lock the post
let betaPost1 = (await resolvePost(beta, postRes.post_view.post)).post.unwrap();
let betaPost1 = (
await resolvePost(beta, postRes.post_view.post)
).post.unwrap();
let lockedPostRes = await lockPost(beta, true, betaPost1.post);
expect(lockedPostRes.post_view.post.locked).toBe(true);
@ -181,7 +210,7 @@ test('Lock a post', async () => {
// Try to make a new comment there, on alpha
let comment: any = await createComment(alpha, alphaPost1.post.id, None);
expect(comment['error']).toBe('locked');
expect(comment["error"]).toBe("locked");
// Unlock a post
let unlockedPost = await lockPost(beta, false, betaPost1.post);
@ -199,7 +228,7 @@ test('Lock a post', async () => {
expect(commentAlpha).toBeDefined();
});
test('Delete a post', async () => {
test("Delete a post", async () => {
let postRes = await createPost(alpha, betaCommunity.community.id);
expect(postRes.post_view.post).toBeDefined();
@ -217,26 +246,38 @@ test('Delete a post', async () => {
expect(undeletedPost.post_view.post.deleted).toBe(false);
// Make sure lemmy beta sees post is undeleted
let betaPost2 = (await resolvePost(beta, postRes.post_view.post)).post.unwrap();
let betaPost2 = (
await resolvePost(beta, postRes.post_view.post)
).post.unwrap();
expect(betaPost2.post.deleted).toBe(false);
assertPostFederation(betaPost2, undeletedPost.post_view);
// Make sure lemmy beta cannot delete the post
let deletedPostBeta = await deletePost(beta, true, betaPost2.post) as any;
expect(deletedPostBeta.error).toStrictEqual('no_post_edit_allowed');
let deletedPostBeta = (await deletePost(beta, true, betaPost2.post)) as any;
expect(deletedPostBeta.error).toStrictEqual("no_post_edit_allowed");
});
test('Remove a post from admin and community on different instance', async () => {
let gammaCommunity = await resolveCommunity(gamma, betaCommunity.community.actor_id);
let postRes = await createPost(gamma, gammaCommunity.community.unwrap().community.id);
test("Remove a post from admin and community on different instance", async () => {
let gammaCommunity = await resolveCommunity(
gamma,
betaCommunity.community.actor_id
);
let postRes = await createPost(
gamma,
gammaCommunity.community.unwrap().community.id
);
let alphaPost = (await resolvePost(alpha, postRes.post_view.post)).post.unwrap();
let alphaPost = (
await resolvePost(alpha, postRes.post_view.post)
).post.unwrap();
let removedPost = await removePost(alpha, true, alphaPost.post);
expect(removedPost.post_view.post.removed).toBe(true);
expect(removedPost.post_view.post.name).toBe(postRes.post_view.post.name);
// Make sure lemmy beta sees post is NOT removed
let betaPost = (await resolvePost(beta, postRes.post_view.post)).post.unwrap();
let betaPost = (
await resolvePost(beta, postRes.post_view.post)
).post.unwrap();
expect(betaPost.post.removed).toBe(false);
// Undelete
@ -244,12 +285,14 @@ test('Remove a post from admin and community on different instance', async () =>
expect(undeletedPost.post_view.post.removed).toBe(false);
// Make sure lemmy beta sees post is undeleted
let betaPost2 = (await resolvePost(beta, postRes.post_view.post)).post.unwrap();
let betaPost2 = (
await resolvePost(beta, postRes.post_view.post)
).post.unwrap();
expect(betaPost2.post.removed).toBe(false);
assertPostFederation(betaPost2, undeletedPost.post_view);
});
test('Remove a post from admin and community on same instance', async () => {
test("Remove a post from admin and community on same instance", async () => {
await followBeta(alpha);
let postRes = await createPost(alpha, betaCommunity.community.id);
expect(postRes.post_view.post).toBeDefined();
@ -279,26 +322,31 @@ test('Remove a post from admin and community on same instance', async () => {
await unfollowRemotes(alpha);
});
test('Search for a post', async () => {
test("Search for a post", async () => {
await unfollowRemotes(alpha);
let postRes = await createPost(alpha, betaCommunity.community.id);
expect(postRes.post_view.post).toBeDefined();
let betaPost = (await resolvePost(beta, postRes.post_view.post)).post.unwrap();
let betaPost = (
await resolvePost(beta, postRes.post_view.post)
).post.unwrap();
expect(betaPost.post.name).toBeDefined();
});
test('Enforce site ban for federated user', async () => {
test("Enforce site ban for federated user", async () => {
// create a test user
let alphaUserJwt = await registerUser(alpha);
expect(alphaUserJwt).toBeDefined();
let alpha_user: API = {
client: alpha.client,
auth: alphaUserJwt.jwt,
client: alpha.client,
auth: alphaUserJwt.jwt,
};
let alphaUserActorId = (await getSite(alpha_user)).my_user.unwrap().local_user_view.person.actor_id;
let alphaUserActorId = (await getSite(alpha_user)).my_user.unwrap()
.local_user_view.person.actor_id;
expect(alphaUserActorId).toBeDefined();
let alphaPerson = (await resolvePerson(alpha_user, alphaUserActorId)).person.unwrap();
let alphaPerson = (
await resolvePerson(alpha_user, alphaUserActorId)
).person.unwrap();
expect(alphaPerson).toBeDefined();
// alpha makes post in beta community, it federates to beta instance
@ -307,7 +355,12 @@ test('Enforce site ban for federated user', async () => {
expect(searchBeta1.posts[0]).toBeDefined();
// ban alpha from its instance
let banAlpha = await banPersonFromSite(alpha, alphaPerson.person.id, true, true);
let banAlpha = await banPersonFromSite(
alpha,
alphaPerson.person.id,
true,
true
);
expect(banAlpha.banned).toBe(true);
// alpha ban should be federated to beta
@ -319,7 +372,12 @@ test('Enforce site ban for federated user', async () => {
expect(searchBeta2.posts[0]).toBeUndefined();
// Unban alpha
let unBanAlpha = await banPersonFromSite(alpha, alphaPerson.person.id, false, 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
@ -327,11 +385,11 @@ test('Enforce site ban for federated user', async () => {
let searchBeta3 = await searchPostLocal(beta, postRes2.post_view.post);
expect(searchBeta3.posts[0]).toBeDefined();
let alphaUserOnBeta2 = await resolvePerson(beta, alphaUserActorId)
let alphaUserOnBeta2 = await resolvePerson(beta, alphaUserActorId);
expect(alphaUserOnBeta2.person.unwrap().person.banned).toBe(false);
});
test('Enforce community ban for federated user', async () => {
test("Enforce community ban for federated user", async () => {
let alphaShortname = `@lemmy_alpha@lemmy-alpha:8541`;
let alphaPerson = (await resolvePerson(beta, alphaShortname)).person.unwrap();
expect(alphaPerson).toBeDefined();
@ -342,7 +400,13 @@ test('Enforce community ban for federated user', async () => {
expect(searchBeta1.posts[0]).toBeDefined();
// ban alpha from beta community
let banAlpha = await banPersonFromCommunity(beta, alphaPerson.person.id, 2, true, true);
let banAlpha = await banPersonFromCommunity(
beta,
alphaPerson.person.id,
2,
true,
true
);
expect(banAlpha.banned).toBe(true);
// ensure that the post by alpha got removed
@ -373,29 +437,37 @@ test('Enforce community ban for federated user', async () => {
expect(searchBeta2.posts[0]).toBeDefined();
});
test('A and G subscribe to B (center) A posts, it gets announced to G', async () => {
test("A and G subscribe to B (center) A posts, it gets announced to G", async () => {
let postRes = await createPost(alpha, betaCommunity.community.id);
expect(postRes.post_view.post).toBeDefined();
let betaPost = (await resolvePost(gamma, postRes.post_view.post)).post.unwrap();
let betaPost = (
await resolvePost(gamma, postRes.post_view.post)
).post.unwrap();
expect(betaPost.post.name).toBeDefined();
});
test('Report a post', async () => {
test("Report a post", async () => {
let betaCommunity = (await resolveBetaCommunity(beta)).community.unwrap();
let postRes = await createPost(beta, betaCommunity.community.id);
expect(postRes.post_view.post).toBeDefined();
let alphaPost = (await resolvePost(alpha, postRes.post_view.post)).post.unwrap();
let alphaReport = (await reportPost(alpha, alphaPost.post.id, randomString(10)))
.post_report_view.post_report;
let alphaPost = (
await resolvePost(alpha, postRes.post_view.post)
).post.unwrap();
let alphaReport = (
await reportPost(alpha, alphaPost.post.id, randomString(10))
).post_report_view.post_report;
let betaReport = (await listPostReports(beta)).post_reports[0].post_report;
expect(betaReport).toBeDefined();
expect(betaReport.resolved).toBe(false);
expect(betaReport.original_post_name).toBe(alphaReport.original_post_name);
expect(betaReport.original_post_url.unwrapOr("none")).toBe(alphaReport.original_post_url.unwrapOr("none"));
expect(betaReport.original_post_body.unwrapOr("none")).toBe(alphaReport.original_post_body.unwrapOr("none"));
expect(betaReport.original_post_url.unwrapOr("none")).toBe(
alphaReport.original_post_url.unwrapOr("none")
);
expect(betaReport.original_post_body.unwrapOr("none")).toBe(
alphaReport.original_post_body.unwrapOr("none")
);
expect(betaReport.reason).toBe(alphaReport.reason);
});

View file

@ -9,7 +9,7 @@ import {
listPrivateMessages,
deletePrivateMessage,
unfollowRemotes,
} from './shared';
} from "./shared";
let recipient_id: number;
@ -23,7 +23,7 @@ afterAll(async () => {
await unfollowRemotes(alpha);
});
test('Create a private message', async () => {
test("Create a private message", async () => {
let pmRes = await createPrivateMessage(alpha, recipient_id);
expect(pmRes.private_message_view.private_message.content).toBeDefined();
expect(pmRes.private_message_view.private_message.local).toBe(true);
@ -37,8 +37,8 @@ test('Create a private message', async () => {
expect(betaPms.private_messages[0].recipient.local).toBe(true);
});
test('Update a private message', async () => {
let updatedContent = 'A jest test federated private message edited';
test("Update a private message", async () => {
let updatedContent = "A jest test federated private message edited";
let pmRes = await createPrivateMessage(alpha, recipient_id);
let pmUpdated = await editPrivateMessage(
@ -55,7 +55,7 @@ test('Update a private message', async () => {
);
});
test('Delete a private message', async () => {
test("Delete a private message", async () => {
let pmRes = await createPrivateMessage(alpha, recipient_id);
let betaPms1 = await listPrivateMessages(beta);
let deletedPmRes = await deletePrivateMessage(

View file

@ -1,4 +1,4 @@
import {None, Some, Option} from '@sniptt/monads';
import { None, Some, Option } from "@sniptt/monads";
import {
Login,
LoginResponse,
@ -63,8 +63,8 @@ import {
EditSite,
CommentSortType,
GetComments,
GetCommentsResponse
} from 'lemmy-js-client';
GetCommentsResponse,
} from "lemmy-js-client";
export interface API {
client: LemmyHttp;
@ -72,59 +72,59 @@ export interface API {
}
export let alpha: API = {
client: new LemmyHttp('http://127.0.0.1:8541'),
client: new LemmyHttp("http://127.0.0.1:8541"),
auth: None,
};
export let beta: API = {
client: new LemmyHttp('http://127.0.0.1:8551'),
client: new LemmyHttp("http://127.0.0.1:8551"),
auth: None,
};
export let gamma: API = {
client: new LemmyHttp('http://127.0.0.1:8561'),
client: new LemmyHttp("http://127.0.0.1:8561"),
auth: None,
};
export let delta: API = {
client: new LemmyHttp('http://127.0.0.1:8571'),
client: new LemmyHttp("http://127.0.0.1:8571"),
auth: None,
};
export let epsilon: API = {
client: new LemmyHttp('http://127.0.0.1:8581'),
client: new LemmyHttp("http://127.0.0.1:8581"),
auth: None,
};
const password = 'lemmylemmy'
const password = "lemmylemmy";
export async function setupLogins() {
let formAlpha = new Login({
username_or_email: 'lemmy_alpha',
username_or_email: "lemmy_alpha",
password,
});
let resAlpha = alpha.client.login(formAlpha);
let formBeta = new Login({
username_or_email: 'lemmy_beta',
username_or_email: "lemmy_beta",
password,
});
let resBeta = beta.client.login(formBeta);
let formGamma = new Login({
username_or_email: 'lemmy_gamma',
username_or_email: "lemmy_gamma",
password,
});
let resGamma = gamma.client.login(formGamma);
let formDelta = new Login({
username_or_email: 'lemmy_delta',
username_or_email: "lemmy_delta",
password,
});
let resDelta = delta.client.login(formDelta);
let formEpsilon = new Login({
username_or_email: 'lemmy_epsilon',
username_or_email: "lemmy_epsilon",
password,
});
let resEpsilon = epsilon.client.login(formEpsilon);
@ -145,6 +145,8 @@ export async function setupLogins() {
// Registration applications are now enabled by default, need to disable them
let editSiteForm = new EditSite({
require_application: Some(false),
federation_debug: Some(true),
name: None,
sidebar: None,
description: None,
@ -155,23 +157,74 @@ export async function setupLogins() {
enable_nsfw: None,
community_creation_admin_only: None,
require_email_verification: None,
require_application: Some(false),
application_question: None,
private_instance: None,
default_theme: None,
legal_information: None,
default_post_listing_type: None,
legal_information: None,
application_email_admins: None,
hide_modlog_mod_names: None,
discussion_languages: None,
slur_filter_regex: None,
actor_name_max_length: None,
rate_limit_message: Some(999),
rate_limit_message_per_second: None,
rate_limit_post: Some(999),
rate_limit_post_per_second: None,
rate_limit_register: Some(999),
rate_limit_register_per_second: None,
rate_limit_image: Some(999),
rate_limit_image_per_second: None,
rate_limit_comment: Some(999),
rate_limit_comment_per_second: None,
rate_limit_search: Some(999),
rate_limit_search_per_second: None,
federation_enabled: None,
federation_strict_allowlist: None,
federation_http_fetch_retry_limit: None,
federation_worker_count: None,
captcha_enabled: None,
captcha_difficulty: None,
allowed_instances: None,
blocked_instances: None,
auth: "",
});
// Set the blocks and auths for each
editSiteForm.auth = alpha.auth.unwrap();
editSiteForm.allowed_instances = Some([
"lemmy-beta",
"lemmy-gamma",
"lemmy-delta",
"lemmy-epsilon",
]);
await alpha.client.editSite(editSiteForm);
editSiteForm.auth = beta.auth.unwrap();
editSiteForm.allowed_instances = Some([
"lemmy-alpha",
"lemmy-gamma",
"lemmy-delta",
"lemmy-epsilon",
]);
await beta.client.editSite(editSiteForm);
editSiteForm.auth = gamma.auth.unwrap();
editSiteForm.allowed_instances = Some([
"lemmy-alpha",
"lemmy-beta",
"lemmy-delta",
"lemmy-epsilon",
]);
await gamma.client.editSite(editSiteForm);
editSiteForm.allowed_instances = Some(["lemmy-beta"]);
editSiteForm.auth = delta.auth.unwrap();
await delta.client.editSite(editSiteForm);
editSiteForm.auth = epsilon.auth.unwrap();
editSiteForm.allowed_instances = Some([]);
editSiteForm.blocked_instances = Some(["lemmy-alpha"]);
await epsilon.client.editSite(editSiteForm);
// Create the main alpha/beta communities
@ -185,7 +238,7 @@ export async function createPost(
): Promise<PostResponse> {
let name = randomString(5);
let body = Some(randomString(10));
let url = Some('https://google.com/');
let url = Some("https://google.com/");
let form = new CreatePost({
name,
url,
@ -194,12 +247,13 @@ export async function createPost(
community_id,
nsfw: None,
honeypot: None,
language_id: None,
});
return api.client.createPost(form);
}
export async function editPost(api: API, post: Post): Promise<PostResponse> {
let name = Some('A jest test federated post, updated');
let name = Some("A jest test federated post, updated");
let form = new EditPost({
name,
post_id: post.id,
@ -207,6 +261,7 @@ export async function editPost(api: API, post: Post): Promise<PostResponse> {
nsfw: None,
url: None,
body: None,
language_id: None,
});
return api.client.editPost(form);
}
@ -342,7 +397,7 @@ export async function resolveBetaCommunity(
): Promise<ResolveObjectResponse> {
// Use short-hand search url
let form = new ResolveObject({
q: '!main@lemmy-beta:8551',
q: "!main@lemmy-beta:8551",
auth: api.auth,
});
return api.client.resolveObject(form);
@ -415,7 +470,7 @@ export async function followCommunity(
let form = new FollowCommunity({
community_id,
follow,
auth: api.auth.unwrap()
auth: api.auth.unwrap(),
});
return api.client.followCommunity(form);
}
@ -428,7 +483,7 @@ export async function likePost(
let form = new CreatePostLike({
post_id: post.id,
score: score,
auth: api.auth.unwrap()
auth: api.auth.unwrap(),
});
return api.client.likePost(form);
@ -438,13 +493,14 @@ export async function createComment(
api: API,
post_id: number,
parent_id: Option<number>,
content = 'a jest test comment'
content = "a jest test comment"
): Promise<CommentResponse> {
let form = new CreateComment({
content,
post_id,
parent_id,
form_id: None,
language_id: None,
auth: api.auth.unwrap(),
});
return api.client.createComment(form);
@ -453,13 +509,15 @@ export async function createComment(
export async function editComment(
api: API,
comment_id: number,
content = 'A jest test federated comment update'
content = Some("A jest test federated comment update")
): Promise<CommentResponse> {
let form = new EditComment({
content,
comment_id,
form_id: None,
auth: api.auth.unwrap()
language_id: None,
distinguished: None,
auth: api.auth.unwrap(),
});
return api.client.editComment(form);
}
@ -491,7 +549,9 @@ export async function removeComment(
return api.client.removeComment(form);
}
export async function getMentions(api: API): Promise<GetPersonMentionsResponse> {
export async function getMentions(
api: API
): Promise<GetPersonMentionsResponse> {
let form = new GetPersonMentions({
sort: Some(CommentSortType.New),
unread_only: Some(false),
@ -519,7 +579,7 @@ export async function createCommunity(
api: API,
name_: string = randomString(5)
): Promise<CommunityResponse> {
let description = Some('a sample description');
let description = Some("a sample description");
let form = new CreateCommunity({
name: name_,
title: name_,
@ -577,7 +637,7 @@ export async function createPrivateMessage(
api: API,
recipient_id: number
): Promise<PrivateMessageResponse> {
let content = 'A jest test federated private message';
let content = "A jest test federated private message";
let form = new CreatePrivateMessage({
content,
recipient_id,
@ -590,7 +650,7 @@ export async function editPrivateMessage(
api: API,
private_message_id: number
): Promise<PrivateMessageResponse> {
let updatedContent = 'A jest test federated private message edited';
let updatedContent = "A jest test federated private message edited";
let form = new EditPrivateMessage({
content: updatedContent,
private_message_id,
@ -630,18 +690,18 @@ export async function registerUser(
return api.client.register(form);
}
export async function saveUserSettingsBio(
api: API
): Promise<LoginResponse> {
export async function saveUserSettingsBio(api: API): Promise<LoginResponse> {
let form = new SaveUserSettings({
show_nsfw: Some(true),
theme: Some('darkly'),
theme: Some("darkly"),
default_sort_type: Some(Object.keys(SortType).indexOf(SortType.Active)),
default_listing_type: Some(Object.keys(ListingType).indexOf(ListingType.All)),
lang: Some('en'),
default_listing_type: Some(
Object.keys(ListingType).indexOf(ListingType.All)
),
interface_language: Some("en"),
show_avatars: Some(true),
send_notifications_to_email: Some(false),
bio: Some('a changed bio'),
bio: Some("a changed bio"),
avatar: None,
banner: None,
display_name: None,
@ -652,6 +712,7 @@ export async function saveUserSettingsBio(
show_bot_accounts: None,
show_new_post_notifs: None,
bot_account: None,
discussion_languages: None,
auth: api.auth.unwrap(),
});
return saveUserSettings(api, form);
@ -660,18 +721,20 @@ export async function saveUserSettingsBio(
export async function saveUserSettingsFederated(
api: API
): Promise<LoginResponse> {
let avatar = Some('https://image.flaticon.com/icons/png/512/35/35896.png');
let banner = Some('https://image.flaticon.com/icons/png/512/36/35896.png');
let bio = Some('a changed bio');
let avatar = Some("https://image.flaticon.com/icons/png/512/35/35896.png");
let banner = Some("https://image.flaticon.com/icons/png/512/36/35896.png");
let bio = Some("a changed bio");
let form = new SaveUserSettings({
show_nsfw: Some(false),
theme: Some(''),
theme: Some(""),
default_sort_type: Some(Object.keys(SortType).indexOf(SortType.Hot)),
default_listing_type: Some(Object.keys(ListingType).indexOf(ListingType.All)),
lang: Some(''),
default_listing_type: Some(
Object.keys(ListingType).indexOf(ListingType.All)
),
interface_language: Some(""),
avatar,
banner,
display_name: Some('user321'),
display_name: Some("user321"),
show_avatars: Some(false),
send_notifications_to_email: Some(false),
bio,
@ -682,6 +745,7 @@ export async function saveUserSettingsFederated(
bot_account: None,
show_bot_accounts: None,
show_new_post_notifs: None,
discussion_languages: None,
auth: api.auth.unwrap(),
});
return await saveUserSettings(alpha, form);
@ -694,19 +758,15 @@ export async function saveUserSettings(
return api.client.saveUserSettings(form);
}
export async function deleteUser(
api: API
): Promise<DeleteAccountResponse> {
export async function deleteUser(api: API): Promise<DeleteAccountResponse> {
let form = new DeleteAccount({
auth: api.auth.unwrap(),
password
password,
});
return api.client.deleteAccount(form);
}
export async function getSite(
api: API
): Promise<GetSiteResponse> {
export async function getSite(api: API): Promise<GetSiteResponse> {
let form = new GetSite({
auth: api.auth,
});
@ -725,14 +785,12 @@ export async function listPrivateMessages(
return api.client.getPrivateMessages(form);
}
export async function unfollowRemotes(
api: API
): Promise<GetSiteResponse> {
export async function unfollowRemotes(api: API): Promise<GetSiteResponse> {
// Unfollow all remote communities
let site = await getSite(api);
let remoteFollowed = site.my_user.unwrap().follows.filter(
c => c.community.local == false
);
let remoteFollowed = site.my_user
.unwrap()
.follows.filter(c => c.community.local == false);
for (let cu of remoteFollowed) {
await followCommunity(api, false, cu.community.id);
}
@ -743,7 +801,11 @@ export async function unfollowRemotes(
export async function followBeta(api: API): Promise<CommunityResponse> {
let betaCommunity = (await resolveBetaCommunity(api)).community;
if (betaCommunity.isSome()) {
let follow = await followCommunity(api, true, betaCommunity.unwrap().community.id);
let follow = await followCommunity(
api,
true,
betaCommunity.unwrap().community.id
);
return follow;
} else {
return Promise.reject("no community worked");
@ -763,7 +825,9 @@ export async function reportPost(
return api.client.createPostReport(form);
}
export async function listPostReports(api: API): Promise<ListPostReportsResponse> {
export async function listPostReports(
api: API
): Promise<ListPostReportsResponse> {
let form = new ListPostReports({
auth: api.auth.unwrap(),
page: None,
@ -787,7 +851,9 @@ export async function reportComment(
return api.client.createCommentReport(form);
}
export async function listCommentReports(api: API): Promise<ListCommentReportsResponse> {
export async function listCommentReports(
api: API
): Promise<ListCommentReportsResponse> {
let form = new ListCommentReports({
page: None,
limit: None,
@ -798,7 +864,7 @@ export async function listCommentReports(api: API): Promise<ListCommentReportsRe
return api.client.listCommentReports(form);
}
export function delay(millis: number = 500) {
export function delay(millis = 500) {
return new Promise(resolve => setTimeout(resolve, millis));
}
@ -811,8 +877,9 @@ export function wrapper(form: any): string {
}
export function randomString(length: number): string {
var result = '';
var characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_';
var result = "";
var characters =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_";
var charactersLength = characters.length;
for (var i = 0; i < length; i++) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));

View file

@ -1,8 +1,6 @@
jest.setTimeout(120000);
import {None} from '@sniptt/monads';
import {
PersonViewSafe,
} from 'lemmy-js-client';
import { None } from "@sniptt/monads";
import { PersonViewSafe } from "lemmy-js-client";
import {
alpha,
@ -20,7 +18,7 @@ import {
resolveComment,
saveUserSettingsFederated,
setupLogins,
} from './shared';
} from "./shared";
beforeAll(async () => {
await setupLogins();
@ -28,59 +26,82 @@ beforeAll(async () => {
let apShortname: string;
function assertUserFederation(userOne: PersonViewSafe, userTwo: PersonViewSafe) {
function assertUserFederation(
userOne: PersonViewSafe,
userTwo: PersonViewSafe
) {
expect(userOne.person.name).toBe(userTwo.person.name);
expect(userOne.person.display_name.unwrapOr("none")).toBe(userTwo.person.display_name.unwrapOr("none"));
expect(userOne.person.bio.unwrapOr("none")).toBe(userTwo.person.bio.unwrapOr("none"));
expect(userOne.person.display_name.unwrapOr("none")).toBe(
userTwo.person.display_name.unwrapOr("none")
);
expect(userOne.person.bio.unwrapOr("none")).toBe(
userTwo.person.bio.unwrapOr("none")
);
expect(userOne.person.actor_id).toBe(userTwo.person.actor_id);
expect(userOne.person.avatar.unwrapOr("none")).toBe(userTwo.person.avatar.unwrapOr("none"));
expect(userOne.person.banner.unwrapOr("none")).toBe(userTwo.person.banner.unwrapOr("none"));
expect(userOne.person.avatar.unwrapOr("none")).toBe(
userTwo.person.avatar.unwrapOr("none")
);
expect(userOne.person.banner.unwrapOr("none")).toBe(
userTwo.person.banner.unwrapOr("none")
);
expect(userOne.person.published).toBe(userTwo.person.published);
}
test('Create user', async () => {
test("Create user", async () => {
let userRes = await registerUser(alpha);
expect(userRes.jwt).toBeDefined();
alpha.auth = userRes.jwt;
let site = await getSite(alpha);
expect(site.my_user).toBeDefined();
apShortname = `@${site.my_user.unwrap().local_user_view.person.name}@lemmy-alpha:8541`;
apShortname = `@${
site.my_user.unwrap().local_user_view.person.name
}@lemmy-alpha:8541`;
});
test('Set some user settings, check that they are federated', async () => {
test("Set some user settings, check that they are federated", async () => {
await saveUserSettingsFederated(alpha);
let alphaPerson = (await resolvePerson(alpha, apShortname)).person.unwrap();
let betaPerson = (await resolvePerson(beta, apShortname)).person.unwrap();
assertUserFederation(alphaPerson, betaPerson);
});
test('Delete user', async () => {
test("Delete user", async () => {
let userRes = await registerUser(alpha);
expect(userRes.jwt).toBeDefined();
let user: API = {
client: alpha.client,
auth: userRes.jwt
}
auth: userRes.jwt,
};
// make a local post and comment
let alphaCommunity = (await resolveCommunity(user, '!main@lemmy-alpha:8541')).community.unwrap();
let localPost = (await createPost(user, alphaCommunity.community.id)).post_view.post;
let alphaCommunity = (
await resolveCommunity(user, "!main@lemmy-alpha:8541")
).community.unwrap();
let localPost = (await createPost(user, alphaCommunity.community.id))
.post_view.post;
expect(localPost).toBeDefined();
let localComment = (await createComment(user, localPost.id, None)).comment_view.comment;
let localComment = (await createComment(user, localPost.id, None))
.comment_view.comment;
expect(localComment).toBeDefined();
// make a remote post and comment
let betaCommunity = (await resolveBetaCommunity(user)).community.unwrap();
let remotePost = (await createPost(user, betaCommunity.community.id)).post_view.post;
let remotePost = (await createPost(user, betaCommunity.community.id))
.post_view.post;
expect(remotePost).toBeDefined();
let remoteComment = (await createComment(user, remotePost.id, None)).comment_view.comment;
let remoteComment = (await createComment(user, remotePost.id, None))
.comment_view.comment;
expect(remoteComment).toBeDefined();
await deleteUser(user);
expect((await resolvePost(alpha, localPost)).post.isNone()).toBe(true);
expect((await resolveComment(alpha, localComment)).comment.isNone()).toBe(true)
expect((await resolvePost(alpha, remotePost)).post.isNone()).toBe(true)
expect((await resolveComment(alpha, remoteComment)).comment.isNone()).toBe(true)
expect((await resolveComment(alpha, localComment)).comment.isNone()).toBe(
true
);
expect((await resolvePost(alpha, remotePost)).post.isNone()).toBe(true);
expect((await resolveComment(alpha, remoteComment)).comment.isNone()).toBe(
true
);
});

File diff suppressed because it is too large Load diff

View file

@ -94,8 +94,10 @@ impl PerformCrud for EditSite {
blocking(context.pool(), move |conn| {
Site::update(conn, site_id, &site_form)
})
.await?
.map_err(|e| LemmyError::from_error_message(e, "couldnt_update_site"))?;
.await
// Ignore errors for all these, so as to not throw errors if no update occurs
// Diesel will throw an error for empty update forms
.ok();
let local_site_form = LocalSiteUpdateForm::builder()
.enable_downvotes(data.enable_downvotes)
@ -126,8 +128,8 @@ impl PerformCrud for EditSite {
let update_local_site = blocking(context.pool(), move |conn| {
LocalSite::update(conn, &local_site_form)
})
.await?
.map_err(|e| LemmyError::from_error_message(e, "couldnt_update_site"))?;
.await
.ok();
let local_site_rate_limit_form = LocalSiteRateLimitUpdateForm::builder()
.message(data.rate_limit_message)
@ -147,7 +149,8 @@ impl PerformCrud for EditSite {
blocking(context.pool(), move |conn| {
LocalSiteRateLimit::update(conn, &local_site_rate_limit_form)
})
.await??;
.await
.ok();
// Replace the blocked and allowed instances
let allowed = data.allowed_instances.to_owned();
@ -166,7 +169,16 @@ impl PerformCrud for EditSite {
// will be able to log in. It really only wants this to be a requirement for NEW signups.
// So if it was set from false, to true, you need to update all current users columns to be verified.
if !local_site.require_application && update_local_site.require_application {
let new_require_application = update_local_site
.as_ref()
.map(|ols| {
ols
.as_ref()
.map(|ls| ls.require_application)
.unwrap_or(false)
})
.unwrap_or(false);
if !local_site.require_application && new_require_application {
blocking(context.pool(), move |conn| {
LocalUser::set_all_users_registration_applications_accepted(conn)
})
@ -174,7 +186,16 @@ impl PerformCrud for EditSite {
.map_err(|e| LemmyError::from_error_message(e, "couldnt_set_all_registrations_accepted"))?;
}
if !local_site.require_email_verification && update_local_site.require_email_verification {
let new_require_email_verification = update_local_site
.as_ref()
.map(|ols| {
ols
.as_ref()
.map(|ls| ls.require_email_verification)
.unwrap_or(false)
})
.unwrap_or(false);
if !local_site.require_email_verification && new_require_email_verification {
blocking(context.pool(), move |conn| {
LocalUser::set_all_users_email_verified(conn)
})

View file

@ -144,7 +144,7 @@ impl PerformCrud for Register {
.build();
let inserted_local_user = match blocking(context.pool(), move |conn| {
LocalUser::register(conn, &local_user_form)
LocalUser::create(conn, &local_user_form)
})
.await?
{

View file

@ -1,9 +1,6 @@
{
"actor": "http://enterprise.lemmy.ml/u/lemmy_beta",
"object": "http://ds9.lemmy.ml/post/1",
"cc": [
"https://www.w3.org/ns/activitystreams#Public"
],
"type": "Dislike",
"id": "http://enterprise.lemmy.ml/activities/dislike/64d40d40-a829-43a5-8247-1fb595b3ca1c"
}

View file

@ -1,9 +1,6 @@
{
"actor": "http://ds9.lemmy.ml/u/lemmy_alpha",
"object": "http://ds9.lemmy.ml/comment/1",
"cc": [
"https://www.w3.org/ns/activitystreams#Public"
],
"type": "Like",
"id": "http://ds9.lemmy.ml/activities/like/fd61d070-7382-46a9-b2b7-6bb253732877"
}

View file

@ -3,15 +3,9 @@
"object": {
"actor": "http://enterprise.lemmy.ml/u/lemmy_beta",
"object": "http://ds9.lemmy.ml/post/1",
"cc": [
"https://www.w3.org/ns/activitystreams#Public"
],
"type": "Like",
"id": "http://enterprise.lemmy.ml/activities/like/2227ab2c-79e2-4fca-a1d2-1d67dacf2457"
},
"cc": [
"https://www.w3.org/ns/activitystreams#Public"
],
"type": "Undo",
"id": "http://enterprise.lemmy.ml/activities/undo/6cc6fb71-39fe-49ea-9506-f0423b101e98"
}

View file

@ -3,15 +3,9 @@
"object": {
"actor": "http://ds9.lemmy.ml/u/lemmy_alpha",
"object": "http://ds9.lemmy.ml/comment/1",
"cc": [
"https://www.w3.org/ns/activitystreams#Public"
],
"type": "Like",
"id": "http://ds9.lemmy.ml/activities/like/efcf7ae2-dfcc-4ff4-9ce4-6adf251ff004"
},
"cc": [
"https://www.w3.org/ns/activitystreams#Public"
],
"type": "Undo",
"id": "http://ds9.lemmy.ml/activities/undo/3518565c-24a7-4d9e-8e0a-f7a2f45ac618"
}

View file

@ -14,7 +14,10 @@ use activitypub_federation::{
use activitystreams_kinds::public;
use anyhow::anyhow;
use lemmy_api_common::utils::blocking;
use lemmy_db_schema::{newtypes::CommunityId, source::community::Community};
use lemmy_db_schema::{
newtypes::CommunityId,
source::{community::Community, local_site::LocalSite},
};
use lemmy_db_views_actor::structs::{CommunityPersonBanView, CommunityView};
use lemmy_utils::error::LemmyError;
use lemmy_websocket::LemmyContext;
@ -167,6 +170,14 @@ where
ActorT: Actor + ActorType,
Activity: ActivityHandler<Error = LemmyError>,
{
let federation_enabled = blocking(context.pool(), &LocalSite::read)
.await?
.map(|l| l.federation_enabled)
.unwrap_or(false);
if !federation_enabled {
return Ok(());
}
info!("Sending activity {}", activity.id().to_string());
let activity = WithContext::new(activity, CONTEXT.deref().clone());

View file

@ -21,7 +21,7 @@ use activitypub_federation::{
traits::ActivityHandler,
utils::verify_urls_match,
};
use activitystreams_kinds::{activity::UndoType, public};
use activitystreams_kinds::activity::UndoType;
use lemmy_api_common::utils::blocking;
use lemmy_db_schema::{newtypes::CommunityId, source::community::Community, traits::Crud};
use lemmy_utils::error::LemmyError;
@ -54,7 +54,6 @@ impl UndoVote {
let undo_vote = UndoVote {
actor: ObjectId::new(actor.actor_id()),
object,
cc: vec![public()],
kind: UndoType::Undo,
id: id.clone(),
unparsed: Default::default(),

View file

@ -13,7 +13,6 @@ use crate::{
PostOrComment,
};
use activitypub_federation::{core::object_id::ObjectId, data::Data, traits::ActivityHandler};
use activitystreams_kinds::public;
use anyhow::anyhow;
use lemmy_api_common::utils::blocking;
use lemmy_db_schema::{
@ -37,7 +36,6 @@ impl Vote {
Ok(Vote {
actor: ObjectId::new(actor.actor_id()),
object: ObjectId::new(object.ap_id()),
cc: vec![public()],
kind: kind.clone(),
id: generate_activity_id(kind, &context.settings().get_protocol_and_hostname())?,
unparsed: Default::default(),

View file

@ -13,11 +13,7 @@ use lemmy_db_schema::{
source::{activity::Activity, instance::Instance, local_site::LocalSite},
utils::DbPool,
};
use lemmy_utils::{
error::LemmyError,
location_info,
settings::{structs::Settings, SETTINGS},
};
use lemmy_utils::{error::LemmyError, location_info, settings::structs::Settings};
use lemmy_websocket::LemmyContext;
use once_cell::sync::{Lazy, OnceCell};
use url::{ParseError, Url};
@ -36,6 +32,7 @@ static CONTEXT: Lazy<Vec<serde_json::Value>> = Lazy::new(|| {
});
// TODO: store this in context? but its only used in this crate, no need to expose it elsewhere
// TODO this singleton needs to be redone to account for live data.
fn local_instance(context: &LemmyContext) -> &'static LocalInstance {
static LOCAL_INSTANCE: OnceCell<LocalInstance> = OnceCell::new();
LOCAL_INSTANCE.get_or_init(|| {
@ -58,18 +55,12 @@ fn local_instance(context: &LemmyContext) -> &'static LocalInstance {
.map(|l| l.federation_debug)
.unwrap_or(true);
let local_site_data = fetch_local_site_data(conn)
.expect("should have local_site_data")
.to_owned();
let settings = InstanceSettings::builder()
.http_fetch_retry_limit(http_fetch_retry_limit)
.worker_count(worker_count)
.debug(federation_debug)
// TODO No idea why, but you can't pass context.settings() to the verify_url_function closure
// without the value getting captured.
// TODO this is broken
.verify_url_function(|url| check_apub_id_valid(url, &local_site_data, &SETTINGS))
.http_signature_compat(true)
.build()
.expect("configure federation");
@ -92,6 +83,7 @@ fn local_instance(context: &LemmyContext) -> &'static LocalInstance {
/// `use_strict_allowlist` should be true only when parsing a remote community, or when parsing a
/// post/comment in a local community.
#[tracing::instrument(skip(settings, local_site_data))]
// TODO This function needs to be called by incoming activities
fn check_apub_id_valid(
apub_id: &Url,
local_site_data: &LocalSiteData,

View file

@ -2,7 +2,7 @@ use crate::{
objects::person::ApubPerson,
protocol::{activities::voting::vote::Vote, Unparsed},
};
use activitypub_federation::{core::object_id::ObjectId, deser::helpers::deserialize_one_or_many};
use activitypub_federation::core::object_id::ObjectId;
use activitystreams_kinds::activity::UndoType;
use serde::{Deserialize, Serialize};
use url::Url;
@ -12,8 +12,6 @@ use url::Url;
pub struct UndoVote {
pub(crate) actor: ObjectId<ApubPerson>,
pub(crate) object: Vote,
#[serde(deserialize_with = "deserialize_one_or_many", default)]
pub(crate) cc: Vec<Url>,
#[serde(rename = "type")]
pub(crate) kind: UndoType,
pub(crate) id: Url,

View file

@ -3,7 +3,7 @@ use crate::{
objects::person::ApubPerson,
protocol::Unparsed,
};
use activitypub_federation::{core::object_id::ObjectId, deser::helpers::deserialize_one_or_many};
use activitypub_federation::core::object_id::ObjectId;
use lemmy_utils::error::LemmyError;
use serde::{Deserialize, Serialize};
use std::convert::TryFrom;
@ -15,8 +15,6 @@ use url::Url;
pub struct Vote {
pub(crate) actor: ObjectId<ApubPerson>,
pub(crate) object: ObjectId<PostOrComment>,
#[serde(deserialize_with = "deserialize_one_or_many", default)]
pub(crate) cc: Vec<Url>,
#[serde(rename = "type")]
pub(crate) kind: VoteType,
pub(crate) id: Url,

View file

@ -15,6 +15,7 @@ use diesel::{
RunQueryDsl,
};
use lemmy_utils::error::LemmyError;
use once_cell::sync::OnceCell;
impl LocalUserLanguage {
pub fn read(
@ -23,10 +24,11 @@ impl LocalUserLanguage {
) -> Result<Vec<LanguageId>, Error> {
use crate::schema::local_user_language::dsl::*;
local_user_language
let langs = local_user_language
.filter(local_user_id.eq(for_local_user_id))
.select(language_id)
.get_results(conn)
.get_results(conn)?;
convert_read_languages(conn, langs)
}
/// Update the user's languages.
@ -42,7 +44,7 @@ impl LocalUserLanguage {
// Clear the current user languages
delete(local_user_language.filter(local_user_id.eq(for_local_user_id))).execute(conn)?;
let lang_ids = update_languages(conn, language_ids)?;
let lang_ids = convert_update_languages(conn, language_ids)?;
for l in lang_ids {
let form = LocalUserLanguageForm {
local_user_id: for_local_user_id,
@ -69,10 +71,11 @@ impl SiteLanguage {
pub fn read(conn: &mut PgConnection, for_site_id: SiteId) -> Result<Vec<LanguageId>, Error> {
use crate::schema::site_language::dsl::*;
site_language
let langs = site_language
.filter(site_id.eq(for_site_id))
.select(language_id)
.load(conn)
.load(conn)?;
convert_read_languages(conn, langs)
}
pub fn update(
@ -85,7 +88,7 @@ impl SiteLanguage {
// Clear the current languages
delete(site_language.filter(site_id.eq(for_site_id))).execute(conn)?;
let lang_ids = update_languages(conn, language_ids)?;
let lang_ids = convert_update_languages(conn, language_ids)?;
for l in lang_ids {
let form = SiteLanguageForm {
site_id: for_site_id,
@ -158,10 +161,11 @@ impl CommunityLanguage {
for_community_id: CommunityId,
) -> Result<Vec<LanguageId>, Error> {
use crate::schema::community_language::dsl::*;
community_language
let langs = community_language
.filter(community_id.eq(for_community_id))
.select(language_id)
.get_results(conn)
.get_results(conn)?;
convert_read_languages(conn, langs)
}
pub fn update(
@ -211,8 +215,8 @@ pub fn default_post_language(
}
}
// If no language is given, set all languages
fn update_languages(
/// If no language is given, set all languages
fn convert_update_languages(
conn: &mut PgConnection,
language_ids: Vec<LanguageId>,
) -> Result<Vec<LanguageId>, Error> {
@ -228,6 +232,28 @@ fn update_languages(
}
}
/// If all languages are returned, return empty vec instead
fn convert_read_languages(
conn: &mut PgConnection,
language_ids: Vec<LanguageId>,
) -> Result<Vec<LanguageId>, Error> {
static ALL_LANGUAGES_COUNT: OnceCell<usize> = OnceCell::new();
let count = ALL_LANGUAGES_COUNT.get_or_init(|| {
use crate::schema::language::dsl::*;
let count: i64 = language
.select(count(id))
.first(conn)
.expect("read number of languages");
count as usize
});
if &language_ids.len() == count {
Ok(vec![])
} else {
Ok(language_ids)
}
}
#[cfg(test)]
mod tests {
use crate::{
@ -277,17 +303,33 @@ mod tests {
#[test]
#[serial]
fn test_update_languages() {
fn test_convert_update_languages() {
let conn = &mut establish_unpooled_connection();
// call with empty vec, returns all languages
let updated1 = update_languages(conn, vec![]).unwrap();
assert_eq!(184, updated1.len());
let converted1 = convert_update_languages(conn, vec![]).unwrap();
assert_eq!(184, converted1.len());
// call with nonempty vec, returns same vec
let test_langs = test_langs1(conn);
let updated2 = update_languages(conn, test_langs.clone()).unwrap();
assert_eq!(test_langs, updated2);
let converted2 = convert_update_languages(conn, test_langs.clone()).unwrap();
assert_eq!(test_langs, converted2);
}
#[test]
#[serial]
fn test_convert_read_languages() {
let conn = &mut establish_unpooled_connection();
// call with all languages, returns empty vec
use crate::schema::language::dsl::*;
let all_langs = language.select(id).get_results(conn).unwrap();
let converted1: Vec<LanguageId> = convert_read_languages(conn, all_langs).unwrap();
assert_eq!(0, converted1.len());
// call with nonempty vec, returns same vec
let test_langs = test_langs1(conn);
let converted2 = convert_read_languages(conn, test_langs.clone()).unwrap();
assert_eq!(test_langs, converted2);
}
#[test]

View file

@ -67,15 +67,6 @@ mod safe_settings_type {
}
impl LocalUser {
pub fn register(conn: &mut PgConnection, form: &LocalUserInsertForm) -> Result<Self, Error> {
let mut edited_user = form.clone();
let password_hash =
hash(&form.password_encrypted, DEFAULT_COST).expect("Couldn't hash password");
edited_user.password_encrypted = password_hash;
Self::create(conn, &edited_user)
}
pub fn update_password(
conn: &mut PgConnection,
local_user_id: LocalUserId,
@ -117,8 +108,13 @@ impl Crud for LocalUser {
diesel::delete(local_user.find(local_user_id)).execute(conn)
}
fn create(conn: &mut PgConnection, form: &Self::InsertForm) -> Result<Self, Error> {
let mut form_with_encrypted_password = form.clone();
let password_hash =
hash(&form.password_encrypted, DEFAULT_COST).expect("Couldn't hash password");
form_with_encrypted_password.password_encrypted = password_hash;
let local_user_ = insert_into(local_user)
.values(form)
.values(form_with_encrypted_password)
.get_result::<Self>(conn)?;
let site_languages = SiteLanguage::read_local(conn);

View file

@ -1,7 +1,10 @@
use crate::{newtypes::InstanceId, schema::federation_allowlist};
use crate::newtypes::InstanceId;
use serde::{Deserialize, Serialize};
use std::fmt::Debug;
#[cfg(feature = "full")]
use crate::schema::federation_allowlist;
#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
#[cfg_attr(feature = "full", derive(Queryable, Associations, Identifiable))]
#[cfg_attr(

View file

@ -1,7 +1,10 @@
use crate::{newtypes::InstanceId, schema::federation_blocklist};
use crate::newtypes::InstanceId;
use serde::{Deserialize, Serialize};
use std::fmt::Debug;
#[cfg(feature = "full")]
use crate::schema::federation_blocklist;
#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
#[cfg_attr(feature = "full", derive(Queryable, Associations, Identifiable))]
#[cfg_attr(

View file

@ -1,8 +1,12 @@
use crate::{newtypes::InstanceId, schema::instance};
use crate::newtypes::InstanceId;
use std::fmt::Debug;
#[derive(PartialEq, Eq, Debug, Queryable, Identifiable)]
#[diesel(table_name = instance)]
#[cfg(feature = "full")]
use crate::schema::instance;
#[derive(PartialEq, Eq, Debug)]
#[cfg_attr(feature = "full", derive(Queryable, Identifiable))]
#[cfg_attr(feature = "full", diesel(table_name = instance))]
pub struct Instance {
pub id: InstanceId,
pub domain: String,
@ -10,8 +14,8 @@ pub struct Instance {
pub updated: Option<chrono::NaiveDateTime>,
}
#[derive(Insertable, AsChangeset)]
#[diesel(table_name = instance)]
#[cfg_attr(feature = "full", derive(Insertable, AsChangeset))]
#[cfg_attr(feature = "full", diesel(table_name = instance))]
pub struct InstanceForm {
pub domain: String,
pub updated: Option<chrono::NaiveDateTime>,

View file

@ -6,7 +6,6 @@
admin_username: lemmy_alpha
admin_password: lemmylemmy
site_name: lemmy-alpha
sidebar: alphas sidebar
}
database: {
database: lemmy
@ -16,25 +15,4 @@
port: 5432
pool_size: 5
}
federation: {
enabled: true
allowed_instances: ["lemmy-beta","lemmy-gamma","lemmy-delta","lemmy-epsilon"]
debug: true
}
captcha: {
enabled: false
difficulty: medium
}
rate_limit: {
message: 180
message_per_second: 60
post: 99999
post_per_second: 600
register: 99999
register_per_second: 3600
image: 6
image_per_second: 3600
comment: 99999
comment_per_second: 600
}
}

View file

@ -15,25 +15,4 @@
port: 5432
pool_size: 5
}
federation: {
enabled: true
allowed_instances: ["lemmy-alpha","lemmy-gamma","lemmy-delta","lemmy-epsilon"]
debug: true
}
captcha: {
enabled: false
difficulty: medium
}
rate_limit: {
message: 180
message_per_second: 60
post: 99999
post_per_second: 600
register: 99999
register_per_second: 3600
image: 6
image_per_second: 3600
comment: 99999
comment_per_second: 600
}
}

View file

@ -15,25 +15,4 @@
port: 5432
pool_size: 5
}
federation: {
enabled: true
allowed_instances: ["lemmy-beta"]
debug: true
}
captcha: {
enabled: false
difficulty: medium
}
rate_limit: {
message: 180
message_per_second: 60
post: 99999
post_per_second: 600
register: 99999
register_per_second: 3600
image: 6
image_per_second: 3600
comment: 99999
comment_per_second: 600
}
}

View file

@ -15,25 +15,4 @@
port: 5432
pool_size: 5
}
federation: {
enabled: true
blocked_instances: ["lemmy-alpha"]
debug: true
}
captcha: {
enabled: false
difficulty: medium
}
rate_limit: {
message: 180
message_per_second: 60
post: 99999
post_per_second: 600
register: 99999
register_per_second: 3600
image: 6
image_per_second: 3600
comment: 99999
comment_per_second: 600
}
}

View file

@ -15,25 +15,4 @@
port: 5432
pool_size: 5
}
federation: {
enabled: true
allowed_instances: ["lemmy-alpha","lemmy-beta","lemmy-delta","lemmy-epsilon"]
debug: true
}
captcha: {
enabled: false
difficulty: medium
}
rate_limit: {
message: 180
message_per_second: 60
post: 99999
post_per_second: 600
register: 99999
register_per_second: 3600
image: 6
image_per_second: 3600
comment: 99999
comment_per_second: 600
}
}

View file

@ -9,7 +9,7 @@ alter table site
add column application_question text default 'to verify that you are human, please explain why you want to create an account on this site'::text,
add column private_instance boolean default false not null,
add column default_theme text default 'browser'::text not null,
add column default_post_listing_type text default 'local'::text not null,
add column default_post_listing_type text default 'Local'::text not null,
add column legal_information text,
add column hide_modlog_mod_names boolean default true not null,
add column application_email_admins boolean default false not null;

View file

@ -79,7 +79,7 @@ create table local_site (
application_question text default 'to verify that you are human, please explain why you want to create an account on this site'::text,
private_instance boolean default false not null,
default_theme text default 'browser'::text not null,
default_post_listing_type text default 'local'::text not null,
default_post_listing_type text default 'Local'::text not null,
legal_information text,
hide_modlog_mod_names boolean default true not null,
application_email_admins boolean default false not null,

View file

@ -459,6 +459,16 @@ fn initialize_local_site_2022_10_10(
// Create the rate limit table
let local_site_rate_limit_form = LocalSiteRateLimitInsertForm::builder()
// TODO these have to be set, because the database defaults are too low for the federation
// tests to pass, and there's no way to live update the rate limits without restarting the
// server.
// This can be removed once live rate limits are enabled.
.message(Some(999))
.post(Some(999))
.register(Some(999))
.image(Some(999))
.comment(Some(999))
.search(Some(999))
.local_site_id(local_site.id)
.build();
LocalSiteRateLimit::create(conn, &local_site_rate_limit_form)?;

View file

@ -1,4 +1,3 @@
#![recursion_limit = "512"]
pub mod api_routes;
pub mod code_migrations;
pub mod root_span_builder;

View file

@ -114,6 +114,9 @@ async fn main() -> Result<(), LemmyError> {
// Set up the rate limiter
let rate_limit_config =
local_site_rate_limit_to_rate_limit_config(&site_view.local_site_rate_limit);
// TODO this isn't live-updating
// https://github.com/LemmyNet/lemmy/issues/2508
let rate_limiter = RateLimit {
rate_limiter: Arc::new(Mutex::new(RateLimiter::default())),
rate_limit_config,