use super::errors::{AuthError, UserId};
use crate::types::SessionId;
#[derive(Debug, Clone, PartialEq)]
pub struct TokenBudget {
pub limit: Option<u64>,
pub used: u64,
}
impl TokenBudget {
#[must_use]
pub fn remaining(&self) -> Option<u64> {
self.limit.map(|l| l.saturating_sub(self.used))
}
#[must_use]
pub fn is_exhausted(&self) -> bool {
self.limit.is_some_and(|l| self.used >= l)
}
#[must_use]
pub fn unlimited() -> Self {
Self {
limit: None,
used: 0,
}
}
}
pub trait SessionAccessProvider: Send + Sync {
fn can_access_session(&self, user: &UserId, session: &SessionId) -> Result<bool, AuthError>;
fn can_use_model(&self, user: &UserId, model: &str) -> Result<bool, AuthError>;
fn can_use_tool(&self, _user: &UserId, _tool: &str) -> Result<bool, AuthError> {
Ok(true)
}
fn can_spend(&self, _user: &UserId, _tokens: u64) -> Result<bool, AuthError> {
Ok(true)
}
fn token_budget(&self, user: &UserId) -> Result<TokenBudget, AuthError>;
fn record_usage(&self, _user: &UserId, _tokens: u64) -> Result<(), AuthError> {
Ok(())
}
}
pub struct AllowAllAccess;
impl SessionAccessProvider for AllowAllAccess {
fn can_access_session(&self, _user: &UserId, _session: &SessionId) -> Result<bool, AuthError> {
Ok(true)
}
fn can_use_model(&self, _user: &UserId, _model: &str) -> Result<bool, AuthError> {
Ok(true)
}
fn token_budget(&self, _user: &UserId) -> Result<TokenBudget, AuthError> {
Ok(TokenBudget::unlimited())
}
}