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
21 changed files with 314 additions and 291 deletions
+3 -1
View File
@@ -35,6 +35,7 @@ impl Scope for plume_models::posts::Post {
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>
where
A: Action,
@@ -42,9 +43,10 @@ where
{
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
.guard::<ApiToken>()
.await
.map_failure(|_| (Status::Unauthorized, ()))
.and_then(|token| {
if token.can(A::to_str(), S::to_str()) {
+25 -14
View File
@@ -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<std::option::NoneError> 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,
-2
View File
@@ -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;
+20 -21
View File
@@ -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<Error> 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
}
}
}
}
+22 -24
View File
@@ -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<Self, Self::Error> {
async fn from_request(r: &'a Request<'r>) -> request::Outcome<Self, Self::Error> {
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()
}
}
}
+1 -1
View File
@@ -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 {
+4 -5
View File
@@ -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())
+28 -2
View File
@@ -44,21 +44,47 @@ pub fn host_meta() -> String {
struct WebfingerResolver;
impl Resolver<PlumeRocket> 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<Webfinger, ResolverError> {
fn find(
&self,
prefix: Prefix,
acct: String,
ctx: PlumeRocket,
) -> Result<Webfinger, ResolverError> {
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<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>")]
+23 -26
View File
@@ -51,33 +51,30 @@ impl IntoContext for PlumeRocket {
#[derive(Debug)]
pub struct Ructe(pub Vec<u8>);
#[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"<form ") {
return HtmlCt(self.0).respond_to(r).await;
}
let mut hasher = DefaultHasher::new();
hasher.write(&self.0);
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(HtmlCt(self.0).respond_to(r).await.ok().unwrap())
.header(Header::new("ETag", etag))
.ok()
.await
}
})
async fn respond_to(self, r: &'r Request<'_>) -> 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"<form ") {
return HtmlCt(self.0).respond_to(r).await;
}
let mut hasher = DefaultHasher::new();
hasher.write(&self.0);
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()
} else {
Response::build()
.merge(HtmlCt(self.0).respond_to(r).await.ok().unwrap())
.header(Header::new("ETag", etag))
.ok()
}
}
}