use serde::{Deserialize, Serialize};
use std::collections::BTreeSet;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum AiPermission {
Read,
Search,
Propose,
Commit,
Delete,
}
impl AiPermission {
pub fn is_mutating(self) -> bool {
matches!(self, Self::Commit | Self::Delete)
}
pub fn as_str(self) -> &'static str {
match self {
Self::Read => "read",
Self::Search => "search",
Self::Propose => "propose",
Self::Commit => "commit",
Self::Delete => "delete",
}
}
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
#[serde(transparent)]
pub struct AiPermissions {
granted: BTreeSet<AiPermission>,
}
impl AiPermissions {
pub fn none() -> Self {
Self::default()
}
pub fn read_and_propose() -> Self {
Self::from([
AiPermission::Read,
AiPermission::Search,
AiPermission::Propose,
])
}
pub fn from(permissions: impl IntoIterator<Item = AiPermission>) -> Self {
Self {
granted: permissions.into_iter().collect(),
}
}
pub fn allows(&self, permission: AiPermission) -> bool {
self.granted.contains(&permission)
}
pub fn is_empty(&self) -> bool {
self.granted.is_empty()
}
pub fn grants_mutation(&self) -> bool {
self.granted
.iter()
.any(|permission| permission.is_mutating())
}
pub fn granted(&self) -> impl Iterator<Item = AiPermission> + '_ {
self.granted.iter().copied()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn the_default_grant_cannot_change_anything() {
let permissions = AiPermissions::read_and_propose();
assert!(permissions.allows(AiPermission::Read));
assert!(permissions.allows(AiPermission::Propose));
assert!(!permissions.allows(AiPermission::Commit));
assert!(!permissions.allows(AiPermission::Delete));
assert!(!permissions.grants_mutation());
}
#[test]
fn proposing_is_not_mutating_but_committing_is() {
assert!(!AiPermission::Propose.is_mutating());
assert!(AiPermission::Commit.is_mutating());
assert!(AiPermission::Delete.is_mutating());
}
#[test]
fn granting_commit_is_visible_as_such() {
let permissions = AiPermissions::from([AiPermission::Read, AiPermission::Commit]);
assert!(
permissions.grants_mutation(),
"a settings screen must be able to warn about this"
);
}
}