plume-models: convert admin & api-tokens to async
n.b.: I do *not* like the error handling in api_tokens 😒️
This commit is contained in:
parent
fd9764ff17
commit
909f677bdd
@ -1,38 +1,42 @@
|
|||||||
use crate::users::User;
|
use crate::users::User;
|
||||||
use rocket::{
|
use rocket::{
|
||||||
http::Status,
|
http::Status,
|
||||||
request::{self, FromRequest, Request},
|
request::{self, FromRequestAsync, 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> FromRequest<'a, 'r> for Admin {
|
impl<'a, 'r> FromRequestAsync<'a, 'r> for Admin {
|
||||||
type Error = ();
|
type Error = ();
|
||||||
|
|
||||||
fn from_request(request: &'a Request<'r>) -> request::Outcome<Admin, ()> {
|
fn from_request(request: &'a Request<'r>) -> request::FromRequestFuture<'a, Self, Self::Error> {
|
||||||
let user = request.guard::<User>()?;
|
Box::pin(async move {
|
||||||
|
let user = try_outcome!(request.guard::<User>());
|
||||||
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> FromRequest<'a, 'r> for Moderator {
|
impl<'a, 'r> FromRequestAsync<'a, 'r> for Moderator {
|
||||||
type Error = ();
|
type Error = ();
|
||||||
|
|
||||||
fn from_request(request: &'a Request<'r>) -> request::Outcome<Moderator, ()> {
|
fn from_request(request: &'a Request<'r>) -> request::FromRequestFuture<'a, Self, Self::Error> {
|
||||||
let user = request.guard::<User>()?;
|
Box::pin(async move {
|
||||||
|
let user = try_outcome!(request.guard::<User>());
|
||||||
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, ()))
|
||||||
}
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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, FromRequest, Request},
|
request::{self, FromRequestAsync, Request},
|
||||||
Outcome,
|
Outcome,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -76,34 +76,37 @@ pub enum TokenError {
|
|||||||
DbError,
|
DbError,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'r> FromRequest<'a, 'r> for ApiToken {
|
impl<'a, 'r> FromRequestAsync<'a, 'r> for ApiToken {
|
||||||
type Error = TokenError;
|
type Error = TokenError;
|
||||||
|
|
||||||
fn from_request(request: &'a Request<'r>) -> request::Outcome<ApiToken, 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();
|
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(' ');
|
||||||
let auth_type = parsed_header.next().map_or_else(
|
if let Some(auth_type) = parsed_header.next() {
|
||||||
|| Outcome::Failure((Status::BadRequest, TokenError::NoType)),
|
if let Some(val) = parsed_header.next() {
|
||||||
Outcome::Success,
|
|
||||||
)?;
|
|
||||||
let val = parsed_header.next().map_or_else(
|
|
||||||
|| Outcome::Failure((Status::BadRequest, TokenError::NoValue)),
|
|
||||||
Outcome::Success,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
if auth_type == "Bearer" {
|
if auth_type == "Bearer" {
|
||||||
let conn = request
|
if let Outcome::Success(conn) = request.guard::<DbConn>() {
|
||||||
.guard::<DbConn>()
|
|
||||||
.map_failure(|_| (Status::InternalServerError, TokenError::DbError))?;
|
|
||||||
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::BadRequest, TokenError::NoValue));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return Outcome::Failure((Status::BadRequest, TokenError::NoType));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Outcome::Forward(())
|
Outcome::Forward(())
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user