cognee_http_server/permissions.rs
1//! Permission-gate helpers used across the write-path routers.
2//!
3//! OSS keeps only the trait-based `AclDb` shim. The blanket
4//! `impl AclDb for DatabaseConnection`, the full 8-step
5//! `PermissionsRepository::user_can` resolution
6//! (`tenants.md §5.1`), and the `permissions` router live in the
7//! closed `cognee-http-cloud` / `cognee-access-control` crates.
8//!
9//! `REQUIRE_AUTHORIZATION=false|0|no` short-circuits to `Ok(())` (Python's
10//! `ENABLE_BACKEND_ACCESS_CONTROL=false` parity). When the env var is
11//! left at its default and no `acl_db` is wired on the
12//! [`ComponentHandles`] (the pure-OSS case), permission checks pass
13//! through — there is no ACL backend to consult.
14
15use uuid::Uuid;
16
17use crate::components::ComponentHandles;
18use crate::error::ApiError;
19
20/// Dispatch on the `ComponentHandles`: when an `acl_db` impl is wired
21/// (closed builds), delegate to it; otherwise allow the operation
22/// because OSS does not bundle an ACL backend.
23pub async fn check_permission_via_handles(
24 handles: &ComponentHandles,
25 user_id: Uuid,
26 dataset_id: Uuid,
27 perm: &str,
28) -> Result<(), ApiError> {
29 if is_authorization_disabled() {
30 return Ok(());
31 }
32 let Some(ref acl) = handles.acl_db else {
33 // OSS bundle: no ACL backend wired — allow the operation. The
34 // closed `cognee-http-cloud` crate installs a real `AclDb`
35 // implementation via the `RouterBuilder`.
36 return Ok(());
37 };
38 let allowed = acl
39 .has_permission_with_roles(user_id, dataset_id, perm)
40 .await
41 .map_err(|e| ApiError::Internal(anyhow::anyhow!("ACL check failed: {e}")))?;
42 if allowed {
43 Ok(())
44 } else {
45 Err(ApiError::Forbidden(format!(
46 "No {perm} permission on dataset {dataset_id}"
47 )))
48 }
49}
50
51/// Returns `true` when authorization is required (i.e. not explicitly disabled).
52///
53/// Mirrors Python's `ENABLE_BACKEND_ACCESS_CONTROL` env var.
54pub fn is_authorization_required() -> bool {
55 !is_authorization_disabled()
56}
57
58/// Returns `true` when `REQUIRE_AUTHORIZATION` is explicitly disabled.
59fn is_authorization_disabled() -> bool {
60 matches!(
61 std::env::var("REQUIRE_AUTHORIZATION")
62 .as_deref()
63 .unwrap_or("true"),
64 "false" | "0" | "no"
65 )
66}