move towards using #[rocket::async_trait]

this also upgrades some dependencies
some of that fixes stuff, others breaks stuff.
This commit is contained in:
Igor Galić 2020-05-15 22:38:21 +02:00
parent 097d0ea9ce
commit 3c830ab0ce
No known key found for this signature in database
GPG Key ID: ACFEFF7F6A123A86
21 changed files with 314 additions and 291 deletions

1
.gitignore vendored
View File

@ -18,3 +18,4 @@ tags.*
search_index search_index
.buildconfig .buildconfig
__pycache__ __pycache__
.vscode/

79
Cargo.lock generated
View File

@ -6,7 +6,7 @@ version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5bfd311e7b4102971757a2a6f143a93b1a8e6b5afc2c46936af827fd9eab403f" checksum = "5bfd311e7b4102971757a2a6f143a93b1a8e6b5afc2c46936af827fd9eab403f"
dependencies = [ dependencies = [
"activitystreams-derive", "activitystreams-derive 0.1.1",
"activitystreams-traits", "activitystreams-traits",
"activitystreams-types", "activitystreams-types",
"serde", "serde",
@ -25,6 +25,17 @@ dependencies = [
"syn 0.13.11", "syn 0.13.11",
] ]
[[package]]
name = "activitystreams-derive"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "65608fdeae5eb05485d5b71a3d2242d76b2b7413608c196d47eb4dff3eed7b85"
dependencies = [
"proc-macro2 1.0.12",
"quote 1.0.4",
"syn 1.0.19",
]
[[package]] [[package]]
name = "activitystreams-traits" name = "activitystreams-traits"
version = "0.1.0" version = "0.1.0"
@ -42,7 +53,7 @@ version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff74c5765278614a009f97b9ec12f9a7c732bbcc5e0337fcfcab619b784860ec" checksum = "ff74c5765278614a009f97b9ec12f9a7c732bbcc5e0337fcfcab619b784860ec"
dependencies = [ dependencies = [
"activitystreams-derive", "activitystreams-derive 0.1.1",
"activitystreams-traits", "activitystreams-traits",
"chrono", "chrono",
"mime 0.3.16", "mime 0.3.16",
@ -142,7 +153,7 @@ checksum = "da71fef07bc806586090247e971229289f64c210a278ee5ae419314eb386b31d"
dependencies = [ dependencies = [
"proc-macro2 1.0.12", "proc-macro2 1.0.12",
"quote 1.0.4", "quote 1.0.4",
"syn 1.0.18", "syn 1.0.19",
] ]
[[package]] [[package]]
@ -746,7 +757,7 @@ dependencies = [
"bitflags 1.2.1", "bitflags 1.2.1",
"proc-macro2 1.0.12", "proc-macro2 1.0.12",
"quote 1.0.4", "quote 1.0.4",
"syn 1.0.18", "syn 1.0.19",
] ]
[[package]] [[package]]
@ -784,7 +795,7 @@ checksum = "45f5098f628d02a7a0f68ddba586fb61e80edec3bdc1be3b921f4ceec60858d3"
dependencies = [ dependencies = [
"proc-macro2 1.0.12", "proc-macro2 1.0.12",
"quote 1.0.4", "quote 1.0.4",
"syn 1.0.18", "syn 1.0.19",
] ]
[[package]] [[package]]
@ -978,7 +989,7 @@ checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4"
dependencies = [ dependencies = [
"proc-macro2 1.0.12", "proc-macro2 1.0.12",
"quote 1.0.4", "quote 1.0.4",
"syn 1.0.18", "syn 1.0.19",
"synstructure", "synstructure",
] ]
@ -993,9 +1004,9 @@ dependencies = [
[[package]] [[package]]
name = "filetime" name = "filetime"
version = "0.2.9" version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f59efc38004c988e4201d11d263b8171f49a2e7ec0bdbb71773433f271504a5e" checksum = "affc17579b132fc2461adf7c575cc6e8b134ebca52c51f5411388965227dc695"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"libc", "libc",
@ -1179,7 +1190,7 @@ dependencies = [
"proc-macro-hack 0.5.15", "proc-macro-hack 0.5.15",
"proc-macro2 1.0.12", "proc-macro2 1.0.12",
"quote 1.0.4", "quote 1.0.4",
"syn 1.0.18", "syn 1.0.19",
] ]
[[package]] [[package]]
@ -1829,7 +1840,7 @@ dependencies = [
"migrations_internals", "migrations_internals",
"proc-macro2 1.0.12", "proc-macro2 1.0.12",
"quote 1.0.4", "quote 1.0.4",
"syn 1.0.18", "syn 1.0.19",
] ]
[[package]] [[package]]
@ -2171,9 +2182,9 @@ checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de"
[[package]] [[package]]
name = "openssl-sys" name = "openssl-sys"
version = "0.9.55" version = "0.9.56"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7717097d810a0f2e2323f9e5d11e71608355e24828410b55b9d4f18aa5f9a5d8" checksum = "f02309a7f127000ed50594f0b50ecc69e7c654e16d41b4e8156d1b3df8e0b52e"
dependencies = [ dependencies = [
"autocfg 1.0.0", "autocfg 1.0.0",
"cc", "cc",
@ -2354,29 +2365,29 @@ dependencies = [
[[package]] [[package]]
name = "pin-project" name = "pin-project"
version = "0.4.10" version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "36e3dcd42688c05a66f841d22c5d8390d9a5d4c9aaf57b9285eae4900a080063" checksum = "82c3bfbfb5bb42f99498c7234bbd768c220eb0cea6818259d0d18a1aa3d2595d"
dependencies = [ dependencies = [
"pin-project-internal", "pin-project-internal",
] ]
[[package]] [[package]]
name = "pin-project-internal" name = "pin-project-internal"
version = "0.4.10" version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4d7346ac577ff1296e06a418e7618e22655bae834d4970cb6e39d6da8119969" checksum = "ccbf6449dcfb18562c015526b085b8df1aa3cdab180af8ec2ebd300a3bd28f63"
dependencies = [ dependencies = [
"proc-macro2 1.0.12", "proc-macro2 1.0.12",
"quote 1.0.4", "quote 1.0.4",
"syn 1.0.18", "syn 1.0.19",
] ]
[[package]] [[package]]
name = "pin-project-lite" name = "pin-project-lite"
version = "0.1.4" version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "237844750cfbb86f67afe27eee600dfbbcb6188d734139b534cbfbf4f96792ae" checksum = "f7505eeebd78492e0f6108f7171c4948dbb120ee8119d9d77d0afa5469bef67f"
[[package]] [[package]]
name = "pin-utils" name = "pin-utils"
@ -2435,7 +2446,6 @@ dependencies = [
"rpassword", "rpassword",
"rsass", "rsass",
"ructe", "ructe",
"runtime-fmt",
"scheduled-thread-pool", "scheduled-thread-pool",
"serde", "serde",
"serde_json", "serde_json",
@ -2472,7 +2482,7 @@ name = "plume-common"
version = "0.4.0" version = "0.4.0"
dependencies = [ dependencies = [
"activitypub", "activitypub",
"activitystreams-derive", "activitystreams-derive 0.2.0",
"activitystreams-traits", "activitystreams-traits",
"array_tool", "array_tool",
"base64 0.10.1", "base64 0.10.1",
@ -3066,7 +3076,7 @@ dependencies = [
[[package]] [[package]]
name = "rocket_i18n" name = "rocket_i18n"
version = "0.5.0" version = "0.5.0"
source = "git+https://github.com/Plume-org/rocket_i18n?branch=go-async#a6c8cfb3c516d857493d938ec0c89e7bd0c29cad" source = "git+https://github.com/Plume-org/rocket_i18n?branch=go-async#6ff7e2a7dd6dfc730478433f881300f36930ff52"
dependencies = [ dependencies = [
"gettext 0.4.0", "gettext 0.4.0",
"rocket", "rocket",
@ -3108,15 +3118,6 @@ dependencies = [
"nom 5.1.1", "nom 5.1.1",
] ]
[[package]]
name = "runtime-fmt"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "703425f78450961e590726ac24d823e6dc2340dc18282cf0cb6a417b26ca2ce8"
dependencies = [
"unicode-xid 0.2.0",
]
[[package]] [[package]]
name = "rust-stemmers" name = "rust-stemmers"
version = "1.2.0" version = "1.2.0"
@ -3266,7 +3267,7 @@ checksum = "9e549e3abf4fb8621bd1609f11dfc9f5e50320802273b12f3811a67e6716ea6c"
dependencies = [ dependencies = [
"proc-macro2 1.0.12", "proc-macro2 1.0.12",
"quote 1.0.4", "quote 1.0.4",
"syn 1.0.18", "syn 1.0.19",
] ]
[[package]] [[package]]
@ -3326,7 +3327,7 @@ dependencies = [
"itertools", "itertools",
"proc-macro2 1.0.12", "proc-macro2 1.0.12",
"quote 1.0.4", "quote 1.0.4",
"syn 1.0.18", "syn 1.0.19",
] ]
[[package]] [[package]]
@ -3339,7 +3340,7 @@ dependencies = [
"itertools", "itertools",
"proc-macro2 1.0.12", "proc-macro2 1.0.12",
"quote 1.0.4", "quote 1.0.4",
"syn 1.0.18", "syn 1.0.19",
] ]
[[package]] [[package]]
@ -3561,9 +3562,9 @@ dependencies = [
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.18" version = "1.0.19"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "410a7488c0a728c7ceb4ad59b9567eb4053d02e8cc7f5c0e0eeeb39518369213" checksum = "e8e5aa70697bb26ee62214ae3288465ecec0000f05182f039b477001f08f5ae7"
dependencies = [ dependencies = [
"proc-macro2 1.0.12", "proc-macro2 1.0.12",
"quote 1.0.4", "quote 1.0.4",
@ -3587,7 +3588,7 @@ checksum = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545"
dependencies = [ dependencies = [
"proc-macro2 1.0.12", "proc-macro2 1.0.12",
"quote 1.0.4", "quote 1.0.4",
"syn 1.0.18", "syn 1.0.19",
"unicode-xid 0.2.0", "unicode-xid 0.2.0",
] ]
@ -4069,7 +4070,7 @@ dependencies = [
"log 0.4.8", "log 0.4.8",
"proc-macro2 1.0.12", "proc-macro2 1.0.12",
"quote 1.0.4", "quote 1.0.4",
"syn 1.0.18", "syn 1.0.19",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
@ -4103,7 +4104,7 @@ checksum = "8eb197bd3a47553334907ffd2f16507b4f4f01bbec3ac921a7719e0decdfe72a"
dependencies = [ dependencies = [
"proc-macro2 1.0.12", "proc-macro2 1.0.12",
"quote 1.0.4", "quote 1.0.4",
"syn 1.0.18", "syn 1.0.19",
"wasm-bindgen-backend", "wasm-bindgen-backend",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]

View File

@ -23,7 +23,6 @@ num_cpus = "1.10"
rocket = { git = "https://github.com/SergioBenitez/Rocket", rev = "async" } rocket = { git = "https://github.com/SergioBenitez/Rocket", rev = "async" }
rocket_contrib = { git = "https://github.com/SergioBenitez/Rocket", rev = "async" , features = ["json"] } rocket_contrib = { git = "https://github.com/SergioBenitez/Rocket", rev = "async" , features = ["json"] }
rpassword = "4.0" rpassword = "4.0"
runtime-fmt = "0.4.0"
scheduled-thread-pool = "0.2.2" scheduled-thread-pool = "0.2.2"
serde = "1.0" serde = "1.0"
serde_json = "1.0" serde_json = "1.0"

View File

@ -6,7 +6,7 @@ edition = "2018"
[dependencies] [dependencies]
activitypub = "0.1.1" activitypub = "0.1.1"
activitystreams-derive = "0.1.1" activitystreams-derive = "0.2"
activitystreams-traits = "0.1.0" activitystreams-traits = "0.1.0"
array_tool = "1.0" array_tool = "1.0"
base64 = "0.10" base64 = "0.10"

View File

@ -3,8 +3,8 @@ use array_tool::vec::Uniq;
use reqwest::ClientBuilder; use reqwest::ClientBuilder;
use rocket::{ use rocket::{
http::Status, http::Status,
request::{FromRequestAsync, FromRequestFuture, Request}, request::{FromRequest, Request},
response::{Responder, Response, ResultFuture}, response::{Responder, Response, Result},
Outcome, Outcome,
}; };
use serde_json; use serde_json;
@ -61,42 +61,36 @@ impl<T> ActivityStream<T> {
ActivityStream(t) ActivityStream(t)
} }
} }
#[rocket::async_trait]
impl<'r, O: Object + Send + 'r> Responder<'r> for ActivityStream<O> { impl<'r, O: Object + Send + 'r> Responder<'r> for ActivityStream<O> {
fn respond_to(self, request: &'r Request<'_>) -> ResultFuture<'r> { async fn respond_to(self, request: &'r Request<'_>) -> Result<'r> {
Box::pin(async move { let mut json = serde_json::to_value(&self.0).map_err(|_| Status::InternalServerError)?;
let mut json = json["@context"] = context();
serde_json::to_value(&self.0).map_err(|_| Status::InternalServerError)?; let result = serde_json::to_string(&json).map_err(rocket::response::Debug);
json["@context"] = context(); match result.respond_to(request).await {
let result = serde_json::to_string(&json).map_err(rocket::response::Debug); Ok(r) => Response::build_from(r)
match result.respond_to(request).await { .raw_header("Content-Type", "application/activity+json")
Ok(r) => { .ok(),
Response::build_from(r) Err(e) => Err(e),
.raw_header("Content-Type", "application/activity+json") }
.ok()
.await
}
Err(e) => Err(e),
}
})
} }
} }
#[derive(Clone)] #[derive(Clone)]
pub struct ApRequest; pub struct ApRequest;
impl<'a, 'r> FromRequestAsync<'a, 'r> for ApRequest { #[rocket::async_trait]
impl<'a, 'r> FromRequest<'a, 'r> for ApRequest {
type Error = (); type Error = ();
fn from_request(request: &'a Request<'r>) -> FromRequestFuture<'a, Self, Self::Error> { async fn from_request(request: &'a Request<'r>) -> Outcome<Self, (Status, Self::Error), ()> {
Box::pin(async move { request
request .headers()
.headers() .get_one("Accept")
.get_one("Accept") .map(|header| {
.map(|header| { header
header .split(',')
.split(',') .map(|ct| {
.map(|ct| { match ct.trim() {
match ct.trim() {
// bool for Forward: true if found a valid Content-Type for Plume first (HTML), // bool for Forward: true if found a valid Content-Type for Plume first (HTML),
// false otherwise // false otherwise
"application/ld+json; profile=\"https://w3.org/ns/activitystreams\"" "application/ld+json; profile=\"https://w3.org/ns/activitystreams\""
@ -106,18 +100,17 @@ impl<'a, 'r> FromRequestAsync<'a, 'r> for ApRequest {
"text/html" => Outcome::Forward(true), "text/html" => Outcome::Forward(true),
_ => Outcome::Forward(false), _ => Outcome::Forward(false),
} }
}) })
.fold(Outcome::Forward(false), |out, ct| { .fold(Outcome::Forward(false), |out, ct| {
if out.clone().forwarded().unwrap_or_else(|| out.is_success()) { if out.clone().forwarded().unwrap_or_else(|| out.is_success()) {
out out
} else { } else {
ct ct
} }
}) })
.map_forward(|_| ()) .map_forward(|_| ())
}) })
.unwrap_or(Outcome::Forward(())) .unwrap_or(Outcome::Forward(()))
})
} }
} }
pub fn broadcast<S, A, T, C>(sender: &S, act: A, to: Vec<T>) pub fn broadcast<S, A, T, C>(sender: &S, act: A, to: Vec<T>)
@ -217,8 +210,7 @@ pub struct PublicKey {
pub public_key_pem: Option<serde_json::Value>, pub public_key_pem: Option<serde_json::Value>,
} }
#[derive(Clone, Debug, Default, UnitString)] #[derive(Clone, Debug, Default, Deserialize, Serialize)]
#[activitystreams(Hashtag)]
pub struct HashtagType; pub struct HashtagType;
#[derive(Clone, Debug, Default, Deserialize, Serialize, Properties)] #[derive(Clone, Debug, Default, Deserialize, Serialize, Properties)]

View File

@ -1,42 +1,40 @@
use crate::users::User; use crate::users::User;
use rocket::{ use rocket::{
http::Status, http::Status,
request::{self, FromRequestAsync, Request}, request::{self, FromRequest, Request},
Outcome, Outcome,
}; };
/// Wrapper around User to use as a request guard on pages reserved to admins. /// Wrapper around User to use as a request guard on pages reserved to admins.
pub struct Admin(pub User); pub struct Admin(pub User);
impl<'a, 'r> FromRequestAsync<'a, 'r> for Admin { #[rocket::async_trait]
impl<'a, 'r> FromRequest<'a, 'r> for Admin {
type Error = (); type Error = ();
fn from_request(request: &'a Request<'r>) -> request::FromRequestFuture<'a, Self, Self::Error> { async fn from_request(request: &'a Request<'r>) -> request::Outcome<Self, Self::Error> {
Box::pin(async move { let user = try_outcome!(User::from_request(request).await);
let user = try_outcome!(User::from_request(request).await); if user.is_admin() {
if user.is_admin() { Outcome::Success(Admin(user))
Outcome::Success(Admin(user)) } else {
} else { Outcome::Failure((Status::Unauthorized, ()))
Outcome::Failure((Status::Unauthorized, ())) }
}
})
} }
} }
/// Same as `Admin` but for moderators. /// Same as `Admin` but for moderators.
pub struct Moderator(pub User); pub struct Moderator(pub User);
impl<'a, 'r> FromRequestAsync<'a, 'r> for Moderator { #[rocket::async_trait]
impl<'a, 'r> FromRequest<'a, 'r> for Moderator {
type Error = (); type Error = ();
fn from_request(request: &'a Request<'r>) -> request::FromRequestFuture<'a, Self, Self::Error> { async fn from_request(request: &'a Request<'r>) -> request::Outcome<Self, Self::Error> {
Box::pin(async move { let user = try_outcome!(User::from_request(request).await);
let user = try_outcome!(User::from_request(request).await); if user.is_moderator() {
if user.is_moderator() { Outcome::Success(Moderator(user))
Outcome::Success(Moderator(user)) } else {
} else { Outcome::Failure((Status::Unauthorized, ()))
Outcome::Failure((Status::Unauthorized, ())) }
}
})
} }
} }

View File

@ -3,7 +3,7 @@ use chrono::NaiveDateTime;
use diesel::{self, ExpressionMethods, QueryDsl, RunQueryDsl}; use diesel::{self, ExpressionMethods, QueryDsl, RunQueryDsl};
use rocket::{ use rocket::{
http::Status, http::Status,
request::{self, FromRequestAsync, Request}, request::{self, FromRequest, Request},
Outcome, Outcome,
}; };
@ -76,39 +76,38 @@ pub enum TokenError {
DbError, DbError,
} }
impl<'a, 'r> FromRequestAsync<'a, 'r> for ApiToken { #[rocket::async_trait]
impl<'a, 'r> FromRequest<'a, 'r> for ApiToken {
type Error = TokenError; type Error = TokenError;
fn from_request(request: &'a Request<'r>) -> request::FromRequestFuture<'a, Self, Self::Error> { async fn from_request(request: &'a Request<'r>) -> request::Outcome<Self, Self::Error> {
Box::pin(async move { let headers: Vec<_> = request.headers().get("Authorization").collect();
let headers: Vec<_> = request.headers().get("Authorization").collect(); if headers.len() != 1 {
if headers.len() != 1 { return Outcome::Failure((Status::BadRequest, TokenError::NoHeader));
return Outcome::Failure((Status::BadRequest, TokenError::NoHeader)); }
}
let mut parsed_header = headers[0].split(' '); let mut parsed_header = headers[0].split(' ');
if let Some(auth_type) = parsed_header.next() { if let Some(auth_type) = parsed_header.next() {
if let Some(val) = parsed_header.next() { if let Some(val) = parsed_header.next() {
if auth_type == "Bearer" { if auth_type == "Bearer" {
if let Outcome::Success(conn) = DbConn::from_request(request).await { if let Outcome::Success(conn) = DbConn::from_request(request).await {
if let Ok(token) = ApiToken::find_by_value(&*conn, val) { if let Ok(token) = ApiToken::find_by_value(&*conn, val) {
return Outcome::Success(token); return Outcome::Success(token);
}
} else {
return Outcome::Failure((
Status::InternalServerError,
TokenError::DbError,
));
} }
} else {
return Outcome::Failure((
Status::InternalServerError,
TokenError::DbError,
));
} }
} else {
return Outcome::Failure((Status::BadRequest, TokenError::NoValue));
} }
} else { } else {
return Outcome::Failure((Status::BadRequest, TokenError::NoType)); return Outcome::Failure((Status::BadRequest, TokenError::NoValue));
} }
} else {
return Outcome::Failure((Status::BadRequest, TokenError::NoType));
}
Outcome::Forward(()) Outcome::Forward(())
})
} }
} }

