mirror of https://github.com/LemmyNet/lemmy.git
Merge branch 'remove-hardcoded-https-dess' into main
commit
2ad137c280
|
@ -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",
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
});
|
});
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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"
|
||||||
|
@ -44,4 +45,4 @@ async-trait = "0.1"
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
background-jobs = " 0.8"
|
background-jobs = " 0.8"
|
||||||
reqwest = { version = "0.10", features = ["json"] }
|
reqwest = { version = "0.10", features = ["json"] }
|
||||||
|
|
|
@ -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()
|
||||||
);
|
);
|
||||||
|
|
|
@ -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(())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
))?)
|
))?)
|
||||||
|
|
|
@ -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(),
|
||||||
|
|
|
@ -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)?
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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"] }
|
||||||
|
|
|
@ -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> {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
))
|
))
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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)?;
|
||||||
|
|
||||||
|
|
|
@ -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%"));
|
||||||
|
|
|
@ -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
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
||||||
))?,
|
))?,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue