summaryrefslogtreecommitdiffstats
path: root/server/src
diff options
context:
space:
mode:
authorDessalines <tyhou13@gmx.com>2020-06-23 21:11:38 -0400
committerDessalines <tyhou13@gmx.com>2020-06-23 21:11:38 -0400
commitdc94e58cbf7e7de10d97331a3056380a3416e0b0 (patch)
tree85ed25783b0470ead3012a9718aea50b39c940dd /server/src
parentfd6a040568239d2e6949394fdc0ce0f7ac70275c (diff)
parent790b944031f9433be765936763d848ffa6e1b496 (diff)
Merge branch 'master' into federation_merge_from_master_2
Diffstat (limited to 'server/src')
-rw-r--r--server/src/api/community.rs24
-rw-r--r--server/src/api/mod.rs5
-rw-r--r--server/src/api/post.rs18
-rw-r--r--server/src/apub/activities.rs13
-rw-r--r--server/src/apub/extensions/signatures.rs23
-rw-r--r--server/src/apub/fetcher.rs5
-rw-r--r--server/src/apub/mod.rs3
-rw-r--r--server/src/lib.rs71
-rw-r--r--server/src/version.rs2
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";