cedar_policy_validator/
err.rs1use std::collections::HashSet;
18
19use cedar_policy_core::{
20 ast::{EntityAttrEvaluationError, EntityUID, Name},
21 parser::err::{ParseError, ParseErrors},
22 transitive_closure,
23};
24use itertools::Itertools;
25use thiserror::Error;
26
27#[derive(Debug, Error)]
28pub enum SchemaError {
29 #[error("failed to parse schema: {0}")]
31 Serde(#[from] serde_json::Error),
32 #[error("transitive closure computation/enforcement error on action hierarchy: {0}")]
35 ActionTransitiveClosure(Box<transitive_closure::TcError<EntityUID>>),
36 #[error("transitive closure computation/enforcement error on entity type hierarchy: {0}")]
39 EntityTypeTransitiveClosure(#[from] transitive_closure::TcError<Name>),
40 #[error("unsupported feature used in schema: {0}")]
42 UnsupportedFeature(UnsupportedFeature),
43 #[error("undeclared entity type(s): {0:?}")]
48 UndeclaredEntityTypes(HashSet<String>),
49 #[error("undeclared action(s): {0:?}")]
51 UndeclaredActions(HashSet<String>),
52 #[error("undeclared common type(s): {0:?}")]
54 UndeclaredCommonTypes(HashSet<String>),
55 #[error("duplicate entity type `{0}`")]
58 DuplicateEntityType(String),
59 #[error("duplicate action `{0}`")]
62 DuplicateAction(String),
63 #[error("duplicate common type `{0}`")]
65 DuplicateCommonType(String),
66 #[error("cycle in action hierarchy containing `{0}`")]
68 CycleInActionHierarchy(EntityUID),
69 #[error("parse error in entity type: {}", Self::format_parse_errs(.0))]
71 ParseEntityType(ParseErrors),
72 #[error("parse error in namespace identifier: {}", Self::format_parse_errs(.0))]
74 ParseNamespace(ParseErrors),
75 #[error("parse error in extension type: {}", Self::format_parse_errs(.0))]
77 ParseExtensionType(ParseErrors),
78 #[error("parse error in common type identifier: {}", Self::format_parse_errs(.0))]
81 ParseCommonType(ParseErrors),
82 #[error("entity type `Action` declared in `entityTypes` list")]
87 ActionEntityTypeDeclared,
88 #[error("{0} is declared with a type other than `Record`")]
90 ContextOrShapeNotRecord(ContextOrShape),
91 #[error("action `{0}` has an attribute that is an empty set")]
95 ActionAttributesContainEmptySet(EntityUID),
96 #[error("action `{0}` has an attribute with unsupported JSON representation: {1}")]
99 UnsupportedActionAttribute(EntityUID, String),
100 #[error(transparent)]
102 ActionAttrEval(EntityAttrEvaluationError),
103 #[error("uses the `__expr` escape, which is no longer supported")]
106 ExprEscapeUsed,
107}
108
109impl From<transitive_closure::TcError<EntityUID>> for SchemaError {
110 fn from(e: transitive_closure::TcError<EntityUID>) -> Self {
111 match e {
115 transitive_closure::TcError::MissingTcEdge { .. } => {
116 SchemaError::ActionTransitiveClosure(Box::new(e))
117 }
118 transitive_closure::TcError::HasCycle { vertex_with_loop } => {
119 SchemaError::CycleInActionHierarchy(vertex_with_loop)
120 }
121 }
122 }
123}
124
125pub type Result<T> = std::result::Result<T, SchemaError>;
126
127impl SchemaError {
128 fn format_parse_errs(errs: &[ParseError]) -> String {
129 errs.iter().map(|e| e.to_string()).join(", ")
130 }
131}
132
133#[derive(Debug)]
134pub enum ContextOrShape {
135 ActionContext(EntityUID),
136 EntityTypeShape(Name),
137}
138
139impl std::fmt::Display for ContextOrShape {
140 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
141 match self {
142 ContextOrShape::ActionContext(action) => write!(f, "Context for action {}", action),
143 ContextOrShape::EntityTypeShape(entity_type) => {
144 write!(f, "Shape for entity type {}", entity_type)
145 }
146 }
147 }
148}
149
150#[derive(Debug)]
151pub enum UnsupportedFeature {
152 OpenRecordsAndEntities,
153 ActionAttributes(Vec<String>),
155}
156
157impl std::fmt::Display for UnsupportedFeature {
158 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
159 match self {
160 Self::OpenRecordsAndEntities => write!(
161 f,
162 "records and entities with `additionalAttributes` are experimental, but the experimental `partial-validate` feature is not enabled"
163 ),
164 Self::ActionAttributes(attrs) => write!(
165 f,
166 "action declared with attributes: [{}]",
167 attrs.iter().join(", ")
168 ),
169 }
170 }
171}