surrealdb_core/iam/policies/
mod.rs

1use cedar_policy::{Authorizer, Context, Decision, Entities, Entity, EntityUid, Request, Response};
2
3mod policy_set;
4
5use policy_set::*;
6
7use crate::iam::{Action, Actor, Resource};
8
9/// Checks if the actor is allowed to do the action on the resource, given the context and based on the default policy set.
10pub fn is_allowed(
11	actor: &Actor,
12	action: &Action,
13	resource: &Resource,
14	context: Context,
15) -> (bool, Response) {
16	_is_allowed(
17		Some(actor.into()),
18		Some(action.into()),
19		Some(resource.into()),
20		Entities::from_entities(_get_entities(Some(actor), Some(resource))).unwrap(),
21		context,
22	)
23}
24
25fn _get_entities(actor: Option<&Actor>, resource: Option<&Resource>) -> Vec<Entity> {
26	let mut entities = Vec::new();
27	if let Some(actor) = actor {
28		entities.extend(actor.cedar_entities());
29	}
30	if let Some(resource) = resource {
31		entities.extend(resource.cedar_entities());
32	}
33	entities
34}
35
36fn _is_allowed(
37	actor: Option<EntityUid>,
38	action: Option<EntityUid>,
39	resource: Option<EntityUid>,
40	entities: Entities,
41	context: Context,
42) -> (bool, Response) {
43	let policy_set = POLICY_SET.to_owned();
44
45	let authorizer = Authorizer::new();
46
47	let req = Request::new(actor, action, resource, context);
48
49	let res = authorizer.is_authorized(&req, &policy_set, &entities);
50
51	(res.decision() == Decision::Allow, res)
52}
53
54#[cfg(test)]
55mod tests {
56	use cedar_policy::{ValidationMode, ValidationResult, Validator};
57
58	use crate::iam::{default_schema, entities::Level, ResourceKind, Role};
59
60	use super::*;
61
62	#[test]
63	fn validate_policy_set() {
64		let validator = Validator::new(default_schema());
65		let result = Validator::validate(&validator, &POLICY_SET, ValidationMode::default());
66
67		if !ValidationResult::validation_passed(&result) {
68			let e = ValidationResult::validation_errors(&result);
69			for err in e {
70				println!("{}", err);
71			}
72			panic!("Policy set validation failed");
73		}
74	}
75
76	#[test]
77	fn test_is_allowed() {
78		// Returns true if the actor is allowed to do the action on the resource
79		let actor = Actor::new("test".into(), vec![Role::Viewer], Level::Root);
80		let res = ResourceKind::Namespace.on_root();
81
82		let (allowed, _) = is_allowed(&actor, &Action::View, &res, Context::empty());
83		assert!(allowed);
84
85		// Returns false if the actor is not allowed to do the action on the resource
86		let actor = Actor::new(
87			"test".into(),
88			vec![Role::Viewer],
89			Level::Database("test".into(), "test".into()),
90		);
91		let res = ResourceKind::Namespace.on_root();
92
93		let (allowed, _) = is_allowed(&actor, &Action::View, &res, Context::empty());
94		assert!(!allowed);
95	}
96}