Skip to content

Commit 26b1ec5

Browse files
Aaron Elinejohn-h-kastner-awscdisselkoen
committed
Added some useful methods and docs (#1186)
Signed-off-by: Aaron Eline <[email protected]> Co-authored-by: John Kastner <[email protected]> Co-authored-by: Craig Disselkoen <[email protected]>
1 parent 55575f6 commit 26b1ec5

File tree

3 files changed

+80
-5
lines changed

3 files changed

+80
-5
lines changed

cedar-policy-core/src/ast/entity.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,8 +317,17 @@ pub struct Entity {
317317
ancestors: HashSet<EntityUID>,
318318
}
319319

320+
impl std::hash::Hash for Entity {
321+
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
322+
self.uid.hash(state);
323+
}
324+
}
325+
320326
impl Entity {
321327
/// Create a new `Entity` with this UID, attributes, and ancestors
328+
///
329+
/// # Errors
330+
/// - Will error if any of the [`RestrictedExpr]`s in `attrs` error when evaluated
322331
pub fn new(
323332
uid: EntityUID,
324333
attrs: HashMap<SmolStr, RestrictedExpr>,
@@ -346,6 +355,13 @@ impl Entity {
346355
})
347356
}
348357

358+
/// Create a new `Entity` with this UID, ancestors, and an empty set of attributes
359+
///
360+
/// Since there are no attributes, this method does not error, and returns `Self` instead of `Result<Self>`
361+
pub fn new_empty_attrs(uid: EntityUID, ancestors: HashSet<EntityUID>) -> Self {
362+
Self::new_with_attr_partial_value(uid, HashMap::new(), ancestors)
363+
}
364+
349365
/// Create a new `Entity` with this UID, attributes, and ancestors.
350366
///
351367
/// Unlike in `Entity::new()`, in this constructor, attributes are expressed

