game_manager_lib\commands/
settings.rs

1//! Módulo de gerenciamento de configurações e secrets.
2//!
3//! Fornece interface para armazenar e recuperar credenciais
4//! sensíveis (API keys, IDs) de forma segura usando criptografia.
5//! Todos os secrets são criptografados usando AES-256-GCM antes de serem salvas no banco de dados.
6//! A chave de criptografia é derivada de características únicas via `security::init_security()`.
7
8use crate::database;
9use crate::errors::AppError;
10use serde::{Deserialize, Serialize};
11use tauri::AppHandle;
12
13/// Lote de todas as API keys configuradas no sistema.
14///
15/// Usado para retornar múltiplos secrets de uma vez para o frontend.
16#[derive(Serialize, Deserialize)]
17pub struct KeysBatch {
18    #[serde(rename = "steamId")]
19    pub steam_id: String,
20    #[serde(rename = "steamApiKey")]
21    pub steam_api_key: String,
22    #[serde(rename = "rawgApiKey")]
23    pub rawg_api_key: String,
24    #[serde(rename = "geminiApiKey")]
25    pub gemini_api_key: String,
26}
27
28/// Recupera todos os secrets configurados em lote.
29///
30/// Busca e descriptografa todas as credenciais armazenadas,
31/// retornando strings vazias para secrets não configurados.
32#[tauri::command]
33pub fn get_secrets(app: AppHandle) -> Result<KeysBatch, AppError> {
34    Ok(KeysBatch {
35        steam_id: database::get_secret(&app, "steam_id")?,
36        steam_api_key: database::get_secret(&app, "steam_api_key")?,
37        rawg_api_key: database::get_secret(&app, "rawg_api_key")?,
38        gemini_api_key: database::get_secret(&app, "gemini_api_key")?,
39    })
40}
41
42/// Configura múltiplos secrets numa única operação.
43///
44/// Permite atualizar várias credenciais simultaneamente.
45/// Mantém a compatibilidade com o objeto JSON enviado pelo frontend.
46#[tauri::command]
47pub fn set_secrets(
48    app: AppHandle,
49    steam_id: Option<String>,
50    steam_api_key: Option<String>,
51    rawg_api_key: Option<String>,
52    gemini_api_key: Option<String>,
53) -> Result<(), AppError> {
54    // Helper para salvar ou deletar baseado no valor
55    let save_or_delete = |key: &str, value: Option<String>| -> Result<(), AppError> {
56        if let Some(v) = value {
57            let trimmed = v.trim();
58            if trimmed.is_empty() {
59                database::delete_secret(&app, key)?;
60            } else {
61                database::set_secret(&app, key, trimmed)?;
62            }
63        }
64        Ok(())
65    };
66
67    save_or_delete("steam_id", steam_id)?;
68    save_or_delete("steam_api_key", steam_api_key)?;
69    save_or_delete("rawg_api_key", rawg_api_key)?;
70    save_or_delete("gemini_api_key", gemini_api_key)?;
71
72    Ok(())
73}
74
75/// Define um secret individual por nome de chave.
76///
77/// Versão genérica que permite configurar qualquer secret suportado fornecendo nome e valor.
78#[tauri::command]
79pub fn set_secret(app: AppHandle, key_name: String, key_value: String) -> Result<(), AppError> {
80    let trimmed_val = key_value.trim();
81
82    if trimmed_val.is_empty() {
83        return Err(AppError::ValidationError(
84            "Valor não pode ser vazio".to_string(),
85        ));
86    }
87
88    database::set_secret(&app, &key_name, trimmed_val)
89}
90
91/// Recupera um secret individual por nome de chave.
92///
93/// Busca e descriptografa uma credencial específica do banco.
94#[tauri::command]
95pub fn get_secret(app: AppHandle, key_name: String) -> Result<String, AppError> {
96    database::get_secret(&app, &key_name)
97}
98
99/// Remove permanentemente um secret do banco.
100///
101/// Exclui a credencial criptografada do banco de dados. Operação irreversível.
102#[tauri::command]
103pub fn delete_secret(app: AppHandle, key_name: String) -> Result<(), AppError> {
104    database::delete_secret(&app, &key_name)
105}
106
107/// Lista todos os nomes de secrets suportados pelo sistema.
108///
109/// Retorna lista com os nomes de todas as credenciais que podem
110/// ser configuradas, útil para validação no frontend.
111#[tauri::command]
112pub fn list_secrets() -> Vec<String> {
113    database::list_supported_keys()
114        .into_iter()
115        .map(|s| s.to_string())
116        .collect()
117}