From 4f1240487e5c02dbeb2ac255552aacce9a4d16c2 Mon Sep 17 00:00:00 2001 From: Dessalines Date: Tue, 12 Sep 2023 15:54:49 -0400 Subject: [PATCH 01/44] Fixing high CPU usage on federation worker recheck. Fixes #3958 --- crates/federate/src/worker.rs | 9 +++++---- .../down.sql | 2 ++ .../2023-09-12-194850_add_federation_worker_index/up.sql | 2 ++ 3 files changed, 9 insertions(+), 4 deletions(-) create mode 100644 migrations/2023-09-12-194850_add_federation_worker_index/down.sql create mode 100644 migrations/2023-09-12-194850_add_federation_worker_index/up.sql diff --git a/crates/federate/src/worker.rs b/crates/federate/src/worker.rs index a2bdf33c2..f1fbbb9c3 100644 --- a/crates/federate/src/worker.rs +++ b/crates/federate/src/worker.rs @@ -32,10 +32,10 @@ static WORK_FINISHED_RECHECK_DELAY: Duration = Duration::from_secs(1); static WORK_FINISHED_RECHECK_DELAY: Duration = Duration::from_secs(30); #[cfg(debug_assertions)] static FOLLOW_ADDITIONS_RECHECK_DELAY: Lazy = - Lazy::new(|| chrono::Duration::seconds(1)); + Lazy::new(|| chrono::Duration::minutes(1)); #[cfg(not(debug_assertions))] static FOLLOW_ADDITIONS_RECHECK_DELAY: Lazy = - Lazy::new(|| chrono::Duration::minutes(1)); + Lazy::new(|| chrono::Duration::minutes(5)); static FOLLOW_REMOVALS_RECHECK_DELAY: Lazy = Lazy::new(|| chrono::Duration::hours(1)); pub(crate) struct InstanceWorker { @@ -254,7 +254,8 @@ impl InstanceWorker { .send_inboxes .iter() .filter_map(std::option::Option::as_ref) - .filter_map(|u| (u.domain() == Some(&self.instance.domain)).then(|| u.inner().clone())), + .filter(|&u| (u.domain() == Some(&self.instance.domain))) + .map(|u| u.inner().clone()), ); Ok(inbox_urls) } @@ -295,7 +296,7 @@ impl InstanceWorker { .await? .into_iter() .fold(HashMap::new(), |mut map, (c, u)| { - map.entry(c).or_insert_with(HashSet::new).insert(u.into()); + map.entry(c).or_default().insert(u.into()); map }), new_last_fetch, diff --git a/migrations/2023-09-12-194850_add_federation_worker_index/down.sql b/migrations/2023-09-12-194850_add_federation_worker_index/down.sql new file mode 100644 index 000000000..a203e8087 --- /dev/null +++ b/migrations/2023-09-12-194850_add_federation_worker_index/down.sql @@ -0,0 +1,2 @@ +DROP INDEX idx_person_local_instance; + diff --git a/migrations/2023-09-12-194850_add_federation_worker_index/up.sql b/migrations/2023-09-12-194850_add_federation_worker_index/up.sql new file mode 100644 index 000000000..bbbab0b1f --- /dev/null +++ b/migrations/2023-09-12-194850_add_federation_worker_index/up.sql @@ -0,0 +1,2 @@ +CREATE INDEX idx_person_local_instance ON person (local DESC, instance_id); + From dca43dcfd9e376ee63e5416a4421477371d8d44c Mon Sep 17 00:00:00 2001 From: phiresky Date: Wed, 13 Sep 2023 10:54:10 +0000 Subject: [PATCH 02/44] fix a bug where after an hour community follows would be overwritten completely by an incremental upgrade --- crates/federate/src/worker.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/federate/src/worker.rs b/crates/federate/src/worker.rs index f1fbbb9c3..3bc6218bb 100644 --- a/crates/federate/src/worker.rs +++ b/crates/federate/src/worker.rs @@ -264,7 +264,7 @@ impl InstanceWorker { if (Utc::now() - self.last_full_communities_fetch) > *FOLLOW_REMOVALS_RECHECK_DELAY { // process removals every hour (self.followed_communities, self.last_full_communities_fetch) = self - .get_communities(pool, self.instance.id, self.last_full_communities_fetch) + .get_communities(pool, self.instance.id, Utc.timestamp_nanos(0)) .await?; self.last_incremental_communities_fetch = self.last_full_communities_fetch; } From b09ffa7197cb28c5de72ff0497103f14b20ec558 Mon Sep 17 00:00:00 2001 From: phiresky Date: Wed, 13 Sep 2023 11:20:09 +0000 Subject: [PATCH 03/44] instead of changing fed delays in debug mode, change them via env variable --- api_tests/run-federation-test.sh | 1 + crates/federate/src/worker.rs | 54 ++++++++++++++++++++++++-------- 2 files changed, 42 insertions(+), 13 deletions(-) diff --git a/api_tests/run-federation-test.sh b/api_tests/run-federation-test.sh index 3042fd344..aca57bc5f 100755 --- a/api_tests/run-federation-test.sh +++ b/api_tests/run-federation-test.sh @@ -2,6 +2,7 @@ set -e export LEMMY_DATABASE_URL=postgres://lemmy:password@localhost:5432 +export LEMMY_TEST_FAST_FEDERATION=1 # by default, the persistent federation queue has delays in the scale of 30s-5min pushd .. cargo build rm target/lemmy_server || true diff --git a/crates/federate/src/worker.rs b/crates/federate/src/worker.rs index 3bc6218bb..b52e4dbbf 100644 --- a/crates/federate/src/worker.rs +++ b/crates/federate/src/worker.rs @@ -22,20 +22,47 @@ use std::{ }; use tokio::{sync::mpsc::UnboundedSender, time::sleep}; use tokio_util::sync::CancellationToken; -/// save state to db every n sends if there's no failures (otherwise state is saved after every attempt) + +/// Decrease the delays of the federation queue. +/// Should only be used for federation tests since it significantly increases CPU and DB load of the federation queue. +static LEMMY_TEST_FAST_FEDERATION: Lazy = Lazy::new(|| { + std::env::var("LEMMY_TEST_FAST_FEDERATION") + .map(|s| !s.is_empty()) + .unwrap_or(false) +}); + +/// Check whether to save state to db every n sends if there's no failures (during failures state is saved after every attempt) +/// This determines the batch size for loop_batch. After a batch ends and SAVE_STATE_EVERY_TIME has passed, the federation_queue_state is updated in the DB. static CHECK_SAVE_STATE_EVERY_IT: i64 = 100; +/// Save state to db after this time has passed since the last state (so if the server crashes or is SIGKILLed, less than X seconds of activities are resent) static SAVE_STATE_EVERY_TIME: Duration = Duration::from_secs(60); -/// recheck for new federation work every n seconds -#[cfg(debug_assertions)] -static WORK_FINISHED_RECHECK_DELAY: Duration = Duration::from_secs(1); -#[cfg(not(debug_assertions))] -static WORK_FINISHED_RECHECK_DELAY: Duration = Duration::from_secs(30); -#[cfg(debug_assertions)] -static FOLLOW_ADDITIONS_RECHECK_DELAY: Lazy = - Lazy::new(|| chrono::Duration::minutes(1)); -#[cfg(not(debug_assertions))] -static FOLLOW_ADDITIONS_RECHECK_DELAY: Lazy = - Lazy::new(|| chrono::Duration::minutes(5)); +/// Recheck for new federation work every n seconds. +/// +/// When the queue is processed faster than new activities are added and it reaches the current time with an empty batch, +/// this is the delay the queue waits before it checks if new activities have been added to the sent_activities table. +/// This delay is only applied if no federated activity happens during sending activities of the last batch. +static WORK_FINISHED_RECHECK_DELAY: Lazy = Lazy::new(|| { + if *LEMMY_TEST_FAST_FEDERATION { + Duration::from_secs(1) + } else { + Duration::from_secs(30) + } +}); +/// interval with which new additions to community_followers are queried. +/// +/// The first time some user on an instance follows a specific remote community (or, more precisely: the first time a (followed_community_id, follower_inbox_url) tuple appears), +/// this delay limits the maximum time until the follow actually results in activities from that community id being sent to that inbox url. +/// This delay currently needs to not be too small because the DB load is currently fairly high because of the current structure of storing inboxes for every person, not having a separate list of shared_inboxes, and the architecture of having every instance queue be fully separate. +/// (see https://github.com/LemmyNet/lemmy/issues/3958) +static FOLLOW_ADDITIONS_RECHECK_DELAY: Lazy = Lazy::new(|| { + if *LEMMY_TEST_FAST_FEDERATION { + chrono::Duration::seconds(1) + } else { + chrono::Duration::minutes(2) + } +}); +/// The same as FOLLOW_ADDITIONS_RECHECK_DELAY, but triggering when the last person on an instance unfollows a specific remote community. +/// This is expected to happen pretty rarely and updating it in a timely manner is not too important. static FOLLOW_REMOVALS_RECHECK_DELAY: Lazy = Lazy::new(|| chrono::Duration::hours(1)); pub(crate) struct InstanceWorker { @@ -121,6 +148,7 @@ impl InstanceWorker { } Ok(()) } + /// send out a batch of CHECK_SAVE_STATE_EVERY_IT activities async fn loop_batch(&mut self, pool: &mut DbPool<'_>) -> Result<()> { let latest_id = get_latest_activity_id(pool).await?; if self.state.last_successful_id == -1 { @@ -134,7 +162,7 @@ impl InstanceWorker { if id == latest_id { // no more work to be done, wait before rechecking tokio::select! { - () = sleep(WORK_FINISHED_RECHECK_DELAY) => {}, + () = sleep(*WORK_FINISHED_RECHECK_DELAY) => {}, () = self.stop.cancelled() => {} } return Ok(()); From 7ee707e78be701eb1fad795a9ad41a08a7e28e51 Mon Sep 17 00:00:00 2001 From: phiresky Date: Wed, 13 Sep 2023 11:59:09 +0000 Subject: [PATCH 04/44] ci From c86173577d8c620e403c5002948b6432a08ee3d4 Mon Sep 17 00:00:00 2001 From: phiresky Date: Fri, 15 Sep 2023 15:51:31 +0000 Subject: [PATCH 05/44] fix export location --- api_tests/prepare-drone-federation-test.sh | 2 ++ api_tests/run-federation-test.sh | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/api_tests/prepare-drone-federation-test.sh b/api_tests/prepare-drone-federation-test.sh index ba6dd324b..ac204ed31 100755 --- a/api_tests/prepare-drone-federation-test.sh +++ b/api_tests/prepare-drone-federation-test.sh @@ -6,6 +6,8 @@ set -e export RUST_BACKTRACE=1 export RUST_LOG="warn,lemmy_server=debug,lemmy_federate=debug,lemmy_api=debug,lemmy_api_common=debug,lemmy_api_crud=debug,lemmy_apub=debug,lemmy_db_schema=debug,lemmy_db_views=debug,lemmy_db_views_actor=debug,lemmy_db_views_moderator=debug,lemmy_routes=debug,lemmy_utils=debug,lemmy_websocket=debug" +export LEMMY_TEST_FAST_FEDERATION=1 # by default, the persistent federation queue has delays in the scale of 30s-5min + for INSTANCE in lemmy_alpha lemmy_beta lemmy_gamma lemmy_delta lemmy_epsilon; do echo "DB URL: ${LEMMY_DATABASE_URL} INSTANCE: $INSTANCE" psql "${LEMMY_DATABASE_URL}/lemmy" -c "DROP DATABASE IF EXISTS $INSTANCE" diff --git a/api_tests/run-federation-test.sh b/api_tests/run-federation-test.sh index aca57bc5f..3042fd344 100755 --- a/api_tests/run-federation-test.sh +++ b/api_tests/run-federation-test.sh @@ -2,7 +2,6 @@ set -e export LEMMY_DATABASE_URL=postgres://lemmy:password@localhost:5432 -export LEMMY_TEST_FAST_FEDERATION=1 # by default, the persistent federation queue has delays in the scale of 30s-5min pushd .. cargo build rm target/lemmy_server || true From fc1f9c1ec33c3ccfcd04f7fa8a217954f24a79bf Mon Sep 17 00:00:00 2001 From: phiresky Date: Fri, 15 Sep 2023 22:06:55 +0000 Subject: [PATCH 06/44] ci From 08401fc85fd98b1512909a41462a2970f5afc6cb Mon Sep 17 00:00:00 2001 From: phiresky Date: Mon, 18 Sep 2023 14:25:35 +0000 Subject: [PATCH 07/44] Revert "remove synchronous federation" This reverts commit 2767ab4a6fed9aa8d197eda0c6a25a1d617d192d. --- api_tests/run-federation-test.sh | 1 + crates/api_common/src/send_activity.rs | 59 ++++++++++++++++++++++---- crates/api_crud/src/post/create.rs | 7 ++- crates/apub/src/activities/mod.rs | 14 +++++- crates/utils/src/lib.rs | 11 +++++ src/lib.rs | 9 +++- 6 files changed, 89 insertions(+), 12 deletions(-) diff --git a/api_tests/run-federation-test.sh b/api_tests/run-federation-test.sh index 3042fd344..ff74744a1 100755 --- a/api_tests/run-federation-test.sh +++ b/api_tests/run-federation-test.sh @@ -2,6 +2,7 @@ set -e export LEMMY_DATABASE_URL=postgres://lemmy:password@localhost:5432 +export LEMMY_SYNCHRONOUS_FEDERATION=1 # currently this is true in debug by default, but still. pushd .. cargo build rm target/lemmy_server || true diff --git a/crates/api_common/src/send_activity.rs b/crates/api_common/src/send_activity.rs index 84b2efb2d..897f102fe 100644 --- a/crates/api_common/src/send_activity.rs +++ b/crates/api_common/src/send_activity.rs @@ -17,14 +17,22 @@ use lemmy_db_schema::{ }, }; use lemmy_db_views::structs::PrivateMessageView; -use lemmy_utils::error::LemmyResult; -use once_cell::sync::OnceCell; +use lemmy_utils::{error::LemmyResult, SYNCHRONOUS_FEDERATION}; +use once_cell::sync::{Lazy, OnceCell}; +use tokio::{ + sync::{ + mpsc, + mpsc::{UnboundedReceiver, UnboundedSender, WeakUnboundedSender}, + Mutex, + }, + task::JoinHandle, +}; use url::Url; type MatchOutgoingActivitiesBoxed = Box fn(SendActivityData, &'a Data) -> BoxFuture<'a, LemmyResult<()>>>; -/// This static is necessary so that the api_common crates don't need to depend on lemmy_apub +/// This static is necessary so that activities can be sent out synchronously for tests and the api_common crates don't need to depend on lemmy_apub pub static MATCH_OUTGOING_ACTIVITIES: OnceCell = OnceCell::new(); #[derive(Debug)] @@ -54,16 +62,51 @@ pub enum SendActivityData { CreateReport(Url, Person, Community, String), } -pub struct ActivityChannel; +// TODO: instead of static, move this into LemmyContext. make sure that stopping the process with +// ctrl+c still works. +static ACTIVITY_CHANNEL: Lazy = Lazy::new(|| { + let (sender, receiver) = mpsc::unbounded_channel(); + let weak_sender = sender.downgrade(); + ActivityChannel { + weak_sender, + receiver: Mutex::new(receiver), + keepalive_sender: Mutex::new(Some(sender)), + } +}); + +pub struct ActivityChannel { + weak_sender: WeakUnboundedSender, + receiver: Mutex>, + keepalive_sender: Mutex>>, +} impl ActivityChannel { + pub async fn retrieve_activity() -> Option { + let mut lock = ACTIVITY_CHANNEL.receiver.lock().await; + lock.recv().await + } + pub async fn submit_activity( data: SendActivityData, context: &Data, ) -> LemmyResult<()> { - MATCH_OUTGOING_ACTIVITIES - .get() - .expect("retrieve function pointer")(data, context) - .await + if *SYNCHRONOUS_FEDERATION { + MATCH_OUTGOING_ACTIVITIES + .get() + .expect("retrieve function pointer")(data, context) + .await?; + } + // could do `ACTIVITY_CHANNEL.keepalive_sender.lock()` instead and get rid of weak_sender, + // not sure which way is more efficient + else if let Some(sender) = ACTIVITY_CHANNEL.weak_sender.upgrade() { + sender.send(data)?; + } + Ok(()) + } + + pub async fn close(outgoing_activities_task: JoinHandle>) -> LemmyResult<()> { + ACTIVITY_CHANNEL.keepalive_sender.lock().await.take(); + outgoing_activities_task.await??; + Ok(()) } } diff --git a/crates/api_crud/src/post/create.rs b/crates/api_crud/src/post/create.rs index 8cc6ffe62..d0b0f368c 100644 --- a/crates/api_crud/src/post/create.rs +++ b/crates/api_crud/src/post/create.rs @@ -37,6 +37,7 @@ use lemmy_utils::{ slurs::{check_slurs, check_slurs_opt}, validation::{check_url_scheme, clean_url_params, is_valid_body_field, is_valid_post_title}, }, + SYNCHRONOUS_FEDERATION, }; use tracing::Instrument; use url::Url; @@ -189,7 +190,11 @@ pub async fn create_post( Err(e) => Err(e).with_lemmy_type(LemmyErrorType::CouldntSendWebmention), } }; - spawn_try_task(task); + if *SYNCHRONOUS_FEDERATION { + task.await?; + } else { + spawn_try_task(task); + } }; build_post_response(&context, community_id, person_id, post_id).await diff --git a/crates/apub/src/activities/mod.rs b/crates/apub/src/activities/mod.rs index 29ec5bd30..53adc78df 100644 --- a/crates/apub/src/activities/mod.rs +++ b/crates/apub/src/activities/mod.rs @@ -45,6 +45,7 @@ use lemmy_db_views_actor::structs::{CommunityPersonBanView, CommunityView}; use lemmy_utils::{ error::{LemmyError, LemmyErrorExt, LemmyErrorType, LemmyResult}, spawn_try_task, + SYNCHRONOUS_FEDERATION, }; use serde::Serialize; use std::{ops::Deref, time::Duration}; @@ -220,6 +221,13 @@ where Ok(()) } +pub async fn handle_outgoing_activities(context: Data) -> LemmyResult<()> { + while let Some(data) = ActivityChannel::retrieve_activity().await { + match_outgoing_activities(data, &context.reset_request_count()).await? + } + Ok(()) +} + pub async fn match_outgoing_activities( data: SendActivityData, context: &Data, @@ -324,6 +332,10 @@ pub async fn match_outgoing_activities( } } }; - spawn_try_task(fed_task); + if *SYNCHRONOUS_FEDERATION { + fed_task.await?; + } else { + spawn_try_task(fed_task); + } Ok(()) } diff --git a/crates/utils/src/lib.rs b/crates/utils/src/lib.rs index c0553de31..1ef8a842c 100644 --- a/crates/utils/src/lib.rs +++ b/crates/utils/src/lib.rs @@ -18,6 +18,7 @@ pub mod version; use error::LemmyError; use futures::Future; +use once_cell::sync::Lazy; use std::time::Duration; use tracing::Instrument; @@ -37,6 +38,16 @@ macro_rules! location_info { }; } +/// if true, all federation should happen synchronously. useful for debugging and testing. +/// defaults to true on debug mode, false on releasemode +/// override to true by setting env LEMMY_SYNCHRONOUS_FEDERATION=1 +/// override to false by setting env LEMMY_SYNCHRONOUS_FEDERATION="" +pub static SYNCHRONOUS_FEDERATION: Lazy = Lazy::new(|| { + std::env::var("LEMMY_SYNCHRONOUS_FEDERATION") + .map(|s| !s.is_empty()) + .unwrap_or(cfg!(debug_assertions)) +}); + /// tokio::spawn, but accepts a future that may fail and also /// * logs errors /// * attaches the spawned task to the tracing span of the caller for better logging diff --git a/src/lib.rs b/src/lib.rs index e1c6d1fae..9ce1bfa00 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -28,14 +28,14 @@ use lemmy_api_common::{ context::LemmyContext, lemmy_db_views::structs::SiteView, request::build_user_agent, - send_activity::MATCH_OUTGOING_ACTIVITIES, + send_activity::{ActivityChannel, MATCH_OUTGOING_ACTIVITIES}, utils::{ check_private_instance_and_federation_enabled, local_site_rate_limit_to_rate_limit_config, }, }; use lemmy_apub::{ - activities::match_outgoing_activities, + activities::{handle_outgoing_activities, match_outgoing_activities}, VerifyUrlData, FEDERATION_HTTP_FETCH_LIMIT, }; @@ -203,6 +203,8 @@ pub async fn start_lemmy_server(args: CmdArgs) -> Result<(), LemmyError> { Box::pin(match_outgoing_activities(d, c)) })) .expect("set function pointer"); + let request_data = federation_config.to_request_data(); + let outgoing_activities_task = tokio::task::spawn(handle_outgoing_activities(request_data)); let server = if args.http_server { Some(create_http_server( @@ -245,6 +247,9 @@ pub async fn start_lemmy_server(args: CmdArgs) -> Result<(), LemmyError> { federate.cancel().await?; } + // Wait for outgoing apub sends to complete + ActivityChannel::close(outgoing_activities_task).await?; + Ok(()) } From 27141553b6d17925050bf1e16ac1a8c1ea1afeb5 Mon Sep 17 00:00:00 2001 From: phiresky Date: Mon, 18 Sep 2023 14:28:49 +0000 Subject: [PATCH 08/44] fix after revert --- api_tests/prepare-drone-federation-test.sh | 23 +++++++++++----------- api_tests/run-federation-test.sh | 1 - crates/apub/src/activities/mod.rs | 5 ++++- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/api_tests/prepare-drone-federation-test.sh b/api_tests/prepare-drone-federation-test.sh index ac204ed31..fc19ee8c8 100755 --- a/api_tests/prepare-drone-federation-test.sh +++ b/api_tests/prepare-drone-federation-test.sh @@ -6,7 +6,8 @@ set -e export RUST_BACKTRACE=1 export RUST_LOG="warn,lemmy_server=debug,lemmy_federate=debug,lemmy_api=debug,lemmy_api_common=debug,lemmy_api_crud=debug,lemmy_apub=debug,lemmy_db_schema=debug,lemmy_db_views=debug,lemmy_db_views_actor=debug,lemmy_db_views_moderator=debug,lemmy_routes=debug,lemmy_utils=debug,lemmy_websocket=debug" -export LEMMY_TEST_FAST_FEDERATION=1 # by default, the persistent federation queue has delays in the scale of 30s-5min +export LEMMY_SYNCHRONOUS_FEDERATION=1 # currently this is true in debug by default, but still. +export LEMMY_TEST_FAST_FEDERATION=1 # by default, the persistent federation queue has delays in the scale of 30s-5min for INSTANCE in lemmy_alpha lemmy_beta lemmy_gamma lemmy_delta lemmy_epsilon; do echo "DB URL: ${LEMMY_DATABASE_URL} INSTANCE: $INSTANCE" @@ -36,30 +37,30 @@ echo "$PWD" echo "start alpha" LEMMY_CONFIG_LOCATION=./docker/federation/lemmy_alpha.hjson \ -LEMMY_DATABASE_URL="${LEMMY_DATABASE_URL}/lemmy_alpha" \ -target/lemmy_server >/tmp/lemmy_alpha.out 2>&1 & + LEMMY_DATABASE_URL="${LEMMY_DATABASE_URL}/lemmy_alpha" \ + target/lemmy_server >/tmp/lemmy_alpha.out 2>&1 & echo "start beta" LEMMY_CONFIG_LOCATION=./docker/federation/lemmy_beta.hjson \ -LEMMY_DATABASE_URL="${LEMMY_DATABASE_URL}/lemmy_beta" \ -target/lemmy_server >/tmp/lemmy_beta.out 2>&1 & + LEMMY_DATABASE_URL="${LEMMY_DATABASE_URL}/lemmy_beta" \ + target/lemmy_server >/tmp/lemmy_beta.out 2>&1 & echo "start gamma" LEMMY_CONFIG_LOCATION=./docker/federation/lemmy_gamma.hjson \ -LEMMY_DATABASE_URL="${LEMMY_DATABASE_URL}/lemmy_gamma" \ -target/lemmy_server >/tmp/lemmy_gamma.out 2>&1 & + LEMMY_DATABASE_URL="${LEMMY_DATABASE_URL}/lemmy_gamma" \ + target/lemmy_server >/tmp/lemmy_gamma.out 2>&1 & echo "start delta" # An instance with only an allowlist for beta LEMMY_CONFIG_LOCATION=./docker/federation/lemmy_delta.hjson \ -LEMMY_DATABASE_URL="${LEMMY_DATABASE_URL}/lemmy_delta" \ -target/lemmy_server >/tmp/lemmy_delta.out 2>&1 & + LEMMY_DATABASE_URL="${LEMMY_DATABASE_URL}/lemmy_delta" \ + target/lemmy_server >/tmp/lemmy_delta.out 2>&1 & echo "start epsilon" # An instance who has a blocklist, with lemmy-alpha blocked LEMMY_CONFIG_LOCATION=./docker/federation/lemmy_epsilon.hjson \ -LEMMY_DATABASE_URL="${LEMMY_DATABASE_URL}/lemmy_epsilon" \ -target/lemmy_server >/tmp/lemmy_epsilon.out 2>&1 & + LEMMY_DATABASE_URL="${LEMMY_DATABASE_URL}/lemmy_epsilon" \ + target/lemmy_server >/tmp/lemmy_epsilon.out 2>&1 & echo "wait for all instances to start" while [[ "$(curl -s -o /dev/null -w '%{http_code}' 'lemmy-alpha:8541/api/v3/site')" != "200" ]]; do sleep 1; done diff --git a/api_tests/run-federation-test.sh b/api_tests/run-federation-test.sh index ff74744a1..3042fd344 100755 --- a/api_tests/run-federation-test.sh +++ b/api_tests/run-federation-test.sh @@ -2,7 +2,6 @@ set -e export LEMMY_DATABASE_URL=postgres://lemmy:password@localhost:5432 -export LEMMY_SYNCHRONOUS_FEDERATION=1 # currently this is true in debug by default, but still. pushd .. cargo build rm target/lemmy_server || true diff --git a/crates/apub/src/activities/mod.rs b/crates/apub/src/activities/mod.rs index 53adc78df..81bf806a6 100644 --- a/crates/apub/src/activities/mod.rs +++ b/crates/apub/src/activities/mod.rs @@ -33,7 +33,10 @@ use activitypub_federation::{ traits::{ActivityHandler, Actor}, }; use anyhow::anyhow; -use lemmy_api_common::{context::LemmyContext, send_activity::SendActivityData}; +use lemmy_api_common::{ + context::LemmyContext, + send_activity::{ActivityChannel, SendActivityData}, +}; use lemmy_db_schema::{ newtypes::CommunityId, source::{ From 48496599b2bd5a5394343ffa20054373976e907d Mon Sep 17 00:00:00 2001 From: phiresky Date: Mon, 18 Sep 2023 15:45:39 +0000 Subject: [PATCH 09/44] ci From 943b960c32a4b56c38c81f3112bfa12603c2d184 Mon Sep 17 00:00:00 2001 From: phiresky Date: Mon, 18 Sep 2023 16:29:08 +0000 Subject: [PATCH 10/44] fix waits after all follow actions --- api_tests/src/comment.spec.ts | 13 ++++--------- api_tests/src/community.spec.ts | 10 ---------- api_tests/src/post.spec.ts | 2 -- api_tests/src/shared.ts | 25 +++++++++++++++++-------- 4 files changed, 21 insertions(+), 29 deletions(-) diff --git a/api_tests/src/comment.spec.ts b/api_tests/src/comment.spec.ts index 000c0b0ab..9011fb8f1 100644 --- a/api_tests/src/comment.spec.ts +++ b/api_tests/src/comment.spec.ts @@ -42,10 +42,7 @@ let postOnAlphaRes: PostResponse; beforeAll(async () => { await setupLogins(); await unfollows(); - await followBeta(alpha); - await followBeta(gamma); - // wait for FOLLOW_ADDITIONS_RECHECK_DELAY - await delay(2000); + await Promise.all([followBeta(alpha), followBeta(gamma)]); let betaCommunity = (await resolveBetaCommunity(alpha)).community; if (betaCommunity) { postOnAlphaRes = await createPost(alpha, betaCommunity.community.id); @@ -560,8 +557,6 @@ test("Check that activity from another instance is sent to third instance", asyn () => resolveBetaCommunity(gamma), c => c.community?.subscribed === "Subscribed", ); - // FOLLOW_ADDITIONS_RECHECK_DELAY - await delay(2000); // Create a post on beta let betaPost = await createPost(beta, 2); @@ -607,8 +602,7 @@ test("Check that activity from another instance is sent to third instance", asyn commentRes.comment_view, ); - await unfollowRemotes(alpha); - await unfollowRemotes(gamma); + await Promise.all([unfollowRemotes(alpha), unfollowRemotes(gamma)]); }); test("Fetch in_reply_tos: A is unsubbed from B, B makes a post, and some embedded comments, A subs to B, B updates the lowest level comment, A fetches both the post and all the inreplyto comments for that post.", async () => { @@ -671,7 +665,8 @@ test("Fetch in_reply_tos: A is unsubbed from B, B makes a post, and some embedde () => getComments(alpha, alphaPostB!.post.id), c => c.comments[1]?.comment.content === - parentCommentRes.comment_view.comment.content, + parentCommentRes.comment_view.comment.content && + c.comments[0]?.comment.content === updateRes.comment_view.comment.content, ); expect(alphaPost.post_view.post.name).toBeDefined(); assertCommentFederation( diff --git a/api_tests/src/community.spec.ts b/api_tests/src/community.spec.ts index a2af84440..c078cd9b0 100644 --- a/api_tests/src/community.spec.ts +++ b/api_tests/src/community.spec.ts @@ -87,12 +87,6 @@ test("Delete community", async () => { // Make sure the follow response went through expect(follow.community_view.community.local).toBe(false); - await waitUntil( - () => resolveCommunity(alpha, searchShort), - g => g.community?.subscribed === "Subscribed", - ); - // wait FOLLOW_ADDITIONS_RECHECK_DELAY - await delay(2000); let deleteCommunityRes = await deleteCommunity( beta, true, @@ -145,10 +139,6 @@ test("Remove community", async () => { // Make sure the follow response went through expect(follow.community_view.community.local).toBe(false); - await waitUntil( - () => resolveCommunity(alpha, searchShort), - g => g.community?.subscribed === "Subscribed", - ); let removeCommunityRes = await removeCommunity( beta, true, diff --git a/api_tests/src/post.spec.ts b/api_tests/src/post.spec.ts index cd3eec71b..1696ef998 100644 --- a/api_tests/src/post.spec.ts +++ b/api_tests/src/post.spec.ts @@ -220,8 +220,6 @@ test("Lock a post", async () => { () => resolveBetaCommunity(alpha), c => c.community?.subscribed === "Subscribed", ); - // wait FOLLOW_ADDITIONS_RECHECK_DELAY (there's no API to wait for this currently) - await delay(2_000); let postRes = await createPost(alpha, betaCommunity.community.id); // wait for federation diff --git a/api_tests/src/shared.ts b/api_tests/src/shared.ts index d116d329f..7e6124025 100644 --- a/api_tests/src/shared.ts +++ b/api_tests/src/shared.ts @@ -447,7 +447,14 @@ export async function followCommunity( follow, auth: api.auth, }; - return api.client.followCommunity(form); + const res = await api.client.followCommunity(form); + await waitUntil( + () => resolveCommunity(api, res.community_view.community.actor_id), + g => g.community?.subscribed === (follow ? "Subscribed" : "NotSubscribed"), + ); + // wait FOLLOW_ADDITIONS_RECHECK_DELAY (there's no API to wait for this currently) + await delay(2000); + return res; } export async function likePost( @@ -745,9 +752,9 @@ export async function unfollowRemotes(api: API): Promise { let site = await getSite(api); let remoteFollowed = site.my_user?.follows.filter(c => c.community.local == false) ?? []; - for (let cu of remoteFollowed) { - await followCommunity(api, false, cu.community.id); - } + await Promise.all( + remoteFollowed.map(cu => followCommunity(api, false, cu.community.id)), + ); let siteRes = await getSite(api); return siteRes; } @@ -841,10 +848,12 @@ export function randomString(length: number): string { } export async function unfollows() { - await unfollowRemotes(alpha); - await unfollowRemotes(gamma); - await unfollowRemotes(delta); - await unfollowRemotes(epsilon); + await Promise.all([ + unfollowRemotes(alpha), + unfollowRemotes(gamma), + unfollowRemotes(delta), + unfollowRemotes(epsilon), + ]); } export function getCommentParentId(comment: Comment): number | undefined { From 9e886fba4a93139bdd10fd1b85d7288615f0455d Mon Sep 17 00:00:00 2001 From: phiresky Date: Mon, 18 Sep 2023 16:49:55 +0000 Subject: [PATCH 11/44] delay shorter --- api_tests/src/post.spec.ts | 12 +++++++++--- api_tests/src/shared.ts | 6 ++++-- crates/federate/src/util.rs | 26 +++++++++++++++++++++++++- crates/federate/src/worker.rs | 29 ++++++++--------------------- 4 files changed, 46 insertions(+), 27 deletions(-) diff --git a/api_tests/src/post.spec.ts b/api_tests/src/post.spec.ts index 1696ef998..b2d07c291 100644 --- a/api_tests/src/post.spec.ts +++ b/api_tests/src/post.spec.ts @@ -279,8 +279,9 @@ test("Delete a post", async () => { // Make sure lemmy beta sees post is deleted // This will be undefined because of the tombstone - await expect(resolvePost(beta, postRes.post_view.post)).rejects.toBe( - "couldnt_find_object", + await waitUntil( + () => resolvePost(beta, postRes.post_view.post).catch(e => e), + e => e === "couldnt_find_object", ); // Undelete @@ -288,7 +289,12 @@ test("Delete a post", async () => { expect(undeletedPost.post_view.post.deleted).toBe(false); // Make sure lemmy beta sees post is undeleted - let betaPost2 = (await resolvePost(beta, postRes.post_view.post)).post; + let betaPost2 = ( + await waitUntil( + () => resolvePost(beta, postRes.post_view.post).catch(e => e), + e => e !== "couldnt_find_object", + ) + ).post; if (!betaPost2) { throw "Missing beta post 2"; } diff --git a/api_tests/src/shared.ts b/api_tests/src/shared.ts index 7e6124025..6898221f3 100644 --- a/api_tests/src/shared.ts +++ b/api_tests/src/shared.ts @@ -872,13 +872,15 @@ export async function waitUntil( fetcher: () => Promise, checker: (t: T) => boolean, retries = 10, - delaySeconds = 2, + delaySeconds = [0.2, 0.5, 1, 2, 3], ) { let retry = 0; while (retry++ < retries) { const result = await fetcher(); if (checker(result)) return result; - await delay(delaySeconds * 1000); + await delay( + delaySeconds[Math.min(retry - 1, delaySeconds.length - 1)] * 1000, + ); } throw Error( `Failed "${fetcher}": "${checker}" did not return true after ${retries} retries (delayed ${delaySeconds}s each)`, diff --git a/crates/federate/src/util.rs b/crates/federate/src/util.rs index 4f260708d..f00ccadb3 100644 --- a/crates/federate/src/util.rs +++ b/crates/federate/src/util.rs @@ -31,6 +31,26 @@ use std::{ use tokio::{task::JoinHandle, time::sleep}; use tokio_util::sync::CancellationToken; +/// Decrease the delays of the federation queue. +/// Should only be used for federation tests since it significantly increases CPU and DB load of the federation queue. +pub(crate) static LEMMY_TEST_FAST_FEDERATION: Lazy = Lazy::new(|| { + std::env::var("LEMMY_TEST_FAST_FEDERATION") + .map(|s| !s.is_empty()) + .unwrap_or(false) +}); +/// Recheck for new federation work every n seconds. +/// +/// When the queue is processed faster than new activities are added and it reaches the current time with an empty batch, +/// this is the delay the queue waits before it checks if new activities have been added to the sent_activities table. +/// This delay is only applied if no federated activity happens during sending activities of the last batch. +pub(crate) static WORK_FINISHED_RECHECK_DELAY: Lazy = Lazy::new(|| { + if *LEMMY_TEST_FAST_FEDERATION { + Duration::from_millis(100) + } else { + Duration::from_secs(30) + } +}); + pub struct CancellableTask { f: Pin> + Send + 'static>>, ended: Arc>, @@ -162,7 +182,11 @@ pub(crate) async fn get_activity_cached( pub(crate) async fn get_latest_activity_id(pool: &mut DbPool<'_>) -> Result { static CACHE: Lazy> = Lazy::new(|| { Cache::builder() - .time_to_live(Duration::from_secs(1)) + .time_to_live(if *LEMMY_TEST_FAST_FEDERATION { + *WORK_FINISHED_RECHECK_DELAY + } else { + Duration::from_secs(1) + }) .build() }); CACHE diff --git a/crates/federate/src/worker.rs b/crates/federate/src/worker.rs index b52e4dbbf..b6e174c04 100644 --- a/crates/federate/src/worker.rs +++ b/crates/federate/src/worker.rs @@ -1,6 +1,13 @@ use crate::{ federation_queue_state::FederationQueueState, - util::{get_activity_cached, get_actor_cached, get_latest_activity_id, retry_sleep_duration}, + util::{ + get_activity_cached, + get_actor_cached, + get_latest_activity_id, + retry_sleep_duration, + LEMMY_TEST_FAST_FEDERATION, + WORK_FINISHED_RECHECK_DELAY, + }, }; use activitypub_federation::{activity_sending::SendActivityTask, config::Data}; use anyhow::{Context, Result}; @@ -23,31 +30,11 @@ use std::{ use tokio::{sync::mpsc::UnboundedSender, time::sleep}; use tokio_util::sync::CancellationToken; -/// Decrease the delays of the federation queue. -/// Should only be used for federation tests since it significantly increases CPU and DB load of the federation queue. -static LEMMY_TEST_FAST_FEDERATION: Lazy = Lazy::new(|| { - std::env::var("LEMMY_TEST_FAST_FEDERATION") - .map(|s| !s.is_empty()) - .unwrap_or(false) -}); - /// Check whether to save state to db every n sends if there's no failures (during failures state is saved after every attempt) /// This determines the batch size for loop_batch. After a batch ends and SAVE_STATE_EVERY_TIME has passed, the federation_queue_state is updated in the DB. static CHECK_SAVE_STATE_EVERY_IT: i64 = 100; /// Save state to db after this time has passed since the last state (so if the server crashes or is SIGKILLed, less than X seconds of activities are resent) static SAVE_STATE_EVERY_TIME: Duration = Duration::from_secs(60); -/// Recheck for new federation work every n seconds. -/// -/// When the queue is processed faster than new activities are added and it reaches the current time with an empty batch, -/// this is the delay the queue waits before it checks if new activities have been added to the sent_activities table. -/// This delay is only applied if no federated activity happens during sending activities of the last batch. -static WORK_FINISHED_RECHECK_DELAY: Lazy = Lazy::new(|| { - if *LEMMY_TEST_FAST_FEDERATION { - Duration::from_secs(1) - } else { - Duration::from_secs(30) - } -}); /// interval with which new additions to community_followers are queried. /// /// The first time some user on an instance follows a specific remote community (or, more precisely: the first time a (followed_community_id, follower_inbox_url) tuple appears), From 954b3f443d18bca428f01c2a24447b312851420d Mon Sep 17 00:00:00 2001 From: phiresky Date: Mon, 18 Sep 2023 17:04:46 +0000 Subject: [PATCH 12/44] fix wait --- api_tests/src/comment.spec.ts | 2 +- api_tests/src/post.spec.ts | 14 ++++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/api_tests/src/comment.spec.ts b/api_tests/src/comment.spec.ts index 9011fb8f1..2314205d1 100644 --- a/api_tests/src/comment.spec.ts +++ b/api_tests/src/comment.spec.ts @@ -511,7 +511,7 @@ test("A and G subscribe to B (center) A posts, G mentions B, it gets announced t // Make sure alpha sees it let alphaPostComments2 = await waitUntil( () => getComments(alpha, alphaPost.post_view.post.id), - e => !!e.comments[0], + e => e.comments[0]?.counts.score === 1, ); expect(alphaPostComments2.comments[0].comment.content).toBe(commentContent); expect(alphaPostComments2.comments[0].community.local).toBe(true); diff --git a/api_tests/src/post.spec.ts b/api_tests/src/post.spec.ts index b2d07c291..89dfaa35f 100644 --- a/api_tests/src/post.spec.ts +++ b/api_tests/src/post.spec.ts @@ -365,16 +365,22 @@ test("Remove a post from admin and community on same instance", async () => { expect(removePostRes.post_view.post.removed).toBe(true); // Make sure lemmy alpha sees post is removed - // let alphaPost = await getPost(alpha, postRes.post_view.post.id); - // expect(alphaPost.post_view.post.removed).toBe(true); // TODO this shouldn't be commented - // assertPostFederation(alphaPost.post_view, removePostRes.post_view); + let alphaPost = await waitUntil( + () => getPost(alpha, postRes.post_view.post.id), + p => p.post_view.post.removed, + ); + expect(alphaPost.post_view.post.removed).toBe(true); + assertPostFederation(alphaPost.post_view, removePostRes.post_view); // Undelete let undeletedPost = await removePost(beta, false, betaPost.post); expect(undeletedPost.post_view.post.removed).toBe(false); // Make sure lemmy alpha sees post is undeleted - let alphaPost2 = await getPost(alpha, postRes.post_view.post.id); + let alphaPost2 = await waitUntil( + () => getPost(alpha, postRes.post_view.post.id), + p => !p.post_view.post.removed, + ); expect(alphaPost2.post_view.post.removed).toBe(false); assertPostFederation(alphaPost2.post_view, undeletedPost.post_view); await unfollowRemotes(alpha); From 007f4f53198938907e4e64f6052a0e8a51391070 Mon Sep 17 00:00:00 2001 From: phiresky Date: Mon, 18 Sep 2023 17:30:02 +0000 Subject: [PATCH 13/44] wait on score --- api_tests/src/comment.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api_tests/src/comment.spec.ts b/api_tests/src/comment.spec.ts index 2314205d1..9685d654f 100644 --- a/api_tests/src/comment.spec.ts +++ b/api_tests/src/comment.spec.ts @@ -591,7 +591,7 @@ test("Check that activity from another instance is sent to third instance", asyn // Make sure alpha sees it let alphaPostComments2 = await waitUntil( () => getComments(alpha, alphaPost!.post.id), - e => !!e.comments[0], + e => e.comments[0]?.counts.score === 1, ); expect(alphaPostComments2.comments[0].comment.content).toBe(commentContent); expect(alphaPostComments2.comments[0].community.local).toBe(false); From d58e2e9db7205f0e035e66ffbd3db4ef444471a5 Mon Sep 17 00:00:00 2001 From: phiresky Date: Mon, 18 Sep 2023 18:09:18 +0000 Subject: [PATCH 14/44] minor test improvement --- api_tests/src/comment.spec.ts | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/api_tests/src/comment.spec.ts b/api_tests/src/comment.spec.ts index 9685d654f..214988198 100644 --- a/api_tests/src/comment.spec.ts +++ b/api_tests/src/comment.spec.ts @@ -36,14 +36,16 @@ import { delay, } from "./shared"; import { CommentView } from "lemmy-js-client/dist/types/CommentView"; +import { CommunityView } from "lemmy-js-client"; +let betaCommunity: CommunityView | undefined; let postOnAlphaRes: PostResponse; beforeAll(async () => { await setupLogins(); await unfollows(); await Promise.all([followBeta(alpha), followBeta(gamma)]); - let betaCommunity = (await resolveBetaCommunity(alpha)).community; + betaCommunity = (await resolveBetaCommunity(alpha)).community; if (betaCommunity) { postOnAlphaRes = await createPost(alpha, betaCommunity.community.id); } @@ -397,7 +399,7 @@ test("Reply to a comment from another instance, get notification", async () => { () => getUnreadCount(alpha), e => e.replies >= 1, ); - expect(alphaUnreadCountRes.replies).toBe(1); + expect(alphaUnreadCountRes.replies).toBeGreaterThanOrEqual(1); // check inbox of replies on alpha, fetching read/unread both let alphaRepliesRes = await getReplies(alpha); @@ -414,6 +416,8 @@ test("Reply to a comment from another instance, get notification", async () => { }); test("Mention beta from alpha", async () => { + if (!betaCommunity) throw Error("no community"); + const postOnAlphaRes = await createPost(alpha, betaCommunity.community.id); // Create a new branch, trunk-level comment branch, from alpha instance let commentRes = await createComment(alpha, postOnAlphaRes.post_view.post.id); // Create a reply comment to previous comment, this has a mention in body @@ -440,9 +444,9 @@ test("Mention beta from alpha", async () => { // Make sure that both new comments are seen on beta and have parent/child relationship let betaPostComments = await waitUntil( () => getComments(beta, betaPost!.post.id), - c => c.comments[1].counts.score === 1, + c => c.comments[1]?.counts.score === 1, ); - expect(betaPostComments.comments.length).toBeGreaterThanOrEqual(2); + expect(betaPostComments.comments.length).toEqual(2); // the trunk-branch root comment will be older than the mention reply comment, so index 1 let betaRootComment = betaPostComments.comments[1]; // the trunk-branch root comment should not have a parent @@ -700,16 +704,17 @@ test("Report a comment", async () => { throw "Missing alpha comment"; } - let alphaReport = ( - await reportComment(alpha, alphaComment.id, randomString(10)) - ).comment_report_view.comment_report; + const reason = randomString(10); + let alphaReport = (await reportComment(alpha, alphaComment.id, reason)) + .comment_report_view.comment_report; - let betaReport = ( - await waitUntil( - () => listCommentReports(beta), - e => !!e.comment_reports[0], - ) - ).comment_reports[0].comment_report; + let betaReport = (await waitUntil( + () => + listCommentReports(beta).then(r => + r.comment_reports.find(rep => rep.comment_report.reason === reason), + ), + e => !!e, + ))!.comment_report; expect(betaReport).toBeDefined(); expect(betaReport.resolved).toBe(false); expect(betaReport.original_comment_text).toBe( From 9868065089dd0ff7751ae73dc9f12a5409011e28 Mon Sep 17 00:00:00 2001 From: phiresky Date: Mon, 18 Sep 2023 18:23:55 +0000 Subject: [PATCH 15/44] minor test improvement --- api_tests/src/comment.spec.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/api_tests/src/comment.spec.ts b/api_tests/src/comment.spec.ts index 214988198..36bf5809e 100644 --- a/api_tests/src/comment.spec.ts +++ b/api_tests/src/comment.spec.ts @@ -374,16 +374,17 @@ test("Reply to a comment from another instance, get notification", async () => { expect(replyRes.comment_view.counts.score).toBe(1); // Make sure that reply comment is seen on alpha - // TODO not sure why, but a searchComment back to alpha, for the ap_id of betas - // comment, isn't working. - // let searchAlpha = await searchComment(alpha, replyRes.comment); + let commentSearch = await waitUntil( + () => resolveComment(alpha, replyRes.comment_view.comment), + c => c.comment?.counts.score === 1, + ); + let alphaComment = commentSearch.comment!; let postComments = await waitUntil( () => getComments(alpha, postOnAlphaRes.post_view.post.id), pc => pc.comments.length >= 2, ); // Note: this test fails when run twice and this count will differ expect(postComments.comments.length).toBeGreaterThanOrEqual(2); - let alphaComment = postComments.comments[0]; expect(alphaComment.comment.content).toBeDefined(); expect(getCommentParentId(alphaComment.comment)).toBe( From 2f0ad53b60e773c194716e8b122b53f7a22b2a65 Mon Sep 17 00:00:00 2001 From: phiresky Date: Mon, 18 Sep 2023 18:39:09 +0000 Subject: [PATCH 16/44] wait longer for fed init --- api_tests/src/shared.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api_tests/src/shared.ts b/api_tests/src/shared.ts index 6898221f3..9d2bd3e02 100644 --- a/api_tests/src/shared.ts +++ b/api_tests/src/shared.ts @@ -205,7 +205,7 @@ export async function setupLogins() { // otherwise the first few federated events may be missed // (because last_successful_id is set to current id when federation to an instance is first started) // only needed the first time so do in this try - await delay(6_000); + await delay(10_000); } catch (_) { console.log("Communities already exist"); } From 7dd857e00ba99bca8b8cf4ea9d961b859c26a10f Mon Sep 17 00:00:00 2001 From: phiresky Date: Mon, 18 Sep 2023 19:19:40 +0000 Subject: [PATCH 17/44] log result --- api_tests/src/shared.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/api_tests/src/shared.ts b/api_tests/src/shared.ts index 9d2bd3e02..df5d299c6 100644 --- a/api_tests/src/shared.ts +++ b/api_tests/src/shared.ts @@ -875,13 +875,15 @@ export async function waitUntil( delaySeconds = [0.2, 0.5, 1, 2, 3], ) { let retry = 0; + let result; while (retry++ < retries) { - const result = await fetcher(); + result = await fetcher(); if (checker(result)) return result; await delay( delaySeconds[Math.min(retry - 1, delaySeconds.length - 1)] * 1000, ); } + console.error("result", result); throw Error( `Failed "${fetcher}": "${checker}" did not return true after ${retries} retries (delayed ${delaySeconds}s each)`, ); From dff54d5e390e460767fe2bbbdd8dad66cb48fc83 Mon Sep 17 00:00:00 2001 From: phiresky Date: Mon, 18 Sep 2023 19:58:20 +0000 Subject: [PATCH 18/44] tweak tests more --- api_tests/src/comment.spec.ts | 25 +++++++++++++-------- api_tests/src/community.spec.ts | 2 +- api_tests/src/post.spec.ts | 39 +++++++++++++++++++-------------- api_tests/src/shared.ts | 3 ++- 4 files changed, 42 insertions(+), 27 deletions(-) diff --git a/api_tests/src/comment.spec.ts b/api_tests/src/comment.spec.ts index 36bf5809e..3c8578d80 100644 --- a/api_tests/src/comment.spec.ts +++ b/api_tests/src/comment.spec.ts @@ -342,6 +342,8 @@ test("Federated comment like", async () => { }); test("Reply to a comment from another instance, get notification", async () => { + await alpha.client.markAllAsRead({ auth: alpha.auth }); + let betaCommunity = (await resolveBetaCommunity(alpha)).community; if (!betaCommunity) { throw "Missing beta community"; @@ -404,16 +406,20 @@ test("Reply to a comment from another instance, get notification", async () => { // check inbox of replies on alpha, fetching read/unread both let alphaRepliesRes = await getReplies(alpha); - expect(alphaRepliesRes.replies.length).toBe(1); - expect(alphaRepliesRes.replies[0].comment.content).toBeDefined(); - expect(alphaRepliesRes.replies[0].community.local).toBe(false); - expect(alphaRepliesRes.replies[0].creator.local).toBe(false); - expect(alphaRepliesRes.replies[0].counts.score).toBe(1); + const alphaReply = alphaRepliesRes.replies.find( + r => r.comment.id === alphaComment.comment.id, + ); + expect(alphaReply).toBeDefined(); + if (!alphaReply) throw Error(); + expect(alphaReply.comment.content).toBeDefined(); + expect(alphaReply.community.local).toBe(false); + expect(alphaReply.creator.local).toBe(false); + expect(alphaReply.counts.score).toBe(1); // ToDo: interesting alphaRepliesRes.replies[0].comment_reply.id is 1, meaning? how did that come about? - expect(alphaRepliesRes.replies[0].comment.id).toBe(alphaComment.comment.id); + expect(alphaReply.comment.id).toBe(alphaComment.comment.id); // this is a new notification, getReplies fetch was for read/unread both, confirm it is unread. - expect(alphaRepliesRes.replies[0].comment_reply.read).toBe(false); - assertCommentFederation(alphaRepliesRes.replies[0], replyRes.comment_view); + expect(alphaReply.comment_reply.read).toBe(false); + assertCommentFederation(alphaReply, replyRes.comment_view); }); test("Mention beta from alpha", async () => { @@ -494,7 +500,8 @@ test("A and G subscribe to B (center) A posts, G mentions B, it gets announced t expect(alphaPost.post_view.community.local).toBe(true); // Make sure gamma sees it - let gammaPost = (await resolvePost(gamma, alphaPost.post_view.post)).post; + let gammaPost = (await resolvePost(gamma, alphaPost.post_view.post, false))! + .post; if (!gammaPost) { throw "Missing gamma post"; diff --git a/api_tests/src/community.spec.ts b/api_tests/src/community.spec.ts index c078cd9b0..a6ecd1ab8 100644 --- a/api_tests/src/community.spec.ts +++ b/api_tests/src/community.spec.ts @@ -237,7 +237,7 @@ test("Admin actions in remote community are not federated to origin", async () = expect(banRes.banned).toBe(true); // ban doesnt federate to community's origin instance alpha - let alphaPost = (await resolvePost(alpha, gammaPost.post)).post; + let alphaPost = (await resolvePost(alpha, gammaPost.post, false)).post; expect(alphaPost?.creator_banned_from_community).toBe(false); // and neither to gamma diff --git a/api_tests/src/post.spec.ts b/api_tests/src/post.spec.ts index 89dfaa35f..1edabdcc8 100644 --- a/api_tests/src/post.spec.ts +++ b/api_tests/src/post.spec.ts @@ -83,10 +83,10 @@ test("Create a post", async () => { // Make sure that post is liked on beta const res = await waitUntil( - () => resolvePost(beta, postRes.post_view.post), - res => res.post?.counts.score === 1, + () => resolvePost(beta, postRes.post_view.post).catch(e => null), + res => res?.post?.counts.score === 1, ); - let betaPost = res.post; + let betaPost = res?.post; expect(betaPost).toBeDefined(); expect(betaPost?.community.local).toBe(true); @@ -177,7 +177,7 @@ test("Sticky a post", async () => { } let postRes = await createPost(alpha, betaCommunity.community.id); - let betaPost1 = (await resolvePost(beta, postRes.post_view.post)).post; + let betaPost1 = (await resolvePost(beta, postRes.post_view.post, false)).post; if (!betaPost1) { throw "Missing beta post1"; } @@ -201,7 +201,8 @@ test("Sticky a post", async () => { expect(betaPost2?.post.featured_community).toBe(false); // Make sure that gamma cannot sticky the post on beta - let gammaPost = (await resolvePost(gamma, postRes.post_view.post)).post; + let gammaPost = (await resolvePost(gamma, postRes.post_view.post, false)) + .post; if (!gammaPost) { throw "Missing gamma post"; } @@ -320,7 +321,8 @@ test("Remove a post from admin and community on different instance", async () => } let postRes = await createPost(gamma, gammaCommunity.id); - let alphaPost = (await resolvePost(alpha, postRes.post_view.post)).post; + let alphaPost = (await resolvePost(alpha, postRes.post_view.post, false)) + .post; if (!alphaPost) { throw "Missing alpha post"; } @@ -329,7 +331,7 @@ test("Remove a post from admin and community on different instance", async () => expect(removedPost.post_view.post.name).toBe(postRes.post_view.post.name); // Make sure lemmy beta sees post is NOT removed - let betaPost = (await resolvePost(beta, postRes.post_view.post)).post; + let betaPost = (await resolvePost(beta, postRes.post_view.post, false)).post; if (!betaPost) { throw "Missing beta post"; } @@ -533,7 +535,7 @@ test("A and G subscribe to B (center) A posts, it gets announced to G", async () let postRes = await createPost(alpha, betaCommunity.community.id); expect(postRes.post_view.post).toBeDefined(); - let betaPost = (await resolvePost(gamma, postRes.post_view.post)).post; + let betaPost = (await resolvePost(gamma, postRes.post_view.post, false)).post; expect(betaPost?.post.name).toBeDefined(); }); @@ -546,7 +548,8 @@ test("Report a post", async () => { let postRes = await createPost(beta, betaCommunity.community.id); expect(postRes.post_view.post).toBeDefined(); - let alphaPost = (await resolvePost(alpha, postRes.post_view.post)).post; + let alphaPost = (await resolvePost(alpha, postRes.post_view.post, false)) + .post; if (!alphaPost) { throw "Missing alpha post"; } @@ -554,12 +557,16 @@ test("Report a post", async () => { await reportPost(alpha, alphaPost.post.id, randomString(10)) ).post_report_view.post_report; - let betaReport = ( - await waitUntil( - () => listPostReports(beta), - res => !!res.post_reports[0], - ) - ).post_reports[0].post_report; + let betaReport = (await waitUntil( + () => + listPostReports(beta).then(p => + p.post_reports.find( + r => + r.post_report.original_post_name === alphaReport.original_post_name, + ), + ), + res => !!res, + ))!.post_report; expect(betaReport).toBeDefined(); expect(betaReport.resolved).toBe(false); expect(betaReport.original_post_name).toBe(alphaReport.original_post_name); @@ -588,7 +595,7 @@ test("Sanitize HTML", async () => { "<script>alert('xss');</script> hello &"'", ); - let alphaPost = (await resolvePost(alpha, post.post_view.post)).post; + let alphaPost = (await resolvePost(alpha, post.post_view.post, false)).post; // second escaping over federation, avoid double escape of & expect(alphaPost?.post.body).toBe( "<script>alert('xss');</script> hello &"'", diff --git a/api_tests/src/shared.ts b/api_tests/src/shared.ts index df5d299c6..b3f9f637f 100644 --- a/api_tests/src/shared.ts +++ b/api_tests/src/shared.ts @@ -296,10 +296,11 @@ export async function lockPost( export async function resolvePost( api: API, post: Post, + localOnly = true, ): Promise { let form: ResolveObject = { q: post.ap_id, - auth: api.auth, + auth: localOnly ? null : api.auth, }; return api.client.resolveObject(form); } From afde8e757681d37309795bf4cccdc9500a40ffc9 Mon Sep 17 00:00:00 2001 From: phiresky Date: Mon, 18 Sep 2023 20:31:12 +0000 Subject: [PATCH 19/44] tweak more tests --- api_tests/src/comment.spec.ts | 5 ++++- api_tests/src/post.spec.ts | 1 - 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/api_tests/src/comment.spec.ts b/api_tests/src/comment.spec.ts index 3c8578d80..24822d1d1 100644 --- a/api_tests/src/comment.spec.ts +++ b/api_tests/src/comment.spec.ts @@ -468,7 +468,10 @@ test("Mention beta from alpha", async () => { expect(betaRootComment.counts.score).toBe(1); assertCommentFederation(betaRootComment, commentRes.comment_view); - let mentionsRes = await getMentions(beta); + let mentionsRes = await waitUntil( + () => getMentions(beta), + m => !!m.mentions[0], + ); expect(mentionsRes.mentions[0].comment.content).toBeDefined(); expect(mentionsRes.mentions[0].community.local).toBe(true); expect(mentionsRes.mentions[0].creator.local).toBe(false); diff --git a/api_tests/src/post.spec.ts b/api_tests/src/post.spec.ts index 1edabdcc8..228925d06 100644 --- a/api_tests/src/post.spec.ts +++ b/api_tests/src/post.spec.ts @@ -287,7 +287,6 @@ test("Delete a post", async () => { // Undelete let undeletedPost = await deletePost(alpha, false, postRes.post_view.post); - expect(undeletedPost.post_view.post.deleted).toBe(false); // Make sure lemmy beta sees post is undeleted let betaPost2 = ( From a19b1d2606fda7d733621e41176ad57095cbea19 Mon Sep 17 00:00:00 2001 From: phiresky Date: Mon, 18 Sep 2023 21:02:52 +0000 Subject: [PATCH 20/44] ci From 990445bf8465aee7f1bf77fcad5d53ee2a131ecb Mon Sep 17 00:00:00 2001 From: phiresky Date: Mon, 18 Sep 2023 21:08:17 +0000 Subject: [PATCH 21/44] tmp tail lemmy log --- .woodpecker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.woodpecker.yml b/.woodpecker.yml index 49fbe3db2..c180d8d58 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -204,7 +204,7 @@ steps: - bash api_tests/prepare-drone-federation-test.sh - cd api_tests/ - yarn - - yarn api-test + - tail -f /tmp/lemmy*.out & yarn api-test when: *slow_check_paths rebuild-cache: From 2e7d2d1956744acc3b0a444f1ebec848c9808adc Mon Sep 17 00:00:00 2001 From: phiresky Date: Wed, 20 Sep 2023 10:46:25 +0000 Subject: [PATCH 22/44] wait for post api test function, better announce activity id --- api_tests/src/post.spec.ts | 118 ++++++------------ api_tests/src/shared.ts | 13 ++ .../apub/src/activities/community/announce.rs | 13 +- crates/apub/src/activities/mod.rs | 17 ++- 4 files changed, 79 insertions(+), 82 deletions(-) diff --git a/api_tests/src/post.spec.ts b/api_tests/src/post.spec.ts index 228925d06..54faa1714 100644 --- a/api_tests/src/post.spec.ts +++ b/api_tests/src/post.spec.ts @@ -35,7 +35,7 @@ import { unfollows, resolveCommunity, waitUntil, - delay, + waitForPost, } from "./shared"; import { PostView } from "lemmy-js-client/dist/types/PostView"; import { CreatePost } from "lemmy-js-client/dist/types/CreatePost"; @@ -82,11 +82,11 @@ test("Create a post", async () => { expect(postRes.post_view.counts.score).toBe(1); // Make sure that post is liked on beta - const res = await waitUntil( - () => resolvePost(beta, postRes.post_view.post).catch(e => null), - res => res?.post?.counts.score === 1, + const betaPost = await waitForPost( + beta, + postRes.post_view.post, + res => res?.counts.score === 1, ); - let betaPost = res?.post; expect(betaPost).toBeDefined(); expect(betaPost?.community.local).toBe(true); @@ -122,12 +122,12 @@ test("Unlike a post", async () => { expect(unlike2.post_view.counts.score).toBe(0); // Make sure that post is unliked on beta - const betaPost = ( - await waitUntil( - () => resolvePost(beta, postRes.post_view.post), - b => b.post?.counts.score === 0, - ) - ).post; + const betaPost = await waitForPost( + beta, + postRes.post_view.post, + post => post.counts.score === 0, + ); + expect(betaPost).toBeDefined(); expect(betaPost?.community.local).toBe(true); expect(betaPost?.creator.local).toBe(false); @@ -140,26 +140,16 @@ test("Update a post", async () => { throw "Missing beta community"; } let postRes = await createPost(alpha, betaCommunity.community.id); - await waitUntil( - () => resolvePost(beta, postRes.post_view.post), - res => !!res.post, - ); + await waitForPost(beta, postRes.post_view.post); let updatedName = "A jest test federated post, updated"; let updatedPost = await editPost(alpha, postRes.post_view.post); - await waitUntil( - () => resolvePost(beta, postRes.post_view.post), - res => res.post?.post.name === updatedName, - ); expect(updatedPost.post_view.post.name).toBe(updatedName); expect(updatedPost.post_view.community.local).toBe(false); expect(updatedPost.post_view.creator.local).toBe(true); // Make sure that post is updated on beta - let betaPost = (await resolvePost(beta, postRes.post_view.post)).post; - if (!betaPost) { - throw "Missing beta post"; - } + let betaPost = await waitForPost(beta, updatedPost.post_view.post); expect(betaPost.community.local).toBe(true); expect(betaPost.creator.local).toBe(false); expect(betaPost.post.name).toBe(updatedName); @@ -223,26 +213,17 @@ test("Lock a post", async () => { ); let postRes = await createPost(alpha, betaCommunity.community.id); - // wait for federation - await waitUntil( - () => searchPostLocal(beta, postRes.post_view.post), - res => !!res.posts[0], - ); + let betaPost1 = await waitForPost(beta, postRes.post_view.post); // Lock the post - let betaPost1 = (await resolvePost(beta, postRes.post_view.post)).post; - if (!betaPost1) { - throw "Missing beta post1"; - } let lockedPostRes = await lockPost(beta, true, betaPost1.post); expect(lockedPostRes.post_view.post.locked).toBe(true); // Make sure that post is locked on alpha - let searchAlpha = await waitUntil( - () => searchPostLocal(alpha, postRes.post_view.post), - res => res.posts[0]?.post.locked, + let alphaPost1 = await waitForPost( + alpha, + postRes.post_view.post, + post => post.post.locked, ); - let alphaPost1 = searchAlpha.posts[0]; - expect(alphaPost1.post.locked).toBe(true); // Try to make a new comment there, on alpha await expect(createComment(alpha, alphaPost1.post.id)).rejects.toBe("locked"); @@ -252,11 +233,11 @@ test("Lock a post", async () => { expect(unlockedPost.post_view.post.locked).toBe(false); // Make sure that post is unlocked on alpha - let searchAlpha2 = await waitUntil( - () => searchPostLocal(alpha, postRes.post_view.post), - res => !res.posts[0]?.post.locked, + let alphaPost2 = await waitForPost( + alpha, + postRes.post_view.post, + post => !post.post.locked, ); - let alphaPost2 = searchAlpha2.posts[0]; expect(alphaPost2.community.local).toBe(false); expect(alphaPost2.creator.local).toBe(true); expect(alphaPost2.post.locked).toBe(false); @@ -280,21 +261,14 @@ test("Delete a post", async () => { // Make sure lemmy beta sees post is deleted // This will be undefined because of the tombstone - await waitUntil( - () => resolvePost(beta, postRes.post_view.post).catch(e => e), - e => e === "couldnt_find_object", - ); + await waitForPost(beta, postRes.post_view.post, p => !p); // Undelete let undeletedPost = await deletePost(alpha, false, postRes.post_view.post); // Make sure lemmy beta sees post is undeleted - let betaPost2 = ( - await waitUntil( - () => resolvePost(beta, postRes.post_view.post).catch(e => e), - e => e !== "couldnt_find_object", - ) - ).post; + let betaPost2 = await waitForPost(beta, postRes.post_view.post); + if (!betaPost2) { throw "Missing beta post 2"; } @@ -354,11 +328,7 @@ test("Remove a post from admin and community on same instance", async () => { let postRes = await createPost(alpha, betaCommunity.community.id); expect(postRes.post_view.post).toBeDefined(); // Get the id for beta - let searchBeta = await waitUntil( - () => searchPostLocal(beta, postRes.post_view.post), - res => !!res.posts[0], - ); - let betaPost = searchBeta.posts[0]; + let betaPost = await waitForPost(beta, postRes.post_view.post); expect(betaPost).toBeDefined(); // The beta admin removes it (the community lives on beta) @@ -366,24 +336,26 @@ test("Remove a post from admin and community on same instance", async () => { expect(removePostRes.post_view.post.removed).toBe(true); // Make sure lemmy alpha sees post is removed - let alphaPost = await waitUntil( - () => getPost(alpha, postRes.post_view.post.id), - p => p.post_view.post.removed, + let alphaPost = await waitForPost( + alpha, + postRes.post_view.post, + p => p.post.removed, ); - expect(alphaPost.post_view.post.removed).toBe(true); - assertPostFederation(alphaPost.post_view, removePostRes.post_view); + expect(alphaPost.post.removed).toBe(true); + assertPostFederation(alphaPost, removePostRes.post_view); // Undelete let undeletedPost = await removePost(beta, false, betaPost.post); expect(undeletedPost.post_view.post.removed).toBe(false); // Make sure lemmy alpha sees post is undeleted - let alphaPost2 = await waitUntil( - () => getPost(alpha, postRes.post_view.post.id), - p => !p.post_view.post.removed, + let alphaPost2 = await waitForPost( + alpha, + postRes.post_view.post, + p => !p.post.removed, ); - expect(alphaPost2.post_view.post.removed).toBe(false); - assertPostFederation(alphaPost2.post_view, undeletedPost.post_view); + expect(alphaPost2.post.removed).toBe(false); + assertPostFederation(alphaPost2, undeletedPost.post_view); await unfollowRemotes(alpha); }); @@ -424,11 +396,7 @@ test("Enforce site ban for federated user", async () => { // alpha makes post in beta community, it federates to beta instance let postRes1 = await createPost(alpha_user, betaCommunity.community.id); - let searchBeta1 = await waitUntil( - () => searchPostLocal(beta, postRes1.post_view.post), - res => !!res.posts[0], - ); - expect(searchBeta1.posts[0]).toBeDefined(); + let searchBeta1 = await waitForPost(beta, postRes1.post_view.post); // ban alpha from its instance let banAlpha = await banPersonFromSite( @@ -447,7 +415,7 @@ test("Enforce site ban for federated user", async () => { expect(alphaUserOnBeta1.person?.person.banned).toBe(true); // existing alpha post should be removed on beta - let searchBeta2 = await getPost(beta, searchBeta1.posts[0].post.id); + let searchBeta2 = await getPost(beta, searchBeta1.post.id); expect(searchBeta2.post_view.post.removed).toBe(true); // Unban alpha @@ -461,11 +429,7 @@ test("Enforce site ban for federated user", async () => { // alpha makes new post in beta community, it federates let postRes2 = await createPost(alpha_user, betaCommunity.community.id); - let searchBeta3 = await waitUntil( - () => searchPostLocal(beta, postRes2.post_view.post), - e => !!e.posts[0], - ); - expect(searchBeta3.posts[0]).toBeDefined(); + let searchBeta3 = await waitForPost(beta, postRes2.post_view.post); let alphaUserOnBeta2 = await resolvePerson(beta, alphaUserActorId); expect(alphaUserOnBeta2.person?.person.banned).toBe(false); diff --git a/api_tests/src/shared.ts b/api_tests/src/shared.ts index b3f9f637f..1166b5134 100644 --- a/api_tests/src/shared.ts +++ b/api_tests/src/shared.ts @@ -4,6 +4,7 @@ import { GetUnreadCount, GetUnreadCountResponse, LemmyHttp, + PostView, } from "lemmy-js-client"; import { CreatePost } from "lemmy-js-client/dist/types/CreatePost"; import { DeletePost } from "lemmy-js-client/dist/types/DeletePost"; @@ -318,6 +319,18 @@ export async function searchPostLocal( return api.client.search(form); } +/// wait for a post to appear locally without pulling it +export async function waitForPost( + api: API, + post: Post, + checker: (t: PostView) => boolean = p => !!p, +) { + return waitUntil( + () => searchPostLocal(api, post).then(p => p.posts[0] as PostView), + checker, + ); +} + export async function getPost( api: API, post_id: number, diff --git a/crates/apub/src/activities/community/announce.rs b/crates/apub/src/activities/community/announce.rs index 5939c023a..ab82eb1de 100644 --- a/crates/apub/src/activities/community/announce.rs +++ b/crates/apub/src/activities/community/announce.rs @@ -1,6 +1,7 @@ use crate::{ activities::{ generate_activity_id, + generate_announce_activity_id, send_lemmy_activity, verify_is_public, verify_person_in_community, @@ -75,16 +76,20 @@ impl AnnounceActivity { community: &ApubCommunity, context: &Data, ) -> Result { + let inner_kind = object + .other + .get("type") + .and_then(|e| e.as_str()) + .unwrap_or("other"); + let id = + generate_announce_activity_id(inner_kind, &context.settings().get_protocol_and_hostname())?; Ok(AnnounceActivity { actor: community.id().into(), to: vec![public()], object: IdOrNestedObject::NestedObject(object), cc: vec![community.followers_url.clone().into()], kind: AnnounceType::Announce, - id: generate_activity_id( - &AnnounceType::Announce, - &context.settings().get_protocol_and_hostname(), - )?, + id, }) } diff --git a/crates/apub/src/activities/mod.rs b/crates/apub/src/activities/mod.rs index 81bf806a6..2e26e0678 100644 --- a/crates/apub/src/activities/mod.rs +++ b/crates/apub/src/activities/mod.rs @@ -28,7 +28,7 @@ use crate::{ use activitypub_federation::{ config::Data, fetch::object_id::ObjectId, - kinds::public, + kinds::{activity::AnnounceType, public}, protocol::context::WithContext, traits::{ActivityHandler, Actor}, }; @@ -185,6 +185,21 @@ where Url::parse(&id) } +/// like generate_activity_id but also add the inner kind for easier debugging +fn generate_announce_activity_id( + inner_kind: &str, + protocol_and_hostname: &str, +) -> Result { + let id = format!( + "{}/activities/{}/{}/{}", + protocol_and_hostname, + AnnounceType::Announce.to_string().to_lowercase(), + inner_kind, + Uuid::new_v4() + ); + Url::parse(&id) +} + pub(crate) trait GetActorType { fn actor_type(&self) -> ActorType; } From ae3b8f4f76b35bb2450b4ab98a301e02628072cb Mon Sep 17 00:00:00 2001 From: phiresky Date: Wed, 20 Sep 2023 11:21:47 +0000 Subject: [PATCH 23/44] fix --- api_tests/src/post.spec.ts | 21 ++++++++++----------- api_tests/src/shared.ts | 6 +++--- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/api_tests/src/post.spec.ts b/api_tests/src/post.spec.ts index 54faa1714..3b0e24129 100644 --- a/api_tests/src/post.spec.ts +++ b/api_tests/src/post.spec.ts @@ -125,7 +125,7 @@ test("Unlike a post", async () => { const betaPost = await waitForPost( beta, postRes.post_view.post, - post => post.counts.score === 0, + post => post?.counts.score === 0, ); expect(betaPost).toBeDefined(); @@ -222,7 +222,7 @@ test("Lock a post", async () => { let alphaPost1 = await waitForPost( alpha, postRes.post_view.post, - post => post.post.locked, + post => !!post && post.post.locked, ); // Try to make a new comment there, on alpha @@ -236,7 +236,7 @@ test("Lock a post", async () => { let alphaPost2 = await waitForPost( alpha, postRes.post_view.post, - post => !post.post.locked, + post => !!post && !post.post.locked, ); expect(alphaPost2.community.local).toBe(false); expect(alphaPost2.creator.local).toBe(true); @@ -336,13 +336,12 @@ test("Remove a post from admin and community on same instance", async () => { expect(removePostRes.post_view.post.removed).toBe(true); // Make sure lemmy alpha sees post is removed - let alphaPost = await waitForPost( - alpha, - postRes.post_view.post, - p => p.post.removed, + let alphaPost = await waitUntil( + () => getPost(alpha, postRes.post_view.post.id), + p => p?.post_view.post.removed ?? false, ); - expect(alphaPost.post.removed).toBe(true); - assertPostFederation(alphaPost, removePostRes.post_view); + expect(alphaPost.post_view?.post.removed).toBe(true); + assertPostFederation(alphaPost.post_view, removePostRes.post_view); // Undelete let undeletedPost = await removePost(beta, false, betaPost.post); @@ -352,7 +351,7 @@ test("Remove a post from admin and community on same instance", async () => { let alphaPost2 = await waitForPost( alpha, postRes.post_view.post, - p => !p.post.removed, + p => !!p && !p.post.removed, ); expect(alphaPost2.post.removed).toBe(false); assertPostFederation(alphaPost2, undeletedPost.post_view); @@ -367,7 +366,7 @@ test("Search for a post", async () => { let postRes = await createPost(alpha, betaCommunity.community.id); expect(postRes.post_view.post).toBeDefined(); - let betaPost = (await resolvePost(beta, postRes.post_view.post)).post; + let betaPost = await waitForPost(beta, postRes.post_view.post); expect(betaPost?.post.name).toBeDefined(); }); diff --git a/api_tests/src/shared.ts b/api_tests/src/shared.ts index 1166b5134..54dfb97a0 100644 --- a/api_tests/src/shared.ts +++ b/api_tests/src/shared.ts @@ -323,10 +323,10 @@ export async function searchPostLocal( export async function waitForPost( api: API, post: Post, - checker: (t: PostView) => boolean = p => !!p, + checker: (t: PostView | undefined) => boolean = p => !!p, ) { - return waitUntil( - () => searchPostLocal(api, post).then(p => p.posts[0] as PostView), + return waitUntil( + () => searchPostLocal(api, post).then(p => p.posts[0]), checker, ); } From c792f46c59147b6dbe64b620e117c2bf3416edf1 Mon Sep 17 00:00:00 2001 From: phiresky Date: Wed, 20 Sep 2023 11:38:12 +0000 Subject: [PATCH 24/44] more wait for --- api_tests/src/comment.spec.ts | 7 ++++--- api_tests/src/post.spec.ts | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/api_tests/src/comment.spec.ts b/api_tests/src/comment.spec.ts index 24822d1d1..2afbc9fc7 100644 --- a/api_tests/src/comment.spec.ts +++ b/api_tests/src/comment.spec.ts @@ -34,6 +34,7 @@ import { getUnreadCount, waitUntil, delay, + waitForPost, } from "./shared"; import { CommentView } from "lemmy-js-client/dist/types/CommentView"; import { CommunityView } from "lemmy-js-client"; @@ -441,7 +442,7 @@ test("Mention beta from alpha", async () => { expect(mentionRes.comment_view.counts.score).toBe(1); // get beta's localized copy of the alpha post - let betaPost = (await resolvePost(beta, postOnAlphaRes.post_view.post)).post; + let betaPost = await waitForPost(beta, postOnAlphaRes.post_view.post); if (!betaPost) { throw "unable to locate post on beta"; } @@ -578,13 +579,13 @@ test("Check that activity from another instance is sent to third instance", asyn expect(betaPost.post_view.community.local).toBe(true); // Make sure gamma and alpha see it - let gammaPost = (await resolvePost(gamma, betaPost.post_view.post)).post; + let gammaPost = await waitForPost(gamma, betaPost.post_view.post); if (!gammaPost) { throw "Missing gamma post"; } expect(gammaPost.post).toBeDefined(); - let alphaPost = (await resolvePost(alpha, betaPost.post_view.post)).post; + let alphaPost = await waitForPost(alpha, betaPost.post_view.post); if (!alphaPost) { throw "Missing alpha post"; } diff --git a/api_tests/src/post.spec.ts b/api_tests/src/post.spec.ts index 3b0e24129..602aba8cf 100644 --- a/api_tests/src/post.spec.ts +++ b/api_tests/src/post.spec.ts @@ -167,7 +167,7 @@ test("Sticky a post", async () => { } let postRes = await createPost(alpha, betaCommunity.community.id); - let betaPost1 = (await resolvePost(beta, postRes.post_view.post, false)).post; + let betaPost1 = await waitForPost(beta, postRes.post_view.post); if (!betaPost1) { throw "Missing beta post1"; } From 78a8a7b8b79880af28e43ad350f435bc45ef67f4 Mon Sep 17 00:00:00 2001 From: phiresky Date: Wed, 20 Sep 2023 11:41:34 +0000 Subject: [PATCH 25/44] clippy --- crates/apub/src/activities/community/announce.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/apub/src/activities/community/announce.rs b/crates/apub/src/activities/community/announce.rs index ab82eb1de..e84a970f3 100644 --- a/crates/apub/src/activities/community/announce.rs +++ b/crates/apub/src/activities/community/announce.rs @@ -79,7 +79,7 @@ impl AnnounceActivity { let inner_kind = object .other .get("type") - .and_then(|e| e.as_str()) + .and_then(serde_json::Value::as_str) .unwrap_or("other"); let id = generate_announce_activity_id(inner_kind, &context.settings().get_protocol_and_hostname())?; From a59a94492d9541ad18f1a7dfdcfe4b09cb5a484e Mon Sep 17 00:00:00 2001 From: phiresky Date: Wed, 20 Sep 2023 12:29:09 +0000 Subject: [PATCH 26/44] more debug log --- crates/apub/src/activities/mod.rs | 2 +- crates/federate/src/worker.rs | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/crates/apub/src/activities/mod.rs b/crates/apub/src/activities/mod.rs index 2e26e0678..fcb90b13a 100644 --- a/crates/apub/src/activities/mod.rs +++ b/crates/apub/src/activities/mod.rs @@ -194,7 +194,7 @@ fn generate_announce_activity_id( "{}/activities/{}/{}/{}", protocol_and_hostname, AnnounceType::Announce.to_string().to_lowercase(), - inner_kind, + inner_kind.to_lowercase(), Uuid::new_v4() ); Url::parse(&id) diff --git a/crates/federate/src/worker.rs b/crates/federate/src/worker.rs index b6e174c04..249fc100e 100644 --- a/crates/federate/src/worker.rs +++ b/crates/federate/src/worker.rs @@ -168,6 +168,12 @@ impl InstanceWorker { self.state.last_successful_id = id; continue; }; + tracing::info!( + "processing send of {} {} for {}", + ele.0.id, + ele.0.ap_id, + self.instance.domain + ); if let Err(e) = self.send_retry_loop(pool, &ele.0, &ele.1).await { tracing::warn!( "sending {} errored internally, skipping activity: {:?}", @@ -197,6 +203,13 @@ impl InstanceWorker { .get_inbox_urls(pool, activity) .await .context("failed figuring out inbox urls")?; + tracing::info!( + "inboxes of {} for {} {}: {:?}", + self.instance.domain, + activity.id, + activity.ap_id, + inbox_urls + ); if inbox_urls.is_empty() { self.state.last_successful_id = activity.id; return Ok(()); From a61d56473271eeeec5242c4c8082537c0599e1dd Mon Sep 17 00:00:00 2001 From: phiresky Date: Wed, 20 Sep 2023 13:07:36 +0000 Subject: [PATCH 27/44] fix delete test --- api_tests/src/post.spec.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/api_tests/src/post.spec.ts b/api_tests/src/post.spec.ts index 602aba8cf..c8affbab9 100644 --- a/api_tests/src/post.spec.ts +++ b/api_tests/src/post.spec.ts @@ -261,13 +261,17 @@ test("Delete a post", async () => { // Make sure lemmy beta sees post is deleted // This will be undefined because of the tombstone - await waitForPost(beta, postRes.post_view.post, p => !p); + await waitForPost(beta, postRes.post_view.post, p => !p || p.post.deleted); // Undelete let undeletedPost = await deletePost(alpha, false, postRes.post_view.post); // Make sure lemmy beta sees post is undeleted - let betaPost2 = await waitForPost(beta, postRes.post_view.post); + let betaPost2 = await waitForPost( + beta, + postRes.post_view.post, + p => !!p && !p.post.deleted, + ); if (!betaPost2) { throw "Missing beta post 2"; From 1a0c866b5169cfc8130e53df69dc6e1dbc190361 Mon Sep 17 00:00:00 2001 From: phiresky Date: Wed, 20 Sep 2023 13:37:18 +0000 Subject: [PATCH 28/44] logging temporary --- crates/apub/src/activities/mod.rs | 7 ++++--- crates/federate/src/worker.rs | 2 ++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/crates/apub/src/activities/mod.rs b/crates/apub/src/activities/mod.rs index fcb90b13a..b7cbbd500 100644 --- a/crates/apub/src/activities/mod.rs +++ b/crates/apub/src/activities/mod.rs @@ -217,12 +217,12 @@ where ActorT: Actor + GetActorType, Activity: ActivityHandler, { - info!("Sending activity {}", activity.id().to_string()); + info!("Saving outgoing activity to queue {}", activity.id()); let activity = WithContext::new(activity, CONTEXT.deref().clone()); let form = SentActivityForm { ap_id: activity.id().clone().into(), - data: serde_json::to_value(activity.clone())?, + data: serde_json::to_value(activity)?, sensitive, send_inboxes: send_targets .inboxes @@ -234,7 +234,8 @@ where actor_type: actor.actor_type(), actor_apub_id: actor.id().into(), }; - SentActivity::create(&mut data.pool(), form).await?; + let created = SentActivity::create(&mut data.pool(), form).await?; + info!("Queued for send: {:?}", created); Ok(()) } diff --git a/crates/federate/src/worker.rs b/crates/federate/src/worker.rs index 249fc100e..14c86a7d3 100644 --- a/crates/federate/src/worker.rs +++ b/crates/federate/src/worker.rs @@ -161,10 +161,12 @@ impl InstanceWorker { { id += 1; processed_activities += 1; + tracing::info!("looking at activity {id}, proc={processed_activities}, latest={latest_id}"); let Some(ele) = get_activity_cached(pool, id) .await .context("failed reading activity from db")? else { + tracing::info!("activity {id} empty, marking latest"); self.state.last_successful_id = id; continue; }; From 3d649e1d3e986ab1541f13183ef5d1cdc3b1aaf0 Mon Sep 17 00:00:00 2001 From: phiresky Date: Wed, 20 Sep 2023 14:18:31 +0000 Subject: [PATCH 29/44] remove synchronous federation flag --- api_tests/prepare-drone-federation-test.sh | 3 +-- api_tests/src/post.spec.ts | 1 + crates/api_common/src/send_activity.rs | 14 ++++---------- crates/api_crud/src/post/create.rs | 10 ++-------- crates/apub/src/activities/mod.rs | 12 ++---------- crates/utils/src/lib.rs | 11 ----------- 6 files changed, 10 insertions(+), 41 deletions(-) diff --git a/api_tests/prepare-drone-federation-test.sh b/api_tests/prepare-drone-federation-test.sh index fc19ee8c8..4044ba0dd 100755 --- a/api_tests/prepare-drone-federation-test.sh +++ b/api_tests/prepare-drone-federation-test.sh @@ -6,8 +6,7 @@ set -e export RUST_BACKTRACE=1 export RUST_LOG="warn,lemmy_server=debug,lemmy_federate=debug,lemmy_api=debug,lemmy_api_common=debug,lemmy_api_crud=debug,lemmy_apub=debug,lemmy_db_schema=debug,lemmy_db_views=debug,lemmy_db_views_actor=debug,lemmy_db_views_moderator=debug,lemmy_routes=debug,lemmy_utils=debug,lemmy_websocket=debug" -export LEMMY_SYNCHRONOUS_FEDERATION=1 # currently this is true in debug by default, but still. -export LEMMY_TEST_FAST_FEDERATION=1 # by default, the persistent federation queue has delays in the scale of 30s-5min +export LEMMY_TEST_FAST_FEDERATION=1 # by default, the persistent federation queue has delays in the scale of 30s-5min for INSTANCE in lemmy_alpha lemmy_beta lemmy_gamma lemmy_delta lemmy_epsilon; do echo "DB URL: ${LEMMY_DATABASE_URL} INSTANCE: $INSTANCE" diff --git a/api_tests/src/post.spec.ts b/api_tests/src/post.spec.ts index c8affbab9..1530d6bb0 100644 --- a/api_tests/src/post.spec.ts +++ b/api_tests/src/post.spec.ts @@ -254,6 +254,7 @@ test("Delete a post", async () => { let postRes = await createPost(alpha, betaCommunity.community.id); expect(postRes.post_view.post).toBeDefined(); + await waitForPost(beta, postRes.post_view.post); let deletedPost = await deletePost(alpha, true, postRes.post_view.post); expect(deletedPost.post_view.post.deleted).toBe(true); diff --git a/crates/api_common/src/send_activity.rs b/crates/api_common/src/send_activity.rs index 897f102fe..6d9c722a1 100644 --- a/crates/api_common/src/send_activity.rs +++ b/crates/api_common/src/send_activity.rs @@ -17,7 +17,7 @@ use lemmy_db_schema::{ }, }; use lemmy_db_views::structs::PrivateMessageView; -use lemmy_utils::{error::LemmyResult, SYNCHRONOUS_FEDERATION}; +use lemmy_utils::error::LemmyResult; use once_cell::sync::{Lazy, OnceCell}; use tokio::{ sync::{ @@ -32,7 +32,7 @@ use url::Url; type MatchOutgoingActivitiesBoxed = Box fn(SendActivityData, &'a Data) -> BoxFuture<'a, LemmyResult<()>>>; -/// This static is necessary so that activities can be sent out synchronously for tests and the api_common crates don't need to depend on lemmy_apub +/// This static is necessary so that the api_common crates don't need to depend on lemmy_apub pub static MATCH_OUTGOING_ACTIVITIES: OnceCell = OnceCell::new(); #[derive(Debug)] @@ -88,17 +88,11 @@ impl ActivityChannel { pub async fn submit_activity( data: SendActivityData, - context: &Data, + _context: &Data, ) -> LemmyResult<()> { - if *SYNCHRONOUS_FEDERATION { - MATCH_OUTGOING_ACTIVITIES - .get() - .expect("retrieve function pointer")(data, context) - .await?; - } // could do `ACTIVITY_CHANNEL.keepalive_sender.lock()` instead and get rid of weak_sender, // not sure which way is more efficient - else if let Some(sender) = ACTIVITY_CHANNEL.weak_sender.upgrade() { + if let Some(sender) = ACTIVITY_CHANNEL.weak_sender.upgrade() { sender.send(data)?; } Ok(()) diff --git a/crates/api_crud/src/post/create.rs b/crates/api_crud/src/post/create.rs index d0b0f368c..3da75589a 100644 --- a/crates/api_crud/src/post/create.rs +++ b/crates/api_crud/src/post/create.rs @@ -37,7 +37,6 @@ use lemmy_utils::{ slurs::{check_slurs, check_slurs_opt}, validation::{check_url_scheme, clean_url_params, is_valid_body_field, is_valid_post_title}, }, - SYNCHRONOUS_FEDERATION, }; use tracing::Instrument; use url::Url; @@ -176,7 +175,7 @@ pub async fn create_post( mark_post_as_read(person_id, post_id, &mut context.pool()).await?; if let Some(url) = updated_post.url.clone() { - let task = async move { + spawn_try_task(async move { let mut webmention = Webmention::new::(updated_post.ap_id.clone().into(), url.clone().into())?; webmention.set_checked(true); @@ -189,12 +188,7 @@ pub async fn create_post( Ok(_) => Ok(()), Err(e) => Err(e).with_lemmy_type(LemmyErrorType::CouldntSendWebmention), } - }; - if *SYNCHRONOUS_FEDERATION { - task.await?; - } else { - spawn_try_task(task); - } + }); }; build_post_response(&context, community_id, person_id, post_id).await diff --git a/crates/apub/src/activities/mod.rs b/crates/apub/src/activities/mod.rs index b7cbbd500..54a96014e 100644 --- a/crates/apub/src/activities/mod.rs +++ b/crates/apub/src/activities/mod.rs @@ -45,11 +45,7 @@ use lemmy_db_schema::{ }, }; use lemmy_db_views_actor::structs::{CommunityPersonBanView, CommunityView}; -use lemmy_utils::{ - error::{LemmyError, LemmyErrorExt, LemmyErrorType, LemmyResult}, - spawn_try_task, - SYNCHRONOUS_FEDERATION, -}; +use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType, LemmyResult}; use serde::Serialize; use std::{ops::Deref, time::Duration}; use tracing::info; @@ -351,10 +347,6 @@ pub async fn match_outgoing_activities( } } }; - if *SYNCHRONOUS_FEDERATION { - fed_task.await?; - } else { - spawn_try_task(fed_task); - } + fed_task.await?; Ok(()) } diff --git a/crates/utils/src/lib.rs b/crates/utils/src/lib.rs index 1ef8a842c..c0553de31 100644 --- a/crates/utils/src/lib.rs +++ b/crates/utils/src/lib.rs @@ -18,7 +18,6 @@ pub mod version; use error::LemmyError; use futures::Future; -use once_cell::sync::Lazy; use std::time::Duration; use tracing::Instrument; @@ -38,16 +37,6 @@ macro_rules! location_info { }; } -/// if true, all federation should happen synchronously. useful for debugging and testing. -/// defaults to true on debug mode, false on releasemode -/// override to true by setting env LEMMY_SYNCHRONOUS_FEDERATION=1 -/// override to false by setting env LEMMY_SYNCHRONOUS_FEDERATION="" -pub static SYNCHRONOUS_FEDERATION: Lazy = Lazy::new(|| { - std::env::var("LEMMY_SYNCHRONOUS_FEDERATION") - .map(|s| !s.is_empty()) - .unwrap_or(cfg!(debug_assertions)) -}); - /// tokio::spawn, but accepts a future that may fail and also /// * logs errors /// * attaches the spawned task to the tracing span of the caller for better logging From a808d3208a25908edd2da7e6f9cd3f2634e9432f Mon Sep 17 00:00:00 2001 From: phiresky Date: Wed, 20 Sep 2023 14:51:40 +0000 Subject: [PATCH 30/44] use max(id) instead of seq max value to prevent uncommitted transactions from causing skipped activities --- crates/federate/src/util.rs | 27 +++++---------------------- 1 file changed, 5 insertions(+), 22 deletions(-) diff --git a/crates/federate/src/util.rs b/crates/federate/src/util.rs index f00ccadb3..f744d45f4 100644 --- a/crates/federate/src/util.rs +++ b/crates/federate/src/util.rs @@ -1,8 +1,5 @@ use anyhow::{anyhow, Context, Result}; -use diesel::{ - prelude::*, - sql_types::{Bool, Int8}, -}; +use diesel::prelude::*; use diesel_async::RunQueryDsl; use lemmy_apub::{ activity_lists::SharedInboxActivities, @@ -191,17 +188,11 @@ pub(crate) async fn get_latest_activity_id(pool: &mut DbPool<'_>) -> Result = sent_activity.select(max(id)).get_result(conn).await?; + let latest_id = seq.unwrap_or(0); anyhow::Result::<_, anyhow::Error>::Ok(latest_id as ActivityId) }) .await @@ -212,11 +203,3 @@ pub(crate) async fn get_latest_activity_id(pool: &mut DbPool<'_>) -> Result Duration { Duration::from_secs_f64(10.0 * 2.0_f64.powf(f64::from(retry_count))) } - -#[derive(QueryableByName)] -struct Sequence { - #[diesel(sql_type = Int8)] - last_value: i64, // this value is bigint for some reason even if sequence is int4 - #[diesel(sql_type = Bool)] - is_called: bool, -} From ae37ca0137b2139cc84285464c3002bf4c7ee6e0 Mon Sep 17 00:00:00 2001 From: phiresky Date: Wed, 20 Sep 2023 15:33:09 +0000 Subject: [PATCH 31/44] re-remove debug comments --- crates/apub/src/activities/mod.rs | 3 +-- crates/federate/src/worker.rs | 15 --------------- 2 files changed, 1 insertion(+), 17 deletions(-) diff --git a/crates/apub/src/activities/mod.rs b/crates/apub/src/activities/mod.rs index 54a96014e..958065ffa 100644 --- a/crates/apub/src/activities/mod.rs +++ b/crates/apub/src/activities/mod.rs @@ -230,8 +230,7 @@ where actor_type: actor.actor_type(), actor_apub_id: actor.id().into(), }; - let created = SentActivity::create(&mut data.pool(), form).await?; - info!("Queued for send: {:?}", created); + SentActivity::create(&mut data.pool(), form).await?; Ok(()) } diff --git a/crates/federate/src/worker.rs b/crates/federate/src/worker.rs index 14c86a7d3..b6e174c04 100644 --- a/crates/federate/src/worker.rs +++ b/crates/federate/src/worker.rs @@ -161,21 +161,13 @@ impl InstanceWorker { { id += 1; processed_activities += 1; - tracing::info!("looking at activity {id}, proc={processed_activities}, latest={latest_id}"); let Some(ele) = get_activity_cached(pool, id) .await .context("failed reading activity from db")? else { - tracing::info!("activity {id} empty, marking latest"); self.state.last_successful_id = id; continue; }; - tracing::info!( - "processing send of {} {} for {}", - ele.0.id, - ele.0.ap_id, - self.instance.domain - ); if let Err(e) = self.send_retry_loop(pool, &ele.0, &ele.1).await { tracing::warn!( "sending {} errored internally, skipping activity: {:?}", @@ -205,13 +197,6 @@ impl InstanceWorker { .get_inbox_urls(pool, activity) .await .context("failed figuring out inbox urls")?; - tracing::info!( - "inboxes of {} for {} {}: {:?}", - self.instance.domain, - activity.id, - activity.ap_id, - inbox_urls - ); if inbox_urls.is_empty() { self.state.last_successful_id = activity.id; return Ok(()); From ac0c0c88564b1cb6c6aab7ec3aeff8ccc2e2b15f Mon Sep 17 00:00:00 2001 From: phiresky Date: Wed, 20 Sep 2023 15:33:31 +0000 Subject: [PATCH 32/44] re-remove lemmy logs --- .woodpecker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.woodpecker.yml b/.woodpecker.yml index c180d8d58..49fbe3db2 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -204,7 +204,7 @@ steps: - bash api_tests/prepare-drone-federation-test.sh - cd api_tests/ - yarn - - tail -f /tmp/lemmy*.out & yarn api-test + - yarn api-test when: *slow_check_paths rebuild-cache: From 1b7ab96887d7e7ca7b2b7f217d91faa1ab9dbf95 Mon Sep 17 00:00:00 2001 From: phiresky Date: Wed, 20 Sep 2023 20:26:00 +0000 Subject: [PATCH 33/44] wait until ban post removed --- api_tests/src/post.spec.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/api_tests/src/post.spec.ts b/api_tests/src/post.spec.ts index 1530d6bb0..68ddbb730 100644 --- a/api_tests/src/post.spec.ts +++ b/api_tests/src/post.spec.ts @@ -419,8 +419,10 @@ test("Enforce site ban for federated user", async () => { expect(alphaUserOnBeta1.person?.person.banned).toBe(true); // existing alpha post should be removed on beta - let searchBeta2 = await getPost(beta, searchBeta1.post.id); - expect(searchBeta2.post_view.post.removed).toBe(true); + let searchBeta2 = await waitUntil( + () => getPost(beta, searchBeta1.post.id), + s => s.post_view.post.removed, + ); // Unban alpha let unBanAlpha = await banPersonFromSite( From f16aa9228d3e47d101898607cdccbe0d4772220e Mon Sep 17 00:00:00 2001 From: phiresky Date: Wed, 20 Sep 2023 20:55:43 +0000 Subject: [PATCH 34/44] community fix --- api_tests/src/community.spec.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/api_tests/src/community.spec.ts b/api_tests/src/community.spec.ts index a8ea3073a..a313d97d2 100644 --- a/api_tests/src/community.spec.ts +++ b/api_tests/src/community.spec.ts @@ -27,6 +27,7 @@ import { blockInstance, waitUntil, delay, + waitForPost, } from "./shared"; beforeAll(async () => { @@ -351,8 +352,9 @@ test("User blocks instance, communities are hidden", async () => { expect(postRes.post_view.post.id).toBeDefined(); // fetch post to alpha - let alphaPost = await resolvePost(alpha, postRes.post_view.post); - expect(alphaPost.post?.post).toBeDefined(); + let alphaPost = (await resolvePost(alpha, postRes.post_view.post, false)) + .post!; + expect(alphaPost.post).toBeDefined(); // post should be included in listing let listing = await getPosts(alpha, "All"); @@ -360,7 +362,7 @@ test("User blocks instance, communities are hidden", async () => { expect(listing_ids).toContain(postRes.post_view.post.ap_id); // block the beta instance - await blockInstance(alpha, alphaPost.post!.community.instance_id, true); + await blockInstance(alpha, alphaPost.community.instance_id, true); // after blocking, post should not be in listing let listing2 = await getPosts(alpha, "All"); @@ -368,7 +370,7 @@ test("User blocks instance, communities are hidden", async () => { expect(listing_ids2.indexOf(postRes.post_view.post.ap_id)).toBe(-1); // unblock instance again - await blockInstance(alpha, alphaPost.post!.community.instance_id, false); + await blockInstance(alpha, alphaPost.community.instance_id, false); // post should be included in listing let listing3 = await getPosts(alpha, "All"); From 7e8b973128cad8b183340e66a6b1cc5d6e402575 Mon Sep 17 00:00:00 2001 From: phiresky Date: Wed, 20 Sep 2023 21:21:23 +0000 Subject: [PATCH 35/44] empty From f858d8cbce4453d469733c61d03a9e9c9e001ef8 Mon Sep 17 00:00:00 2001 From: Nutomic Date: Thu, 21 Sep 2023 12:42:28 +0200 Subject: [PATCH 36/44] Remove explicit auth params (#3946) * Remove explicit auth params (ref #3725) Only take auth via header or cookie. This requires a new version of lemmy-js-client for api tests to pass. * rework api_crud * remove remaining auth params, move logic to session middleware * fmt, fix test * update js client * remove auth param from api tests * Pass auth as header * add ! * url vars, setHeader * cleanup * fmt * update * Updating for new lemmy-js-client. --------- Co-authored-by: Dessalines Co-authored-by: Dessalines --- Cargo.lock | 1 + Cargo.toml | 1 + api_tests/package.json | 2 +- api_tests/src/comment.spec.ts | 10 +- api_tests/src/community.spec.ts | 12 +- api_tests/src/post.spec.ts | 21 +- api_tests/src/shared.ts | 336 +++++++----------- api_tests/src/user.spec.ts | 28 +- api_tests/yarn.lock | 8 +- crates/api/src/comment/distinguish.rs | 7 +- crates/api/src/comment/like.rs | 4 +- crates/api/src/comment/save.rs | 6 +- crates/api/src/comment_report/create.rs | 11 +- crates/api/src/comment_report/list.rs | 6 +- crates/api/src/comment_report/resolve.rs | 7 +- crates/api/src/community/add_mod.rs | 6 +- crates/api/src/community/ban.rs | 11 +- crates/api/src/community/block.rs | 5 +- crates/api/src/community/follow.rs | 6 +- crates/api/src/community/hide.rs | 5 +- crates/api/src/community/transfer.rs | 6 +- crates/api/src/lib.rs | 62 ---- crates/api/src/local_user/add_admin.rs | 5 +- crates/api/src/local_user/ban_person.rs | 6 +- crates/api/src/local_user/block.rs | 4 +- crates/api/src/local_user/change_password.rs | 6 +- crates/api/src/local_user/list_banned.rs | 13 +- crates/api/src/local_user/login.rs | 34 +- .../local_user/notifications/list_mentions.rs | 5 +- .../local_user/notifications/list_replies.rs | 5 +- .../local_user/notifications/mark_all_read.rs | 10 +- .../notifications/mark_mention_read.rs | 5 +- .../notifications/mark_reply_read.rs | 5 +- .../local_user/notifications/unread_count.rs | 14 +- crates/api/src/local_user/report_count.rs | 11 +- crates/api/src/local_user/save_settings.rs | 6 +- crates/api/src/post/feature.rs | 12 +- crates/api/src/post/like.rs | 4 +- crates/api/src/post/lock.rs | 11 +- crates/api/src/post/mark_read.rs | 6 +- crates/api/src/post/save.rs | 7 +- crates/api/src/post_report/create.rs | 11 +- crates/api/src/post_report/list.rs | 6 +- crates/api/src/post_report/resolve.rs | 7 +- crates/api/src/private_message/mark_read.rs | 6 +- .../api/src/private_message_report/create.rs | 6 +- crates/api/src/private_message_report/list.rs | 10 +- .../api/src/private_message_report/resolve.rs | 7 +- crates/api/src/site/block.rs | 5 +- crates/api/src/site/leave_admin.rs | 12 +- crates/api/src/site/mod_log.rs | 5 +- crates/api/src/site/purge/comment.rs | 6 +- crates/api/src/site/purge/community.rs | 11 +- crates/api/src/site/purge/person.rs | 5 +- crates/api/src/site/purge/post.rs | 6 +- .../site/registration_applications/approve.rs | 5 +- .../site/registration_applications/list.rs | 9 +- .../registration_applications/unread_count.rs | 11 +- crates/api_common/src/comment.rs | 13 - crates/api_common/src/community.rs | 13 - crates/api_common/src/custom_emoji.rs | 4 - crates/api_common/src/person.rs | 36 -- crates/api_common/src/post.rs | 15 - crates/api_common/src/private_message.rs | 9 - crates/api_common/src/site.rs | 38 -- crates/api_common/src/utils.rs | 92 +---- crates/api_crud/src/comment/create.rs | 4 +- crates/api_crud/src/comment/delete.rs | 7 +- crates/api_crud/src/comment/read.rs | 5 +- crates/api_crud/src/comment/remove.rs | 7 +- crates/api_crud/src/comment/update.rs | 11 +- crates/api_crud/src/community/create.rs | 5 +- crates/api_crud/src/community/delete.rs | 6 +- crates/api_crud/src/community/list.rs | 5 +- crates/api_crud/src/community/remove.rs | 6 +- crates/api_crud/src/community/update.rs | 5 +- crates/api_crud/src/custom_emoji/create.rs | 7 +- crates/api_crud/src/custom_emoji/delete.rs | 6 +- crates/api_crud/src/custom_emoji/update.rs | 7 +- crates/api_crud/src/post/create.rs | 4 +- crates/api_crud/src/post/delete.rs | 6 +- crates/api_crud/src/post/read.rs | 14 +- crates/api_crud/src/post/remove.rs | 6 +- crates/api_crud/src/post/update.rs | 10 +- crates/api_crud/src/private_message/create.rs | 3 +- crates/api_crud/src/private_message/delete.rs | 6 +- crates/api_crud/src/private_message/read.rs | 5 +- crates/api_crud/src/private_message/update.rs | 6 +- crates/api_crud/src/site/create.rs | 6 +- crates/api_crud/src/site/read.rs | 53 +-- crates/api_crud/src/site/update.rs | 12 +- crates/api_crud/src/user/delete.rs | 6 +- crates/apub/src/api/list_comments.rs | 5 +- crates/apub/src/api/list_posts.rs | 5 +- crates/apub/src/api/read_community.rs | 5 +- crates/apub/src/api/read_person.rs | 5 +- crates/apub/src/api/resolve_object.rs | 5 +- crates/apub/src/api/search.rs | 5 +- crates/routes/src/images.rs | 41 +-- src/session_middleware.rs | 118 +++++- 100 files changed, 567 insertions(+), 918 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dee04c62b..6426d317d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2894,6 +2894,7 @@ dependencies = [ "rustls 0.21.3", "serde", "serde_json", + "serial_test", "tokio", "tokio-postgres", "tokio-postgres-rustls", diff --git a/Cargo.toml b/Cargo.toml index 72ab87d4f..723d7aabf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -166,5 +166,6 @@ tokio-postgres-rustls = { workspace = true } chrono = { workspace = true } prometheus = { version = "0.13.3", features = ["process"], optional = true } actix-web-prom = { version = "0.6.0", optional = true } +serial_test = { workspace = true } clap = { version = "4.3.19", features = ["derive"] } lemmy_federate = { version = "0.18.1", path = "crates/federate" } diff --git a/api_tests/package.json b/api_tests/package.json index e57d37d08..56624f9e2 100644 --- a/api_tests/package.json +++ b/api_tests/package.json @@ -19,7 +19,7 @@ "eslint": "^8.40.0", "eslint-plugin-prettier": "^4.0.0", "jest": "^29.5.0", - "lemmy-js-client": "0.19.0-rc.5", + "lemmy-js-client": "0.19.0-rc.12", "prettier": "^3.0.0", "ts-jest": "^29.1.0", "typescript": "^5.0.4" diff --git a/api_tests/src/comment.spec.ts b/api_tests/src/comment.spec.ts index 000c0b0ab..394f73dcd 100644 --- a/api_tests/src/comment.spec.ts +++ b/api_tests/src/comment.spec.ts @@ -24,7 +24,6 @@ import { reportComment, listCommentReports, randomString, - API, unfollows, getComments, getCommentParentId, @@ -34,8 +33,10 @@ import { getUnreadCount, waitUntil, delay, + alphaUrl, } from "./shared"; import { CommentView } from "lemmy-js-client/dist/types/CommentView"; +import { LemmyHttp } from "lemmy-js-client"; let postOnAlphaRes: PostResponse; @@ -227,10 +228,9 @@ test.skip("Remove a comment from admin and community on the same instance", asyn test("Remove a comment from admin and community on different instance", async () => { let alpha_user = await registerUser(alpha); - let newAlphaApi: API = { - client: alpha.client, - auth: alpha_user.jwt ?? "", - }; + let newAlphaApi = new LemmyHttp(alphaUrl, { + headers: { auth: alpha_user.jwt ?? "" }, + }); // New alpha user creates a community, post, and comment. let newCommunity = await createCommunity(newAlphaApi); diff --git a/api_tests/src/community.spec.ts b/api_tests/src/community.spec.ts index effd2169e..d91ac8aa7 100644 --- a/api_tests/src/community.spec.ts +++ b/api_tests/src/community.spec.ts @@ -19,7 +19,6 @@ import { getPost, resolvePost, registerUser, - API, getPosts, getComments, createComment, @@ -27,7 +26,9 @@ import { blockInstance, waitUntil, delay, + alphaUrl, } from "./shared"; +import { LemmyHttp } from "lemmy-js-client"; beforeAll(async () => { await setupLogins(); @@ -258,11 +259,10 @@ test("Admin actions in remote community are not federated to origin", async () = test("moderator view", async () => { // register a new user with their own community on alpha and post to it - let otherUser: API = { - auth: (await registerUser(alpha)).jwt ?? "", - client: alpha.client, - }; - expect(otherUser.auth).not.toBe(""); + let registerUserRes = await registerUser(alpha); + let otherUser = new LemmyHttp(alphaUrl, { + headers: { auth: registerUserRes.jwt ?? "" }, + }); let otherCommunity = (await createCommunity(otherUser)).community_view; expect(otherCommunity.community.name).toBeDefined(); diff --git a/api_tests/src/post.spec.ts b/api_tests/src/post.spec.ts index cd3eec71b..2ef28951f 100644 --- a/api_tests/src/post.spec.ts +++ b/api_tests/src/post.spec.ts @@ -30,15 +30,16 @@ import { listPostReports, randomString, registerUser, - API, getSite, unfollows, resolveCommunity, waitUntil, delay, + alphaUrl, } from "./shared"; import { PostView } from "lemmy-js-client/dist/types/PostView"; import { CreatePost } from "lemmy-js-client/dist/types/CreatePost"; +import { LemmyHttp } from "lemmy-js-client"; let betaCommunity: CommunityView | undefined; @@ -395,17 +396,16 @@ test("Enforce site ban for federated user", async () => { // create a test user let alphaUserJwt = await registerUser(alpha); expect(alphaUserJwt).toBeDefined(); - let alpha_user: API = { - client: alpha.client, - auth: alphaUserJwt.jwt ?? "", - }; - const alphaUserActorId = (await getSite(alpha_user)).my_user?.local_user_view + let alpha_user = new LemmyHttp(alphaUrl, { + headers: { auth: alphaUserJwt.jwt ?? "" }, + }); + let alphaUserActorId = (await getSite(alpha_user)).my_user?.local_user_view .person.actor_id; if (!alphaUserActorId) { throw "Missing alpha user actor id"; } expect(alphaUserActorId).toBeDefined(); - let alphaPerson = (await resolvePerson(alpha_user, alphaUserActorId)).person; + let alphaPerson = (await resolvePerson(alpha_user, alphaUserActorId!)).person; if (!alphaPerson) { throw "Missing alpha person"; } @@ -430,7 +430,7 @@ test("Enforce site ban for federated user", async () => { // alpha ban should be federated to beta let alphaUserOnBeta1 = await waitUntil( - () => resolvePerson(beta, alphaUserActorId), + () => resolvePerson(beta, alphaUserActorId!), res => res.person?.person.banned ?? false, ); expect(alphaUserOnBeta1.person?.person.banned).toBe(true); @@ -456,7 +456,7 @@ test("Enforce site ban for federated user", async () => { ); expect(searchBeta3.posts[0]).toBeDefined(); - let alphaUserOnBeta2 = await resolvePerson(beta, alphaUserActorId); + let alphaUserOnBeta2 = await resolvePerson(beta, alphaUserActorId!); expect(alphaUserOnBeta2.person?.person.banned).toBe(false); }); @@ -569,10 +569,9 @@ test("Sanitize HTML", async () => { let form: CreatePost = { name, body, - auth: beta.auth, community_id: betaCommunity.community.id, }; - let post = await beta.client.createPost(form); + let post = await beta.createPost(form); // first escaping for the api expect(post.post_view.post.body).toBe( "<script>alert('xss');</script> hello &"'", diff --git a/api_tests/src/shared.ts b/api_tests/src/shared.ts index f7039942d..19636f386 100644 --- a/api_tests/src/shared.ts +++ b/api_tests/src/shared.ts @@ -3,7 +3,6 @@ import { BlockInstanceResponse, GetReplies, GetRepliesResponse, - GetUnreadCount, GetUnreadCountResponse, InstanceId, LemmyHttp, @@ -56,7 +55,6 @@ import { SaveUserSettings } from "lemmy-js-client/dist/types/SaveUserSettings"; import { DeleteAccount } from "lemmy-js-client/dist/types/DeleteAccount"; import { GetSiteResponse } from "lemmy-js-client/dist/types/GetSiteResponse"; import { DeleteAccountResponse } from "lemmy-js-client/dist/types/DeleteAccountResponse"; -import { GetSite } from "lemmy-js-client/dist/types/GetSite"; import { PrivateMessagesResponse } from "lemmy-js-client/dist/types/PrivateMessagesResponse"; import { GetPrivateMessages } from "lemmy-js-client/dist/types/GetPrivateMessages"; import { PostReportResponse } from "lemmy-js-client/dist/types/PostReportResponse"; @@ -73,35 +71,17 @@ import { GetPersonDetailsResponse } from "lemmy-js-client/dist/types/GetPersonDe import { GetPersonDetails } from "lemmy-js-client/dist/types/GetPersonDetails"; import { ListingType } from "lemmy-js-client/dist/types/ListingType"; -export interface API { - client: LemmyHttp; - auth: string; -} +export let alphaUrl = "http://127.0.0.1:8541"; +export let betaUrl = "http://127.0.0.1:8551"; +export let gammaUrl = "http://127.0.0.1:8561"; +export let deltaUrl = "http://127.0.0.1:8571"; +export let epsilonUrl = "http://127.0.0.1:8581"; -export let alpha: API = { - client: new LemmyHttp("http://127.0.0.1:8541"), - auth: "", -}; - -export let beta: API = { - client: new LemmyHttp("http://127.0.0.1:8551"), - auth: "", -}; - -export let gamma: API = { - client: new LemmyHttp("http://127.0.0.1:8561"), - auth: "", -}; - -export let delta: API = { - client: new LemmyHttp("http://127.0.0.1:8571"), - auth: "", -}; - -export let epsilon: API = { - client: new LemmyHttp("http://127.0.0.1:8581"), - auth: "", -}; +export let alpha = new LemmyHttp(alphaUrl); +export let beta = new LemmyHttp(betaUrl); +export let gamma = new LemmyHttp(gammaUrl); +export let delta = new LemmyHttp(deltaUrl); +export let epsilon = new LemmyHttp(epsilonUrl); const password = "lemmylemmy"; @@ -110,31 +90,31 @@ export async function setupLogins() { username_or_email: "lemmy_alpha", password, }; - let resAlpha = alpha.client.login(formAlpha); + let resAlpha = alpha.login(formAlpha); let formBeta: Login = { username_or_email: "lemmy_beta", password, }; - let resBeta = beta.client.login(formBeta); + let resBeta = beta.login(formBeta); let formGamma: Login = { username_or_email: "lemmy_gamma", password, }; - let resGamma = gamma.client.login(formGamma); + let resGamma = gamma.login(formGamma); let formDelta: Login = { username_or_email: "lemmy_delta", password, }; - let resDelta = delta.client.login(formDelta); + let resDelta = delta.login(formDelta); let formEpsilon: Login = { username_or_email: "lemmy_epsilon", password, }; - let resEpsilon = epsilon.client.login(formEpsilon); + let resEpsilon = epsilon.login(formEpsilon); let res = await Promise.all([ resAlpha, @@ -143,12 +123,11 @@ export async function setupLogins() { resDelta, resEpsilon, ]); - - alpha.auth = res[0].jwt ?? ""; - beta.auth = res[1].jwt ?? ""; - gamma.auth = res[2].jwt ?? ""; - delta.auth = res[3].jwt ?? ""; - epsilon.auth = res[4].jwt ?? ""; + alpha.setHeaders({ auth: res[0].jwt ?? "" }); + beta.setHeaders({ auth: res[1].jwt ?? "" }); + gamma.setHeaders({ auth: res[2].jwt ?? "" }); + delta.setHeaders({ auth: res[3].jwt ?? "" }); + epsilon.setHeaders({ auth: res[4].jwt ?? "" }); // Registration applications are now enabled by default, need to disable them let editSiteForm: EditSite = { @@ -159,45 +138,39 @@ export async function setupLogins() { rate_limit_image: 999, rate_limit_comment: 999, rate_limit_search: 999, - auth: "", }; // Set the blocks and auths for each - editSiteForm.auth = alpha.auth; editSiteForm.allowed_instances = [ "lemmy-beta", "lemmy-gamma", "lemmy-delta", "lemmy-epsilon", ]; - await alpha.client.editSite(editSiteForm); + await alpha.editSite(editSiteForm); - editSiteForm.auth = beta.auth; editSiteForm.allowed_instances = [ "lemmy-alpha", "lemmy-gamma", "lemmy-delta", "lemmy-epsilon", ]; - await beta.client.editSite(editSiteForm); + await beta.editSite(editSiteForm); - editSiteForm.auth = gamma.auth; editSiteForm.allowed_instances = [ "lemmy-alpha", "lemmy-beta", "lemmy-delta", "lemmy-epsilon", ]; - await gamma.client.editSite(editSiteForm); + await gamma.editSite(editSiteForm); editSiteForm.allowed_instances = ["lemmy-beta"]; - editSiteForm.auth = delta.auth; - await delta.client.editSite(editSiteForm); + await delta.editSite(editSiteForm); - editSiteForm.auth = epsilon.auth; editSiteForm.allowed_instances = []; editSiteForm.blocked_instances = ["lemmy-alpha"]; - await epsilon.client.editSite(editSiteForm); + await epsilon.editSite(editSiteForm); // Create the main alpha/beta communities // Ignore thrown errors of duplicates @@ -215,7 +188,7 @@ export async function setupLogins() { } export async function createPost( - api: API, + api: LemmyHttp, community_id: number, ): Promise { let name = randomString(5); @@ -227,50 +200,49 @@ export async function createPost( name, url, body, - auth: api.auth, community_id, }; - return api.client.createPost(form); + return api.createPost(form); } -export async function editPost(api: API, post: Post): Promise { +export async function editPost( + api: LemmyHttp, + post: Post, +): Promise { let name = "A jest test federated post, updated"; let form: EditPost = { name, post_id: post.id, - auth: api.auth, }; - return api.client.editPost(form); + return api.editPost(form); } export async function deletePost( - api: API, + api: LemmyHttp, deleted: boolean, post: Post, ): Promise { let form: DeletePost = { post_id: post.id, deleted: deleted, - auth: api.auth, }; - return api.client.deletePost(form); + return api.deletePost(form); } export async function removePost( - api: API, + api: LemmyHttp, removed: boolean, post: Post, ): Promise { let form: RemovePost = { post_id: post.id, removed, - auth: api.auth, }; - return api.client.removePost(form); + return api.removePost(form); } export async function featurePost( - api: API, + api: LemmyHttp, featured: boolean, post: Post, ): Promise { @@ -278,61 +250,56 @@ export async function featurePost( post_id: post.id, featured, feature_type: "Community", - auth: api.auth, }; - return api.client.featurePost(form); + return api.featurePost(form); } export async function lockPost( - api: API, + api: LemmyHttp, locked: boolean, post: Post, ): Promise { let form: LockPost = { post_id: post.id, locked, - auth: api.auth, }; - return api.client.lockPost(form); + return api.lockPost(form); } export async function resolvePost( - api: API, + api: LemmyHttp, post: Post, ): Promise { let form: ResolveObject = { q: post.ap_id, - auth: api.auth, }; - return api.client.resolveObject(form); + return api.resolveObject(form); } export async function searchPostLocal( - api: API, + api: LemmyHttp, post: Post, ): Promise { let form: Search = { q: post.name, type_: "Posts", sort: "TopAll", - auth: api.auth, }; - return api.client.search(form); + return api.search(form); } export async function getPost( - api: API, + api: LemmyHttp, post_id: number, ): Promise { let form: GetPost = { id: post_id, - auth: api.auth, }; - return api.client.getPost(form); + return api.getPost(form); } export async function getComments( - api: API, + api: LemmyHttp, post_id?: number, listingType: ListingType = "All", ): Promise { @@ -340,75 +307,66 @@ export async function getComments( post_id: post_id, type_: listingType, sort: "New", - auth: api.auth, }; - return api.client.getComments(form); + return api.getComments(form); } export async function getUnreadCount( - api: API, + api: LemmyHttp, ): Promise { - let form: GetUnreadCount = { - auth: api.auth, - }; - return api.client.getUnreadCount(form); + return api.getUnreadCount(); } -export async function getReplies(api: API): Promise { +export async function getReplies(api: LemmyHttp): Promise { let form: GetReplies = { sort: "New", unread_only: false, - auth: api.auth, }; - return api.client.getReplies(form); + return api.getReplies(form); } export async function resolveComment( - api: API, + api: LemmyHttp, comment: Comment, ): Promise { let form: ResolveObject = { q: comment.ap_id, - auth: api.auth, }; - return api.client.resolveObject(form); + return api.resolveObject(form); } export async function resolveBetaCommunity( - api: API, + api: LemmyHttp, ): Promise { // Use short-hand search url let form: ResolveObject = { q: "!main@lemmy-beta:8551", - auth: api.auth, }; - return api.client.resolveObject(form); + return api.resolveObject(form); } export async function resolveCommunity( - api: API, + api: LemmyHttp, q: string, ): Promise { let form: ResolveObject = { q, - auth: api.auth, }; - return api.client.resolveObject(form); + return api.resolveObject(form); } export async function resolvePerson( - api: API, + api: LemmyHttp, apShortname: string, ): Promise { let form: ResolveObject = { q: apShortname, - auth: api.auth, }; - return api.client.resolveObject(form); + return api.resolveObject(form); } export async function banPersonFromSite( - api: API, + api: LemmyHttp, person_id: number, ban: boolean, remove_data: boolean, @@ -418,13 +376,12 @@ export async function banPersonFromSite( person_id, ban, remove_data: remove_data, - auth: api.auth, }; - return api.client.banPerson(form); + return api.banPerson(form); } export async function banPersonFromCommunity( - api: API, + api: LemmyHttp, person_id: number, community_id: number, remove_data: boolean, @@ -435,40 +392,37 @@ export async function banPersonFromCommunity( community_id, remove_data: remove_data, ban, - auth: api.auth, }; - return api.client.banFromCommunity(form); + return api.banFromCommunity(form); } export async function followCommunity( - api: API, + api: LemmyHttp, follow: boolean, community_id: number, ): Promise { let form: FollowCommunity = { community_id, follow, - auth: api.auth, }; - return api.client.followCommunity(form); + return api.followCommunity(form); } export async function likePost( - api: API, + api: LemmyHttp, score: number, post: Post, ): Promise { let form: CreatePostLike = { post_id: post.id, score: score, - auth: api.auth, }; - return api.client.likePost(form); + return api.likePost(form); } export async function createComment( - api: API, + api: LemmyHttp, post_id: number, parent_id?: number, content = "a jest test comment", @@ -477,76 +431,70 @@ export async function createComment( content, post_id, parent_id, - auth: api.auth, }; - return api.client.createComment(form); + return api.createComment(form); } export async function editComment( - api: API, + api: LemmyHttp, comment_id: number, content = "A jest test federated comment update", ): Promise { let form: EditComment = { content, comment_id, - auth: api.auth, }; - return api.client.editComment(form); + return api.editComment(form); } export async function deleteComment( - api: API, + api: LemmyHttp, deleted: boolean, comment_id: number, ): Promise { let form: DeleteComment = { comment_id, deleted, - auth: api.auth, }; - return api.client.deleteComment(form); + return api.deleteComment(form); } export async function removeComment( - api: API, + api: LemmyHttp, removed: boolean, comment_id: number, ): Promise { let form: RemoveComment = { comment_id, removed, - auth: api.auth, }; - return api.client.removeComment(form); + return api.removeComment(form); } export async function getMentions( - api: API, + api: LemmyHttp, ): Promise { let form: GetPersonMentions = { sort: "New", unread_only: false, - auth: api.auth, }; - return api.client.getPersonMentions(form); + return api.getPersonMentions(form); } export async function likeComment( - api: API, + api: LemmyHttp, score: number, comment: Comment, ): Promise { let form: CreateCommentLike = { comment_id: comment.id, score, - auth: api.auth, }; - return api.client.likeComment(form); + return api.likeComment(form); } export async function createCommunity( - api: API, + api: LemmyHttp, name_: string = randomString(5), ): Promise { let description = "a sample description"; @@ -554,100 +502,92 @@ export async function createCommunity( name: name_, title: name_, description, - auth: api.auth, }; - return api.client.createCommunity(form); + return api.createCommunity(form); } export async function getCommunity( - api: API, + api: LemmyHttp, id: number, ): Promise { let form: GetCommunity = { id, - auth: api.auth, }; - return api.client.getCommunity(form); + return api.getCommunity(form); } export async function getCommunityByName( - api: API, + api: LemmyHttp, name: string, ): Promise { let form: GetCommunity = { name, - auth: api.auth, }; - return api.client.getCommunity(form); + return api.getCommunity(form); } export async function deleteCommunity( - api: API, + api: LemmyHttp, deleted: boolean, community_id: number, ): Promise { let form: DeleteCommunity = { community_id, deleted, - auth: api.auth, }; - return api.client.deleteCommunity(form); + return api.deleteCommunity(form); } export async function removeCommunity( - api: API, + api: LemmyHttp, removed: boolean, community_id: number, ): Promise { let form: RemoveCommunity = { community_id, removed, - auth: api.auth, }; - return api.client.removeCommunity(form); + return api.removeCommunity(form); } export async function createPrivateMessage( - api: API, + api: LemmyHttp, recipient_id: number, ): Promise { let content = "A jest test federated private message"; let form: CreatePrivateMessage = { content, recipient_id, - auth: api.auth, }; - return api.client.createPrivateMessage(form); + return api.createPrivateMessage(form); } export async function editPrivateMessage( - api: API, + api: LemmyHttp, private_message_id: number, ): Promise { let updatedContent = "A jest test federated private message edited"; let form: EditPrivateMessage = { content: updatedContent, private_message_id, - auth: api.auth, }; - return api.client.editPrivateMessage(form); + return api.editPrivateMessage(form); } export async function deletePrivateMessage( - api: API, + api: LemmyHttp, deleted: boolean, private_message_id: number, ): Promise { let form: DeletePrivateMessage = { deleted, private_message_id, - auth: api.auth, }; - return api.client.deletePrivateMessage(form); + return api.deletePrivateMessage(form); } export async function registerUser( - api: API, + api: LemmyHttp, username: string = randomString(5), ): Promise { let form: Register = { @@ -656,10 +596,12 @@ export async function registerUser( password_verify: password, show_nsfw: true, }; - return api.client.register(form); + return api.register(form); } -export async function saveUserSettingsBio(api: API): Promise { +export async function saveUserSettingsBio( + api: LemmyHttp, +): Promise { let form: SaveUserSettings = { show_nsfw: true, blur_nsfw: false, @@ -671,13 +613,12 @@ export async function saveUserSettingsBio(api: API): Promise { show_avatars: true, send_notifications_to_email: false, bio: "a changed bio", - auth: api.auth, }; return saveUserSettings(api, form); } export async function saveUserSettingsFederated( - api: API, + api: LemmyHttp, ): Promise { let avatar = "https://image.flaticon.com/icons/png/512/35/35896.png"; let banner = "https://image.flaticon.com/icons/png/512/36/35896.png"; @@ -695,55 +636,52 @@ export async function saveUserSettingsFederated( show_avatars: false, send_notifications_to_email: false, bio, - auth: api.auth, }; - return await saveUserSettings(alpha, form); + return await saveUserSettings(api, form); } export async function saveUserSettings( - api: API, + api: LemmyHttp, form: SaveUserSettings, ): Promise { - return api.client.saveUserSettings(form); + return api.saveUserSettings(form); } export async function getPersonDetails( - api: API, + api: LemmyHttp, person_id: number, ): Promise { let form: GetPersonDetails = { - auth: api.auth, person_id: person_id, }; - return api.client.getPersonDetails(form); + return api.getPersonDetails(form); } -export async function deleteUser(api: API): Promise { +export async function deleteUser( + api: LemmyHttp, +): Promise { let form: DeleteAccount = { - auth: api.auth, delete_content: true, password, }; - return api.client.deleteAccount(form); + return api.deleteAccount(form); } -export async function getSite(api: API): Promise { - let form: GetSite = { - auth: api.auth, - }; - return api.client.getSite(form); +export async function getSite(api: LemmyHttp): Promise { + return api.getSite(); } export async function listPrivateMessages( - api: API, + api: LemmyHttp, ): Promise { let form: GetPrivateMessages = { - auth: api.auth, unread_only: false, }; - return api.client.getPrivateMessages(form); + return api.getPrivateMessages(form); } -export async function unfollowRemotes(api: API): Promise { +export async function unfollowRemotes( + api: LemmyHttp, +): Promise { // Unfollow all remote communities let site = await getSite(api); let remoteFollowed = @@ -755,7 +693,7 @@ export async function unfollowRemotes(api: API): Promise { return siteRes; } -export async function followBeta(api: API): Promise { +export async function followBeta(api: LemmyHttp): Promise { let betaCommunity = (await resolveBetaCommunity(api)).community; if (betaCommunity) { let follow = await followCommunity(api, true, betaCommunity.community.id); @@ -766,71 +704,63 @@ export async function followBeta(api: API): Promise { } export async function reportPost( - api: API, + api: LemmyHttp, post_id: number, reason: string, ): Promise { let form: CreatePostReport = { post_id, reason, - auth: api.auth, }; - return api.client.createPostReport(form); + return api.createPostReport(form); } export async function listPostReports( - api: API, + api: LemmyHttp, ): Promise { - let form: ListPostReports = { - auth: api.auth, - }; - return api.client.listPostReports(form); + let form: ListPostReports = {}; + return api.listPostReports(form); } export async function reportComment( - api: API, + api: LemmyHttp, comment_id: number, reason: string, ): Promise { let form: CreateCommentReport = { comment_id, reason, - auth: api.auth, }; - return api.client.createCommentReport(form); + return api.createCommentReport(form); } export async function listCommentReports( - api: API, + api: LemmyHttp, ): Promise { - let form: ListCommentReports = { - auth: api.auth, - }; - return api.client.listCommentReports(form); + let form: ListCommentReports = {}; + return api.listCommentReports(form); } export function getPosts( - api: API, + api: LemmyHttp, listingType?: ListingType, ): Promise { let form: GetPosts = { - auth: api.auth, type_: listingType, }; - return api.client.getPosts(form); + return api.getPosts(form); } export function blockInstance( - api: API, + api: LemmyHttp, instance_id: InstanceId, block: boolean, ): Promise { let form: BlockInstance = { instance_id, block, - auth: api.auth, }; - return api.client.blockInstance(form); + return api.blockInstance(form); } export function delay(millis = 500) { diff --git a/api_tests/src/user.spec.ts b/api_tests/src/user.spec.ts index f488ebe1e..e679e8053 100644 --- a/api_tests/src/user.spec.ts +++ b/api_tests/src/user.spec.ts @@ -13,10 +13,10 @@ import { resolveBetaCommunity, deleteUser, resolvePost, - API, resolveComment, saveUserSettingsFederated, setupLogins, + alphaUrl, } from "./shared"; import { LemmyHttp } from "lemmy-js-client"; import { GetPosts } from "lemmy-js-client/dist/types/GetPosts"; @@ -40,9 +40,11 @@ function assertUserFederation(userOne?: PersonView, userTwo?: PersonView) { test("Create user", async () => { let userRes = await registerUser(alpha); expect(userRes.jwt).toBeDefined(); - alpha.auth = userRes.jwt ?? ""; + let user = new LemmyHttp(alphaUrl, { + headers: { auth: userRes.jwt ?? "" }, + }); - let site = await getSite(alpha); + let site = await getSite(user); expect(site.my_user).toBeDefined(); if (!site.my_user) { throw "Missing site user"; @@ -60,10 +62,9 @@ test("Set some user settings, check that they are federated", async () => { test("Delete user", async () => { let userRes = await registerUser(alpha); expect(userRes.jwt).toBeDefined(); - let user: API = { - client: alpha.client, - auth: userRes.jwt ?? "", - }; + let user = new LemmyHttp(alphaUrl, { + headers: { auth: userRes.jwt ?? "" }, + }); // make a local post and comment let alphaCommunity = (await resolveCommunity(user, "!main@lemmy-alpha:8541")) @@ -107,17 +108,14 @@ test("Delete user", async () => { }); test("Requests with invalid auth should be treated as unauthenticated", async () => { - let invalid_auth: API = { - client: new LemmyHttp("http://127.0.0.1:8541"), - auth: "invalid", - }; + let invalid_auth = new LemmyHttp(alphaUrl, { + headers: { auth: "" }, + }); let site = await getSite(invalid_auth); expect(site.my_user).toBeUndefined(); expect(site.site_view).toBeDefined(); - let form: GetPosts = { - auth: "invalid", - }; - let posts = invalid_auth.client.getPosts(form); + let form: GetPosts = {}; + let posts = invalid_auth.getPosts(form); expect((await posts).posts).toBeDefined(); }); diff --git a/api_tests/yarn.lock b/api_tests/yarn.lock index 3b6a85146..eb9859b8d 100644 --- a/api_tests/yarn.lock +++ b/api_tests/yarn.lock @@ -2174,10 +2174,10 @@ kleur@^3.0.3: resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== -lemmy-js-client@0.19.0-rc.5: - version "0.19.0-rc.5" - resolved "https://registry.yarnpkg.com/lemmy-js-client/-/lemmy-js-client-0.19.0-rc.5.tgz#a0d3e0ac829b1e46124edcf3a0343ae04317d51a" - integrity sha512-Z1T95Ht1VZNvWlLH9XpVnO2oC7LhMT81jTiU5BhYPIkEtGhOwN91jk5uI1oyI6/d4v9lwbrsyzFYPsiuMmXTFQ== +lemmy-js-client@0.19.0-rc.12: + version "0.19.0-rc.12" + resolved "https://registry.yarnpkg.com/lemmy-js-client/-/lemmy-js-client-0.19.0-rc.12.tgz#e3bd4e21b1966d583ab790ef70ece8394b012b48" + integrity sha512-1iu2fW9vlb3TrI+QR/ODP3+5pWZB0rUqL1wH09IzomDXohCqoQvfmXpwArmgF4Eq8GZgjkcfeMDC2gMrfw/i7Q== dependencies: cross-fetch "^3.1.5" form-data "^4.0.0" diff --git a/crates/api/src/comment/distinguish.rs b/crates/api/src/comment/distinguish.rs index a378e51b9..5059e2db7 100644 --- a/crates/api/src/comment/distinguish.rs +++ b/crates/api/src/comment/distinguish.rs @@ -2,22 +2,21 @@ use actix_web::web::{Data, Json}; use lemmy_api_common::{ comment::{CommentResponse, DistinguishComment}, context::LemmyContext, - utils::{check_community_ban, is_mod_or_admin, local_user_view_from_jwt}, + utils::{check_community_ban, is_mod_or_admin}, }; use lemmy_db_schema::{ source::comment::{Comment, CommentUpdateForm}, traits::Crud, }; -use lemmy_db_views::structs::CommentView; +use lemmy_db_views::structs::{CommentView, LocalUserView}; use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType}; #[tracing::instrument(skip(context))] pub async fn distinguish_comment( data: Json, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; - let orig_comment = CommentView::read(&mut context.pool(), data.comment_id, None).await?; check_community_ban( diff --git a/crates/api/src/comment/like.rs b/crates/api/src/comment/like.rs index af013f283..ee0a0bd7e 100644 --- a/crates/api/src/comment/like.rs +++ b/crates/api/src/comment/like.rs @@ -5,7 +5,7 @@ use lemmy_api_common::{ comment::{CommentResponse, CreateCommentLike}, context::LemmyContext, send_activity::{ActivityChannel, SendActivityData}, - utils::{check_community_ban, check_downvotes_enabled, local_user_view_from_jwt}, + utils::{check_community_ban, check_downvotes_enabled}, }; use lemmy_db_schema::{ newtypes::LocalUserId, @@ -24,9 +24,9 @@ use std::ops::Deref; pub async fn like_comment( data: Json, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { let local_site = LocalSite::read(&mut context.pool()).await?; - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; let mut recipient_ids = Vec::::new(); diff --git a/crates/api/src/comment/save.rs b/crates/api/src/comment/save.rs index f2c926f17..95c08e701 100644 --- a/crates/api/src/comment/save.rs +++ b/crates/api/src/comment/save.rs @@ -2,22 +2,20 @@ use actix_web::web::{Data, Json}; use lemmy_api_common::{ comment::{CommentResponse, SaveComment}, context::LemmyContext, - utils::local_user_view_from_jwt, }; use lemmy_db_schema::{ source::comment::{CommentSaved, CommentSavedForm}, traits::Saveable, }; -use lemmy_db_views::structs::CommentView; +use lemmy_db_views::structs::{CommentView, LocalUserView}; use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType}; #[tracing::instrument(skip(context))] pub async fn save_comment( data: Json, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; - let comment_saved_form = CommentSavedForm { comment_id: data.comment_id, person_id: local_user_view.person.id, diff --git a/crates/api/src/comment_report/create.rs b/crates/api/src/comment_report/create.rs index e493d60a3..3c1304674 100644 --- a/crates/api/src/comment_report/create.rs +++ b/crates/api/src/comment_report/create.rs @@ -5,12 +5,7 @@ use lemmy_api_common::{ comment::{CommentReportResponse, CreateCommentReport}, context::LemmyContext, send_activity::{ActivityChannel, SendActivityData}, - utils::{ - check_community_ban, - local_user_view_from_jwt, - sanitize_html_api, - send_new_report_email_to_admins, - }, + utils::{check_community_ban, sanitize_html_api, send_new_report_email_to_admins}, }; use lemmy_db_schema::{ source::{ @@ -19,7 +14,7 @@ use lemmy_db_schema::{ }, traits::Reportable, }; -use lemmy_db_views::structs::{CommentReportView, CommentView}; +use lemmy_db_views::structs::{CommentReportView, CommentView, LocalUserView}; use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType}; /// Creates a comment report and notifies the moderators of the community @@ -27,8 +22,8 @@ use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType}; pub async fn create_comment_report( data: Json, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; let local_site = LocalSite::read(&mut context.pool()).await?; let reason = sanitize_html_api(data.reason.trim()); diff --git a/crates/api/src/comment_report/list.rs b/crates/api/src/comment_report/list.rs index 839288521..bc8dd2677 100644 --- a/crates/api/src/comment_report/list.rs +++ b/crates/api/src/comment_report/list.rs @@ -2,9 +2,8 @@ use actix_web::web::{Data, Json, Query}; use lemmy_api_common::{ comment::{ListCommentReports, ListCommentReportsResponse}, context::LemmyContext, - utils::local_user_view_from_jwt, }; -use lemmy_db_views::comment_report_view::CommentReportQuery; +use lemmy_db_views::{comment_report_view::CommentReportQuery, structs::LocalUserView}; use lemmy_utils::error::LemmyError; /// Lists comment reports for a community if an id is supplied @@ -13,9 +12,8 @@ use lemmy_utils::error::LemmyError; pub async fn list_comment_reports( data: Query, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; - let community_id = data.community_id; let unresolved_only = data.unresolved_only.unwrap_or_default(); diff --git a/crates/api/src/comment_report/resolve.rs b/crates/api/src/comment_report/resolve.rs index 8e03484e8..8296f068b 100644 --- a/crates/api/src/comment_report/resolve.rs +++ b/crates/api/src/comment_report/resolve.rs @@ -2,10 +2,10 @@ use actix_web::web::{Data, Json}; use lemmy_api_common::{ comment::{CommentReportResponse, ResolveCommentReport}, context::LemmyContext, - utils::{is_mod_or_admin, local_user_view_from_jwt}, + utils::is_mod_or_admin, }; use lemmy_db_schema::{source::comment_report::CommentReport, traits::Reportable}; -use lemmy_db_views::structs::CommentReportView; +use lemmy_db_views::structs::{CommentReportView, LocalUserView}; use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType}; /// Resolves or unresolves a comment report and notifies the moderators of the community @@ -13,9 +13,8 @@ use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType}; pub async fn resolve_comment_report( data: Json, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; - let report_id = data.report_id; let person_id = local_user_view.person.id; let report = CommentReportView::read(&mut context.pool(), report_id, person_id).await?; diff --git a/crates/api/src/community/add_mod.rs b/crates/api/src/community/add_mod.rs index f5fac1503..e08686361 100644 --- a/crates/api/src/community/add_mod.rs +++ b/crates/api/src/community/add_mod.rs @@ -4,7 +4,7 @@ use lemmy_api_common::{ community::{AddModToCommunity, AddModToCommunityResponse}, context::LemmyContext, send_activity::{ActivityChannel, SendActivityData}, - utils::{is_mod_or_admin, local_user_view_from_jwt}, + utils::is_mod_or_admin, }; use lemmy_db_schema::{ source::{ @@ -13,6 +13,7 @@ use lemmy_db_schema::{ }, traits::{Crud, Joinable}, }; +use lemmy_db_views::structs::LocalUserView; use lemmy_db_views_actor::structs::CommunityModeratorView; use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType}; @@ -20,9 +21,8 @@ use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType}; pub async fn add_mod_to_community( data: Json, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; - let community_id = data.community_id; // Verify that only mods or admins can add mod diff --git a/crates/api/src/community/ban.rs b/crates/api/src/community/ban.rs index e969e9b78..c2f70b7c0 100644 --- a/crates/api/src/community/ban.rs +++ b/crates/api/src/community/ban.rs @@ -4,12 +4,7 @@ use lemmy_api_common::{ community::{BanFromCommunity, BanFromCommunityResponse}, context::LemmyContext, send_activity::{ActivityChannel, SendActivityData}, - utils::{ - is_mod_or_admin, - local_user_view_from_jwt, - remove_user_data_in_community, - sanitize_html_api_opt, - }, + utils::{is_mod_or_admin, remove_user_data_in_community, sanitize_html_api_opt}, }; use lemmy_db_schema::{ source::{ @@ -23,6 +18,7 @@ use lemmy_db_schema::{ }, traits::{Bannable, Crud, Followable}, }; +use lemmy_db_views::structs::LocalUserView; use lemmy_db_views_actor::structs::PersonView; use lemmy_utils::{ error::{LemmyError, LemmyErrorExt, LemmyErrorType}, @@ -33,9 +29,8 @@ use lemmy_utils::{ pub async fn ban_from_community( data: Json, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; - let banned_person_id = data.person_id; let remove_data = data.remove_data.unwrap_or(false); let expires = data.expires.map(naive_from_unix); diff --git a/crates/api/src/community/block.rs b/crates/api/src/community/block.rs index f27b7c01b..fd4a5a01b 100644 --- a/crates/api/src/community/block.rs +++ b/crates/api/src/community/block.rs @@ -4,7 +4,6 @@ use lemmy_api_common::{ community::{BlockCommunity, BlockCommunityResponse}, context::LemmyContext, send_activity::{ActivityChannel, SendActivityData}, - utils::local_user_view_from_jwt, }; use lemmy_db_schema::{ source::{ @@ -13,6 +12,7 @@ use lemmy_db_schema::{ }, traits::{Blockable, Followable}, }; +use lemmy_db_views::structs::LocalUserView; use lemmy_db_views_actor::structs::CommunityView; use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType}; @@ -20,9 +20,8 @@ use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType}; pub async fn block_community( data: Json, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; - let community_id = data.community_id; let person_id = local_user_view.person.id; let community_block_form = CommunityBlockForm { diff --git a/crates/api/src/community/follow.rs b/crates/api/src/community/follow.rs index 2a50a94ed..91ffce714 100644 --- a/crates/api/src/community/follow.rs +++ b/crates/api/src/community/follow.rs @@ -4,7 +4,7 @@ use lemmy_api_common::{ community::{CommunityResponse, FollowCommunity}, context::LemmyContext, send_activity::{ActivityChannel, SendActivityData}, - utils::{check_community_ban, check_community_deleted_or_removed, local_user_view_from_jwt}, + utils::{check_community_ban, check_community_deleted_or_removed}, }; use lemmy_db_schema::{ source::{ @@ -13,6 +13,7 @@ use lemmy_db_schema::{ }, traits::{Crud, Followable}, }; +use lemmy_db_views::structs::LocalUserView; use lemmy_db_views_actor::structs::CommunityView; use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType}; @@ -20,9 +21,8 @@ use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType}; pub async fn follow_community( data: Json, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; - let community = Community::read(&mut context.pool(), data.community_id).await?; let mut community_follower_form = CommunityFollowerForm { community_id: community.id, diff --git a/crates/api/src/community/hide.rs b/crates/api/src/community/hide.rs index 8fd270181..5f2b9d6fb 100644 --- a/crates/api/src/community/hide.rs +++ b/crates/api/src/community/hide.rs @@ -5,7 +5,7 @@ use lemmy_api_common::{ community::{CommunityResponse, HideCommunity}, context::LemmyContext, send_activity::{ActivityChannel, SendActivityData}, - utils::{is_admin, local_user_view_from_jwt, sanitize_html_api_opt}, + utils::{is_admin, sanitize_html_api_opt}, }; use lemmy_db_schema::{ source::{ @@ -14,15 +14,16 @@ use lemmy_db_schema::{ }, traits::Crud, }; +use lemmy_db_views::structs::LocalUserView; use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType}; #[tracing::instrument(skip(context))] pub async fn hide_community( data: Json, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { // Verify its a admin (only admin can hide or unhide it) - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; is_admin(&local_user_view)?; let community_form = CommunityUpdateForm { diff --git a/crates/api/src/community/transfer.rs b/crates/api/src/community/transfer.rs index 1dc5a96e0..fd2e293f8 100644 --- a/crates/api/src/community/transfer.rs +++ b/crates/api/src/community/transfer.rs @@ -3,7 +3,7 @@ use anyhow::Context; use lemmy_api_common::{ community::{GetCommunityResponse, TransferCommunity}, context::LemmyContext, - utils::{is_admin, is_top_mod, local_user_view_from_jwt}, + utils::{is_admin, is_top_mod}, }; use lemmy_db_schema::{ source::{ @@ -12,6 +12,7 @@ use lemmy_db_schema::{ }, traits::{Crud, Joinable}, }; +use lemmy_db_views::structs::LocalUserView; use lemmy_db_views_actor::structs::{CommunityModeratorView, CommunityView}; use lemmy_utils::{ error::{LemmyError, LemmyErrorExt, LemmyErrorType}, @@ -24,9 +25,8 @@ use lemmy_utils::{ pub async fn transfer_community( data: Json, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; - // Fetch the community mods let community_id = data.community_id; let mut community_mods = diff --git a/crates/api/src/lib.rs b/crates/api/src/lib.rs index 22a021970..04df09308 100644 --- a/crates/api/src/lib.rs +++ b/crates/api/src/lib.rs @@ -126,68 +126,6 @@ mod tests { #![allow(clippy::indexing_slicing)] use super::*; - use lemmy_api_common::utils::check_validator_time; - use lemmy_db_schema::{ - source::{ - instance::Instance, - local_user::{LocalUser, LocalUserInsertForm}, - person::{Person, PersonInsertForm}, - secret::Secret, - }, - traits::Crud, - utils::build_db_pool_for_tests, - }; - use lemmy_utils::{claims::Claims, settings::SETTINGS}; - use serial_test::serial; - - #[tokio::test] - #[serial] - async fn test_should_not_validate_user_token_after_password_change() { - let pool = &build_db_pool_for_tests().await; - let pool = &mut pool.into(); - let secret = Secret::init(pool).await.unwrap(); - let settings = &SETTINGS.to_owned(); - - let inserted_instance = Instance::read_or_create(pool, "my_domain.tld".to_string()) - .await - .unwrap(); - - let new_person = PersonInsertForm::builder() - .name("Gerry9812".into()) - .public_key("pubkey".to_string()) - .instance_id(inserted_instance.id) - .build(); - - let inserted_person = Person::create(pool, &new_person).await.unwrap(); - - let local_user_form = LocalUserInsertForm::builder() - .person_id(inserted_person.id) - .password_encrypted("123456".to_string()) - .build(); - - let inserted_local_user = LocalUser::create(pool, &local_user_form).await.unwrap(); - - let jwt = Claims::jwt( - inserted_local_user.id.0, - &secret.jwt_secret, - &settings.hostname, - ) - .unwrap(); - let claims = Claims::decode(&jwt, &secret.jwt_secret).unwrap().claims; - let check = check_validator_time(&inserted_local_user.validator_time, &claims); - assert!(check.is_ok()); - - // The check should fail, since the validator time is now newer than the jwt issue time - let updated_local_user = - LocalUser::update_password(pool, inserted_local_user.id, "password111") - .await - .unwrap(); - let check_after = check_validator_time(&updated_local_user.validator_time, &claims); - assert!(check_after.is_err()); - - let num_deleted = Person::delete(pool, inserted_person.id).await.unwrap(); - assert_eq!(1, num_deleted); - } #[test] fn test_build_totp() { diff --git a/crates/api/src/local_user/add_admin.rs b/crates/api/src/local_user/add_admin.rs index 8e50147a4..502335876 100644 --- a/crates/api/src/local_user/add_admin.rs +++ b/crates/api/src/local_user/add_admin.rs @@ -2,7 +2,7 @@ use actix_web::web::{Data, Json}; use lemmy_api_common::{ context::LemmyContext, person::{AddAdmin, AddAdminResponse}, - utils::{is_admin, local_user_view_from_jwt}, + utils::is_admin, }; use lemmy_db_schema::{ source::{ @@ -19,9 +19,8 @@ use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType}; pub async fn add_admin( data: Json, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; - // Make sure user is an admin is_admin(&local_user_view)?; diff --git a/crates/api/src/local_user/ban_person.rs b/crates/api/src/local_user/ban_person.rs index 3a83d6c6e..ecc09220d 100644 --- a/crates/api/src/local_user/ban_person.rs +++ b/crates/api/src/local_user/ban_person.rs @@ -4,7 +4,7 @@ use lemmy_api_common::{ context::LemmyContext, person::{BanPerson, BanPersonResponse}, send_activity::{ActivityChannel, SendActivityData}, - utils::{is_admin, local_user_view_from_jwt, remove_user_data, sanitize_html_api_opt}, + utils::{is_admin, remove_user_data, sanitize_html_api_opt}, }; use lemmy_db_schema::{ source::{ @@ -13,6 +13,7 @@ use lemmy_db_schema::{ }, traits::Crud, }; +use lemmy_db_views::structs::LocalUserView; use lemmy_db_views_actor::structs::PersonView; use lemmy_utils::{ error::{LemmyError, LemmyErrorExt, LemmyErrorType}, @@ -22,9 +23,8 @@ use lemmy_utils::{ pub async fn ban_from_site( data: Json, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; - // Make sure user is an admin is_admin(&local_user_view)?; diff --git a/crates/api/src/local_user/block.rs b/crates/api/src/local_user/block.rs index 77a23aef3..cb345616b 100644 --- a/crates/api/src/local_user/block.rs +++ b/crates/api/src/local_user/block.rs @@ -2,7 +2,6 @@ use actix_web::web::{Data, Json}; use lemmy_api_common::{ context::LemmyContext, person::{BlockPerson, BlockPersonResponse}, - utils::local_user_view_from_jwt, }; use lemmy_db_schema::{ source::person_block::{PersonBlock, PersonBlockForm}, @@ -16,9 +15,8 @@ use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType}; pub async fn block_person( data: Json, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; - let target_id = data.person_id; let person_id = local_user_view.person.id; diff --git a/crates/api/src/local_user/change_password.rs b/crates/api/src/local_user/change_password.rs index 532c8ed7c..9b491d821 100644 --- a/crates/api/src/local_user/change_password.rs +++ b/crates/api/src/local_user/change_password.rs @@ -3,9 +3,10 @@ use bcrypt::verify; use lemmy_api_common::{ context::LemmyContext, person::{ChangePassword, LoginResponse}, - utils::{local_user_view_from_jwt, password_length_check}, + utils::password_length_check, }; use lemmy_db_schema::source::local_user::LocalUser; +use lemmy_db_views::structs::LocalUserView; use lemmy_utils::{ claims::Claims, error::{LemmyError, LemmyErrorType}, @@ -15,9 +16,8 @@ use lemmy_utils::{ pub async fn change_password( data: Json, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(data.auth.as_ref(), &context).await?; - password_length_check(&data.new_password)?; // Make sure passwords match diff --git a/crates/api/src/local_user/list_banned.rs b/crates/api/src/local_user/list_banned.rs index c4c0a98ae..5c76d89a8 100644 --- a/crates/api/src/local_user/list_banned.rs +++ b/crates/api/src/local_user/list_banned.rs @@ -1,18 +1,13 @@ -use actix_web::web::{Data, Json, Query}; -use lemmy_api_common::{ - context::LemmyContext, - person::{BannedPersonsResponse, GetBannedPersons}, - utils::{is_admin, local_user_view_from_jwt}, -}; +use actix_web::web::{Data, Json}; +use lemmy_api_common::{context::LemmyContext, person::BannedPersonsResponse, utils::is_admin}; +use lemmy_db_views::structs::LocalUserView; use lemmy_db_views_actor::structs::PersonView; use lemmy_utils::error::LemmyError; pub async fn list_banned_users( - data: Query, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; - // Make sure user is an admin is_admin(&local_user_view)?; diff --git a/crates/api/src/local_user/login.rs b/crates/api/src/local_user/login.rs index 5dd3e29d8..11a5c6b01 100644 --- a/crates/api/src/local_user/login.rs +++ b/crates/api/src/local_user/login.rs @@ -4,7 +4,13 @@ use bcrypt::verify; use lemmy_api_common::{ context::LemmyContext, person::{Login, LoginResponse}, - utils::{check_registration_application, check_user_valid}, + utils, + utils::check_user_valid, +}; +use lemmy_db_schema::{ + source::{local_site::LocalSite, registration_application::RegistrationApplication}, + utils::DbPool, + RegistrationMode, }; use lemmy_db_views::structs::{LocalUserView, SiteView}; use lemmy_utils::{ @@ -72,3 +78,29 @@ pub async fn login( registration_created: false, })) } + +async fn check_registration_application( + local_user_view: &LocalUserView, + local_site: &LocalSite, + pool: &mut DbPool<'_>, +) -> Result<(), LemmyError> { + if (local_site.registration_mode == RegistrationMode::RequireApplication + || local_site.registration_mode == RegistrationMode::Closed) + && !local_user_view.local_user.accepted_application + && !local_user_view.local_user.admin + { + // Fetch the registration, see if its denied + let local_user_id = local_user_view.local_user.id; + let registration = RegistrationApplication::find_by_local_user_id(pool, local_user_id).await?; + if let Some(deny_reason) = registration.deny_reason { + let lang = utils::get_interface_language(local_user_view); + let registration_denied_message = format!("{}: {}", lang.registration_denied(), deny_reason); + Err(LemmyErrorType::RegistrationDenied( + registration_denied_message, + ))? + } else { + Err(LemmyErrorType::RegistrationApplicationIsPending)? + } + } + Ok(()) +} diff --git a/crates/api/src/local_user/notifications/list_mentions.rs b/crates/api/src/local_user/notifications/list_mentions.rs index af32e31a8..9f9ee3ae8 100644 --- a/crates/api/src/local_user/notifications/list_mentions.rs +++ b/crates/api/src/local_user/notifications/list_mentions.rs @@ -2,8 +2,8 @@ use actix_web::web::{Data, Json, Query}; use lemmy_api_common::{ context::LemmyContext, person::{GetPersonMentions, GetPersonMentionsResponse}, - utils::local_user_view_from_jwt, }; +use lemmy_db_views::structs::LocalUserView; use lemmy_db_views_actor::person_mention_view::PersonMentionQuery; use lemmy_utils::error::LemmyError; @@ -11,9 +11,8 @@ use lemmy_utils::error::LemmyError; pub async fn list_mentions( data: Query, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; - let sort = data.sort; let page = data.page; let limit = data.limit; diff --git a/crates/api/src/local_user/notifications/list_replies.rs b/crates/api/src/local_user/notifications/list_replies.rs index 8a7658d72..555989721 100644 --- a/crates/api/src/local_user/notifications/list_replies.rs +++ b/crates/api/src/local_user/notifications/list_replies.rs @@ -2,8 +2,8 @@ use actix_web::web::{Data, Json, Query}; use lemmy_api_common::{ context::LemmyContext, person::{GetReplies, GetRepliesResponse}, - utils::local_user_view_from_jwt, }; +use lemmy_db_views::structs::LocalUserView; use lemmy_db_views_actor::comment_reply_view::CommentReplyQuery; use lemmy_utils::error::LemmyError; @@ -11,9 +11,8 @@ use lemmy_utils::error::LemmyError; pub async fn list_replies( data: Query, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; - let sort = data.sort; let page = data.page; let limit = data.limit; diff --git a/crates/api/src/local_user/notifications/mark_all_read.rs b/crates/api/src/local_user/notifications/mark_all_read.rs index a38b23c53..d3667460b 100644 --- a/crates/api/src/local_user/notifications/mark_all_read.rs +++ b/crates/api/src/local_user/notifications/mark_all_read.rs @@ -1,22 +1,18 @@ use actix_web::web::{Data, Json}; -use lemmy_api_common::{ - context::LemmyContext, - person::{GetRepliesResponse, MarkAllAsRead}, - utils::local_user_view_from_jwt, -}; +use lemmy_api_common::{context::LemmyContext, person::GetRepliesResponse}; use lemmy_db_schema::source::{ comment_reply::CommentReply, person_mention::PersonMention, private_message::PrivateMessage, }; +use lemmy_db_views::structs::LocalUserView; use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType}; #[tracing::instrument(skip(context))] pub async fn mark_all_notifications_read( - data: Json, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; let person_id = local_user_view.person.id; // Mark all comment_replies as read diff --git a/crates/api/src/local_user/notifications/mark_mention_read.rs b/crates/api/src/local_user/notifications/mark_mention_read.rs index f4529015d..4cce598ac 100644 --- a/crates/api/src/local_user/notifications/mark_mention_read.rs +++ b/crates/api/src/local_user/notifications/mark_mention_read.rs @@ -2,12 +2,12 @@ use actix_web::web::{Data, Json}; use lemmy_api_common::{ context::LemmyContext, person::{MarkPersonMentionAsRead, PersonMentionResponse}, - utils::local_user_view_from_jwt, }; use lemmy_db_schema::{ source::person_mention::{PersonMention, PersonMentionUpdateForm}, traits::Crud, }; +use lemmy_db_views::structs::LocalUserView; use lemmy_db_views_actor::structs::PersonMentionView; use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType}; @@ -15,9 +15,8 @@ use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType}; pub async fn mark_person_mention_as_read( data: Json, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; - let person_mention_id = data.person_mention_id; let read_person_mention = PersonMention::read(&mut context.pool(), person_mention_id).await?; diff --git a/crates/api/src/local_user/notifications/mark_reply_read.rs b/crates/api/src/local_user/notifications/mark_reply_read.rs index 4439a6cfb..f7b259c94 100644 --- a/crates/api/src/local_user/notifications/mark_reply_read.rs +++ b/crates/api/src/local_user/notifications/mark_reply_read.rs @@ -2,12 +2,12 @@ use actix_web::web::{Data, Json}; use lemmy_api_common::{ context::LemmyContext, person::{CommentReplyResponse, MarkCommentReplyAsRead}, - utils::local_user_view_from_jwt, }; use lemmy_db_schema::{ source::comment_reply::{CommentReply, CommentReplyUpdateForm}, traits::Crud, }; +use lemmy_db_views::structs::LocalUserView; use lemmy_db_views_actor::structs::CommentReplyView; use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType}; @@ -15,9 +15,8 @@ use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType}; pub async fn mark_reply_as_read( data: Json, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; - let comment_reply_id = data.comment_reply_id; let read_comment_reply = CommentReply::read(&mut context.pool(), comment_reply_id).await?; diff --git a/crates/api/src/local_user/notifications/unread_count.rs b/crates/api/src/local_user/notifications/unread_count.rs index 0315609dd..c0b1f0f2e 100644 --- a/crates/api/src/local_user/notifications/unread_count.rs +++ b/crates/api/src/local_user/notifications/unread_count.rs @@ -1,20 +1,14 @@ -use actix_web::web::{Data, Json, Query}; -use lemmy_api_common::{ - context::LemmyContext, - person::{GetUnreadCount, GetUnreadCountResponse}, - utils::local_user_view_from_jwt, -}; -use lemmy_db_views::structs::PrivateMessageView; +use actix_web::web::{Data, Json}; +use lemmy_api_common::{context::LemmyContext, person::GetUnreadCountResponse}; +use lemmy_db_views::structs::{LocalUserView, PrivateMessageView}; use lemmy_db_views_actor::structs::{CommentReplyView, PersonMentionView}; use lemmy_utils::error::LemmyError; #[tracing::instrument(skip(context))] pub async fn unread_count( - data: Query, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; - let person_id = local_user_view.person.id; let replies = CommentReplyView::get_unread_replies(&mut context.pool(), person_id).await?; diff --git a/crates/api/src/local_user/report_count.rs b/crates/api/src/local_user/report_count.rs index 08be9c948..3bfa1559b 100644 --- a/crates/api/src/local_user/report_count.rs +++ b/crates/api/src/local_user/report_count.rs @@ -2,18 +2,21 @@ use actix_web::web::{Data, Json}; use lemmy_api_common::{ context::LemmyContext, person::{GetReportCount, GetReportCountResponse}, - utils::local_user_view_from_jwt, }; -use lemmy_db_views::structs::{CommentReportView, PostReportView, PrivateMessageReportView}; +use lemmy_db_views::structs::{ + CommentReportView, + LocalUserView, + PostReportView, + PrivateMessageReportView, +}; use lemmy_utils::error::LemmyError; #[tracing::instrument(skip(context))] pub async fn report_count( data: Json, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; - let person_id = local_user_view.person.id; let admin = local_user_view.local_user.admin; let community_id = data.community_id; diff --git a/crates/api/src/local_user/save_settings.rs b/crates/api/src/local_user/save_settings.rs index 045a3c2f7..7d3b675f6 100644 --- a/crates/api/src/local_user/save_settings.rs +++ b/crates/api/src/local_user/save_settings.rs @@ -2,7 +2,7 @@ use actix_web::web::{Data, Json}; use lemmy_api_common::{ context::LemmyContext, person::{LoginResponse, SaveUserSettings}, - utils::{local_user_view_from_jwt, sanitize_html_api_opt, send_verification_email}, + utils::{sanitize_html_api_opt, send_verification_email}, }; use lemmy_db_schema::{ source::{ @@ -13,7 +13,7 @@ use lemmy_db_schema::{ traits::Crud, utils::{diesel_option_overwrite, diesel_option_overwrite_to_url}, }; -use lemmy_db_views::structs::SiteView; +use lemmy_db_views::structs::{LocalUserView, SiteView}; use lemmy_utils::{ claims::Claims, error::{LemmyError, LemmyErrorExt, LemmyErrorType}, @@ -24,8 +24,8 @@ use lemmy_utils::{ pub async fn save_user_settings( data: Json, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; let site_view = SiteView::read_local(&mut context.pool()).await?; let bio = sanitize_html_api_opt(&data.bio); diff --git a/crates/api/src/post/feature.rs b/crates/api/src/post/feature.rs index 02b9551a9..8c2d2fced 100644 --- a/crates/api/src/post/feature.rs +++ b/crates/api/src/post/feature.rs @@ -5,13 +5,7 @@ use lemmy_api_common::{ context::LemmyContext, post::{FeaturePost, PostResponse}, send_activity::{ActivityChannel, SendActivityData}, - utils::{ - check_community_ban, - check_community_deleted_or_removed, - is_admin, - is_mod_or_admin, - local_user_view_from_jwt, - }, + utils::{check_community_ban, check_community_deleted_or_removed, is_admin, is_mod_or_admin}, }; use lemmy_db_schema::{ source::{ @@ -21,15 +15,15 @@ use lemmy_db_schema::{ traits::Crud, PostFeatureType, }; +use lemmy_db_views::structs::LocalUserView; use lemmy_utils::error::LemmyError; #[tracing::instrument(skip(context))] pub async fn feature_post( data: Json, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; - let post_id = data.post_id; let orig_post = Post::read(&mut context.pool(), post_id).await?; diff --git a/crates/api/src/post/like.rs b/crates/api/src/post/like.rs index b9b2bede0..d4f9d644d 100644 --- a/crates/api/src/post/like.rs +++ b/crates/api/src/post/like.rs @@ -9,7 +9,6 @@ use lemmy_api_common::{ check_community_ban, check_community_deleted_or_removed, check_downvotes_enabled, - local_user_view_from_jwt, mark_post_as_read, }, }; @@ -21,6 +20,7 @@ use lemmy_db_schema::{ }, traits::{Crud, Likeable}, }; +use lemmy_db_views::structs::LocalUserView; use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType}; use std::ops::Deref; @@ -28,8 +28,8 @@ use std::ops::Deref; pub async fn like_post( data: Json, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; let local_site = LocalSite::read(&mut context.pool()).await?; // Don't do a downvote if site has downvotes disabled diff --git a/crates/api/src/post/lock.rs b/crates/api/src/post/lock.rs index b2ba9b3d1..ecd206156 100644 --- a/crates/api/src/post/lock.rs +++ b/crates/api/src/post/lock.rs @@ -5,12 +5,7 @@ use lemmy_api_common::{ context::LemmyContext, post::{LockPost, PostResponse}, send_activity::{ActivityChannel, SendActivityData}, - utils::{ - check_community_ban, - check_community_deleted_or_removed, - is_mod_or_admin, - local_user_view_from_jwt, - }, + utils::{check_community_ban, check_community_deleted_or_removed, is_mod_or_admin}, }; use lemmy_db_schema::{ source::{ @@ -19,15 +14,15 @@ use lemmy_db_schema::{ }, traits::Crud, }; +use lemmy_db_views::structs::LocalUserView; use lemmy_utils::error::LemmyError; #[tracing::instrument(skip(context))] pub async fn lock_post( data: Json, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; - let post_id = data.post_id; let orig_post = Post::read(&mut context.pool(), post_id).await?; diff --git a/crates/api/src/post/mark_read.rs b/crates/api/src/post/mark_read.rs index ecb1b3448..a248b0196 100644 --- a/crates/api/src/post/mark_read.rs +++ b/crates/api/src/post/mark_read.rs @@ -3,18 +3,16 @@ use lemmy_api_common::{ context::LemmyContext, post::{MarkPostAsRead, PostResponse}, utils, - utils::local_user_view_from_jwt, }; -use lemmy_db_views::structs::PostView; +use lemmy_db_views::structs::{LocalUserView, PostView}; use lemmy_utils::error::LemmyError; #[tracing::instrument(skip(context))] pub async fn mark_post_as_read( data: Json, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; - let post_id = data.post_id; let person_id = local_user_view.person.id; diff --git a/crates/api/src/post/save.rs b/crates/api/src/post/save.rs index ddad6ede4..164840770 100644 --- a/crates/api/src/post/save.rs +++ b/crates/api/src/post/save.rs @@ -2,22 +2,21 @@ use actix_web::web::{Data, Json}; use lemmy_api_common::{ context::LemmyContext, post::{PostResponse, SavePost}, - utils::{local_user_view_from_jwt, mark_post_as_read}, + utils::mark_post_as_read, }; use lemmy_db_schema::{ source::post::{PostSaved, PostSavedForm}, traits::Saveable, }; -use lemmy_db_views::structs::PostView; +use lemmy_db_views::structs::{LocalUserView, PostView}; use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType}; #[tracing::instrument(skip(context))] pub async fn save_post( data: Json, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; - let post_saved_form = PostSavedForm { post_id: data.post_id, person_id: local_user_view.person.id, diff --git a/crates/api/src/post_report/create.rs b/crates/api/src/post_report/create.rs index 8a5162a60..6a32d505b 100644 --- a/crates/api/src/post_report/create.rs +++ b/crates/api/src/post_report/create.rs @@ -5,12 +5,7 @@ use lemmy_api_common::{ context::LemmyContext, post::{CreatePostReport, PostReportResponse}, send_activity::{ActivityChannel, SendActivityData}, - utils::{ - check_community_ban, - local_user_view_from_jwt, - sanitize_html_api, - send_new_report_email_to_admins, - }, + utils::{check_community_ban, sanitize_html_api, send_new_report_email_to_admins}, }; use lemmy_db_schema::{ source::{ @@ -19,7 +14,7 @@ use lemmy_db_schema::{ }, traits::Reportable, }; -use lemmy_db_views::structs::{PostReportView, PostView}; +use lemmy_db_views::structs::{LocalUserView, PostReportView, PostView}; use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType}; /// Creates a post report and notifies the moderators of the community @@ -27,8 +22,8 @@ use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType}; pub async fn create_post_report( data: Json, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; let local_site = LocalSite::read(&mut context.pool()).await?; let reason = sanitize_html_api(data.reason.trim()); diff --git a/crates/api/src/post_report/list.rs b/crates/api/src/post_report/list.rs index e6509fe00..5cf2889ea 100644 --- a/crates/api/src/post_report/list.rs +++ b/crates/api/src/post_report/list.rs @@ -2,9 +2,8 @@ use actix_web::web::{Data, Json, Query}; use lemmy_api_common::{ context::LemmyContext, post::{ListPostReports, ListPostReportsResponse}, - utils::local_user_view_from_jwt, }; -use lemmy_db_views::post_report_view::PostReportQuery; +use lemmy_db_views::{post_report_view::PostReportQuery, structs::LocalUserView}; use lemmy_utils::error::LemmyError; /// Lists post reports for a community if an id is supplied @@ -13,9 +12,8 @@ use lemmy_utils::error::LemmyError; pub async fn list_post_reports( data: Query, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; - let community_id = data.community_id; let unresolved_only = data.unresolved_only.unwrap_or_default(); diff --git a/crates/api/src/post_report/resolve.rs b/crates/api/src/post_report/resolve.rs index 94e841e08..fe01c748c 100644 --- a/crates/api/src/post_report/resolve.rs +++ b/crates/api/src/post_report/resolve.rs @@ -2,10 +2,10 @@ use actix_web::web::{Data, Json}; use lemmy_api_common::{ context::LemmyContext, post::{PostReportResponse, ResolvePostReport}, - utils::{is_mod_or_admin, local_user_view_from_jwt}, + utils::is_mod_or_admin, }; use lemmy_db_schema::{source::post_report::PostReport, traits::Reportable}; -use lemmy_db_views::structs::PostReportView; +use lemmy_db_views::structs::{LocalUserView, PostReportView}; use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType}; /// Resolves or unresolves a post report and notifies the moderators of the community @@ -13,9 +13,8 @@ use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType}; pub async fn resolve_post_report( data: Json, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; - let report_id = data.report_id; let person_id = local_user_view.person.id; let report = PostReportView::read(&mut context.pool(), report_id, person_id).await?; diff --git a/crates/api/src/private_message/mark_read.rs b/crates/api/src/private_message/mark_read.rs index 6b6f7a51d..6b089c0ab 100644 --- a/crates/api/src/private_message/mark_read.rs +++ b/crates/api/src/private_message/mark_read.rs @@ -2,22 +2,20 @@ use actix_web::web::{Data, Json}; use lemmy_api_common::{ context::LemmyContext, private_message::{MarkPrivateMessageAsRead, PrivateMessageResponse}, - utils::local_user_view_from_jwt, }; use lemmy_db_schema::{ source::private_message::{PrivateMessage, PrivateMessageUpdateForm}, traits::Crud, }; -use lemmy_db_views::structs::PrivateMessageView; +use lemmy_db_views::structs::{LocalUserView, PrivateMessageView}; use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType}; #[tracing::instrument(skip(context))] pub async fn mark_pm_as_read( data: Json, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; - // Checking permissions let private_message_id = data.private_message_id; let orig_private_message = PrivateMessage::read(&mut context.pool(), private_message_id).await?; diff --git a/crates/api/src/private_message_report/create.rs b/crates/api/src/private_message_report/create.rs index ed19fdc35..2c4291581 100644 --- a/crates/api/src/private_message_report/create.rs +++ b/crates/api/src/private_message_report/create.rs @@ -3,7 +3,7 @@ use actix_web::web::{Data, Json}; use lemmy_api_common::{ context::LemmyContext, private_message::{CreatePrivateMessageReport, PrivateMessageReportResponse}, - utils::{local_user_view_from_jwt, sanitize_html_api, send_new_report_email_to_admins}, + utils::{sanitize_html_api, send_new_report_email_to_admins}, }; use lemmy_db_schema::{ source::{ @@ -13,15 +13,15 @@ use lemmy_db_schema::{ }, traits::{Crud, Reportable}, }; -use lemmy_db_views::structs::PrivateMessageReportView; +use lemmy_db_views::structs::{LocalUserView, PrivateMessageReportView}; use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType}; #[tracing::instrument(skip(context))] pub async fn create_pm_report( data: Json, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; let local_site = LocalSite::read(&mut context.pool()).await?; let reason = sanitize_html_api(data.reason.trim()); diff --git a/crates/api/src/private_message_report/list.rs b/crates/api/src/private_message_report/list.rs index 21e0cab21..2dc3e6efc 100644 --- a/crates/api/src/private_message_report/list.rs +++ b/crates/api/src/private_message_report/list.rs @@ -2,18 +2,20 @@ use actix_web::web::{Data, Json, Query}; use lemmy_api_common::{ context::LemmyContext, private_message::{ListPrivateMessageReports, ListPrivateMessageReportsResponse}, - utils::{is_admin, local_user_view_from_jwt}, + utils::is_admin, +}; +use lemmy_db_views::{ + private_message_report_view::PrivateMessageReportQuery, + structs::LocalUserView, }; -use lemmy_db_views::private_message_report_view::PrivateMessageReportQuery; use lemmy_utils::error::LemmyError; #[tracing::instrument(skip(context))] pub async fn list_pm_reports( data: Query, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; - is_admin(&local_user_view)?; let unresolved_only = data.unresolved_only.unwrap_or_default(); diff --git a/crates/api/src/private_message_report/resolve.rs b/crates/api/src/private_message_report/resolve.rs index 7f3f0647a..202fdcd29 100644 --- a/crates/api/src/private_message_report/resolve.rs +++ b/crates/api/src/private_message_report/resolve.rs @@ -2,19 +2,18 @@ use actix_web::web::{Data, Json}; use lemmy_api_common::{ context::LemmyContext, private_message::{PrivateMessageReportResponse, ResolvePrivateMessageReport}, - utils::{is_admin, local_user_view_from_jwt}, + utils::is_admin, }; use lemmy_db_schema::{source::private_message_report::PrivateMessageReport, traits::Reportable}; -use lemmy_db_views::structs::PrivateMessageReportView; +use lemmy_db_views::structs::{LocalUserView, PrivateMessageReportView}; use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType}; #[tracing::instrument(skip(context))] pub async fn resolve_pm_report( data: Json, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; - is_admin(&local_user_view)?; let report_id = data.report_id; diff --git a/crates/api/src/site/block.rs b/crates/api/src/site/block.rs index 3278767cf..be48e8ce8 100644 --- a/crates/api/src/site/block.rs +++ b/crates/api/src/site/block.rs @@ -3,21 +3,20 @@ use actix_web::web::Json; use lemmy_api_common::{ context::LemmyContext, site::{BlockInstance, BlockInstanceResponse}, - utils::local_user_view_from_jwt, }; use lemmy_db_schema::{ source::instance_block::{InstanceBlock, InstanceBlockForm}, traits::Blockable, }; +use lemmy_db_views::structs::LocalUserView; use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType}; #[tracing::instrument(skip(context))] pub async fn block_instance( data: Json, + local_user_view: LocalUserView, context: Data, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; - let instance_id = data.instance_id; let person_id = local_user_view.person.id; let instance_block_form = InstanceBlockForm { diff --git a/crates/api/src/site/leave_admin.rs b/crates/api/src/site/leave_admin.rs index 24b7184ae..f25747ef3 100644 --- a/crates/api/src/site/leave_admin.rs +++ b/crates/api/src/site/leave_admin.rs @@ -1,9 +1,5 @@ use actix_web::web::{Data, Json}; -use lemmy_api_common::{ - context::LemmyContext, - site::{GetSiteResponse, LeaveAdmin}, - utils::{is_admin, local_user_view_from_jwt}, -}; +use lemmy_api_common::{context::LemmyContext, site::GetSiteResponse, utils::is_admin}; use lemmy_db_schema::{ source::{ actor_language::SiteLanguage, @@ -14,7 +10,7 @@ use lemmy_db_schema::{ }, traits::Crud, }; -use lemmy_db_views::structs::{CustomEmojiView, SiteView}; +use lemmy_db_views::structs::{CustomEmojiView, LocalUserView, SiteView}; use lemmy_db_views_actor::structs::PersonView; use lemmy_utils::{ error::{LemmyError, LemmyErrorType}, @@ -23,11 +19,9 @@ use lemmy_utils::{ #[tracing::instrument(skip(context))] pub async fn leave_admin( - data: Json, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; - is_admin(&local_user_view)?; // Make sure there isn't just one admin (so if one leaves, there will still be one left) diff --git a/crates/api/src/site/mod_log.rs b/crates/api/src/site/mod_log.rs index 6743469b7..9c66c72a1 100644 --- a/crates/api/src/site/mod_log.rs +++ b/crates/api/src/site/mod_log.rs @@ -2,13 +2,14 @@ use actix_web::web::{Data, Json, Query}; use lemmy_api_common::{ context::LemmyContext, site::{GetModlog, GetModlogResponse}, - utils::{check_private_instance, is_admin, is_mod_or_admin, local_user_view_from_jwt_opt}, + utils::{check_private_instance, is_admin, is_mod_or_admin}, }; use lemmy_db_schema::{ newtypes::{CommunityId, PersonId}, source::local_site::LocalSite, ModlogActionType, }; +use lemmy_db_views::structs::LocalUserView; use lemmy_db_views_moderator::structs::{ AdminPurgeCommentView, AdminPurgeCommunityView, @@ -34,8 +35,8 @@ use ModlogActionType::*; pub async fn get_mod_log( data: Query, context: Data, + local_user_view: Option, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt_opt(data.auth.as_ref(), &context).await; let local_site = LocalSite::read(&mut context.pool()).await?; check_private_instance(&local_user_view, &local_site)?; diff --git a/crates/api/src/site/purge/comment.rs b/crates/api/src/site/purge/comment.rs index fa0973cf1..ec4ef02af 100644 --- a/crates/api/src/site/purge/comment.rs +++ b/crates/api/src/site/purge/comment.rs @@ -2,7 +2,7 @@ use actix_web::web::{Data, Json}; use lemmy_api_common::{ context::LemmyContext, site::{PurgeComment, PurgeItemResponse}, - utils::{is_admin, local_user_view_from_jwt, sanitize_html_api_opt}, + utils::{is_admin, sanitize_html_api_opt}, }; use lemmy_db_schema::{ source::{ @@ -11,15 +11,15 @@ use lemmy_db_schema::{ }, traits::Crud, }; +use lemmy_db_views::structs::LocalUserView; use lemmy_utils::error::LemmyError; #[tracing::instrument(skip(context))] pub async fn purge_comment( data: Json, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; - // Only let admin purge an item is_admin(&local_user_view)?; diff --git a/crates/api/src/site/purge/community.rs b/crates/api/src/site/purge/community.rs index 8e609501a..8e731fa29 100644 --- a/crates/api/src/site/purge/community.rs +++ b/crates/api/src/site/purge/community.rs @@ -3,12 +3,7 @@ use lemmy_api_common::{ context::LemmyContext, request::purge_image_from_pictrs, site::{PurgeCommunity, PurgeItemResponse}, - utils::{ - is_admin, - local_user_view_from_jwt, - purge_image_posts_for_community, - sanitize_html_api_opt, - }, + utils::{is_admin, purge_image_posts_for_community, sanitize_html_api_opt}, }; use lemmy_db_schema::{ source::{ @@ -17,15 +12,15 @@ use lemmy_db_schema::{ }, traits::Crud, }; +use lemmy_db_views::structs::LocalUserView; use lemmy_utils::error::LemmyError; #[tracing::instrument(skip(context))] pub async fn purge_community( data: Json, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; - // Only let admin purge an item is_admin(&local_user_view)?; diff --git a/crates/api/src/site/purge/person.rs b/crates/api/src/site/purge/person.rs index b2968ec31..1e68db88f 100644 --- a/crates/api/src/site/purge/person.rs +++ b/crates/api/src/site/purge/person.rs @@ -3,7 +3,7 @@ use lemmy_api_common::{ context::LemmyContext, request::delete_image_from_pictrs, site::{PurgeItemResponse, PurgePerson}, - utils::{is_admin, local_user_view_from_jwt, sanitize_html_api_opt}, + utils::{is_admin, sanitize_html_api_opt}, }; use lemmy_db_schema::{ source::{ @@ -20,9 +20,8 @@ use lemmy_utils::error::LemmyError; pub async fn purge_person( data: Json, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; - // Only let admin purge an item is_admin(&local_user_view)?; diff --git a/crates/api/src/site/purge/post.rs b/crates/api/src/site/purge/post.rs index 53dbf44e3..5e1ff4ea5 100644 --- a/crates/api/src/site/purge/post.rs +++ b/crates/api/src/site/purge/post.rs @@ -3,7 +3,7 @@ use lemmy_api_common::{ context::LemmyContext, request::purge_image_from_pictrs, site::{PurgeItemResponse, PurgePost}, - utils::{is_admin, local_user_view_from_jwt, sanitize_html_api_opt}, + utils::{is_admin, sanitize_html_api_opt}, }; use lemmy_db_schema::{ source::{ @@ -12,15 +12,15 @@ use lemmy_db_schema::{ }, traits::Crud, }; +use lemmy_db_views::structs::LocalUserView; use lemmy_utils::error::LemmyError; #[tracing::instrument(skip(context))] pub async fn purge_post( data: Json, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; - // Only let admin purge an item is_admin(&local_user_view)?; diff --git a/crates/api/src/site/registration_applications/approve.rs b/crates/api/src/site/registration_applications/approve.rs index 344fa82c8..036a60e00 100644 --- a/crates/api/src/site/registration_applications/approve.rs +++ b/crates/api/src/site/registration_applications/approve.rs @@ -2,7 +2,7 @@ use actix_web::web::{Data, Json}; use lemmy_api_common::{ context::LemmyContext, site::{ApproveRegistrationApplication, RegistrationApplicationResponse}, - utils::{is_admin, local_user_view_from_jwt, send_application_approved_email}, + utils::{is_admin, send_application_approved_email}, }; use lemmy_db_schema::{ source::{ @@ -18,9 +18,8 @@ use lemmy_utils::error::LemmyError; pub async fn approve_registration_application( data: Json, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; - let app_id = data.id; // Only let admins do this diff --git a/crates/api/src/site/registration_applications/list.rs b/crates/api/src/site/registration_applications/list.rs index 0690f50fb..30ce9aaf2 100644 --- a/crates/api/src/site/registration_applications/list.rs +++ b/crates/api/src/site/registration_applications/list.rs @@ -2,18 +2,21 @@ use actix_web::web::{Data, Json, Query}; use lemmy_api_common::{ context::LemmyContext, site::{ListRegistrationApplications, ListRegistrationApplicationsResponse}, - utils::{is_admin, local_user_view_from_jwt}, + utils::is_admin, }; use lemmy_db_schema::source::local_site::LocalSite; -use lemmy_db_views::registration_application_view::RegistrationApplicationQuery; +use lemmy_db_views::{ + registration_application_view::RegistrationApplicationQuery, + structs::LocalUserView, +}; use lemmy_utils::error::LemmyError; /// Lists registration applications, filterable by undenied only. pub async fn list_registration_applications( data: Query, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; let local_site = LocalSite::read(&mut context.pool()).await?; // Make sure user is an admin diff --git a/crates/api/src/site/registration_applications/unread_count.rs b/crates/api/src/site/registration_applications/unread_count.rs index 49929c070..255859198 100644 --- a/crates/api/src/site/registration_applications/unread_count.rs +++ b/crates/api/src/site/registration_applications/unread_count.rs @@ -1,18 +1,17 @@ -use actix_web::web::{Data, Json, Query}; +use actix_web::web::{Data, Json}; use lemmy_api_common::{ context::LemmyContext, - site::{GetUnreadRegistrationApplicationCount, GetUnreadRegistrationApplicationCountResponse}, - utils::{is_admin, local_user_view_from_jwt}, + site::GetUnreadRegistrationApplicationCountResponse, + utils::is_admin, }; use lemmy_db_schema::source::local_site::LocalSite; -use lemmy_db_views::structs::RegistrationApplicationView; +use lemmy_db_views::structs::{LocalUserView, RegistrationApplicationView}; use lemmy_utils::error::LemmyError; pub async fn get_unread_registration_application_count( - data: Query, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; let local_site = LocalSite::read(&mut context.pool()).await?; // Only let admins do this diff --git a/crates/api_common/src/comment.rs b/crates/api_common/src/comment.rs index ec9ca1328..c2589fb2a 100644 --- a/crates/api_common/src/comment.rs +++ b/crates/api_common/src/comment.rs @@ -1,4 +1,3 @@ -use crate::sensitive::Sensitive; use lemmy_db_schema::{ newtypes::{CommentId, CommentReportId, CommunityId, LanguageId, LocalUserId, PostId}, CommentSortType, @@ -20,7 +19,6 @@ pub struct CreateComment { pub post_id: PostId, pub parent_id: Option, pub language_id: Option, - pub auth: Sensitive, } #[skip_serializing_none] @@ -30,7 +28,6 @@ pub struct CreateComment { /// Fetch an individual comment. pub struct GetComment { pub id: CommentId, - pub auth: Option>, } #[skip_serializing_none] @@ -42,7 +39,6 @@ pub struct EditComment { pub comment_id: CommentId, pub content: Option, pub language_id: Option, - pub auth: Sensitive, } #[skip_serializing_none] @@ -53,7 +49,6 @@ pub struct EditComment { pub struct DistinguishComment { pub comment_id: CommentId, pub distinguished: bool, - pub auth: Sensitive, } #[skip_serializing_none] @@ -64,7 +59,6 @@ pub struct DistinguishComment { pub struct DeleteComment { pub comment_id: CommentId, pub deleted: bool, - pub auth: Sensitive, } #[skip_serializing_none] @@ -76,7 +70,6 @@ pub struct RemoveComment { pub comment_id: CommentId, pub removed: bool, pub reason: Option, - pub auth: Sensitive, } #[derive(Debug, Serialize, Deserialize, Clone, Default)] @@ -86,7 +79,6 @@ pub struct RemoveComment { pub struct SaveComment { pub comment_id: CommentId, pub save: bool, - pub auth: Sensitive, } #[skip_serializing_none] @@ -107,7 +99,6 @@ pub struct CreateCommentLike { pub comment_id: CommentId, /// Must be -1, 0, or 1 . pub score: i16, - pub auth: Sensitive, } #[skip_serializing_none] @@ -128,7 +119,6 @@ pub struct GetComments { pub saved_only: Option, pub liked_only: Option, pub disliked_only: Option, - pub auth: Option>, } #[derive(Debug, Serialize, Deserialize, Clone)] @@ -146,7 +136,6 @@ pub struct GetCommentsResponse { pub struct CreateCommentReport { pub comment_id: CommentId, pub reason: String, - pub auth: Sensitive, } #[derive(Debug, Serialize, Deserialize, Clone)] @@ -164,7 +153,6 @@ pub struct CommentReportResponse { pub struct ResolveCommentReport { pub report_id: CommentReportId, pub resolved: bool, - pub auth: Sensitive, } #[skip_serializing_none] @@ -179,7 +167,6 @@ pub struct ListCommentReports { pub unresolved_only: Option, /// if no community is given, it returns reports for all communities moderated by the auth user pub community_id: Option, - pub auth: Sensitive, } #[derive(Debug, Serialize, Deserialize, Clone)] diff --git a/crates/api_common/src/community.rs b/crates/api_common/src/community.rs index ff6ed1271..7c96344b5 100644 --- a/crates/api_common/src/community.rs +++ b/crates/api_common/src/community.rs @@ -1,4 +1,3 @@ -use crate::sensitive::Sensitive; use lemmy_db_schema::{ newtypes::{CommunityId, LanguageId, PersonId}, source::site::Site, @@ -20,7 +19,6 @@ pub struct GetCommunity { pub id: Option, /// Example: star_trek , or star_trek@xyz.tld pub name: Option, - pub auth: Option>, } #[skip_serializing_none] @@ -56,7 +54,6 @@ pub struct CreateCommunity { /// Whether to restrict posting only to moderators. pub posting_restricted_to_mods: Option, pub discussion_languages: Option>, - pub auth: Sensitive, } #[derive(Debug, Serialize, Deserialize, Clone)] @@ -79,7 +76,6 @@ pub struct ListCommunities { pub show_nsfw: Option, pub page: Option, pub limit: Option, - pub auth: Option>, } #[derive(Debug, Serialize, Deserialize, Clone)] @@ -102,7 +98,6 @@ pub struct BanFromCommunity { pub remove_data: Option, pub reason: Option, pub expires: Option, - pub auth: Sensitive, } #[derive(Debug, Serialize, Deserialize, Clone)] @@ -122,7 +117,6 @@ pub struct AddModToCommunity { pub community_id: CommunityId, pub person_id: PersonId, pub added: bool, - pub auth: Sensitive, } #[derive(Debug, Serialize, Deserialize, Clone)] @@ -153,7 +147,6 @@ pub struct EditCommunity { /// Whether to restrict posting only to moderators. pub posting_restricted_to_mods: Option, pub discussion_languages: Option>, - pub auth: Sensitive, } #[skip_serializing_none] @@ -166,7 +159,6 @@ pub struct HideCommunity { pub community_id: CommunityId, pub hidden: bool, pub reason: Option, - pub auth: Sensitive, } #[skip_serializing_none] @@ -177,7 +169,6 @@ pub struct HideCommunity { pub struct DeleteCommunity { pub community_id: CommunityId, pub deleted: bool, - pub auth: Sensitive, } #[skip_serializing_none] @@ -190,7 +181,6 @@ pub struct RemoveCommunity { pub removed: bool, pub reason: Option, pub expires: Option, - pub auth: Sensitive, } #[derive(Debug, Serialize, Deserialize, Clone, Default)] @@ -200,7 +190,6 @@ pub struct RemoveCommunity { pub struct FollowCommunity { pub community_id: CommunityId, pub follow: bool, - pub auth: Sensitive, } #[derive(Debug, Serialize, Deserialize, Clone, Default)] @@ -210,7 +199,6 @@ pub struct FollowCommunity { pub struct BlockCommunity { pub community_id: CommunityId, pub block: bool, - pub auth: Sensitive, } #[skip_serializing_none] @@ -230,5 +218,4 @@ pub struct BlockCommunityResponse { pub struct TransferCommunity { pub community_id: CommunityId, pub person_id: PersonId, - pub auth: Sensitive, } diff --git a/crates/api_common/src/custom_emoji.rs b/crates/api_common/src/custom_emoji.rs index 7f3461ca7..83248dc91 100644 --- a/crates/api_common/src/custom_emoji.rs +++ b/crates/api_common/src/custom_emoji.rs @@ -1,4 +1,3 @@ -use crate::sensitive::Sensitive; use lemmy_db_schema::newtypes::CustomEmojiId; use lemmy_db_views::structs::CustomEmojiView; use serde::{Deserialize, Serialize}; @@ -17,7 +16,6 @@ pub struct CreateCustomEmoji { pub image_url: Url, pub alt_text: String, pub keywords: Vec, - pub auth: Sensitive, } #[derive(Debug, Serialize, Deserialize, Clone)] @@ -31,7 +29,6 @@ pub struct EditCustomEmoji { pub image_url: Url, pub alt_text: String, pub keywords: Vec, - pub auth: Sensitive, } #[derive(Debug, Serialize, Deserialize, Clone, Default)] @@ -40,7 +37,6 @@ pub struct EditCustomEmoji { /// Delete a custom emoji. pub struct DeleteCustomEmoji { pub id: CustomEmojiId, - pub auth: Sensitive, } #[derive(Serialize, Deserialize, Clone)] diff --git a/crates/api_common/src/person.rs b/crates/api_common/src/person.rs index 3f43f30df..feb945b17 100644 --- a/crates/api_common/src/person.rs +++ b/crates/api_common/src/person.rs @@ -119,7 +119,6 @@ pub struct SaveUserSettings { pub show_new_post_notifs: Option, /// A list of languages you are able to see discussion in. pub discussion_languages: Option>, - pub auth: Sensitive, /// Open links in a new tab pub open_links_in_new_tab: Option, /// Enable infinite scroll @@ -134,7 +133,6 @@ pub struct ChangePassword { pub new_password: Sensitive, pub new_password_verify: Sensitive, pub old_password: Sensitive, - pub auth: Sensitive, } #[skip_serializing_none] @@ -167,7 +165,6 @@ pub struct GetPersonDetails { pub limit: Option, pub community_id: Option, pub saved_only: Option, - pub auth: Option>, } #[derive(Debug, Serialize, Deserialize, Clone)] @@ -181,14 +178,6 @@ pub struct GetPersonDetailsResponse { pub moderates: Vec, } -#[derive(Debug, Serialize, Deserialize, Clone, Default)] -#[cfg_attr(feature = "full", derive(TS))] -#[cfg_attr(feature = "full", ts(export))] -/// Marks all notifications as read. -pub struct MarkAllAsRead { - pub auth: Sensitive, -} - #[derive(Debug, Serialize, Deserialize, Clone, Default)] #[cfg_attr(feature = "full", derive(TS))] #[cfg_attr(feature = "full", ts(export))] @@ -196,7 +185,6 @@ pub struct MarkAllAsRead { pub struct AddAdmin { pub person_id: PersonId, pub added: bool, - pub auth: Sensitive, } #[derive(Debug, Serialize, Deserialize, Clone)] @@ -219,18 +207,9 @@ pub struct BanPerson { pub remove_data: Option, pub reason: Option, pub expires: Option, - pub auth: Sensitive, } -#[derive(Debug, Serialize, Deserialize, Clone, Default)] -#[cfg_attr(feature = "full", derive(TS))] -#[cfg_attr(feature = "full", ts(export))] -/// Get a list of banned persons. // TODO, this should be paged, since the list can be quite long. -pub struct GetBannedPersons { - pub auth: Sensitive, -} - #[derive(Debug, Serialize, Deserialize, Clone)] #[cfg_attr(feature = "full", derive(TS))] #[cfg_attr(feature = "full", ts(export))] @@ -255,7 +234,6 @@ pub struct BanPersonResponse { pub struct BlockPerson { pub person_id: PersonId, pub block: bool, - pub auth: Sensitive, } #[derive(Debug, Serialize, Deserialize, Clone)] @@ -277,7 +255,6 @@ pub struct GetReplies { pub page: Option, pub limit: Option, pub unread_only: Option, - pub auth: Sensitive, } #[derive(Debug, Serialize, Deserialize, Clone, Default)] @@ -299,7 +276,6 @@ pub struct GetPersonMentions { pub page: Option, pub limit: Option, pub unread_only: Option, - pub auth: Sensitive, } #[derive(Debug, Serialize, Deserialize, Clone)] @@ -317,7 +293,6 @@ pub struct GetPersonMentionsResponse { pub struct MarkPersonMentionAsRead { pub person_mention_id: PersonMentionId, pub read: bool, - pub auth: Sensitive, } #[derive(Debug, Serialize, Deserialize, Clone)] @@ -335,7 +310,6 @@ pub struct PersonMentionResponse { pub struct MarkCommentReplyAsRead { pub comment_reply_id: CommentReplyId, pub read: bool, - pub auth: Sensitive, } #[derive(Debug, Serialize, Deserialize, Clone)] @@ -353,7 +327,6 @@ pub struct CommentReplyResponse { pub struct DeleteAccount { pub password: Sensitive, pub delete_content: bool, - pub auth: Sensitive, } #[derive(Debug, Serialize, Deserialize, Clone)] @@ -393,7 +366,6 @@ pub struct PasswordChangeAfterReset { /// Get a count of the number of reports. pub struct GetReportCount { pub community_id: Option, - pub auth: Sensitive, } #[skip_serializing_none] @@ -408,14 +380,6 @@ pub struct GetReportCountResponse { pub private_message_reports: Option, } -#[derive(Debug, Serialize, Deserialize, Clone, Default)] -#[cfg_attr(feature = "full", derive(TS))] -#[cfg_attr(feature = "full", ts(export))] -/// Get a count of unread notifications. -pub struct GetUnreadCount { - pub auth: Sensitive, -} - #[derive(Debug, Serialize, Deserialize, Clone)] #[cfg_attr(feature = "full", derive(TS))] #[cfg_attr(feature = "full", ts(export))] diff --git a/crates/api_common/src/post.rs b/crates/api_common/src/post.rs index bb5c1cccc..86f721701 100644 --- a/crates/api_common/src/post.rs +++ b/crates/api_common/src/post.rs @@ -1,4 +1,3 @@ -use crate::sensitive::Sensitive; use lemmy_db_schema::{ newtypes::{CommentId, CommunityId, DbUrl, LanguageId, PostId, PostReportId}, ListingType, @@ -29,7 +28,6 @@ pub struct CreatePost { pub honeypot: Option, pub nsfw: Option, pub language_id: Option, - pub auth: Sensitive, } #[derive(Debug, Serialize, Deserialize, Clone)] @@ -47,7 +45,6 @@ pub struct PostResponse { pub struct GetPost { pub id: Option, pub comment_id: Option, - pub auth: Option>, } #[derive(Debug, Serialize, Deserialize, Clone)] @@ -78,7 +75,6 @@ pub struct GetPosts { pub saved_only: Option, pub liked_only: Option, pub disliked_only: Option, - pub auth: Option>, pub page_cursor: Option, } @@ -101,7 +97,6 @@ pub struct CreatePostLike { pub post_id: PostId, /// Score must be -1, 0, or 1. pub score: i16, - pub auth: Sensitive, } #[skip_serializing_none] @@ -118,7 +113,6 @@ pub struct EditPost { pub body: Option, pub nsfw: Option, pub language_id: Option, - pub auth: Sensitive, } #[derive(Debug, Serialize, Deserialize, Clone, Default)] @@ -128,7 +122,6 @@ pub struct EditPost { pub struct DeletePost { pub post_id: PostId, pub deleted: bool, - pub auth: Sensitive, } #[skip_serializing_none] @@ -140,7 +133,6 @@ pub struct RemovePost { pub post_id: PostId, pub removed: bool, pub reason: Option, - pub auth: Sensitive, } #[derive(Debug, Serialize, Deserialize, Clone, Default)] @@ -150,7 +142,6 @@ pub struct RemovePost { pub struct MarkPostAsRead { pub post_id: PostId, pub read: bool, - pub auth: Sensitive, } #[derive(Debug, Serialize, Deserialize, Clone, Default)] @@ -160,7 +151,6 @@ pub struct MarkPostAsRead { pub struct LockPost { pub post_id: PostId, pub locked: bool, - pub auth: Sensitive, } #[derive(Debug, Serialize, Deserialize, Clone, Default)] @@ -171,7 +161,6 @@ pub struct FeaturePost { pub post_id: PostId, pub featured: bool, pub feature_type: PostFeatureType, - pub auth: Sensitive, } #[derive(Debug, Serialize, Deserialize, Clone, Default)] @@ -181,7 +170,6 @@ pub struct FeaturePost { pub struct SavePost { pub post_id: PostId, pub save: bool, - pub auth: Sensitive, } #[derive(Debug, Serialize, Deserialize, Clone, Default)] @@ -191,7 +179,6 @@ pub struct SavePost { pub struct CreatePostReport { pub post_id: PostId, pub reason: String, - pub auth: Sensitive, } #[derive(Debug, Serialize, Deserialize, Clone)] @@ -209,7 +196,6 @@ pub struct PostReportResponse { pub struct ResolvePostReport { pub report_id: PostReportId, pub resolved: bool, - pub auth: Sensitive, } #[skip_serializing_none] @@ -224,7 +210,6 @@ pub struct ListPostReports { pub unresolved_only: Option, /// if no community is given, it returns reports for all communities moderated by the auth user pub community_id: Option, - pub auth: Sensitive, } #[derive(Debug, Serialize, Deserialize, Clone)] diff --git a/crates/api_common/src/private_message.rs b/crates/api_common/src/private_message.rs index d27c4f659..8d469127d 100644 --- a/crates/api_common/src/private_message.rs +++ b/crates/api_common/src/private_message.rs @@ -1,4 +1,3 @@ -use crate::sensitive::Sensitive; use lemmy_db_schema::newtypes::{PersonId, PrivateMessageId, PrivateMessageReportId}; use lemmy_db_views::structs::{PrivateMessageReportView, PrivateMessageView}; use serde::{Deserialize, Serialize}; @@ -13,7 +12,6 @@ use ts_rs::TS; pub struct CreatePrivateMessage { pub content: String, pub recipient_id: PersonId, - pub auth: Sensitive, } #[derive(Debug, Serialize, Deserialize, Clone, Default)] @@ -23,7 +21,6 @@ pub struct CreatePrivateMessage { pub struct EditPrivateMessage { pub private_message_id: PrivateMessageId, pub content: String, - pub auth: Sensitive, } #[derive(Debug, Serialize, Deserialize, Clone, Default)] @@ -33,7 +30,6 @@ pub struct EditPrivateMessage { pub struct DeletePrivateMessage { pub private_message_id: PrivateMessageId, pub deleted: bool, - pub auth: Sensitive, } #[derive(Debug, Serialize, Deserialize, Clone, Default)] @@ -43,7 +39,6 @@ pub struct DeletePrivateMessage { pub struct MarkPrivateMessageAsRead { pub private_message_id: PrivateMessageId, pub read: bool, - pub auth: Sensitive, } #[skip_serializing_none] @@ -56,7 +51,6 @@ pub struct GetPrivateMessages { pub page: Option, pub limit: Option, pub creator_id: Option, - pub auth: Sensitive, } #[derive(Debug, Serialize, Deserialize, Clone)] @@ -82,7 +76,6 @@ pub struct PrivateMessageResponse { pub struct CreatePrivateMessageReport { pub private_message_id: PrivateMessageId, pub reason: String, - pub auth: Sensitive, } #[derive(Debug, Serialize, Deserialize, Clone)] @@ -100,7 +93,6 @@ pub struct PrivateMessageReportResponse { pub struct ResolvePrivateMessageReport { pub report_id: PrivateMessageReportId, pub resolved: bool, - pub auth: Sensitive, } #[skip_serializing_none] @@ -114,7 +106,6 @@ pub struct ListPrivateMessageReports { pub limit: Option, /// Only shows the unresolved reports pub unresolved_only: Option, - pub auth: Sensitive, } #[derive(Debug, Serialize, Deserialize, Clone)] diff --git a/crates/api_common/src/site.rs b/crates/api_common/src/site.rs index 7ed94f2de..b047c6dd0 100644 --- a/crates/api_common/src/site.rs +++ b/crates/api_common/src/site.rs @@ -1,4 +1,3 @@ -use crate::sensitive::Sensitive; use lemmy_db_schema::{ newtypes::{CommentId, CommunityId, InstanceId, LanguageId, PersonId, PostId}, source::{instance::Instance, language::Language, tagline::Tagline}, @@ -62,7 +61,6 @@ pub struct Search { pub listing_type: Option, pub page: Option, pub limit: Option, - pub auth: Option>, } #[derive(Debug, Serialize, Deserialize, Clone)] @@ -85,7 +83,6 @@ pub struct SearchResponse { pub struct ResolveObject { /// Can be the full url, or a shortened version like: !fediverse@lemmy.ml pub q: String, - pub auth: Option>, } #[skip_serializing_none] @@ -113,7 +110,6 @@ pub struct GetModlog { pub limit: Option, pub type_: Option, pub other_person_id: Option, - pub auth: Option>, } #[derive(Debug, Serialize, Deserialize, Clone)] @@ -184,7 +180,6 @@ pub struct CreateSite { pub blocked_instances: Option>, pub taglines: Option>, pub registration_mode: Option, - pub auth: Sensitive, } #[skip_serializing_none] @@ -263,16 +258,6 @@ pub struct EditSite { pub registration_mode: Option, /// Whether to email admins for new reports. pub reports_email_admins: Option, - pub auth: Sensitive, -} - -#[skip_serializing_none] -#[derive(Debug, Serialize, Deserialize, Clone, Default)] -#[cfg_attr(feature = "full", derive(TS))] -#[cfg_attr(feature = "full", ts(export))] -/// Fetches the site. -pub struct GetSite { - pub auth: Option>, } #[derive(Debug, Serialize, Deserialize, Clone)] @@ -326,14 +311,6 @@ pub struct MyUserInfo { pub discussion_languages: Vec, } -#[derive(Debug, Serialize, Deserialize, Clone)] -#[cfg_attr(feature = "full", derive(TS))] -#[cfg_attr(feature = "full", ts(export))] -/// Leaves the admin team. -pub struct LeaveAdmin { - pub auth: Sensitive, -} - #[derive(Debug, Serialize, Deserialize, Clone)] #[cfg_attr(feature = "full", derive(TS))] #[cfg_attr(feature = "full", ts(export))] @@ -352,7 +329,6 @@ pub struct FederatedInstances { pub struct PurgePerson { pub person_id: PersonId, pub reason: Option, - pub auth: Sensitive, } #[skip_serializing_none] @@ -363,7 +339,6 @@ pub struct PurgePerson { pub struct PurgeCommunity { pub community_id: CommunityId, pub reason: Option, - pub auth: Sensitive, } #[skip_serializing_none] @@ -374,7 +349,6 @@ pub struct PurgeCommunity { pub struct PurgePost { pub post_id: PostId, pub reason: Option, - pub auth: Sensitive, } #[skip_serializing_none] @@ -385,7 +359,6 @@ pub struct PurgePost { pub struct PurgeComment { pub comment_id: CommentId, pub reason: Option, - pub auth: Sensitive, } #[derive(Serialize, Deserialize, Clone)] @@ -406,7 +379,6 @@ pub struct ListRegistrationApplications { pub unread_only: Option, pub page: Option, pub limit: Option, - pub auth: Sensitive, } #[derive(Debug, Serialize, Deserialize, Clone)] @@ -426,7 +398,6 @@ pub struct ApproveRegistrationApplication { pub id: i32, pub approve: bool, pub deny_reason: Option, - pub auth: Sensitive, } #[derive(Debug, Serialize, Deserialize, Clone)] @@ -437,14 +408,6 @@ pub struct RegistrationApplicationResponse { pub registration_application: RegistrationApplicationView, } -#[derive(Debug, Serialize, Deserialize, Clone)] -#[cfg_attr(feature = "full", derive(TS))] -#[cfg_attr(feature = "full", ts(export))] -/// Gets a count of unread registration applications. -pub struct GetUnreadRegistrationApplicationCount { - pub auth: Sensitive, -} - #[derive(Debug, Serialize, Deserialize, Clone)] #[cfg_attr(feature = "full", derive(TS))] #[cfg_attr(feature = "full", ts(export))] @@ -460,7 +423,6 @@ pub struct GetUnreadRegistrationApplicationCountResponse { pub struct BlockInstance { pub instance_id: InstanceId, pub block: bool, - pub auth: Sensitive, } #[skip_serializing_none] diff --git a/crates/api_common/src/utils.rs b/crates/api_common/src/utils.rs index 9d8181a2e..26ef18c9e 100644 --- a/crates/api_common/src/utils.rs +++ b/crates/api_common/src/utils.rs @@ -1,14 +1,9 @@ -use crate::{ - context::LemmyContext, - request::purge_image_from_pictrs, - sensitive::Sensitive, - site::FederatedInstances, -}; +use crate::{context::LemmyContext, request::purge_image_from_pictrs, site::FederatedInstances}; use anyhow::Context; use chrono::{DateTime, Utc}; use lemmy_db_schema::{ impls::person::is_banned, - newtypes::{CommunityId, DbUrl, LocalUserId, PersonId, PostId}, + newtypes::{CommunityId, DbUrl, PersonId, PostId}, source::{ comment::{Comment, CommentUpdateForm}, community::{Community, CommunityModerator, CommunityUpdateForm}, @@ -20,11 +15,9 @@ use lemmy_db_schema::{ person::{Person, PersonUpdateForm}, person_block::PersonBlock, post::{Post, PostRead, PostReadForm}, - registration_application::RegistrationApplication, }, traits::{Crud, Readable}, utils::DbPool, - RegistrationMode, }; use lemmy_db_views::{comment_view::CommentQuery, structs::LocalUserView}; use lemmy_db_views_actor::structs::{ @@ -33,9 +26,8 @@ use lemmy_db_views_actor::structs::{ CommunityView, }; use lemmy_utils::{ - claims::Claims, email::{send_email, translations::Lang}, - error::{LemmyError, LemmyErrorExt, LemmyErrorExt2, LemmyErrorType}, + error::{LemmyError, LemmyErrorExt, LemmyErrorType}, location_info, rate_limit::RateLimitConfig, settings::structs::Settings, @@ -134,58 +126,6 @@ pub async fn mark_post_as_unread( .with_lemmy_type(LemmyErrorType::CouldntMarkPostAsRead) } -#[tracing::instrument(skip_all)] -pub async fn local_user_view_from_jwt( - jwt: &str, - context: &LemmyContext, -) -> Result { - let claims = Claims::decode(jwt, &context.secret().jwt_secret) - .with_lemmy_type(LemmyErrorType::NotLoggedIn)? - .claims; - let local_user_id = LocalUserId(claims.sub); - let local_user_view = LocalUserView::read(&mut context.pool(), local_user_id).await?; - check_user_valid( - local_user_view.person.banned, - local_user_view.person.ban_expires, - local_user_view.person.deleted, - )?; - - check_validator_time(&local_user_view.local_user.validator_time, &claims)?; - - Ok(local_user_view) -} - -#[tracing::instrument(skip_all)] -pub async fn local_user_view_from_jwt_opt( - jwt: Option<&Sensitive>, - context: &LemmyContext, -) -> Option { - local_user_view_from_jwt(jwt?, context).await.ok() -} -#[tracing::instrument(skip_all)] -pub async fn local_user_view_from_jwt_opt_new( - local_user_view: &mut Option, - jwt: Option<&Sensitive>, - context: &LemmyContext, -) { - if local_user_view.is_none() { - *local_user_view = local_user_view_from_jwt_opt(jwt, context).await; - } -} - -/// Checks if user's token was issued before user's password reset. -pub fn check_validator_time( - validator_time: &DateTime, - claims: &Claims, -) -> Result<(), LemmyError> { - let user_validation_time = validator_time.timestamp(); - if user_validation_time > claims.iat { - Err(LemmyErrorType::NotLoggedIn)? - } else { - Ok(()) - } -} - pub fn check_user_valid( banned: bool, ban_expires: Option>, @@ -505,32 +445,6 @@ pub async fn send_new_report_email_to_admins( Ok(()) } -pub async fn check_registration_application( - local_user_view: &LocalUserView, - local_site: &LocalSite, - pool: &mut DbPool<'_>, -) -> Result<(), LemmyError> { - if (local_site.registration_mode == RegistrationMode::RequireApplication - || local_site.registration_mode == RegistrationMode::Closed) - && !local_user_view.local_user.accepted_application - && !local_user_view.local_user.admin - { - // Fetch the registration, see if its denied - let local_user_id = local_user_view.local_user.id; - let registration = RegistrationApplication::find_by_local_user_id(pool, local_user_id).await?; - if let Some(deny_reason) = registration.deny_reason { - let lang = get_interface_language(local_user_view); - let registration_denied_message = format!("{}: {}", lang.registration_denied(), deny_reason); - Err(LemmyErrorType::RegistrationDenied( - registration_denied_message, - ))? - } else { - Err(LemmyErrorType::RegistrationApplicationIsPending)? - } - } - Ok(()) -} - pub fn check_private_instance_and_federation_enabled( local_site: &LocalSite, ) -> Result<(), LemmyError> { diff --git a/crates/api_crud/src/comment/create.rs b/crates/api_crud/src/comment/create.rs index 3ba19d1b9..c9aa4f774 100644 --- a/crates/api_crud/src/comment/create.rs +++ b/crates/api_crud/src/comment/create.rs @@ -12,7 +12,6 @@ use lemmy_api_common::{ generate_local_apub_endpoint, get_post, local_site_to_slur_regex, - local_user_view_from_jwt, sanitize_html_api, EndpointType, }, @@ -28,6 +27,7 @@ use lemmy_db_schema::{ }, traits::{Crud, Likeable}, }; +use lemmy_db_views::structs::LocalUserView; use lemmy_utils::{ error::{LemmyError, LemmyErrorExt, LemmyErrorType}, utils::{ @@ -43,8 +43,8 @@ const MAX_COMMENT_DEPTH_LIMIT: usize = 100; pub async fn create_comment( data: Json, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; let local_site = LocalSite::read(&mut context.pool()).await?; let content = remove_slurs( diff --git a/crates/api_crud/src/comment/delete.rs b/crates/api_crud/src/comment/delete.rs index 5f5db905e..1c986d03c 100644 --- a/crates/api_crud/src/comment/delete.rs +++ b/crates/api_crud/src/comment/delete.rs @@ -5,7 +5,7 @@ use lemmy_api_common::{ comment::{CommentResponse, DeleteComment}, context::LemmyContext, send_activity::{ActivityChannel, SendActivityData}, - utils::{check_community_ban, local_user_view_from_jwt}, + utils::check_community_ban, }; use lemmy_db_schema::{ source::{ @@ -14,16 +14,15 @@ use lemmy_db_schema::{ }, traits::Crud, }; -use lemmy_db_views::structs::CommentView; +use lemmy_db_views::structs::{CommentView, LocalUserView}; use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType}; #[tracing::instrument(skip(context))] pub async fn delete_comment( data: Json, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; - let comment_id = data.comment_id; let orig_comment = CommentView::read(&mut context.pool(), comment_id, None).await?; diff --git a/crates/api_crud/src/comment/read.rs b/crates/api_crud/src/comment/read.rs index 5f07f7496..733d08682 100644 --- a/crates/api_crud/src/comment/read.rs +++ b/crates/api_crud/src/comment/read.rs @@ -3,17 +3,18 @@ use lemmy_api_common::{ build_response::build_comment_response, comment::{CommentResponse, GetComment}, context::LemmyContext, - utils::{check_private_instance, local_user_view_from_jwt_opt}, + utils::check_private_instance, }; use lemmy_db_schema::source::local_site::LocalSite; +use lemmy_db_views::structs::LocalUserView; use lemmy_utils::error::LemmyError; #[tracing::instrument(skip(context))] pub async fn get_comment( data: Query, context: Data, + local_user_view: Option, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt_opt(data.auth.as_ref(), &context).await; let local_site = LocalSite::read(&mut context.pool()).await?; check_private_instance(&local_user_view, &local_site)?; diff --git a/crates/api_crud/src/comment/remove.rs b/crates/api_crud/src/comment/remove.rs index 2bb5c75f2..601101bb8 100644 --- a/crates/api_crud/src/comment/remove.rs +++ b/crates/api_crud/src/comment/remove.rs @@ -5,7 +5,7 @@ use lemmy_api_common::{ comment::{CommentResponse, RemoveComment}, context::LemmyContext, send_activity::{ActivityChannel, SendActivityData}, - utils::{check_community_ban, is_mod_or_admin, local_user_view_from_jwt}, + utils::{check_community_ban, is_mod_or_admin}, }; use lemmy_db_schema::{ source::{ @@ -15,16 +15,15 @@ use lemmy_db_schema::{ }, traits::Crud, }; -use lemmy_db_views::structs::CommentView; +use lemmy_db_views::structs::{CommentView, LocalUserView}; use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType}; #[tracing::instrument(skip(context))] pub async fn remove_comment( data: Json, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; - let comment_id = data.comment_id; let orig_comment = CommentView::read(&mut context.pool(), comment_id, None).await?; diff --git a/crates/api_crud/src/comment/update.rs b/crates/api_crud/src/comment/update.rs index bf6bdff84..2d966d0fa 100644 --- a/crates/api_crud/src/comment/update.rs +++ b/crates/api_crud/src/comment/update.rs @@ -5,12 +5,7 @@ use lemmy_api_common::{ comment::{CommentResponse, EditComment}, context::LemmyContext, send_activity::{ActivityChannel, SendActivityData}, - utils::{ - check_community_ban, - local_site_to_slur_regex, - local_user_view_from_jwt, - sanitize_html_api_opt, - }, + utils::{check_community_ban, local_site_to_slur_regex, sanitize_html_api_opt}, }; use lemmy_db_schema::{ source::{ @@ -21,7 +16,7 @@ use lemmy_db_schema::{ traits::Crud, utils::naive_now, }; -use lemmy_db_views::structs::CommentView; +use lemmy_db_views::structs::{CommentView, LocalUserView}; use lemmy_utils::{ error::{LemmyError, LemmyErrorExt, LemmyErrorType}, utils::{ @@ -35,8 +30,8 @@ use lemmy_utils::{ pub async fn update_comment( data: Json, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; let local_site = LocalSite::read(&mut context.pool()).await?; let comment_id = data.comment_id; diff --git a/crates/api_crud/src/community/create.rs b/crates/api_crud/src/community/create.rs index d6c07c128..633fa81a9 100644 --- a/crates/api_crud/src/community/create.rs +++ b/crates/api_crud/src/community/create.rs @@ -11,7 +11,6 @@ use lemmy_api_common::{ generate_shared_inbox_url, is_admin, local_site_to_slur_regex, - local_user_view_from_jwt, sanitize_html_api, sanitize_html_api_opt, EndpointType, @@ -32,7 +31,7 @@ use lemmy_db_schema::{ traits::{ApubActor, Crud, Followable, Joinable}, utils::diesel_option_overwrite_to_url_create, }; -use lemmy_db_views::structs::SiteView; +use lemmy_db_views::structs::{LocalUserView, SiteView}; use lemmy_utils::{ error::{LemmyError, LemmyErrorExt, LemmyErrorType}, utils::{ @@ -45,8 +44,8 @@ use lemmy_utils::{ pub async fn create_community( data: Json, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; let site_view = SiteView::read_local(&mut context.pool()).await?; let local_site = site_view.local_site; diff --git a/crates/api_crud/src/community/delete.rs b/crates/api_crud/src/community/delete.rs index 9c8db512d..7c94e0ccc 100644 --- a/crates/api_crud/src/community/delete.rs +++ b/crates/api_crud/src/community/delete.rs @@ -5,12 +5,13 @@ use lemmy_api_common::{ community::{CommunityResponse, DeleteCommunity}, context::LemmyContext, send_activity::{ActivityChannel, SendActivityData}, - utils::{is_top_mod, local_user_view_from_jwt}, + utils::is_top_mod, }; use lemmy_db_schema::{ source::community::{Community, CommunityUpdateForm}, traits::Crud, }; +use lemmy_db_views::structs::LocalUserView; use lemmy_db_views_actor::structs::CommunityModeratorView; use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType}; @@ -18,9 +19,8 @@ use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType}; pub async fn delete_community( data: Json, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; - // Fetch the community mods let community_id = data.community_id; let community_mods = diff --git a/crates/api_crud/src/community/list.rs b/crates/api_crud/src/community/list.rs index 1f620dd9c..0879421ba 100644 --- a/crates/api_crud/src/community/list.rs +++ b/crates/api_crud/src/community/list.rs @@ -2,9 +2,10 @@ use actix_web::web::{Data, Json, Query}; use lemmy_api_common::{ community::{ListCommunities, ListCommunitiesResponse}, context::LemmyContext, - utils::{check_private_instance, is_admin, local_user_view_from_jwt_opt}, + utils::{check_private_instance, is_admin}, }; use lemmy_db_schema::source::local_site::LocalSite; +use lemmy_db_views::structs::LocalUserView; use lemmy_db_views_actor::community_view::CommunityQuery; use lemmy_utils::error::LemmyError; @@ -12,8 +13,8 @@ use lemmy_utils::error::LemmyError; pub async fn list_communities( data: Query, context: Data, + local_user_view: Option, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt_opt(data.auth.as_ref(), &context).await; let local_site = LocalSite::read(&mut context.pool()).await?; let is_admin = local_user_view .as_ref() diff --git a/crates/api_crud/src/community/remove.rs b/crates/api_crud/src/community/remove.rs index f0bee639d..3a2cc654a 100644 --- a/crates/api_crud/src/community/remove.rs +++ b/crates/api_crud/src/community/remove.rs @@ -5,7 +5,7 @@ use lemmy_api_common::{ community::{CommunityResponse, RemoveCommunity}, context::LemmyContext, send_activity::{ActivityChannel, SendActivityData}, - utils::{is_admin, local_user_view_from_jwt}, + utils::is_admin, }; use lemmy_db_schema::{ source::{ @@ -14,6 +14,7 @@ use lemmy_db_schema::{ }, traits::Crud, }; +use lemmy_db_views::structs::LocalUserView; use lemmy_utils::{ error::{LemmyError, LemmyErrorExt, LemmyErrorType}, utils::time::naive_from_unix, @@ -23,9 +24,8 @@ use lemmy_utils::{ pub async fn remove_community( data: Json, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; - // Verify its an admin (only an admin can remove a community) is_admin(&local_user_view)?; diff --git a/crates/api_crud/src/community/update.rs b/crates/api_crud/src/community/update.rs index 122cab94e..893128d8c 100644 --- a/crates/api_crud/src/community/update.rs +++ b/crates/api_crud/src/community/update.rs @@ -5,7 +5,7 @@ use lemmy_api_common::{ community::{CommunityResponse, EditCommunity}, context::LemmyContext, send_activity::{ActivityChannel, SendActivityData}, - utils::{local_site_to_slur_regex, local_user_view_from_jwt, sanitize_html_api_opt}, + utils::{local_site_to_slur_regex, sanitize_html_api_opt}, }; use lemmy_db_schema::{ newtypes::PersonId, @@ -17,6 +17,7 @@ use lemmy_db_schema::{ traits::Crud, utils::{diesel_option_overwrite, diesel_option_overwrite_to_url, naive_now}, }; +use lemmy_db_views::structs::LocalUserView; use lemmy_db_views_actor::structs::CommunityModeratorView; use lemmy_utils::{ error::{LemmyError, LemmyErrorExt, LemmyErrorType}, @@ -27,8 +28,8 @@ use lemmy_utils::{ pub async fn update_community( data: Json, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; let local_site = LocalSite::read(&mut context.pool()).await?; let slur_regex = local_site_to_slur_regex(&local_site); diff --git a/crates/api_crud/src/custom_emoji/create.rs b/crates/api_crud/src/custom_emoji/create.rs index 046003627..7a2ae9b2d 100644 --- a/crates/api_crud/src/custom_emoji/create.rs +++ b/crates/api_crud/src/custom_emoji/create.rs @@ -3,23 +3,22 @@ use actix_web::web::Json; use lemmy_api_common::{ context::LemmyContext, custom_emoji::{CreateCustomEmoji, CustomEmojiResponse}, - utils::{is_admin, local_user_view_from_jwt, sanitize_html_api}, + utils::{is_admin, sanitize_html_api}, }; use lemmy_db_schema::source::{ custom_emoji::{CustomEmoji, CustomEmojiInsertForm}, custom_emoji_keyword::{CustomEmojiKeyword, CustomEmojiKeywordInsertForm}, local_site::LocalSite, }; -use lemmy_db_views::structs::CustomEmojiView; +use lemmy_db_views::structs::{CustomEmojiView, LocalUserView}; use lemmy_utils::error::LemmyError; #[tracing::instrument(skip(context))] pub async fn create_custom_emoji( data: Json, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; - let local_site = LocalSite::read(&mut context.pool()).await?; // Make sure user is an admin is_admin(&local_user_view)?; diff --git a/crates/api_crud/src/custom_emoji/delete.rs b/crates/api_crud/src/custom_emoji/delete.rs index be88d310f..44cddd520 100644 --- a/crates/api_crud/src/custom_emoji/delete.rs +++ b/crates/api_crud/src/custom_emoji/delete.rs @@ -3,18 +3,18 @@ use actix_web::web::Json; use lemmy_api_common::{ context::LemmyContext, custom_emoji::{DeleteCustomEmoji, DeleteCustomEmojiResponse}, - utils::{is_admin, local_user_view_from_jwt}, + utils::is_admin, }; use lemmy_db_schema::source::custom_emoji::CustomEmoji; +use lemmy_db_views::structs::LocalUserView; use lemmy_utils::error::LemmyError; #[tracing::instrument(skip(context))] pub async fn delete_custom_emoji( data: Json, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; - // Make sure user is an admin is_admin(&local_user_view)?; CustomEmoji::delete(&mut context.pool(), data.id).await?; diff --git a/crates/api_crud/src/custom_emoji/update.rs b/crates/api_crud/src/custom_emoji/update.rs index 965250feb..5c115d5c1 100644 --- a/crates/api_crud/src/custom_emoji/update.rs +++ b/crates/api_crud/src/custom_emoji/update.rs @@ -3,23 +3,22 @@ use actix_web::web::Json; use lemmy_api_common::{ context::LemmyContext, custom_emoji::{CustomEmojiResponse, EditCustomEmoji}, - utils::{is_admin, local_user_view_from_jwt, sanitize_html_api}, + utils::{is_admin, sanitize_html_api}, }; use lemmy_db_schema::source::{ custom_emoji::{CustomEmoji, CustomEmojiUpdateForm}, custom_emoji_keyword::{CustomEmojiKeyword, CustomEmojiKeywordInsertForm}, local_site::LocalSite, }; -use lemmy_db_views::structs::CustomEmojiView; +use lemmy_db_views::structs::{CustomEmojiView, LocalUserView}; use lemmy_utils::error::LemmyError; #[tracing::instrument(skip(context))] pub async fn update_custom_emoji( data: Json, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; - let local_site = LocalSite::read(&mut context.pool()).await?; // Make sure user is an admin is_admin(&local_user_view)?; diff --git a/crates/api_crud/src/post/create.rs b/crates/api_crud/src/post/create.rs index 8cc6ffe62..5c061cb37 100644 --- a/crates/api_crud/src/post/create.rs +++ b/crates/api_crud/src/post/create.rs @@ -12,7 +12,6 @@ use lemmy_api_common::{ generate_local_apub_endpoint, honeypot_check, local_site_to_slur_regex, - local_user_view_from_jwt, mark_post_as_read, sanitize_html_api, sanitize_html_api_opt, @@ -29,6 +28,7 @@ use lemmy_db_schema::{ }, traits::{Crud, Likeable}, }; +use lemmy_db_views::structs::LocalUserView; use lemmy_db_views_actor::structs::CommunityView; use lemmy_utils::{ error::{LemmyError, LemmyErrorExt, LemmyErrorType}, @@ -46,8 +46,8 @@ use webmention::{Webmention, WebmentionError}; pub async fn create_post( data: Json, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; let local_site = LocalSite::read(&mut context.pool()).await?; let slur_regex = local_site_to_slur_regex(&local_site); diff --git a/crates/api_crud/src/post/delete.rs b/crates/api_crud/src/post/delete.rs index 0f471a527..90c95c6b2 100644 --- a/crates/api_crud/src/post/delete.rs +++ b/crates/api_crud/src/post/delete.rs @@ -5,21 +5,21 @@ use lemmy_api_common::{ context::LemmyContext, post::{DeletePost, PostResponse}, send_activity::{ActivityChannel, SendActivityData}, - utils::{check_community_ban, check_community_deleted_or_removed, local_user_view_from_jwt}, + utils::{check_community_ban, check_community_deleted_or_removed}, }; use lemmy_db_schema::{ source::post::{Post, PostUpdateForm}, traits::Crud, }; +use lemmy_db_views::structs::LocalUserView; use lemmy_utils::error::{LemmyError, LemmyErrorType}; #[tracing::instrument(skip(context))] pub async fn delete_post( data: Json, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; - let post_id = data.post_id; let orig_post = Post::read(&mut context.pool(), post_id).await?; diff --git a/crates/api_crud/src/post/read.rs b/crates/api_crud/src/post/read.rs index d37b1a582..352f97fe1 100644 --- a/crates/api_crud/src/post/read.rs +++ b/crates/api_crud/src/post/read.rs @@ -2,19 +2,17 @@ use actix_web::web::{Data, Json, Query}; use lemmy_api_common::{ context::LemmyContext, post::{GetPost, GetPostResponse}, - utils::{ - check_private_instance, - is_mod_or_admin_opt, - local_user_view_from_jwt_opt, - mark_post_as_read, - }, + utils::{check_private_instance, is_mod_or_admin_opt, mark_post_as_read}, }; use lemmy_db_schema::{ aggregates::structs::{PersonPostAggregates, PersonPostAggregatesForm}, source::{comment::Comment, local_site::LocalSite, post::Post}, traits::Crud, }; -use lemmy_db_views::{post_view::PostQuery, structs::PostView}; +use lemmy_db_views::{ + post_view::PostQuery, + structs::{LocalUserView, PostView}, +}; use lemmy_db_views_actor::structs::{CommunityModeratorView, CommunityView}; use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType}; @@ -22,8 +20,8 @@ use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType}; pub async fn get_post( data: Query, context: Data, + local_user_view: Option, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt_opt(data.auth.as_ref(), &context).await; let local_site = LocalSite::read(&mut context.pool()).await?; check_private_instance(&local_user_view, &local_site)?; diff --git a/crates/api_crud/src/post/remove.rs b/crates/api_crud/src/post/remove.rs index ee100cfdc..52f380d88 100644 --- a/crates/api_crud/src/post/remove.rs +++ b/crates/api_crud/src/post/remove.rs @@ -5,7 +5,7 @@ use lemmy_api_common::{ context::LemmyContext, post::{PostResponse, RemovePost}, send_activity::{ActivityChannel, SendActivityData}, - utils::{check_community_ban, is_mod_or_admin, local_user_view_from_jwt}, + utils::{check_community_ban, is_mod_or_admin}, }; use lemmy_db_schema::{ source::{ @@ -14,15 +14,15 @@ use lemmy_db_schema::{ }, traits::Crud, }; +use lemmy_db_views::structs::LocalUserView; use lemmy_utils::error::LemmyError; #[tracing::instrument(skip(context))] pub async fn remove_post( data: Json, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; - let post_id = data.post_id; let orig_post = Post::read(&mut context.pool(), post_id).await?; diff --git a/crates/api_crud/src/post/update.rs b/crates/api_crud/src/post/update.rs index 880991b8e..04e6191a8 100644 --- a/crates/api_crud/src/post/update.rs +++ b/crates/api_crud/src/post/update.rs @@ -6,12 +6,7 @@ use lemmy_api_common::{ post::{EditPost, PostResponse}, request::fetch_site_data, send_activity::{ActivityChannel, SendActivityData}, - utils::{ - check_community_ban, - local_site_to_slur_regex, - local_user_view_from_jwt, - sanitize_html_api_opt, - }, + utils::{check_community_ban, local_site_to_slur_regex, sanitize_html_api_opt}, }; use lemmy_db_schema::{ source::{ @@ -22,6 +17,7 @@ use lemmy_db_schema::{ traits::Crud, utils::{diesel_option_overwrite, naive_now}, }; +use lemmy_db_views::structs::LocalUserView; use lemmy_utils::{ error::{LemmyError, LemmyErrorExt, LemmyErrorType}, utils::{ @@ -35,8 +31,8 @@ use std::ops::Deref; pub async fn update_post( data: Json, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; let local_site = LocalSite::read(&mut context.pool()).await?; let data_url = data.url.as_ref(); diff --git a/crates/api_crud/src/private_message/create.rs b/crates/api_crud/src/private_message/create.rs index 1e22935ce..c0bdb8ed1 100644 --- a/crates/api_crud/src/private_message/create.rs +++ b/crates/api_crud/src/private_message/create.rs @@ -9,7 +9,6 @@ use lemmy_api_common::{ generate_local_apub_endpoint, get_interface_language, local_site_to_slur_regex, - local_user_view_from_jwt, sanitize_html_api, send_email_to_user, EndpointType, @@ -32,8 +31,8 @@ use lemmy_utils::{ pub async fn create_private_message( data: Json, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; let local_site = LocalSite::read(&mut context.pool()).await?; let content = sanitize_html_api(&data.content); diff --git a/crates/api_crud/src/private_message/delete.rs b/crates/api_crud/src/private_message/delete.rs index 65db3b1c1..ef0864d70 100644 --- a/crates/api_crud/src/private_message/delete.rs +++ b/crates/api_crud/src/private_message/delete.rs @@ -4,22 +4,20 @@ use lemmy_api_common::{ context::LemmyContext, private_message::{DeletePrivateMessage, PrivateMessageResponse}, send_activity::{ActivityChannel, SendActivityData}, - utils::local_user_view_from_jwt, }; use lemmy_db_schema::{ source::private_message::{PrivateMessage, PrivateMessageUpdateForm}, traits::Crud, }; -use lemmy_db_views::structs::PrivateMessageView; +use lemmy_db_views::structs::{LocalUserView, PrivateMessageView}; use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType}; #[tracing::instrument(skip(context))] pub async fn delete_private_message( data: Json, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; - // Checking permissions let private_message_id = data.private_message_id; let orig_private_message = PrivateMessage::read(&mut context.pool(), private_message_id).await?; diff --git a/crates/api_crud/src/private_message/read.rs b/crates/api_crud/src/private_message/read.rs index 0d3ba8620..933d410f1 100644 --- a/crates/api_crud/src/private_message/read.rs +++ b/crates/api_crud/src/private_message/read.rs @@ -2,17 +2,16 @@ use actix_web::web::{Data, Json, Query}; use lemmy_api_common::{ context::LemmyContext, private_message::{GetPrivateMessages, PrivateMessagesResponse}, - utils::local_user_view_from_jwt, }; -use lemmy_db_views::private_message_view::PrivateMessageQuery; +use lemmy_db_views::{private_message_view::PrivateMessageQuery, structs::LocalUserView}; use lemmy_utils::error::LemmyError; #[tracing::instrument(skip(context))] pub async fn get_private_message( data: Query, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(data.auth.as_ref(), &context).await?; let person_id = local_user_view.person.id; let page = data.page; diff --git a/crates/api_crud/src/private_message/update.rs b/crates/api_crud/src/private_message/update.rs index 258dd8bcb..7e55c6416 100644 --- a/crates/api_crud/src/private_message/update.rs +++ b/crates/api_crud/src/private_message/update.rs @@ -4,7 +4,7 @@ use lemmy_api_common::{ context::LemmyContext, private_message::{EditPrivateMessage, PrivateMessageResponse}, send_activity::{ActivityChannel, SendActivityData}, - utils::{local_site_to_slur_regex, local_user_view_from_jwt, sanitize_html_api}, + utils::{local_site_to_slur_regex, sanitize_html_api}, }; use lemmy_db_schema::{ source::{ @@ -14,7 +14,7 @@ use lemmy_db_schema::{ traits::Crud, utils::naive_now, }; -use lemmy_db_views::structs::PrivateMessageView; +use lemmy_db_views::structs::{LocalUserView, PrivateMessageView}; use lemmy_utils::{ error::{LemmyError, LemmyErrorExt, LemmyErrorType}, utils::{slurs::remove_slurs, validation::is_valid_body_field}, @@ -24,8 +24,8 @@ use lemmy_utils::{ pub async fn update_private_message( data: Json, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; let local_site = LocalSite::read(&mut context.pool()).await?; // Checking permissions diff --git a/crates/api_crud/src/site/create.rs b/crates/api_crud/src/site/create.rs index 5cf9a04a7..136a187f2 100644 --- a/crates/api_crud/src/site/create.rs +++ b/crates/api_crud/src/site/create.rs @@ -8,7 +8,6 @@ use lemmy_api_common::{ generate_site_inbox_url, is_admin, local_site_rate_limit_to_rate_limit_config, - local_user_view_from_jwt, sanitize_html_api, sanitize_html_api_opt, }, @@ -24,7 +23,7 @@ use lemmy_db_schema::{ traits::Crud, utils::{diesel_option_overwrite, diesel_option_overwrite_to_url, naive_now}, }; -use lemmy_db_views::structs::SiteView; +use lemmy_db_views::structs::{LocalUserView, SiteView}; use lemmy_utils::{ error::{LemmyError, LemmyErrorType, LemmyResult}, utils::{ @@ -44,8 +43,8 @@ use url::Url; pub async fn create_site( data: Json, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; let local_site = LocalSite::read(&mut context.pool()).await?; // Make sure user is an admin; other types of users should not create site data... @@ -589,7 +588,6 @@ mod tests { blocked_instances: None, taglines: None, registration_mode: site_registration_mode, - auth: Default::default(), } } } diff --git a/crates/api_crud/src/site/read.rs b/crates/api_crud/src/site/read.rs index d435b8684..2f16b8696 100644 --- a/crates/api_crud/src/site/read.rs +++ b/crates/api_crud/src/site/read.rs @@ -1,17 +1,12 @@ -use actix_web::web::{Data, Json, Query}; +use actix_web::web::{Data, Json}; use lemmy_api_common::{ context::LemmyContext, - sensitive::Sensitive, - site::{GetSite, GetSiteResponse, MyUserInfo}, - utils::{check_user_valid, check_validator_time}, + site::{GetSiteResponse, MyUserInfo}, }; -use lemmy_db_schema::{ - newtypes::LocalUserId, - source::{ - actor_language::{LocalUserLanguage, SiteLanguage}, - language::Language, - tagline::Tagline, - }, +use lemmy_db_schema::source::{ + actor_language::{LocalUserLanguage, SiteLanguage}, + language::Language, + tagline::Tagline, }; use lemmy_db_views::structs::{CustomEmojiView, LocalUserView, SiteView}; use lemmy_db_views_actor::structs::{ @@ -23,24 +18,21 @@ use lemmy_db_views_actor::structs::{ PersonView, }; use lemmy_utils::{ - claims::Claims, error::{LemmyError, LemmyErrorExt, LemmyErrorType}, version, }; #[tracing::instrument(skip(context))] pub async fn get_site( - data: Query, context: Data, + local_user_view: Option, ) -> Result, LemmyError> { let site_view = SiteView::read_local(&mut context.pool()).await?; let admins = PersonView::admins(&mut context.pool()).await?; // Build the local user - let my_user = if let Some(local_user_view) = - local_user_settings_view_from_jwt_opt(data.auth.as_ref(), &context).await - { + let my_user = if let Some(local_user_view) = local_user_view { let person_id = local_user_view.person.id; let local_user_id = local_user_view.local_user.id; @@ -100,32 +92,3 @@ pub async fn get_site( custom_emojis, })) } - -#[tracing::instrument(skip_all)] -async fn local_user_settings_view_from_jwt_opt( - jwt: Option<&Sensitive>, - context: &LemmyContext, -) -> Option { - match jwt { - Some(jwt) => { - let claims = Claims::decode(jwt.as_ref(), &context.secret().jwt_secret) - .ok()? - .claims; - let local_user_id = LocalUserId(claims.sub); - let local_user_view = LocalUserView::read(&mut context.pool(), local_user_id) - .await - .ok()?; - check_user_valid( - local_user_view.person.banned, - local_user_view.person.ban_expires, - local_user_view.person.deleted, - ) - .ok()?; - - check_validator_time(&local_user_view.local_user.validator_time, &claims).ok()?; - - Some(local_user_view) - } - None => None, - } -} diff --git a/crates/api_crud/src/site/update.rs b/crates/api_crud/src/site/update.rs index 4d1fbd4d9..792faa785 100644 --- a/crates/api_crud/src/site/update.rs +++ b/crates/api_crud/src/site/update.rs @@ -3,12 +3,7 @@ use actix_web::web::{Data, Json}; use lemmy_api_common::{ context::LemmyContext, site::{EditSite, SiteResponse}, - utils::{ - is_admin, - local_site_rate_limit_to_rate_limit_config, - local_user_view_from_jwt, - sanitize_html_api_opt, - }, + utils::{is_admin, local_site_rate_limit_to_rate_limit_config, sanitize_html_api_opt}, }; use lemmy_db_schema::{ source::{ @@ -25,7 +20,7 @@ use lemmy_db_schema::{ utils::{diesel_option_overwrite, diesel_option_overwrite_to_url, naive_now}, RegistrationMode, }; -use lemmy_db_views::structs::SiteView; +use lemmy_db_views::structs::{LocalUserView, SiteView}; use lemmy_utils::{ error::{LemmyError, LemmyErrorExt, LemmyErrorType, LemmyResult}, utils::{ @@ -44,8 +39,8 @@ use lemmy_utils::{ pub async fn update_site( data: Json, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; let site_view = SiteView::read_local(&mut context.pool()).await?; let local_site = site_view.local_site; let site = site_view.site; @@ -588,7 +583,6 @@ mod tests { taglines: None, registration_mode: site_registration_mode, reports_email_admins: None, - auth: Default::default(), } } } diff --git a/crates/api_crud/src/user/delete.rs b/crates/api_crud/src/user/delete.rs index bf1dcdab1..b3abb532f 100644 --- a/crates/api_crud/src/user/delete.rs +++ b/crates/api_crud/src/user/delete.rs @@ -5,18 +5,18 @@ use lemmy_api_common::{ context::LemmyContext, person::{DeleteAccount, DeleteAccountResponse}, send_activity::{ActivityChannel, SendActivityData}, - utils::{local_user_view_from_jwt, purge_user_account}, + utils::purge_user_account, }; use lemmy_db_schema::source::person::Person; +use lemmy_db_views::structs::LocalUserView; use lemmy_utils::error::{LemmyError, LemmyErrorType}; #[tracing::instrument(skip(context))] pub async fn delete_account( data: Json, context: Data, + local_user_view: LocalUserView, ) -> Result, LemmyError> { - let local_user_view = local_user_view_from_jwt(data.auth.as_ref(), &context).await?; - // Verify the password let valid: bool = verify( &data.password, diff --git a/crates/apub/src/api/list_comments.rs b/crates/apub/src/api/list_comments.rs index cec2ed9c5..7d1de019e 100644 --- a/crates/apub/src/api/list_comments.rs +++ b/crates/apub/src/api/list_comments.rs @@ -8,7 +8,7 @@ use actix_web::web::{Json, Query}; use lemmy_api_common::{ comment::{GetComments, GetCommentsResponse}, context::LemmyContext, - utils::{check_private_instance, local_user_view_from_jwt_opt_new}, + utils::check_private_instance, }; use lemmy_db_schema::{ source::{comment::Comment, community::Community, local_site::LocalSite}, @@ -21,9 +21,8 @@ use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType}; pub async fn list_comments( data: Query, context: Data, - mut local_user_view: Option, + local_user_view: Option, ) -> Result, LemmyError> { - local_user_view_from_jwt_opt_new(&mut local_user_view, data.auth.as_ref(), &context).await; let local_site = LocalSite::read(&mut context.pool()).await?; check_private_instance(&local_user_view, &local_site)?; diff --git a/crates/apub/src/api/list_posts.rs b/crates/apub/src/api/list_posts.rs index 425e2adf2..dc3618c50 100644 --- a/crates/apub/src/api/list_posts.rs +++ b/crates/apub/src/api/list_posts.rs @@ -8,7 +8,7 @@ use actix_web::web::{Json, Query}; use lemmy_api_common::{ context::LemmyContext, post::{GetPosts, GetPostsResponse}, - utils::{check_private_instance, local_user_view_from_jwt_opt_new}, + utils::check_private_instance, }; use lemmy_db_schema::source::{community::Community, local_site::LocalSite}; use lemmy_db_views::{ @@ -21,9 +21,8 @@ use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType}; pub async fn list_posts( data: Query, context: Data, - mut local_user_view: Option, + local_user_view: Option, ) -> Result, LemmyError> { - local_user_view_from_jwt_opt_new(&mut local_user_view, data.auth.as_ref(), &context).await; let local_site = LocalSite::read(&mut context.pool()).await?; check_private_instance(&local_user_view, &local_site)?; diff --git a/crates/apub/src/api/read_community.rs b/crates/apub/src/api/read_community.rs index 76f7f580d..afa6fb829 100644 --- a/crates/apub/src/api/read_community.rs +++ b/crates/apub/src/api/read_community.rs @@ -4,7 +4,7 @@ use actix_web::web::{Json, Query}; use lemmy_api_common::{ community::{GetCommunity, GetCommunityResponse}, context::LemmyContext, - utils::{check_private_instance, is_mod_or_admin_opt, local_user_view_from_jwt_opt_new}, + utils::{check_private_instance, is_mod_or_admin_opt}, }; use lemmy_db_schema::source::{ actor_language::CommunityLanguage, @@ -20,9 +20,8 @@ use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorExt2, LemmyErrorTy pub async fn get_community( data: Query, context: Data, - mut local_user_view: Option, + local_user_view: Option, ) -> Result, LemmyError> { - local_user_view_from_jwt_opt_new(&mut local_user_view, data.auth.as_ref(), &context).await; let local_site = LocalSite::read(&mut context.pool()).await?; if data.name.is_none() && data.id.is_none() { diff --git a/crates/apub/src/api/read_person.rs b/crates/apub/src/api/read_person.rs index 754a942f1..26ad287f1 100644 --- a/crates/apub/src/api/read_person.rs +++ b/crates/apub/src/api/read_person.rs @@ -4,7 +4,7 @@ use actix_web::web::{Json, Query}; use lemmy_api_common::{ context::LemmyContext, person::{GetPersonDetails, GetPersonDetailsResponse}, - utils::{check_private_instance, local_user_view_from_jwt_opt_new}, + utils::check_private_instance, }; use lemmy_db_schema::{ source::{local_site::LocalSite, person::Person}, @@ -18,14 +18,13 @@ use lemmy_utils::error::{LemmyError, LemmyErrorExt2, LemmyErrorType}; pub async fn read_person( data: Query, context: Data, - mut local_user_view: Option, + local_user_view: Option, ) -> Result, LemmyError> { // Check to make sure a person name or an id is given if data.username.is_none() && data.person_id.is_none() { Err(LemmyErrorType::NoIdGiven)? } - local_user_view_from_jwt_opt_new(&mut local_user_view, data.auth.as_ref(), &context).await; let local_site = LocalSite::read(&mut context.pool()).await?; check_private_instance(&local_user_view, &local_site)?; diff --git a/crates/apub/src/api/resolve_object.rs b/crates/apub/src/api/resolve_object.rs index b8c0cef14..e081377f6 100644 --- a/crates/apub/src/api/resolve_object.rs +++ b/crates/apub/src/api/resolve_object.rs @@ -9,7 +9,7 @@ use diesel::NotFound; use lemmy_api_common::{ context::LemmyContext, site::{ResolveObject, ResolveObjectResponse}, - utils::{check_private_instance, local_user_view_from_jwt_opt_new}, + utils::check_private_instance, }; use lemmy_db_schema::{newtypes::PersonId, source::local_site::LocalSite, utils::DbPool}; use lemmy_db_views::structs::{CommentView, LocalUserView, PostView}; @@ -20,9 +20,8 @@ use lemmy_utils::error::{LemmyError, LemmyErrorExt2, LemmyErrorType}; pub async fn resolve_object( data: Query, context: Data, - mut local_user_view: Option, + local_user_view: Option, ) -> Result, LemmyError> { - local_user_view_from_jwt_opt_new(&mut local_user_view, data.auth.as_ref(), &context).await; let local_site = LocalSite::read(&mut context.pool()).await?; check_private_instance(&local_user_view, &local_site)?; let person_id = local_user_view.map(|v| v.person.id); diff --git a/crates/apub/src/api/search.rs b/crates/apub/src/api/search.rs index 262f91681..0c7231e8f 100644 --- a/crates/apub/src/api/search.rs +++ b/crates/apub/src/api/search.rs @@ -4,7 +4,7 @@ use actix_web::web::{Json, Query}; use lemmy_api_common::{ context::LemmyContext, site::{Search, SearchResponse}, - utils::{check_private_instance, is_admin, local_user_view_from_jwt_opt_new}, + utils::{check_private_instance, is_admin}, }; use lemmy_db_schema::{ source::{community::Community, local_site::LocalSite}, @@ -19,9 +19,8 @@ use lemmy_utils::error::LemmyError; pub async fn search( data: Query, context: Data, - mut local_user_view: Option, + local_user_view: Option, ) -> Result, LemmyError> { - local_user_view_from_jwt_opt_new(&mut local_user_view, data.auth.as_ref(), &context).await; let local_site = LocalSite::read(&mut context.pool()).await?; check_private_instance(&local_user_view, &local_site)?; diff --git a/crates/routes/src/images.rs b/crates/routes/src/images.rs index 5133cfd82..db3341418 100644 --- a/crates/routes/src/images.rs +++ b/crates/routes/src/images.rs @@ -11,15 +11,13 @@ use actix_web::{ HttpResponse, }; use futures::stream::{Stream, StreamExt}; -use lemmy_api_common::{context::LemmyContext, utils::local_user_view_from_jwt}; -use lemmy_db_schema::{ - newtypes::LocalUserId, - source::{ - image_upload::{ImageUpload, ImageUploadForm}, - local_site::LocalSite, - }, +use lemmy_api_common::context::LemmyContext; +use lemmy_db_schema::source::{ + image_upload::{ImageUpload, ImageUploadForm}, + local_site::LocalSite, }; -use lemmy_utils::{claims::Claims, rate_limit::RateLimitCell, REQWEST_TIMEOUT}; +use lemmy_db_views::structs::LocalUserView; +use lemmy_utils::{rate_limit::RateLimitCell, REQWEST_TIMEOUT}; use reqwest::Body; use reqwest_middleware::{ClientWithMiddleware, RequestBuilder}; use serde::{Deserialize, Serialize}; @@ -96,15 +94,10 @@ async fn upload( body: web::Payload, client: web::Data, context: web::Data, + // require login + local_user_view: LocalUserView, ) -> Result { // TODO: check rate limit here - let jwt = req.cookie("jwt").ok_or(error::ErrorUnauthorized( - "No auth header for picture upload", - ))?; - let claims = Claims::decode(jwt.value(), &context.secret().jwt_secret); - if claims.is_err() { - return Ok(HttpResponse::Unauthorized().finish()); - }; let pictrs_config = context.settings().pictrs_config()?; let image_url = format!("{}image", pictrs_config.url); @@ -123,10 +116,9 @@ async fn upload( let status = res.status(); let images = res.json::().await.map_err(error::ErrorBadRequest)?; if let Some(images) = &images.files { - let local_user_id = LocalUserId(claims?.claims.sub); for uploaded_image in images { let form = ImageUploadForm { - local_user_id, + local_user_id: local_user_view.local_user.id, pictrs_alias: uploaded_image.file.to_string(), pictrs_delete_token: uploaded_image.delete_token.to_string(), }; @@ -145,21 +137,14 @@ async fn full_res( req: HttpRequest, client: web::Data, context: web::Data, + local_user_view: Option, ) -> Result { // block access to images if instance is private and unauthorized, public let local_site = LocalSite::read(&mut context.pool()) .await .map_err(error::ErrorBadRequest)?; - if local_site.private_instance { - let jwt = req.cookie("jwt").ok_or(error::ErrorUnauthorized( - "No auth header for picture access", - ))?; - if local_user_view_from_jwt(jwt.value(), &context) - .await - .is_err() - { - return Ok(HttpResponse::Unauthorized().finish()); - }; + if local_site.private_instance && local_user_view.is_none() { + return Ok(HttpResponse::Unauthorized().finish()); } let name = &filename.into_inner(); @@ -219,6 +204,8 @@ async fn delete( req: HttpRequest, client: web::Data, context: web::Data, + // require login + _local_user_view: LocalUserView, ) -> Result { let (token, file) = components.into_inner(); diff --git a/src/session_middleware.rs b/src/session_middleware.rs index 5824f33df..c48f6f1c7 100644 --- a/src/session_middleware.rs +++ b/src/session_middleware.rs @@ -6,10 +6,19 @@ use actix_web::{ Error, HttpMessage, }; +use chrono::{DateTime, Utc}; use core::future::Ready; use futures_util::future::LocalBoxFuture; -use lemmy_api_common::{context::LemmyContext, utils::local_user_view_from_jwt}; -use lemmy_utils::error::{LemmyError, LemmyErrorType}; +use lemmy_api_common::{ + context::LemmyContext, + lemmy_db_views::structs::LocalUserView, + utils::check_user_valid, +}; +use lemmy_db_schema::newtypes::LocalUserId; +use lemmy_utils::{ + claims::Claims, + error::{LemmyError, LemmyErrorExt2, LemmyErrorType}, +}; use reqwest::header::HeaderValue; use std::{future::ready, rc::Rc}; @@ -118,3 +127,108 @@ where }) } } + +#[tracing::instrument(skip_all)] +async fn local_user_view_from_jwt( + jwt: &str, + context: &LemmyContext, +) -> Result { + let claims = Claims::decode(jwt, &context.secret().jwt_secret) + .with_lemmy_type(LemmyErrorType::NotLoggedIn)? + .claims; + let local_user_id = LocalUserId(claims.sub); + let local_user_view = LocalUserView::read(&mut context.pool(), local_user_id).await?; + check_user_valid( + local_user_view.person.banned, + local_user_view.person.ban_expires, + local_user_view.person.deleted, + )?; + + check_validator_time(&local_user_view.local_user.validator_time, &claims)?; + + Ok(local_user_view) +} + +/// Checks if user's token was issued before user's password reset. +fn check_validator_time(validator_time: &DateTime, claims: &Claims) -> Result<(), LemmyError> { + let user_validation_time = validator_time.timestamp(); + if user_validation_time > claims.iat { + Err(LemmyErrorType::NotLoggedIn)? + } else { + Ok(()) + } +} + +#[cfg(test)] +mod tests { + #![allow(clippy::unwrap_used)] + #![allow(clippy::indexing_slicing)] + + use super::*; + use lemmy_db_schema::{ + source::{ + instance::Instance, + local_user::{LocalUser, LocalUserInsertForm}, + person::{Person, PersonInsertForm}, + secret::Secret, + }, + traits::Crud, + utils::build_db_pool_for_tests, + }; + use lemmy_utils::{claims::Claims, settings::SETTINGS}; + use serial_test::serial; + use std::env; + + #[tokio::test] + #[serial] + async fn test_session_auth() { + let pool = &build_db_pool_for_tests().await; + let pool = &mut pool.into(); + let secret = Secret::init(pool).await.unwrap(); + + // test.sh sets `LEMMY_CONFIG_LOCATION=../../config/config.hjson` for code under crates folder. + // this results in a config not found error, so we need to unset this var and use default. + env::remove_var("LEMMY_CONFIG_LOCATION"); + let settings = &SETTINGS.to_owned(); + + let inserted_instance = Instance::read_or_create(pool, "my_domain.tld".to_string()) + .await + .unwrap(); + + let new_person = PersonInsertForm::builder() + .name("Gerry9812".into()) + .public_key("pubkey".to_string()) + .instance_id(inserted_instance.id) + .build(); + + let inserted_person = Person::create(pool, &new_person).await.unwrap(); + + let local_user_form = LocalUserInsertForm::builder() + .person_id(inserted_person.id) + .password_encrypted("123456".to_string()) + .build(); + + let inserted_local_user = LocalUser::create(pool, &local_user_form).await.unwrap(); + + let jwt = Claims::jwt( + inserted_local_user.id.0, + &secret.jwt_secret, + &settings.hostname, + ) + .unwrap(); + let claims = Claims::decode(&jwt, &secret.jwt_secret).unwrap().claims; + let check = check_validator_time(&inserted_local_user.validator_time, &claims); + assert!(check.is_ok()); + + // The check should fail, since the validator time is now newer than the jwt issue time + let updated_local_user = + LocalUser::update_password(pool, inserted_local_user.id, "password111") + .await + .unwrap(); + let check_after = check_validator_time(&updated_local_user.validator_time, &claims); + assert!(check_after.is_err()); + + let num_deleted = Person::delete(pool, inserted_person.id).await.unwrap(); + assert_eq!(1, num_deleted); + } +} From 459d5a372648f1e2b58244a1694a5d2c2ba93a34 Mon Sep 17 00:00:00 2001 From: phiresky Date: Thu, 21 Sep 2023 11:07:20 +0000 Subject: [PATCH 37/44] Revert "re-remove lemmy logs" This reverts commit ac0c0c88564b1cb6c6aab7ec3aeff8ccc2e2b15f. --- .woodpecker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.woodpecker.yml b/.woodpecker.yml index 49fbe3db2..c180d8d58 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -204,7 +204,7 @@ steps: - bash api_tests/prepare-drone-federation-test.sh - cd api_tests/ - yarn - - yarn api-test + - tail -f /tmp/lemmy*.out & yarn api-test when: *slow_check_paths rebuild-cache: From 6d519ef376cf45d1231b18c2aa6cfa641e09b411 Mon Sep 17 00:00:00 2001 From: phiresky Date: Thu, 21 Sep 2023 11:07:36 +0000 Subject: [PATCH 38/44] Revert "re-remove debug comments" This reverts commit ae37ca0137b2139cc84285464c3002bf4c7ee6e0. --- crates/apub/src/activities/mod.rs | 3 ++- crates/federate/src/worker.rs | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/crates/apub/src/activities/mod.rs b/crates/apub/src/activities/mod.rs index 958065ffa..54a96014e 100644 --- a/crates/apub/src/activities/mod.rs +++ b/crates/apub/src/activities/mod.rs @@ -230,7 +230,8 @@ where actor_type: actor.actor_type(), actor_apub_id: actor.id().into(), }; - SentActivity::create(&mut data.pool(), form).await?; + let created = SentActivity::create(&mut data.pool(), form).await?; + info!("Queued for send: {:?}", created); Ok(()) } diff --git a/crates/federate/src/worker.rs b/crates/federate/src/worker.rs index b6e174c04..14c86a7d3 100644 --- a/crates/federate/src/worker.rs +++ b/crates/federate/src/worker.rs @@ -161,13 +161,21 @@ impl InstanceWorker { { id += 1; processed_activities += 1; + tracing::info!("looking at activity {id}, proc={processed_activities}, latest={latest_id}"); let Some(ele) = get_activity_cached(pool, id) .await .context("failed reading activity from db")? else { + tracing::info!("activity {id} empty, marking latest"); self.state.last_successful_id = id; continue; }; + tracing::info!( + "processing send of {} {} for {}", + ele.0.id, + ele.0.ap_id, + self.instance.domain + ); if let Err(e) = self.send_retry_loop(pool, &ele.0, &ele.1).await { tracing::warn!( "sending {} errored internally, skipping activity: {:?}", @@ -197,6 +205,13 @@ impl InstanceWorker { .get_inbox_urls(pool, activity) .await .context("failed figuring out inbox urls")?; + tracing::info!( + "inboxes of {} for {} {}: {:?}", + self.instance.domain, + activity.id, + activity.ap_id, + inbox_urls + ); if inbox_urls.is_empty() { self.state.last_successful_id = activity.id; return Ok(()); From dec25f9ee8387f3ef78a882e1fcc400344f63364 Mon Sep 17 00:00:00 2001 From: phiresky Date: Thu, 21 Sep 2023 11:11:54 +0000 Subject: [PATCH 39/44] ensure overlap --- crates/federate/src/worker.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/federate/src/worker.rs b/crates/federate/src/worker.rs index 14c86a7d3..dea82ea3f 100644 --- a/crates/federate/src/worker.rs +++ b/crates/federate/src/worker.rs @@ -320,7 +320,7 @@ impl InstanceWorker { instance_id: InstanceId, last_fetch: DateTime, ) -> Result<(HashMap>, DateTime)> { - let new_last_fetch = Utc::now(); // update to time before fetch to ensure overlap + let new_last_fetch = Utc::now() - chrono::Duration::seconds(10); // update to time before fetch to ensure overlap. subtract 10s to ensure overlap even if published date is not exact Ok(( CommunityFollowerView::get_instance_followed_community_inboxes(pool, instance_id, last_fetch) .await? From 2c283d90ca60b5b8e39d71562e1865ad652e6c72 Mon Sep 17 00:00:00 2001 From: phiresky Date: Thu, 21 Sep 2023 11:45:33 +0000 Subject: [PATCH 40/44] Revert "Revert "re-remove debug comments"" This reverts commit 6d519ef376cf45d1231b18c2aa6cfa641e09b411. --- crates/apub/src/activities/mod.rs | 3 +-- crates/federate/src/worker.rs | 15 --------------- 2 files changed, 1 insertion(+), 17 deletions(-) diff --git a/crates/apub/src/activities/mod.rs b/crates/apub/src/activities/mod.rs index 54a96014e..958065ffa 100644 --- a/crates/apub/src/activities/mod.rs +++ b/crates/apub/src/activities/mod.rs @@ -230,8 +230,7 @@ where actor_type: actor.actor_type(), actor_apub_id: actor.id().into(), }; - let created = SentActivity::create(&mut data.pool(), form).await?; - info!("Queued for send: {:?}", created); + SentActivity::create(&mut data.pool(), form).await?; Ok(()) } diff --git a/crates/federate/src/worker.rs b/crates/federate/src/worker.rs index dea82ea3f..3eda2e746 100644 --- a/crates/federate/src/worker.rs +++ b/crates/federate/src/worker.rs @@ -161,21 +161,13 @@ impl InstanceWorker { { id += 1; processed_activities += 1; - tracing::info!("looking at activity {id}, proc={processed_activities}, latest={latest_id}"); let Some(ele) = get_activity_cached(pool, id) .await .context("failed reading activity from db")? else { - tracing::info!("activity {id} empty, marking latest"); self.state.last_successful_id = id; continue; }; - tracing::info!( - "processing send of {} {} for {}", - ele.0.id, - ele.0.ap_id, - self.instance.domain - ); if let Err(e) = self.send_retry_loop(pool, &ele.0, &ele.1).await { tracing::warn!( "sending {} errored internally, skipping activity: {:?}", @@ -205,13 +197,6 @@ impl InstanceWorker { .get_inbox_urls(pool, activity) .await .context("failed figuring out inbox urls")?; - tracing::info!( - "inboxes of {} for {} {}: {:?}", - self.instance.domain, - activity.id, - activity.ap_id, - inbox_urls - ); if inbox_urls.is_empty() { self.state.last_successful_id = activity.id; return Ok(()); From 07ffdc3d53ff56cc80209985588bb2dbdc891d19 Mon Sep 17 00:00:00 2001 From: phiresky Date: Thu, 21 Sep 2023 11:45:43 +0000 Subject: [PATCH 41/44] Revert "Revert "re-remove lemmy logs"" This reverts commit 459d5a372648f1e2b58244a1694a5d2c2ba93a34. --- .woodpecker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.woodpecker.yml b/.woodpecker.yml index c180d8d58..49fbe3db2 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -204,7 +204,7 @@ steps: - bash api_tests/prepare-drone-federation-test.sh - cd api_tests/ - yarn - - tail -f /tmp/lemmy*.out & yarn api-test + - yarn api-test when: *slow_check_paths rebuild-cache: From 31f3677270af509ca48965de736e09e2df939778 Mon Sep 17 00:00:00 2001 From: phiresky Date: Thu, 21 Sep 2023 12:01:22 +0000 Subject: [PATCH 42/44] fix after merge --- api_tests/src/comment.spec.ts | 7 +++---- api_tests/src/community.spec.ts | 5 ++--- api_tests/src/post.spec.ts | 15 ++++++--------- 3 files changed, 11 insertions(+), 16 deletions(-) diff --git a/api_tests/src/comment.spec.ts b/api_tests/src/comment.spec.ts index 47321f9cc..fe8c3943e 100644 --- a/api_tests/src/comment.spec.ts +++ b/api_tests/src/comment.spec.ts @@ -504,8 +504,7 @@ test("A and G subscribe to B (center) A posts, G mentions B, it gets announced t expect(alphaPost.post_view.community.local).toBe(true); // Make sure gamma sees it - let gammaPost = (await resolvePost(gamma, alphaPost.post_view.post, false))! - .post; + let gammaPost = (await resolvePost(gamma, alphaPost.post_view.post))!.post; if (!gammaPost) { throw "Missing gamma post"; @@ -670,8 +669,8 @@ test("Fetch in_reply_tos: A is unsubbed from B, B makes a post, and some embedde expect(updateRes.comment_view.comment.content).toBe(updatedCommentContent); // Get the post from alpha - let alphaPostB = (await resolvePost(alpha, postOnBetaRes.post_view.post)) - .post; + let alphaPostB = await waitForPost(alpha, postOnBetaRes.post_view.post); + if (!alphaPostB) { throw "Missing alpha post B"; } diff --git a/api_tests/src/community.spec.ts b/api_tests/src/community.spec.ts index f9d83c8cf..b81dd900c 100644 --- a/api_tests/src/community.spec.ts +++ b/api_tests/src/community.spec.ts @@ -240,7 +240,7 @@ test("Admin actions in remote community are not federated to origin", async () = expect(banRes.banned).toBe(true); // ban doesnt federate to community's origin instance alpha - let alphaPost = (await resolvePost(alpha, gammaPost.post, false)).post; + let alphaPost = (await resolvePost(alpha, gammaPost.post)).post; expect(alphaPost?.creator_banned_from_community).toBe(false); // and neither to gamma @@ -352,8 +352,7 @@ test("User blocks instance, communities are hidden", async () => { expect(postRes.post_view.post.id).toBeDefined(); // fetch post to alpha - let alphaPost = (await resolvePost(alpha, postRes.post_view.post, false)) - .post!; + let alphaPost = (await resolvePost(alpha, postRes.post_view.post)).post!; expect(alphaPost.post).toBeDefined(); // post should be included in listing diff --git a/api_tests/src/post.spec.ts b/api_tests/src/post.spec.ts index 5e656e2f4..51a10293b 100644 --- a/api_tests/src/post.spec.ts +++ b/api_tests/src/post.spec.ts @@ -192,8 +192,7 @@ test("Sticky a post", async () => { expect(betaPost2?.post.featured_community).toBe(false); // Make sure that gamma cannot sticky the post on beta - let gammaPost = (await resolvePost(gamma, postRes.post_view.post, false)) - .post; + let gammaPost = (await resolvePost(gamma, postRes.post_view.post)).post; if (!gammaPost) { throw "Missing gamma post"; } @@ -300,8 +299,7 @@ test("Remove a post from admin and community on different instance", async () => } let postRes = await createPost(gamma, gammaCommunity.id); - let alphaPost = (await resolvePost(alpha, postRes.post_view.post, false)) - .post; + let alphaPost = (await resolvePost(alpha, postRes.post_view.post)).post; if (!alphaPost) { throw "Missing alpha post"; } @@ -310,7 +308,7 @@ test("Remove a post from admin and community on different instance", async () => expect(removedPost.post_view.post.name).toBe(postRes.post_view.post.name); // Make sure lemmy beta sees post is NOT removed - let betaPost = (await resolvePost(beta, postRes.post_view.post, false)).post; + let betaPost = (await resolvePost(beta, postRes.post_view.post)).post; if (!betaPost) { throw "Missing beta post"; } @@ -504,7 +502,7 @@ test("A and G subscribe to B (center) A posts, it gets announced to G", async () let postRes = await createPost(alpha, betaCommunity.community.id); expect(postRes.post_view.post).toBeDefined(); - let betaPost = (await resolvePost(gamma, postRes.post_view.post, false)).post; + let betaPost = (await resolvePost(gamma, postRes.post_view.post)).post; expect(betaPost?.post.name).toBeDefined(); }); @@ -517,8 +515,7 @@ test("Report a post", async () => { let postRes = await createPost(beta, betaCommunity.community.id); expect(postRes.post_view.post).toBeDefined(); - let alphaPost = (await resolvePost(alpha, postRes.post_view.post, false)) - .post; + let alphaPost = (await resolvePost(alpha, postRes.post_view.post)).post; if (!alphaPost) { throw "Missing alpha post"; } @@ -563,7 +560,7 @@ test("Sanitize HTML", async () => { "<script>alert('xss');</script> hello &"'", ); - let alphaPost = (await resolvePost(alpha, post.post_view.post, false)).post; + let alphaPost = (await resolvePost(alpha, post.post_view.post)).post; // second escaping over federation, avoid double escape of & expect(alphaPost?.post.body).toBe( "<script>alert('xss');</script> hello &"'", From fe40adfc39d09273145bd8649374ca43ed81ab5e Mon Sep 17 00:00:00 2001 From: phiresky Date: Thu, 21 Sep 2023 12:32:41 +0000 Subject: [PATCH 43/44] fix after merge --- api_tests/src/shared.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api_tests/src/shared.ts b/api_tests/src/shared.ts index f50b64e64..a1868f8f2 100644 --- a/api_tests/src/shared.ts +++ b/api_tests/src/shared.ts @@ -291,7 +291,7 @@ export async function searchPostLocal( /// wait for a post to appear locally without pulling it export async function waitForPost( - api: API, + api: LemmyHttp, post: Post, checker: (t: PostView | undefined) => boolean = p => !!p, ) { From 9bcadadede08cc5e724bd394e9d21e17cbf458e1 Mon Sep 17 00:00:00 2001 From: phiresky Date: Thu, 21 Sep 2023 12:52:10 +0000 Subject: [PATCH 44/44] fix after merge --- api_tests/src/comment.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api_tests/src/comment.spec.ts b/api_tests/src/comment.spec.ts index fe8c3943e..6ced2bf33 100644 --- a/api_tests/src/comment.spec.ts +++ b/api_tests/src/comment.spec.ts @@ -343,7 +343,7 @@ test("Federated comment like", async () => { }); test("Reply to a comment from another instance, get notification", async () => { - await alpha.client.markAllAsRead({ auth: alpha.auth }); + await alpha.markAllAsRead(); let betaCommunity = (await resolveBetaCommunity(alpha)).community; if (!betaCommunity) {