#![warn(missing_docs)]
use rocket::http::Status;
use rocket::request::{FromRequest, Outcome};
use rocket::Request;
use std::collections::HashSet;
pub struct ApiToken {
tokens: HashSet<String>,
enabled: bool,
}
impl ApiToken {
pub fn new(tokens: Vec<String>, enabled: bool) -> Self {
Self {
tokens: tokens
.into_iter()
.map(|token| format!("Bearer {}", token))
.collect(),
enabled,
}
}
pub fn add_bearer(&mut self, token: &str) {
self.tokens.insert(format!("Bearer {}", token));
}
}
#[derive(Debug)]
pub struct Authorized;
#[rocket::async_trait]
impl<'r> FromRequest<'r> for Authorized {
type Error = &'static str;
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {
let token = request
.rocket()
.state::<ApiToken>()
.expect("Token state not available.");
if !token.enabled {
return Outcome::Success(Authorized);
}
match request.headers().get_one("Authorization") {
Some(value) => {
if token.tokens.contains(value) {
Outcome::Success(Authorized)
} else {
Outcome::Error((Status::Unauthorized, "invalid token"))
}
}
_ => Outcome::Error((Status::Unauthorized, "Authorization header not found")),
}
}
}