Skip to main content

source_map_tauri/tauri_config/
effective.rs

1use anyhow::Result;
2use serde_json::{json, Value};
3
4use crate::{
5    config::{normalize_path, ResolvedConfig},
6    discovery::RepoDiscovery,
7    ids::document_id,
8    model::ArtifactDoc,
9    security::apply_artifact_security,
10};
11
12pub fn extract_effective_capabilities(
13    config: &ResolvedConfig,
14    discovery: &RepoDiscovery,
15) -> Result<Vec<ArtifactDoc>> {
16    let mut windows = Vec::new();
17    for path in &discovery.tauri_configs {
18        let text = std::fs::read_to_string(path)?;
19        let value: serde_json::Value = serde_json::from_str(&text)?;
20        if let Some(items) = value
21            .get("app")
22            .and_then(|item| item.get("windows"))
23            .and_then(serde_json::Value::as_array)
24        {
25            for item in items {
26                if let Some(label) = item.get("label").and_then(serde_json::Value::as_str) {
27                    windows.push(label.to_owned());
28                } else {
29                    windows.push("main".to_owned());
30                }
31            }
32        }
33    }
34
35    let mut docs = Vec::new();
36    for window in windows {
37        let mut permissions = Vec::new();
38        let mut capability_ids = Vec::new();
39        for path in &discovery.capability_files {
40            let text = std::fs::read_to_string(path)?;
41            let value: serde_json::Value =
42                serde_json::from_str(&text).unwrap_or_else(|_| json!({}));
43            let matches_window = value
44                .get("windows")
45                .and_then(serde_json::Value::as_array)
46                .map(|items| {
47                    items
48                        .iter()
49                        .any(|item| item.as_str() == Some(window.as_str()))
50                })
51                .unwrap_or(false);
52            if matches_window {
53                if let Some(identifier) =
54                    value.get("identifier").and_then(serde_json::Value::as_str)
55                {
56                    capability_ids.push(identifier.to_owned());
57                }
58                if let Some(items) = value
59                    .get("permissions")
60                    .and_then(serde_json::Value::as_array)
61                {
62                    permissions.extend(
63                        items
64                            .iter()
65                            .filter_map(|item| item.as_str())
66                            .map(str::to_owned),
67                    );
68                }
69            }
70        }
71        let source_path = discovery
72            .capability_files
73            .first()
74            .map(|path| normalize_path(&config.root, path))
75            .unwrap_or_else(|| "src-tauri/capabilities".to_owned());
76        let mut doc = ArtifactDoc {
77            id: document_id(
78                &config.repo,
79                "tauri_capability_effective",
80                Some(&source_path),
81                Some(1),
82                Some(&window),
83            ),
84            repo: config.repo.clone(),
85            kind: "tauri_capability_effective".to_owned(),
86            side: Some("config".to_owned()),
87            language: Some("json".to_owned()),
88            name: Some(window.clone()),
89            display_name: Some(window.clone()),
90            source_path: Some(source_path),
91            line_start: Some(1),
92            line_end: Some(1),
93            column_start: None,
94            column_end: None,
95            package_name: None,
96            comments: Vec::new(),
97            tags: vec!["capability".to_owned()],
98            related_symbols: Vec::new(),
99            related_tests: Vec::new(),
100            risk_level: "medium".to_owned(),
101            risk_reasons: vec!["multiple capabilities merge for window".to_owned()],
102            contains_phi: false,
103            has_related_tests: false,
104            updated_at: chrono::Utc::now().to_rfc3339(),
105            data: Default::default(),
106        };
107        doc.data
108            .insert("window_label".to_owned(), Value::String(window));
109        doc.data.insert(
110            "capability_ids".to_owned(),
111            Value::Array(capability_ids.into_iter().map(Value::String).collect()),
112        );
113        doc.data.insert(
114            "permissions".to_owned(),
115            Value::Array(permissions.iter().cloned().map(Value::String).collect()),
116        );
117        doc.data.insert(
118            "plugin_permissions".to_owned(),
119            Value::Array(
120                permissions
121                    .iter()
122                    .filter(|item| item.contains(':'))
123                    .cloned()
124                    .map(Value::String)
125                    .collect(),
126            ),
127        );
128        doc.data
129            .insert("merged_capabilities".to_owned(), Value::Bool(true));
130        doc.data
131            .insert("remote_capability".to_owned(), Value::Bool(false));
132        apply_artifact_security(&mut doc);
133        docs.push(doc);
134    }
135    Ok(docs)
136}