View File

@ -6,7 +6,7 @@ use diesel::r2d2::{
use diesel::{dsl::sql_query, ConnectionError, RunQueryDsl}; use diesel::{dsl::sql_query, ConnectionError, RunQueryDsl};
use rocket::{ use rocket::{
http::Status, http::Status,
request::{self, FromRequestAsync}, request::{self, FromRequest},
Outcome, Request, Outcome, Request,
}; };
use std::ops::Deref; use std::ops::Deref;
@ -21,16 +21,15 @@ pub struct DbConn(pub PooledConnection<ConnectionManager<Connection>>);
/// Attempts to retrieve a single connection from the managed database pool. If /// Attempts to retrieve a single connection from the managed database pool. If
/// no pool is currently managed, fails with an `InternalServerError` status. If /// no pool is currently managed, fails with an `InternalServerError` status. If
/// no connections are available, fails with a `ServiceUnavailable` status. /// no connections are available, fails with a `ServiceUnavailable` status.
impl<'a, 'r> FromRequestAsync<'a, 'r> for DbConn { #[rocket::async_trait]
impl<'a, 'r> FromRequest<'a, 'r> for DbConn {
type Error = (); type Error = ();
fn from_request(request: &'a Request<'r>) -> request::FromRequestFuture<'a, Self, Self::Error> { async fn from_request(request: &'a Request<'r>) -> request::Outcome<Self, Self::Error> {
Box::pin(async move { match DbConn::from_request(request).await {
match DbConn::from_request(request).await { Outcome::Success(a) => return Outcome::Success(a),
Outcome::Success(a) => return Outcome::Success(a), _ => return Outcome::Failure((Status::ServiceUnavailable, ())),
_ => return Outcome::Failure((Status::ServiceUnavailable, ())), };
};
})
} }
} }

