From 3c830ab0ced0510fb996557ba32e6be93c4d6f89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Igor=20Gali=C4=87?= Date: Fri, 15 May 2020 22:38:21 +0200 Subject: [PATCH] move towards using #[rocket::async_trait] this also upgrades some dependencies some of that fixes stuff, others breaks stuff. --- .gitignore | 1 + Cargo.lock | 79 +++++++++++++------------- Cargo.toml | 1 - plume-common/Cargo.toml | 2 +- plume-common/src/activity_pub/mod.rs | 80 ++++++++++++-------------- plume-models/src/admin.rs | 40 +++++++------ plume-models/src/api_tokens.rs | 51 +++++++++-------- plume-models/src/db_conn.rs | 17 +++--- plume-models/src/headers.rs | 3 +- plume-models/src/plume_rocket.rs | 84 +++++++++++++++------------- plume-models/src/users.rs | 23 ++++---- rust-toolchain | 2 +- src/api/authorization.rs | 4 +- src/api/mod.rs | 39 ++++++++----- src/main.rs | 2 - src/routes/errors.rs | 41 +++++++------- src/routes/mod.rs | 46 ++++++++------- src/routes/posts.rs | 2 +- src/routes/user.rs | 9 ++- src/routes/well_known.rs | 30 +++++++++- src/template_utils.rs | 49 ++++++++-------- 21 files changed, 314 insertions(+), 291 deletions(-) diff --git a/.gitignore b/.gitignore index d8d6fd27..172aeb0b 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,4 @@ tags.* search_index .buildconfig __pycache__ +.vscode/ diff --git a/Cargo.lock b/Cargo.lock index 783e5c71..742772d8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6,7 +6,7 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5bfd311e7b4102971757a2a6f143a93b1a8e6b5afc2c46936af827fd9eab403f" dependencies = [ - "activitystreams-derive", + "activitystreams-derive 0.1.1", "activitystreams-traits", "activitystreams-types", "serde", @@ -25,6 +25,17 @@ dependencies = [ "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]] name = "activitystreams-traits" version = "0.1.0" @@ -42,7 +53,7 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff74c5765278614a009f97b9ec12f9a7c732bbcc5e0337fcfcab619b784860ec" dependencies = [ - "activitystreams-derive", + "activitystreams-derive 0.1.1", "activitystreams-traits", "chrono", "mime 0.3.16", @@ -142,7 +153,7 @@ checksum = "da71fef07bc806586090247e971229289f64c210a278ee5ae419314eb386b31d" dependencies = [ "proc-macro2 1.0.12", "quote 1.0.4", - "syn 1.0.18", + "syn 1.0.19", ] [[package]] @@ -746,7 +757,7 @@ dependencies = [ "bitflags 1.2.1", "proc-macro2 1.0.12", "quote 1.0.4", - "syn 1.0.18", + "syn 1.0.19", ] [[package]] @@ -784,7 +795,7 @@ checksum = "45f5098f628d02a7a0f68ddba586fb61e80edec3bdc1be3b921f4ceec60858d3" dependencies = [ "proc-macro2 1.0.12", "quote 1.0.4", - "syn 1.0.18", + "syn 1.0.19", ] [[package]] @@ -978,7 +989,7 @@ checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" dependencies = [ "proc-macro2 1.0.12", "quote 1.0.4", - "syn 1.0.18", + "syn 1.0.19", "synstructure", ] @@ -993,9 +1004,9 @@ dependencies = [ [[package]] name = "filetime" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f59efc38004c988e4201d11d263b8171f49a2e7ec0bdbb71773433f271504a5e" +checksum = "affc17579b132fc2461adf7c575cc6e8b134ebca52c51f5411388965227dc695" dependencies = [ "cfg-if", "libc", @@ -1179,7 +1190,7 @@ dependencies = [ "proc-macro-hack 0.5.15", "proc-macro2 1.0.12", "quote 1.0.4", - "syn 1.0.18", + "syn 1.0.19", ] [[package]] @@ -1829,7 +1840,7 @@ dependencies = [ "migrations_internals", "proc-macro2 1.0.12", "quote 1.0.4", - "syn 1.0.18", + "syn 1.0.19", ] [[package]] @@ -2171,9 +2182,9 @@ checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" [[package]] name = "openssl-sys" -version = "0.9.55" +version = "0.9.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7717097d810a0f2e2323f9e5d11e71608355e24828410b55b9d4f18aa5f9a5d8" +checksum = "f02309a7f127000ed50594f0b50ecc69e7c654e16d41b4e8156d1b3df8e0b52e" dependencies = [ "autocfg 1.0.0", "cc", @@ -2354,29 +2365,29 @@ dependencies = [ [[package]] name = "pin-project" -version = "0.4.10" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36e3dcd42688c05a66f841d22c5d8390d9a5d4c9aaf57b9285eae4900a080063" +checksum = "82c3bfbfb5bb42f99498c7234bbd768c220eb0cea6818259d0d18a1aa3d2595d" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "0.4.10" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4d7346ac577ff1296e06a418e7618e22655bae834d4970cb6e39d6da8119969" +checksum = "ccbf6449dcfb18562c015526b085b8df1aa3cdab180af8ec2ebd300a3bd28f63" dependencies = [ "proc-macro2 1.0.12", "quote 1.0.4", - "syn 1.0.18", + "syn 1.0.19", ] [[package]] name = "pin-project-lite" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "237844750cfbb86f67afe27eee600dfbbcb6188d734139b534cbfbf4f96792ae" +checksum = "f7505eeebd78492e0f6108f7171c4948dbb120ee8119d9d77d0afa5469bef67f" [[package]] name = "pin-utils" @@ -2435,7 +2446,6 @@ dependencies = [ "rpassword", "rsass", "ructe", - "runtime-fmt", "scheduled-thread-pool", "serde", "serde_json", @@ -2472,7 +2482,7 @@ name = "plume-common" version = "0.4.0" dependencies = [ "activitypub", - "activitystreams-derive", + "activitystreams-derive 0.2.0", "activitystreams-traits", "array_tool", "base64 0.10.1", @@ -3066,7 +3076,7 @@ dependencies = [ [[package]] name = "rocket_i18n" 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 = [ "gettext 0.4.0", "rocket", @@ -3108,15 +3118,6 @@ dependencies = [ "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]] name = "rust-stemmers" version = "1.2.0" @@ -3266,7 +3267,7 @@ checksum = "9e549e3abf4fb8621bd1609f11dfc9f5e50320802273b12f3811a67e6716ea6c" dependencies = [ "proc-macro2 1.0.12", "quote 1.0.4", - "syn 1.0.18", + "syn 1.0.19", ] [[package]] @@ -3326,7 +3327,7 @@ dependencies = [ "itertools", "proc-macro2 1.0.12", "quote 1.0.4", - "syn 1.0.18", + "syn 1.0.19", ] [[package]] @@ -3339,7 +3340,7 @@ dependencies = [ "itertools", "proc-macro2 1.0.12", "quote 1.0.4", - "syn 1.0.18", + "syn 1.0.19", ] [[package]] @@ -3561,9 +3562,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.18" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "410a7488c0a728c7ceb4ad59b9567eb4053d02e8cc7f5c0e0eeeb39518369213" +checksum = "e8e5aa70697bb26ee62214ae3288465ecec0000f05182f039b477001f08f5ae7" dependencies = [ "proc-macro2 1.0.12", "quote 1.0.4", @@ -3587,7 +3588,7 @@ checksum = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545" dependencies = [ "proc-macro2 1.0.12", "quote 1.0.4", - "syn 1.0.18", + "syn 1.0.19", "unicode-xid 0.2.0", ] @@ -4069,7 +4070,7 @@ dependencies = [ "log 0.4.8", "proc-macro2 1.0.12", "quote 1.0.4", - "syn 1.0.18", + "syn 1.0.19", "wasm-bindgen-shared", ] @@ -4103,7 +4104,7 @@ checksum = "8eb197bd3a47553334907ffd2f16507b4f4f01bbec3ac921a7719e0decdfe72a" dependencies = [ "proc-macro2 1.0.12", "quote 1.0.4", - "syn 1.0.18", + "syn 1.0.19", "wasm-bindgen-backend", "wasm-bindgen-shared", ] diff --git a/Cargo.toml b/Cargo.toml index 460db7e1..894d9672 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,6 @@ num_cpus = "1.10" rocket = { git = "https://github.com/SergioBenitez/Rocket", rev = "async" } rocket_contrib = { git = "https://github.com/SergioBenitez/Rocket", rev = "async" , features = ["json"] } rpassword = "4.0" -runtime-fmt = "0.4.0" scheduled-thread-pool = "0.2.2" serde = "1.0" serde_json = "1.0" diff --git a/plume-common/Cargo.toml b/plume-common/Cargo.toml index d5b5f765..7ee4cfca 100644 --- a/plume-common/Cargo.toml +++ b/plume-common/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" [dependencies] activitypub = "0.1.1" -activitystreams-derive = "0.1.1" +activitystreams-derive = "0.2" activitystreams-traits = "0.1.0" array_tool = "1.0" base64 = "0.10" diff --git a/plume-common/src/activity_pub/mod.rs b/plume-common/src/activity_pub/mod.rs index 6efb3869..cb9d19db 100644 --- a/plume-common/src/activity_pub/mod.rs +++ b/plume-common/src/activity_pub/mod.rs @@ -3,8 +3,8 @@ use array_tool::vec::Uniq; use reqwest::ClientBuilder; use rocket::{ http::Status, - request::{FromRequestAsync, FromRequestFuture, Request}, - response::{Responder, Response, ResultFuture}, + request::{FromRequest, Request}, + response::{Responder, Response, Result}, Outcome, }; use serde_json; @@ -61,42 +61,36 @@ impl ActivityStream { ActivityStream(t) } } - +#[rocket::async_trait] impl<'r, O: Object + Send + 'r> Responder<'r> for ActivityStream { - fn respond_to(self, request: &'r Request<'_>) -> ResultFuture<'r> { - Box::pin(async move { - let mut json = - serde_json::to_value(&self.0).map_err(|_| Status::InternalServerError)?; - json["@context"] = context(); - let result = serde_json::to_string(&json).map_err(rocket::response::Debug); - match result.respond_to(request).await { - Ok(r) => { - Response::build_from(r) - .raw_header("Content-Type", "application/activity+json") - .ok() - .await - } - Err(e) => Err(e), - } - }) + async fn respond_to(self, request: &'r Request<'_>) -> Result<'r> { + let mut json = serde_json::to_value(&self.0).map_err(|_| Status::InternalServerError)?; + json["@context"] = context(); + let result = serde_json::to_string(&json).map_err(rocket::response::Debug); + match result.respond_to(request).await { + Ok(r) => Response::build_from(r) + .raw_header("Content-Type", "application/activity+json") + .ok(), + Err(e) => Err(e), + } } } #[derive(Clone)] pub struct ApRequest; -impl<'a, 'r> FromRequestAsync<'a, 'r> for ApRequest { +#[rocket::async_trait] +impl<'a, 'r> FromRequest<'a, 'r> for ApRequest { type Error = (); - fn from_request(request: &'a Request<'r>) -> FromRequestFuture<'a, Self, Self::Error> { - Box::pin(async move { - request - .headers() - .get_one("Accept") - .map(|header| { - header - .split(',') - .map(|ct| { - match ct.trim() { + async fn from_request(request: &'a Request<'r>) -> Outcome { + request + .headers() + .get_one("Accept") + .map(|header| { + header + .split(',') + .map(|ct| { + match ct.trim() { // bool for Forward: true if found a valid Content-Type for Plume first (HTML), // false otherwise "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), _ => Outcome::Forward(false), } - }) - .fold(Outcome::Forward(false), |out, ct| { - if out.clone().forwarded().unwrap_or_else(|| out.is_success()) { - out - } else { - ct - } - }) - .map_forward(|_| ()) - }) - .unwrap_or(Outcome::Forward(())) - }) + }) + .fold(Outcome::Forward(false), |out, ct| { + if out.clone().forwarded().unwrap_or_else(|| out.is_success()) { + out + } else { + ct + } + }) + .map_forward(|_| ()) + }) + .unwrap_or(Outcome::Forward(())) } } pub fn broadcast(sender: &S, act: A, to: Vec) @@ -217,8 +210,7 @@ pub struct PublicKey { pub public_key_pem: Option, } -#[derive(Clone, Debug, Default, UnitString)] -#[activitystreams(Hashtag)] +#[derive(Clone, Debug, Default, Deserialize, Serialize)] pub struct HashtagType; #[derive(Clone, Debug, Default, Deserialize, Serialize, Properties)] diff --git a/plume-models/src/admin.rs b/plume-models/src/admin.rs index 1dd810a9..1062434f 100644 --- a/plume-models/src/admin.rs +++ b/plume-models/src/admin.rs @@ -1,42 +1,40 @@ use crate::users::User; use rocket::{ http::Status, - request::{self, FromRequestAsync, Request}, + request::{self, FromRequest, Request}, Outcome, }; /// Wrapper around User to use as a request guard on pages reserved to admins. 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 = (); - fn from_request(request: &'a Request<'r>) -> request::FromRequestFuture<'a, Self, Self::Error> { - Box::pin(async move { - let user = try_outcome!(User::from_request(request).await); - if user.is_admin() { - Outcome::Success(Admin(user)) - } else { - Outcome::Failure((Status::Unauthorized, ())) - } - }) + async fn from_request(request: &'a Request<'r>) -> request::Outcome { + let user = try_outcome!(User::from_request(request).await); + if user.is_admin() { + Outcome::Success(Admin(user)) + } else { + Outcome::Failure((Status::Unauthorized, ())) + } } } /// Same as `Admin` but for moderators. 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 = (); - fn from_request(request: &'a Request<'r>) -> request::FromRequestFuture<'a, Self, Self::Error> { - Box::pin(async move { - let user = try_outcome!(User::from_request(request).await); - if user.is_moderator() { - Outcome::Success(Moderator(user)) - } else { - Outcome::Failure((Status::Unauthorized, ())) - } - }) + async fn from_request(request: &'a Request<'r>) -> request::Outcome { + let user = try_outcome!(User::from_request(request).await); + if user.is_moderator() { + Outcome::Success(Moderator(user)) + } else { + Outcome::Failure((Status::Unauthorized, ())) + } } } diff --git a/plume-models/src/api_tokens.rs b/plume-models/src/api_tokens.rs index 84aefbf8..1a7002e3 100644 --- a/plume-models/src/api_tokens.rs +++ b/plume-models/src/api_tokens.rs @@ -3,7 +3,7 @@ use chrono::NaiveDateTime; use diesel::{self, ExpressionMethods, QueryDsl, RunQueryDsl}; use rocket::{ http::Status, - request::{self, FromRequestAsync, Request}, + request::{self, FromRequest, Request}, Outcome, }; @@ -76,39 +76,38 @@ pub enum TokenError { DbError, } -impl<'a, 'r> FromRequestAsync<'a, 'r> for ApiToken { +#[rocket::async_trait] +impl<'a, 'r> FromRequest<'a, 'r> for ApiToken { type Error = TokenError; - fn from_request(request: &'a Request<'r>) -> request::FromRequestFuture<'a, Self, Self::Error> { - Box::pin(async move { - let headers: Vec<_> = request.headers().get("Authorization").collect(); - if headers.len() != 1 { - return Outcome::Failure((Status::BadRequest, TokenError::NoHeader)); - } + async fn from_request(request: &'a Request<'r>) -> request::Outcome { + let headers: Vec<_> = request.headers().get("Authorization").collect(); + if headers.len() != 1 { + return Outcome::Failure((Status::BadRequest, TokenError::NoHeader)); + } - let mut parsed_header = headers[0].split(' '); - if let Some(auth_type) = parsed_header.next() { - if let Some(val) = parsed_header.next() { - if auth_type == "Bearer" { - if let Outcome::Success(conn) = DbConn::from_request(request).await { - if let Ok(token) = ApiToken::find_by_value(&*conn, val) { - return Outcome::Success(token); - } - } else { - return Outcome::Failure(( - Status::InternalServerError, - TokenError::DbError, - )); + let mut parsed_header = headers[0].split(' '); + if let Some(auth_type) = parsed_header.next() { + if let Some(val) = parsed_header.next() { + if auth_type == "Bearer" { + if let Outcome::Success(conn) = DbConn::from_request(request).await { + if let Ok(token) = ApiToken::find_by_value(&*conn, val) { + return Outcome::Success(token); } + } else { + return Outcome::Failure(( + Status::InternalServerError, + TokenError::DbError, + )); } - } else { - return Outcome::Failure((Status::BadRequest, TokenError::NoValue)); } } 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(()) } } diff --git a/plume-models/src/db_conn.rs b/plume-models/src/db_conn.rs index a44f5ecb..2eceda88 100644 --- a/plume-models/src/db_conn.rs +++ b/plume-models/src/db_conn.rs @@ -6,7 +6,7 @@ use diesel::r2d2::{ use diesel::{dsl::sql_query, ConnectionError, RunQueryDsl}; use rocket::{ http::Status, - request::{self, FromRequestAsync}, + request::{self, FromRequest}, Outcome, Request, }; use std::ops::Deref; @@ -21,16 +21,15 @@ pub struct DbConn(pub PooledConnection>); /// Attempts to retrieve a single connection from the managed database pool. If /// no pool is currently managed, fails with an `InternalServerError` status. If /// 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 = (); - fn from_request(request: &'a Request<'r>) -> request::FromRequestFuture<'a, Self, Self::Error> { - Box::pin(async move { - match DbConn::from_request(request).await { - Outcome::Success(a) => return Outcome::Success(a), - _ => return Outcome::Failure((Status::ServiceUnavailable, ())), - }; - }) + async fn from_request(request: &'a Request<'r>) -> request::Outcome { + match DbConn::from_request(request).await { + Outcome::Success(a) => return Outcome::Success(a), + _ => return Outcome::Failure((Status::ServiceUnavailable, ())), + }; } } diff --git a/plume-models/src/headers.rs b/plume-models/src/headers.rs index 0d5d2923..7f43ddd6 100644 --- a/plume-models/src/headers.rs +++ b/plume-models/src/headers.rs @@ -6,10 +6,11 @@ use rocket::{ pub struct Headers<'r>(pub HeaderMap<'r>); +#[rocket::async_trait] impl<'a, 'r> FromRequest<'a, 'r> for Headers<'r> { type Error = (); - fn from_request(request: &'a Request<'r>) -> request::Outcome { + async fn from_request(request: &'a Request<'r>) -> request::Outcome { let mut headers = HeaderMap::new(); for header in request.headers().clone().into_iter() { headers.add(header); diff --git a/plume-models/src/plume_rocket.rs b/plume-models/src/plume_rocket.rs index 5be466e7..749897bc 100644 --- a/plume-models/src/plume_rocket.rs +++ b/plume-models/src/plume_rocket.rs @@ -4,7 +4,7 @@ pub use self::module::PlumeRocket; mod module { use crate::{db_conn::DbConn, search, users}; use rocket::{ - request::{self, FlashMessage, FromRequestAsync, Request}, + request::{self, FlashMessage, FromRequest, Request}, Outcome, State, }; use scheduled_thread_pool::ScheduledThreadPool; @@ -20,29 +20,38 @@ mod module { 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 = (); - fn from_request( - request: &'a Request<'r>, - ) -> request::FromRequestFuture<'a, Self, Self::Error> { - Box::pin(async move { - let conn = try_outcome!(DbConn::from_request(request).await); - let intl = try_outcome!(rocket_i18n::I18n::from_request(request).await); - let user = try_outcome!(users::User::from_request(request).await); - let worker = - try_outcome!(request.guard::<'_, State<'_, Arc>>()); - let searcher = - try_outcome!(request.guard::<'_, State<'_, Arc>>()); - let flash_msg = request.guard::>().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(), - }) + async fn from_request(request: &'a Request<'r>) -> request::Outcome { + let conn = DbConn::from_request(request).await.succeeded().unwrap(); + let intl = rocket_i18n::I18n::from_request(request) + .await + .succeeded() + .unwrap(); + let user = users::User::from_request(request) + .await + .succeeded() + .unwrap(); + let worker = request + .guard::>>() + .await + .succeeded() + .unwrap(); + let searcher = request + .guard::>>() + .await + .succeeded() + .unwrap(); + let flash_msg = request.guard::>().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 { use crate::{db_conn::DbConn, search, users}; use rocket::{ - request::{self, FromRequestAsync, Request}, + request::{self, FromRequest, Request}, Outcome, State, }; use scheduled_thread_pool::ScheduledThreadPool; @@ -66,25 +75,20 @@ mod module { pub worker: Arc, } - impl<'a, 'r> FromRequestAsync<'a, 'r> for PlumeRocket { + #[rocket::async_trait] + impl<'a, 'r> FromRequest<'a, 'r> for PlumeRocket { type Error = (); - fn from_request( - request: &'a Request<'r>, - ) -> request::FromRequestFuture<'a, Self, Self::Error> { - Box::pin(async move { - let conn = try_outcome!(DbConn::from_request(request).await); - let user = try_outcome!(users::User::from_request(request).await); - let worker = - try_outcome!(request.guard::<'_, State<'_, Arc>>()); - let searcher = - try_outcome!(request.guard::<'_, State<'_, Arc>>()); - Outcome::Success(PlumeRocket { - conn, - user: Some(user), - worker: worker.clone(), - searcher: searcher.clone(), - }) + async fn from_request(request: &'a Request<'r>) -> request::Outcome { + let conn = try_outcome!(DbConn::from_request(request).await); + let user = try_outcome!(users::User::from_request(request).await); + let worker = try_outcome!(request.guard::<'_, State<'_, Arc>>()); + let searcher = try_outcome!(request.guard::<'_, State<'_, Arc>>()); + Outcome::Success(PlumeRocket { + conn, + user: Some(user), + worker: worker.clone(), + searcher: searcher.clone(), }) } } diff --git a/plume-models/src/users.rs b/plume-models/src/users.rs index 2a68b712..6f67a809 100644 --- a/plume-models/src/users.rs +++ b/plume-models/src/users.rs @@ -35,7 +35,7 @@ use reqwest::{ }; use rocket::{ outcome::IntoOutcome, - request::{self, FromRequestAsync, Request}, + request::{self, FromRequest, Request}, }; use serde_json; 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 = (); - fn from_request(request: &'a Request<'r>) -> request::FromRequestFuture<'a, Self, Self::Error> { - Box::pin(async move { - let conn = try_outcome!(DbConn::from_request(request).await); - request - .cookies() - .get_private(AUTH_COOKIE) - .and_then(|cookie| cookie.value().parse().ok()) - .and_then(|id| User::get(&*conn, id).ok()) - .or_forward(()) - }) + async fn from_request(request: &'a Request<'r>) -> request::Outcome { + let conn = try_outcome!(DbConn::from_request(request).await); + request + .cookies() + .get_private(AUTH_COOKIE) + .and_then(|cookie| cookie.value().parse().ok()) + .and_then(|id| User::get(&*conn, id).ok()) + .or_forward(()) } } diff --git a/rust-toolchain b/rust-toolchain index b54a6029..2cc138d9 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1 +1 @@ -nightly-2020-01-15 +nightly-2020-05-05 diff --git a/src/api/authorization.rs b/src/api/authorization.rs index 8a23ada5..3f610993 100644 --- a/src/api/authorization.rs +++ b/src/api/authorization.rs @@ -35,6 +35,7 @@ impl Scope for plume_models::posts::Post { pub struct Authorization(pub ApiToken, PhantomData<(A, S)>); +#[rocket::async_trait] impl<'a, 'r, A, S> FromRequest<'a, 'r> for Authorization where A: Action, @@ -42,9 +43,10 @@ where { type Error = (); - fn from_request(request: &'a Request<'r>) -> request::Outcome, ()> { + async fn from_request(request: &'a Request<'r>) -> request::Outcome, ()> { request .guard::() + .await .map_failure(|_| (Status::Unauthorized, ())) .and_then(|token| { if token.can(A::to_str(), S::to_str()) { diff --git a/src/api/mod.rs b/src/api/mod.rs index 2a53b19a..6e622e22 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -2,6 +2,7 @@ use rocket::{ request::{Form, Request}, response::{self, Responder}, + Outcome, }; use rocket_contrib::json::Json; use serde_json; @@ -26,21 +27,31 @@ impl From for ApiError { } } +#[rocket::async_trait] 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 { - Error::NotFound => Json(json!({ - "error": "Not found" - })) - .respond_to(req), - Error::Unauthorized => Json(json!({ - "error": "You are not authorized to access this resource" - })) - .respond_to(req), - _ => Json(json!({ - "error": "Server error" - })) - .respond_to(req), + Error::NotFound => { + Json(json!({ + "error": "Not found" + })) + .respond_to(req) + .await + } + Error::Unauthorized => { + Json(json!({ + "error": "You are not authorized to access this resource" + })) + .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 app = App::find_by_client_id(conn, &query.client_id)?; 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) { let token = ApiToken::insert( conn, diff --git a/src/main.rs b/src/main.rs index 27b1282b..11f18c3e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,8 +6,6 @@ extern crate gettext_macros; #[macro_use] extern crate rocket; #[macro_use] -extern crate runtime_fmt; -#[macro_use] extern crate serde_json; #[macro_use] extern crate validator_derive; diff --git a/src/routes/errors.rs b/src/routes/errors.rs index 904d1fd7..02d6883b 100644 --- a/src/routes/errors.rs +++ b/src/routes/errors.rs @@ -1,7 +1,7 @@ use crate::template_utils::{IntoContext, Ructe}; use plume_models::{Error, PlumeRocket}; use rocket::{ - request::FromRequestAsync, + request::FromRequest, response::{self, Responder}, Request, }; @@ -15,29 +15,28 @@ impl From for ErrorPage { } } +#[rocket::async_trait] impl<'r> Responder<'r> for ErrorPage { - fn respond_to(self, req: &'r Request<'_>) -> response::ResultFuture<'r> { - Box::pin(async move { - let rockets = PlumeRocket::from_request(req).await.unwrap(); + async fn respond_to(self, req: &'r Request<'_>) -> response::Result<'r> { + let rockets = PlumeRocket::from_request(req).await.unwrap(); - match self.0 { - Error::NotFound => { - 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 - } + match self.0 { + Error::NotFound => { + 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 + } + } } } diff --git a/src/routes/mod.rs b/src/routes/mod.rs index 27c8d2b2..a142a2ae 100755 --- a/src/routes/mod.rs +++ b/src/routes/mod.rs @@ -94,10 +94,11 @@ impl Page { #[derive(Shrinkwrap)] pub struct ContentLen(pub u64); +#[rocket::async_trait] impl<'a, 'r> FromRequest<'a, 'r> for ContentLen { type Error = (); - fn from_request(r: &'a Request<'r>) -> request::Outcome { + async fn from_request(r: &'a Request<'r>) -> request::Outcome { match r.limits().get("forms") { Some(l) => Outcome::Success(ContentLen(l)), None => Outcome::Failure((Status::InternalServerError, ())), @@ -213,32 +214,29 @@ pub struct CachedFile { #[derive(Debug)] pub struct ThemeFile(NamedFile); +#[rocket::async_trait] impl<'r> Responder<'r> for ThemeFile { - fn respond_to(self, r: &'r Request<'_>) -> response::ResultFuture<'r> { - Box::pin(async move { - let contents = std::fs::read(self.0.path()).map_err(|_| Status::InternalServerError)?; + async fn respond_to(self, r: &'r Request<'_>) -> response::Result<'r> { + let contents = std::fs::read(self.0.path()).map_err(|_| Status::InternalServerError)?; - let mut hasher = DefaultHasher::new(); - hasher.write(&contents); - let etag = format!("{:x}", hasher.finish()); + let mut hasher = DefaultHasher::new(); + hasher.write(&contents); + let etag = format!("{:x}", hasher.finish()); - if r.headers() - .get("If-None-Match") - .any(|s| s[1..s.len() - 1] == etag) - { - Response::build() - .status(Status::NotModified) - .header(Header::new("ETag", etag)) - .ok() - .await - } else { - Response::build() - .merge(self.0.respond_to(r).await.ok().unwrap()) - .header(Header::new("ETag", etag)) - .ok() - .await - } - }) + if r.headers() + .get("If-None-Match") + .any(|s| s[1..s.len() - 1] == etag) + { + Response::build() + .status(Status::NotModified) + .header(Header::new("ETag", etag)) + .ok() + } else { + Response::build() + .merge(self.0.respond_to(r).await.ok().unwrap()) + .header(Header::new("ETag", etag)) + .ok() + } } } diff --git a/src/routes/posts.rs b/src/routes/posts.rs index 9b295b2f..134fb827 100644 --- a/src/routes/posts.rs +++ b/src/routes/posts.rs @@ -643,7 +643,7 @@ pub fn remote_interact_post( .and_then(|blog| Post::find_by_slug(&rockets.conn, &slug, blog.id))?; if let Some(uri) = User::fetch_remote_interact_uri(&remote.remote) .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()) } else { diff --git a/src/routes/user.rs b/src/routes/user.rs index e0bfd783..e024d7e4 100644 --- a/src/routes/user.rs +++ b/src/routes/user.rs @@ -201,15 +201,14 @@ pub fn follow_not_connected( if let Some(uri) = User::fetch_remote_interact_uri(&remote_form) .ok() .and_then(|uri| { - rt_format!( - uri, - uri = format!( + uri.replace( + "{uri}", + format!( "{}@{}", target.fqn, target.get_instance(&rockets.conn).ok()?.public_domain - ) + ), ) - .ok() }) { Ok(Redirect::to(uri).into()) diff --git a/src/routes/well_known.rs b/src/routes/well_known.rs index 723ec1e0..80aa0916 100644 --- a/src/routes/well_known.rs +++ b/src/routes/well_known.rs @@ -44,21 +44,47 @@ pub fn host_meta() -> String { struct WebfingerResolver; impl Resolver for WebfingerResolver { - fn instance_domain<'a>() -> &'a str { + fn instance_domain<'a>(&self) -> &'a str { CONFIG.base_url.as_str() } - fn find(prefix: Prefix, acct: String, ctx: PlumeRocket) -> Result { + fn find( + &self, + prefix: Prefix, + acct: String, + ctx: PlumeRocket, + ) -> Result { match prefix { Prefix::Acct => User::find_by_fqn(&ctx, &acct) + .await .and_then(|usr| usr.webfinger(&*ctx.conn)) .or(Err(ResolverError::NotFound)), Prefix::Group => Blog::find_by_fqn(&ctx, &acct) + .await .and_then(|blog| blog.webfinger(&*ctx.conn)) .or(Err(ResolverError::NotFound)), Prefix::Custom(_) => Err(ResolverError::NotFound), } } + fn endpoint( + &self, + resource: impl Into, + resource_repo: PlumeRocket, + ) -> Result { + 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?")] diff --git a/src/template_utils.rs b/src/template_utils.rs index 157f2fd4..8d630588 100644 --- a/src/template_utils.rs +++ b/src/template_utils.rs @@ -51,33 +51,30 @@ impl IntoContext for PlumeRocket { #[derive(Debug)] pub struct Ructe(pub Vec); +#[rocket::async_trait] impl<'r> Responder<'r> for Ructe { - fn respond_to(self, r: &'r Request) -> response::ResultFuture<'r> { - Box::pin(async move { - //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"
) -> response::Result<'r> { + //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"