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

miette integration for all errors in Core, Validator, and cedar-policy #477

Merged
merged 14 commits into from
Dec 8, 2023
39 changes: 0 additions & 39 deletions cedar-policy-cli/src/err.rs

This file was deleted.

92 changes: 36 additions & 56 deletions cedar-policy-cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@
// omitted.
#![allow(clippy::needless_return)]

mod err;

use clap::{ArgAction, Args, Parser, Subcommand, ValueEnum};
use miette::{miette, IntoDiagnostic, NamedSource, Report, Result, WrapErr};
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -197,7 +195,6 @@ impl RequestArgs {
qjson.context,
schema.and_then(|s| Some((s, action.as_ref()?))),
)
.into_diagnostic()
.wrap_err_with(|| format!("failed to create a context from {jsonfile}"))?;
Request::new(
principal,
Expand Down Expand Up @@ -245,7 +242,6 @@ impl RequestArgs {
f,
schema.and_then(|s| Some((s, action.as_ref()?))),
)
.into_diagnostic()
.wrap_err_with(|| format!("failed to create a context from {jsonfile}"))?,
Err(e) => Err(e).into_diagnostic().wrap_err_with(|| {
format!("error while loading context from {jsonfile}")
Expand Down Expand Up @@ -430,7 +426,7 @@ pub fn check_parse(args: &CheckParseArgs) -> CedarExitCode {
match read_policy_set(args.policies_file.as_ref()) {
Ok(_) => CedarExitCode::Success,
Err(e) => {
println!("Error: {e:?}");
println!("{e:?}");
CedarExitCode::Failure
}
}
Expand All @@ -452,15 +448,15 @@ pub fn validate(args: &ValidateArgs) -> CedarExitCode {
let pset = match read_policy_set(Some(&args.policies_file)) {
Ok(pset) => pset,
Err(e) => {
println!("Error: {e:?}");
println!("{e:?}");
return CedarExitCode::Failure;
}
};

let schema = match read_schema_file(&args.schema_file) {
Ok(schema) => schema,
Err(e) => {
println!("Error: {e:?}");
println!("{e:?}");
return CedarExitCode::Failure;
}
};
Expand Down Expand Up @@ -503,22 +499,22 @@ pub fn evaluate(args: &EvaluateArgs) -> (CedarExitCode, EvalResult) {
None => None,
Some(Ok(schema)) => Some(schema),
Some(Err(e)) => {
println!("Error: {e:?}");
println!("{e:?}");
return (CedarExitCode::Failure, EvalResult::Bool(false));
}
};
let request = match args.request.get_request(schema.as_ref()) {
Ok(q) => q,
Err(e) => {
println!("Error: {e:?}");
println!("{e:?}");
return (CedarExitCode::Failure, EvalResult::Bool(false));
}
};
let expr =
match Expression::from_str(&args.expression).wrap_err("failed to parse the expression") {
Ok(expr) => expr,
Err(e) => {
println!("Error: {e:?}");
println!("{e:?}");
return (CedarExitCode::Failure, EvalResult::Bool(false));
}
};
Expand All @@ -527,17 +523,15 @@ pub fn evaluate(args: &EvaluateArgs) -> (CedarExitCode, EvalResult) {
Some(file) => match load_entities(file, schema.as_ref()) {
Ok(entities) => entities,
Err(e) => {
println!("Error: {e:?}");
println!("{e:?}");
return (CedarExitCode::Failure, EvalResult::Bool(false));
}
},
};
match eval_expression(&request, &entities, &expr)
.into_diagnostic()
.wrap_err("failed to evaluate the expression")
match eval_expression(&request, &entities, &expr).wrap_err("failed to evaluate the expression")
{
Err(e) => {
println!("Error: {e:?}");
println!("{e:?}");
return (CedarExitCode::Failure, EvalResult::Bool(false));
}
Ok(result) => {
Expand All @@ -549,7 +543,7 @@ pub fn evaluate(args: &EvaluateArgs) -> (CedarExitCode, EvalResult) {

pub fn link(args: &LinkArgs) -> CedarExitCode {
if let Err(err) = link_inner(args) {
println!("Error: {err:?}");
println!("{err:?}");
CedarExitCode::Failure
} else {
CedarExitCode::Success
Expand All @@ -568,7 +562,7 @@ fn format_policies_inner(args: &FormatArgs) -> Result<()> {

pub fn format_policies(args: &FormatArgs) -> CedarExitCode {
if let Err(err) = format_policies_inner(args) {
println!("Error: {err:?}");
println!("{err:?}");
CedarExitCode::Failure
} else {
CedarExitCode::Success
Expand Down Expand Up @@ -666,7 +660,7 @@ fn new_inner(args: &NewArgs) -> Result<()> {

pub fn new(args: &NewArgs) -> CedarExitCode {
if let Err(err) = new_inner(args) {
println!("Error: {err:?}");
println!("{err:?}");
CedarExitCode::Failure
} else {
CedarExitCode::Success
Expand All @@ -682,13 +676,11 @@ fn create_slot_env(data: &HashMap<SlotId, String>) -> Result<HashMap<SlotId, Ent
fn link_inner(args: &LinkArgs) -> Result<()> {
let mut policies = read_policy_set(Some(&args.policies_file))?;
let slotenv = create_slot_env(&args.arguments.data)?;
policies
.link(
PolicyId::from_str(&args.template_id)?,
PolicyId::from_str(&args.new_id)?,
slotenv,
)
.into_diagnostic()?;
policies.link(
PolicyId::from_str(&args.template_id)?,
PolicyId::from_str(&args.new_id)?,
slotenv,
)?;
let linked = policies
.policy(&PolicyId::from_str(&args.new_id)?)
.ok_or_else(|| miette!("Failed to add template-linked policy"))?;
Expand Down Expand Up @@ -763,13 +755,11 @@ impl From<TemplateLinked> for LiteralTemplateLinked {
fn add_template_links_to_set(path: impl AsRef<Path>, policy_set: &mut PolicySet) -> Result<()> {
for template_linked in load_liked_file(path)? {
let slot_env = create_slot_env(&template_linked.args)?;
policy_set
.link(
PolicyId::from_str(&template_linked.template_id)?,
PolicyId::from_str(&template_linked.link_id)?,
slot_env,
)
.into_diagnostic()?;
policy_set.link(
PolicyId::from_str(&template_linked.template_id)?,
PolicyId::from_str(&template_linked.link_id)?,
slot_env,
)?;
}
Ok(())
}
Expand Down Expand Up @@ -874,14 +864,12 @@ fn load_entities(entities_filename: impl AsRef<Path>, schema: Option<&Schema>) -
.read(true)
.open(entities_filename.as_ref())
{
Ok(f) => Entities::from_json_file(f, schema)
.into_diagnostic()
.wrap_err_with(|| {
format!(
"failed to parse entities from file {}",
entities_filename.as_ref().display()
)
}),
Ok(f) => Entities::from_json_file(f, schema).wrap_err_with(|| {
format!(
"failed to parse entities from file {}",
entities_filename.as_ref().display()
)
}),
Err(e) => Err(e).into_diagnostic().wrap_err_with(|| {
format!(
"failed to open entities file {}",
Expand All @@ -904,25 +892,19 @@ fn rename_from_id_annotation(ps: PolicySet) -> Result<PolicySet> {
Some(anno) => anno.parse().map(|a| t.new_id(a)),
});
for t in t_iter {
let template = t
.into_diagnostic()
.wrap_err("failed to parse policy id annotation")?;
let template = t.wrap_err("failed to parse policy id annotation")?;
new_ps
.add_template(template)
.into_diagnostic()
.wrap_err("failed to add template to policy set")?;
}
let p_iter = ps.policies().map(|p| match p.annotation("id") {
None => Ok(p.clone()),
Some(anno) => anno.parse().map(|a| p.new_id(a)),
});
for p in p_iter {
let policy = p
.into_diagnostic()
.wrap_err("failed to parse policy id annotation")?;
let policy = p.wrap_err("failed to parse policy id annotation")?;
new_ps
.add(policy)
.into_diagnostic()
.wrap_err("failed to add template to policy set")?;
}
Ok(new_ps)
Expand Down Expand Up @@ -987,14 +969,12 @@ fn read_policy_set(

fn read_schema_file(filename: impl AsRef<Path> + std::marker::Copy) -> Result<Schema> {
let schema_src = read_from_file(filename, "schema")?;
Schema::from_str(&schema_src)
.into_diagnostic()
.wrap_err_with(|| {
format!(
"failed to parse schema from file {}",
filename.as_ref().display()
)
})
Schema::from_str(&schema_src).wrap_err_with(|| {
format!(
"failed to parse schema from file {}",
filename.as_ref().display()
)
})
}

/// This uses the Cedar API to call the authorization engine.
Expand Down
2 changes: 1 addition & 1 deletion cedar-policy-cli/tests/integration_tests/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ fn constant_true() -> bool {
true
}

fn value_to_euid_string(v: serde_json::Value) -> Result<String, impl std::error::Error> {
fn value_to_euid_string(v: serde_json::Value) -> Result<String, impl miette::Diagnostic> {
EntityUid::from_json(v).map(|euid| euid.to_string())
}

Expand Down
4 changes: 3 additions & 1 deletion cedar-policy-core/src/ast/entity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use crate::parser::err::ParseErrors;
use crate::transitive_closure::TCNode;
use crate::FromNormalizedStr;
use itertools::Itertools;
use miette::Diagnostic;
use serde::{Deserialize, Serialize};
use serde_with::{serde_as, TryFromInto};
use smol_str::SmolStr;
Expand Down Expand Up @@ -448,14 +449,15 @@ impl std::fmt::Display for PartialValueSerializedAsExpr {
/// Error type for evaluation errors when evaluating an entity attribute.
/// Contains some extra contextual information and the underlying
/// `EvaluationError`.
#[derive(Debug, Error)]
#[derive(Debug, Diagnostic, Error)]
#[error("failed to evaluate attribute `{attr}` of `{uid}`: {err}")]
pub struct EntityAttrEvaluationError {
/// UID of the entity where the error was encountered
pub uid: EntityUID,
/// Attribute of the entity where the error was encountered
pub attr: SmolStr,
/// Underlying evaluation error
#[diagnostic(transparent)]
pub err: EvaluationError,
}

Expand Down
5 changes: 3 additions & 2 deletions cedar-policy-core/src/ast/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/

use crate::{ast::*, parser::err::ParseErrors};
use miette::Diagnostic;
use serde::{Deserialize, Serialize};
use smol_str::SmolStr;
use std::{
Expand Down Expand Up @@ -600,7 +601,7 @@ impl std::str::FromStr for Expr {
}

/// Enum for errors encountered during substitution
#[derive(Debug, Clone, Error)]
#[derive(Debug, Clone, Diagnostic, Error)]
pub enum SubstitutionError {
/// The supplied value did not match the type annotation on the unknown.
#[error("expected a value of type {expected}, got a value of type {actual}")]
Expand Down Expand Up @@ -1059,7 +1060,7 @@ impl<T: Clone> ExprBuilder<T> {
}

/// Errors when constructing an `Expr`
#[derive(Debug, PartialEq, Error)]
#[derive(Debug, PartialEq, Diagnostic, Error)]
pub enum ExprConstructionError {
/// A key occurred twice (or more) in a record literal
#[error("duplicate key `{key}` in record literal")]
Expand Down
8 changes: 5 additions & 3 deletions cedar-policy-core/src/ast/policy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

use crate::ast::*;
use itertools::Itertools;
use miette::Diagnostic;
use serde::{Deserialize, Serialize};
use smol_str::SmolStr;
use std::collections::BTreeMap;
Expand Down Expand Up @@ -242,7 +243,7 @@ impl std::fmt::Display for Template {
}

/// Errors instantiating templates
#[derive(Debug, Clone, PartialEq, Eq, Error)]
#[derive(Debug, Clone, PartialEq, Eq, Diagnostic, Error)]
pub enum LinkingError {
/// An error with the slot arguments provided
// INVARIANT: `unbound_values` and `extra_values` can't both be empty
Expand Down Expand Up @@ -567,13 +568,14 @@ mod hashing_tests {
// GRCOV_BEGIN_COVERAGE

/// Errors that can happen during policy reification
#[derive(Debug, Error)]
#[derive(Debug, Diagnostic, Error)]
pub enum ReificationError {
/// The [`PolicyID`] linked to did not exist
#[error("the id linked to does not exist")]
NoSuchTemplate(PolicyID),
/// Error instantiating the policy
#[error(transparent)]
#[diagnostic(transparent)]
Instantiation(#[from] LinkingError),
}

Expand Down Expand Up @@ -1209,7 +1211,7 @@ impl EntityReference {
}

/// Error for unexpected slots
#[derive(Debug, Clone, PartialEq, Error)]
#[derive(Debug, Clone, PartialEq, Diagnostic, Error)]
pub enum UnexpectedSlotError {
/// Found this slot where slots are not allowed
#[error("found slot `{0}` where slots are not allowed")]
Expand Down
Loading
Loading