Make Plume compile on release (#365)
* Remove use of String for body parameters Create SignedJson and implement FromData for it * Make Travis test on release * Remove warning when installing and fix coverage
This commit is contained in:
+44
-1
@@ -11,11 +11,21 @@ use activitypub::{
|
||||
object::Tombstone
|
||||
};
|
||||
use failure::Error;
|
||||
use rocket::{
|
||||
data::*,
|
||||
http::Status,
|
||||
Outcome::{self, *},
|
||||
Request,
|
||||
};
|
||||
use rocket_contrib::json::*;
|
||||
use serde::Deserialize;
|
||||
use serde_json;
|
||||
|
||||
use std::io::Read;
|
||||
|
||||
use plume_common::activity_pub::{
|
||||
inbox::{Deletable, FromActivity, InboxError},
|
||||
Id,
|
||||
Id,request::Digest,
|
||||
};
|
||||
use plume_models::{
|
||||
comments::Comment, follows::Follow, instance::Instance, likes, posts::Post, reshares::Reshare,
|
||||
@@ -125,3 +135,36 @@ pub trait Inbox {
|
||||
|
||||
impl Inbox for Instance {}
|
||||
impl Inbox for User {}
|
||||
|
||||
const JSON_LIMIT: u64 = 1 << 20;
|
||||
|
||||
pub struct SignedJson<T>(pub Digest, pub Json<T>);
|
||||
|
||||
impl<'a, T: Deserialize<'a>> FromData<'a> for SignedJson<T> {
|
||||
type Error = JsonError<'a>;
|
||||
type Owned = String;
|
||||
type Borrowed = str;
|
||||
|
||||
fn transform(r: &Request, d: Data) -> Transform<Outcome<Self::Owned, (Status, Self::Error), Data>> {
|
||||
let size_limit = r.limits().get("json").unwrap_or(JSON_LIMIT);
|
||||
let mut s = String::with_capacity(512);
|
||||
match d.open().take(size_limit).read_to_string(&mut s) {
|
||||
Ok(_) => Transform::Borrowed(Success(s)),
|
||||
Err(e) => Transform::Borrowed(Failure((Status::BadRequest, JsonError::Io(e))))
|
||||
}
|
||||
}
|
||||
|
||||
fn from_data(_: &Request, o: Transformed<'a, Self>) -> Outcome<Self, (Status, Self::Error), Data> {
|
||||
let string = o.borrowed()?;
|
||||
match serde_json::from_str(&string) {
|
||||
Ok(v) => Success(SignedJson(Digest::from_body(&string),Json(v))),
|
||||
Err(e) => {
|
||||
if e.is_data() {
|
||||
Failure((Status::UnprocessableEntity, JsonError::Parse(string, e)))
|
||||
} else {
|
||||
Failure((Status::BadRequest, JsonError::Parse(string, e)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ use plume_models::{
|
||||
safe_string::SafeString,
|
||||
instance::*
|
||||
};
|
||||
use inbox::Inbox;
|
||||
use inbox::{Inbox, SignedJson};
|
||||
use routes::Page;
|
||||
use template_utils::Ructe;
|
||||
use Searcher;
|
||||
@@ -186,15 +186,15 @@ pub fn ban(_admin: Admin, conn: DbConn, id: i32, searcher: Searcher) -> Redirect
|
||||
}
|
||||
|
||||
#[post("/inbox", data = "<data>")]
|
||||
pub fn shared_inbox(conn: DbConn, data: String, headers: Headers, searcher: Searcher) -> Result<String, status::BadRequest<&'static str>> {
|
||||
let act: serde_json::Value = serde_json::from_str(&data[..]).expect("instance::shared_inbox: deserialization error");
|
||||
pub fn shared_inbox(conn: DbConn, data: SignedJson<serde_json::Value>, headers: Headers, searcher: Searcher) -> Result<String, status::BadRequest<&'static str>> {
|
||||
let act = data.1.into_inner();
|
||||
|
||||
let activity = act.clone();
|
||||
let actor_id = activity["actor"].as_str()
|
||||
.or_else(|| activity["actor"]["id"].as_str()).ok_or(status::BadRequest(Some("Missing actor id for activity")))?;
|
||||
|
||||
let actor = User::from_url(&conn, actor_id).expect("instance::shared_inbox: user error");
|
||||
if !verify_http_headers(&actor, &headers.0, &data).is_secure() &&
|
||||
if !verify_http_headers(&actor, &headers.0, &data.0).is_secure() &&
|
||||
!act.clone().verify(&actor) {
|
||||
println!("Rejected invalid activity supposedly from {}, with headers {:?}", actor.username, headers.0);
|
||||
return Err(status::BadRequest(Some("Invalid signature")));
|
||||
|
||||
+4
-5
@@ -9,7 +9,7 @@ use rocket_i18n::I18n;
|
||||
use serde_json;
|
||||
use validator::{Validate, ValidationError, ValidationErrors};
|
||||
|
||||
use inbox::Inbox;
|
||||
use inbox::{Inbox, SignedJson};
|
||||
use plume_common::activity_pub::{
|
||||
broadcast,
|
||||
inbox::{Deletable, FromActivity, Notify},
|
||||
@@ -349,13 +349,12 @@ pub fn outbox(name: String, conn: DbConn) -> Option<ActivityStream<OrderedCollec
|
||||
pub fn inbox(
|
||||
name: String,
|
||||
conn: DbConn,
|
||||
data: String,
|
||||
data: SignedJson<serde_json::Value>,
|
||||
headers: Headers,
|
||||
searcher: Searcher,
|
||||
) -> Result<String, Option<status::BadRequest<&'static str>>> {
|
||||
let user = User::find_local(&*conn, &name).ok_or(None)?;
|
||||
let act: serde_json::Value =
|
||||
serde_json::from_str(&data).expect("user::inbox: deserialization error");
|
||||
let act = data.1.into_inner();
|
||||
|
||||
let activity = act.clone();
|
||||
let actor_id = activity["actor"]
|
||||
@@ -366,7 +365,7 @@ pub fn inbox(
|
||||
))))?;
|
||||
|
||||
let actor = User::from_url(&conn, actor_id).expect("user::inbox: user error");
|
||||
if !verify_http_headers(&actor, &headers.0, &data).is_secure()
|
||||
if !verify_http_headers(&actor, &headers.0, &data.0).is_secure()
|
||||
&& !act.clone().verify(&actor)
|
||||
{
|
||||
println!(
|
||||
|
||||
Reference in New Issue
Block a user