use oso::{Oso, PolarClass}; use std::collections::HashMap; fn types() -> anyhow::Result<()> { let mut oso = Oso::new(); #[derive(Clone, PolarClass)] struct User1 { #[polar(attribute)] name: String, #[polar(attribute)] is_admin: bool, } oso.register_class(User1::get_polar_class())?; oso.load_str(r#"allow(actor: User1, _action, _resource) if actor.is_admin;"#)?; let user1 = User1 { name: "alice".to_string(), is_admin: true, }; assert!(oso.is_allowed(user1, "foo", "bar")?); let mut oso = Oso::new(); #[derive(Clone, PolarClass)] struct User2 { #[polar(attribute)] name: String, #[polar(attribute)] is_admin: bool, } impl User2 { fn new(name: String, is_admin: bool) -> Self { Self { name, is_admin } } fn is_called_alice(&self) -> bool { self.name == "alice" } } oso.register_class( User2::get_polar_class_builder() .set_constructor(User2::new) .add_method("is_called_alice", User2::is_called_alice) .build(), )?; oso.load_str( r#" allow(user: User2, _, _) if user.is_admin; ?= allow(new User2("bob", true), "foo", "bar"); ?= new User2("alice", true).is_called_alice(); "#, )?; let mut oso = Oso::new(); #[derive(Clone, PolarClass)] struct User3 { #[polar(attribute)] name: String, #[polar(attribute)] is_admin: bool, } oso.register_class(User3::get_polar_class())?; oso.load_str(r#"allow(actor, _action, _resource) if actor matches User3{name: "alice"};"#)?; let user3 = User3 { name: "alice".to_string(), is_admin: true, }; assert!(oso.is_allowed(user3, "foo", "bar")?); assert!(!oso.is_allowed("notauser", "foo", "bar")?); Ok(()) } fn strings() -> anyhow::Result<()> { let mut oso = Oso::new(); #[derive(PolarClass, Clone)] struct User { #[polar(attribute)] pub username: String, } oso.register_class(User::get_polar_class())?; oso.load_str( r#"allow(actor, _action, _resource) if actor.username.ends_with("example.com");"#, )?; let user = User { username: "alice@example.com".to_owned(), }; assert!(oso.is_allowed(user, "foo", "bar")?); Ok(()) } fn vecs() -> anyhow::Result<()> { let mut oso = Oso::new(); #[derive(Clone, PolarClass)] struct User { #[polar(attribute)] pub groups: Vec, } oso.register_class(User::get_polar_class()).unwrap(); oso.load_str(r#"allow(actor, _action, _resource) if "HR" in actor.groups;"#)?; let user = User { groups: vec!["HR".to_string(), "payroll".to_string()], }; assert!(oso.is_allowed(user, "foo", "bar")?); Ok(()) } fn maps() -> anyhow::Result<()> { let mut oso = Oso::new(); #[derive(Clone, PolarClass)] struct User { #[polar(attribute)] pub roles: HashMap, } oso.register_class(User::get_polar_class())?; oso.load_str(r#"allow(actor, _action, _resource) if actor.roles.project1 = "admin";"#)?; let user = User { roles: maplit::hashmap! { "project1".to_string() => "admin".to_string() }, }; assert!(oso.is_allowed(user, "foo", "bar")?); Ok(()) } fn enums() -> anyhow::Result<()> { let mut oso = Oso::new(); #[derive(Clone)] enum UserType { Admin, Guest, } impl oso::PolarClass for UserType {} oso.register_class( oso::Class::builder::() .add_method("is_admin", |u: &UserType| matches!(u, UserType::Admin)) .build(), )?; oso.load_str(r#"allow(actor, _action, _resource) if actor.is_admin();"#)?; let user = UserType::Admin; assert!(oso.is_allowed(user, "foo", "bar")?); assert!(!oso.is_allowed(UserType::Guest, "foo", "bar")?); Ok(()) } fn iters() -> anyhow::Result<()> { let mut oso = Oso::new(); #[derive(Clone, PolarClass)] struct User { groups: Vec, } oso.register_class( User::get_polar_class_builder() .add_iterator_method("get_group", |u: &User| u.groups.clone().into_iter()) .build(), ) .unwrap(); oso.load_str(r#"allow(actor, _action, _resource) if "payroll" in actor.get_group();"#)?; let user = User { groups: vec!["HR".to_string(), "payroll".to_string()], }; assert!(oso.is_allowed(user, "foo", "bar")?); Ok(()) } fn main() -> anyhow::Result<()> { strings()?; vecs()?; maps()?; enums()?; iters()?; types()?; println!("Examples passed"); Ok(()) }