262 lines
11 KiB
Rust
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)
|
|
}
|
|
}
|
|
|