Skip to main content

cedar_policy/api/
err.rs

1/*
2 * Copyright Cedar Contributors
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      https://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//! This module defines the publicly exported error types.
18
19use crate::{EntityUid, PolicyId};
20pub use cedar_policy_core::ast::{
21    expression_construction_errors, restricted_expr_errors, ContainsUnknown,
22    ExpressionConstructionError, PartialValueToValueError, RestrictedExpressionError,
23};
24#[cfg(feature = "tpe")]
25use cedar_policy_core::entities::conformance::err::EntitySchemaConformanceError;
26#[cfg(feature = "entity-manifest")]
27use cedar_policy_core::entities::err::EntitiesError;
28pub use cedar_policy_core::evaluator::{evaluation_errors, EvaluationError};
29pub use cedar_policy_core::extensions::{
30    extension_function_lookup_errors, ExtensionFunctionLookupError,
31};
32pub use cedar_policy_core::validator::cedar_schema::{schema_warnings, SchemaWarning};
33#[cfg(feature = "entity-manifest")]
34pub use cedar_policy_core::validator::entity_manifest::slicing::EntitySliceError;
35#[cfg(feature = "entity-manifest")]
36use cedar_policy_core::validator::entity_manifest::{
37    self, PartialExpressionError, PartialRequestError, UnsupportedCedarFeatureError,
38};
39pub use cedar_policy_core::validator::{schema_errors, SchemaError};
40use cedar_policy_core::{ast, authorizer, est, pst};
41use miette::Diagnostic;
42use ref_cast::RefCast;
43use serde::ser::Error;
44use smol_str::SmolStr;
45use thiserror::Error;
46use to_cedar_syntax_errors::NameCollisionsError;
47use to_cedar_syntax_errors::UnconvertibleEntityTypeShapeError;
48
49#[cfg(feature = "entity-manifest")]
50use super::ValidationResult;
51
52#[cfg(feature = "tpe")]
53pub use cedar_policy_core::tpe::err as tpe_err;
54
55/// Errors related to [`crate::Entities`]
56pub mod entities_errors {
57    pub use cedar_policy_core::entities::err::{Duplicate, EntitiesError, TransitiveClosureError};
58}
59
60/// Errors related to serializing/deserializing entities or contexts to/from JSON
61pub mod entities_json_errors {
62    pub use cedar_policy_core::entities::json::err::{
63        ActionParentIsNotAction, DuplicateKey, ExpectedExtnValue, ExpectedLiteralEntityRef,
64        ExtnCall0Arguments, ExtnCall2OrMoreArguments, JsonDeserializationError, JsonError,
65        JsonSerializationError, MissingImpliedConstructor, MissingRequiredRecordAttr, ParseEscape,
66        ReservedKey, Residual, TypeMismatch, UnexpectedRecordAttr, UnexpectedRestrictedExprKind,
67    };
68}
69
70/// Errors related to schema conformance checking for entities
71pub mod conformance_errors {
72    pub use cedar_policy_core::entities::conformance::err::{
73        ActionDeclarationMismatch, EntitySchemaConformanceError, ExtensionFunctionLookup,
74        InvalidAncestorType, MissingRequiredEntityAttr, TypeMismatch, UndeclaredAction,
75        UnexpectedEntityAttr, UnexpectedEntityTag, UnexpectedEntityTypeError,
76    };
77}
78
79/// Errors that can occur during authorization
80#[derive(Debug, Diagnostic, PartialEq, Eq, Error, Clone)]
81pub enum AuthorizationError {
82    /// An error occurred when evaluating a policy.
83    #[error(transparent)]
84    #[diagnostic(transparent)]
85    PolicyEvaluationError(#[from] authorization_errors::PolicyEvaluationError),
86}
87
88/// Error subtypes for [`AuthorizationError`]
89pub mod authorization_errors {
90    use crate::{EvaluationError, PolicyId};
91    use cedar_policy_core::{ast, authorizer};
92    use miette::Diagnostic;
93    use ref_cast::RefCast;
94    use thiserror::Error;
95
96    /// An error occurred when evaluating a policy
97    #[derive(Debug, Diagnostic, PartialEq, Eq, Error, Clone)]
98    #[error("error while evaluating policy `{id}`: {error}")]
99    #[diagnostic(forward(error))]
100    pub struct PolicyEvaluationError {
101        /// Id of the policy with an error
102        id: ast::PolicyID,
103        /// Underlying evaluation error
104        error: EvaluationError,
105    }
106
107    impl PolicyEvaluationError {
108        /// Get the [`PolicyId`] of the erroring policy
109        pub fn policy_id(&self) -> &PolicyId {
110            PolicyId::ref_cast(&self.id)
111        }
112
113        /// Get the underlying [`EvaluationError`]
114        pub fn inner(&self) -> &EvaluationError {
115            &self.error
116        }
117
118        /// Consume this error, producing the underlying [`EvaluationError`]
119        pub fn into_inner(self) -> EvaluationError {
120            self.error
121        }
122    }
123
124    #[doc(hidden)]
125    impl From<authorizer::AuthorizationError> for PolicyEvaluationError {
126        fn from(e: authorizer::AuthorizationError) -> Self {
127            match e {
128                authorizer::AuthorizationError::PolicyEvaluationError { id, error } => {
129                    Self { id, error }
130                }
131            }
132        }
133    }
134}
135
136#[doc(hidden)]
137impl From<authorizer::AuthorizationError> for AuthorizationError {
138    fn from(value: authorizer::AuthorizationError) -> Self {
139        Self::PolicyEvaluationError(value.into())
140    }
141}
142
143/// Errors that occur during concretizing a partial request
144#[derive(Debug, Diagnostic, Error)]
145#[error(transparent)]
146#[diagnostic(transparent)]
147pub struct ConcretizationError(pub(crate) cedar_policy_core::authorizer::ConcretizationError);
148
149/// Errors that can be encountered when re-evaluating a partial response
150#[derive(Debug, Diagnostic, Error)]
151pub enum ReauthorizationError {
152    /// An evaluation error was encountered
153    #[error(transparent)]
154    #[diagnostic(transparent)]
155    Evaluation(#[from] EvaluationError),
156    /// A policy set error was encountered
157    #[error(transparent)]
158    #[diagnostic(transparent)]
159    PolicySet(#[from] PolicySetError),
160    /// A request concretization error was encountered
161    #[error(transparent)]
162    #[diagnostic(transparent)]
163    Concretization(#[from] ConcretizationError),
164}
165
166#[doc(hidden)]
167impl From<cedar_policy_core::authorizer::ReauthorizationError> for ReauthorizationError {
168    fn from(e: cedar_policy_core::authorizer::ReauthorizationError) -> Self {
169        match e {
170            cedar_policy_core::authorizer::ReauthorizationError::PolicySetError(err) => {
171                Self::PolicySet(err.into())
172            }
173            cedar_policy_core::authorizer::ReauthorizationError::ConcretizationError(err) => {
174                Self::Concretization(ConcretizationError(err))
175            }
176        }
177    }
178}
179
180/// Errors serializing Schemas to the Cedar syntax
181#[derive(Debug, Error, Diagnostic)]
182#[non_exhaustive]
183pub enum ToCedarSchemaError {
184    /// Duplicate names were found in the schema
185    #[error(transparent)]
186    #[diagnostic(transparent)]
187    NameCollisions(#[from] to_cedar_syntax_errors::NameCollisionsError),
188    /// Entity type definitions with shapes not supported in Cedar schema syntax were found in the schema
189    #[diagnostic(transparent)]
190    #[error(transparent)]
191    UnconvertibleEntityTypeShape(#[from] to_cedar_syntax_errors::UnconvertibleEntityTypeShapeError),
192}
193
194/// Error subtypes for [`ToCedarSchemaError`]
195pub mod to_cedar_syntax_errors {
196    use miette::Diagnostic;
197    use thiserror::Error;
198
199    /// Duplicate names were found in the schema
200    #[derive(Debug, Error, Diagnostic)]
201    #[error("{err}")]
202    #[diagnostic(forward(err))]
203    pub struct NameCollisionsError {
204        pub(super) err: cedar_policy_core::validator::cedar_schema::fmt::NameCollisionsError,
205        // because `.names()` needs to return borrowed `&str`, we need somewhere to borrow from, hence here
206        pub(super) names_as_strings: Vec<String>,
207    }
208
209    impl NameCollisionsError {
210        /// Get the names that had collisions
211        pub fn names(&self) -> impl Iterator<Item = &str> {
212            self.names_as_strings
213                .iter()
214                .map(std::string::String::as_str)
215        }
216    }
217
218    /// Entity type definitions with shapes not supported in Cedar schema syntax were found in the schema
219    #[derive(Debug, Error, Diagnostic)]
220    #[error("{err}")]
221    #[diagnostic(forward(err))]
222    pub struct UnconvertibleEntityTypeShapeError {
223        pub(super) err:
224            cedar_policy_core::validator::cedar_schema::fmt::UnconvertibleEntityTypeShapeError,
225        // because `.names()` needs to return borrowed `&str`, we need somewhere to borrow from, hence here
226        pub(super) names_as_strings: Vec<String>,
227    }
228
229    impl UnconvertibleEntityTypeShapeError {
230        /// Get the names of the type definitions with shapes not supported in Cedar schema syntax.
231        pub fn names(&self) -> impl Iterator<Item = &str> {
232            self.names_as_strings
233                .iter()
234                .map(std::string::String::as_str)
235        }
236    }
237}
238
239#[doc(hidden)]
240impl From<cedar_policy_core::validator::cedar_schema::fmt::ToCedarSchemaSyntaxError>
241    for ToCedarSchemaError
242{
243    fn from(
244        value: cedar_policy_core::validator::cedar_schema::fmt::ToCedarSchemaSyntaxError,
245    ) -> Self {
246        match value {
247            cedar_policy_core::validator::cedar_schema::fmt::ToCedarSchemaSyntaxError::NameCollisions(
248                name_collision_err,
249            ) => NameCollisionsError {
250                names_as_strings: name_collision_err
251                    .names()
252                    .map(ToString::to_string)
253                    .collect(),
254                err: name_collision_err,
255            }
256            .into(),
257            cedar_policy_core::validator::cedar_schema::fmt::ToCedarSchemaSyntaxError::UnconvertibleEntityTypeShape(err) => UnconvertibleEntityTypeShapeError {
258                names_as_strings: err
259                    .names()
260                    .map(ToString::to_string)
261                    .collect(),
262                err,
263            }.into(),
264        }
265    }
266}
267
268/// Error subtypes for [`CedarSchemaError`]
269pub mod cedar_schema_errors {
270    use miette::Diagnostic;
271    use thiserror::Error;
272
273    pub use cedar_policy_core::validator::CedarSchemaParseError as ParseError;
274
275    /// IO error while parsing a Cedar schema
276    #[derive(Debug, Error, Diagnostic)]
277    #[error(transparent)]
278    pub struct IoError(#[from] pub(super) std::io::Error);
279}
280
281/// Errors when parsing schemas
282#[derive(Debug, Diagnostic, Error)]
283#[non_exhaustive]
284pub enum CedarSchemaError {
285    /// Error parsing a schema in the Cedar syntax
286    #[error(transparent)]
287    #[diagnostic(transparent)]
288    Parse(#[from] cedar_schema_errors::ParseError),
289    /// IO error while parsing a Cedar schema
290    #[error(transparent)]
291    #[diagnostic(transparent)]
292    Io(#[from] cedar_schema_errors::IoError),
293    /// Encountered a `SchemaError` while parsing a Cedar schema
294    #[error(transparent)]
295    #[diagnostic(transparent)]
296    Schema(#[from] SchemaError),
297}
298
299#[doc(hidden)]
300impl From<cedar_policy_core::validator::CedarSchemaError> for CedarSchemaError {
301    fn from(value: cedar_policy_core::validator::CedarSchemaError) -> Self {
302        match value {
303            cedar_policy_core::validator::CedarSchemaError::Schema(e) => e.into(),
304            cedar_policy_core::validator::CedarSchemaError::IO(e) => {
305                cedar_schema_errors::IoError(e).into()
306            }
307            cedar_policy_core::validator::CedarSchemaError::Parsing(e) => e.into(),
308        }
309    }
310}
311
312/// Error when evaluating an entity attribute or tag
313#[derive(Debug, Diagnostic, Error)]
314#[error("in {} `{attr_or_tag}` of `{uid}`: {err}", if *.was_attr { "attribute" } else { "tag" })]
315#[diagnostic(forward(err))]
316pub struct EntityAttrEvaluationError {
317    /// Action that had the attribute or tag with the error
318    uid: EntityUid,
319    /// Attribute or tag that had the error
320    attr_or_tag: SmolStr,
321    /// Is `attr_or_tag` an attribute (`true`) or a tag (`false`)
322    was_attr: bool,
323    /// Underlying evaluation error
324    err: EvaluationError,
325}
326
327impl EntityAttrEvaluationError {
328    /// Get the [`EntityUid`] of the action that had the attribute with the error
329    pub fn action(&self) -> &EntityUid {
330        &self.uid
331    }
332
333    /// Get the name of the attribute or tag that had the error
334    //
335    // Method is named `.attr()` and not `.attr_or_tag()` for historical / backwards-compatibility reasons
336    pub fn attr(&self) -> &SmolStr {
337        &self.attr_or_tag
338    }
339
340    /// Get the underlying evaluation error
341    pub fn inner(&self) -> &EvaluationError {
342        &self.err
343    }
344}
345
346#[doc(hidden)]
347impl From<ast::EntityAttrEvaluationError> for EntityAttrEvaluationError {
348    fn from(err: ast::EntityAttrEvaluationError) -> Self {
349        Self {
350            uid: err.uid.into(),
351            attr_or_tag: err.attr_or_tag,
352            was_attr: err.was_attr,
353            err: err.err,
354        }
355    }
356}
357
358/// Errors while trying to create a `Context`
359#[derive(Debug, Diagnostic, Error)]
360pub enum ContextCreationError {
361    /// Tried to create a `Context` out of something other than a record
362    #[error(transparent)]
363    #[diagnostic(transparent)]
364    NotARecord(context_creation_errors::NotARecord),
365    /// Error evaluating the expression given for the `Context`
366    #[error(transparent)]
367    #[diagnostic(transparent)]
368    Evaluation(#[from] EvaluationError),
369    /// Error constructing the expression given for the `Context`.
370    /// Only returned by `Context::from_pairs()`
371    #[error(transparent)]
372    #[diagnostic(transparent)]
373    ExpressionConstruction(#[from] ExpressionConstructionError),
374}
375
376#[doc(hidden)]
377impl From<ast::ContextCreationError> for ContextCreationError {
378    fn from(e: ast::ContextCreationError) -> Self {
379        match e {
380            ast::ContextCreationError::NotARecord(nre) => Self::NotARecord(nre),
381            ast::ContextCreationError::Evaluation(e) => Self::Evaluation(e),
382            ast::ContextCreationError::ExpressionConstruction(ece) => {
383                Self::ExpressionConstruction(ece)
384            }
385        }
386    }
387}
388
389/// Error subtypes for [`ContextCreationError`]
390mod context_creation_errors {
391    pub use cedar_policy_core::ast::context_creation_errors::NotARecord;
392}
393
394/// Error subtypes for [`ValidationError`].
395///
396/// Errors are primarily documented on their variants in [`ValidationError`].
397pub mod validation_errors;
398
399/// An error generated by the validator when it finds a potential problem in a
400/// policy.
401#[derive(Debug, Clone, Error, Diagnostic)]
402#[non_exhaustive]
403pub enum ValidationError {
404    /// A policy contains an entity type that is not declared in the schema.
405    #[error(transparent)]
406    #[diagnostic(transparent)]
407    UnrecognizedEntityType(#[from] validation_errors::UnrecognizedEntityType),
408    /// A policy contains an action that is not declared in the schema.
409    #[error(transparent)]
410    #[diagnostic(transparent)]
411    UnrecognizedActionId(#[from] validation_errors::UnrecognizedActionId),
412    /// There is no action satisfying the action scope constraint that can be
413    /// applied to a principal and resources that both satisfy their respective
414    /// scope conditions.
415    #[error(transparent)]
416    #[diagnostic(transparent)]
417    InvalidActionApplication(#[from] validation_errors::InvalidActionApplication),
418    /// The typechecker expected to see a subtype of one of the types in
419    /// `expected`, but saw `actual`.
420    #[error(transparent)]
421    #[diagnostic(transparent)]
422    UnexpectedType(#[from] validation_errors::UnexpectedType),
423    /// The typechecker could not compute a least upper bound for `types`.
424    #[error(transparent)]
425    #[diagnostic(transparent)]
426    IncompatibleTypes(#[from] validation_errors::IncompatibleTypes),
427    /// The typechecker detected an access to a record or entity attribute
428    /// that it could not statically guarantee would be present.
429    #[error(transparent)]
430    #[diagnostic(transparent)]
431    UnsafeAttributeAccess(#[from] validation_errors::UnsafeAttributeAccess),
432    /// The typechecker could not conclude that an access to an optional
433    /// attribute was safe.
434    #[error(transparent)]
435    #[diagnostic(transparent)]
436    UnsafeOptionalAttributeAccess(#[from] validation_errors::UnsafeOptionalAttributeAccess),
437    /// The typechecker could not conclude that an access to a tag was safe.
438    #[error(transparent)]
439    #[diagnostic(transparent)]
440    UnsafeTagAccess(#[from] validation_errors::UnsafeTagAccess),
441    /// `.getTag()` on an entity type which cannot have tags according to the schema.
442    #[error(transparent)]
443    #[diagnostic(transparent)]
444    NoTagsAllowed(#[from] validation_errors::NoTagsAllowed),
445    /// Undefined extension function.
446    #[error(transparent)]
447    #[diagnostic(transparent)]
448    UndefinedFunction(#[from] validation_errors::UndefinedFunction),
449    /// Incorrect number of arguments in an extension function application.
450    #[error(transparent)]
451    #[diagnostic(transparent)]
452    WrongNumberArguments(#[from] validation_errors::WrongNumberArguments),
453    /// Error returned by custom extension function argument validation
454    #[diagnostic(transparent)]
455    #[error(transparent)]
456    FunctionArgumentValidation(#[from] validation_errors::FunctionArgumentValidation),
457    /// Error returned when an empty set literal is found in a policy.
458    #[diagnostic(transparent)]
459    #[error(transparent)]
460    EmptySetForbidden(#[from] validation_errors::EmptySetForbidden),
461    /// Error returned when an extension constructor is applied to an non-literal expression.
462    #[diagnostic(transparent)]
463    #[error(transparent)]
464    NonLitExtConstructor(#[from] validation_errors::NonLitExtConstructor),
465    /// This error type is no longer ever returned, but remains here for
466    /// backwards-compatibility (removing the variant entirely would be a
467    /// breaking change).
468    #[error(transparent)]
469    #[diagnostic(transparent)]
470    HierarchyNotRespected(#[from] validation_errors::HierarchyNotRespected),
471    /// Returned when an internal invariant is violated (should not happen; if
472    /// this is ever returned, please file an issue)
473    #[error(transparent)]
474    #[diagnostic(transparent)]
475    InternalInvariantViolation(#[from] validation_errors::InternalInvariantViolation),
476    /// Entity level violation
477    #[error(transparent)]
478    #[diagnostic(transparent)]
479    EntityDerefLevelViolation(#[from] validation_errors::EntityDerefLevelViolation),
480    /// Returned when an entity is of an enumerated entity type but has invalid EID
481    #[error(transparent)]
482    #[diagnostic(transparent)]
483    InvalidEnumEntity(#[from] validation_errors::InvalidEnumEntity),
484}
485
486impl ValidationError {
487    /// Extract the policy id of the policy where the validator found the issue.
488    pub fn policy_id(&self) -> &crate::PolicyId {
489        match self {
490            Self::UnrecognizedEntityType(e) => e.policy_id(),
491            Self::UnrecognizedActionId(e) => e.policy_id(),
492            Self::InvalidActionApplication(e) => e.policy_id(),
493            Self::UnexpectedType(e) => e.policy_id(),
494            Self::IncompatibleTypes(e) => e.policy_id(),
495            Self::UnsafeAttributeAccess(e) => e.policy_id(),
496            Self::UnsafeOptionalAttributeAccess(e) => e.policy_id(),
497            Self::UnsafeTagAccess(e) => e.policy_id(),
498            Self::NoTagsAllowed(e) => e.policy_id(),
499            Self::UndefinedFunction(e) => e.policy_id(),
500            Self::WrongNumberArguments(e) => e.policy_id(),
501            Self::FunctionArgumentValidation(e) => e.policy_id(),
502            Self::EmptySetForbidden(e) => e.policy_id(),
503            Self::NonLitExtConstructor(e) => e.policy_id(),
504            Self::HierarchyNotRespected(e) => e.policy_id(),
505            Self::InternalInvariantViolation(e) => e.policy_id(),
506            Self::EntityDerefLevelViolation(e) => e.policy_id(),
507            Self::InvalidEnumEntity(e) => e.policy_id(),
508        }
509    }
510}
511
512#[doc(hidden)]
513impl From<cedar_policy_core::validator::ValidationError> for ValidationError {
514    fn from(error: cedar_policy_core::validator::ValidationError) -> Self {
515        match error {
516            cedar_policy_core::validator::ValidationError::UnrecognizedEntityType(e) => {
517                Self::UnrecognizedEntityType(e.into())
518            }
519            cedar_policy_core::validator::ValidationError::UnrecognizedActionId(e) => {
520                Self::UnrecognizedActionId(e.into())
521            }
522            cedar_policy_core::validator::ValidationError::InvalidActionApplication(e) => {
523                Self::InvalidActionApplication(e.into())
524            }
525            cedar_policy_core::validator::ValidationError::UnexpectedType(e) => {
526                Self::UnexpectedType(e.into())
527            }
528            cedar_policy_core::validator::ValidationError::IncompatibleTypes(e) => {
529                Self::IncompatibleTypes(e.into())
530            }
531            cedar_policy_core::validator::ValidationError::UnsafeAttributeAccess(e) => {
532                Self::UnsafeAttributeAccess(e.into())
533            }
534            cedar_policy_core::validator::ValidationError::UnsafeOptionalAttributeAccess(e) => {
535                Self::UnsafeOptionalAttributeAccess(e.into())
536            }
537            cedar_policy_core::validator::ValidationError::UnsafeTagAccess(e) => {
538                Self::UnsafeTagAccess(e.into())
539            }
540            cedar_policy_core::validator::ValidationError::NoTagsAllowed(e) => {
541                Self::NoTagsAllowed(e.into())
542            }
543            cedar_policy_core::validator::ValidationError::UndefinedFunction(e) => {
544                Self::UndefinedFunction(e.into())
545            }
546            cedar_policy_core::validator::ValidationError::WrongNumberArguments(e) => {
547                Self::WrongNumberArguments(e.into())
548            }
549            cedar_policy_core::validator::ValidationError::FunctionArgumentValidation(e) => {
550                Self::FunctionArgumentValidation(e.into())
551            }
552            cedar_policy_core::validator::ValidationError::EmptySetForbidden(e) => {
553                Self::EmptySetForbidden(e.into())
554            }
555            cedar_policy_core::validator::ValidationError::NonLitExtConstructor(e) => {
556                Self::NonLitExtConstructor(e.into())
557            }
558            cedar_policy_core::validator::ValidationError::InternalInvariantViolation(e) => {
559                Self::InternalInvariantViolation(e.into())
560            }
561            cedar_policy_core::validator::ValidationError::InvalidEnumEntity(e) => {
562                Self::InvalidEnumEntity(e.into())
563            }
564            cedar_policy_core::validator::ValidationError::EntityDerefLevelViolation(e) => {
565                Self::EntityDerefLevelViolation(e.into())
566            }
567        }
568    }
569}
570
571/// Error subtypes for [`ValidationWarning`].
572///
573/// Validation warnings are primarily documented on their variants in [`ValidationWarning`].
574pub mod validation_warnings;
575
576/// Represents the different kinds of validation warnings and information
577/// specific to that warning.
578///
579/// Marked as `non_exhaustive` to allow adding additional warnings in the future
580/// as a non-breaking change.
581#[derive(Debug, Clone, Error, Diagnostic)]
582#[non_exhaustive]
583pub enum ValidationWarning {
584    /// A string contains a mix of characters for different scripts (e.g., latin
585    /// and cyrillic alphabets). Different scripts can contain visually similar
586    /// characters which may be confused for each other.
587    #[diagnostic(transparent)]
588    #[error(transparent)]
589    MixedScriptString(#[from] validation_warnings::MixedScriptString),
590    /// A string contains bidirectional text control characters. These can be used to create crafted pieces of code that obfuscate true control flow.
591    #[diagnostic(transparent)]
592    #[error(transparent)]
593    BidiCharsInString(#[from] validation_warnings::BidiCharsInString),
594    /// An id contains bidirectional text control characters. These can be used to create crafted pieces of code that obfuscate true control flow.
595    #[diagnostic(transparent)]
596    #[error(transparent)]
597    BidiCharsInIdentifier(#[from] validation_warnings::BidiCharsInIdentifier),
598    /// An id contains a mix of characters for different scripts (e.g., latin and
599    /// cyrillic alphabets). Different scripts can contain visually similar
600    /// characters which may be confused for each other.
601    #[diagnostic(transparent)]
602    #[error(transparent)]
603    MixedScriptIdentifier(#[from] validation_warnings::MixedScriptIdentifier),
604    /// An id contains characters that is not a [graphical ASCII character](https://doc.rust-lang.org/std/primitive.char.html#method.is_ascii_graphic),
605    /// not the space character (`U+0020`), and falls outside of the General
606    /// Security Profile for Identifiers. We recommend adhering to this if
607    /// possible. See [Unicode® Technical Standard #39](https://unicode.org/reports/tr39/#General_Security_Profile) for more information.
608    #[diagnostic(transparent)]
609    #[error(transparent)]
610    ConfusableIdentifier(#[from] validation_warnings::ConfusableIdentifier),
611    /// The typechecker found that a policy condition will always evaluate to false.
612    #[diagnostic(transparent)]
613    #[error(transparent)]
614    ImpossiblePolicy(#[from] validation_warnings::ImpossiblePolicy),
615}
616
617impl ValidationWarning {
618    /// Extract the policy id of the policy where the validator found the issue.
619    pub fn policy_id(&self) -> &PolicyId {
620        match self {
621            Self::MixedScriptString(w) => w.policy_id(),
622            Self::BidiCharsInString(w) => w.policy_id(),
623            Self::BidiCharsInIdentifier(w) => w.policy_id(),
624            Self::MixedScriptIdentifier(w) => w.policy_id(),
625            Self::ConfusableIdentifier(w) => w.policy_id(),
626            Self::ImpossiblePolicy(w) => w.policy_id(),
627        }
628    }
629}
630
631#[doc(hidden)]
632impl From<cedar_policy_core::validator::ValidationWarning> for ValidationWarning {
633    fn from(warning: cedar_policy_core::validator::ValidationWarning) -> Self {
634        match warning {
635            cedar_policy_core::validator::ValidationWarning::MixedScriptString(w) => {
636                Self::MixedScriptString(w.into())
637            }
638            cedar_policy_core::validator::ValidationWarning::BidiCharsInString(w) => {
639                Self::BidiCharsInString(w.into())
640            }
641            cedar_policy_core::validator::ValidationWarning::BidiCharsInIdentifier(w) => {
642                Self::BidiCharsInIdentifier(w.into())
643            }
644            cedar_policy_core::validator::ValidationWarning::MixedScriptIdentifier(w) => {
645                Self::MixedScriptIdentifier(w.into())
646            }
647            cedar_policy_core::validator::ValidationWarning::ConfusableIdentifier(w) => {
648                Self::ConfusableIdentifier(w.into())
649            }
650            cedar_policy_core::validator::ValidationWarning::ImpossiblePolicy(w) => {
651                Self::ImpossiblePolicy(w.into())
652            }
653        }
654    }
655}
656
657/// Error subtypes for [`PolicySetError`]
658pub mod policy_set_errors {
659    use super::Error;
660    use crate::PolicyId;
661    use cedar_policy_core::ast;
662    use miette::Diagnostic;
663
664    /// There was a duplicate [`PolicyId`] encountered in either the set of
665    /// templates or the set of policies.
666    #[derive(Debug, Diagnostic, Error)]
667    #[error("duplicate template or policy id `{id}`")]
668    pub struct AlreadyDefined {
669        pub(crate) id: PolicyId,
670    }
671
672    impl AlreadyDefined {
673        /// Get the [`PolicyId`] for which there was a duplicate
674        pub fn duplicate_id(&self) -> &PolicyId {
675            &self.id
676        }
677    }
678
679    /// Error when linking a template
680    #[derive(Debug, Diagnostic, Error)]
681    #[error("unable to link template")]
682    #[diagnostic(transparent)]
683    pub struct LinkingError {
684        #[from]
685        pub(crate) inner: ast::LinkingError,
686    }
687
688    /// Expected a static policy, but a template-linked policy was provided
689    #[derive(Debug, Diagnostic, Error)]
690    #[error("expected a static policy, but a template-linked policy was provided")]
691    pub struct ExpectedStatic {
692        /// A private field, just so the public interface notes this as a
693        /// private-fields struct and not a empty-fields struct for semver
694        /// purposes (e.g., consumers cannot construct this type with
695        /// `ExpectedStatic {}`)
696        _dummy: (),
697    }
698
699    impl ExpectedStatic {
700        pub(crate) fn new() -> Self {
701            Self { _dummy: () }
702        }
703    }
704
705    /// Expected a template, but a static policy was provided.
706    #[derive(Debug, Diagnostic, Error)]
707    #[error("expected a template, but a static policy was provided")]
708    pub struct ExpectedTemplate {
709        /// A private field, just so the public interface notes this as a
710        /// private-fields struct and not a empty-fields struct for semver
711        /// purposes (e.g., consumers cannot construct this type with
712        /// `ExpectedTemplate {}`)
713        _dummy: (),
714    }
715
716    impl ExpectedTemplate {
717        pub(crate) fn new() -> Self {
718            Self { _dummy: () }
719        }
720    }
721
722    /// Error when removing a static policy that doesn't exist
723    #[derive(Debug, Diagnostic, Error)]
724    #[error("unable to remove static policy `{policy_id}` because it does not exist")]
725    pub struct PolicyNonexistentError {
726        pub(crate) policy_id: PolicyId,
727    }
728
729    impl PolicyNonexistentError {
730        /// Get the [`PolicyId`] of the policy which didn't exist
731        pub fn policy_id(&self) -> &PolicyId {
732            &self.policy_id
733        }
734    }
735
736    /// Error when removing a template that doesn't exist
737    #[derive(Debug, Diagnostic, Error)]
738    #[error("unable to remove template `{template_id}` because it does not exist")]
739    pub struct TemplateNonexistentError {
740        pub(crate) template_id: PolicyId,
741    }
742
743    impl TemplateNonexistentError {
744        /// Get the [`PolicyId`] of the template which didn't exist
745        pub fn template_id(&self) -> &PolicyId {
746            &self.template_id
747        }
748    }
749
750    /// Error when removing a template with active links
751    #[derive(Debug, Diagnostic, Error)]
752    #[error("unable to remove policy template `{template_id}` because it has active links")]
753    pub struct RemoveTemplateWithActiveLinksError {
754        pub(crate) template_id: PolicyId,
755    }
756
757    impl RemoveTemplateWithActiveLinksError {
758        /// Get the [`PolicyId`] of the template which had active links
759        pub fn template_id(&self) -> &PolicyId {
760            &self.template_id
761        }
762    }
763
764    /// Error when removing a template that is not a template
765    #[derive(Debug, Diagnostic, Error)]
766    #[error("unable to remove policy template `{template_id}` because it is not a template")]
767    pub struct RemoveTemplateNotTemplateError {
768        pub(crate) template_id: PolicyId,
769    }
770
771    impl RemoveTemplateNotTemplateError {
772        /// Get the [`PolicyId`] of the template which is not a template
773        pub fn template_id(&self) -> &PolicyId {
774            &self.template_id
775        }
776    }
777
778    /// Error when unlinking a template-linked policy
779    #[derive(Debug, Diagnostic, Error)]
780    #[error("unable to unlink policy `{policy_id}` because it does not exist")]
781    pub struct LinkNonexistentError {
782        pub(crate) policy_id: PolicyId,
783    }
784
785    impl LinkNonexistentError {
786        /// Get the [`PolicyId`] of the link which does not exist
787        pub fn policy_id(&self) -> &PolicyId {
788            &self.policy_id
789        }
790    }
791
792    /// Error when removing a link that is not a link
793    #[derive(Debug, Diagnostic, Error)]
794    #[error("unable to unlink `{policy_id}` because it is not a link")]
795    pub struct UnlinkLinkNotLinkError {
796        pub(crate) policy_id: PolicyId,
797    }
798
799    impl UnlinkLinkNotLinkError {
800        /// Get the [`PolicyId`] of the link which is not a link
801        pub fn policy_id(&self) -> &PolicyId {
802            &self.policy_id
803        }
804    }
805
806    /// Error during JSON ser/de of the policy set (as opposed to individual policies)
807    #[derive(Debug, Diagnostic, Error)]
808    #[error("error serializing/deserializing policy set to/from JSON")]
809    pub struct JsonPolicySetError {
810        #[from]
811        pub(crate) inner: serde_json::Error,
812    }
813}
814
815/// Potential errors when adding to a `PolicySet`.
816#[derive(Debug, Diagnostic, Error)]
817#[non_exhaustive]
818pub enum PolicySetError {
819    /// There was a duplicate [`PolicyId`] encountered in either the set of
820    /// templates or the set of policies.
821    #[error(transparent)]
822    #[diagnostic(transparent)]
823    AlreadyDefined(#[from] policy_set_errors::AlreadyDefined),
824    /// Error when linking a template
825    #[error(transparent)]
826    #[diagnostic(transparent)]
827    Linking(#[from] policy_set_errors::LinkingError),
828    /// Expected a static policy, but a template-linked policy was provided
829    #[error(transparent)]
830    #[diagnostic(transparent)]
831    ExpectedStatic(#[from] policy_set_errors::ExpectedStatic),
832    /// Expected a template, but a static policy was provided.
833    #[error(transparent)]
834    #[diagnostic(transparent)]
835    ExpectedTemplate(#[from] policy_set_errors::ExpectedTemplate),
836    /// Error when removing a static policy that doesn't exist
837    #[error(transparent)]
838    #[diagnostic(transparent)]
839    PolicyNonexistent(#[from] policy_set_errors::PolicyNonexistentError),
840    /// Error when removing a template that doesn't exist
841    #[error(transparent)]
842    #[diagnostic(transparent)]
843    TemplateNonexistent(#[from] policy_set_errors::TemplateNonexistentError),
844    /// Error when removing a template with active links
845    #[error(transparent)]
846    #[diagnostic(transparent)]
847    RemoveTemplateWithActiveLinks(#[from] policy_set_errors::RemoveTemplateWithActiveLinksError),
848    /// Error when removing a template that is not a template
849    #[error(transparent)]
850    #[diagnostic(transparent)]
851    RemoveTemplateNotTemplate(#[from] policy_set_errors::RemoveTemplateNotTemplateError),
852    /// Error when unlinking a linked policy
853    #[error(transparent)]
854    #[diagnostic(transparent)]
855    LinkNonexistent(#[from] policy_set_errors::LinkNonexistentError),
856    /// Error when removing a link that is not a link
857    #[error(transparent)]
858    #[diagnostic(transparent)]
859    UnlinkLinkNotLink(#[from] policy_set_errors::UnlinkLinkNotLinkError),
860    /// Error when converting a policy/template from JSON format
861    #[error(transparent)]
862    #[diagnostic(transparent)]
863    FromJson(#[from] PolicyFromJsonError),
864    /// Error when converting a policy/template to JSON format
865    #[error("Error serializing a policy/template to JSON")]
866    #[diagnostic(transparent)]
867    ToJson(#[from] PolicyToJsonError),
868    /// Error during JSON ser/de of the policy set (as opposed to individual policies)
869    #[error(transparent)]
870    #[diagnostic(transparent)]
871    JsonPolicySet(#[from] policy_set_errors::JsonPolicySetError),
872    /// Error when converting from PST representation
873    #[error(transparent)]
874    #[diagnostic(transparent)]
875    PstConversion(#[from] pst::PstConstructionError),
876}
877
878#[doc(hidden)]
879impl From<ast::PolicySetError> for PolicySetError {
880    fn from(e: ast::PolicySetError) -> Self {
881        match e {
882            ast::PolicySetError::Occupied { id } => {
883                Self::AlreadyDefined(policy_set_errors::AlreadyDefined {
884                    id: PolicyId::new(id),
885                })
886            }
887        }
888    }
889}
890
891#[doc(hidden)]
892impl From<ast::LinkingError> for PolicySetError {
893    fn from(e: ast::LinkingError) -> Self {
894        Self::Linking(e.into())
895    }
896}
897
898#[doc(hidden)]
899impl From<ast::UnexpectedSlotError> for PolicySetError {
900    fn from(_: ast::UnexpectedSlotError) -> Self {
901        Self::ExpectedStatic(policy_set_errors::ExpectedStatic::new())
902    }
903}
904
905#[doc(hidden)]
906impl From<est::PolicySetFromJsonError> for PolicySetError {
907    fn from(e: est::PolicySetFromJsonError) -> Self {
908        match e {
909            est::PolicySetFromJsonError::PolicySet(e) => e.into(),
910            est::PolicySetFromJsonError::Linking(e) => e.into(),
911            est::PolicySetFromJsonError::FromJsonError(e) => Self::FromJson(e.into()),
912        }
913    }
914}
915
916/// Represents one or more [`ParseError`]s encountered when parsing a policy or
917/// expression.
918///
919/// By default, the `Diagnostic` and `Error` implementations will only print the
920/// first error. If you want to see all errors, use `.iter()` or `.into_iter()`.
921#[derive(Debug, Diagnostic, Error)]
922#[error(transparent)]
923#[diagnostic(transparent)]
924pub struct ParseErrors(#[from] cedar_policy_core::parser::err::ParseErrors);
925
926impl ParseErrors {
927    /// Get every [`ParseError`] associated with this [`ParseErrors`] object.
928    /// The returned iterator is guaranteed to be nonempty.
929    pub fn iter(&self) -> impl Iterator<Item = &ParseError> {
930        self.0.iter().map(ParseError::ref_cast)
931    }
932}
933
934/// Errors that can occur when parsing policies or expressions.
935///
936/// Marked as `non_exhaustive` to support adding additional error information
937/// in the future without a major version bump.
938#[derive(Debug, Diagnostic, Error, RefCast)]
939#[repr(transparent)]
940#[error(transparent)]
941#[diagnostic(transparent)]
942#[non_exhaustive]
943pub struct ParseError {
944    #[from]
945    inner: cedar_policy_core::parser::err::ParseError,
946}
947
948/// Errors that can happen when getting the JSON representation of a policy
949#[derive(Debug, Diagnostic, Error)]
950pub enum PolicyToJsonError {
951    /// Parse error in the policy text
952    #[error(transparent)]
953    #[diagnostic(transparent)]
954    Parse(#[from] ParseErrors),
955    /// For linked policies, error linking the JSON representation
956    #[error(transparent)]
957    #[diagnostic(transparent)]
958    Link(#[from] policy_to_json_errors::JsonLinkError),
959    /// Error in the JSON serialization
960    #[error(transparent)]
961    JsonSerialization(#[from] policy_to_json_errors::PolicyJsonSerializationError),
962}
963
964#[doc(hidden)]
965impl From<est::LinkingError> for PolicyToJsonError {
966    fn from(e: est::LinkingError) -> Self {
967        policy_to_json_errors::JsonLinkError::from(e).into()
968    }
969}
970
971impl From<serde_json::Error> for PolicyToJsonError {
972    fn from(e: serde_json::Error) -> Self {
973        policy_to_json_errors::PolicyJsonSerializationError::from(e).into()
974    }
975}
976
977impl From<pst::PstConstructionError> for PolicyToJsonError {
978    fn from(e: pst::PstConstructionError) -> Self {
979        Self::JsonSerialization(serde_json::Error::custom(e.to_string()).into())
980    }
981}
982
983/// Error subtypes for [`PolicyToJsonError`]
984pub mod policy_to_json_errors {
985    use cedar_policy_core::est;
986    use miette::Diagnostic;
987    use thiserror::Error;
988
989    /// Error linking the JSON representation of a linked policy
990    #[derive(Debug, Diagnostic, Error)]
991    #[error(transparent)]
992    #[diagnostic(transparent)]
993    pub struct JsonLinkError {
994        /// Underlying error
995        #[from]
996        err: est::LinkingError,
997    }
998
999    /// Error serializing a policy as JSON
1000    #[derive(Debug, Diagnostic, Error)]
1001    #[error(transparent)]
1002    pub struct PolicyJsonSerializationError {
1003        /// Underlying error
1004        #[from]
1005        err: serde_json::Error,
1006    }
1007}
1008
1009/// Error when converting a policy or template from JSON format
1010#[derive(Debug, Diagnostic, Error)]
1011#[error("error deserializing a policy/template from JSON")]
1012#[diagnostic(transparent)]
1013pub struct PolicyFromJsonError {
1014    #[from]
1015    pub(crate) inner: cedar_policy_core::est::FromJsonError,
1016}
1017
1018/// Error type for parsing `Context` from JSON
1019#[derive(Debug, Diagnostic, Error)]
1020pub enum ContextJsonError {
1021    /// Error deserializing the JSON into a [`crate::Context`]
1022    #[error(transparent)]
1023    #[diagnostic(transparent)]
1024    JsonDeserialization(#[from] entities_json_errors::JsonDeserializationError),
1025    /// Error constructing the [`crate::Context`] itself
1026    #[error(transparent)]
1027    #[diagnostic(transparent)]
1028    ContextCreation(#[from] ContextCreationError),
1029    /// The supplied action doesn't exist in the supplied schema
1030    #[error(transparent)]
1031    #[diagnostic(transparent)]
1032    MissingAction(#[from] context_json_errors::MissingActionError),
1033}
1034
1035impl ContextJsonError {
1036    /// Construct a `ContextJsonError::MissingAction`
1037    pub(crate) fn missing_action(action: EntityUid) -> Self {
1038        Self::MissingAction(context_json_errors::MissingActionError { action })
1039    }
1040}
1041
1042#[doc(hidden)]
1043impl From<cedar_policy_core::entities::json::ContextJsonDeserializationError> for ContextJsonError {
1044    fn from(e: cedar_policy_core::entities::json::ContextJsonDeserializationError) -> Self {
1045        match e {
1046            cedar_policy_core::entities::json::ContextJsonDeserializationError::JsonDeserialization(e) => Self::JsonDeserialization(e),
1047            cedar_policy_core::entities::json::ContextJsonDeserializationError::ContextCreation(e) => Self::ContextCreation(e.into())
1048        }
1049    }
1050}
1051
1052/// Error subtypes for [`ContextJsonError`]
1053pub mod context_json_errors {
1054    use super::EntityUid;
1055    use miette::Diagnostic;
1056    use thiserror::Error;
1057
1058    /// The supplied action doesn't exist in the supplied schema
1059    #[derive(Debug, Diagnostic, Error)]
1060    #[error("action `{action}` does not exist in the supplied schema")]
1061    pub struct MissingActionError {
1062        /// UID of the action which doesn't exist
1063        pub(super) action: EntityUid,
1064    }
1065
1066    impl MissingActionError {
1067        /// Get the [`EntityUid`] of the action which doesn't exist
1068        pub fn action(&self) -> &EntityUid {
1069            &self.action
1070        }
1071    }
1072}
1073
1074/// Error type for parsing a `RestrictedExpression`
1075#[derive(Debug, Diagnostic, Error)]
1076#[non_exhaustive]
1077pub enum RestrictedExpressionParseError {
1078    /// Failed to parse the expression
1079    #[error(transparent)]
1080    #[diagnostic(transparent)]
1081    Parse(#[from] ParseErrors),
1082    /// Parsed successfully as an expression, but failed to construct a
1083    /// restricted expression, for the reason indicated in the underlying error
1084    #[error(transparent)]
1085    #[diagnostic(transparent)]
1086    InvalidRestrictedExpression(#[from] RestrictedExpressionError),
1087}
1088
1089#[doc(hidden)]
1090impl From<cedar_policy_core::ast::RestrictedExpressionParseError>
1091    for RestrictedExpressionParseError
1092{
1093    fn from(e: cedar_policy_core::ast::RestrictedExpressionParseError) -> Self {
1094        match e {
1095            cedar_policy_core::ast::RestrictedExpressionParseError::Parse(e) => {
1096                Self::Parse(e.into())
1097            }
1098            cedar_policy_core::ast::RestrictedExpressionParseError::InvalidRestrictedExpression(
1099                e,
1100            ) => e.into(),
1101        }
1102    }
1103}
1104
1105/// The request does not conform to the schema
1106#[derive(Debug, Diagnostic, Error)]
1107#[non_exhaustive]
1108pub enum RequestValidationError {
1109    /// Request action is not declared in the schema
1110    #[error(transparent)]
1111    #[diagnostic(transparent)]
1112    UndeclaredAction(#[from] request_validation_errors::UndeclaredActionError),
1113    /// Request principal is of a type not declared in the schema
1114    #[error(transparent)]
1115    #[diagnostic(transparent)]
1116    UndeclaredPrincipalType(#[from] request_validation_errors::UndeclaredPrincipalTypeError),
1117    /// Request resource is of a type not declared in the schema
1118    #[error(transparent)]
1119    #[diagnostic(transparent)]
1120    UndeclaredResourceType(#[from] request_validation_errors::UndeclaredResourceTypeError),
1121    /// Request principal is of a type that is declared in the schema, but is
1122    /// not valid for the request action
1123    #[error(transparent)]
1124    #[diagnostic(transparent)]
1125    InvalidPrincipalType(#[from] request_validation_errors::InvalidPrincipalTypeError),
1126    /// Request resource is of a type that is declared in the schema, but is
1127    /// not valid for the request action
1128    #[error(transparent)]
1129    #[diagnostic(transparent)]
1130    InvalidResourceType(#[from] request_validation_errors::InvalidResourceTypeError),
1131    /// Context does not comply with the shape specified for the request action
1132    #[error(transparent)]
1133    #[diagnostic(transparent)]
1134    InvalidContext(#[from] request_validation_errors::InvalidContextError),
1135    /// Error computing the type of the `Context`
1136    #[error(transparent)]
1137    #[diagnostic(transparent)]
1138    TypeOfContext(#[from] request_validation_errors::TypeOfContextError),
1139    /// Error when a principal or resource entity is of an enumerated entity
1140    /// type but has an invalid EID
1141    #[error(transparent)]
1142    #[diagnostic(transparent)]
1143    InvalidEnumEntity(#[from] request_validation_errors::InvalidEnumEntityError),
1144}
1145
1146#[doc(hidden)]
1147impl From<cedar_policy_core::validator::RequestValidationError> for RequestValidationError {
1148    fn from(e: cedar_policy_core::validator::RequestValidationError) -> Self {
1149        match e {
1150            cedar_policy_core::validator::RequestValidationError::UndeclaredAction(e) => {
1151                Self::UndeclaredAction(e.into())
1152            }
1153            cedar_policy_core::validator::RequestValidationError::UndeclaredPrincipalType(e) => {
1154                Self::UndeclaredPrincipalType(e.into())
1155            }
1156            cedar_policy_core::validator::RequestValidationError::UndeclaredResourceType(e) => {
1157                Self::UndeclaredResourceType(e.into())
1158            }
1159            cedar_policy_core::validator::RequestValidationError::InvalidPrincipalType(e) => {
1160                Self::InvalidPrincipalType(e.into())
1161            }
1162            cedar_policy_core::validator::RequestValidationError::InvalidResourceType(e) => {
1163                Self::InvalidResourceType(e.into())
1164            }
1165            cedar_policy_core::validator::RequestValidationError::InvalidContext(e) => {
1166                Self::InvalidContext(e.into())
1167            }
1168            cedar_policy_core::validator::RequestValidationError::TypeOfContext(e) => {
1169                Self::TypeOfContext(e.into())
1170            }
1171            cedar_policy_core::validator::RequestValidationError::InvalidEnumEntity(e) => {
1172                Self::InvalidEnumEntity(e.into())
1173            }
1174        }
1175    }
1176}
1177
1178/// Error subtypes for [`RequestValidationError`]
1179pub mod request_validation_errors {
1180    use cedar_policy_core::extensions::ExtensionFunctionLookupError;
1181    use miette::Diagnostic;
1182    use ref_cast::RefCast;
1183    use thiserror::Error;
1184
1185    use crate::{Context, EntityTypeName, EntityUid};
1186
1187    /// Request action is not declared in the schema
1188    #[derive(Debug, Diagnostic, Error)]
1189    #[error(transparent)]
1190    #[diagnostic(transparent)]
1191    pub struct UndeclaredActionError(
1192        #[from] cedar_policy_core::validator::request_validation_errors::UndeclaredActionError,
1193    );
1194
1195    impl UndeclaredActionError {
1196        /// The action which was not declared in the schema
1197        pub fn action(&self) -> &EntityUid {
1198            RefCast::ref_cast(self.0.action())
1199        }
1200    }
1201
1202    /// Request principal is of a type not declared in the schema
1203    #[derive(Debug, Diagnostic, Error)]
1204    #[error(transparent)]
1205    #[diagnostic(transparent)]
1206    pub struct UndeclaredPrincipalTypeError(
1207        #[from]
1208        cedar_policy_core::validator::request_validation_errors::UndeclaredPrincipalTypeError,
1209    );
1210
1211    impl UndeclaredPrincipalTypeError {
1212        /// The principal type which was not declared in the schema
1213        pub fn principal_ty(&self) -> &EntityTypeName {
1214            RefCast::ref_cast(self.0.principal_ty())
1215        }
1216    }
1217
1218    /// Request resource is of a type not declared in the schema
1219    #[derive(Debug, Diagnostic, Error)]
1220    #[error(transparent)]
1221    #[diagnostic(transparent)]
1222    pub struct UndeclaredResourceTypeError(
1223        #[from]
1224        cedar_policy_core::validator::request_validation_errors::UndeclaredResourceTypeError,
1225    );
1226
1227    impl UndeclaredResourceTypeError {
1228        /// The resource type which was not declared in the schema
1229        pub fn resource_ty(&self) -> &EntityTypeName {
1230            RefCast::ref_cast(self.0.resource_ty())
1231        }
1232    }
1233
1234    /// Request principal is of a type that is declared in the schema, but is
1235    /// not valid for the request action
1236    #[derive(Debug, Diagnostic, Error)]
1237    #[error(transparent)]
1238    #[diagnostic(transparent)]
1239    pub struct InvalidPrincipalTypeError(
1240        #[from] cedar_policy_core::validator::request_validation_errors::InvalidPrincipalTypeError,
1241    );
1242
1243    impl InvalidPrincipalTypeError {
1244        /// The principal type which is not valid
1245        pub fn principal_ty(&self) -> &EntityTypeName {
1246            RefCast::ref_cast(self.0.principal_ty())
1247        }
1248
1249        /// The action which it is not valid for
1250        pub fn action(&self) -> &EntityUid {
1251            RefCast::ref_cast(self.0.action())
1252        }
1253    }
1254
1255    /// Request resource is of a type that is declared in the schema, but is
1256    /// not valid for the request action
1257    #[derive(Debug, Diagnostic, Error)]
1258    #[error(transparent)]
1259    #[diagnostic(transparent)]
1260    pub struct InvalidResourceTypeError(
1261        #[from] cedar_policy_core::validator::request_validation_errors::InvalidResourceTypeError,
1262    );
1263
1264    impl InvalidResourceTypeError {
1265        /// The resource type which is not valid
1266        pub fn resource_ty(&self) -> &EntityTypeName {
1267            RefCast::ref_cast(self.0.resource_ty())
1268        }
1269
1270        /// The action which it is not valid for
1271        pub fn action(&self) -> &EntityUid {
1272            RefCast::ref_cast(self.0.action())
1273        }
1274    }
1275
1276    /// Context does not comply with the shape specified for the request action
1277    #[derive(Debug, Diagnostic, Error)]
1278    #[error(transparent)]
1279    #[diagnostic(transparent)]
1280    pub struct InvalidContextError(
1281        #[from] cedar_policy_core::validator::request_validation_errors::InvalidContextError,
1282    );
1283
1284    impl InvalidContextError {
1285        /// The context which is not valid
1286        pub fn context(&self) -> &Context {
1287            RefCast::ref_cast(self.0.context())
1288        }
1289
1290        /// The action which it is not valid for
1291        pub fn action(&self) -> &EntityUid {
1292            RefCast::ref_cast(self.0.action())
1293        }
1294    }
1295
1296    /// Error computing the type of the `Context`
1297    #[derive(Debug, Diagnostic, Error)]
1298    #[error(transparent)]
1299    #[diagnostic(transparent)]
1300    pub struct TypeOfContextError(#[from] ExtensionFunctionLookupError);
1301
1302    /// Error when a principal or resource entity is of an enumerated entity
1303    /// type but has an invalid EID
1304    #[derive(Debug, Diagnostic, Error)]
1305    #[error(transparent)]
1306    #[diagnostic(transparent)]
1307    pub struct InvalidEnumEntityError(
1308        #[from] cedar_policy_core::entities::conformance::err::InvalidEnumEntityError,
1309    );
1310}
1311
1312/// An error generated by entity slicing.
1313#[derive(Debug, Error, Diagnostic)]
1314#[non_exhaustive]
1315#[cfg(feature = "entity-manifest")]
1316pub enum EntityManifestError {
1317    /// A validation error was encountered
1318    #[error(transparent)]
1319    #[diagnostic(transparent)]
1320    Validation(#[from] ValidationResult),
1321    /// A entities error was encountered
1322    #[error(transparent)]
1323    #[diagnostic(transparent)]
1324    Entities(#[from] EntitiesError),
1325
1326    /// The request was partial
1327    #[error(transparent)]
1328    #[diagnostic(transparent)]
1329    PartialRequest(#[from] PartialRequestError),
1330    /// A policy was partial
1331    #[error(transparent)]
1332    #[diagnostic(transparent)]
1333    PartialExpression(#[from] PartialExpressionError),
1334    /// Encounters unsupported Cedar feature
1335    #[error(transparent)]
1336    #[diagnostic(transparent)]
1337    UnsupportedCedarFeature(#[from] UnsupportedCedarFeatureError),
1338}
1339
1340#[cfg(feature = "entity-manifest")]
1341impl From<entity_manifest::EntityManifestError> for EntityManifestError {
1342    fn from(e: entity_manifest::EntityManifestError) -> Self {
1343        match e {
1344            entity_manifest::EntityManifestError::Validation(e) => Self::Validation(e.into()),
1345            entity_manifest::EntityManifestError::Entities(e) => Self::Entities(e),
1346            entity_manifest::EntityManifestError::PartialRequest(e) => Self::PartialRequest(e),
1347            entity_manifest::EntityManifestError::PartialExpression(e) => {
1348                Self::PartialExpression(e)
1349            }
1350            entity_manifest::EntityManifestError::UnsupportedCedarFeature(e) => {
1351                Self::UnsupportedCedarFeature(e)
1352            }
1353        }
1354    }
1355}
1356
1357#[cfg(feature = "tpe")]
1358/// Error thrown when creating a `PartialRequest`
1359#[doc = include_str!("../../experimental_warning.md")]
1360#[derive(Debug, Error, Diagnostic)]
1361pub enum PartialRequestCreationError {
1362    /// When the context contains unknowns
1363    #[error("Context contains unknowns")]
1364    ContextContainsUnknowns,
1365    /// When the request does not pass validation
1366    #[error(transparent)]
1367    #[diagnostic(transparent)]
1368    Validation(#[from] RequestValidationError),
1369}
1370
1371#[cfg(feature = "tpe")]
1372/// Errors that can be encountered when re-evaluating a partial response
1373#[doc = include_str!("../../experimental_warning.md")]
1374#[derive(Debug, Error)]
1375pub enum TpeReauthorizationError {
1376    /// `Request` cannot be validated
1377    #[error(transparent)]
1378    RequestValidation(#[from] RequestValidationError),
1379    /// `Entities` cannot be validated
1380    #[error(transparent)]
1381    EntityValidation(#[from] EntitySchemaConformanceError),
1382    /// Inconsistent entities
1383    #[error(transparent)]
1384    InconsistentEntities(#[from] tpe_err::EntitiesConsistencyError),
1385    /// Inconsistent requests
1386    #[error(transparent)]
1387    InconsistentRequests(#[from] tpe_err::RequestConsistencyError),
1388}
1389
1390#[cfg(feature = "tpe")]
1391impl From<tpe_err::ReauthorizationError> for TpeReauthorizationError {
1392    fn from(value: tpe_err::ReauthorizationError) -> Self {
1393        match value {
1394            tpe_err::ReauthorizationError::EntitiesConsistentcy(e) => Self::InconsistentEntities(e),
1395            tpe_err::ReauthorizationError::EntityValidation(e) => Self::EntityValidation(e),
1396            tpe_err::ReauthorizationError::RequestConsistentcy(e) => Self::InconsistentRequests(e),
1397            tpe_err::ReauthorizationError::RequestValidation(e) => {
1398                Self::RequestValidation(e.into())
1399            }
1400        }
1401    }
1402}
1403
1404#[cfg(feature = "tpe")]
1405/// Errors that can be encountered when performing a permission query
1406#[doc = include_str!("../../experimental_warning.md")]
1407#[derive(Debug, Error)]
1408pub enum PermissionQueryError {
1409    /// When concrete entities fail to validate or contain unknowns
1410    #[error(transparent)]
1411    Entities(#[from] tpe_err::EntitiesError),
1412    /// When TPE fails
1413    #[error(transparent)]
1414    TPE(#[from] tpe_err::TpeError),
1415}
1416
1417#[cfg(feature = "tpe")]
1418#[doc = include_str!("../../experimental_warning.md")]
1419/// Error when constructing [`crate::PartialEntity`]
1420#[derive(Debug, Error)]
1421pub enum PartialEntityError {
1422    /// An evaluation error was encountered
1423    #[error(transparent)]
1424    Evaluation(#[from] EvaluationError),
1425    /// Fail to construct a [`crate::PartialEntity`]
1426    #[error(transparent)]
1427    Entities(#[from] tpe_err::EntitiesError),
1428}