mirror of
https://github.com/LemmyNet/lemmy
synced 2025-02-20 16:08:59 +00:00
Move middleware code into api_routes for faster compilation (#5341)
* Move middleware code into api_routes for faster compilation * fix wasm * cleanup
This commit is contained in:
parent
1fdc229338
commit
a531e384b1
23 changed files with 196 additions and 204 deletions
32
Cargo.lock
generated
32
Cargo.lock
generated
|
@ -2080,9 +2080,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
|
|||
|
||||
[[package]]
|
||||
name = "hyper"
|
||||
version = "0.14.30"
|
||||
version = "0.14.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a152ddd61dfaec7273fe8419ab357f33aee0d914c5f4efbf0d96fa749eea5ec9"
|
||||
checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-channel",
|
||||
|
@ -2129,7 +2129,7 @@ checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590"
|
|||
dependencies = [
|
||||
"futures-util",
|
||||
"http 0.2.12",
|
||||
"hyper 0.14.30",
|
||||
"hyper 0.14.32",
|
||||
"rustls 0.21.12",
|
||||
"tokio",
|
||||
"tokio-rustls 0.24.1",
|
||||
|
@ -2555,7 +2555,6 @@ version = "0.19.6-beta.7"
|
|||
dependencies = [
|
||||
"activitypub_federation",
|
||||
"actix-web",
|
||||
"actix-web-httpauth",
|
||||
"anyhow",
|
||||
"base64 0.22.1",
|
||||
"bcrypt",
|
||||
|
@ -2585,6 +2584,7 @@ version = "0.19.6-beta.7"
|
|||
dependencies = [
|
||||
"activitypub_federation",
|
||||
"actix-web",
|
||||
"actix-web-httpauth",
|
||||
"anyhow",
|
||||
"chrono",
|
||||
"encoding_rs",
|
||||
|
@ -2614,6 +2614,7 @@ dependencies = [
|
|||
"url",
|
||||
"urlencoding",
|
||||
"uuid",
|
||||
"webmention",
|
||||
"webpage",
|
||||
]
|
||||
|
||||
|
@ -2640,7 +2641,6 @@ dependencies = [
|
|||
"tracing",
|
||||
"url",
|
||||
"uuid",
|
||||
"webmention",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2833,20 +2833,29 @@ name = "lemmy_routes"
|
|||
version = "0.19.6-beta.7"
|
||||
dependencies = [
|
||||
"activitypub_federation",
|
||||
"actix-cors",
|
||||
"actix-web",
|
||||
"actix-web-prom",
|
||||
"anyhow",
|
||||
"chrono",
|
||||
"clokwerk",
|
||||
"diesel",
|
||||
"diesel-async",
|
||||
"futures",
|
||||
"futures-util",
|
||||
"http 1.2.0",
|
||||
"lemmy_api_common",
|
||||
"lemmy_db_schema",
|
||||
"lemmy_db_views",
|
||||
"lemmy_db_views_actor",
|
||||
"lemmy_utils",
|
||||
"pretty_assertions",
|
||||
"prometheus",
|
||||
"reqwest 0.12.12",
|
||||
"reqwest-middleware",
|
||||
"rss",
|
||||
"serde",
|
||||
"serial_test",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"url",
|
||||
|
@ -2857,15 +2866,8 @@ name = "lemmy_server"
|
|||
version = "0.19.6-beta.7"
|
||||
dependencies = [
|
||||
"activitypub_federation",
|
||||
"actix-cors",
|
||||
"actix-web",
|
||||
"actix-web-prom",
|
||||
"chrono",
|
||||
"clap",
|
||||
"clokwerk",
|
||||
"diesel",
|
||||
"diesel-async",
|
||||
"futures-util",
|
||||
"lemmy_api",
|
||||
"lemmy_api_common",
|
||||
"lemmy_api_crud",
|
||||
|
@ -2874,18 +2876,14 @@ dependencies = [
|
|||
"lemmy_federate",
|
||||
"lemmy_routes",
|
||||
"lemmy_utils",
|
||||
"pretty_assertions",
|
||||
"prometheus",
|
||||
"reqwest-middleware",
|
||||
"reqwest-tracing",
|
||||
"rustls 0.23.21",
|
||||
"serde_json",
|
||||
"serial_test",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"tracing-actix-web",
|
||||
"tracing-subscriber",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -4096,7 +4094,7 @@ dependencies = [
|
|||
"h2",
|
||||
"http 0.2.12",
|
||||
"http-body 0.4.6",
|
||||
"hyper 0.14.30",
|
||||
"hyper 0.14.32",
|
||||
"hyper-rustls 0.24.2",
|
||||
"ipnet",
|
||||
"js-sys",
|
||||
|
|
15
Cargo.toml
15
Cargo.toml
|
@ -140,6 +140,7 @@ tokio = { version = "1.43.0", features = ["full"] }
|
|||
regex = "1.11.1"
|
||||
diesel-derive-newtype = "2.1.2"
|
||||
diesel-derive-enum = { version = "2.1.0", features = ["postgres"] }
|
||||
enum-map = { version = "2.7" }
|
||||
strum = { version = "0.26.3", features = ["derive"] }
|
||||
itertools = "0.14.0"
|
||||
futures = "0.3.31"
|
||||
|
@ -155,7 +156,6 @@ futures-util = "0.3.31"
|
|||
tokio-postgres = "0.7.12"
|
||||
tokio-postgres-rustls = "0.13.0"
|
||||
urlencoding = "2.1.3"
|
||||
enum-map = "2.7"
|
||||
moka = { version = "0.12.10", features = ["future"] }
|
||||
i-love-jesus = { version = "0.1.0" }
|
||||
clap = { version = "4.5.27", features = ["derive", "env"] }
|
||||
|
@ -174,26 +174,13 @@ lemmy_api_common = { workspace = true }
|
|||
lemmy_routes = { workspace = true }
|
||||
lemmy_federate = { workspace = true }
|
||||
activitypub_federation = { workspace = true }
|
||||
diesel = { workspace = true }
|
||||
diesel-async = { workspace = true }
|
||||
actix-web = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
tracing-actix-web = { workspace = true }
|
||||
tracing-subscriber = { workspace = true }
|
||||
url = { workspace = true }
|
||||
reqwest-middleware = { workspace = true }
|
||||
reqwest-tracing = { workspace = true }
|
||||
clokwerk = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
rustls = { workspace = true }
|
||||
tokio.workspace = true
|
||||
actix-cors = "0.7.0"
|
||||
futures-util = { workspace = true }
|
||||
chrono = { workspace = true }
|
||||
prometheus = { version = "0.13.4", features = ["process"] }
|
||||
serial_test = { workspace = true }
|
||||
clap = { workspace = true }
|
||||
actix-web-prom = "0.9.0"
|
||||
|
||||
[dev-dependencies]
|
||||
pretty_assertions = { workspace = true }
|
||||
|
|
|
@ -36,7 +36,6 @@ url = { workspace = true }
|
|||
hound = "3.5.1"
|
||||
sitemap-rs = "0.2.2"
|
||||
totp-rs = { version = "5.6.0", features = ["gen_secret", "otpauth"] }
|
||||
actix-web-httpauth = "0.8.2"
|
||||
|
||||
[dev-dependencies]
|
||||
serial_test = { workspace = true }
|
||||
|
|
|
@ -1,14 +1,11 @@
|
|||
use activitypub_federation::config::Data;
|
||||
use actix_web::{http::header::Header, HttpRequest};
|
||||
use actix_web_httpauth::headers::authorization::{Authorization, Bearer};
|
||||
use base64::{engine::general_purpose::STANDARD_NO_PAD as base64, Engine};
|
||||
use captcha::Captcha;
|
||||
use lemmy_api_common::{
|
||||
claims::Claims,
|
||||
community::BanFromCommunity,
|
||||
context::LemmyContext,
|
||||
send_activity::{ActivityChannel, SendActivityData},
|
||||
utils::{check_expire_time, check_user_valid, local_site_to_slur_regex, AUTH_COOKIE_NAME},
|
||||
utils::{check_expire_time, local_site_to_slur_regex},
|
||||
};
|
||||
use lemmy_db_schema::{
|
||||
source::{
|
||||
|
@ -26,7 +23,7 @@ use lemmy_db_schema::{
|
|||
};
|
||||
use lemmy_db_views::structs::LocalUserView;
|
||||
use lemmy_utils::{
|
||||
error::{LemmyErrorExt, LemmyErrorExt2, LemmyErrorType, LemmyResult},
|
||||
error::{LemmyErrorExt, LemmyErrorType, LemmyResult},
|
||||
utils::slurs::check_slurs,
|
||||
};
|
||||
use std::io::Cursor;
|
||||
|
@ -95,21 +92,6 @@ pub(crate) fn check_report_reason(reason: &str, local_site: &LocalSite) -> Lemmy
|
|||
}
|
||||
}
|
||||
|
||||
pub fn read_auth_token(req: &HttpRequest) -> LemmyResult<Option<String>> {
|
||||
// Try reading jwt from auth header
|
||||
if let Ok(header) = Authorization::<Bearer>::parse(req) {
|
||||
Ok(Some(header.as_ref().token().to_string()))
|
||||
}
|
||||
// If that fails, try to read from cookie
|
||||
else if let Some(cookie) = &req.cookie(AUTH_COOKIE_NAME) {
|
||||
Ok(Some(cookie.value().to_string()))
|
||||
}
|
||||
// Otherwise, there's no auth
|
||||
else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn check_totp_2fa_valid(
|
||||
local_user_view: &LocalUserView,
|
||||
totp_token: &Option<String>,
|
||||
|
@ -243,20 +225,6 @@ pub(crate) async fn ban_nonlocal_user_from_local_communities(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub async fn local_user_view_from_jwt(
|
||||
jwt: &str,
|
||||
context: &LemmyContext,
|
||||
) -> LemmyResult<LocalUserView> {
|
||||
let local_user_id = Claims::validate(jwt, context)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::NotLoggedIn)?;
|
||||
let local_user_view = LocalUserView::read(&mut context.pool(), local_user_id).await?;
|
||||
check_user_valid(&local_user_view.person)?;
|
||||
|
||||
Ok(local_user_view)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
use crate::read_auth_token;
|
||||
use activitypub_federation::config::Data;
|
||||
use actix_web::{cookie::Cookie, HttpRequest, HttpResponse};
|
||||
use lemmy_api_common::{context::LemmyContext, utils::AUTH_COOKIE_NAME, SuccessResponse};
|
||||
use lemmy_api_common::{
|
||||
context::LemmyContext,
|
||||
utils::{read_auth_token, AUTH_COOKIE_NAME},
|
||||
SuccessResponse,
|
||||
};
|
||||
use lemmy_db_schema::source::login_token::LoginToken;
|
||||
use lemmy_db_views::structs::LocalUserView;
|
||||
use lemmy_utils::error::{LemmyErrorType, LemmyResult};
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
use crate::{local_user_view_from_jwt, read_auth_token};
|
||||
use actix_web::{
|
||||
web::{Data, Json},
|
||||
HttpRequest,
|
||||
};
|
||||
use lemmy_api_common::{context::LemmyContext, SuccessResponse};
|
||||
use lemmy_api_common::{
|
||||
context::LemmyContext,
|
||||
utils::{local_user_view_from_jwt, read_auth_token},
|
||||
SuccessResponse,
|
||||
};
|
||||
use lemmy_utils::error::{LemmyErrorType, LemmyResult};
|
||||
|
||||
/// Returns an error message if the auth token is invalid for any reason. Necessary because other
|
||||
|
|
|
@ -37,6 +37,8 @@ full = [
|
|||
"jsonwebtoken",
|
||||
"mime",
|
||||
"moka",
|
||||
"actix-web-httpauth",
|
||||
"webmention",
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
|
@ -61,8 +63,8 @@ reqwest = { workspace = true, optional = true }
|
|||
ts-rs = { workspace = true, optional = true }
|
||||
moka = { workspace = true, optional = true }
|
||||
anyhow.workspace = true
|
||||
actix-web = { workspace = true, optional = true }
|
||||
enum-map = { workspace = true }
|
||||
actix-web = { workspace = true, optional = true }
|
||||
urlencoding = { workspace = true }
|
||||
mime = { version = "0.3.17", optional = true }
|
||||
mime_guess = "2.0.5"
|
||||
|
@ -72,6 +74,8 @@ webpage = { version = "2.0", default-features = false, optional = true, features
|
|||
] }
|
||||
encoding_rs = { version = "0.8.35", optional = true }
|
||||
jsonwebtoken = { version = "9.3.0", optional = true }
|
||||
actix-web-httpauth = { version = "0.8.2", optional = true }
|
||||
webmention = { version = "0.6.0", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
serial_test = { workspace = true }
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use crate::{
|
||||
claims::Claims,
|
||||
context::LemmyContext,
|
||||
request::{
|
||||
delete_image_from_pictrs,
|
||||
|
@ -7,6 +8,8 @@ use crate::{
|
|||
},
|
||||
site::{FederatedInstances, InstanceWithFederationState},
|
||||
};
|
||||
use actix_web::{http::header::Header, HttpRequest};
|
||||
use actix_web_httpauth::headers::authorization::{Authorization, Bearer};
|
||||
use chrono::{DateTime, Days, Local, TimeZone, Utc};
|
||||
use enum_map::{enum_map, EnumMap};
|
||||
use lemmy_db_schema::{
|
||||
|
@ -39,6 +42,7 @@ use lemmy_db_schema::{
|
|||
},
|
||||
traits::{Crud, Likeable},
|
||||
utils::DbPool,
|
||||
CommunityVisibility,
|
||||
FederationMode,
|
||||
RegistrationMode,
|
||||
};
|
||||
|
@ -54,12 +58,13 @@ use lemmy_db_views_actor::structs::{
|
|||
};
|
||||
use lemmy_utils::{
|
||||
email::{send_email, translations::Lang},
|
||||
error::{LemmyError, LemmyErrorExt, LemmyErrorType, LemmyResult},
|
||||
error::{LemmyError, LemmyErrorExt, LemmyErrorExt2, LemmyErrorType, LemmyResult},
|
||||
rate_limit::{ActionType, BucketConfig},
|
||||
settings::{
|
||||
structs::{PictrsImageMode, Settings},
|
||||
SETTINGS,
|
||||
},
|
||||
spawn_try_task,
|
||||
utils::{
|
||||
markdown::{image_links::markdown_rewrite_image_links, markdown_check_for_blocked_urls},
|
||||
slurs::{build_slur_regex, remove_slurs},
|
||||
|
@ -72,9 +77,10 @@ use moka::future::Cache;
|
|||
use regex::{escape, Regex, RegexSet};
|
||||
use rosetta_i18n::{Language, LanguageId};
|
||||
use std::sync::LazyLock;
|
||||
use tracing::warn;
|
||||
use tracing::{warn, Instrument};
|
||||
use url::{ParseError, Url};
|
||||
use urlencoding::encode;
|
||||
use webmention::{Webmention, WebmentionError};
|
||||
|
||||
pub const AUTH_COOKIE_NAME: &str = "jwt";
|
||||
|
||||
|
@ -1145,6 +1151,55 @@ fn build_proxied_image_url(
|
|||
))
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub async fn local_user_view_from_jwt(
|
||||
jwt: &str,
|
||||
context: &LemmyContext,
|
||||
) -> LemmyResult<LocalUserView> {
|
||||
let local_user_id = Claims::validate(jwt, context)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::NotLoggedIn)?;
|
||||
let local_user_view = LocalUserView::read(&mut context.pool(), local_user_id).await?;
|
||||
check_user_valid(&local_user_view.person)?;
|
||||
|
||||
Ok(local_user_view)
|
||||
}
|
||||
|
||||
pub fn read_auth_token(req: &HttpRequest) -> LemmyResult<Option<String>> {
|
||||
// Try reading jwt from auth header
|
||||
if let Ok(header) = Authorization::<Bearer>::parse(req) {
|
||||
Ok(Some(header.as_ref().token().to_string()))
|
||||
}
|
||||
// If that fails, try to read from cookie
|
||||
else if let Some(cookie) = &req.cookie(AUTH_COOKIE_NAME) {
|
||||
Ok(Some(cookie.value().to_string()))
|
||||
}
|
||||
// Otherwise, there's no auth
|
||||
else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn send_webmention(post: Post, community: Community) {
|
||||
if let Some(url) = post.url.clone() {
|
||||
if community.visibility == CommunityVisibility::Public {
|
||||
spawn_try_task(async move {
|
||||
let mut webmention = Webmention::new::<Url>(post.ap_id.clone().into(), url.clone().into())?;
|
||||
webmention.set_checked(true);
|
||||
match webmention
|
||||
.send()
|
||||
.instrument(tracing::info_span!("Sending webmention"))
|
||||
.await
|
||||
{
|
||||
Err(WebmentionError::NoEndpointDiscovered(_)) => Ok(()),
|
||||
Ok(_) => Ok(()),
|
||||
Err(e) => Err(e).with_lemmy_type(LemmyErrorType::CouldntSendWebmention),
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
|
|
|
@ -27,7 +27,6 @@ futures.workspace = true
|
|||
uuid = { workspace = true }
|
||||
anyhow.workspace = true
|
||||
chrono.workspace = true
|
||||
webmention = "0.6.0"
|
||||
accept-language = "3.1.0"
|
||||
regex = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
|
|
|
@ -13,6 +13,7 @@ use lemmy_api_common::{
|
|||
honeypot_check,
|
||||
local_site_to_slur_regex,
|
||||
process_markdown_opt,
|
||||
send_webmention,
|
||||
},
|
||||
};
|
||||
use lemmy_db_schema::{
|
||||
|
@ -25,13 +26,11 @@ use lemmy_db_schema::{
|
|||
},
|
||||
traits::{Crud, Likeable},
|
||||
utils::diesel_url_create,
|
||||
CommunityVisibility,
|
||||
};
|
||||
use lemmy_db_views::structs::LocalUserView;
|
||||
use lemmy_db_views_actor::structs::CommunityModeratorView;
|
||||
use lemmy_utils::{
|
||||
error::{LemmyErrorExt, LemmyErrorType, LemmyResult},
|
||||
spawn_try_task,
|
||||
utils::{
|
||||
mention::scrape_text_for_mentions,
|
||||
slurs::check_slurs,
|
||||
|
@ -44,9 +43,6 @@ use lemmy_utils::{
|
|||
},
|
||||
},
|
||||
};
|
||||
use tracing::Instrument;
|
||||
use url::Url;
|
||||
use webmention::{Webmention, WebmentionError};
|
||||
|
||||
#[tracing::instrument(skip(context))]
|
||||
pub async fn create_post(
|
||||
|
@ -170,23 +166,3 @@ pub async fn create_post(
|
|||
|
||||
build_post_response(&context, community_id, local_user_view, post_id).await
|
||||
}
|
||||
|
||||
pub fn send_webmention(post: Post, community: Community) {
|
||||
if let Some(url) = post.url.clone() {
|
||||
if community.visibility == CommunityVisibility::Public {
|
||||
spawn_try_task(async move {
|
||||
let mut webmention = Webmention::new::<Url>(post.ap_id.clone().into(), url.clone().into())?;
|
||||
webmention.set_checked(true);
|
||||
match webmention
|
||||
.send()
|
||||
.instrument(tracing::info_span!("Sending webmention"))
|
||||
.await
|
||||
{
|
||||
Err(WebmentionError::NoEndpointDiscovered(_)) => Ok(()),
|
||||
Ok(_) => Ok(()),
|
||||
Err(e) => Err(e).with_lemmy_type(LemmyErrorType::CouldntSendWebmention),
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use super::{convert_published_time, create::send_webmention};
|
||||
use super::convert_published_time;
|
||||
use activitypub_federation::config::Data;
|
||||
use actix_web::web::Json;
|
||||
use chrono::Utc;
|
||||
|
@ -13,6 +13,7 @@ use lemmy_api_common::{
|
|||
get_url_blocklist,
|
||||
local_site_to_slur_regex,
|
||||
process_markdown_opt,
|
||||
send_webmention,
|
||||
},
|
||||
};
|
||||
use lemmy_db_schema::{
|
||||
|
|
|
@ -32,5 +32,16 @@ serde = { workspace = true }
|
|||
url = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
tokio = { workspace = true }
|
||||
futures-util.workspace = true
|
||||
http.workspace = true
|
||||
diesel.workspace = true
|
||||
diesel-async.workspace = true
|
||||
clokwerk = "0.4.0"
|
||||
prometheus = { version = "0.13.4", features = ["process"] }
|
||||
rss = "2.0.11"
|
||||
actix-web-prom = "0.9.0"
|
||||
actix-cors = "0.7.0"
|
||||
|
||||
[dev-dependencies]
|
||||
pretty_assertions.workspace = true
|
||||
serial_test.workspace = true
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
use crate::local_user_view_from_jwt;
|
||||
use actix_web::{error::ErrorBadRequest, web, Error, HttpRequest, HttpResponse, Result};
|
||||
use anyhow::anyhow;
|
||||
use chrono::{DateTime, Utc};
|
||||
use lemmy_api_common::{context::LemmyContext, utils::check_private_instance};
|
||||
use lemmy_api_common::{
|
||||
context::LemmyContext,
|
||||
utils::{check_private_instance, local_user_view_from_jwt},
|
||||
};
|
||||
use lemmy_db_schema::{
|
||||
source::{community::Community, person::Person},
|
||||
traits::ApubActor,
|
||||
|
|
|
@ -1,17 +1,6 @@
|
|||
use lemmy_api_common::{claims::Claims, context::LemmyContext, utils::check_user_valid};
|
||||
use lemmy_db_views::structs::LocalUserView;
|
||||
use lemmy_utils::error::LemmyResult;
|
||||
|
||||
pub mod feeds;
|
||||
pub mod images;
|
||||
pub mod middleware;
|
||||
pub mod nodeinfo;
|
||||
pub mod utils;
|
||||
pub mod webfinger;
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn local_user_view_from_jwt(jwt: &str, context: &LemmyContext) -> LemmyResult<LocalUserView> {
|
||||
let local_user_id = Claims::validate(jwt, context).await?;
|
||||
let local_user_view = LocalUserView::read(&mut context.pool(), local_user_id).await?;
|
||||
check_user_valid(&local_user_view.person)?;
|
||||
|
||||
Ok(local_user_view)
|
||||
}
|
||||
|
|
2
crates/routes/src/middleware/mod.rs
Normal file
2
crates/routes/src/middleware/mod.rs
Normal file
|
@ -0,0 +1,2 @@
|
|||
pub mod idempotency;
|
||||
pub mod session;
|
|
@ -7,8 +7,10 @@ use actix_web::{
|
|||
};
|
||||
use core::future::Ready;
|
||||
use futures_util::future::LocalBoxFuture;
|
||||
use lemmy_api::{local_user_view_from_jwt, read_auth_token};
|
||||
use lemmy_api_common::context::LemmyContext;
|
||||
use lemmy_api_common::{
|
||||
context::LemmyContext,
|
||||
utils::{local_user_view_from_jwt, read_auth_token},
|
||||
};
|
||||
use std::{future::ready, rc::Rc};
|
||||
|
||||
#[derive(Clone)]
|
||||
|
@ -67,9 +69,8 @@ where
|
|||
|
||||
if let Some(jwt) = &jwt {
|
||||
// Ignore any invalid auth so the site can still be used
|
||||
// TODO: this means it will be impossible to get any error message for invalid jwt. Need
|
||||
// to add a separate endpoint for that.
|
||||
// https://github.com/LemmyNet/lemmy/issues/3702
|
||||
// This means it is be impossible to get any error message for invalid jwt. Need
|
||||
// to use `/api/v4/account/validate_auth` for that.
|
||||
let local_user_view = local_user_view_from_jwt(jwt, &context).await.ok();
|
||||
if let Some(local_user_view) = local_user_view {
|
||||
req.extensions_mut().insert(local_user_view);
|
||||
|
@ -99,9 +100,8 @@ where
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
use crate::tests::test_context;
|
||||
use actix_web::test::TestRequest;
|
||||
use lemmy_api_common::claims::Claims;
|
||||
use lemmy_api_common::{claims::Claims, context::LemmyContext};
|
||||
use lemmy_db_schema::{
|
||||
source::{
|
||||
instance::Instance,
|
||||
|
@ -117,7 +117,7 @@ mod tests {
|
|||
#[tokio::test]
|
||||
#[serial]
|
||||
async fn test_session_auth() -> LemmyResult<()> {
|
||||
let context = test_context().await;
|
||||
let context = LemmyContext::init_test_context().await;
|
||||
|
||||
let inserted_instance =
|
||||
Instance::read_or_create(&mut context.pool(), "my_domain.tld".to_string()).await?;
|
38
crates/routes/src/utils/mod.rs
Normal file
38
crates/routes/src/utils/mod.rs
Normal file
|
@ -0,0 +1,38 @@
|
|||
use actix_cors::Cors;
|
||||
use lemmy_utils::settings::structs::Settings;
|
||||
|
||||
pub mod code_migrations;
|
||||
pub mod prometheus_metrics;
|
||||
pub mod scheduled_tasks;
|
||||
|
||||
pub fn cors_config(settings: &Settings) -> Cors {
|
||||
let self_origin = settings.get_protocol_and_hostname();
|
||||
let cors_origin_setting = settings.cors_origin();
|
||||
|
||||
// A default setting for either wildcard, or None
|
||||
let cors_default = Cors::default()
|
||||
.allow_any_origin()
|
||||
.allow_any_method()
|
||||
.allow_any_header()
|
||||
.expose_any_header()
|
||||
.max_age(3600);
|
||||
|
||||
match (cors_origin_setting.clone(), cfg!(debug_assertions)) {
|
||||
(Some(origin), false) => {
|
||||
// Need to call send_wildcard() explicitly, passing this into allowed_origin() results in
|
||||
// error
|
||||
if origin == "*" {
|
||||
cors_default
|
||||
} else {
|
||||
Cors::default()
|
||||
.allowed_origin(&origin)
|
||||
.allowed_origin(&self_origin)
|
||||
.allow_any_method()
|
||||
.allow_any_header()
|
||||
.expose_any_header()
|
||||
.max_age(3600)
|
||||
}
|
||||
}
|
||||
_ => cors_default,
|
||||
}
|
||||
}
|
|
@ -1,10 +1,21 @@
|
|||
use actix_web::{rt::System, web, App, HttpServer};
|
||||
use lemmy_api_common::context::LemmyContext;
|
||||
use actix_web_prom::{PrometheusMetrics, PrometheusMetricsBuilder};
|
||||
use lemmy_api_common::{context::LemmyContext, LemmyErrorType};
|
||||
use lemmy_utils::{error::LemmyResult, settings::structs::PrometheusConfig};
|
||||
use prometheus::{default_registry, Encoder, Gauge, Opts, TextEncoder};
|
||||
use std::{sync::Arc, thread};
|
||||
use tracing::error;
|
||||
|
||||
/// Creates a middleware that populates http metrics for each path, method, and status code
|
||||
pub fn new_prometheus_metrics() -> LemmyResult<PrometheusMetrics> {
|
||||
Ok(
|
||||
PrometheusMetricsBuilder::new("lemmy_api")
|
||||
.registry(default_registry().clone())
|
||||
.build()
|
||||
.map_err(|e| LemmyErrorType::Unknown(format!("Should always be buildable: {e}")))?,
|
||||
)
|
||||
}
|
||||
|
||||
struct PromContext {
|
||||
lemmy: LemmyContext,
|
||||
db_pool_metrics: DbPoolMetrics,
|
|
@ -1,3 +1,4 @@
|
|||
use crate::nodeinfo::{NodeInfo, NodeInfoWellKnown};
|
||||
use activitypub_federation::config::Data;
|
||||
use chrono::{DateTime, TimeZone, Utc};
|
||||
use clokwerk::{AsyncScheduler, TimeUnits as CTimeUnits};
|
||||
|
@ -16,8 +17,8 @@ use diesel_async::{AsyncPgConnection, RunQueryDsl};
|
|||
use lemmy_api_common::{
|
||||
context::LemmyContext,
|
||||
send_activity::{ActivityChannel, SendActivityData},
|
||||
utils::send_webmention,
|
||||
};
|
||||
use lemmy_api_crud::post::create::send_webmention;
|
||||
use lemmy_db_schema::{
|
||||
schema::{
|
||||
captcha_answer,
|
||||
|
@ -48,7 +49,6 @@ use lemmy_db_schema::{
|
|||
DELETED_REPLACEMENT_TEXT,
|
||||
},
|
||||
};
|
||||
use lemmy_routes::nodeinfo::{NodeInfo, NodeInfoWellKnown};
|
||||
use lemmy_utils::error::{LemmyErrorType, LemmyResult};
|
||||
use reqwest_middleware::ClientWithMiddleware;
|
||||
use std::time::Duration;
|
||||
|
@ -553,7 +553,6 @@ async fn build_update_instance_form(
|
|||
mod tests {
|
||||
|
||||
use super::*;
|
||||
use crate::{scheduled_tasks::build_update_instance_form, tests::test_context};
|
||||
use lemmy_api_common::request::client_builder;
|
||||
use lemmy_utils::{
|
||||
error::{LemmyErrorType, LemmyResult},
|
||||
|
@ -586,7 +585,7 @@ mod tests {
|
|||
#[tokio::test]
|
||||
#[serial]
|
||||
async fn test_scheduled_tasks_no_errors() -> LemmyResult<()> {
|
||||
let context = test_context().await;
|
||||
let context = LemmyContext::init_test_context().await;
|
||||
|
||||
startup_jobs(&mut context.pool()).await?;
|
||||
update_instance_software(&mut context.pool(), context.client()).await?;
|
|
@ -82,7 +82,7 @@ lettre = { version = "0.11.11", default-features = false, features = [
|
|||
], optional = true }
|
||||
markdown-it = { version = "0.6.1", optional = true }
|
||||
ts-rs = { workspace = true, optional = true }
|
||||
enum-map = { workspace = true, optional = true }
|
||||
enum-map = { version = "2.7", optional = true }
|
||||
cfg-if = "1"
|
||||
clearurls = { version = "0.0.4", features = ["linkify"] }
|
||||
markdown-it-block-spoiler = "1.0.1"
|
||||
|
|
97
src/lib.rs
97
src/lib.rs
|
@ -1,14 +1,7 @@
|
|||
pub mod api_routes_v3;
|
||||
pub mod api_routes_v4;
|
||||
pub mod code_migrations;
|
||||
pub mod idempotency_middleware;
|
||||
pub mod prometheus_metrics;
|
||||
pub mod scheduled_tasks;
|
||||
pub mod session_middleware;
|
||||
|
||||
use crate::{code_migrations::run_advanced_migrations, session_middleware::SessionMiddleware};
|
||||
use activitypub_federation::config::{FederationConfig, FederationMiddleware};
|
||||
use actix_cors::Cors;
|
||||
use actix_web::{
|
||||
dev::{ServerHandle, ServiceResponse},
|
||||
middleware::{self, Condition, ErrorHandlerResponse, ErrorHandlers},
|
||||
|
@ -17,9 +10,7 @@ use actix_web::{
|
|||
HttpResponse,
|
||||
HttpServer,
|
||||
};
|
||||
use actix_web_prom::PrometheusMetricsBuilder;
|
||||
use clap::{Parser, Subcommand};
|
||||
use idempotency_middleware::{IdempotencyMiddleware, IdempotencySet};
|
||||
use lemmy_api::sitemap::get_sitemap;
|
||||
use lemmy_api_common::{
|
||||
context::LemmyContext,
|
||||
|
@ -39,7 +30,21 @@ use lemmy_apub::{
|
|||
};
|
||||
use lemmy_db_schema::{schema_setup, source::secret::Secret, utils::build_db_pool};
|
||||
use lemmy_federate::{Opts, SendManager};
|
||||
use lemmy_routes::{feeds, nodeinfo, webfinger};
|
||||
use lemmy_routes::{
|
||||
feeds,
|
||||
middleware::{
|
||||
idempotency::{IdempotencyMiddleware, IdempotencySet},
|
||||
session::SessionMiddleware,
|
||||
},
|
||||
nodeinfo,
|
||||
utils::{
|
||||
code_migrations::run_advanced_migrations,
|
||||
cors_config,
|
||||
prometheus_metrics::{new_prometheus_metrics, serve_prometheus},
|
||||
scheduled_tasks,
|
||||
},
|
||||
webfinger,
|
||||
};
|
||||
use lemmy_utils::{
|
||||
error::{LemmyErrorType, LemmyResult},
|
||||
rate_limit::RateLimitCell,
|
||||
|
@ -47,8 +52,6 @@ use lemmy_utils::{
|
|||
settings::{structs::Settings, SETTINGS},
|
||||
VERSION,
|
||||
};
|
||||
use prometheus::default_registry;
|
||||
use prometheus_metrics::serve_prometheus;
|
||||
use reqwest_middleware::ClientBuilder;
|
||||
use reqwest_tracing::TracingMiddleware;
|
||||
use serde_json::json;
|
||||
|
@ -175,19 +178,17 @@ pub async fn start_lemmy_server(args: CmdArgs) -> LemmyResult<()> {
|
|||
|
||||
// Make sure the local site is set up.
|
||||
let site_view = SiteView::read_local(&mut (&pool).into()).await?;
|
||||
let local_site = site_view.local_site;
|
||||
let federation_enabled = local_site.federation_enabled;
|
||||
let federation_enabled = site_view.local_site.federation_enabled;
|
||||
|
||||
if federation_enabled {
|
||||
println!("Federation enabled, host is {}", &SETTINGS.hostname);
|
||||
}
|
||||
|
||||
check_private_instance_and_federation_enabled(&local_site)?;
|
||||
|
||||
// Set up the rate limiter
|
||||
let rate_limit_config =
|
||||
local_site_rate_limit_to_rate_limit_config(&site_view.local_site_rate_limit);
|
||||
let rate_limit_cell = RateLimitCell::new(rate_limit_config);
|
||||
check_private_instance_and_federation_enabled(&site_view.local_site)?;
|
||||
|
||||
println!(
|
||||
"Starting HTTP server at {}:{}",
|
||||
|
@ -205,7 +206,7 @@ pub async fn start_lemmy_server(args: CmdArgs) -> LemmyResult<()> {
|
|||
client.clone(),
|
||||
pictrs_client,
|
||||
secret.clone(),
|
||||
rate_limit_cell.clone(),
|
||||
rate_limit_cell,
|
||||
);
|
||||
|
||||
if let Some(prometheus) = SETTINGS.prometheus.clone() {
|
||||
|
@ -221,8 +222,8 @@ pub async fn start_lemmy_server(args: CmdArgs) -> LemmyResult<()> {
|
|||
.debug(cfg!(debug_assertions))
|
||||
.http_signature_compat(true)
|
||||
.url_verifier(Box::new(VerifyUrlData(context.inner_pool().clone())));
|
||||
if local_site.federation_signed_fetch {
|
||||
let site: ApubSite = site_view.site.into();
|
||||
if site_view.local_site.federation_signed_fetch {
|
||||
let site: ApubSite = site_view.site.clone().into();
|
||||
federation_config_builder.signed_fetch_actor(&site);
|
||||
}
|
||||
let federation_config = federation_config_builder.build().await?;
|
||||
|
@ -329,14 +330,8 @@ fn create_http_server(
|
|||
settings: Settings,
|
||||
federation_enabled: bool,
|
||||
) -> LemmyResult<ServerHandle> {
|
||||
// this must come before the HttpServer creation
|
||||
// creates a middleware that populates http metrics for each path, method, and status code
|
||||
let prom_api_metrics = PrometheusMetricsBuilder::new("lemmy_api")
|
||||
.registry(default_registry().clone())
|
||||
.build()
|
||||
.map_err(|e| LemmyErrorType::Unknown(format!("Should always be buildable: {e}")))?;
|
||||
|
||||
// Must create this outside of HTTP server so that duplicate requests get detected across threads.
|
||||
// These must come before HttpServer creation so they can collect data across threads.
|
||||
let prom_api_metrics = new_prometheus_metrics()?;
|
||||
let idempotency_set = IdempotencySet::default();
|
||||
|
||||
// Create Http server
|
||||
|
@ -358,7 +353,6 @@ fn create_http_server(
|
|||
.wrap(TracingLogger::<DefaultRootSpanBuilder>::new())
|
||||
.wrap(ErrorHandlers::new().default_handler(jsonify_plain_text_errors))
|
||||
.app_data(Data::new(context.clone()))
|
||||
.app_data(Data::new(rate_limit_cell.clone()))
|
||||
.wrap(FederationMiddleware::new(federation_config.clone()))
|
||||
.wrap(IdempotencyMiddleware::new(idempotency_set.clone()))
|
||||
.wrap(SessionMiddleware::new(context.clone()))
|
||||
|
@ -392,50 +386,3 @@ fn create_http_server(
|
|||
tokio::task::spawn(server);
|
||||
Ok(handle)
|
||||
}
|
||||
|
||||
fn cors_config(settings: &Settings) -> Cors {
|
||||
let self_origin = settings.get_protocol_and_hostname();
|
||||
let cors_origin_setting = settings.cors_origin();
|
||||
|
||||
// A default setting for either wildcard, or None
|
||||
let cors_default = Cors::default()
|
||||
.allow_any_origin()
|
||||
.allow_any_method()
|
||||
.allow_any_header()
|
||||
.expose_any_header()
|
||||
.max_age(3600);
|
||||
|
||||
match (cors_origin_setting.clone(), cfg!(debug_assertions)) {
|
||||
(Some(origin), false) => {
|
||||
// Need to call send_wildcard() explicitly, passing this into allowed_origin() results in
|
||||
// error
|
||||
if origin == "*" {
|
||||
cors_default
|
||||
} else {
|
||||
Cors::default()
|
||||
.allowed_origin(&origin)
|
||||
.allowed_origin(&self_origin)
|
||||
.allow_any_method()
|
||||
.allow_any_header()
|
||||
.expose_any_header()
|
||||
.max_age(3600)
|
||||
}
|
||||
}
|
||||
_ => cors_default,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod tests {
|
||||
use activitypub_federation::config::Data;
|
||||
use lemmy_api_common::context::LemmyContext;
|
||||
use std::env::set_current_dir;
|
||||
|
||||
pub async fn test_context() -> Data<LemmyContext> {
|
||||
// hack, necessary so that config file can be loaded from hardcoded, relative path.
|
||||
// Ignore errors as this gets called once for every test (so changing dir again would fail).
|
||||
set_current_dir("crates/utils").ok();
|
||||
|
||||
LemmyContext::init_test_context().await
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue