]> Untitled Git - lemmy.git/commitdiff
Merge branch 'main' of https://github.com/lemmynet/lemmy into main
authorDessalines <tyhou13@gmx.com>
Tue, 22 Sep 2020 15:12:36 +0000 (10:12 -0500)
committerDessalines <tyhou13@gmx.com>
Tue, 22 Sep 2020 15:12:36 +0000 (10:12 -0500)
12 files changed:
.travis.yml
docker/federation/run-tests.bash [moved from docker/federation/run-tests.sh with 100% similarity]
docker/travis/run-tests.bash [moved from docker/travis/run-tests.sh with 100% similarity]
docs/src/contributing_docker_development.md
docs/src/contributing_federation_development.md
docs/src/contributing_tests.md
lemmy_utils/src/lib.rs
src/apub/activity_queue.rs
src/lib.rs
src/main.rs
src/websocket/chat_server.rs
tests/integration_test.rs [new file with mode: 0644]

index 350e0a8e86a87e80ba9e404590e6d38f6675cbb8..64874904325a2c082e4cab0e9e7a8355f2984288 100644 (file)
@@ -20,7 +20,7 @@ before_install:
 # Change dir
 - cd docker/travis
 script:
-- "./run-tests.sh"
+- "./run-tests.bash"
 deploy:
   provider: script
   script: bash docker_push.sh
index 23b9fa00506fdf81b93d6543bedfa758748a7636..586055a067e62ca8f97a8bb796f1a642a99f429d 100644 (file)
@@ -1,10 +1,16 @@
 # Docker Development
 
-## Running
+## Dependencies (on Ubuntu)
 
 ```bash
 sudo apt install git docker-compose
+sudo systemctl start docker
 git clone https://github.com/LemmyNet/lemmy
+```
+
+## Running
+
+```bash
 cd lemmy/docker/dev
 sudo docker-compose up --no-deps --build
 ```
index 08c4e5ca9fcdc1effade7091331acbab4659de10..1d2436033cf6446dc01aa1d55619f2a8ded00c54 100644 (file)
@@ -1,21 +1,9 @@
 # Federation Development
 
-## Setup
-
-If you don't have a local clone of the Lemmy repo yet, just run the following command:
-
-```bash
-git clone https://github.com/LemmyNet/lemmy
-```
-
 ## Running locally
 
-You need to have the following packages installed, the Docker service needs to be running.
-
-- docker
-- docker-compose
+Install the dependencies as described in [Docker development](contributing_docker_development.md). Then run the following
 
