Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adds upsert_entities #1481

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cedar-policy/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Cedar Language Version: TBD
- Added `Entities::remove_entities()` to remove `Entity`s from an `Entities` struct (resolving #701)
- Added `PolicySet::merge_policyset()` to merge a `PolicySet` into another `PolicySet` struct (resolving #610)
- Implemented [RFC 53 (enumerated entity types)](https://github.com/cedar-policy/rfcs/blob/main/text/0053-enum-entities.md) (#1377)
- Added `Entities::upsert_entities()` to add or update `Entity`s in an `Entities` struct (resolving #1479)

### Fixed

Expand Down
37 changes: 37 additions & 0 deletions cedar-policy/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,43 @@ impl Entities {
)?))
}

/// Updates or adds all of the [`Entity`]s in the collection to this [`Entities`]
/// structure, re-computing the transitive closure.
///
/// If a `schema` is provided, this method will ensure that the added
/// entities fully conform to the schema -- for instance, it will error if
/// attributes have the wrong types (e.g., string instead of integer), or if
/// required attributes are missing or superfluous attributes are provided.
/// (This method will not add action entities from the `schema`.)
///
/// Re-computing the transitive closure can be expensive, so it is advised
/// to not call this method in a loop.
/// ## Errors
/// - [`EntitiesError::InvalidEntity`] if `schema` is not none and any entities do not conform
/// to the schema
pub fn upsert_entities(
self,
entities: impl IntoIterator<Item = Entity>,
schema: Option<&Schema>,
) -> Result<Self, EntitiesError> {
let entities: Vec<_> = entities.into_iter().collect();

let removed = self.0.remove_entities(
entities.iter().map(|e| e.uid().0),
cedar_policy_core::entities::TCComputation::AssumeAlreadyComputed
)?;

Ok(Self(
removed.add_entities(
entities.into_iter().map(|e| Arc::new(e.0)), // Second use
schema.map(|s| cedar_policy_validator::CoreSchema::new(&s.0))
.as_ref(),
cedar_policy_core::entities::TCComputation::ComputeNow,
Extensions::all_available(),
)?
))
}

/// Parse an entities JSON file (in [&str] form) and add them into this
/// [`Entities`] structure, re-computing the transitive closure
///
Expand Down