Files
OllaHubBackend/src/services/windows_permissions.rs
T

262 lines
11 KiB
Rust

use std::env;
use std::path::PathBuf;
use crate::services::system;
#[derive(Debug, Clone)]
pub struct PermissionStatus {
pub admin: bool,
pub firewall_configured: bool,
pub defender_exception: bool,
pub network_ok: bool,
pub issues: Vec<String>,
}
pub struct WindowsPermissions;
impl WindowsPermissions {
/// Verifica se o processo está rodando com privilégios de administrador
pub fn check_admin() -> bool {
let ps_cmd = r#"[Security.Principal.WindowsPrincipal]::Current.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)"#;
match system::run_cmd("powershell", &["-NoProfile", "-Command", ps_cmd]) {
Ok(output) => {
let trimmed = output.trim().to_lowercase();
trimmed == "true"
}
Err(_) => false,
}
}
/// Verifica se uma regra de firewall já existe
fn firewall_rule_exists(display_name: &str) -> bool {
let ps_cmd = format!(
r#"Get-NetFirewallRule -DisplayName '{}' -ErrorAction SilentlyContinue | Select-Object -First 1"#,
display_name
);
match system::run_cmd("powershell", &["-NoProfile", "-Command", &ps_cmd]) {
Ok(output) => !output.trim().is_empty(),
Err(_) => false,
}
}
/// Adiciona regra no firewall do Windows para uma porta específica
pub fn request_firewall_rule(port: u16, name: &str) -> Result<(), String> {
let display_name = format!("OllaHubBackend {}", name);
// Verificar se já existe
if Self::firewall_rule_exists(&display_name) {
system::info(&format!("Regra de firewall '{}' já existe", display_name));
return Ok(());
}
// Verificar se tem privilégios de admin
if !Self::check_admin() {
return Err(format!(
"Privilégios de administrador necessários para adicionar regra de firewall na porta {}. Execute como Administrador.",
port
));
}
// Criar regra de firewall
let ps_cmd = format!(
r#"New-NetFirewallRule -DisplayName '{}' -Direction Inbound -LocalPort {} -Protocol TCP -Action Allow -Profile Domain,Private,Public"#,
display_name, port
);
match system::run_cmd("powershell", &["-NoProfile", "-Command", &ps_cmd]) {
Ok(_) => {
system::info(&format!("Regra de firewall criada para porta {} ({})", port, name));
Ok(())
}
Err(e) => Err(format!("Falha ao criar regra de firewall: {}", e)),
}
}
/// Obtém o caminho do executável atual
fn get_executable_path() -> Result<PathBuf, String> {
env::current_exe().map_err(|e| format!("Não foi possível obter caminho do executável: {}", e))
}
/// Verifica se exceção já existe no Windows Defender
fn defender_exception_exists(path: &str) -> bool {
let ps_cmd = format!(
r#"Get-MpPreference | Select-Object -ExpandProperty ExclusionPath | Where-Object {{ $_ -eq '{}' }}"#,
path.replace('\\', "\\\\")
);
match system::run_cmd("powershell", &["-NoProfile", "-Command", &ps_cmd]) {
Ok(output) => !output.trim().is_empty(),
Err(_) => false,
}
}
/// Adiciona exceção no Windows Defender para o executável
pub fn request_defender_exception(exe_path: &str) -> Result<(), String> {
// Verificar se já existe
if Self::defender_exception_exists(exe_path) {
system::info(&format!("Exceção do Windows Defender já existe para: {}", exe_path));
return Ok(());
}
// Verificar se tem privilégios de admin
if !Self::check_admin() {
return Err(format!(
"Privilégios de administrador necessários para adicionar exceção no Windows Defender. Execute como Administrador."
));
}
// Adicionar exceção de caminho
let ps_cmd = format!(
r#"Add-MpPreference -ExclusionPath '{}'"#,
exe_path.replace('\'', "''")
);
match system::run_cmd("powershell", &["-NoProfile", "-Command", &ps_cmd]) {
Ok(_) => {
system::info(&format!("Exceção do Windows Defender adicionada para: {}", exe_path));
Ok(())
}
Err(e) => Err(format!("Falha ao adicionar exceção no Windows Defender: {}", e)),
}
}
/// Verifica permissões de rede (básico)
pub fn request_network_permissions() -> Result<(), String> {
// Verificação básica: tentar criar um socket de teste
// Se falhar, pode indicar problemas de permissão
// Por enquanto, apenas retorna Ok se estiver no Windows
if cfg!(target_os = "windows") {
Ok(())
} else {
Err("Verificação de permissões de rede apenas disponível no Windows".to_string())
}
}
/// Configura todas as permissões necessárias
pub fn setup_all_permissions() -> Result<PermissionStatus, String> {
system::info("Verificando e configurando permissões do Windows...");
let mut status = PermissionStatus {
admin: Self::check_admin(),
firewall_configured: false,
defender_exception: false,
network_ok: false,
issues: Vec::new(),
};
// Log status de admin
system::info("[1/4] Verificando privilégios de administrador...");
if status.admin {
system::info(" ✓ Executando com privilégios de administrador");
} else {
system::warn(" ⚠ Não está executando como administrador. Algumas configurações podem falhar.");
status.issues.push("Execução sem privilégios de administrador".to_string());
}
// Configurar firewall para porta 8080 (API)
system::info("[2/4] Configurando regras de firewall...");
system::info(" → Porta 8080 (API HTTP)...");
match Self::request_firewall_rule(8080, "API") {
Ok(_) => {
status.firewall_configured = true;
system::info(" ✓ Regra de firewall criada para porta 8080");
}
Err(e) => {
status.issues.push(format!("Firewall porta 8080: {}", e));
system::warn(&format!(" ✗ Falha: {}", e));
}
}
// Configurar firewall para porta 11434 (Ollama)
system::info(" → Porta 11434 (Ollama)...");
match Self::request_firewall_rule(11434, "Ollama") {
Ok(_) => {
// Se a porta 8080 foi configurada, manter firewall_configured como true
if !status.firewall_configured {
status.firewall_configured = true;
}
system::info(" ✓ Regra de firewall criada para porta 11434");
}
Err(e) => {
status.issues.push(format!("Firewall porta 11434: {}", e));
system::warn(&format!(" ✗ Falha: {}", e));
}
}
// Configurar exceção no Windows Defender
system::info("[3/4] Configurando exceção no Windows Defender...");
match Self::get_executable_path() {
Ok(exe_path) => {
let exe_str = exe_path.to_string_lossy().to_string();
system::info(&format!(" → Executável: {}", exe_str));
match Self::request_defender_exception(&exe_str) {
Ok(_) => {
status.defender_exception = true;
system::info(" ✓ Exceção adicionada no Windows Defender");
}
Err(e) => {
status.issues.push(format!("Windows Defender: {}", e));
system::warn(&format!(" ✗ Falha: {}", e));
}
}
}
Err(e) => {
status.issues.push(format!("Não foi possível obter caminho do executável: {}", e));
system::warn(&format!(" ✗ Não foi possível configurar exceção no Windows Defender: {}", e));
}
}
// Verificar permissões de rede
system::info("[4/4] Verificando permissões de rede...");
match Self::request_network_permissions() {
Ok(_) => {
status.network_ok = true;
system::info(" ✓ Permissões de rede OK");
}
Err(e) => {
status.issues.push(format!("Permissões de rede: {}", e));
system::warn(&format!(" ✗ Falha: {}", e));
}
}
// Resumo final
system::info("========================================");
if status.issues.is_empty() {
system::info("✓ Todas as permissões foram configuradas com sucesso!");
} else {
system::warn(&format!("⚠ {} problema(s) encontrado(s) durante configuração de permissões", status.issues.len()));
system::info("");
system::info("📋 Instruções manuais para resolver problemas:");
system::info("");
if !status.admin {
system::info(" 1. PRIVILÉGIOS DE ADMINISTRADOR:");
system::info(" → Clique com botão direito no executável");
system::info(" → Selecione 'Executar como administrador'");
system::info("");
}
if !status.firewall_configured {
system::info(" 2. REGRAS DE FIREWALL:");
system::info(" → Abra: Painel de Controle > Firewall do Windows > Configurações avançadas");
system::info(" → Clique em 'Regras de entrada' > 'Nova regra...'");
system::info(" → Tipo: Porta > TCP > Portas específicas: 8080, 11434");
system::info(" → Ação: Permitir a conexão");
system::info(" → Nome: 'OllaHubBackend API' e 'OllaHubBackend Ollama'");
system::info("");
}
if !status.defender_exception {
system::info(" 3. EXCEÇÃO NO WINDOWS DEFENDER:");
if let Ok(exe_path) = Self::get_executable_path() {
system::info(" → Abra: Windows Security > Virus & threat protection");
system::info(" → Clique em 'Manage settings' (Gerenciar configurações)");
system::info(" → Role até 'Exclusions' > 'Add or remove exclusions'");
system::info(" → Adicione exceção de 'File' com o caminho:");
system::info(&format!(" {}", exe_path.to_string_lossy()));
}
system::info("");
}
}
system::info("========================================");
Ok(status)
}
}