Skip to main content

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}