use std::future::{ready, Ready};
use std::ops::Deref;
use actix_web::dev::Payload;
use actix_web::{FromRequest, HttpMessage, HttpRequest};
use crate::http::error::AuthError;
use crate::http::security::User;
#[derive(Debug, Clone)]
pub struct AuthenticatedUser(User);
impl AuthenticatedUser {
pub fn new(user: User) -> Self {
AuthenticatedUser(user)
}
pub fn into_inner(self) -> User {
self.0
}
}
impl Deref for AuthenticatedUser {
type Target = User;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl FromRequest for AuthenticatedUser {
type Error = AuthError;
type Future = Ready<Result<Self, Self::Error>>;
fn from_request(req: &HttpRequest, _payload: &mut Payload) -> Self::Future {
match req.extensions().get::<User>().cloned() {
Some(user) => ready(Ok(AuthenticatedUser(user))),
None => ready(Err(AuthError::Unauthorized)),
}
}
}
#[derive(Debug, Clone)]
pub struct OptionalUser(Option<User>);
impl OptionalUser {
pub fn into_inner(self) -> Option<User> {
self.0
}
pub fn is_authenticated(&self) -> bool {
self.0.is_some()
}
}
impl Deref for OptionalUser {
type Target = Option<User>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl FromRequest for OptionalUser {
type Error = actix_web::Error;
type Future = Ready<Result<Self, Self::Error>>;
fn from_request(req: &HttpRequest, _payload: &mut Payload) -> Self::Future {
let user = req.extensions().get::<User>().cloned();
ready(Ok(OptionalUser(user)))
}
}
pub trait SecurityExt {
fn get_user(&self) -> Option<User>;
fn is_authenticated(&self) -> bool;
fn has_role(&self, role: &str) -> bool;
fn has_any_role(&self, roles: &[&str]) -> bool;
fn has_authority(&self, authority: &str) -> bool;
fn has_any_authority(&self, authorities: &[&str]) -> bool;
}
impl SecurityExt for HttpRequest {
fn get_user(&self) -> Option<User> {
self.extensions().get::<User>().cloned()
}
fn is_authenticated(&self) -> bool {
self.extensions().get::<User>().is_some()
}
fn has_role(&self, role: &str) -> bool {
self.extensions()
.get::<User>()
.is_some_and(|u| u.has_role(role))
}
fn has_any_role(&self, roles: &[&str]) -> bool {
self.extensions()
.get::<User>()
.is_some_and(|u| u.has_any_role(roles))
}
fn has_authority(&self, authority: &str) -> bool {
self.extensions()
.get::<User>()
.is_some_and(|u| u.has_authority(authority))
}
fn has_any_authority(&self, authorities: &[&str]) -> bool {
self.extensions()
.get::<User>()
.is_some_and(|u| u.has_any_authority(authorities))
}
}