2024-11-07 10:49:05 +00:00
|
|
|
jest.setTimeout(120000);
|
|
|
|
|
2024-11-22 15:49:56 +00:00
|
|
|
import { FollowCommunity, LemmyHttp } from "lemmy-js-client";
|
2024-11-07 10:49:05 +00:00
|
|
|
import {
|
|
|
|
alpha,
|
|
|
|
setupLogins,
|
|
|
|
createCommunity,
|
|
|
|
unfollows,
|
|
|
|
registerUser,
|
|
|
|
listCommunityPendingFollows,
|
|
|
|
getCommunity,
|
|
|
|
getCommunityPendingFollowsCount,
|
|
|
|
approveCommunityPendingFollow,
|
|
|
|
randomString,
|
|
|
|
createPost,
|
|
|
|
createComment,
|
|
|
|
beta,
|
|
|
|
resolveCommunity,
|
|
|
|
betaUrl,
|
|
|
|
resolvePost,
|
|
|
|
resolveComment,
|
|
|
|
likeComment,
|
|
|
|
waitUntil,
|
2024-11-22 15:49:56 +00:00
|
|
|
gamma,
|
|
|
|
getPosts,
|
|
|
|
getComments,
|
2024-11-07 10:49:05 +00:00
|
|
|
} from "./shared";
|
|
|
|
|
|
|
|
beforeAll(setupLogins);
|
|
|
|
afterAll(unfollows);
|
|
|
|
|
|
|
|
test("Follow a private community", async () => {
|
|
|
|
// create private community
|
|
|
|
const community = await createCommunity(alpha, randomString(10), "Private");
|
|
|
|
expect(community.community_view.community.visibility).toBe("Private");
|
|
|
|
const alphaCommunityId = community.community_view.community.id;
|
|
|
|
|
|
|
|
// No pending follows yet
|
|
|
|
const pendingFollows0 = await listCommunityPendingFollows(alpha);
|
|
|
|
expect(pendingFollows0.items.length).toBe(0);
|
|
|
|
const pendingFollowsCount0 = await getCommunityPendingFollowsCount(
|
|
|
|
alpha,
|
|
|
|
alphaCommunityId,
|
|
|
|
);
|
|
|
|
expect(pendingFollowsCount0.count).toBe(0);
|
|
|
|
|
|
|
|
// follow as new user
|
|
|
|
const user = await registerUser(beta, betaUrl);
|
|
|
|
const betaCommunity = (
|
|
|
|
await resolveCommunity(user, community.community_view.community.actor_id)
|
|
|
|
).community;
|
|
|
|
expect(betaCommunity).toBeDefined();
|
2024-11-22 15:49:56 +00:00
|
|
|
expect(betaCommunity?.community.visibility).toBe("Private");
|
2024-11-07 10:49:05 +00:00
|
|
|
const betaCommunityId = betaCommunity!.community.id;
|
|
|
|
const follow_form: FollowCommunity = {
|
|
|
|
community_id: betaCommunityId,
|
|
|
|
follow: true,
|
|
|
|
};
|
|
|
|
await user.followCommunity(follow_form);
|
|
|
|
|
|
|
|
// Follow listed as pending
|
|
|
|
const follow1 = await getCommunity(user, betaCommunityId);
|
|
|
|
expect(follow1.community_view.subscribed).toBe("ApprovalRequired");
|
|
|
|
|
|
|
|
// Wait for follow to federate, shown as pending
|
|
|
|
let pendingFollows1 = await waitUntil(
|
|
|
|
() => listCommunityPendingFollows(alpha),
|
|
|
|
f => f.items.length == 1,
|
|
|
|
);
|
|
|
|
expect(pendingFollows1.items[0].is_new_instance).toBe(true);
|
|
|
|
const pendingFollowsCount1 = await getCommunityPendingFollowsCount(
|
|
|
|
alpha,
|
|
|
|
alphaCommunityId,
|
|
|
|
);
|
|
|
|
expect(pendingFollowsCount1.count).toBe(1);
|
|
|
|
|
|
|
|
// user still sees approval required at this point
|
|
|
|
const betaCommunity2 = await getCommunity(user, betaCommunityId);
|
|
|
|
expect(betaCommunity2.community_view.subscribed).toBe("ApprovalRequired");
|
|
|
|
|
|
|
|
// Approve the follow
|
|
|
|
const approve = await approveCommunityPendingFollow(
|
|
|
|
alpha,
|
|
|
|
alphaCommunityId,
|
|
|
|
pendingFollows1.items[0].person.id,
|
|
|
|
);
|
|
|
|
expect(approve.success).toBe(true);
|
|
|
|
|
|
|
|
// Follow is confirmed
|
|
|
|
await waitUntil(
|
|
|
|
() => getCommunity(user, betaCommunityId),
|
|
|
|
c => c.community_view.subscribed == "Subscribed",
|
|
|
|
);
|
|
|
|
const pendingFollows2 = await listCommunityPendingFollows(alpha);
|
|
|
|
expect(pendingFollows2.items.length).toBe(0);
|
|
|
|
const pendingFollowsCount2 = await getCommunityPendingFollowsCount(
|
|
|
|
alpha,
|
|
|
|
alphaCommunityId,
|
|
|
|
);
|
|
|
|
expect(pendingFollowsCount2.count).toBe(0);
|
|
|
|
|
|
|
|
// follow with another user from that instance, is_new_instance should be false now
|
|
|
|
const user2 = await registerUser(beta, betaUrl);
|
|
|
|
await user2.followCommunity(follow_form);
|
|
|
|
let pendingFollows3 = await waitUntil(
|
|
|
|
() => listCommunityPendingFollows(alpha),
|
|
|
|
f => f.items.length == 1,
|
|
|
|
);
|
|
|
|
expect(pendingFollows3.items[0].is_new_instance).toBe(false);
|
|
|
|
|
|
|
|
// cleanup pending follow
|
|
|
|
const approve2 = await approveCommunityPendingFollow(
|
|
|
|
alpha,
|
|
|
|
alphaCommunityId,
|
|
|
|
pendingFollows3.items[0].person.id,
|
|
|
|
);
|
|
|
|
expect(approve2.success).toBe(true);
|
|
|
|
});
|
|
|
|
|
|
|
|
test("Only followers can view and interact with private community content", async () => {
|
|
|
|
// create private community
|
|
|
|
const community = await createCommunity(alpha, randomString(10), "Private");
|
|
|
|
expect(community.community_view.community.visibility).toBe("Private");
|
|
|
|
const alphaCommunityId = community.community_view.community.id;
|
|
|
|
|
|
|
|
// create post and comment
|
|
|
|
const post0 = await createPost(alpha, alphaCommunityId);
|
|
|
|
const post_id = post0.post_view.post.id;
|
|
|
|
expect(post_id).toBeDefined();
|
|
|
|
const comment = await createComment(alpha, post_id);
|
|
|
|
const comment_id = comment.comment_view.comment.id;
|
|
|
|
expect(comment_id).toBeDefined();
|
|
|
|
|
|
|
|
// user is not following the community and cannot view nor create posts
|
|
|
|
const user = await registerUser(beta, betaUrl);
|
|
|
|
const betaCommunity = (
|
|
|
|
await resolveCommunity(user, community.community_view.community.actor_id)
|
|
|
|
).community!.community;
|
|
|
|
await expect(resolvePost(user, post0.post_view.post)).rejects.toStrictEqual(
|
|
|
|
Error("not_found"),
|
|
|
|
);
|
|
|
|
await expect(
|
|
|
|
resolveComment(user, comment.comment_view.comment),
|
|
|
|
).rejects.toStrictEqual(Error("not_found"));
|
|
|
|
await expect(createPost(user, betaCommunity.id)).rejects.toStrictEqual(
|
|
|
|
Error("not_found"),
|
|
|
|
);
|
|
|
|
|
|
|
|
// follow the community and approve
|
|
|
|
const follow_form: FollowCommunity = {
|
|
|
|
community_id: betaCommunity.id,
|
|
|
|
follow: true,
|
|
|
|
};
|
|
|
|
await user.followCommunity(follow_form);
|
2024-11-22 15:49:56 +00:00
|
|
|
approveFollower(alpha, alphaCommunityId);
|
2024-11-07 10:49:05 +00:00
|
|
|
|
|
|
|
// now user can fetch posts and comments in community (using signed fetch), and create posts
|
|
|
|
await waitUntil(
|
|
|
|
() => resolvePost(user, post0.post_view.post),
|
|
|
|
p => p?.post?.post.id != undefined,
|
|
|
|
);
|
|
|
|
const resolvedComment = (
|
|
|
|
await resolveComment(user, comment.comment_view.comment)
|
|
|
|
).comment;
|
|
|
|
expect(resolvedComment?.comment.id).toBeDefined();
|
|
|
|
|
|
|
|
const post1 = await createPost(user, betaCommunity.id);
|
|
|
|
expect(post1.post_view).toBeDefined();
|
|
|
|
const like = await likeComment(user, 1, resolvedComment!.comment);
|
|
|
|
expect(like.comment_view.my_vote).toBe(1);
|
|
|
|
});
|
|
|
|
|
|
|
|
test("Reject follower", async () => {
|
|
|
|
// create private community
|
|
|
|
const community = await createCommunity(alpha, randomString(10), "Private");
|
|
|
|
expect(community.community_view.community.visibility).toBe("Private");
|
|
|
|
const alphaCommunityId = community.community_view.community.id;
|
|
|
|
|
|
|
|
// user is not following the community and cannot view nor create posts
|
|
|
|
const user = await registerUser(beta, betaUrl);
|
|
|
|
const betaCommunity1 = (
|
|
|
|
await resolveCommunity(user, community.community_view.community.actor_id)
|
|
|
|
).community!.community;
|
|
|
|
|
|
|
|
// follow the community and reject
|
|
|
|
const follow_form: FollowCommunity = {
|
|
|
|
community_id: betaCommunity1.id,
|
|
|
|
follow: true,
|
|
|
|
};
|
|
|
|
const follow = await user.followCommunity(follow_form);
|
|
|
|
expect(follow.community_view.subscribed).toBe("ApprovalRequired");
|
|
|
|
|
|
|
|
const pendingFollows1 = await waitUntil(
|
|
|
|
() => listCommunityPendingFollows(alpha),
|
|
|
|
f => f.items.length == 1,
|
|
|
|
);
|
|
|
|
const approve = await approveCommunityPendingFollow(
|
|
|
|
alpha,
|
|
|
|
alphaCommunityId,
|
|
|
|
pendingFollows1.items[0].person.id,
|
|
|
|
false,
|
|
|
|
);
|
|
|
|
expect(approve.success).toBe(true);
|
|
|
|
|
|
|
|
await waitUntil(
|
|
|
|
() => getCommunity(user, betaCommunity1.id),
|
|
|
|
c => c.community_view.subscribed == "NotSubscribed",
|
|
|
|
);
|
|
|
|
});
|
2024-11-22 15:49:56 +00:00
|
|
|
|
|
|
|
test("Follow a private community and receive activities", async () => {
|
|
|
|
// create private community
|
|
|
|
const community = await createCommunity(alpha, randomString(10), "Private");
|
|
|
|
expect(community.community_view.community.visibility).toBe("Private");
|
|
|
|
const alphaCommunityId = community.community_view.community.id;
|
|
|
|
|
|
|
|
// follow with users from beta and gamma
|
|
|
|
const betaCommunity = (
|
|
|
|
await resolveCommunity(beta, community.community_view.community.actor_id)
|
|
|
|
).community;
|
|
|
|
expect(betaCommunity).toBeDefined();
|
|
|
|
const betaCommunityId = betaCommunity!.community.id;
|
|
|
|
const follow_form_beta: FollowCommunity = {
|
|
|
|
community_id: betaCommunityId,
|
|
|
|
follow: true,
|
|
|
|
};
|
|
|
|
await beta.followCommunity(follow_form_beta);
|
|
|
|
await approveFollower(alpha, alphaCommunityId);
|
|
|
|
|
|
|
|
const gammaCommunityId = (
|
|
|
|
await resolveCommunity(gamma, community.community_view.community.actor_id)
|
|
|
|
).community!.community.id;
|
|
|
|
const follow_form_gamma: FollowCommunity = {
|
|
|
|
community_id: gammaCommunityId,
|
|
|
|
follow: true,
|
|
|
|
};
|
|
|
|
await gamma.followCommunity(follow_form_gamma);
|
|
|
|
await approveFollower(alpha, alphaCommunityId);
|
|
|
|
|
|
|
|
// Follow is confirmed
|
|
|
|
await waitUntil(
|
|
|
|
() => getCommunity(beta, betaCommunityId),
|
|
|
|
c => c.community_view.subscribed == "Subscribed",
|
|
|
|
);
|
|
|
|
await waitUntil(
|
|
|
|
() => getCommunity(gamma, gammaCommunityId),
|
|
|
|
c => c.community_view.subscribed == "Subscribed",
|
|
|
|
);
|
|
|
|
|
|
|
|
// create a post and comment from gamma
|
|
|
|
const post = await createPost(gamma, gammaCommunityId);
|
|
|
|
const post_id = post.post_view.post.id;
|
|
|
|
expect(post_id).toBeDefined();
|
|
|
|
const comment = await createComment(gamma, post_id);
|
|
|
|
const comment_id = comment.comment_view.comment.id;
|
|
|
|
expect(comment_id).toBeDefined();
|
|
|
|
|
|
|
|
// post and comment were federated to beta
|
|
|
|
let posts = await waitUntil(
|
|
|
|
() => getPosts(beta, "All", betaCommunityId),
|
|
|
|
c => c.posts.length == 1,
|
|
|
|
);
|
|
|
|
expect(posts.posts[0].post.ap_id).toBe(post.post_view.post.ap_id);
|
|
|
|
expect(posts.posts[0].post.name).toBe(post.post_view.post.name);
|
|
|
|
let comments = await waitUntil(
|
|
|
|
() => getComments(beta, posts.posts[0].post.id),
|
|
|
|
c => c.comments.length == 1,
|
|
|
|
);
|
|
|
|
expect(comments.comments[0].comment.ap_id).toBe(
|
|
|
|
comment.comment_view.comment.ap_id,
|
|
|
|
);
|
|
|
|
expect(comments.comments[0].comment.content).toBe(
|
|
|
|
comment.comment_view.comment.content,
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
test("Fetch remote content in private community", async () => {
|
|
|
|
// create private community
|
|
|
|
const community = await createCommunity(alpha, randomString(10), "Private");
|
|
|
|
expect(community.community_view.community.visibility).toBe("Private");
|
|
|
|
const alphaCommunityId = community.community_view.community.id;
|
|
|
|
|
|
|
|
const betaCommunityId = (
|
|
|
|
await resolveCommunity(beta, community.community_view.community.actor_id)
|
|
|
|
).community!.community.id;
|
|
|
|
const follow_form_beta: FollowCommunity = {
|
|
|
|
community_id: betaCommunityId,
|
|
|
|
follow: true,
|
|
|
|
};
|
|
|
|
await beta.followCommunity(follow_form_beta);
|
|
|
|
await approveFollower(alpha, alphaCommunityId);
|
|
|
|
|
|
|
|
// Follow is confirmed
|
|
|
|
await waitUntil(
|
|
|
|
() => getCommunity(beta, betaCommunityId),
|
|
|
|
c => c.community_view.subscribed == "Subscribed",
|
|
|
|
);
|
|
|
|
|
|
|
|
// beta creates post and comment
|
|
|
|
const post = await createPost(beta, betaCommunityId);
|
|
|
|
const post_id = post.post_view.post.id;
|
|
|
|
expect(post_id).toBeDefined();
|
|
|
|
const comment = await createComment(beta, post_id);
|
|
|
|
const comment_id = comment.comment_view.comment.id;
|
|
|
|
expect(comment_id).toBeDefined();
|
|
|
|
|
|
|
|
// Wait for it to federate
|
|
|
|
await waitUntil(
|
|
|
|
() => resolveComment(alpha, comment.comment_view.comment),
|
|
|
|
p => p?.comment?.comment.id != undefined,
|
|
|
|
);
|
|
|
|
|
|
|
|
// create gamma user
|
|
|
|
const gammaCommunityId = (
|
|
|
|
await resolveCommunity(gamma, community.community_view.community.actor_id)
|
|
|
|
).community!.community.id;
|
|
|
|
const follow_form: FollowCommunity = {
|
|
|
|
community_id: gammaCommunityId,
|
|
|
|
follow: true,
|
|
|
|
};
|
|
|
|
|
|
|
|
// cannot fetch post yet
|
|
|
|
await expect(resolvePost(gamma, post.post_view.post)).rejects.toStrictEqual(
|
|
|
|
Error("not_found"),
|
|
|
|
);
|
|
|
|
// follow community and approve
|
|
|
|
await gamma.followCommunity(follow_form);
|
|
|
|
await approveFollower(alpha, alphaCommunityId);
|
|
|
|
|
|
|
|
// now user can fetch posts and comments in community (using signed fetch), and create posts.
|
|
|
|
// for this to work, beta checks with alpha if gamma is really an approved follower.
|
|
|
|
let resolvedPost = await waitUntil(
|
|
|
|
() => resolvePost(gamma, post.post_view.post),
|
|
|
|
p => p?.post?.post.id != undefined,
|
|
|
|
);
|
|
|
|
expect(resolvedPost.post?.post.ap_id).toBe(post.post_view.post.ap_id);
|
|
|
|
const resolvedComment = await waitUntil(
|
|
|
|
() => resolveComment(gamma, comment.comment_view.comment),
|
|
|
|
p => p?.comment?.comment.id != undefined,
|
|
|
|
);
|
|
|
|
expect(resolvedComment?.comment?.comment.ap_id).toBe(
|
|
|
|
comment.comment_view.comment.ap_id,
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
async function approveFollower(user: LemmyHttp, community_id: number) {
|
|
|
|
let pendingFollows1 = await waitUntil(
|
|
|
|
() => listCommunityPendingFollows(user),
|
|
|
|
f => f.items.length == 1,
|
|
|
|
);
|
|
|
|
const approve = await approveCommunityPendingFollow(
|
|
|
|
alpha,
|
|
|
|
community_id,
|
|
|
|
pendingFollows1.items[0].person.id,
|
|
|
|
);
|
|
|
|
expect(approve.success).toBe(true);
|
|
|
|
}
|