1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
//! Oso policy engine for authorization
//!
//! # Overview
//!
//! Oso is a policy engine for authorization that's embedded in your application.
//! It provides a declarative policy language for expressing authorization logic.
//! You define this logic separately from the rest of your application code,
//! but it executes inside the application and can call directly into it.
//!
//! For more information, guides on using oso, writing policies and adding to your
//! application, go to the [oso documentation](https://docs.osohq.com).
//!
//! For specific information on using with Rust, see the [Rust documentation](https://docs.osohq.com/using/libraries/rust/index.html).
//!
//! ## Note
//!
//! The Oso Rust library is still in early development relative to the other
//! Oso libraries.
//!
//! # Example
//!
//! To get started, create a new [`Oso`] instance, and load Polar policies from either a
//! string or a file:
//!
//! ```
//! # use oso::Oso;
//! # fn main() -> anyhow::Result<()> {
//! let mut oso = Oso::new();
//! oso.load_str(r#"allow(actor, _action, _resource) if actor.username = "alice";"#)?;
//! # Ok(())
//! # }
//! ```
//!
//! You can register classes with oso, which makes it possible to use them for type checking, as
//! well as accessing attributes in policies.
//! The [`PolarClass`](oso_derive::PolarClass) derive macro can handle some of this.
//!
//! ```
//! # fn main() -> anyhow::Result<()> {
//! use oso::{Oso, PolarClass};
//!
//! #[derive(Clone, PolarClass)]
//! struct User {
//! #[polar(attribute)]
//! pub username: String,
//! }
//!
//! impl User {
//! fn superuser() -> Vec<String> {
//! return vec!["alice".to_string(), "charlie".to_string()]
//! }
//! }
//!
//! let mut oso = Oso::new();
//!
//! oso.register_class(
//! User::get_polar_class_builder()
//! .add_class_method("superusers", User::superuser)
//! .build()
//! )?;
//!
//! oso.load_str(r#"allow(actor: User, _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(())
//! # }
//! ```
//! For more examples, see the [Oso documentation](https://docs.osohq.com).
//!
#[macro_use]
pub mod macros;
pub(crate) mod builtins;
pub mod errors;
mod extras;
mod host;
mod oso;
mod query;
pub use crate::oso::{Action, Oso};
pub use errors::{OsoError, Result};
pub use host::{Class, ClassBuilder, FromPolar, FromPolarList, PolarValue, ToPolar, ToPolarList};
pub use query::{Query, ResultSet};
use polar_core::polar::Polar;
/// Classes that can be used as types in Polar policies.
///
/// Implementing this trait and [`Clone`] automatically makes the type [`FromPolar`] and
/// [`ToPolar`], so it can be used with [`Oso::is_allowed()`] calls.
///
/// The default implementation creates a class definition with no attributes or methods registered.
/// Either use [`get_polar_class_builder()`](PolarClass::get_polar_class_builder) or the
/// [`PolarClass`](oso_derive::PolarClass) proc macro to register attributes and methods.
///
/// **Note**: the returned [`Class`] still must be registered on an [`Oso`] instance using
/// [`Oso::register_class()`].
///
/// # Examples
///
/// Register polar class:
///
/// ```
/// use oso::{Oso, PolarClass};
///
/// #[derive(PolarClass)]
/// struct MyClass {
/// #[polar(attribute)]
/// name: String,
/// }
///
/// let mut oso = Oso::new();
/// oso.register_class(MyClass::get_polar_class());
/// ```
///
/// Register polar class with customisations:
///
/// ```
/// use oso::{Oso, PolarClass};
///
/// #[derive(PolarClass, Default, PartialEq)]
/// struct MyClass {
/// name: String,
/// }
///
/// let class = MyClass::get_polar_class_builder()
/// .add_attribute_getter("name", |value| value.name.clone())
/// .with_equality_check()
/// .build();
///
/// let mut oso = Oso::new();
/// oso.register_class(class);
/// ```
pub trait PolarClass: Sized + 'static {
/// Returns the `Class` ready for registration
fn get_polar_class() -> Class {
Self::get_polar_class_builder().build()
}
/// Returns the partially defined `Class` for this type.
///
/// Can still have methods added to it with `add_method`, and attributes
/// with `add_attribute_getter`.
/// Use `Class::build` to finish defining the type.
fn get_polar_class_builder() -> ClassBuilder<Self> {
Class::builder()
}
}
#[cfg(feature = "derive")]
#[allow(unused_imports)]
#[macro_use]
extern crate oso_derive;
#[cfg(feature = "derive")]
#[doc(hidden)]
pub use oso_derive::*;