use std::cell::RefCell;
use crate::http::security::User;
tokio::task_local! {
static SECURITY_CONTEXT: RefCell<Option<User>>;
}
pub struct SecurityContext;
impl SecurityContext {
pub fn get_user() -> Option<User> {
SECURITY_CONTEXT
.try_with(|ctx| ctx.borrow().clone())
.ok()
.flatten()
}
pub fn get_username() -> Option<String> {
Self::get_user().map(|u| u.get_username().to_string())
}
pub fn is_authenticated() -> bool {
Self::get_user().is_some()
}
pub fn has_role(role: &str) -> bool {
Self::get_user().map(|u| u.has_role(role)).unwrap_or(false)
}
pub fn has_any_role(roles: &[&str]) -> bool {
Self::get_user()
.map(|u| u.has_any_role(roles))
.unwrap_or(false)
}
pub fn has_authority(authority: &str) -> bool {
Self::get_user()
.map(|u| u.has_authority(authority))
.unwrap_or(false)
}
pub fn has_any_authority(authorities: &[&str]) -> bool {
Self::get_user()
.map(|u| u.has_any_authority(authorities))
.unwrap_or(false)
}
pub async fn run_with<F, R>(user: Option<User>, f: F) -> R
where
F: std::future::Future<Output = R>,
{
SECURITY_CONTEXT.scope(RefCell::new(user), f).await
}
pub fn set_user(user: Option<User>) {
let _ = SECURITY_CONTEXT.try_with(|ctx| {
*ctx.borrow_mut() = user;
});
}
pub fn clear() {
Self::set_user(None);
}
}
pub struct SecurityContextGuard;
impl Drop for SecurityContextGuard {
fn drop(&mut self) {
SecurityContext::clear();
}
}