From 8bea13d651c2b53f633e475b4ae426c8ef6678c9 Mon Sep 17 00:00:00 2001 From: Dessalines Date: Fri, 25 Sep 2020 11:16:49 -0400 Subject: [PATCH 1/5] More overwriteable fields (#1155) * Adding more overwriteable fields for user. Fixes #1154 * Adding a note for bio. --- lemmy_api/src/user.rs | 35 ++++++++++++++--------------------- lemmy_apub/src/user.rs | 7 +++++-- lemmy_db/src/user.rs | 6 +++--- src/code_migrations.rs | 6 +++--- 4 files changed, 25 insertions(+), 29 deletions(-) diff --git a/lemmy_api/src/user.rs b/lemmy_api/src/user.rs index e2b73c53e..60704e3c1 100644 --- a/lemmy_api/src/user.rs +++ b/lemmy_api/src/user.rs @@ -335,31 +335,24 @@ impl Perform for SaveUserSettings { let user_id = user.id; let read_user = blocking(context.pool(), move |conn| User_::read(conn, user_id)).await??; - let bio = match &data.bio { - Some(bio) => { - if bio.chars().count() <= 300 { - Some(bio.to_owned()) - } else { - return Err(APIError::err("bio_length_overflow").into()); - } - } - None => read_user.bio, - }; - let avatar = diesel_option_overwrite(&data.avatar); let banner = diesel_option_overwrite(&data.banner); let email = diesel_option_overwrite(&data.email); + let bio = diesel_option_overwrite(&data.bio); + let preferred_username = diesel_option_overwrite(&data.preferred_username); + let matrix_user_id = diesel_option_overwrite(&data.matrix_user_id); - // The DB constraint should stop too many characters - let preferred_username = match &data.preferred_username { - Some(preferred_username) => { - if !is_valid_preferred_username(preferred_username.trim()) { - return Err(APIError::err("invalid_username").into()); - } - Some(preferred_username.trim().to_string()) + if let Some(Some(bio)) = &bio { + if bio.chars().count() > 300 { + return Err(APIError::err("bio_length_overflow").into()); } - None => read_user.preferred_username, - }; + } + + if let Some(Some(preferred_username)) = &preferred_username { + if !is_valid_preferred_username(preferred_username.trim()) { + return Err(APIError::err("invalid_username").into()); + } + } let password_encrypted = match &data.new_password { Some(new_password) => { @@ -397,7 +390,7 @@ impl Perform for SaveUserSettings { let user_form = UserForm { name: read_user.name, email, - matrix_user_id: data.matrix_user_id.to_owned(), + matrix_user_id, avatar, banner, password_encrypted, diff --git a/lemmy_apub/src/user.rs b/lemmy_apub/src/user.rs index 950f59a18..60af834ca 100644 --- a/lemmy_apub/src/user.rs +++ b/lemmy_apub/src/user.rs @@ -241,6 +241,9 @@ impl FromApub for UserForm { .context(location_info!())? .to_string(); let preferred_username = person.inner.preferred_username().map(|u| u.to_string()); + + // TODO a limit check (like the API does) might need to be done + // here when we federate to other platforms. Same for preferred_username let bio = person .inner .summary() @@ -253,7 +256,7 @@ impl FromApub for UserForm { Ok(UserForm { name, - preferred_username, + preferred_username: Some(preferred_username), password_encrypted: "".to_string(), admin: false, banned: false, @@ -271,7 +274,7 @@ impl FromApub for UserForm { send_notifications_to_email: false, matrix_user_id: None, actor_id: Some(check_actor_domain(person, expected_domain)?), - bio, + bio: Some(bio), local: false, private_key: None, public_key: Some(person.ext_one.public_key.to_owned().public_key_pem), diff --git a/lemmy_db/src/user.rs b/lemmy_db/src/user.rs index f2c20e947..60fdebbba 100644 --- a/lemmy_db/src/user.rs +++ b/lemmy_db/src/user.rs @@ -42,7 +42,7 @@ pub struct User_ { #[table_name = "user_"] pub struct UserForm { pub name: String, - pub preferred_username: Option, + pub preferred_username: Option>, pub password_encrypted: String, pub admin: bool, pub banned: bool, @@ -57,9 +57,9 @@ pub struct UserForm { pub lang: String, pub show_avatars: bool, pub send_notifications_to_email: bool, - pub matrix_user_id: Option, + pub matrix_user_id: Option>, pub actor_id: Option, - pub bio: Option, + pub bio: Option>, pub local: bool, pub private_key: Option, pub public_key: Option, diff --git a/src/code_migrations.rs b/src/code_migrations.rs index 6a69035da..bd3c74798 100644 --- a/src/code_migrations.rs +++ b/src/code_migrations.rs @@ -49,11 +49,11 @@ fn user_updates_2020_04_02(conn: &PgConnection) -> Result<(), LemmyError> { let form = UserForm { name: cuser.name.to_owned(), email: Some(cuser.email.to_owned()), - matrix_user_id: cuser.matrix_user_id.to_owned(), + matrix_user_id: Some(cuser.matrix_user_id.to_owned()), avatar: Some(cuser.avatar.to_owned()), banner: Some(cuser.banner.to_owned()), password_encrypted: cuser.password_encrypted.to_owned(), - preferred_username: cuser.preferred_username.to_owned(), + preferred_username: Some(cuser.preferred_username.to_owned()), published: Some(cuser.published), updated: None, admin: cuser.admin, @@ -66,7 +66,7 @@ fn user_updates_2020_04_02(conn: &PgConnection) -> Result<(), LemmyError> { show_avatars: cuser.show_avatars, send_notifications_to_email: cuser.send_notifications_to_email, actor_id: Some(make_apub_endpoint(EndpointType::User, &cuser.name).to_string()), - bio: cuser.bio.to_owned(), + bio: Some(cuser.bio.to_owned()), local: cuser.local, private_key: Some(keypair.private_key), public_key: Some(keypair.public_key), From ada82582efc474b9f81ebddac9a6e796ef44ddae Mon Sep 17 00:00:00 2001 From: Dessalines Date: Fri, 25 Sep 2020 16:26:19 -0500 Subject: [PATCH 2/5] Version v0.7.61 --- ansible/VERSION | 2 +- docker/prod/docker-compose.yml | 2 +- docker/travis/docker_push.sh | 4 ++-- lemmy_api/src/version.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ansible/VERSION b/ansible/VERSION index 90ff00a0d..ddf4dd99c 100644 --- a/ansible/VERSION +++ b/ansible/VERSION @@ -1 +1 @@ -v0.7.59 +v0.7.61 diff --git a/docker/prod/docker-compose.yml b/docker/prod/docker-compose.yml index 385fdc7c6..0b64dcd05 100644 --- a/docker/prod/docker-compose.yml +++ b/docker/prod/docker-compose.yml @@ -12,7 +12,7 @@ services: restart: always lemmy: - image: dessalines/lemmy:v0.7.59 + image: dessalines/lemmy:v0.7.61 ports: - "127.0.0.1:8536:8536" restart: always diff --git a/docker/travis/docker_push.sh b/docker/travis/docker_push.sh index 364ff90aa..0d53e6896 100644 --- a/docker/travis/docker_push.sh +++ b/docker/travis/docker_push.sh @@ -1,5 +1,5 @@ #!/bin/sh echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin docker tag dessalines/lemmy:travis \ - dessalines/lemmy:v0.7.59 -docker push dessalines/lemmy:v0.7.59 + dessalines/lemmy:v0.7.61 +docker push dessalines/lemmy:v0.7.61 diff --git a/lemmy_api/src/version.rs b/lemmy_api/src/version.rs index e1a081ad8..63213d54a 100644 --- a/lemmy_api/src/version.rs +++ b/lemmy_api/src/version.rs @@ -1 +1 @@ -pub const VERSION: &str = "v0.7.59"; +pub const VERSION: &str = "v0.7.61"; From 6c8a5723f8eeb0c8de1887c732e20ceaf81f7574 Mon Sep 17 00:00:00 2001 From: Dessalines Date: Thu, 1 Oct 2020 08:32:01 -0500 Subject: [PATCH 3/5] Trying to add some long delays. --- api_tests/src/comment.spec.ts | 22 ++++++++++++---------- api_tests/src/follow.spec.ts | 4 +++- api_tests/src/post.spec.ts | 18 ++++++++++-------- api_tests/src/private_message.spec.ts | 7 ++++--- api_tests/src/shared.ts | 9 +++++++-- 5 files changed, 36 insertions(+), 24 deletions(-) diff --git a/api_tests/src/comment.spec.ts b/api_tests/src/comment.spec.ts index 5017c0fa4..2ee3045c7 100644 --- a/api_tests/src/comment.spec.ts +++ b/api_tests/src/comment.spec.ts @@ -1,4 +1,4 @@ -jest.setTimeout(120000); +jest.setTimeout(180000); import { alpha, beta, @@ -21,6 +21,7 @@ import { registerUser, API, delay, + longDelay, } from './shared'; import { Comment, @@ -35,7 +36,7 @@ beforeAll(async () => { await followBeta(alpha); await followBeta(gamma); let search = await searchForBetaCommunity(alpha); - await delay(10000); + await longDelay(); postRes = await createPost( alpha, 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.creator_local).toBe(true); expect(commentRes.comment.score).toBe(1); - await delay(); + await longDelay(); // Make sure that comment is liked on beta 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) let removeCommentRes = await removeComment(beta, true, betaCommentId); 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) 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); expect(unremoveCommentRes.comment.removed).toBe(false); - await delay(); + await longDelay(); // Make sure that comment is unremoved on beta let refetchedPost2 = await getPost(alpha, postRes.post.id); @@ -210,7 +211,7 @@ test('Unlike a comment', async () => { test('Federated comment like', async () => { let commentRes = await createComment(alpha, postRes.post.id); - await delay(); + await longDelay(); // Find the comment on beta let searchBeta = await searchComment(beta, commentRes.comment); @@ -218,7 +219,7 @@ test('Federated comment like', async () => { let like = await likeComment(beta, 1, betaComment); expect(like.comment.score).toBe(2); - await delay(); + await longDelay(); // Get the post from alpha, check the likes 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.parent_id).toBe(betaComment.id); expect(replyRes.comment.score).toBe(1); - await delay(); + await longDelay(); // Make sure that comment is seen on alpha // 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.creator_local).toBe(true); expect(commentRes.comment.score).toBe(1); - await delay(); + await longDelay(); // Make sure alpha sees it 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].score).toBe(1); assertCommentFederation(alphaPost2.comments[0], commentRes.comment); + await delay(); // Make sure beta has mentions 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 let search = await searchPost(alpha, postRes.post); let alphaPostB = search.posts[0]; - await delay(); + await longDelay(); let alphaPost = await getPost(alpha, alphaPostB.id); expect(alphaPost.post.name).toBeDefined(); diff --git a/api_tests/src/follow.spec.ts b/api_tests/src/follow.spec.ts index e238dc636..e0389f871 100644 --- a/api_tests/src/follow.spec.ts +++ b/api_tests/src/follow.spec.ts @@ -7,6 +7,7 @@ import { checkFollowedCommunities, unfollowRemotes, delay, + longDelay, } from './shared'; beforeAll(async () => { @@ -24,10 +25,11 @@ test('Follow federated community', async () => { // Make sure the follow response went through expect(follow.community.local).toBe(false); expect(follow.community.name).toBe('main'); - await delay(); + await longDelay(); // Check it from local let followCheck = await checkFollowedCommunities(alpha); + await delay(); let remoteCommunityId = followCheck.communities.filter( c => c.community_local == false )[0].community_id; diff --git a/api_tests/src/post.spec.ts b/api_tests/src/post.spec.ts index e62b6cce7..b964e72eb 100644 --- a/api_tests/src/post.spec.ts +++ b/api_tests/src/post.spec.ts @@ -20,6 +20,7 @@ import { getPost, unfollowRemotes, delay, + longDelay, } from './shared'; import { Post, @@ -31,7 +32,7 @@ beforeAll(async () => { await followBeta(gamma); await followBeta(delta); await followBeta(epsilon); - await delay(10000); + await longDelay(); }); afterAll(async () => { @@ -67,7 +68,7 @@ test('Create a post', async () => { expect(postRes.post.community_local).toBe(false); expect(postRes.post.creator_local).toBe(true); expect(postRes.post.score).toBe(1); - await delay(); + await longDelay(); // Make sure that post is liked on beta 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 let unlike2 = await likePost(alpha, 0, postRes.post); expect(unlike2.post.score).toBe(0); - await delay(); + await longDelay(); // Make sure that post is unliked on beta 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 () => { let search = await searchForBetaCommunity(alpha); let postRes = await createPost(alpha, search.communities[0].id); - await delay(); + await longDelay(); // Get the id for beta let searchBeta = await searchPost(beta, postRes.post); let betaPost = searchBeta.posts[0]; - await delay(); + await longDelay(); // The beta admin removes it (the community lives on beta) let removePostRes = await removePost(beta, true, betaPost); expect(removePostRes.post.removed).toBe(true); - await delay(); + await longDelay(); // Make sure lemmy alpha sees post is removed let alphaPost = await getPost(alpha, postRes.post.id); expect(alphaPost.post.removed).toBe(true); assertPostFederation(alphaPost.post, removePostRes.post); - await delay(); + await longDelay(); // Undelete let undeletedPost = await removePost(beta, false, betaPost); expect(undeletedPost.post.removed).toBe(false); - await delay(); + await longDelay(); // Make sure lemmy alpha sees post is undeleted let alphaPost2 = await getPost(alpha, postRes.post.id); + await delay(); expect(alphaPost2.post.removed).toBe(false); assertPostFederation(alphaPost2.post, undeletedPost.post); }); diff --git a/api_tests/src/private_message.spec.ts b/api_tests/src/private_message.spec.ts index 75d1568ff..3ae714880 100644 --- a/api_tests/src/private_message.spec.ts +++ b/api_tests/src/private_message.spec.ts @@ -10,6 +10,7 @@ import { deletePrivateMessage, unfollowRemotes, delay, + longDelay, } from './shared'; let recipient_id: number; @@ -17,7 +18,7 @@ let recipient_id: number; beforeAll(async () => { await setupLogins(); let follow = await followBeta(alpha); - await delay(10000); + await longDelay(); recipient_id = follow.community.creator_id; }); @@ -46,7 +47,7 @@ test('Update a private message', async () => { let pmRes = await createPrivateMessage(alpha, recipient_id); let pmUpdated = await updatePrivateMessage(alpha, pmRes.message.id); expect(pmUpdated.message.content).toBe(updatedContent); - await delay(); + await longDelay(); let betaPms = await listPrivateMessages(beta); expect(betaPms.messages[0].content).toBe(updatedContent); @@ -74,7 +75,7 @@ test('Delete a private message', async () => { pmRes.message.id ); expect(undeletedPmRes.message.deleted).toBe(false); - await delay(); + await longDelay(); let betaPms3 = await listPrivateMessages(beta); expect(betaPms3.messages.length).toBe(betaPms1.messages.length); diff --git a/api_tests/src/shared.ts b/api_tests/src/shared.ts index bf75fa544..6aa5cfc4e 100644 --- a/api_tests/src/shared.ts +++ b/api_tests/src/shared.ts @@ -554,10 +554,15 @@ export async function followBeta(api: API): Promise { } } -export const delay = (millis: number = 1500) => - new Promise((resolve, _reject) => { +export function delay(millis: number = 500) { + return new Promise((resolve, _reject) => { setTimeout(_ => resolve(), millis); }); +} + +export function longDelay() { + return delay(10000); +} export function wrapper(form: any): string { return JSON.stringify(form); From 61f013e4cbab10de8361d9c81b5ee132263aa4dc Mon Sep 17 00:00:00 2001 From: Dessalines Date: Thu, 1 Oct 2020 09:16:56 -0500 Subject: [PATCH 4/5] Trying to fix travis build. --- docker/travis/docker-compose.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docker/travis/docker-compose.yml b/docker/travis/docker-compose.yml index e60f50333..565f7a000 100644 --- a/docker/travis/docker-compose.yml +++ b/docker/travis/docker-compose.yml @@ -8,7 +8,7 @@ services: - LEMMY_DATABASE_URL=postgres://lemmy:password@postgres_alpha:5432/lemmy - LEMMY_JWT_SECRET=changeme - 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_PORT=8541 - LEMMY_SETUP__ADMIN_USERNAME=lemmy_alpha @@ -39,7 +39,7 @@ services: - LEMMY_DATABASE_URL=postgres://lemmy:password@postgres_beta:5432/lemmy - LEMMY_JWT_SECRET=changeme - 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_PORT=8551 - LEMMY_SETUP__ADMIN_USERNAME=lemmy_beta @@ -70,7 +70,7 @@ services: - LEMMY_DATABASE_URL=postgres://lemmy:password@postgres_gamma:5432/lemmy - LEMMY_JWT_SECRET=changeme - 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_PORT=8561 - LEMMY_SETUP__ADMIN_USERNAME=lemmy_gamma @@ -102,7 +102,7 @@ services: - LEMMY_DATABASE_URL=postgres://lemmy:password@postgres_delta:5432/lemmy - LEMMY_JWT_SECRET=changeme - LEMMY_FEDERATION__ENABLED=true - - LEMMY_FEDERATION__TLS_ENABLED=false + - LEMMY_TLS_ENABLED=false - LEMMY_FEDERATION__ALLOWED_INSTANCES=lemmy-beta - LEMMY_PORT=8571 - LEMMY_SETUP__ADMIN_USERNAME=lemmy_delta @@ -134,7 +134,7 @@ services: - LEMMY_DATABASE_URL=postgres://lemmy:password@postgres_epsilon:5432/lemmy - LEMMY_JWT_SECRET=changeme - LEMMY_FEDERATION__ENABLED=true - - LEMMY_FEDERATION__TLS_ENABLED=false + - LEMMY_TLS_ENABLED=false - LEMMY_FEDERATION__BLOCKED_INSTANCES=lemmy-alpha - LEMMY_PORT=8581 - LEMMY_SETUP__ADMIN_USERNAME=lemmy_epsilon From 3a24adc57fa5e215947a4e14273c0fb11a390a11 Mon Sep 17 00:00:00 2001 From: Dessalines Date: Thu, 1 Oct 2020 12:54:20 -0500 Subject: [PATCH 5/5] Renaming to sign_and_send --- lemmy_apub/src/activity_queue.rs | 4 ++-- lemmy_apub/src/extensions/signatures.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lemmy_apub/src/activity_queue.rs b/lemmy_apub/src/activity_queue.rs index ece782c5d..ca0263320 100644 --- a/lemmy_apub/src/activity_queue.rs +++ b/lemmy_apub/src/activity_queue.rs @@ -1,4 +1,4 @@ -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::{ base::{Extends, ExtendsExt}, object::AsObject, @@ -77,7 +77,7 @@ impl ActixJob for SendActivityTask { for to_url in &self.to { let mut headers = BTreeMap::::new(); headers.insert("Content-Type".into(), "application/json".into()); - let result = sign( + let result = sign_and_send( &state.client, headers, to_url, diff --git a/lemmy_apub/src/extensions/signatures.rs b/lemmy_apub/src/extensions/signatures.rs index 452b60c66..cdcb707a6 100644 --- a/lemmy_apub/src/extensions/signatures.rs +++ b/lemmy_apub/src/extensions/signatures.rs @@ -25,7 +25,7 @@ lazy_static! { } /// Signs request headers with the given keypair. -pub async fn sign( +pub async fn sign_and_send( client: &Client, headers: BTreeMap, url: &Url,