#![cfg(test)]
use crate::{PolicyExpr, ReadPolicy, ReadPredicate, render::render_read_policy_sql};
use cratestack_core::{CoolContext, SystemContext, Value};
fn render(allow: &[ReadPolicy], ctx: &CoolContext) -> String {
let mut bind_index = 1usize;
render_read_policy_sql(allow, &[], ctx, &mut bind_index).expect("policy should render")
}
fn allow(expr: PolicyExpr) -> [ReadPolicy; 1] {
[ReadPolicy { expr }]
}
fn system_ctx() -> CoolContext {
SystemContext::for_service("device-reconciler").into_context()
}
fn user_ctx(subject_id: &str) -> CoolContext {
CoolContext::authenticated([("subjectId".to_owned(), Value::String(subject_id.to_owned()))])
}
fn owner_or_system() -> PolicyExpr {
PolicyExpr::Or(&[
PolicyExpr::Predicate(ReadPredicate::AuthIsSystem),
PolicyExpr::Predicate(ReadPredicate::FieldEqAuth {
column: "subject_id",
auth_field: "subjectId",
}),
])
}
#[test]
fn is_system_grants_a_system_context_caller() {
let sql = render(&allow(owner_or_system()), &system_ctx());
assert_eq!(sql, "((TRUE OR FALSE))");
}
#[test]
fn is_system_denies_a_request_derived_caller() {
let sql = render(&allow(owner_or_system()), &user_ctx("subject-1"));
assert_eq!(sql, "((FALSE OR subject_id = $1))");
let sql = render(&allow(owner_or_system()), &CoolContext::anonymous());
assert_eq!(sql, "((FALSE OR FALSE))");
}
#[test]
fn model_that_never_names_is_system_denies_system_callers() {
let owner_only = allow(PolicyExpr::Predicate(ReadPredicate::FieldEqAuth {
column: "subject_id",
auth_field: "subjectId",
}));
let sql = render(&owner_only, &system_ctx());
assert_eq!(
sql, "(FALSE)",
"a system caller must gain nothing on a model that never names isSystem()"
);
let sql = render(&owner_only, &user_ctx("subject-1"));
assert_eq!(sql, "(subject_id = $1)");
}
#[test]
fn empty_allow_list_still_denies_system_callers() {
let mut bind_index = 1usize;
let sql = render_read_policy_sql(&[], &[], &system_ctx(), &mut bind_index)
.expect("empty allow should still render a clause");
assert_eq!(sql, "(FALSE)");
}
#[test]
fn deny_rules_still_beat_a_system_caller() {
let mut bind_index = 1usize;
let sql = render_read_policy_sql(
&allow(PolicyExpr::Predicate(ReadPredicate::AuthIsSystem)),
&allow(PolicyExpr::Predicate(ReadPredicate::AuthIsSystem)),
&system_ctx(),
&mut bind_index,
)
.expect("policy should render");
assert_eq!(sql, "(NOT (TRUE) AND (TRUE))");
}
mod create_path {
use super::*;
use crate::query::evaluate_input_predicate_for_tests as evaluate;
#[test]
fn is_system_predicate_matches_only_system_contexts() {
assert!(evaluate(ReadPredicate::AuthIsSystem, &[], &system_ctx()));
assert!(!evaluate(
ReadPredicate::AuthIsSystem,
&[],
&user_ctx("subject-1")
));
assert!(!evaluate(
ReadPredicate::AuthIsSystem,
&[],
&CoolContext::anonymous()
));
}
#[test]
fn system_caller_does_not_satisfy_an_ownership_predicate() {
assert!(!evaluate(
ReadPredicate::FieldEqAuth {
column: "subject_id",
auth_field: "subjectId",
},
&[],
&system_ctx()
));
}
}