Skip to main content

cedar_policy_cli/command/
evaluate.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
17use cedar_policy::{eval_expression, Entities, EvalResult, Expression};
18use clap::Args;
19use miette::WrapErr;
20use std::str::FromStr;
21
22use crate::{load_entities, CedarExitCode, OptionalSchemaArgs, RequestArgs};
23
24#[derive(Args, Debug)]
25pub struct EvaluateArgs {
26    /// Request args (incorporated by reference)
27    #[command(flatten)]
28    pub request: RequestArgs,
29    /// Schema args (incorporated by reference)
30    ///
31    /// Used to populate the store with action entities and for schema-based
32    /// parsing of entity hierarchy, if present
33    #[command(flatten)]
34    pub schema: OptionalSchemaArgs,
35    /// File containing JSON representation of the Cedar entity hierarchy.
36    /// This is optional; if not present, we'll just use an empty hierarchy.
37    #[arg(long = "entities", value_name = "FILE")]
38    pub entities_file: Option<String>,
39    /// Expression to evaluate
40    #[arg(value_name = "EXPRESSION")]
41    pub expression: String,
42}
43
44pub fn evaluate(args: &EvaluateArgs) -> (CedarExitCode, EvalResult) {
45    println!();
46    let schema = match args.schema.get_schema() {
47        Ok(opt) => opt,
48        Err(e) => {
49            println!("{e:?}");
50            return (CedarExitCode::Failure, EvalResult::Bool(false));
51        }
52    };
53    let request = match args.request.get_request(schema.as_ref()) {
54        Ok(q) => q,
55        Err(e) => {
56            println!("{e:?}");
57            return (CedarExitCode::Failure, EvalResult::Bool(false));
58        }
59    };
60    let expr =
61        match Expression::from_str(&args.expression).wrap_err("failed to parse the expression") {
62            Ok(expr) => expr,
63            Err(e) => {
64                println!("{:?}", e.with_source_code(args.expression.clone()));
65                return (CedarExitCode::Failure, EvalResult::Bool(false));
66            }
67        };
68    let entities = match &args.entities_file {
69        None => Entities::empty(),
70        Some(file) => match load_entities(file, schema.as_ref()) {
71            Ok(entities) => entities,
72            Err(e) => {
73                println!("{e:?}");
74                return (CedarExitCode::Failure, EvalResult::Bool(false));
75            }
76        },
77    };
78    match eval_expression(&request, &entities, &expr).wrap_err("failed to evaluate the expression")
79    {
80        Err(e) => {
81            println!("{e:?}");
82            (CedarExitCode::Failure, EvalResult::Bool(false))
83        }
84        Ok(result) => {
85            println!("{result}");
86            (CedarExitCode::Success, result)
87        }
88    }
89}