Merge branch 'remove-hardcoded-https-dess' into main

This commit is contained in:
Dessalines 2020-10-01 12:56:04 -05:00
commit 2ad137c280
26 changed files with 189 additions and 123 deletions

24
Cargo.lock generated
View file

@ -1566,9 +1566,9 @@ dependencies = [
[[package]] [[package]]
name = "http-signature-normalization" name = "http-signature-normalization"
version = "0.5.2" version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee917294413cec0db93a8af6ecfa63730c1d2bb604bd1da69ba75b342fb23f21" checksum = "cb3a020c37b48d2258910fae9c9b4f8455651f56abfdde1ae68a9397b2765c31"
dependencies = [ dependencies = [
"chrono", "chrono",
"thiserror", "thiserror",
@ -1592,6 +1592,24 @@ dependencies = [
"thiserror", "thiserror",
] ]
[[package]]
name = "http-signature-normalization-reqwest"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7bc26a68f8963e26453c7fdea9e016e2e31a48ca018a9223f96afe2cca1a4bd1"
dependencies = [
"base64 0.12.3",
"bytes",
"chrono",
"futures",
"http",
"http-signature-normalization",
"reqwest",
"sha2",
"thiserror",
"tokio",
]
[[package]] [[package]]
name = "httparse" name = "httparse"
version = "1.3.4" version = "1.3.4"
@ -1866,6 +1884,7 @@ dependencies = [
"futures", "futures",
"http", "http",
"http-signature-normalization-actix", "http-signature-normalization-actix",
"http-signature-normalization-reqwest",
"itertools", "itertools",
"lazy_static", "lazy_static",
"lemmy_db", "lemmy_db",
@ -1896,6 +1915,7 @@ dependencies = [
"chrono", "chrono",
"diesel", "diesel",
"lazy_static", "lazy_static",
"lemmy_utils",
"log", "log",
"regex", "regex",
"serde 1.0.116", "serde 1.0.116",

View file

@ -1,4 +1,4 @@
jest.setTimeout(120000); jest.setTimeout(180000);
import { import {
alpha, alpha,
beta, beta,
@ -21,6 +21,7 @@ import {
registerUser, registerUser,
API, API,
delay, delay,
longDelay,
} from './shared'; } from './shared';
import { import {
Comment, Comment,
@ -35,7 +36,7 @@ beforeAll(async () => {
await followBeta(alpha); await followBeta(alpha);
await followBeta(gamma); await followBeta(gamma);
let search = await searchForBetaCommunity(alpha); let search = await searchForBetaCommunity(alpha);
await delay(10000); await longDelay();
postRes = await createPost( postRes = await createPost(
alpha, alpha,
search.communities.filter(c => c.local == false)[0].id search.communities.filter(c => c.local == false)[0].id
@ -66,7 +67,7 @@ test('Create a comment', async () => {
expect(commentRes.comment.community_local).toBe(false); expect(commentRes.comment.community_local).toBe(false);
expect(commentRes.comment.creator_local).toBe(true); expect(commentRes.comment.creator_local).toBe(true);
expect(commentRes.comment.score).toBe(1); expect(commentRes.comment.score).toBe(1);
await delay(); await longDelay();
// Make sure that comment is liked on beta // Make sure that comment is liked on beta
let searchBeta = await searchComment(beta, commentRes.comment); let searchBeta = await searchComment(beta, commentRes.comment);
@ -147,7 +148,7 @@ test('Remove a comment from admin and community on the same instance', async ()
// The beta admin removes it (the community lives on beta) // The beta admin removes it (the community lives on beta)
let removeCommentRes = await removeComment(beta, true, betaCommentId); let removeCommentRes = await removeComment(beta, true, betaCommentId);
expect(removeCommentRes.comment.removed).toBe(true); expect(removeCommentRes.comment.removed).toBe(true);
await delay(); await longDelay();
// Make sure that comment is removed on alpha (it gets pushed since an admin from beta removed it) // Make sure that comment is removed on alpha (it gets pushed since an admin from beta removed it)
let refetchedPost = await getPost(alpha, postRes.post.id); let refetchedPost = await getPost(alpha, postRes.post.id);
@ -155,7 +156,7 @@ test('Remove a comment from admin and community on the same instance', async ()
let unremoveCommentRes = await removeComment(beta, false, betaCommentId); let unremoveCommentRes = await removeComment(beta, false, betaCommentId);
expect(unremoveCommentRes.comment.removed).toBe(false); expect(unremoveCommentRes.comment.removed).toBe(false);
await delay(); await longDelay();
// Make sure that comment is unremoved on beta // Make sure that comment is unremoved on beta
let refetchedPost2 = await getPost(alpha, postRes.post.id); let refetchedPost2 = await getPost(alpha, postRes.post.id);
@ -210,7 +211,7 @@ test('Unlike a comment', async () => {
test('Federated comment like', async () => { test('Federated comment like', async () => {
let commentRes = await createComment(alpha, postRes.post.id); let commentRes = await createComment(alpha, postRes.post.id);
await delay(); await longDelay();
// Find the comment on beta // Find the comment on beta
let searchBeta = await searchComment(beta, commentRes.comment); let searchBeta = await searchComment(beta, commentRes.comment);
@ -218,7 +219,7 @@ test('Federated comment like', async () => {
let like = await likeComment(beta, 1, betaComment); let like = await likeComment(beta, 1, betaComment);
expect(like.comment.score).toBe(2); expect(like.comment.score).toBe(2);
await delay(); await longDelay();
// Get the post from alpha, check the likes // Get the post from alpha, check the likes
let post = await getPost(alpha, postRes.post.id); let post = await getPost(alpha, postRes.post.id);
@ -241,7 +242,7 @@ test('Reply to a comment', async () => {
expect(replyRes.comment.creator_local).toBe(true); expect(replyRes.comment.creator_local).toBe(true);
expect(replyRes.comment.parent_id).toBe(betaComment.id); expect(replyRes.comment.parent_id).toBe(betaComment.id);
expect(replyRes.comment.score).toBe(1); expect(replyRes.comment.score).toBe(1);
await delay(); await longDelay();
// Make sure that comment is seen on alpha // Make sure that comment is seen on alpha
// TODO not sure why, but a searchComment back to alpha, for the ap_id of betas // TODO not sure why, but a searchComment back to alpha, for the ap_id of betas
@ -310,7 +311,7 @@ test('A and G subscribe to B (center) A posts, G mentions B, it gets announced t
expect(commentRes.comment.community_local).toBe(false); expect(commentRes.comment.community_local).toBe(false);
expect(commentRes.comment.creator_local).toBe(true); expect(commentRes.comment.creator_local).toBe(true);
expect(commentRes.comment.score).toBe(1); expect(commentRes.comment.score).toBe(1);
await delay(); await longDelay();
// Make sure alpha sees it // Make sure alpha sees it
let alphaPost2 = await getPost(alpha, alphaPost.post.id); let alphaPost2 = await getPost(alpha, alphaPost.post.id);
@ -319,6 +320,7 @@ test('A and G subscribe to B (center) A posts, G mentions B, it gets announced t
expect(alphaPost2.comments[0].creator_local).toBe(false); expect(alphaPost2.comments[0].creator_local).toBe(false);
expect(alphaPost2.comments[0].score).toBe(1); expect(alphaPost2.comments[0].score).toBe(1);
assertCommentFederation(alphaPost2.comments[0], commentRes.comment); assertCommentFederation(alphaPost2.comments[0], commentRes.comment);
await delay();
// Make sure beta has mentions // Make sure beta has mentions
let mentionsRes = await getMentions(beta); let mentionsRes = await getMentions(beta);
@ -381,7 +383,7 @@ test('Fetch in_reply_tos: A is unsubbed from B, B makes a post, and some embedde
// Get the post from alpha // Get the post from alpha
let search = await searchPost(alpha, postRes.post); let search = await searchPost(alpha, postRes.post);
let alphaPostB = search.posts[0]; let alphaPostB = search.posts[0];
await delay(); await longDelay();
let alphaPost = await getPost(alpha, alphaPostB.id); let alphaPost = await getPost(alpha, alphaPostB.id);
expect(alphaPost.post.name).toBeDefined(); expect(alphaPost.post.name).toBeDefined();

View file

@ -7,6 +7,7 @@ import {
checkFollowedCommunities, checkFollowedCommunities,
unfollowRemotes, unfollowRemotes,
delay, delay,
longDelay,
} from './shared'; } from './shared';
beforeAll(async () => { beforeAll(async () => {
@ -24,10 +25,11 @@ test('Follow federated community', async () => {
// Make sure the follow response went through // Make sure the follow response went through
expect(follow.community.local).toBe(false); expect(follow.community.local).toBe(false);
expect(follow.community.name).toBe('main'); expect(follow.community.name).toBe('main');
await delay(); await longDelay();
// Check it from local // Check it from local
let followCheck = await checkFollowedCommunities(alpha); let followCheck = await checkFollowedCommunities(alpha);
await delay();
let remoteCommunityId = followCheck.communities.filter( let remoteCommunityId = followCheck.communities.filter(
c => c.community_local == false c => c.community_local == false
)[0].community_id; )[0].community_id;

View file

@ -20,6 +20,7 @@ import {
getPost, getPost,
unfollowRemotes, unfollowRemotes,
delay, delay,
longDelay,
} from './shared'; } from './shared';
import { import {
Post, Post,
@ -31,7 +32,7 @@ beforeAll(async () => {
await followBeta(gamma); await followBeta(gamma);
await followBeta(delta); await followBeta(delta);
await followBeta(epsilon); await followBeta(epsilon);
await delay(10000); await longDelay();
}); });
afterAll(async () => { afterAll(async () => {
@ -67,7 +68,7 @@ test('Create a post', async () => {
expect(postRes.post.community_local).toBe(false); expect(postRes.post.community_local).toBe(false);
expect(postRes.post.creator_local).toBe(true); expect(postRes.post.creator_local).toBe(true);
expect(postRes.post.score).toBe(1); expect(postRes.post.score).toBe(1);
await delay(); await longDelay();
// Make sure that post is liked on beta // Make sure that post is liked on beta
let searchBeta = await searchPost(beta, postRes.post); let searchBeta = await searchPost(beta, postRes.post);
@ -104,7 +105,7 @@ test('Unlike a post', async () => {
// Try to unlike it again, make sure it stays at 0 // Try to unlike it again, make sure it stays at 0
let unlike2 = await likePost(alpha, 0, postRes.post); let unlike2 = await likePost(alpha, 0, postRes.post);
expect(unlike2.post.score).toBe(0); expect(unlike2.post.score).toBe(0);
await delay(); await longDelay();
// Make sure that post is unliked on beta // Make sure that post is unliked on beta
let searchBeta = await searchPost(beta, postRes.post); let searchBeta = await searchPost(beta, postRes.post);
@ -284,31 +285,32 @@ test('Remove a post from admin and community on different instance', async () =>
test('Remove a post from admin and community on same instance', async () => { test('Remove a post from admin and community on same instance', async () => {
let search = await searchForBetaCommunity(alpha); let search = await searchForBetaCommunity(alpha);
let postRes = await createPost(alpha, search.communities[0].id); let postRes = await createPost(alpha, search.communities[0].id);
await delay(); await longDelay();
// Get the id for beta // Get the id for beta
let searchBeta = await searchPost(beta, postRes.post); let searchBeta = await searchPost(beta, postRes.post);
let betaPost = searchBeta.posts[0]; let betaPost = searchBeta.posts[0];
await delay(); await longDelay();
// The beta admin removes it (the community lives on beta) // The beta admin removes it (the community lives on beta)
let removePostRes = await removePost(beta, true, betaPost); let removePostRes = await removePost(beta, true, betaPost);
expect(removePostRes.post.removed).toBe(true); expect(removePostRes.post.removed).toBe(true);
await delay(); await longDelay();
// Make sure lemmy alpha sees post is removed // Make sure lemmy alpha sees post is removed
let alphaPost = await getPost(alpha, postRes.post.id); let alphaPost = await getPost(alpha, postRes.post.id);
expect(alphaPost.post.removed).toBe(true); expect(alphaPost.post.removed).toBe(true);
assertPostFederation(alphaPost.post, removePostRes.post); assertPostFederation(alphaPost.post, removePostRes.post);
await delay(); await longDelay();
// Undelete // Undelete
let undeletedPost = await removePost(beta, false, betaPost); let undeletedPost = await removePost(beta, false, betaPost);
expect(undeletedPost.post.removed).toBe(false); expect(undeletedPost.post.removed).toBe(false);
await delay(); await longDelay();
// Make sure lemmy alpha sees post is undeleted // Make sure lemmy alpha sees post is undeleted
let alphaPost2 = await getPost(alpha, postRes.post.id); let alphaPost2 = await getPost(alpha, postRes.post.id);
await delay();
expect(alphaPost2.post.removed).toBe(false); expect(alphaPost2.post.removed).toBe(false);
assertPostFederation(alphaPost2.post, undeletedPost.post); assertPostFederation(alphaPost2.post, undeletedPost.post);
}); });

View file

@ -10,6 +10,7 @@ import {
deletePrivateMessage, deletePrivateMessage,
unfollowRemotes, unfollowRemotes,
delay, delay,
longDelay,
} from './shared'; } from './shared';
let recipient_id: number; let recipient_id: number;
@ -17,7 +18,7 @@ let recipient_id: number;
beforeAll(async () => { beforeAll(async () => {
await setupLogins(); await setupLogins();
let follow = await followBeta(alpha); let follow = await followBeta(alpha);
await delay(10000); await longDelay();
recipient_id = follow.community.creator_id; recipient_id = follow.community.creator_id;
}); });
@ -46,7 +47,7 @@ test('Update a private message', async () => {
let pmRes = await createPrivateMessage(alpha, recipient_id); let pmRes = await createPrivateMessage(alpha, recipient_id);
let pmUpdated = await updatePrivateMessage(alpha, pmRes.message.id); let pmUpdated = await updatePrivateMessage(alpha, pmRes.message.id);
expect(pmUpdated.message.content).toBe(updatedContent); expect(pmUpdated.message.content).toBe(updatedContent);
await delay(); await longDelay();
let betaPms = await listPrivateMessages(beta); let betaPms = await listPrivateMessages(beta);
expect(betaPms.messages[0].content).toBe(updatedContent); expect(betaPms.messages[0].content).toBe(updatedContent);
@ -74,7 +75,7 @@ test('Delete a private message', async () => {
pmRes.message.id pmRes.message.id
); );
expect(undeletedPmRes.message.deleted).toBe(false); expect(undeletedPmRes.message.deleted).toBe(false);
await delay(); await longDelay();
let betaPms3 = await listPrivateMessages(beta); let betaPms3 = await listPrivateMessages(beta);
expect(betaPms3.messages.length).toBe(betaPms1.messages.length); expect(betaPms3.messages.length).toBe(betaPms1.messages.length);

View file

@ -554,10 +554,15 @@ export async function followBeta(api: API): Promise<CommunityResponse> {
} }
} }
export const delay = (millis: number = 1500) => export function delay(millis: number = 500) {
new Promise((resolve, _reject) => { return new Promise((resolve, _reject) => {
setTimeout(_ => resolve(), millis); setTimeout(_ => resolve(), millis);
}); });
}
export function longDelay() {
return delay(10000);
}
export function wrapper(form: any): string { export function wrapper(form: any): string {
return JSON.stringify(form); return JSON.stringify(form);

View file

@ -31,6 +31,8 @@
bind: "0.0.0.0" bind: "0.0.0.0"
# port where lemmy should listen for incoming requests # port where lemmy should listen for incoming requests
port: 8536 port: 8536
# whether tls is required for activitypub. only disable this for debugging, never for producion.
tls_enabled: true
# json web token for authorization between server and client # json web token for authorization between server and client
jwt_secret: "changeme" jwt_secret: "changeme"
# address where pictrs is available # address where pictrs is available
@ -58,8 +60,6 @@
federation: { federation: {
# whether to enable activitypub federation. this feature is in alpha, do not enable in production. # whether to enable activitypub federation. this feature is in alpha, do not enable in production.
enabled: false enabled: false
# whether tls is required for activitypub. only disable this for debugging, never for producion.
tls_enabled: true
# comma separated list of instances with which federation is allowed # comma separated list of instances with which federation is allowed
allowed_instances: "" allowed_instances: ""
# comma separated list of instances which are blocked from federating # comma separated list of instances which are blocked from federating

View file

@ -43,7 +43,7 @@ services:
- LEMMY_DATABASE_URL=postgres://lemmy:password@postgres_alpha:5432/lemmy - LEMMY_DATABASE_URL=postgres://lemmy:password@postgres_alpha:5432/lemmy
- LEMMY_JWT_SECRET=changeme - LEMMY_JWT_SECRET=changeme
- LEMMY_FEDERATION__ENABLED=true - LEMMY_FEDERATION__ENABLED=true
- LEMMY_FEDERATION__TLS_ENABLED=false - LEMMY_TLS_ENABLED=false
- LEMMY_FEDERATION__ALLOWED_INSTANCES=lemmy-beta,lemmy-gamma,lemmy-delta,lemmy-epsilon - LEMMY_FEDERATION__ALLOWED_INSTANCES=lemmy-beta,lemmy-gamma,lemmy-delta,lemmy-epsilon
- LEMMY_PORT=8541 - LEMMY_PORT=8541
- LEMMY_SETUP__ADMIN_USERNAME=lemmy_alpha - LEMMY_SETUP__ADMIN_USERNAME=lemmy_alpha
@ -82,7 +82,7 @@ services:
- LEMMY_DATABASE_URL=postgres://lemmy:password@postgres_beta:5432/lemmy - LEMMY_DATABASE_URL=postgres://lemmy:password@postgres_beta:5432/lemmy
- LEMMY_JWT_SECRET=changeme - LEMMY_JWT_SECRET=changeme
- LEMMY_FEDERATION__ENABLED=true - LEMMY_FEDERATION__ENABLED=true
- LEMMY_FEDERATION__TLS_ENABLED=false - LEMMY_TLS_ENABLED=false
- LEMMY_FEDERATION__ALLOWED_INSTANCES=lemmy-alpha,lemmy-gamma,lemmy-delta,lemmy-epsilon - LEMMY_FEDERATION__ALLOWED_INSTANCES=lemmy-alpha,lemmy-gamma,lemmy-delta,lemmy-epsilon
- LEMMY_PORT=8551 - LEMMY_PORT=8551
- LEMMY_SETUP__ADMIN_USERNAME=lemmy_beta - LEMMY_SETUP__ADMIN_USERNAME=lemmy_beta
@ -121,7 +121,7 @@ services:
- LEMMY_DATABASE_URL=postgres://lemmy:password@postgres_gamma:5432/lemmy - LEMMY_DATABASE_URL=postgres://lemmy:password@postgres_gamma:5432/lemmy
- LEMMY_JWT_SECRET=changeme - LEMMY_JWT_SECRET=changeme
- LEMMY_FEDERATION__ENABLED=true - LEMMY_FEDERATION__ENABLED=true
- LEMMY_FEDERATION__TLS_ENABLED=false - LEMMY_TLS_ENABLED=false
- LEMMY_FEDERATION__ALLOWED_INSTANCES=lemmy-alpha,lemmy-beta,lemmy-delta,lemmy-epsilon - LEMMY_FEDERATION__ALLOWED_INSTANCES=lemmy-alpha,lemmy-beta,lemmy-delta,lemmy-epsilon
- LEMMY_PORT=8561 - LEMMY_PORT=8561
- LEMMY_SETUP__ADMIN_USERNAME=lemmy_gamma - LEMMY_SETUP__ADMIN_USERNAME=lemmy_gamma
@ -161,7 +161,7 @@ services:
- LEMMY_DATABASE_URL=postgres://lemmy:password@postgres_delta:5432/lemmy - LEMMY_DATABASE_URL=postgres://lemmy:password@postgres_delta:5432/lemmy
- LEMMY_JWT_SECRET=changeme - LEMMY_JWT_SECRET=changeme
- LEMMY_FEDERATION__ENABLED=true - LEMMY_FEDERATION__ENABLED=true
- LEMMY_FEDERATION__TLS_ENABLED=false - LEMMY_TLS_ENABLED=false
- LEMMY_FEDERATION__ALLOWED_INSTANCES=lemmy-beta - LEMMY_FEDERATION__ALLOWED_INSTANCES=lemmy-beta
- LEMMY_PORT=8571 - LEMMY_PORT=8571
- LEMMY_SETUP__ADMIN_USERNAME=lemmy_delta - LEMMY_SETUP__ADMIN_USERNAME=lemmy_delta
@ -201,7 +201,7 @@ services:
- LEMMY_DATABASE_URL=postgres://lemmy:password@postgres_epsilon:5432/lemmy - LEMMY_DATABASE_URL=postgres://lemmy:password@postgres_epsilon:5432/lemmy
- LEMMY_JWT_SECRET=changeme - LEMMY_JWT_SECRET=changeme
- LEMMY_FEDERATION__ENABLED=true - LEMMY_FEDERATION__ENABLED=true
- LEMMY_FEDERATION__TLS_ENABLED=false - LEMMY_TLS_ENABLED=false
- LEMMY_FEDERATION__BLOCKED_INSTANCES=lemmy-alpha - LEMMY_FEDERATION__BLOCKED_INSTANCES=lemmy-alpha
- LEMMY_PORT=8581 - LEMMY_PORT=8581
- LEMMY_SETUP__ADMIN_USERNAME=lemmy_epsilon - LEMMY_SETUP__ADMIN_USERNAME=lemmy_epsilon

View file

@ -8,7 +8,7 @@ services:
- LEMMY_DATABASE_URL=postgres://lemmy:password@postgres_alpha:5432/lemmy - LEMMY_DATABASE_URL=postgres://lemmy:password@postgres_alpha:5432/lemmy
- LEMMY_JWT_SECRET=changeme - LEMMY_JWT_SECRET=changeme
- LEMMY_FEDERATION__ENABLED=true - LEMMY_FEDERATION__ENABLED=true
- LEMMY_FEDERATION__TLS_ENABLED=false - LEMMY_TLS_ENABLED=false
- LEMMY_FEDERATION__ALLOWED_INSTANCES=lemmy-beta,lemmy-gamma,lemmy-delta,lemmy-epsilon - LEMMY_FEDERATION__ALLOWED_INSTANCES=lemmy-beta,lemmy-gamma,lemmy-delta,lemmy-epsilon
- LEMMY_PORT=8541 - LEMMY_PORT=8541
- LEMMY_SETUP__ADMIN_USERNAME=lemmy_alpha - LEMMY_SETUP__ADMIN_USERNAME=lemmy_alpha
@ -39,7 +39,7 @@ services:
- LEMMY_DATABASE_URL=postgres://lemmy:password@postgres_beta:5432/lemmy - LEMMY_DATABASE_URL=postgres://lemmy:password@postgres_beta:5432/lemmy
- LEMMY_JWT_SECRET=changeme - LEMMY_JWT_SECRET=changeme
- LEMMY_FEDERATION__ENABLED=true - LEMMY_FEDERATION__ENABLED=true
- LEMMY_FEDERATION__TLS_ENABLED=false - LEMMY_TLS_ENABLED=false
- LEMMY_FEDERATION__ALLOWED_INSTANCES=lemmy-alpha,lemmy-gamma,lemmy-delta,lemmy-epsilon - LEMMY_FEDERATION__ALLOWED_INSTANCES=lemmy-alpha,lemmy-gamma,lemmy-delta,lemmy-epsilon
- LEMMY_PORT=8551 - LEMMY_PORT=8551
- LEMMY_SETUP__ADMIN_USERNAME=lemmy_beta - LEMMY_SETUP__ADMIN_USERNAME=lemmy_beta
@ -70,7 +70,7 @@ services:
- LEMMY_DATABASE_URL=postgres://lemmy:password@postgres_gamma:5432/lemmy - LEMMY_DATABASE_URL=postgres://lemmy:password@postgres_gamma:5432/lemmy
- LEMMY_JWT_SECRET=changeme - LEMMY_JWT_SECRET=changeme
- LEMMY_FEDERATION__ENABLED=true - LEMMY_FEDERATION__ENABLED=true
- LEMMY_FEDERATION__TLS_ENABLED=false - LEMMY_TLS_ENABLED=false
- LEMMY_FEDERATION__ALLOWED_INSTANCES=lemmy-alpha,lemmy-beta,lemmy-delta,lemmy-epsilon - LEMMY_FEDERATION__ALLOWED_INSTANCES=lemmy-alpha,lemmy-beta,lemmy-delta,lemmy-epsilon
- LEMMY_PORT=8561 - LEMMY_PORT=8561
- LEMMY_SETUP__ADMIN_USERNAME=lemmy_gamma - LEMMY_SETUP__ADMIN_USERNAME=lemmy_gamma
@ -102,7 +102,7 @@ services:
- LEMMY_DATABASE_URL=postgres://lemmy:password@postgres_delta:5432/lemmy - LEMMY_DATABASE_URL=postgres://lemmy:password@postgres_delta:5432/lemmy
- LEMMY_JWT_SECRET=changeme - LEMMY_JWT_SECRET=changeme
- LEMMY_FEDERATION__ENABLED=true - LEMMY_FEDERATION__ENABLED=true
- LEMMY_FEDERATION__TLS_ENABLED=false - LEMMY_TLS_ENABLED=false
- LEMMY_FEDERATION__ALLOWED_INSTANCES=lemmy-beta - LEMMY_FEDERATION__ALLOWED_INSTANCES=lemmy-beta
- LEMMY_PORT=8571 - LEMMY_PORT=8571
- LEMMY_SETUP__ADMIN_USERNAME=lemmy_delta - LEMMY_SETUP__ADMIN_USERNAME=lemmy_delta
@ -134,7 +134,7 @@ services:
- LEMMY_DATABASE_URL=postgres://lemmy:password@postgres_epsilon:5432/lemmy - LEMMY_DATABASE_URL=postgres://lemmy:password@postgres_epsilon:5432/lemmy
- LEMMY_JWT_SECRET=changeme - LEMMY_JWT_SECRET=changeme
- LEMMY_FEDERATION__ENABLED=true - LEMMY_FEDERATION__ENABLED=true
- LEMMY_FEDERATION__TLS_ENABLED=false - LEMMY_TLS_ENABLED=false
- LEMMY_FEDERATION__BLOCKED_INSTANCES=lemmy-alpha - LEMMY_FEDERATION__BLOCKED_INSTANCES=lemmy-alpha
- LEMMY_PORT=8581 - LEMMY_PORT=8581
- LEMMY_SETUP__ADMIN_USERNAME=lemmy_epsilon - LEMMY_SETUP__ADMIN_USERNAME=lemmy_epsilon

View file

@ -906,7 +906,7 @@ impl Perform for PasswordReset {
// TODO no i18n support here. // TODO no i18n support here.
let user_email = &user.email.expect("email"); let user_email = &user.email.expect("email");
let subject = &format!("Password reset for {}", user.name); let subject = &format!("Password reset for {}", user.name);
let hostname = &format!("https://{}", Settings::get().hostname); //TODO add https for now. let hostname = &Settings::get().get_protocol_and_hostname();
let html = &format!("<h1>Password Reset Request for {}</h1><br><a href={}/password_change/{}>Click here to reset your password</a>", user.name, hostname, &token); let html = &format!("<h1>Password Reset Request for {}</h1><br><a href={}/password_change/{}>Click here to reset your password</a>", user.name, hostname, &token);
match send_email(subject, user_email, &user.name, html) { match send_email(subject, user_email, &user.name, html) {
Ok(_o) => _o, Ok(_o) => _o,
@ -970,8 +970,6 @@ impl Perform for CreatePrivateMessage {
let data: &CreatePrivateMessage = &self; let data: &CreatePrivateMessage = &self;
let user = get_user_from_jwt(&data.auth, context.pool()).await?; let user = get_user_from_jwt(&data.auth, context.pool()).await?;
let hostname = &format!("https://{}", Settings::get().hostname);
let content_slurs_removed = remove_slurs(&data.content.to_owned()); let content_slurs_removed = remove_slurs(&data.content.to_owned());
let private_message_form = PrivateMessageForm { let private_message_form = PrivateMessageForm {
@ -1027,7 +1025,9 @@ impl Perform for CreatePrivateMessage {
); );
let html = &format!( let html = &format!(
"<h1>Private Message</h1><br><div>{} - {}</div><br><a href={}/inbox>inbox</a>", "<h1>Private Message</h1><br><div>{} - {}</div><br><a href={}/inbox>inbox</a>",
user.name, &content_slurs_removed, hostname user.name,
&content_slurs_removed,
Settings::get().get_protocol_and_hostname()
); );
match send_email(subject, &email, &recipient_user.name, html) { match send_email(subject, &email, &recipient_user.name, html) {
Ok(_o) => _o, Ok(_o) => _o,

View file

@ -34,6 +34,7 @@ percent-encoding = "2.1"
openssl = "0.10" openssl = "0.10"
http = "0.2" http = "0.2"
http-signature-normalization-actix = { version = "0.4", default-features = false, features = ["sha-2"] } http-signature-normalization-actix = { version = "0.4", default-features = false, features = ["sha-2"] }
http-signature-normalization-reqwest = { version = "0.1.3", default-features = false, features = ["sha-2"] }
base64 = "0.12" base64 = "0.12"
tokio = "0.2" tokio = "0.2"
futures = "0.3" futures = "0.3"

View file

@ -4,7 +4,7 @@ use activitystreams::{
object::AsObject, object::AsObject,
}; };
use lemmy_db::{community::Community, user::User_}; use lemmy_db::{community::Community, user::User_};
use lemmy_utils::{apub::get_apub_protocol_string, settings::Settings, LemmyError}; use lemmy_utils::{settings::Settings, LemmyError};
use lemmy_websocket::LemmyContext; use lemmy_websocket::LemmyContext;
use serde::{export::fmt::Debug, Serialize}; use serde::{export::fmt::Debug, Serialize};
use url::{ParseError, Url}; use url::{ParseError, Url};
@ -40,9 +40,8 @@ where
T: ToString, T: ToString,
{ {
let id = format!( let id = format!(
"{}://{}/activities/{}/{}", "{}/activities/{}/{}",
get_apub_protocol_string(), Settings::get().get_protocol_and_hostname(),
Settings::get().hostname,
kind.to_string().to_lowercase(), kind.to_string().to_lowercase(),
Uuid::new_v4() Uuid::new_v4()
); );

View file

@ -1,10 +1,9 @@
use crate::{check_is_apub_id_valid, extensions::signatures::sign, ActorType}; use crate::{check_is_apub_id_valid, extensions::signatures::sign_and_send, ActorType};
use activitystreams::{ use activitystreams::{
base::{Extends, ExtendsExt}, base::{Extends, ExtendsExt},
object::AsObject, object::AsObject,
}; };
use anyhow::{anyhow, Context, Error}; use anyhow::{anyhow, Context, Error};
use awc::Client;
use background_jobs::{ use background_jobs::{
create_server, create_server,
memory_storage::Storage, memory_storage::Storage,
@ -16,8 +15,9 @@ use background_jobs::{
}; };
use lemmy_utils::{location_info, settings::Settings, LemmyError}; use lemmy_utils::{location_info, settings::Settings, LemmyError};
use log::warn; use log::warn;
use reqwest::Client;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::{future::Future, pin::Pin}; use std::{collections::BTreeMap, future::Future, pin::Pin};
use url::Url; use url::Url;
pub fn send_activity<T, Kind>( pub fn send_activity<T, Kind>(
@ -50,6 +50,7 @@ where
actor_id: actor.actor_id()?, actor_id: actor.actor_id()?,
private_key: actor.private_key().context(location_info!())?, private_key: actor.private_key().context(location_info!())?,
}; };
activity_sender.queue::<SendActivityTask>(message)?; activity_sender.queue::<SendActivityTask>(message)?;
Ok(()) Ok(())
@ -74,27 +75,19 @@ impl ActixJob for SendActivityTask {
fn run(self, state: Self::State) -> Self::Future { fn run(self, state: Self::State) -> Self::Future {
Box::pin(async move { Box::pin(async move {
for to_url in &self.to { for to_url in &self.to {
let request = state let mut headers = BTreeMap::<String, String>::new();
.client headers.insert("Content-Type".into(), "application/json".into());
.post(to_url.as_str()) let result = sign_and_send(
.header("Content-Type", "application/json"); &state.client,
headers,
let signed = sign( to_url,
request,
self.activity.clone(), self.activity.clone(),
&self.actor_id, &self.actor_id,
self.private_key.to_owned(), self.private_key.to_owned(),
) )
.await; .await;
let signed = match signed {
Ok(s) => s, if let Err(e) = result {
Err(e) => {
warn!("{}", e);
// dont return an error because retrying would probably not fix the signing
return Ok(());
}
};
if let Err(e) = signed.send().await {
warn!("{}", e); warn!("{}", e);
return Err(anyhow!( return Err(anyhow!(
"Failed to send activity {} to {}", "Failed to send activity {} to {}",
@ -103,7 +96,6 @@ impl ActixJob for SendActivityTask {
)); ));
} }
} }
Ok(()) Ok(())
}) })
} }

View file

@ -44,8 +44,8 @@ use lemmy_db::{
}; };
use lemmy_structs::blocking; use lemmy_structs::blocking;
use lemmy_utils::{ use lemmy_utils::{
apub::get_apub_protocol_string,
location_info, location_info,
settings::Settings,
utils::{check_slurs, check_slurs_opt, convert_datetime}, utils::{check_slurs, check_slurs_opt, convert_datetime},
LemmyError, LemmyError,
}; };
@ -299,7 +299,7 @@ impl ActorType for Community {
}; };
Ok(Url::parse(&format!( Ok(Url::parse(&format!(
"{}://{}{}/inbox", "{}://{}{}/inbox",
get_apub_protocol_string(), Settings::get().get_protocol_string(),
domain, domain,
port, port,
))?) ))?)

View file

@ -1,12 +1,11 @@
use crate::ActorType; use crate::ActorType;
use activitystreams::unparsed::UnparsedMutExt; use activitystreams::unparsed::UnparsedMutExt;
use activitystreams_ext::UnparsedExtension; use activitystreams_ext::UnparsedExtension;
use actix_web::{client::ClientRequest, HttpRequest}; use actix_web::HttpRequest;
use anyhow::{anyhow, Context}; use anyhow::{anyhow, Context};
use http_signature_normalization_actix::{ use http::{header::HeaderName, HeaderMap, HeaderValue};
digest::{DigestClient, SignExt}, use http_signature_normalization_actix::Config as ConfigActix;
Config, use http_signature_normalization_reqwest::prelude::{Config, SignExt};
};
use lemmy_utils::{location_info, LemmyError}; use lemmy_utils::{location_info, LemmyError};
use log::debug; use log::debug;
use openssl::{ use openssl::{
@ -14,24 +13,38 @@ use openssl::{
pkey::PKey, pkey::PKey,
sign::{Signer, Verifier}, sign::{Signer, Verifier},
}; };
use reqwest::{Client, Response};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use sha2::{Digest, Sha256}; use sha2::{Digest, Sha256};
use std::{collections::BTreeMap, str::FromStr};
use url::Url; use url::Url;
lazy_static! { lazy_static! {
static ref CONFIG2: ConfigActix = ConfigActix::new();
static ref HTTP_SIG_CONFIG: Config = Config::new(); static ref HTTP_SIG_CONFIG: Config = Config::new();
} }
/// Signs request headers with the given keypair. /// Signs request headers with the given keypair.
pub async fn sign( pub async fn sign_and_send(
request: ClientRequest, client: &Client,
headers: BTreeMap<String, String>,
url: &Url,
activity: String, activity: String,
actor_id: &Url, actor_id: &Url,
private_key: String, private_key: String,
) -> Result<DigestClient<String>, LemmyError> { ) -> Result<Response, LemmyError> {
let signing_key_id = format!("{}#main-key", actor_id); let signing_key_id = format!("{}#main-key", actor_id);
let digest_client = request let mut header_map = HeaderMap::new();
for h in headers {
header_map.insert(
HeaderName::from_str(h.0.as_str())?,
HeaderValue::from_str(h.1.as_str())?,
);
}
let response = client
.post(&url.to_string())
.headers(header_map)
.signature_with_digest( .signature_with_digest(
HTTP_SIG_CONFIG.clone(), HTTP_SIG_CONFIG.clone(),
signing_key_id, signing_key_id,
@ -47,12 +60,12 @@ pub async fn sign(
) )
.await?; .await?;
Ok(digest_client) Ok(response)
} }
pub fn verify(request: &HttpRequest, actor: &dyn ActorType) -> Result<(), LemmyError> { pub fn verify(request: &HttpRequest, actor: &dyn ActorType) -> Result<(), LemmyError> {
let public_key = actor.public_key().context(location_info!())?; let public_key = actor.public_key().context(location_info!())?;
let verified = HTTP_SIG_CONFIG let verified = CONFIG2
.begin_verify( .begin_verify(
request.method(), request.method(),
request.uri().path_and_query(), request.uri().path_and_query(),

View file

@ -27,9 +27,9 @@ use lemmy_db::{
}; };
use lemmy_structs::{blocking, site::SearchResponse}; use lemmy_structs::{blocking, site::SearchResponse};
use lemmy_utils::{ use lemmy_utils::{
apub::get_apub_protocol_string,
location_info, location_info,
request::{retry, RecvError}, request::{retry, RecvError},
settings::Settings,
LemmyError, LemmyError,
}; };
use lemmy_websocket::LemmyContext; use lemmy_websocket::LemmyContext;
@ -117,7 +117,12 @@ pub async fn search_by_apub_id(
return Err(anyhow!("Invalid search query: {}", query).into()); return Err(anyhow!("Invalid search query: {}", query).into());
}; };
let url = format!("{}://{}{}", get_apub_protocol_string(), instance, name); let url = format!(
"{}://{}{}",
Settings::get().get_protocol_string(),
instance,
name
);
Url::parse(&url)? Url::parse(&url)?
} else { } else {
Url::parse(&query)? Url::parse(&query)?

View file

@ -32,7 +32,6 @@ use chrono::NaiveDateTime;
use lemmy_db::{activity::do_insert_activity, user::User_, DbPool}; use lemmy_db::{activity::do_insert_activity, user::User_, DbPool};
use lemmy_structs::{blocking, WebFingerResponse}; use lemmy_structs::{blocking, WebFingerResponse};
use lemmy_utils::{ use lemmy_utils::{
apub::get_apub_protocol_string,
location_info, location_info,
request::{retry, RecvError}, request::{retry, RecvError},
settings::Settings, settings::Settings,
@ -97,7 +96,7 @@ fn check_is_apub_id_valid(apub_id: &Url) -> Result<(), LemmyError> {
}; };
} }
if apub_id.scheme() != get_apub_protocol_string() { if apub_id.scheme() != Settings::get().get_protocol_string() {
return Err(anyhow!("invalid apub id scheme: {:?}", apub_id.scheme()).into()); return Err(anyhow!("invalid apub id scheme: {:?}", apub_id.scheme()).into());
} }
@ -319,7 +318,7 @@ pub async fn fetch_webfinger_url(
) -> Result<Url, LemmyError> { ) -> Result<Url, LemmyError> {
let fetch_url = format!( let fetch_url = format!(
"{}://{}/.well-known/webfinger?resource=acct:{}@{}", "{}://{}/.well-known/webfinger?resource=acct:{}@{}",
get_apub_protocol_string(), Settings::get().get_protocol_string(),
mention.domain, mention.domain,
mention.name, mention.name,
mention.domain mention.domain

View file

@ -8,6 +8,7 @@ name = "lemmy_db"
path = "src/lib.rs" path = "src/lib.rs"
[dependencies] [dependencies]
lemmy_utils = { path = "../lemmy_utils" }
diesel = { version = "1.4", features = ["postgres","chrono","r2d2","64-column-tables","serde_json"] } diesel = { version = "1.4", features = ["postgres","chrono","r2d2","64-column-tables","serde_json"] }
chrono = { version = "0.4", features = ["serde"] } chrono = { version = "0.4", features = ["serde"] }
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }

View file

@ -6,6 +6,7 @@ use crate::{
}; };
use bcrypt::{hash, DEFAULT_COST}; use bcrypt::{hash, DEFAULT_COST};
use diesel::{dsl::*, result::Error, *}; use diesel::{dsl::*, result::Error, *};
use lemmy_utils::settings::Settings;
use serde::Serialize; use serde::Serialize;
#[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)] #[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)]
@ -151,7 +152,12 @@ impl User_ {
} }
pub fn get_profile_url(&self, hostname: &str) -> String { pub fn get_profile_url(&self, hostname: &str) -> String {
format!("https://{}/u/{}", hostname, self.name) format!(
"{}://{}/u/{}",
Settings::get().get_protocol_string(),
hostname,
self.name
)
} }
pub fn upsert(conn: &PgConnection, user_form: &UserForm) -> Result<User_, Error> { pub fn upsert(conn: &PgConnection, user_form: &UserForm) -> Result<User_, Error> {

View file

@ -77,7 +77,7 @@ fn do_send_local_notifs(
do_send_email: bool, do_send_email: bool,
) -> Vec<i32> { ) -> Vec<i32> {
let mut recipient_ids = Vec::new(); let mut recipient_ids = Vec::new();
let hostname = &format!("https://{}", Settings::get().hostname); let hostname = &Settings::get().get_protocol_and_hostname();
// Send the local mentions // Send the local mentions
for mention in mentions for mention in mentions

View file

@ -35,14 +35,6 @@ pub enum EndpointType {
PrivateMessage, PrivateMessage,
} }
pub fn get_apub_protocol_string() -> &'static str {
if Settings::get().federation.tls_enabled {
"https"
} else {
"http"
}
}
/// Generates the ActivityPub ID for a given object type and ID. /// Generates the ActivityPub ID for a given object type and ID.
pub fn make_apub_endpoint(endpoint_type: EndpointType, name: &str) -> Url { pub fn make_apub_endpoint(endpoint_type: EndpointType, name: &str) -> Url {
let point = match endpoint_type { let point = match endpoint_type {
@ -54,9 +46,8 @@ pub fn make_apub_endpoint(endpoint_type: EndpointType, name: &str) -> Url {
}; };
Url::parse(&format!( Url::parse(&format!(
"{}://{}/{}/{}", "{}/{}/{}",
get_apub_protocol_string(), Settings::get().get_protocol_and_hostname(),
Settings::get().hostname,
point, point,
name name
)) ))

View file

@ -1,4 +1,4 @@
use crate::{apub::get_apub_protocol_string, settings::Settings, LemmyError}; use crate::{settings::Settings, LemmyError};
use anyhow::anyhow; use anyhow::anyhow;
use log::error; use log::error;
use percent_encoding::{utf8_percent_encode, NON_ALPHANUMERIC}; use percent_encoding::{utf8_percent_encode, NON_ALPHANUMERIC};
@ -149,9 +149,8 @@ pub async fn fetch_iframely_and_pictrs_data(
// The full urls are necessary for federation // The full urls are necessary for federation
let pictrs_thumbnail = if let Some(pictrs_hash) = pictrs_hash { let pictrs_thumbnail = if let Some(pictrs_hash) = pictrs_hash {
Some(format!( Some(format!(
"{}://{}/pictrs/image/{}", "{}/pictrs/image/{}",
get_apub_protocol_string(), Settings::get().get_protocol_and_hostname(),
Settings::get().hostname,
pictrs_hash pictrs_hash
)) ))
} else { } else {

View file

@ -12,6 +12,7 @@ pub struct Settings {
pub hostname: String, pub hostname: String,
pub bind: IpAddr, pub bind: IpAddr,
pub port: u16, pub port: u16,
pub tls_enabled: bool,
pub jwt_secret: String, pub jwt_secret: String,
pub pictrs_url: String, pub pictrs_url: String,
pub rate_limit: RateLimitConfig, pub rate_limit: RateLimitConfig,
@ -68,7 +69,6 @@ pub struct DatabaseConfig {
#[derive(Debug, Deserialize, Clone)] #[derive(Debug, Deserialize, Clone)]
pub struct FederationConfig { pub struct FederationConfig {
pub enabled: bool, pub enabled: bool,
pub tls_enabled: bool,
pub allowed_instances: String, pub allowed_instances: String,
pub blocked_instances: String, pub blocked_instances: String,
} }
@ -157,6 +157,21 @@ impl Settings {
blocked_instances blocked_instances
} }
/// Returns either "http" or "https", depending on tls_enabled setting
pub fn get_protocol_string(&self) -> &'static str {
if self.tls_enabled {
"https"
} else {
"http"
}
}
/// Returns something like `http://localhost` or `https://dev.lemmy.ml`,
/// with the correct protocol and hostname.
pub fn get_protocol_and_hostname(&self) -> String {
format!("{}://{}", self.get_protocol_string(), self.hostname)
}
pub fn save_config_file(data: &str) -> Result<String, Error> { pub fn save_config_file(data: &str) -> Result<String, Error> {
fs::write(CONFIG_FILE, data)?; fs::write(CONFIG_FILE, data)?;

View file

@ -13,7 +13,7 @@ use lemmy_db::{
Crud, Crud,
}; };
use lemmy_utils::{ use lemmy_utils::{
apub::{generate_actor_keypair, get_apub_protocol_string, make_apub_endpoint, EndpointType}, apub::{generate_actor_keypair, make_apub_endpoint, EndpointType},
settings::Settings, settings::Settings,
LemmyError, LemmyError,
}; };
@ -206,9 +206,8 @@ fn post_thumbnail_url_updates_2020_07_27(conn: &PgConnection) -> Result<(), Lemm
info!("Running post_thumbnail_url_updates_2020_07_27"); info!("Running post_thumbnail_url_updates_2020_07_27");
let domain_prefix = format!( let domain_prefix = format!(
"{}://{}/pictrs/image/", "{}/pictrs/image/",
get_apub_protocol_string(), Settings::get().get_protocol_and_hostname(),
Settings::get().hostname
); );
let incorrect_thumbnails = post.filter(thumbnail_url.not_like("http%")); let incorrect_thumbnails = post.filter(thumbnail_url.not_like("http%"));

View file

@ -71,7 +71,7 @@ fn get_feed_all_data(conn: &PgConnection, sort_type: &SortType) -> Result<String
let mut channel_builder = ChannelBuilder::default(); let mut channel_builder = ChannelBuilder::default();
channel_builder channel_builder
.title(&format!("{} - All", site_view.name)) .title(&format!("{} - All", site_view.name))
.link(format!("https://{}", Settings::get().hostname)) .link(Settings::get().get_protocol_and_hostname())
.items(items); .items(items);
if let Some(site_desc) = site_view.description { if let Some(site_desc) = site_view.description {
@ -196,7 +196,7 @@ fn get_feed_front(
let mut channel_builder = ChannelBuilder::default(); let mut channel_builder = ChannelBuilder::default();
channel_builder channel_builder
.title(&format!("{} - Subscribed", site_view.name)) .title(&format!("{} - Subscribed", site_view.name))
.link(format!("https://{}", Settings::get().hostname)) .link(Settings::get().get_protocol_and_hostname())
.items(items); .items(items);
if let Some(site_desc) = site_view.description { if let Some(site_desc) = site_view.description {
@ -225,7 +225,10 @@ fn get_feed_inbox(conn: &PgConnection, jwt: String) -> Result<ChannelBuilder, Le
let mut channel_builder = ChannelBuilder::default(); let mut channel_builder = ChannelBuilder::default();
channel_builder channel_builder
.title(&format!("{} - Inbox", site_view.name)) .title(&format!("{} - Inbox", site_view.name))
.link(format!("https://{}/inbox", Settings::get().hostname)) .link(format!(
"{}/inbox",
Settings::get().get_protocol_and_hostname()
))
.items(items); .items(items);
if let Some(site_desc) = site_view.description { if let Some(site_desc) = site_view.description {
@ -243,8 +246,8 @@ fn create_reply_and_mention_items(
.iter() .iter()
.map(|r| { .map(|r| {
let reply_url = format!( let reply_url = format!(
"https://{}/post/{}/comment/{}", "{}/post/{}/comment/{}",
Settings::get().hostname, Settings::get().get_protocol_and_hostname(),
r.post_id, r.post_id,
r.id r.id
); );
@ -256,8 +259,8 @@ fn create_reply_and_mention_items(
.iter() .iter()
.map(|m| { .map(|m| {
let mention_url = format!( let mention_url = format!(
"https://{}/post/{}/comment/{}", "{}/post/{}/comment/{}",
Settings::get().hostname, Settings::get().get_protocol_and_hostname(),
m.post_id, m.post_id,
m.id m.id
); );
@ -277,7 +280,11 @@ fn build_item(
) -> Result<Item, LemmyError> { ) -> Result<Item, LemmyError> {
let mut i = ItemBuilder::default(); let mut i = ItemBuilder::default();
i.title(format!("Reply from {}", creator_name)); i.title(format!("Reply from {}", creator_name));
let author_url = format!("https://{}/u/{}", Settings::get().hostname, creator_name); let author_url = format!(
"{}/u/{}",
Settings::get().get_protocol_and_hostname(),
creator_name
);
i.author(format!( i.author(format!(
"/u/{} <a href=\"{}\">(link)</a>", "/u/{} <a href=\"{}\">(link)</a>",
creator_name, author_url creator_name, author_url
@ -306,7 +313,11 @@ fn create_post_items(posts: Vec<PostView>) -> Result<Vec<Item>, LemmyError> {
i.title(p.name); i.title(p.name);
let author_url = format!("https://{}/u/{}", Settings::get().hostname, p.creator_name); let author_url = format!(
"{}/u/{}",
Settings::get().get_protocol_and_hostname(),
p.creator_name
);
i.author(format!( i.author(format!(
"/u/{} <a href=\"{}\">(link)</a>", "/u/{} <a href=\"{}\">(link)</a>",
p.creator_name, author_url p.creator_name, author_url
@ -315,7 +326,11 @@ fn create_post_items(posts: Vec<PostView>) -> Result<Vec<Item>, LemmyError> {
let dt = DateTime::<Utc>::from_utc(p.published, Utc); let dt = DateTime::<Utc>::from_utc(p.published, Utc);
i.pub_date(dt.to_rfc2822()); i.pub_date(dt.to_rfc2822());
let post_url = format!("https://{}/post/{}", Settings::get().hostname, p.id); let post_url = format!(
"{}/post/{}",
Settings::get().get_protocol_and_hostname(),
p.id
);
i.comments(post_url.to_owned()); i.comments(post_url.to_owned());
let guid = GuidBuilder::default() let guid = GuidBuilder::default()
.permalink(true) .permalink(true)
@ -325,8 +340,8 @@ fn create_post_items(posts: Vec<PostView>) -> Result<Vec<Item>, LemmyError> {
i.guid(guid); i.guid(guid);
let community_url = format!( let community_url = format!(
"https://{}/c/{}", "{}/c/{}",
Settings::get().hostname, Settings::get().get_protocol_and_hostname(),
p.community_name p.community_name
); );

View file

@ -3,7 +3,7 @@ use anyhow::anyhow;
use lemmy_api::version; use lemmy_api::version;
use lemmy_db::site_view::SiteView; use lemmy_db::site_view::SiteView;
use lemmy_structs::blocking; use lemmy_structs::blocking;
use lemmy_utils::{apub::get_apub_protocol_string, settings::Settings, LemmyError}; use lemmy_utils::{settings::Settings, LemmyError};
use lemmy_websocket::LemmyContext; use lemmy_websocket::LemmyContext;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use url::Url; use url::Url;
@ -19,9 +19,8 @@ async fn node_info_well_known() -> Result<HttpResponse<Body>, LemmyError> {
links: NodeInfoWellKnownLinks { links: NodeInfoWellKnownLinks {
rel: Url::parse("http://nodeinfo.diaspora.software/ns/schema/2.0")?, rel: Url::parse("http://nodeinfo.diaspora.software/ns/schema/2.0")?,
href: Url::parse(&format!( href: Url::parse(&format!(
"{}://{}/nodeinfo/2.0.json", "{}/nodeinfo/2.0.json",
get_apub_protocol_string(), Settings::get().get_protocol_and_hostname()
Settings::get().hostname
))?, ))?,
}, },
}; };