View File

@ -6,10 +6,11 @@ use rocket::{
pub struct Headers<'r>(pub HeaderMap<'r>); pub struct Headers<'r>(pub HeaderMap<'r>);
#[rocket::async_trait]
impl<'a, 'r> FromRequest<'a, 'r> for Headers<'r> { impl<'a, 'r> FromRequest<'a, 'r> for Headers<'r> {
type Error = (); type Error = ();
fn from_request(request: &'a Request<'r>) -> request::Outcome<Self, ()> { async fn from_request(request: &'a Request<'r>) -> request::Outcome<Self, ()> {
let mut headers = HeaderMap::new(); let mut headers = HeaderMap::new();
for header in request.headers().clone().into_iter() { for header in request.headers().clone().into_iter() {
headers.add(header); headers.add(header);

View File

@ -4,7 +4,7 @@ pub use self::module::PlumeRocket;
mod module { mod module {
use crate::{db_conn::DbConn, search, users}; use crate::{db_conn::DbConn, search, users};
use rocket::{ use rocket::{
request::{self, FlashMessage, FromRequestAsync, Request}, request::{self, FlashMessage, FromRequest, Request},
Outcome, State, Outcome, State,
}; };
use scheduled_thread_pool::ScheduledThreadPool; use scheduled_thread_pool::ScheduledThreadPool;
@ -20,29 +20,38 @@ mod module {
pub flash_msg: Option<(String, String)>, pub flash_msg: Option<(String, String)>,
} }
impl<'a, 'r> FromRequestAsync<'a, 'r> for PlumeRocket { #[rocket::async_trait]
impl<'a, 'r> FromRequest<'a, 'r> for PlumeRocket {
type Error = (); type Error = ();
fn from_request( async fn from_request(request: &'a Request<'r>) -> request::Outcome<Self, Self::Error> {
request: &'a Request<'r>, let conn = DbConn::from_request(request).await.succeeded().unwrap();
) -> request::FromRequestFuture<'a, Self, Self::Error> { let intl = rocket_i18n::I18n::from_request(request)
Box::pin(async move { .await
let conn = try_outcome!(DbConn::from_request(request).await); .succeeded()
let intl = try_outcome!(rocket_i18n::I18n::from_request(request).await); .unwrap();
let user = try_outcome!(users::User::from_request(request).await); let user = users::User::from_request(request)
let worker = .await
try_outcome!(request.guard::<'_, State<'_, Arc<ScheduledThreadPool>>>()); .succeeded()
let searcher = .unwrap();
try_outcome!(request.guard::<'_, State<'_, Arc<search::Searcher>>>()); let worker = request
let flash_msg = request.guard::<FlashMessage<'_, '_>>().succeeded(); .guard::<State<'_, Arc<ScheduledThreadPool>>>()
Outcome::Success(PlumeRocket { .await
conn, .succeeded()
intl, .unwrap();
user: Some(user), let searcher = request
flash_msg: flash_msg.map(|f| (f.name().into(), f.msg().into())), .guard::<State<'_, Arc<search::Searcher>>>()
worker: worker.clone(), .await
searcher: searcher.clone(), .succeeded()
}) .unwrap();
let flash_msg = request.guard::<FlashMessage<'_, '_>>().await.succeeded();
Outcome::Success(PlumeRocket {
conn,
intl,
user: Some(user),
flash_msg: flash_msg.map(|f| (f.name().into(), f.msg().into())),
worker: worker.clone(),
searcher: searcher.clone(),
}) })
} }
} }
@ -52,7 +61,7 @@ mod module {
mod module { mod module {
use crate::{db_conn::DbConn, search, users}; use crate::{db_conn::DbConn, search, users};
use rocket::{ use rocket::{
request::{self, FromRequestAsync, Request}, request::{self, FromRequest, Request},
Outcome, State, Outcome, State,
}; };
use scheduled_thread_pool::ScheduledThreadPool; use scheduled_thread_pool::ScheduledThreadPool;
@ -66,25 +75,20 @@ mod module {
pub worker: Arc<ScheduledThreadPool>, pub worker: Arc<ScheduledThreadPool>,
} }
impl<'a, 'r> FromRequestAsync<'a, 'r> for PlumeRocket { #[rocket::async_trait]
impl<'a, 'r> FromRequest<'a, 'r> for PlumeRocket {
type Error = (); type Error = ();
fn from_request( async fn from_request(request: &'a Request<'r>) -> request::Outcome<Self, Self::Error> {
request: &'a Request<'r>, let conn = try_outcome!(DbConn::from_request(request).await);
) -> request::FromRequestFuture<'a, Self, Self::Error> { let user = try_outcome!(users::User::from_request(request).await);
Box::pin(async move { let worker = try_outcome!(request.guard::<'_, State<'_, Arc<ScheduledThreadPool>>>());
let conn = try_outcome!(DbConn::from_request(request).await); let searcher = try_outcome!(request.guard::<'_, State<'_, Arc<search::Searcher>>>());
let user = try_outcome!(users::User::from_request(request).await); Outcome::Success(PlumeRocket {
let worker = conn,
try_outcome!(request.guard::<'_, State<'_, Arc<ScheduledThreadPool>>>()); user: Some(user),
let searcher = worker: worker.clone(),
try_outcome!(request.guard::<'_, State<'_, Arc<search::Searcher>>>()); searcher: searcher.clone(),
Outcome::Success(PlumeRocket {
conn,
user: Some(user),
worker: worker.clone(),
searcher: searcher.clone(),
})
}) })
} }
} }

View File

@ -35,7 +35,7 @@ use reqwest::{
}; };
use rocket::{ use rocket::{
outcome::IntoOutcome, outcome::IntoOutcome,
request::{self, FromRequestAsync, Request}, request::{self, FromRequest, Request},
}; };
use serde_json; use serde_json;
use std::{ use std::{
@ -796,19 +796,18 @@ impl User {
} }
} }
impl<'a, 'r> FromRequestAsync<'a, 'r> for User { #[rocket::async_trait]
impl<'a, 'r> FromRequest<'a, 'r> for User {
type Error = (); type Error = ();
fn from_request(request: &'a Request<'r>) -> request::FromRequestFuture<'a, Self, Self::Error> { async fn from_request(request: &'a Request<'r>) -> request::Outcome<Self, Self::Error> {
Box::pin(async move { let conn = try_outcome!(DbConn::from_request(request).await);
let conn = try_outcome!(DbConn::from_request(request).await); request
request .cookies()
.cookies() .get_private(AUTH_COOKIE)
.get_private(AUTH_COOKIE) .and_then(|cookie| cookie.value().parse().ok())
.and_then(|cookie| cookie.value().parse().ok()) .and_then(|id| User::get(&*conn, id).ok())
.and_then(|id| User::get(&*conn, id).ok()) .or_forward(())
.or_forward(())
})
} }
} }

View File

@ -1 +1 @@
nightly-2020-01-15 nightly-2020-05-05

View File

@ -35,6 +35,7 @@ impl Scope for plume_models::posts::Post {
pub struct Authorization<A, S>(pub ApiToken, PhantomData<(A, S)>); pub struct Authorization<A, S>(pub ApiToken, PhantomData<(A, S)>);
#[rocket::async_trait]
impl<'a, 'r, A, S> FromRequest<'a, 'r> for Authorization<A, S> impl<'a, 'r, A, S> FromRequest<'a, 'r> for Authorization<A, S>
where where
A: Action, A: Action,
@ -42,9 +43,10 @@ where
{ {
type Error = (); type Error = ();
fn from_request(request: &'a Request<'r>) -> request::Outcome<Authorization<A, S>, ()> { async fn from_request(request: &'a Request<'r>) -> request::Outcome<Authorization<A, S>, ()> {
request request
.guard::<ApiToken>() .guard::<ApiToken>()
.await
.map_failure(|_| (Status::Unauthorized, ())) .map_failure(|_| (Status::Unauthorized, ()))
.and_then(|token| { .and_then(|token| {
if token.can(A::to_str(), S::to_str()) { if token.can(A::to_str(), S::to_str()) {

View File

@ -2,6 +2,7 @@
use rocket::{ use rocket::{
request::{Form, Request}, request::{Form, Request},
response::{self, Responder}, response::{self, Responder},
Outcome,
}; };
use rocket_contrib::json::Json; use rocket_contrib::json::Json;
use serde_json; use serde_json;
@ -26,21 +27,31 @@ impl From<std::option::NoneError> for ApiError {
} }
} }
#[rocket::async_trait]
impl<'r> Responder<'r> for ApiError { impl<'r> Responder<'r> for ApiError {
fn respond_to(self, req: &'r Request) -> response::ResultFuture<'r> { async fn respond_to(self, req: &'r Request<'_>) -> response::Result<'r> {
match self.0 { match self.0 {
Error::NotFound => Json(json!({ Error::NotFound => {
"error": "Not found" Json(json!({
})) "error": "Not found"
.respond_to(req), }))
Error::Unauthorized => Json(json!({ .respond_to(req)
"error": "You are not authorized to access this resource" .await
})) }
.respond_to(req), Error::Unauthorized => {
_ => Json(json!({ Json(json!({
"error": "Server error" "error": "You are not authorized to access this resource"
})) }))
.respond_to(req), .respond_to(req)
.await
}
_ => {
Json(json!({
"error": "Server error"
}))
.respond_to(req)
.await
}
} }
} }
} }
@ -62,7 +73,7 @@ pub fn oauth(
let conn = &*rockets.conn; let conn = &*rockets.conn;
let app = App::find_by_client_id(conn, &query.client_id)?; let app = App::find_by_client_id(conn, &query.client_id)?;
if app.client_secret == query.client_secret { if app.client_secret == query.client_secret {
if let Ok(user) = User::find_by_fqn(&rockets, &query.username) { if let Outcome::Success(user) = User::find_by_fqn(&rockets, &query.username) {
if user.auth(&query.password) { if user.auth(&query.password) {
let token = ApiToken::insert( let token = ApiToken::insert(
conn, conn,

View File

@ -6,8 +6,6 @@ extern crate gettext_macros;
#[macro_use] #[macro_use]
extern crate rocket; extern crate rocket;
#[macro_use] #[macro_use]
extern crate runtime_fmt;
#[macro_use]
extern crate serde_json; extern crate serde_json;
#[macro_use] #[macro_use]
extern crate validator_derive; extern crate validator_derive;

View File

@ -1,7 +1,7 @@
use crate::template_utils::{IntoContext, Ructe}; use crate::template_utils::{IntoContext, Ructe};
use plume_models::{Error, PlumeRocket}; use plume_models::{Error, PlumeRocket};
use rocket::{ use rocket::{
request::FromRequestAsync, request::FromRequest,
response::{self, Responder}, response::{self, Responder},
Request, Request,
}; };
@ -15,29 +15,28 @@ impl From<Error> for ErrorPage {
} }
} }
#[rocket::async_trait]
impl<'r> Responder<'r> for ErrorPage { impl<'r> Responder<'r> for ErrorPage {
fn respond_to(self, req: &'r Request<'_>) -> response::ResultFuture<'r> { async fn respond_to(self, req: &'r Request<'_>) -> response::Result<'r> {
Box::pin(async move { let rockets = PlumeRocket::from_request(req).await.unwrap();
let rockets = PlumeRocket::from_request(req).await.unwrap();
match self.0 { match self.0 {
Error::NotFound => { Error::NotFound => {
render!(errors::not_found(&rockets.to_context())) render!(errors::not_found(&rockets.to_context()))
.respond_to(req) .respond_to(req)
.await .await
}
Error::Unauthorized => {
render!(errors::not_found(&rockets.to_context()))
.respond_to(req)
.await
}
_ => {
render!(errors::not_found(&rockets.to_context()))
.respond_to(req)
.await
}
} }
}) Error::Unauthorized => {
render!(errors::not_found(&rockets.to_context()))
.respond_to(req)
.await
}
_ => {
render!(errors::not_found(&rockets.to_context()))
.respond_to(req)
.await
}
}
} }
} }

View File

@ -94,10 +94,11 @@ impl Page {
#[derive(Shrinkwrap)] #[derive(Shrinkwrap)]
pub struct ContentLen(pub u64); pub struct ContentLen(pub u64);
#[rocket::async_trait]
impl<'a, 'r> FromRequest<'a, 'r> for ContentLen { impl<'a, 'r> FromRequest<'a, 'r> for ContentLen {
type Error = (); type Error = ();
fn from_request(r: &'a Request<'r>) -> request::Outcome<Self, Self::Error> { async fn from_request(r: &'a Request<'r>) -> request::Outcome<Self, Self::Error> {
match r.limits().get("forms") { match r.limits().get("forms") {
Some(l) => Outcome::Success(ContentLen(l)), Some(l) => Outcome::Success(ContentLen(l)),
None => Outcome::Failure((Status::InternalServerError, ())), None => Outcome::Failure((Status::InternalServerError, ())),
@ -213,32 +214,29 @@ pub struct CachedFile {
#[derive(Debug)] #[derive(Debug)]
pub struct ThemeFile(NamedFile); pub struct ThemeFile(NamedFile);
#[rocket::async_trait]
impl<'r> Responder<'r> for ThemeFile { impl<'r> Responder<'r> for ThemeFile {
fn respond_to(self, r: &'r Request<'_>) -> response::ResultFuture<'r> { async fn respond_to(self, r: &'r Request<'_>) -> response::Result<'r> {
Box::pin(async move { let contents = std::fs::read(self.0.path()).map_err(|_| Status::InternalServerError)?;
let contents = std::fs::read(self.0.path()).map_err(|_| Status::InternalServerError)?;
let mut hasher = DefaultHasher::new(); let mut hasher = DefaultHasher::new();
hasher.write(&contents); hasher.write(&contents);
let etag = format!("{:x}", hasher.finish()); let etag = format!("{:x}", hasher.finish());
if r.headers() if r.headers()
.get("If-None-Match") .get("If-None-Match")
.any(|s| s[1..s.len() - 1] == etag) .any(|s| s[1..s.len() - 1] == etag)
{ {
Response::build() Response::build()
.status(Status::NotModified) .status(Status::NotModified)
.header(Header::new("ETag", etag)) .header(Header::new("ETag", etag))
.ok() .ok()
.await } else {
} else { Response::build()
Response::build() .merge(self.0.respond_to(r).await.ok().unwrap())
.merge(self.0.respond_to(r).await.ok().unwrap()) .header(Header::new("ETag", etag))
.header(Header::new("ETag", etag)) .ok()
.ok() }
.await
}
})
} }
} }

View File

@ -643,7 +643,7 @@ pub fn remote_interact_post(
.and_then(|blog| Post::find_by_slug(&rockets.conn, &slug, blog.id))?; .and_then(|blog| Post::find_by_slug(&rockets.conn, &slug, blog.id))?;
if let Some(uri) = User::fetch_remote_interact_uri(&remote.remote) if let Some(uri) = User::fetch_remote_interact_uri(&remote.remote)
.ok() .ok()
.and_then(|uri| rt_format!(uri, uri = target.ap_url).ok()) .and_then(|uri| uri.replace("{uri}", format!("{}", target.ap_url)).ok())
{ {
Ok(Redirect::to(uri).into()) Ok(Redirect::to(uri).into())
} else { } else {

View File

@ -201,15 +201,14 @@ pub fn follow_not_connected(
if let Some(uri) = User::fetch_remote_interact_uri(&remote_form) if let Some(uri) = User::fetch_remote_interact_uri(&remote_form)
.ok() .ok()
.and_then(|uri| { .and_then(|uri| {
rt_format!( uri.replace(
uri, "{uri}",
uri = format!( format!(
"{}@{}", "{}@{}",
target.fqn, target.fqn,
target.get_instance(&rockets.conn).ok()?.public_domain target.get_instance(&rockets.conn).ok()?.public_domain
) ),
) )
.ok()
}) })
{ {
Ok(Redirect::to(uri).into()) Ok(Redirect::to(uri).into())

View File

@ -44,21 +44,47 @@ pub fn host_meta() -> String {
struct WebfingerResolver; struct WebfingerResolver;
impl Resolver<PlumeRocket> for WebfingerResolver { impl Resolver<PlumeRocket> for WebfingerResolver {
fn instance_domain<'a>() -> &'a str { fn instance_domain<'a>(&self) -> &'a str {
CONFIG.base_url.as_str() CONFIG.base_url.as_str()
} }
fn find(prefix: Prefix, acct: String, ctx: PlumeRocket) -> Result<Webfinger, ResolverError> { fn find(
&self,
prefix: Prefix,
acct: String,
ctx: PlumeRocket,
) -> Result<Webfinger, ResolverError> {
match prefix { match prefix {
Prefix::Acct => User::find_by_fqn(&ctx, &acct) Prefix::Acct => User::find_by_fqn(&ctx, &acct)
.await
.and_then(|usr| usr.webfinger(&*ctx.conn)) .and_then(|usr| usr.webfinger(&*ctx.conn))
.or(Err(ResolverError::NotFound)), .or(Err(ResolverError::NotFound)),
Prefix::Group => Blog::find_by_fqn(&ctx, &acct) Prefix::Group => Blog::find_by_fqn(&ctx, &acct)
.await
.and_then(|blog| blog.webfinger(&*ctx.conn)) .and_then(|blog| blog.webfinger(&*ctx.conn))
.or(Err(ResolverError::NotFound)), .or(Err(ResolverError::NotFound)),
Prefix::Custom(_) => Err(ResolverError::NotFound), Prefix::Custom(_) => Err(ResolverError::NotFound),
} }
} }
fn endpoint(
&self,
resource: impl Into<String>,
resource_repo: PlumeRocket,
) -> Result<Webfinger, ResolverError> {
let resource = resource.into();
let mut parsed_query = resource.splitn(2, ':');
let res_prefix = Prefix::from(parsed_query.next().ok_or(ResolverError::InvalidResource)?);
let res = parsed_query.next().ok_or(ResolverError::InvalidResource)?;
let mut parsed_res = res.splitn(2, '@');
let user = parsed_res.next().ok_or(ResolverError::InvalidResource)?;
let domain = parsed_res.next().ok_or(ResolverError::InvalidResource)?;
if domain == webfinger.instance_domain() {
webfinger.find(res_prefix, user.to_string(), resource_repo)
} else {
Err(ResolverError::WrongDomain)
}
}
} }
#[get("/.well-known/webfinger?<resource>")] #[get("/.well-known/webfinger?<resource>")]

View File

@ -51,33 +51,30 @@ impl IntoContext for PlumeRocket {
#[derive(Debug)] #[derive(Debug)]
pub struct Ructe(pub Vec<u8>); pub struct Ructe(pub Vec<u8>);
#[rocket::async_trait]
impl<'r> Responder<'r> for Ructe { impl<'r> Responder<'r> for Ructe {
fn respond_to(self, r: &'r Request) -> response::ResultFuture<'r> { async fn respond_to(self, r: &'r Request<'_>) -> response::Result<'r> {
Box::pin(async move { //if method is not Get or page contain a form, no caching
//if method is not Get or page contain a form, no caching if r.method() != Method::Get || self.0.windows(6).any(|w| w == b"<form ") {
if r.method() != Method::Get || self.0.windows(6).any(|w| w == b"<form ") { return HtmlCt(self.0).respond_to(r).await;
return HtmlCt(self.0).respond_to(r).await; }
} let mut hasher = DefaultHasher::new();
let mut hasher = DefaultHasher::new(); hasher.write(&self.0);
hasher.write(&self.0); let etag = format!("{:x}", hasher.finish());
let etag = format!("{:x}", hasher.finish()); if r.headers()
if r.headers() .get("If-None-Match")
.get("If-None-Match") .any(|s| s[1..s.len() - 1] == etag)
.any(|s| s[1..s.len() - 1] == etag) {
{ Response::build()
Response::build() .status(Status::NotModified)
.status(Status::NotModified) .header(Header::new("ETag", etag))
.header(Header::new("ETag", etag)) .ok()
.ok() } else {
.await Response::build()
} else { .merge(HtmlCt(self.0).respond_to(r).await.ok().unwrap())
Response::build() .header(Header::new("ETag", etag))
.merge(HtmlCt(self.0).respond_to(r).await.ok().unwrap()) .ok()
.header(Header::new("ETag", etag)) }
.ok()
.await
}
})
} }
} }