1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
use anyhow::{Error, Result};
use std::fs::{File, OpenOptions};
use std::io::{Read, Write};
use std::path::PathBuf;
use std::{env, fs};

use crate::scout::blockchain::BlockChain;

const INK_DEFAULT_CONFIG: &str = include_str!("./ink_default_config.toml");

fn create_default_config(
    file_path: PathBuf,
    detectors: Vec<String>,
    bc: BlockChain,
) -> Result<File> {
    let mut file = OpenOptions::new()
        .read(true)
        .write(true)
        .create(true)
        .open(file_path)?;
    let str = match bc {
        BlockChain::Ink => INK_DEFAULT_CONFIG.to_string(),
        BlockChain::Soroban => {
            let mut default_config = toml::Table::new();
            let mut dev_table = toml::Table::new();
            let mut auditor_table = toml::Table::new();
            for detector in detectors {
                let mut detector_config = toml::Table::new();
                detector_config.insert("enabled".to_string(), toml::Value::Boolean(true));
                dev_table.insert(
                    detector.clone(),
                    toml::Value::Table(detector_config.clone()),
                );
                auditor_table.insert(detector, toml::Value::Table(detector_config));
            }
            default_config.insert("auditor".to_string(), toml::Value::Table(auditor_table));
            default_config.insert("dev".to_string(), toml::Value::Table(dev_table));
            toml::to_string_pretty::<toml::Table>(&default_config)?
        }
    };
    file.write_all(str.as_bytes())?;
    Ok(file)
}

pub fn open_config_or_default(bc: BlockChain, detectors: Vec<String>) -> Result<toml::Table> {
    let base_path = match std::env::consts::OS {
        "windows" => env::var("USERPROFILE")? + "/scout/",
        _ => env::var("HOME")? + "/.config/scout/",
    };
    let path = PathBuf::from(base_path);
    if let Err(_metadata) = fs::metadata(&path) {
        fs::create_dir_all(&path)?;
    }
    let file_path = path.as_path().join(match bc {
        BlockChain::Ink => "ink-config.toml",
        BlockChain::Soroban => "soroban-config.toml",
    });
    if !file_path.as_path().exists() {
        create_default_config(file_path.clone(), detectors, bc)?;
    }
    let mut file = File::open(&file_path)?;
    let mut toml_str = String::new();
    let _len = file.read_to_string(&mut toml_str)?;
    let config: toml::Table = toml::from_str(&toml_str)?;

    Ok(config)
}

pub fn profile_enabled_detectors(config: toml::Table, profile: String) -> Result<Vec<String>> {
    let profile = config.get(&profile);
    if profile.is_none() {
        return Err(Error::msg(format!(
            "Profile \"{:?}\" does not exist",
            profile
        )));
    }
    let mut ret_vec = Vec::<String>::new();
    for (detector, config) in profile.unwrap().as_table().unwrap().into_iter() {
        if let Some(val) = config.as_table().unwrap().get("enabled") {
            if val.is_bool() && val.as_bool().unwrap() {
                ret_vec.push(detector.clone());
            }
        }
    }
    Ok(ret_vec)
}