Skip to content

Commit 3fd64da

Browse files
Changes needed by RFC 53 (#524)
Signed-off-by: Shaobo He <shaobohe@amazon.com>
1 parent 4774c3c commit 3fd64da

File tree

8 files changed

+309
-146
lines changed

8 files changed

+309
-146
lines changed

cedar-drt/fuzz/src/schemas.rs

Lines changed: 56 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616

1717
use cedar_policy_core::ast::{Id, InternalName, Name};
1818
use cedar_policy_validator::json_schema;
19+
use cedar_policy_validator::json_schema::EntityTypeKind;
1920
use cedar_policy_validator::RawName;
21+
use cedar_policy_validator::ValidatorEntityTypeKind;
2022
use itertools::Itertools;
2123
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
2224

@@ -228,36 +230,67 @@ impl<N: Clone + PartialEq + Debug + Display + TypeName + Ord> Equiv for json_sch
228230
fn equiv(lhs: &Self, rhs: &Self) -> Result<(), String> {
229231
Equiv::equiv(&lhs.annotations, &rhs.annotations)
230232
.map_err(|e| format!("mismatch in entity annotations: {e}"))?;
231-
Equiv::equiv(
232-
&lhs.member_of_types.iter().collect::<BTreeSet<_>>(),
233-
&rhs.member_of_types.iter().collect::<BTreeSet<_>>(),
234-
)
235-
.map_err(|e| format!("memberOfTypes are not equal: {e}"))?;
236-
Equiv::equiv(&lhs.shape, &rhs.shape).map_err(|e| format!("mismatched types: {e}"))?;
237-
match (&lhs.tags, &rhs.tags) {
238-
(Some(ts1), Some(ts2)) => {
239-
Equiv::equiv(ts1, ts2).map_err(|msg| format!("mismatched entity tags: {msg}"))
233+
match (&lhs.kind, &rhs.kind) {
234+
(EntityTypeKind::Enum { choices: c1 }, EntityTypeKind::Enum { choices: c2 }) => {
235+
if c1 != c2 {
236+
Err(format!(
237+
"enumerated entity types have different eid choices: {c1:?} and {c2:?}"
238+
))
239+
} else {
240+
Ok(())
241+
}
242+
}
243+
(EntityTypeKind::Standard(lhs), EntityTypeKind::Standard(rhs)) => {
244+
Equiv::equiv(
245+
&lhs.member_of_types.iter().collect::<BTreeSet<_>>(),
246+
&rhs.member_of_types.iter().collect::<BTreeSet<_>>(),
247+
)
248+
.map_err(|e| format!("memberOfTypes are not equal: {e}"))?;
249+
Equiv::equiv(&lhs.shape, &rhs.shape)
250+
.map_err(|e| format!("mismatched types: {e}"))?;
251+
match (&lhs.tags, &rhs.tags) {
252+
(Some(ts1), Some(ts2)) => Equiv::equiv(ts1, ts2)
253+
.map_err(|msg| format!("mismatched entity tags: {msg}")),
254+
(None, None) => Ok(()),
255+
(Some(ts), None) | (None, Some(ts)) => {
256+
Err(format!("only one side has tags: {ts}"))
257+
}
258+
}
240259
}
241-
(None, None) => Ok(()),
242-
(Some(ts), None) | (None, Some(ts)) => Err(format!("only one side has tags: {ts}")),
260+
(k1, k2) => Err(format!("different entity type kind: {:?} and {:?}", k1, k2)),
243261
}
244262
}
245263
}
246264

247265
impl Equiv for cedar_policy_validator::ValidatorEntityType {
248266
fn equiv(lhs: &Self, rhs: &Self) -> Result<(), String> {
249-
Equiv::equiv(&lhs.descendants, &rhs.descendants)?;
250-
Equiv::equiv(
251-
&lhs.attributes().collect::<HashMap<_, _>>(),
252-
&rhs.attributes().collect::<HashMap<_, _>>(),
253-
)?;
254-
if lhs.tag_type() != rhs.tag_type() {
255-
return Err(format!(
256-
"encountered different tags types: {:?} and {:?}",
257-
lhs.tag_type(),
258-
rhs.tag_type()
259-
));
260-
}
267+
match (&lhs.kind, &rhs.kind) {
268+
(ValidatorEntityTypeKind::Enum(c1), ValidatorEntityTypeKind::Enum(c2)) => {
269+
if c1 != c2 {
270+
return Err(format!(
271+
"enumerated entity types have different eid choices: {c1:?} and {c2:?}"
272+
));
273+
}
274+
}
275+
(ValidatorEntityTypeKind::Standard(_), ValidatorEntityTypeKind::Standard(_)) => {
276+
Equiv::equiv(&lhs.descendants, &rhs.descendants)?;
277+
Equiv::equiv(
278+
&lhs.attributes().iter().collect::<HashMap<_, _>>(),
279+
&rhs.attributes().iter().collect::<HashMap<_, _>>(),
280+
)?;
281+
if lhs.tag_type() != rhs.tag_type() {
282+
return Err(format!(
283+
"encountered different tags types: {:?} and {:?}",
284+
lhs.tag_type(),
285+
rhs.tag_type()
286+
));
287+
}
288+
}
289+
(k1, k2) => {
290+
return Err(format!("different entity type kind: {:?} and {:?}", k1, k2));
291+
}
292+
};
293+
261294
Ok(())
262295
}
263296
}

cedar-lean/CedarProto/ValidatorEntityType.lean

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ structure ValidatorEntityType where
3232
descendants : Array Spec.EntityTypeProto
3333
attrs : RecordType
3434
tags : Option CedarType
35+
enums: Array String
3536
deriving Inhabited
3637

3738
-- the Tag message in Validator.proto
@@ -91,12 +92,19 @@ def mergeTags (result : ValidatorEntityType) (x : TagMessage) : ValidatorEntityT
9192
tags := mergeOption result.tags (some x.optional_type)
9293
}
9394

95+
@[inline]
96+
def mergeEnums (result : ValidatorEntityType) (x : Array String) : ValidatorEntityType :=
97+
{result with
98+
enums := result.enums ++ x
99+
}
100+
94101
@[inline]
95102
def merge (x y : ValidatorEntityType) : ValidatorEntityType :=
96103
{
97104
descendants := y.descendants ++ x.descendants
98105
attrs := Field.merge x.attrs y.attrs
99106
tags := mergeOption x.tags y.tags
107+
enums := x.enums ++ y.enums
100108
}
101109

102110
@[inline]
@@ -111,6 +119,9 @@ def parseField (t : Tag) : BParsec (MergeFn ValidatorEntityType) := do
111119
| 5 =>
112120
let x : TagMessage ← Field.guardedParse t
113121
pure (pure $ mergeTags · x)
122+
| 6 =>
123+
let x : Repeated String ← Field.guardedParse t
124+
pure (pure $ mergeEnums · x)
114125
| _ =>
115126
t.wireType.skip
116127
pure ignore

cedar-lean/CedarProto/ValidatorSchema.lean

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,11 +71,19 @@ def toEntitySchema (ets : EntityTypeWithTypesMap) : EntitySchema :=
7171
let ancestorMap := descendantsToAncestors descendantMap
7272
Data.Map.make (ets.map
7373
(λ (k,v) => (k,
74+
if v.enums.isEmpty then
7475
{
7576
ancestors := ancestorMap.find! k,
7677
attrs := Data.Map.make v.attrs.kvs,
7778
tags := v.tags,
78-
})))
79+
}
80+
else
81+
{
82+
ancestors := ancestorMap.find! k,
83+
attrs := Data.Map.empty,
84+
tags := none,
85+
}
86+
)))
7987
end Cedar.Validation.Proto.EntityTypeWithTypesMap
8088

