use std::env;
use std::fs;
use std::path::Path;
fn main() {
let out_dir = env::var("OUT_DIR").unwrap();
let dest_path = Path::new(&out_dir).join("generated_roles.rs");
let _macro_include_path = Path::new(&out_dir).join("roles_include.rs");
let permissions_path = env::var("DB_PERMISSIONS_PATH").unwrap_or_else(|_| "permissions.yaml".to_string());
let roles: Vec<String> = if Path::new(&permissions_path).exists() {
match fs::read_to_string(&permissions_path) {
Ok(content) => {
let mut found_roles = Vec::new();
let mut in_roles_section = false;
for line in content.lines() {
let trimmed = line.trim();
if trimmed.starts_with("roles:") {
in_roles_section = true;
continue;
}
if in_roles_section {
if trimmed.starts_with("- name:") {
if let Some(name_start) = trimmed.find(":") {
let name_part = &trimmed[name_start + 1..];
let name = name_part.trim().trim_matches('"').trim_matches('\'');
if !name.is_empty() {
found_roles.push(name.to_string());
}
}
} else if trimmed.starts_with('-') && !trimmed.contains(":") {
let role_name = trimmed.trim_start_matches('-').trim();
if !role_name.is_empty() && !role_name.starts_with("name:") {
found_roles.push(role_name.to_string());
}
} else if !trimmed.is_empty()
&& !trimmed.starts_with("tables:")
&& !trimmed.starts_with("#")
&& !trimmed.starts_with(" ")
&& trimmed.ends_with(':')
&& !trimmed.contains("name")
{
let role_name = trimmed.trim_end_matches(':').trim();
if !role_name.is_empty() {
found_roles.push(role_name.to_string());
}
}
}
}
found_roles.sort();
found_roles.dedup();
if found_roles.is_empty() {
eprintln!("Warning: No roles found in permissions.yaml. Using empty role list.");
}
found_roles
}
Err(e) => {
eprintln!(
"Warning: Could not read permissions.yaml: {}. Using empty role list.",
e
);
Vec::new()
}
}
} else {
Vec::new()
};
let roles_array_code = if roles.is_empty() {
"// No roles defined in permissions.yaml - all roles are allowed at compile time".to_string()
} else {
roles
.iter()
.map(|r| format!(" \"{}\"", r))
.collect::<Vec<_>>()
.join(",\n")
};
let generated_code = format!(
r#"// Auto-generated by build.rs
// This file contains the list of roles defined in permissions.yaml
/// List of all roles defined in permissions.yaml
pub const DEFINED_ROLES: &[&str] = &[
{}
];
/// Check if a role is defined in permissions.yaml
pub fn is_role_defined(role: &str) -> bool {{
DEFINED_ROLES.contains(&role)
}}
/// Get all defined roles
pub fn get_defined_roles() -> &'static [&'static str] {{
DEFINED_ROLES
}}
"#,
roles_array_code
);
fs::write(&dest_path, generated_code).unwrap();
println!("cargo:rerun-if-changed={}", permissions_path);
}