Skip to content

Commit e57ef73

Browse files
Refactor TPE (#1822)
Signed-off-by: Shaobo He <[email protected]>
1 parent 96f3028 commit e57ef73

File tree

7 files changed

+112
-85
lines changed

7 files changed

+112
-85
lines changed

cedar-policy-core/src/tpe/batched_evaluator.rs renamed to cedar-policy-core/src/batched_evaluator.rs

Lines changed: 6 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -16,23 +16,22 @@
1616

1717
//! This module contains the batched evaluator implementation and the (internal) definition of [`EntityLoader`]
1818
19+
pub mod err;
20+
1921
use std::collections::{HashMap, HashSet};
2022
use std::iter;
2123
use std::sync::Arc;
2224

23-
use crate::ast::{Entity, EntityUID, EntityUIDEntry, Expr, PolicyID, Request};
25+
use crate::ast::{Entity, EntityUID, EntityUIDEntry, Request};
2426
use crate::authorizer::Decision;
27+
use crate::batched_evaluator::err::{BatchedEvalError, InsufficientIterationsError};
2528
use crate::entities::TCComputation;
2629
use crate::tpe::entities::PartialEntity;
27-
use crate::tpe::err::{
28-
BatchedEvalError, InsufficientIterationsError, NonstaticPolicyError, PartialRequestError,
29-
TPEError,
30-
};
30+
use crate::tpe::err::{PartialRequestError, TPEError};
31+
use crate::tpe::policy_expr_map;
3132
use crate::tpe::request::{PartialEntityUID, PartialRequest};
3233
use crate::tpe::residual::Residual;
3334
use crate::tpe::response::{ResidualPolicy, Response};
34-
use crate::validator::typecheck::{PolicyCheck, Typechecker};
35-
use crate::validator::types::Type;
3635
use crate::validator::ValidatorSchema;
3736
use crate::{ast::PolicySet, extensions::Extensions};
3837

@@ -47,38 +46,6 @@ pub trait EntityLoader {
4746
fn load_entities(&mut self, uids: &HashSet<EntityUID>) -> HashMap<EntityUID, Option<Entity>>;
4847
}
4948

50-
pub(crate) fn policy_expr_map<'a>(
51-
request: &'a PartialRequest,
52-
ps: &'a PolicySet,
53-
schema: &ValidatorSchema,
54-
) -> std::result::Result<HashMap<&'a PolicyID, Expr<Option<Type>>>, TPEError> {
55-
let mut exprs = HashMap::new();
56-
let tc = Typechecker::new(schema, crate::validator::ValidationMode::Strict);
57-
let env = request.find_request_env(schema)?;
58-
for p in ps.policies() {
59-
if !p.is_static() {
60-
return Err(NonstaticPolicyError.into());
61-
}
62-
let t = p.template();
63-
match tc.typecheck_by_single_request_env(t, &env) {
64-
PolicyCheck::Success(expr) => {
65-
exprs.insert(p.id(), expr);
66-
}
67-
PolicyCheck::Fail(errs) => {
68-
return Err(TPEError::Validation(errs));
69-
}
70-
PolicyCheck::Irrelevant(errs, expr) => {
71-
if errs.is_empty() {
72-
exprs.insert(p.id(), expr);
73-
} else {
74-
return Err(TPEError::Validation(errs));
75-
}
76-
}
77-
}
78-
}
79-
Ok(exprs)
80-
}
81-
8249
fn concrete_request_to_partial(
8350
request: &Request,
8451
schema: &ValidatorSchema,
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
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 contains possible errors thrown by batched evaluation
18+
19+
use thiserror::Error;
20+
21+
use crate::ast::PartialValueToValueError;
22+
use crate::tpe::err::{EntitiesError, MissingEntitiesError, PartialRequestError, TPEError};
23+
use crate::validator::RequestValidationError;
24+
25+
/// Errors for Batched Evaluation
26+
#[derive(Debug, Error)]
27+
#[non_exhaustive]
28+
pub enum BatchedEvalError {
29+
/// Error thrown by TPE
30+
#[error(transparent)]
31+
TPE(#[from] TPEError),
32+
/// Error when the request is not valid
33+
#[error(transparent)]
34+
RequestValidation(#[from] RequestValidationError),
35+
/// Error when the request is partial
36+
#[error(transparent)]
37+
PartialRequest(#[from] PartialRequestError),
38+
/// Error when the loaded entities are not valid
39+
#[error(transparent)]
40+
Entities(#[from] EntitiesError),
41+
/// Error thrown when a entity loader provided entity was partial instead of fully concrete
42+
#[error(transparent)]
43+
PartialValueToValue(#[from] PartialValueToValueError),
44+
/// Error the entity loader failed to load all requested entities
45+
#[error(transparent)]
46+
MissingEntities(#[from] MissingEntitiesError),
47+
/// Error when batched evaluation did not converge due to the iteration limit
48+
#[error(transparent)]
49+
InsufficientIterations(#[from] InsufficientIterationsError),
50+
}
51+
52+
/// Batched evaluation may not return an answer when the maximum
53+
/// iterations is too low.
54+
#[derive(Debug, Error)]
55+
#[error("Batched evaluation failed: insufficient iteration limit.")]
56+
pub struct InsufficientIterationsError {}

cedar-policy-core/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ pub use from_normalized_str::*;
2828
pub mod entities;
2929
#[macro_use]
3030
mod error_macros;
31+
#[cfg(feature = "tpe")]
32+
pub mod batched_evaluator;
3133
pub mod est;
3234
pub mod evaluator;
3335
pub mod expr_builder;

cedar-policy-core/src/tpe.rs

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,24 +16,56 @@
1616

1717
//! This module contains the type-aware partial evaluator.
1818
19-
pub mod batched_evaluator;
2019
pub mod entities;
2120
pub mod err;
2221
pub mod evaluator;
2322
pub mod request;
2423
pub mod residual;
2524
pub mod response;
2625

27-
use std::sync::Arc;
26+
use std::{collections::HashMap, sync::Arc};
2827

29-
use crate::tpe::batched_evaluator::policy_expr_map;
30-
use crate::tpe::err::TPEError;
28+
use crate::ast::{Expr, PolicyID};
29+
use crate::tpe::err::{NonstaticPolicyError, TPEError};
3130
use crate::tpe::response::{ResidualPolicy, Response};
32-
use crate::validator::ValidatorSchema;
31+
use crate::validator::types::Type;
32+
use crate::validator::{typecheck::PolicyCheck, typecheck::Typechecker, ValidatorSchema};
3333
use crate::{ast::PolicySet, extensions::Extensions};
3434

3535
use crate::tpe::{entities::PartialEntities, evaluator::Evaluator, request::PartialRequest};
3636

37+
pub(crate) fn policy_expr_map<'a>(
38+
request: &'a PartialRequest,
39+
ps: &'a PolicySet,
40+
schema: &ValidatorSchema,
41+
) -> std::result::Result<HashMap<&'a PolicyID, Expr<Option<Type>>>, TPEError> {
42+
let mut exprs = HashMap::new();
43+
let tc = Typechecker::new(schema, crate::validator::ValidationMode::Strict);
44+
let env = request.find_request_env(schema)?;
45+
for p in ps.policies() {
46+
if !p.is_static() {
47+
return Err(NonstaticPolicyError.into());
48+
}
49+
let t = p.template();
50+
match tc.typecheck_by_single_request_env(t, &env) {
51+
PolicyCheck::Success(expr) => {
52+
exprs.insert(p.id(), expr);
53+
}
54+
PolicyCheck::Fail(errs) => {
55+
return Err(TPEError::Validation(errs));
56+
}
57+
PolicyCheck::Irrelevant(errs, expr) => {
58+
if errs.is_empty() {
59+
exprs.insert(p.id(), expr);
60+
} else {
61+
return Err(TPEError::Validation(errs));
62+
}
63+
}
64+
}
65+
}
66+
Ok(exprs)
67+
}
68+
3769
/// Type-aware partial-evaluation on a `PolicySet`.
3870
/// Both `request` and `entities` should be valid and hence be constructed
3971
/// using their safe constructors.

cedar-policy-core/src/tpe/err.rs

Lines changed: 1 addition & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use smol_str::SmolStr;
2323
use thiserror::Error;
2424

2525
use crate::{
26-
ast::{Eid, EntityType, EntityUID, PartialValueToValueError},
26+
ast::{Eid, EntityType, EntityUID},
2727
entities::{
2828
conformance::err::{EntitySchemaConformanceError, InvalidEnumEntityError},
2929
err::Duplicate,
@@ -109,39 +109,6 @@ pub enum TPEError {
109109
ExprToResidualError(#[from] ExprToResidualError),
110110
}
111111

112-
/// Errors for Batched Evaluation
113-
#[derive(Debug, Error)]
114-
#[non_exhaustive]
115-
pub enum BatchedEvalError {
116-
/// Error thrown by TPE
117-
#[error(transparent)]
118-
TPE(#[from] TPEError),
119-
/// Error when the request is not valid
120-
#[error(transparent)]
121-
RequestValidation(#[from] RequestValidationError),
122-
/// Error when the request is partial
123-
#[error(transparent)]
124-
PartialRequest(#[from] PartialRequestError),
125-
/// Error when the loaded entities are not valid
126-
#[error(transparent)]
127-
Entities(#[from] EntitiesError),
128-
/// Error thrown when a entity loader provided entity was partial instead of fully concrete
129-
#[error(transparent)]
130-
PartialValueToValue(#[from] PartialValueToValueError),
131-
/// Error the entity loader failed to load all requested entities
132-
#[error(transparent)]
133-
MissingEntities(#[from] MissingEntitiesError),
134-
/// Error when batched evaluation did not converge due to the iteration limit
135-
#[error(transparent)]
136-
InsufficientIterations(#[from] InsufficientIterationsError),
137-
}
138-
139-
/// Batched evaluation may not return an answer when the maximum
140-
/// iterations is too low.
141-
#[derive(Debug, Error)]
142-
#[error("Batched evaluation failed: insufficient iteration limit.")]
143-
pub struct InsufficientIterationsError {}
144-
145112
/// Residuals require fully typed expressions without
146113
/// unknowns or parse errors.
147114
#[derive(Debug, Error)]

cedar-policy/src/api.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5117,11 +5117,11 @@ mod tpe {
51175117

51185118
use cedar_policy_core::ast;
51195119
use cedar_policy_core::authorizer::Decision;
5120-
use cedar_policy_core::tpe;
5121-
use cedar_policy_core::tpe::batched_evaluator::is_authorized_batched;
5122-
use cedar_policy_core::tpe::{
5123-
batched_evaluator::EntityLoader as EntityLoaderInternal, err::BatchedEvalError,
5120+
use cedar_policy_core::batched_evaluator::is_authorized_batched;
5121+
use cedar_policy_core::batched_evaluator::{
5122+
err::BatchedEvalError, EntityLoader as EntityLoaderInternal,
51245123
};
5124+
use cedar_policy_core::tpe;
51255125
use cedar_policy_core::{
51265126
entities::conformance::EntitySchemaConformanceChecker, extensions::Extensions,
51275127
validator::CoreSchema,
@@ -5154,8 +5154,8 @@ mod tpe {
51545154
}
51555155

51565156
/// A partial [`Request`]
5157-
/// Its principal and resource could have unknown [`EntityId`]; its action
5158-
/// must be know; and its context could be unknown
5157+
/// Its principal/resource types and action must be known and its context
5158+
/// must either be fully known or unknown
51595159
#[repr(transparent)]
51605160
#[derive(Debug, Clone, RefCast)]
51615161
pub struct PartialRequest(pub(crate) tpe::request::PartialRequest);
@@ -5296,6 +5296,8 @@ mod tpe {
52965296

52975297
impl PartialEntities {
52985298
/// Construct [`PartialEntities`] from a JSON value
5299+
/// The `parent`, `attrs`, `tags` field must be either fully known or
5300+
/// unknown. And parent entities cannot have unknown parents.
52995301
pub fn from_json_value(
53005302
value: serde_json::Value,
53015303
schema: &Schema,

cedar-policy/src/test/test.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8783,7 +8783,8 @@ unless
87838783
str::FromStr,
87848784
};
87858785

8786-
use cedar_policy_core::tpe::err::{BatchedEvalError, TPEError};
8786+
use cedar_policy_core::batched_evaluator::err::BatchedEvalError;
8787+
use cedar_policy_core::tpe::err::TPEError;
87878788
use cool_asserts::assert_matches;
87888789
use itertools::Itertools;
87898790

0 commit comments

Comments
 (0)