diff --git a/docker/federation-test/run-tests.sh b/docker/federation-test/run-tests.sh index 9d8a7e58f..b2d319ddd 100755 --- a/docker/federation-test/run-tests.sh +++ b/docker/federation-test/run-tests.sh @@ -14,6 +14,7 @@ yarn echo "Waiting for Lemmy to start..." while [[ "$(curl -s -o /dev/null -w '%{http_code}' 'localhost:8540/api/v1/site')" != "200" ]]; do sleep 1; done while [[ "$(curl -s -o /dev/null -w '%{http_code}' 'localhost:8550/api/v1/site')" != "200" ]]; do sleep 1; done +while [[ "$(curl -s -o /dev/null -w '%{http_code}' 'localhost:8560/api/v1/site')" != "200" ]]; do sleep 1; done yarn api-test || true popd diff --git a/docker/federation/docker-compose.yml b/docker/federation/docker-compose.yml index 496e7fa60..3f986a814 100644 --- a/docker/federation/docker-compose.yml +++ b/docker/federation/docker-compose.yml @@ -6,6 +6,7 @@ services: ports: - "8540:8540" - "8550:8550" + - "8560:8560" volumes: # Hack to make this work from both docker/federation/ and docker/federation-test/ - ../federation/nginx.conf:/etc/nginx/nginx.conf @@ -14,6 +15,8 @@ services: - pictshare_alpha - lemmy_beta - pictshare_beta + - lemmy_gamma + - pictshare_gamma - iframely restart: "always" @@ -26,7 +29,7 @@ services: - LEMMY_FRONT_END_DIR=/app/dist - LEMMY_FEDERATION__ENABLED=true - LEMMY_FEDERATION__TLS_ENABLED=false - - LEMMY_FEDERATION__INSTANCE_WHITELIST=lemmy_beta + - LEMMY_FEDERATION__INSTANCE_WHITELIST=lemmy_beta,lemmy_gamma - LEMMY_PORT=8540 - LEMMY_SETUP__ADMIN_USERNAME=lemmy_alpha - LEMMY_SETUP__ADMIN_PASSWORD=lemmy @@ -60,7 +63,7 @@ services: - LEMMY_FRONT_END_DIR=/app/dist - LEMMY_FEDERATION__ENABLED=true - LEMMY_FEDERATION__TLS_ENABLED=false - - LEMMY_FEDERATION__INSTANCE_WHITELIST=lemmy_alpha + - LEMMY_FEDERATION__INSTANCE_WHITELIST=lemmy_alpha,lemmy_gamma - LEMMY_PORT=8550 - LEMMY_SETUP__ADMIN_USERNAME=lemmy_beta - LEMMY_SETUP__ADMIN_PASSWORD=lemmy @@ -85,6 +88,40 @@ services: - ./volumes/pictshare_beta:/usr/share/nginx/html/data restart: always + lemmy_gamma: + image: lemmy-federation:latest + environment: + - LEMMY_HOSTNAME=lemmy_gamma:8560 + - LEMMY_DATABASE_URL=postgres://lemmy:password@postgres_gamma:5432/lemmy + - LEMMY_JWT_SECRET=changeme + - LEMMY_FRONT_END_DIR=/app/dist + - LEMMY_FEDERATION__ENABLED=true + - LEMMY_FEDERATION__TLS_ENABLED=false + - LEMMY_FEDERATION__INSTANCE_WHITELIST=lemmy_alpha,lemmy_beta + - LEMMY_PORT=8560 + - LEMMY_SETUP__ADMIN_USERNAME=lemmy_gamma + - LEMMY_SETUP__ADMIN_PASSWORD=lemmy + - LEMMY_SETUP__SITE_NAME=lemmy_gamma + - RUST_BACKTRACE=1 + - RUST_LOG=debug + restart: always + depends_on: + - postgres_gamma + postgres_gamma: + image: postgres:12-alpine + environment: + - POSTGRES_USER=lemmy + - POSTGRES_PASSWORD=password + - POSTGRES_DB=lemmy + volumes: + - ./volumes/postgres_gamma:/var/lib/postgresql/data + restart: always + pictshare_gamma: + image: shtripok/pictshare:latest + volumes: + - ./volumes/pictshare_gamma:/usr/share/nginx/html/data + restart: always + iframely: image: dogbin/iframely:latest volumes: diff --git a/docker/federation/nginx.conf b/docker/federation/nginx.conf index c0633ea42..a73b0954e 100644 --- a/docker/federation/nginx.conf +++ b/docker/federation/nginx.conf @@ -72,4 +72,39 @@ http { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } } + + server { + listen 8560; + server_name 127.0.0.1; + access_log off; + + # Upload limit for pictshare + client_max_body_size 50M; + + location / { + proxy_pass http://lemmy_gamma:8560; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + + # WebSocket support + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + } + + location /pictshare/ { + proxy_pass http://pictshare_gamma:80/; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + } + + location /iframely/ { + proxy_pass http://iframely:80/; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + } + } } diff --git a/server/src/apub/shared_inbox.rs b/server/src/apub/shared_inbox.rs index 81dd14c39..3ecc873e5 100644 --- a/server/src/apub/shared_inbox.rs +++ b/server/src/apub/shared_inbox.rs @@ -218,7 +218,6 @@ where let community = Community::read_from_actor_id(conn, &community_uri)?; if community.local { let sending_user = get_or_fetch_and_upsert_remote_user(&sender.to_string(), &conn)?; - insert_activity(&conn, sending_user.id, &activity, false)?; Community::do_announce(activity, &community, &sending_user, conn) } else { Ok(HttpResponse::NotFound().finish()) diff --git a/ui/src/api_tests/api.spec.ts b/ui/src/api_tests/api.spec.ts index d5da17c7f..4e38cfee4 100644 --- a/ui/src/api_tests/api.spec.ts +++ b/ui/src/api_tests/api.spec.ts @@ -26,12 +26,17 @@ import { } from '../interfaces'; let lemmyAlphaUrl = 'http://localhost:8540'; -let lemmyBetaUrl = 'http://localhost:8550'; let lemmyAlphaApiUrl = `${lemmyAlphaUrl}/api/v1`; -let lemmyBetaApiUrl = `${lemmyBetaUrl}/api/v1`; let lemmyAlphaAuth: string; + +let lemmyBetaUrl = 'http://localhost:8550'; +let lemmyBetaApiUrl = `${lemmyBetaUrl}/api/v1`; let lemmyBetaAuth: string; +let lemmyGammaUrl = 'http://localhost:8560'; +let lemmyGammaApiUrl = `${lemmyGammaUrl}/api/v1`; +let lemmyGammaAuth: string; + // Workaround for tests being run before beforeAll() is finished // https://github.com/facebook/jest/issues/9527#issuecomment-592406108 describe('main', () => { @@ -67,6 +72,22 @@ describe('main', () => { }).then(d => d.json()); lemmyBetaAuth = resB.jwt; + + console.log('Logging in as lemmy_gamma'); + let formC = { + username_or_email: 'lemmy_gamma', + password: 'lemmy', + }; + + let resG: LoginResponse = await fetch(`${lemmyGammaApiUrl}/user/login`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: wrapper(formC), + }).then(d => d.json()); + + lemmyGammaAuth = resG.jwt; }); describe('post_search', () => { @@ -190,6 +211,51 @@ describe('main', () => { // Make sure the follow response went through expect(followResAgain.community.local).toBe(false); expect(followResAgain.community.name).toBe('main'); + + // Also make G follow B + + // Use short-hand search url + let searchUrlG = `${lemmyGammaApiUrl}/search?q=!main@lemmy_beta:8550&type_=All&sort=TopAll`; + + let searchResponseG: SearchResponse = await fetch(searchUrlG, { + method: 'GET', + }).then(d => d.json()); + + expect(searchResponseG.communities[0].name).toBe('main'); + + let followFormG: FollowCommunityForm = { + community_id: searchResponseG.communities[0].id, + follow: true, + auth: lemmyGammaAuth, + }; + + let followResG: CommunityResponse = await fetch( + `${lemmyGammaApiUrl}/community/follow`, + { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: wrapper(followFormG), + } + ).then(d => d.json()); + + // Make sure the follow response went through + expect(followResG.community.local).toBe(false); + expect(followResG.community.name).toBe('main'); + + // Check that you are subscribed to it locally + let followedCommunitiesUrlG = `${lemmyGammaApiUrl}/user/followed_communities?&auth=${lemmyGammaAuth}`; + let followedCommunitiesResG: GetFollowedCommunitiesResponse = await fetch( + followedCommunitiesUrlG, + { + method: 'GET', + } + ).then(d => d.json()); + + expect(followedCommunitiesResG.communities[1].community_local).toBe( + false + ); }); }); @@ -1176,6 +1242,78 @@ describe('main', () => { expect(searchResponse.comments[0].content).toBe(content); }); }); + + describe('announce', () => { + test('A and G subscribe to B (center) A does action, it gets announced to G', async () => { + // A and G are already subscribed to B earlier. + // + let postName = 'A jest test post for announce'; + let createPostForm: PostForm = { + name: postName, + auth: lemmyAlphaAuth, + community_id: 2, + creator_id: 2, + nsfw: false, + }; + + let createPostRes: PostResponse = await fetch( + `${lemmyAlphaApiUrl}/post`, + { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: wrapper(createPostForm), + } + ).then(d => d.json()); + expect(createPostRes.post.name).toBe(postName); + + // Make sure that post got announced to Gamma + let searchUrl = `${lemmyGammaApiUrl}/search?q=${createPostRes.post.ap_id}&type_=All&sort=TopAll`; + let searchResponse: SearchResponse = await fetch(searchUrl, { + method: 'GET', + }).then(d => d.json()); + let postId = searchResponse.posts[0].id; + expect(searchResponse.posts[0].name).toBe(postName); + + // Create a test comment on Gamma, make sure it gets announced to alpha + let commentContent = + 'A jest test federated comment announce, lets mention @lemmy_beta@lemmy_beta:8550'; + + let commentForm: CommentForm = { + content: commentContent, + post_id: postId, + auth: lemmyGammaAuth, + }; + + let createCommentRes: CommentResponse = await fetch( + `${lemmyGammaApiUrl}/comment`, + { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: wrapper(commentForm), + } + ).then(d => d.json()); + + expect(createCommentRes.comment.content).toBe(commentContent); + expect(createCommentRes.comment.community_local).toBe(false); + expect(createCommentRes.comment.creator_local).toBe(true); + expect(createCommentRes.comment.score).toBe(1); + + // Get the post from alpha, make sure it has gamma's comment + let getPostUrl = `${lemmyAlphaApiUrl}/post?id=5`; + let getPostRes: GetPostResponse = await fetch(getPostUrl, { + method: 'GET', + }).then(d => d.json()); + + expect(getPostRes.comments[0].content).toBe(commentContent); + expect(getPostRes.comments[0].community_local).toBe(true); + expect(getPostRes.comments[0].creator_local).toBe(false); + expect(getPostRes.comments[0].score).toBe(1); + }); + }); }); function wrapper(form: any): string {