use super::atomic::AtomicPermission;
use super::composite::PermissionSet;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
pub type Timestamp = u64;
#[cfg(not(target_arch = "wasm32"))]
pub fn current_timestamp_millis() -> Timestamp {
std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap_or_default()
.as_millis() as u64
}
#[cfg(target_arch = "wasm32")]
pub fn current_timestamp_millis() -> Timestamp {
js_sys::Date::now() as u64
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[non_exhaustive]
pub struct TemporalPermission {
pub permission: AtomicPermission,
pub valid_from: Option<Timestamp>,
pub valid_until: Option<Timestamp>,
}
impl TemporalPermission {
pub fn new(
permission: AtomicPermission,
valid_from: Option<Timestamp>,
valid_until: Option<Timestamp>,
) -> Self {
Self {
permission,
valid_from,
valid_until,
}
}
pub fn is_valid_at(&self, timestamp: Timestamp) -> bool {
let after_start = self.valid_from.is_none_or(|start| timestamp >= start);
let before_end = self.valid_until.is_none_or(|end| timestamp < end);
after_start && before_end
}
pub fn is_currently_valid(&self) -> bool {
self.is_valid_at(current_timestamp_millis())
}
}
#[derive(Debug, Clone, Default)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[non_exhaustive]
pub struct TemporalPermissionSet {
permissions: Vec<TemporalPermission>,
}
impl TemporalPermissionSet {
pub fn new() -> Self {
Self::default()
}
pub fn add(&mut self, perm: TemporalPermission) {
self.permissions.push(perm);
}
pub fn effective_at(&self, timestamp: Timestamp) -> PermissionSet {
self.permissions
.iter()
.filter(|p| p.is_valid_at(timestamp))
.map(|p| p.permission.clone())
.collect()
}
pub fn currently_effective(&self) -> PermissionSet {
self.effective_at(current_timestamp_millis())
}
pub fn len(&self) -> usize {
self.permissions.len()
}
pub fn is_empty(&self) -> bool {
self.permissions.is_empty()
}
pub fn remove(&mut self, permission: &AtomicPermission) -> bool {
let initial_len = self.permissions.len();
self.permissions.retain(|tp| &tp.permission != permission);
self.permissions.len() != initial_len
}
}