8189
namespace Cedar.Validation.Proto.EntityUidWithActionsIdMap

cedar-lean/DiffTest/Parser.lean

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -508,14 +508,22 @@ partial def jsonToCedarType (json : Lean.Json) : ParseResult CedarType := do
508508
.ok (.ext name)
509509
| tag => .error s!"jsonToCedarType: unknown tag {tag}"
510510

511+
partial def jsonToEntityTypeKind (json: Lean.Json) : ParseResult (RecordType × Option CedarType) := do
512+
let (tag, value) ← unpackJsonSum json
513+
match tag with
514+
| "Enum" => .ok (Map.empty, none)
515+
| "Standard" =>
516+
let attrs ← getJsonField value "attributes" >>= (getJsonField · "attrs") >>= jsonToRecordType
517+
let tags ← -- the "tags" field may be absent
518+
match getJsonField value "tags" with
519+
| .ok jty => (jsonToCedarType jty).map λ ty => (attrs, some ty)
520+
| .error _ => .ok (attrs, none)
521+
| tag => .error s!"jsonToEntityTypeKind: unknown tag {tag}"
522+
511523
partial def jsonToEntityTypeEntry (json : Lean.Json) : ParseResult JsonEntitySchemaEntry := do
512524
let descendants_json ← getJsonField json "descendants" >>= jsonToArray
513525
let descendants ← List.mapM jsonToName descendants_json.toList
514-
let attrs ← getJsonField json "attributes" >>= (getJsonField · "attrs") >>= jsonToRecordType
515-
let tags ← -- the "tags" field may be absent
516-
match getJsonField json "tags" with
517-
| .ok jty => (jsonToCedarType jty).map .some
518-
| .error _ => .ok .none
526+
let (attrs, tags) ← getJsonField json "kind" >>= jsonToEntityTypeKind
519527
.ok {
520528
descendants := Set.make descendants,
521529
attrs := attrs,

cedar-policy-generators/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ rand = "0.8.5"
1717
anyhow = "1.0.72"
1818
serde_with = "3.4.0"
1919
thiserror = "2.0"
20+
nonempty = { version = "0.10", features = ["arbitrary"] }
2021

2122
[dev.dependencies]
2223
rand = "0.8.5"

cedar-policy-generators/src/expr.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ use crate::{accum, gen, gen_inner, uniform};
2828
use arbitrary::{Arbitrary, MaxRecursionReached, Unstructured};
2929
use cedar_policy_core::ast::{self, UnreservedId};
3030
use cedar_policy_core::est::Annotations;
31-
use cedar_policy_validator::json_schema;
31+
use cedar_policy_validator::json_schema::{self, EntityTypeKind, StandardEntityType};
3232
use smol_str::SmolStr;
3333
use std::collections::BTreeMap;
3434

@@ -590,11 +590,14 @@ impl<'a> ExprGenerator<'a> {
590590
.expect("Failed to select entity index."),
591591
)
592592
.expect("Failed to select entity from map.");
593-
let attr_names: Vec<&SmolStr> =
594-
attrs_from_attrs_or_context(&self.schema.schema, &entity_type.shape)
595-
.attrs
596-
.keys()
597-
.collect::<Vec<_>>();
593+
let attr_names: Vec<&SmolStr> = match &entity_type.kind {
594+
// Generate an empty vec here so that we fail fast
595+
EntityTypeKind::Enum { .. } => vec![],
596+
EntityTypeKind::Standard(StandardEntityType { shape, ..}) => attrs_from_attrs_or_context(&self.schema.schema, shape)
597+
.attrs
598+
.keys()
599+
.collect::<Vec<_>>()
600+
};
598601
let attr_name = SmolStr::clone(u.choose(&attr_names)?);
599602
Ok(ast::Expr::has_attr(
600603
self.generate_expr_for_schematype(
@@ -2559,7 +2562,7 @@ impl<'a> ExprGenerator<'a> {
25592562
u: &mut Unstructured<'_>,
25602563
) -> Result<ast::EntityUID> {
25612564
match self.hierarchy {
2562-
None => generate_uid_with_type(ty.clone(), u),
2565+
None => generate_uid_with_type(ty.clone(), &self.schema.get_uid_choices(ty), u),
25632566
Some(hierarchy) => hierarchy.arbitrary_uid_with_type(ty, u),
25642567
}
25652568
}

0 commit comments

Comments
 (0)