diff options
author | Dessalines <tyhou13@gmx.com> | 2020-06-23 21:11:38 -0400 |
---|---|---|
committer | Dessalines <tyhou13@gmx.com> | 2020-06-23 21:11:38 -0400 |
commit | dc94e58cbf7e7de10d97331a3056380a3416e0b0 (patch) | |
tree | 85ed25783b0470ead3012a9718aea50b39c940dd /server/src | |
parent | fd6a040568239d2e6949394fdc0ce0f7ac70275c (diff) | |
parent | 790b944031f9433be765936763d848ffa6e1b496 (diff) |
Merge branch 'master' into federation_merge_from_master_2
Diffstat (limited to 'server/src')
-rw-r--r-- | server/src/api/community.rs | 24 | ||||
-rw-r--r-- | server/src/api/mod.rs | 5 | ||||
-rw-r--r-- | server/src/api/post.rs | 18 | ||||
-rw-r--r-- | server/src/apub/activities.rs | 13 | ||||
-rw-r--r-- | server/src/apub/extensions/signatures.rs | 23 | ||||
-rw-r--r-- | server/src/apub/fetcher.rs | 5 | ||||
-rw-r--r-- | server/src/apub/mod.rs | 3 | ||||
-rw-r--r-- | server/src/lib.rs | 71 | ||||
-rw-r--r-- | server/src/version.rs | 2 |
9 files changed, 95 insertions, 69 deletions
diff --git a/server/src/api/community.rs b/server/src/api/community.rs index cb412fcc..3fc67eb3 100644 --- a/server/src/api/community.rs +++ b/server/src/api/community.rs @@ -1,3 +1,4 @@ +use super::*; use crate::{ api::{APIError, Oper, Perform}, apub::{ @@ -6,19 +7,8 @@ use crate::{ ActorType, EndpointType, }, - db::{ - community::*, - community_view::*, - moderator::*, - site::*, - user::*, - user_view::*, - Bannable, - Crud, - Followable, - Joinable, - SortType, - }, + db::{Bannable, Crud, Followable, Joinable, SortType}, + is_valid_community_name, naive_from_unix, naive_now, slur_check, @@ -259,6 +249,10 @@ impl Perform for Oper<CreateCommunity> { } } + if !is_valid_community_name(&data.name) { + return Err(APIError::err("invalid_community_name").into()); + } + let user_id = claims.id; let conn = pool.get()?; @@ -353,6 +347,10 @@ impl Perform for Oper<EditCommunity> { Err(_e) => return Err(APIError::err("not_logged_in").into()), }; + if !is_valid_community_name(&data.name) { + return Err(APIError::err("invalid_community_name").into()); + } + let user_id = claims.id; let conn = pool.get()?; diff --git a/server/src/api/mod.rs b/server/src/api/mod.rs index 5120e9bc..afd62aff 100644 --- a/server/src/api/mod.rs +++ b/server/src/api/mod.rs @@ -1,4 +1,7 @@ -use crate::websocket::WebsocketInfo; +use crate::{ + db::{community::*, community_view::*, moderator::*, site::*, user::*, user_view::*}, + websocket::WebsocketInfo, +}; use diesel::{ r2d2::{ConnectionManager, Pool}, PgConnection, diff --git a/server/src/api/post.rs b/server/src/api/post.rs index 9bbde791..420bef1f 100644 --- a/server/src/api/post.rs +++ b/server/src/api/post.rs @@ -17,7 +17,7 @@ use crate::{ Saveable, SortType, }, - fetch_iframely_and_pictshare_data, + fetch_iframely_and_pictrs_data, naive_now, slur_check, slurs_vec_to_str, @@ -152,9 +152,9 @@ impl Perform for Oper<CreatePost> { return Err(APIError::err("site_ban").into()); } - // Fetch Iframely and Pictshare cached image - let (iframely_title, iframely_description, iframely_html, pictshare_thumbnail) = - fetch_iframely_and_pictshare_data(data.url.to_owned()); + // Fetch Iframely and pictrs cached image + let (iframely_title, iframely_description, iframely_html, pictrs_thumbnail) = + fetch_iframely_and_pictrs_data(data.url.to_owned()); let post_form = PostForm { name: data.name.to_owned(), @@ -171,7 +171,7 @@ impl Perform for Oper<CreatePost> { embed_title: iframely_title, embed_description: iframely_description, embed_html: iframely_html, - thumbnail_url: pictshare_thumbnail, + thumbnail_url: pictrs_thumbnail, ap_id: "changeme".into(), local: true, published: None, @@ -507,9 +507,9 @@ impl Perform for Oper<EditPost> { return Err(APIError::err("site_ban").into()); } - // Fetch Iframely and Pictshare cached image - let (iframely_title, iframely_description, iframely_html, pictshare_thumbnail) = - fetch_iframely_and_pictshare_data(data.url.to_owned()); + // Fetch Iframely and Pictrs cached image + let (iframely_title, iframely_description, iframely_html, pictrs_thumbnail) = + fetch_iframely_and_pictrs_data(data.url.to_owned()); let read_post = Post::read(&conn, data.edit_id)?; @@ -528,7 +528,7 @@ impl Perform for Oper<EditPost> { embed_title: iframely_title, embed_description: iframely_description, embed_html: iframely_html, - thumbnail_url: pictshare_thumbnail, + thumbnail_url: pictrs_thumbnail, ap_id: read_post.ap_id, local: read_post.local, published: None, diff --git a/server/src/apub/activities.rs b/server/src/apub/activities.rs index b5bb9d76..3c4034c9 100644 --- a/server/src/apub/activities.rs +++ b/server/src/apub/activities.rs @@ -5,7 +5,6 @@ use crate::{ use activitystreams::{context, object::properties::ObjectProperties, public, Activity, Base}; use diesel::PgConnection; use failure::{Error, _core::fmt::Debug}; -use isahc::prelude::*; use log::debug; use serde::Serialize; use url::Url; @@ -57,16 +56,18 @@ where for t in to { let to_url = Url::parse(&t)?; if !is_apub_id_valid(&to_url) { - debug!("Not sending activity to {} (invalid or blocklisted)", t); + debug!("Not sending activity to {} (invalid or blacklisted)", t); continue; } - let request = Request::post(t).header("Host", to_url.domain().unwrap()); - let signature = sign(&request, actor)?; + let mut request = attohttpc::post(t).header("Host", to_url.domain().unwrap()); + let signature = sign(&mut request, actor)?; let res = request .header("Signature", signature) .header("Content-Type", "application/json") - .body(json.to_owned())? - .send()?; + .text(json.to_owned()) + .send()? + .text()?; + debug!("Result for activity send: {:?}", res); } Ok(()) diff --git a/server/src/apub/extensions/signatures.rs b/server/src/apub/extensions/signatures.rs index 4156f0b3..7aa9489c 100644 --- a/server/src/apub/extensions/signatures.rs +++ b/server/src/apub/extensions/signatures.rs @@ -1,8 +1,8 @@ use crate::apub::ActorType; use activitystreams::ext::Extension; use actix_web::HttpRequest; +use attohttpc::RequestBuilder; use failure::Error; -use http::request::Builder; use http_signature_normalization::Config; use log::debug; use openssl::{ @@ -35,28 +35,29 @@ pub fn generate_actor_keypair() -> Result<Keypair, Error> { }) } +// TODO is it possible to create this signature, with just the url and actor? /// Signs request headers with the given keypair. -pub fn sign(request: &Builder, actor: &dyn ActorType) -> Result<String, Error> { +pub fn sign(request: &mut RequestBuilder, actor: &dyn ActorType) -> Result<String, Error> { let signing_key_id = format!("{}#main-key", actor.actor_id()); let headers = request - .headers_ref() - .unwrap() + .inspect() + .headers() .iter() .map(|h| -> Result<(String, String), Error> { Ok((h.0.as_str().to_owned(), h.1.to_str()?.to_owned())) }) .collect::<Result<BTreeMap<String, String>, Error>>()?; + let mut path_and_query = request.inspect().url().path().to_owned(); + if let Some(query) = request.inspect().url().query() { + path_and_query.push_str(query); + } + let signature_header_value = HTTP_SIG_CONFIG .begin_sign( - request.method_ref().unwrap().as_str(), - request - .uri_ref() - .unwrap() - .path_and_query() - .unwrap() - .as_str(), + request.inspect().method().as_str(), + &path_and_query, headers, )? .sign(signing_key_id, |signing_string| { diff --git a/server/src/apub/fetcher.rs b/server/src/apub/fetcher.rs index 7f7a3f97..20bab4e2 100644 --- a/server/src/apub/fetcher.rs +++ b/server/src/apub/fetcher.rs @@ -2,7 +2,6 @@ use activitystreams::object::Note; use actix_web::Result; use diesel::{result::Error::NotFound, PgConnection}; use failure::{Error, _core::fmt::Debug}; -use isahc::prelude::*; use log::debug; use serde::Deserialize; use std::time::Duration; @@ -64,11 +63,11 @@ where } // TODO: this function should return a future let timeout = Duration::from_secs(60); - let text = Request::get(url.as_str()) + let text: String = attohttpc::get(url.as_str()) .header("Accept", APUB_JSON_CONTENT_TYPE) .connect_timeout(timeout) .timeout(timeout) - .body(())? + // .body(()) .send()? .text()?; let res: Response = serde_json::from_str(&text)?; diff --git a/server/src/apub/mod.rs b/server/src/apub/mod.rs index 6a2d6cff..7d2aee65 100644 --- a/server/src/apub/mod.rs +++ b/server/src/apub/mod.rs @@ -32,7 +32,6 @@ use actix_web::{body::Body, HttpResponse, Result}; use chrono::NaiveDateTime; use diesel::PgConnection; use failure::Error; -use isahc::prelude::*; use log::debug; use serde::Serialize; use url::Url; @@ -253,7 +252,7 @@ pub fn fetch_webfinger_url(mention: &MentionData) -> Result<String, Error> { mention.domain ); debug!("Fetching webfinger url: {}", &fetch_url); - let text = isahc::get(&fetch_url)?.text()?; + let text: String = attohttpc::get(&fetch_url).send()?.text()?; let res: WebFingerResponse = serde_json::from_str(&text)?; let link = res .links diff --git a/server/src/lib.rs b/server/src/lib.rs index 32c37439..2391449c 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -39,7 +39,6 @@ pub mod websocket; use crate::settings::Settings; use actix_web::dev::ConnectionInfo; use chrono::{DateTime, FixedOffset, Local, NaiveDateTime, Utc}; -use isahc::prelude::*; use itertools::Itertools; use lettre::{ smtp::{ @@ -86,7 +85,8 @@ pub fn is_email_regex(test: &str) -> bool { } pub fn is_image_content_type(test: &str) -> Result<(), failure::Error> { - if isahc::get(test)? + if attohttpc::get(test) + .send()? .headers() .get("Content-Type") .ok_or_else(|| format_err!("No Content-Type header"))? @@ -180,30 +180,40 @@ pub struct IframelyResponse { pub fn fetch_iframely(url: &str) -> Result<IframelyResponse, failure::Error> { let fetch_url = format!("http://iframely/oembed?url={}", url); - let text = isahc::get(&fetch_url)?.text()?; + let text: String = attohttpc::get(&fetch_url).send()?.text()?; let res: IframelyResponse = serde_json::from_str(&text)?; Ok(res) } -#[derive(Deserialize, Debug)] -pub struct PictshareResponse { - status: String, - url: String, +#[derive(Deserialize, Debug, Clone)] +pub struct PictrsResponse { + files: Vec<PictrsFile>, + msg: String, +} + +#[derive(Deserialize, Debug, Clone)] +pub struct PictrsFile { + file: String, + delete_token: String, } -pub fn fetch_pictshare(image_url: &str) -> Result<PictshareResponse, failure::Error> { +pub fn fetch_pictrs(image_url: &str) -> Result<PictrsResponse, failure::Error> { is_image_content_type(image_url)?; let fetch_url = format!( - "http://pictshare/api/geturl.php?url={}", - utf8_percent_encode(image_url, NON_ALPHANUMERIC) + "http://pictrs:8080/image/download?url={}", + utf8_percent_encode(image_url, NON_ALPHANUMERIC) // TODO this might not be needed ); - let text = isahc::get(&fetch_url)?.text()?; - let res: PictshareResponse = serde_json::from_str(&text)?; - Ok(res) + let text = attohttpc::get(&fetch_url).send()?.text()?; + let res: PictrsResponse = serde_json::from_str(&text)?; + if res.msg == "ok" { + Ok(res) + } else { + Err(format_err!("{}", &res.msg)) + } } -fn fetch_iframely_and_pictshare_data( +fn fetch_iframely_and_pictrs_data( url: Option<String>, ) -> ( Option<String>, @@ -223,20 +233,20 @@ fn fetch_iframely_and_pictshare_data( } }; - // Fetch pictshare thumbnail - let pictshare_thumbnail = match iframely_thumbnail_url { - Some(iframely_thumbnail_url) => match fetch_pictshare(&iframely_thumbnail_url) { - Ok(res) => Some(res.url), + // Fetch pictrs thumbnail + let pictrs_thumbnail = match iframely_thumbnail_url { + Some(iframely_thumbnail_url) => match fetch_pictrs(&iframely_thumbnail_url) { + Ok(res) => Some(res.files[0].file.to_owned()), Err(e) => { - error!("pictshare err: {}", e); + error!("pictrs err: {}", e); None } }, // Try to generate a small thumbnail if iframely is not supported - None => match fetch_pictshare(&url) { - Ok(res) => Some(res.url), + None => match fetch_pictrs(&url) { + Ok(res) => Some(res.files[0].file.to_owned()), Err(e) => { - error!("pictshare err: {}", e); + error!("pictrs err: {}", e); None } }, @@ -246,7 +256,7 @@ fn fetch_iframely_and_pictshare_data( iframely_title, iframely_description, iframely_html, - pictshare_thumbnail, + pictrs_thumbnail, ) } None => (None, None, None, None), @@ -298,11 +308,16 @@ pub fn is_valid_username(name: &str) -> bool { VALID_USERNAME_REGEX.is_match(name) } +pub fn is_valid_community_name(name: &str) -> bool { + VALID_COMMUNITY_NAME_REGEX.is_match(name) +} + #[cfg(test)] mod tests { use crate::{ is_email_regex, is_image_content_type, + is_valid_community_name, is_valid_username, remove_slurs, scrape_text_for_mentions, @@ -345,6 +360,15 @@ mod tests { } #[test] + fn test_valid_community_name() { + assert!(is_valid_community_name("example")); + assert!(is_valid_community_name("example_community")); + assert!(!is_valid_community_name("Example")); + assert!(!is_valid_community_name("Ex")); + assert!(!is_valid_community_name("")); + } + + #[test] fn test_slur_filter() { let test = "coons test dindu ladyboy tranny retardeds. Capitalized Niggerz. This is a bunch of other safe text."; @@ -402,4 +426,5 @@ lazy_static! { // static ref WEBFINGER_USER_REGEX: Regex = Regex::new(r"@(?P<name>[\w.]+)@(?P<domain>[a-zA-Z0-9._-]+\.[a-zA-Z0-9_-]+)").unwrap(); static ref WEBFINGER_USER_REGEX: Regex = Regex::new(r"@(?P<name>[\w.]+)@(?P<domain>[a-zA-Z0-9._:-]+)").unwrap(); static ref VALID_USERNAME_REGEX: Regex = Regex::new(r"^[a-zA-Z0-9_]{3,20}$").unwrap(); + static ref VALID_COMMUNITY_NAME_REGEX: Regex = Regex::new(r"^[a-z0-9_]{3,20}$").unwrap(); } diff --git a/server/src/version.rs b/server/src/version.rs index 354b86b4..22de3471 100644 --- a/server/src/version.rs +++ b/server/src/version.rs @@ -1 +1 @@ -pub const VERSION: &str = "v0.6.71"; +pub const VERSION: &str = "v0.7.0"; |