cedar_agent/schemas/
data.rs

1use std::error::Error;
2
3use cedar_policy_core::entities::{
4    EntitiesError, EntityJSON, EntityJsonParser, NoEntitiesSchema, TCComputation,
5};
6use cedar_policy_core::extensions::Extensions;
7use cedar_policy_core::{ast, entities};
8use cedar_policy::Schema;
9use log::debug;
10use rocket::serde::json::serde_json::{from_str, json, to_string};
11use rocket::serde::json::Value;
12
13use rocket_okapi::okapi::schemars;
14use rocket_okapi::okapi::schemars::JsonSchema;
15use serde::{Deserialize, Serialize};
16
17use crate::common::EmptyError;
18
19#[derive(Debug, Serialize, Deserialize, JsonSchema)]
20pub struct Entity(Value);
21
22impl From<ast::Entity> for Entity {
23    fn from(value: ast::Entity) -> Self {
24        let entity_json = EntityJSON::from_entity(&value).unwrap();
25        let json_string = to_string(&entity_json).unwrap();
26        Self(from_str(&json_string).unwrap())
27    }
28}
29
30impl TryInto<ast::Entity> for Entity {
31    type Error = Box<dyn Error>;
32
33    fn try_into(self) -> Result<ast::Entity, Self::Error> {
34        debug!("Parsing entity into ast format");
35        let parser: EntityJsonParser<NoEntitiesSchema> =
36            EntityJsonParser::new(None, Extensions::all_available(), TCComputation::ComputeNow);
37        let entities = match parser.from_json_value(self.0) {
38            Ok(entities) => entities,
39            Err(err) => return Err(err.into()),
40        };
41        for entity in entities.iter() {
42            return Ok(entity.clone());
43        }
44        Err(EmptyError.into())
45    }
46}
47
48#[derive(Debug, Serialize, Deserialize, JsonSchema)]
49pub struct Entities(Vec<Entity>);
50
51impl Entities {
52    pub fn len(&self) -> usize {
53        self.0.len()
54    }
55
56    // Custom conversion function in place of a TryInto implementation
57    // This is due to the extra optional argument (schema)
58    pub fn convert_to_cedar_entities(&self, schema: &Option<Schema>) -> Result<cedar_policy::Entities, EntitiesError> {
59        debug!("Parsing entities into cedar format");
60        cedar_policy::Entities::from_json_value(json!(self.0), schema.as_ref())
61    }
62}
63
64impl From<entities::Entities> for Entities {
65    fn from(value: entities::Entities) -> Self {
66        Self(value.iter().map(|v| Entity::from(v.clone())).collect())
67    }
68}
69
70impl TryInto<entities::Entities> for Entities {
71    type Error = EntitiesError;
72
73    fn try_into(self) -> Result<entities::Entities, Self::Error> {
74        debug!("Parsing entities into ast format");
75        let parser: EntityJsonParser<NoEntitiesSchema> =
76            EntityJsonParser::new(None, Extensions::all_available(), TCComputation::ComputeNow);
77        parser.from_json_value(json!(self.0))
78    }
79}