Skip to main content

greentic_bundle/access/
mod.rs

1pub mod edit;
2pub mod eval;
3pub mod gmap;
4pub mod parse;
5
6use std::path::Path;
7
8use anyhow::{Context, Result};
9use serde::Serialize;
10
11pub use edit::upsert_policy;
12pub use eval::{MatchDecision, eval_policy, eval_with_overlay};
13pub use gmap::{GmapMutation, GmapTarget};
14pub use parse::{GmapPath, GmapRule, Policy, parse_file, parse_path, parse_rule_line, parse_str};
15
16#[derive(Debug, Serialize)]
17pub struct AccessMutationPreview {
18    pub gmap_path: String,
19    pub rule_path: String,
20    pub policy: String,
21    pub writes: Vec<String>,
22}
23
24pub fn mutate_access(
25    root: &Path,
26    target: &GmapTarget,
27    mutation: &GmapMutation,
28    dry_run: bool,
29) -> Result<AccessMutationPreview> {
30    let gmap_path = crate::project::gmap_path(root, target);
31    let resolved_writes =
32        crate::project::resolved_output_paths(root, &target.tenant, target.team.as_deref());
33
34    let preview = AccessMutationPreview {
35        gmap_path: relative_display(root, &gmap_path),
36        rule_path: mutation.rule_path.clone(),
37        policy: mutation.policy.to_string(),
38        writes: std::iter::once(relative_display(root, &gmap_path))
39            .chain(
40                resolved_writes
41                    .iter()
42                    .map(|path| relative_display(root, path)),
43            )
44            .collect(),
45    };
46
47    if dry_run {
48        return Ok(preview);
49    }
50
51    crate::project::ensure_layout(root)?;
52    if let Some(team) = &target.team {
53        crate::project::ensure_team(root, &target.tenant, team)?;
54    } else {
55        crate::project::ensure_tenant(root, &target.tenant)?;
56    }
57    upsert_policy(&gmap_path, &mutation.rule_path, mutation.policy.clone())
58        .with_context(|| format!("update gmap {}", gmap_path.display()))?;
59    crate::project::sync_project(root)?;
60    Ok(preview)
61}
62
63fn relative_display(root: &Path, path: &Path) -> String {
64    path.strip_prefix(root)
65        .unwrap_or(path)
66        .display()
67        .to_string()
68}
69
70pub const ACCESS_LAYOUT_HINT: &str = "tenants/<tenant>/tenant.gmap";