src/config/cached_user_info.rs: cache it up to 5 seconds
This commit is contained in:
parent
365f0f720c
commit
6e695960ca
|
@ -1,10 +1,11 @@
|
|||
//! Cached user info for fast ACL permission checks
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::sync::{RwLock, Arc};
|
||||
|
||||
use anyhow::{Error, bail};
|
||||
|
||||
use proxmox::api::section_config::SectionConfigData;
|
||||
use lazy_static::lazy_static;
|
||||
use proxmox::api::UserInformation;
|
||||
|
||||
use super::acl::{AclTree, ROLE_NAMES};
|
||||
|
@ -16,14 +17,43 @@ pub struct CachedUserInfo {
|
|||
acl_tree: Arc<AclTree>,
|
||||
}
|
||||
|
||||
fn now() -> i64 { unsafe { libc::time(std::ptr::null_mut()) } }
|
||||
|
||||
struct ConfigCache {
|
||||
data: Option<Arc<CachedUserInfo>>,
|
||||
last_update: i64,
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
static ref CACHED_CONFIG: RwLock<ConfigCache> = RwLock::new(
|
||||
ConfigCache { data: None, last_update: 0 }
|
||||
);
|
||||
}
|
||||
|
||||
impl CachedUserInfo {
|
||||
|
||||
/// Creates a new instance.
|
||||
pub fn new() -> Result<Self, Error> {
|
||||
Ok(CachedUserInfo {
|
||||
/// Returns a cached instance (up to 5 seconds old).
|
||||
pub fn new() -> Result<Arc<Self>, Error> {
|
||||
let now = now();
|
||||
{ // limit scope
|
||||
let cache = CACHED_CONFIG.read().unwrap();
|
||||
if (now - cache.last_update) < 5 {
|
||||
if let Some(ref config) = cache.data {
|
||||
return Ok(config.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let config = Arc::new(CachedUserInfo {
|
||||
user_cfg: super::user::cached_config()?,
|
||||
acl_tree: super::acl::cached_config()?,
|
||||
})
|
||||
});
|
||||
|
||||
let mut cache = CACHED_CONFIG.write().unwrap();
|
||||
cache.last_update = now;
|
||||
cache.data = Some(config.clone());
|
||||
|
||||
Ok(config)
|
||||
}
|
||||
|
||||
/// Test if a user account is enabled and not expired
|
||||
|
@ -34,8 +64,7 @@ impl CachedUserInfo {
|
|||
}
|
||||
if let Some(expire) = info.expire {
|
||||
if expire > 0 {
|
||||
let now = unsafe { libc::time(std::ptr::null_mut()) };
|
||||
if expire <= now {
|
||||
if expire <= now() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -562,7 +562,7 @@ pub async fn handle_request(api: Arc<ApiConfig>, req: Request<Body>) -> Result<R
|
|||
}
|
||||
Some(api_method) => {
|
||||
let user = rpcenv.get_user();
|
||||
if !check_api_permission(api_method.access.permission, user.as_deref(), &uri_param, &user_info) {
|
||||
if !check_api_permission(api_method.access.permission, user.as_deref(), &uri_param, user_info.as_ref()) {
|
||||
let err = http_err!(FORBIDDEN, format!("permission check failed"));
|
||||
tokio::time::delay_until(Instant::from_std(access_forbidden_time)).await;
|
||||
return Ok((formatter.format_error)(err));
|
||||
|
|
Loading…
Reference in New Issue