cedar-policy-core/src/entities.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,13 @@ impl Entities {
162162
///
163163
/// If you pass `TCComputation::AssumeAlreadyComputed`, then the caller is
164164
/// responsible for ensuring that TC and DAG hold before calling this method.
165+
///
166+
/// # Errors
167+
/// - [`EntitiesError::Duplicate`] if there are any duplicate entities in `entities`
168+
/// - [`EntitiesError::TransitiveClosureError`] if `tc_computation ==
169+
/// TCComputation::EnforceAlreadyComputed` and the entities are not transitivly closed
170+
/// - [`EntitiesError::InvalidEntity`] if `schema` is not none and any entities do not conform
171+
/// to the schema
165172
pub fn from_entities(
166173
entities: impl IntoIterator<Item = Entity>,
167174
schema: Option<&impl Schema>,
@@ -817,7 +824,7 @@ mod json_parsing_tests {
817824
parser.from_json_value(json).expect("JSON is correct")
818825
}
819826

820-
/// Ensure the initial conditions of the entiites still hold
827+
/// Ensure the initial conditions of the entities still hold
821828
fn simple_entities_still_sane(e: &Entities) {
822829
let bob = r#"Test::"bob""#.parse().unwrap();
823830
let alice = e.entity(&r#"Test::"alice""#.parse().unwrap()).unwrap();

cedar-policy/src/api.rs

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ use std::str::FromStr;
5454

5555
/// Entity datatype
5656
#[repr(transparent)]
57-
#[derive(Debug, Clone, PartialEq, Eq, RefCast)]
57+
#[derive(Debug, Clone, PartialEq, Eq, RefCast, Hash)]
5858
pub struct Entity(ast::Entity);
5959

6060
impl Entity {
@@ -97,6 +97,16 @@ impl Entity {
9797
)?))
9898
}
9999

100+
/// Create a new `Entity` with this Uid, parents, and no attributes.
101+
/// This is the same as `Self::new` except the attributes are empty, and therefore it can
102+
/// return `Self` instead of `Result<Self>`
103+
pub fn new_empty_attrs(uid: EntityUid, parents: HashSet<EntityUid>) -> Self {
104+
Self(ast::Entity::new_empty_attrs(
105+
uid.into(),
106+
parents.into_iter().map(EntityUid::into).collect(),
107+
))
108+
}
109+
100110
/// Create a new `Entity` with no attributes.
101111
///
102112
/// Unlike [`Entity::new()`], this constructor cannot error.
@@ -338,6 +348,10 @@ impl Entities {
338348
/// error if attributes have the wrong types (e.g., string instead of
339349
/// integer), or if required attributes are missing or superfluous
340350
/// attributes are provided.
351+
/// ## Errors
352+
/// - [`EntitiesError::Duplicate`] if there are any duplicate entities in `entities`
353+
/// - [`EntitiesError::InvalidEntity`] if `schema` is not none and any entities do not conform
354+
/// to the schema
341355
pub fn from_entities(
342356
entities: impl IntoIterator<Item = Entity>,
343357
schema: Option<&Schema>,
@@ -364,6 +378,10 @@ impl Entities {
364378
///
365379
/// Re-computing the transitive closure can be expensive, so it is advised
366380
/// to not call this method in a loop.
381+
/// ## Errors
382+
/// - [`EntitiesError::Duplicate`] if there are any duplicate entities in `entities`
383+
/// - [`EntitiesError::InvalidEntity`] if `schema` is not none and any entities do not conform
384+
/// to the schema
367385
pub fn add_entities(
368386
self,
369387
entities: impl IntoIterator<Item = Entity>,
@@ -394,6 +412,11 @@ impl Entities {
394412
///
395413
/// Re-computing the transitive closure can be expensive, so it is advised
396414
/// to not call this method in a loop.
415+
/// ## Errors
416+
/// - [`EntitiesError::Duplicate`] if there are any duplicate entities in `entities`
417+
/// - [`EntitiesError::InvalidEntity`] if `schema` is not none and any entities do not conform
418+
/// to the schema
419+
/// - [`EntitiesError::Deserialization`] if there are errors while parsing the json
397420
pub fn add_entities_from_json_str(
398421
self,
399422
json: &str,
@@ -427,6 +450,11 @@ impl Entities {
427450
///
428451
/// Re-computing the transitive closure can be expensive, so it is advised
429452
/// to not call this method in a loop.
453+
/// ## Errors
454+
/// - [`EntitiesError::Duplicate`] if there are any duplicate entities in `entities`
455+
/// - [`EntitiesError::InvalidEntity`] if `schema` is not none and any entities do not conform
456+
/// to the schema
457+
/// - [`EntitiesError::Deserialization`] if there are errors while parsing the json
430458
pub fn add_entities_from_json_value(
431459
self,
432460
json: serde_json::Value,
@@ -460,6 +488,12 @@ impl Entities {
460488
///
461489
/// Re-computing the transitive closure can be expensive, so it is advised
462490
/// to not call this method in a loop.
491+
///
492+
/// ## Errors
493+
/// - [`EntitiesError::Duplicate`] if there are any duplicate entities in `entities`
494+
/// - [`EntitiesError::InvalidEntity`] if `schema` is not none and any entities do not conform
495+
/// to the schema
496+
/// - [`EntitiesError::Deserialization`] if there are errors while parsing the json
463497
pub fn add_entities_from_json_file(
464498
self,
465499
json: impl std::io::Read,
@@ -497,6 +531,12 @@ impl Entities {
497531
/// instead of integer), or if required attributes are missing or
498532
/// superfluous attributes are provided.
499533
///
534+
/// ## Errors
535+
/// - [`EntitiesError::Duplicate`] if there are any duplicate entities in `entities`
536+
/// - [`EntitiesError::InvalidEntity`] if `schema` is not none and any entities do not conform
537+
/// to the schema
538+
/// - [`EntitiesError::Deserialization`] if there are errors while parsing the json
539+
///
500540
/// ```
501541
/// # use cedar_policy::{Entities, EntityId, EntityTypeName, EntityUid, EvalResult, Request,PolicySet};
502542
/// # use std::str::FromStr;
@@ -552,6 +592,12 @@ impl Entities {
552592
/// instead of integer), or if required attributes are missing or
553593
/// superfluous attributes are provided.
554594
///
595+
/// ## Errors
596+
/// - [`EntitiesError::Duplicate`] if there are any duplicate entities in `entities`
597+
/// - [`EntitiesError::InvalidEntity`]if `schema` is not none and any entities do not conform
598+
/// to the schema
599+
/// - [`EntitiesError::Deserialization`] if there are errors while parsing the json
600+
///
555601
/// ```
556602
/// # use cedar_policy::{Entities, EntityId, EntityTypeName, EntityUid, EvalResult, Request,PolicySet};
557603
/// let data =serde_json::json!(
@@ -603,6 +649,12 @@ impl Entities {
603649
/// instance, it will error if attributes have the wrong types (e.g., string
604650
/// instead of integer), or if required attributes are missing or
605651
/// superfluous attributes are provided.
652+
///
653+
/// ## Errors
654+
/// - [`EntitiesError::Duplicate`] if there are any duplicate entities in `entities`
655+
/// - [`EntitiesError::InvalidEntity`] if `schema` is not none and any entities do not conform
656+
/// to the schema
657+
/// - [`EntitiesError::Deserialization`] if there are errors while parsing the json
606658
pub fn from_json_file(
607659
json: impl std::io::Read,
608660
schema: Option<&Schema>,
@@ -1485,7 +1537,7 @@ impl Schema {
14851537

14861538
/// Returns an iterator over every entity type that can be a principal for `action` in this schema
14871539
///
1488-
/// # Errors
1540+
/// ## Errors
14891541
///
14901542
/// Returns [`None`] if `action` is not found in the schema
14911543
pub fn principals_for_action(
@@ -1499,7 +1551,7 @@ impl Schema {
14991551

15001552
/// Returns an iterator over every entity type that can be a resource for `action` in this schema
15011553
///
1502-
/// # Errors
1554+
/// ## Errors
15031555
///
15041556
/// Returns [`None`] if `action` is not found in the schema
15051557
pub fn resources_for_action(
@@ -1513,7 +1565,7 @@ impl Schema {
15131565

15141566
/// Returns an iterator over all the entity types that can be an ancestor of `ty`
15151567
///
1516-
/// # Errors
1568+
/// ## Errors
15171569
///
15181570
/// Returns [`None`] if the `ty` is not found in the schema
15191571
pub fn ancestors<'a>(

0 commit comments

Comments
 (0)