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
use crate::{ServiceError, DatabaseRecord, Record}; use serde::{Serialize, de::DeserializeOwned}; /// The `AuthorizeAction` trait of the Aragog library. /// This traits allows provides the ability to authorize a [`Record`] to execute a custom action on /// an other one. /// /// # Example /// ```rust /// # use aragog::{AuthorizeAction, DatabaseRecord, Record, Validate}; /// # use serde::{Deserialize, Serialize}; /// # /// #[derive(Serialize, Deserialize, Clone)] /// pub struct Employee { /// pub is_cook: bool, /// pub is_accountant: bool, /// } /// /// #[derive(Serialize, Deserialize, Clone)] /// pub struct Company { /// pub taxes_payed: bool, /// pub is_cooking_done: bool, /// } /// # /// # impl Record for Company { /// # fn collection_name() -> &'static str { "Companies" } /// # } /// # /// # impl Validate for Company { /// # fn validations(&self,errors: &mut Vec<String>) { } /// # } /// /// pub enum EmployeeAction { /// Cook, /// PayTaxes /// } /// /// impl AuthorizeAction<Company> for Employee { /// type Action = EmployeeAction; /// /// fn is_action_authorized(&self, action: Self::Action, target: Option<&DatabaseRecord<Company>>) -> bool { /// if target.is_none() { return false; } /// let target = target.unwrap(); /// match action { /// EmployeeAction::Cook => self.is_cook && !target.record.is_cooking_done, /// EmployeeAction::PayTaxes => self.is_accountant && !target.record.taxes_payed, /// } /// } /// } /// ``` /// /// [`Record`]: trait.Record.html pub trait AuthorizeAction<T: Serialize + DeserializeOwned + Clone + Record> { /// The action type to be authorized, like a custom enum of ACL actions (write, read) or more /// logic operations. type Action; /// If the object is authorized to do `action` on `target` then the method will return `Ok(())`, /// otherwise a [`ServiceError`]::[`Forbidden`] is returned. /// /// [`ServiceError`]: enum.ServiceError.html /// [`Forbidden`]: enum.ServiceError.html#variant.Forbidden fn authorize_action(&self, action: Self::Action, target: Option<&DatabaseRecord<T>>) -> Result<(), ServiceError> { if self.is_action_authorized(action, target) { return Ok(()) } Err(ServiceError::Forbidden) } /// Returns true if the object is authorized to do `action` on `target` fn is_action_authorized(&self, action: Self::Action, target: Option<&DatabaseRecord<T>>) -> bool; }