-Then run the following
 ```bash
 cd docker/federation
 ./start-local-instances.bash
@@ -40,15 +28,6 @@ To start federation between instances, visit one of them and search for a user,
 
 Firefox containers are a good way to test them interacting.
 
-## Integration tests
-
-To run a suite of suite of federation integration tests:
-
-```bash
-cd docker/federation
-./run-tests.bash
-```
-
 ## Running on a server
 
 Note that federation is currently in alpha. **Only use it for testing**, not on any production server, and be aware that turning on federation may break your instance.
index e40836c30fd653924dea484560ac9c5cac0570fc..494cf5cd949a79882d669bb05a0235baa18127c1 100644 (file)
@@ -12,5 +12,9 @@ psql -U lemmy -c "DROP SCHEMA public CASCADE; CREATE SCHEMA public;"
 
 ### Federation
 
-Install the [Docker development dependencies](contributing_docker_development.md), and execute
-`docker/federation-test/run-tests.sh`
+Install the [Docker development dependencies](contributing_docker_development.md), and execute:
+
+```
+cd docker/federation
+./run-tests.bash
+```
index 9cc1fe025c498550881aa4c636327c2c116ab067..247705e420e2807436b985307aade45fc027bf19 100644 (file)
@@ -57,7 +57,7 @@ impl APIError {
 
 #[derive(Debug)]
 pub struct LemmyError {
-  inner: anyhow::Error,
+  pub inner: anyhow::Error,
 }
 
 impl<T> From<T> for LemmyError
index 008846bf357bb5ada84bfe73088fdf63d1ce5b2a..a48cf5bd2184abc2dc4a7695b6913fee4cc3a6fb 100644 (file)
@@ -79,7 +79,6 @@ impl ActixJob for SendActivityTask {
           .post(to_url.as_str())
           .header("Content-Type", "application/json");
 
-        // TODO: i believe we have to do the signing in here because it is only valid for a few seconds
         let signed = sign(
           request,
           self.activity.clone(),
index 2bab3552aed4c1bf25f49dfc0f4c233d2afc450a..5d5f00b0de01960d0181212995656c5ca2bfffce 100644 (file)
@@ -50,7 +50,7 @@ pub struct LemmyContext {
 }
 
 impl LemmyContext {
-  pub fn create(
+  pub fn new(
     pool: DbPool,
     chat_server: Addr<ChatServer>,
     client: Client,
@@ -79,12 +79,12 @@ impl LemmyContext {
 
 impl Clone for LemmyContext {
   fn clone(&self) -> Self {
-    LemmyContext {
-      pool: self.pool.clone(),
-      chat_server: self.chat_server.clone(),
-      client: self.client.clone(),
-      activity_queue: self.activity_queue.clone(),
-    }
+    LemmyContext::new(
+      self.pool.clone(),
+      self.chat_server.clone(),
+      self.client.clone(),
+      self.activity_queue.clone(),
+    )
   }
 }
 
index 800196cfe9204260471f0b1f1e0db260b27a4da5..d14e006e2fb75be8fedc938804d68dd58e1b7a29 100644 (file)
@@ -84,7 +84,7 @@ async fn main() -> Result<(), LemmyError> {
 
   // Create Http server with websocket support
   HttpServer::new(move || {
-    let context = LemmyContext::create(
+    let context = LemmyContext::new(
       pool.clone(),
       chat_server.to_owned(),
       Client::default(),
index 0c4dfb0ba1e5075cec35d9062cf17dd64e9c2fdb..611f44f9715ba6caa12e6b92e4c6d218787b8d7a 100644 (file)
@@ -361,12 +361,7 @@ impl ChatServer {
 
       let user_operation: UserOperation = UserOperation::from_str(&op)?;
 
-      let context = LemmyContext {
-        pool,
-        chat_server: addr,
-        client,
-        activity_queue,
-      };
+      let context = LemmyContext::new(pool, addr, client, activity_queue);
       let args = Args {
         context,
         rate_limiter,
diff --git a/tests/integration_test.rs b/tests/integration_test.rs
new file mode 100644 (file)
index 0000000..4f280f6
--- /dev/null
@@ -0,0 +1,208 @@
+extern crate lemmy_server;
+
+use activitystreams::{
+  activity::{
+    kind::{CreateType, FollowType},
+    ActorAndObject,
+  },
+  base::{BaseExt, ExtendsExt},
+  object::{Note, ObjectExt},
+};
+use actix::prelude::*;
+use actix_web::{test::TestRequest, web, web::Path, HttpRequest};
+use chrono::Utc;
+use diesel::{
+  r2d2::{ConnectionManager, Pool},
+  PgConnection,
+};
+use http_signature_normalization_actix::PrepareVerifyError;
+use lemmy_db::{
+  community::{Community, CommunityForm},
+  user::{User_, *},
+  Crud,
+  ListingType,
+  SortType,
+};
+use lemmy_rate_limit::{rate_limiter::RateLimiter, RateLimit};
+use lemmy_server::{
+  apub::{
+    activity_queue::create_activity_queue,
+    inbox::{
+      community_inbox,
+      community_inbox::community_inbox,
+      shared_inbox,
+      shared_inbox::shared_inbox,
+      user_inbox,
+      user_inbox::user_inbox,
+    },
+  },
+  websocket::chat_server::ChatServer,
+  LemmyContext,
+};
+use lemmy_utils::{apub::generate_actor_keypair, settings::Settings};
+use reqwest::Client;
+use serde::{Deserialize, Serialize};
+use std::sync::Arc;
+use tokio::sync::Mutex;
+use url::Url;
+
+fn create_context() -> LemmyContext {
+  let settings = Settings::get();
+  let db_url = settings.get_database_url();
+  let manager = ConnectionManager::<PgConnection>::new(&db_url);
+  let pool = Pool::builder()
+    .max_size(settings.database.pool_size)
+    .build(manager)
+    .unwrap();
+  let rate_limiter = RateLimit {
+    rate_limiter: Arc::new(Mutex::new(RateLimiter::default())),
+  };
+  let activity_queue = create_activity_queue();
+  let chat_server = ChatServer::startup(
+    pool.clone(),
+    rate_limiter.clone(),
+    Client::default(),
+    activity_queue.clone(),
+  )
+  .start();
+  LemmyContext::new(
+    pool,
+    chat_server,
+    Client::default(),
+    create_activity_queue(),
+  )
+}
+
+fn create_user(conn: &PgConnection, name: &str) -> User_ {
+  let user_keypair = generate_actor_keypair().unwrap();
+  let new_user = UserForm {
+    name: name.into(),
+    preferred_username: None,
+    password_encrypted: "nope".into(),
+    email: None,
+    matrix_user_id: None,
+    avatar: None,
+    banner: None,
+    admin: false,
+    banned: false,
+    updated: None,
+    show_nsfw: false,
+    theme: "darkly".into(),
+    default_sort_type: SortType::Hot as i16,
+    default_listing_type: ListingType::Subscribed as i16,
+    lang: "browser".into(),
+    show_avatars: true,
+    send_notifications_to_email: false,
+    actor_id: Some(format!("http://localhost:8536/u/{}", name).to_string()),
+    bio: None,
+    local: true,
+    private_key: Some(user_keypair.private_key),
+    public_key: Some(user_keypair.public_key),
+    last_refreshed_at: None,
+  };
+
+  User_::create(&conn, &new_user).unwrap()
+}
+
+fn create_community(conn: &PgConnection, creator_id: i32) -> Community {
+  let new_community = CommunityForm {
+    name: "test_community".into(),
+    creator_id,
+    title: "test_community".to_owned(),
+    description: None,
+    category_id: 1,
+    nsfw: false,
+    removed: None,
+    deleted: None,
+    updated: None,
+    actor_id: None,
+    local: true,
+    private_key: None,
+    public_key: None,
+    last_refreshed_at: None,
+    published: None,
+    icon: None,
+    banner: None,
+  };
+  Community::create(&conn, &new_community).unwrap()
+}
+fn create_activity<'a, Activity, Return>(user_id: String) -> web::Json<Return>
+where
+  for<'de> Return: Deserialize<'de> + 'a,
+  Activity: std::default::Default + Serialize,
+{
+  let mut activity = ActorAndObject::<Activity>::new(user_id, Note::new().into_any_base().unwrap());
+  activity
+    .set_id(Url::parse("http://localhost:8536/create/1").unwrap())
+    .set_many_ccs(vec![Url::parse("http://localhost:8536/c/main").unwrap()]);
+  let activity = serde_json::to_value(&activity).unwrap();
+  let activity: Return = serde_json::from_value(activity).unwrap();
+  web::Json(activity)
+}
+
+fn create_http_request() -> HttpRequest {
+  let time1 = Utc::now().timestamp();
+  let time2 = Utc::now().timestamp();
+  let signature = format!(
+    r#"keyId="my-key-id",algorithm="hs2019",created="{}",expires="{}",headers="(request-target) (created) (expires) date content-type",signature="blah blah blah""#,
+    time1, time2
+  );
+  TestRequest::post()
+    .uri("http://localhost:8536/")
+    .header("Signature", signature)
+    .to_http_request()
+}
+
+#[actix_rt::test]
+async fn test_shared_inbox_expired_signature() {
+  let request = create_http_request();
+  let context = create_context();
+  let connection = &context.pool().get().unwrap();
+  let user = create_user(connection, "shared_inbox_rvgfd");
+  let activity =
+    create_activity::<CreateType, ActorAndObject<shared_inbox::ValidTypes>>(user.actor_id);
+  let response = shared_inbox(request, activity, web::Data::new(context)).await;
+  assert_eq!(
+    format!("{}", response.err().unwrap()),
+    format!("{}", PrepareVerifyError::Expired)
+  );
+  User_::delete(connection, user.id).unwrap();
+}
+
+#[actix_rt::test]
+async fn test_user_inbox_expired_signature() {
+  let request = create_http_request();
+  let context = create_context();
+  let connection = &context.pool().get().unwrap();
+  let user = create_user(connection, "user_inbox_cgsax");
+  let activity =
+    create_activity::<CreateType, ActorAndObject<user_inbox::ValidTypes>>(user.actor_id);
+  let path = Path::<String> {
+    0: "username".to_string(),
+  };
+  let response = user_inbox(request, activity, path, web::Data::new(context)).await;
+  assert_eq!(
+    format!("{}", response.err().unwrap()),
+    format!("{}", PrepareVerifyError::Expired)
+  );
+  User_::delete(connection, user.id).unwrap();
+}
+
+#[actix_rt::test]
+async fn test_community_inbox_expired_signature() {
+  let context = create_context();
+  let connection = &context.pool().get().unwrap();
+  let user = create_user(connection, "community_inbox_hrxa");
+  let community = create_community(connection, user.id);
+  let request = create_http_request();
+  let activity =
+    create_activity::<FollowType, ActorAndObject<community_inbox::ValidTypes>>(user.actor_id);
+  let path = Path::<String> { 0: community.name };
+  let response = community_inbox(request, activity, path, web::Data::new(context)).await;
+  assert_eq!(
+    format!("{}", response.err().unwrap()),
+    format!("{}", PrepareVerifyError::Expired)
+  );
+  User_::delete(connection, user.id).unwrap();
+  Community::delete(connection, community.id).unwrap();
+}