1 extern crate lemmy_server;
4 extern crate diesel_migrations;
7 kind::{CreateType, FollowType},
10 base::{BaseExt, ExtendsExt},
11 object::{Note, ObjectExt},
13 use actix::prelude::*;
14 use actix_web::{test::TestRequest, web, web::Path, HttpRequest};
17 r2d2::{ConnectionManager, Pool},
20 use http_signature_normalization_actix::PrepareVerifyError;
21 use lemmy_api::match_websocket_operation;
23 activity_queue::create_activity_queue,
26 community_inbox::community_inbox,
28 shared_inbox::shared_inbox,
30 user_inbox::user_inbox,
33 use lemmy_db_queries::{get_database_url_from_env, Crud, ListingType, SortType};
34 use lemmy_db_schema::source::{
35 community::{Community, CommunityForm},
36 user::{UserForm, User_},
38 use lemmy_server::code_migrations::run_advanced_migrations;
40 apub::generate_actor_keypair,
41 rate_limit::{rate_limiter::RateLimiter, RateLimit},
44 use lemmy_websocket::{chat_server::ChatServer, LemmyContext};
46 use serde::{Deserialize, Serialize};
47 use std::{ops::Deref, sync::Arc};
48 use tokio::sync::Mutex;
53 fn create_context() -> LemmyContext {
54 let settings = Settings::get();
55 let db_url = match get_database_url_from_env() {
57 Err(_) => settings.get_database_url(),
59 let manager = ConnectionManager::<PgConnection>::new(&db_url);
60 let pool = Pool::builder()
61 .max_size(settings.database.pool_size)
64 embedded_migrations::run(&pool.get().unwrap()).unwrap();
65 run_advanced_migrations(pool.get().unwrap().deref()).unwrap();
66 let rate_limiter = RateLimit {
67 rate_limiter: Arc::new(Mutex::new(RateLimiter::default())),
69 let activity_queue = create_activity_queue();
70 let chat_server = ChatServer::startup(
73 |c, i, o, d| Box::pin(match_websocket_operation(c, i, o, d)),
82 create_activity_queue(),
86 fn create_user(conn: &PgConnection, name: &str) -> User_ {
87 let user_keypair = generate_actor_keypair().unwrap();
88 let new_user = UserForm {
90 preferred_username: None,
91 password_encrypted: "nope".into(),
101 theme: "browser".into(),
102 default_sort_type: SortType::Hot as i16,
103 default_listing_type: ListingType::Subscribed as i16,
104 lang: "browser".into(),
106 send_notifications_to_email: false,
108 Url::parse(&format!("http://localhost:8536/u/{}", name))
114 private_key: Some(user_keypair.private_key),
115 public_key: Some(user_keypair.public_key),
116 last_refreshed_at: None,
118 shared_inbox_url: None,
121 User_::create(&conn, &new_user).unwrap()
124 fn create_community(conn: &PgConnection, creator_id: i32) -> Community {
125 let new_community = CommunityForm {
126 name: "test_community".into(),
128 title: "test_community".to_owned(),
138 last_refreshed_at: None,
144 shared_inbox_url: None,
146 Community::create(&conn, &new_community).unwrap()
148 fn create_activity<'a, Activity, Return>(user_id: Url) -> web::Json<Return>
150 for<'de> Return: Deserialize<'de> + 'a,
151 Activity: std::default::Default + Serialize,
153 let mut activity = ActorAndObject::<Activity>::new(user_id, Note::new().into_any_base().unwrap());
155 .set_id(Url::parse("http://localhost:8536/create/1").unwrap())
156 .set_many_ccs(vec![Url::parse("http://localhost:8536/c/main").unwrap()]);
157 let activity = serde_json::to_value(&activity).unwrap();
158 let activity: Return = serde_json::from_value(activity).unwrap();
162 fn create_http_request() -> HttpRequest {
163 let time1 = Utc::now().timestamp();
164 let time2 = Utc::now().timestamp();
165 let signature = format!(
166 r#"keyId="my-key-id",algorithm="hs2019",created="{}",expires="{}",headers="(request-target) (created) (expires) date content-type",signature="blah blah blah""#,
170 .uri("http://localhost:8536/")
171 .header("Signature", signature)
175 // TODO: this fails with a stack overflow for some reason
178 async fn test_shared_inbox_expired_signature() {
179 let request = create_http_request();
180 let context = create_context();
181 let connection = &context.pool().get().unwrap();
182 let user = create_user(connection, "shared_inbox_rvgfd");
184 create_activity::<CreateType, ActorAndObject<shared_inbox::ValidTypes>>(user.actor_id.into());
185 let response = shared_inbox(request, activity, web::Data::new(context)).await;
187 format!("{}", response.err().unwrap()),
188 format!("{}", PrepareVerifyError::Expired)
190 User_::delete(connection, user.id).unwrap();
194 async fn test_user_inbox_expired_signature() {
195 let request = create_http_request();
196 let context = create_context();
197 let connection = &context.pool().get().unwrap();
198 let user = create_user(connection, "user_inbox_cgsax");
200 create_activity::<CreateType, ActorAndObject<user_inbox::UserValidTypes>>(user.actor_id.into());
201 let path = Path::<String> {
202 0: "username".to_string(),
204 let response = user_inbox(request, activity, path, web::Data::new(context)).await;
206 format!("{}", response.err().unwrap()),
207 format!("{}", PrepareVerifyError::Expired)
209 User_::delete(connection, user.id).unwrap();
213 async fn test_community_inbox_expired_signature() {
214 let context = create_context();
215 let connection = &context.pool().get().unwrap();
216 let user = create_user(connection, "community_inbox_hrxa");
217 let community = create_community(connection, user.id);
218 let request = create_http_request();
219 let activity = create_activity::<FollowType, ActorAndObject<community_inbox::CommunityValidTypes>>(
220 user.actor_id.into(),
222 let path = Path::<String> { 0: community.name };
223 let response = community_inbox(request, activity, path, web::Data::new(context)).await;
225 format!("{}", response.err().unwrap()),
226 format!("{}", PrepareVerifyError::Expired)
228 User_::delete(connection, user.id).unwrap();
229 Community::delete(connection, community.id).unwrap();