fixed build

This commit is contained in:
2025-05-30 08:31:24 +02:00
parent ceb5f43f15
commit 9bb88a253d
14 changed files with 425 additions and 166 deletions

View File

@ -0,0 +1,9 @@
# Nur dieser Inhalt in src-tauri/.cargo/config.toml
[target.aarch64-linux-android]
# Ersetze die Pfade durch deine tatsächlichen NDK-Pfade
# Dein NDK-Basispfad: /home/haex/Android/Sdk/ndk/29.0.13113456
# Stelle sicher, dass der clang-Name (mit API-Level, z.B. ...24-clang) korrekt ist.
linker = "/home/haex/Android/Sdk/ndk/29.0.13113456/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android33-clang"
#ar = "/home/haex/Android/Sdk/ndk/29.0.13113456/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar"
#ranlib = "/home/haex/Android/Sdk/ndk/29.0.13113456/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ranlib"

View File

@ -1,7 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- AndroidTV support -->
<uses-feature android:name="android.software.leanback" android:required="false" />

View File

@ -1,11 +1,15 @@
// database/mod.rs
pub mod core;
use rusqlite::Connection;
use rusqlite::{Connection, OpenFlags, Result as RusqliteResult};
use serde_json::Value as JsonValue;
use std::path::Path;
use std::fs;
use std::path::{Path, PathBuf};
use std::sync::Mutex;
use tauri::{path::BaseDirectory, AppHandle, Manager, State};
use tauri::utils::resources::Resource;
use tauri::{path::BaseDirectory, AppHandle, Manager, State, Wry};
use tokio::io::join;
pub struct DbConnection(pub Mutex<Option<Connection>>);
// Öffentliche Funktionen für direkten Datenbankzugriff
@ -29,7 +33,7 @@ pub async fn sql_execute(
/// Erstellt eine verschlüsselte Datenbank
#[tauri::command]
pub fn create_encrypted_database(
pub fn create_encrypted_database_old(
app_handle: AppHandle,
path: String,
key: String,
@ -39,7 +43,7 @@ pub fn create_encrypted_database(
let resource_path = app_handle
.path()
.resolve("resources/vault.db", BaseDirectory::Resource)
.resolve("vault.db", BaseDirectory::Resource)
.map_err(|e| format!("Fehler beim Auflösen des Ressourcenpfads: {}", e))?;
// Prüfen, ob die Ressourcendatei existiert
@ -229,3 +233,325 @@ pub fn open_encrypted_database(
Ok(format!("success"))
}
// Notwendige Imports an den Anfang des Moduls stellen
//use tauri::{AppHandle, Manager, State, path::BaseDirectory, Wry};
//use rusqlite::{Connection, OpenFlags, Result as RusqliteResult};
//use std::fs;
//use std::path::{Path, PathBuf};
//use std::sync::Mutex; // Für den State
// Stelle sicher, dass dein DbConnection-Typ hier bekannt ist.
// z.B. durch pub struct DbConnection(pub Mutex<Option<Connection>>);
// oder wenn es in einem anderen Modul ist: use crate::path_to::DbConnection;
// Für dieses Beispiel gehe ich davon aus, dass es in crate::DbConnection liegt.
// Ersetze `crate::DbConnection` mit dem korrekten Pfad zu deiner Definition.
//type SharedDbConnectionState = State<'_, crate::DbConnection>;
/// Hilfsfunktion: Lädt ein Asset und kopiert es in eine temporäre Datei.
/// Gibt den Pfad zur temporären Datei zurück.
fn prepare_temporary_asset_db(
app_handle: &AppHandle<Wry>,
asset_name: &str,
temp_base_dir: BaseDirectory,
) -> Result<PathBuf, String> {
println!("Lade Asset '{}' aus dem App-Bundle...", asset_name);
//.resolve("vault.db", BaseDirectory::Resource)
let asset_bytes = app_handle
.asset_resolver()
.get(asset_name.to_string())
.ok_or_else(|| format!("Asset '{}' wurde nicht im Bundle gefunden.", asset_name))?
.bytes()
.to_vec();
println!(
"Asset '{}' erfolgreich geladen ({} bytes).",
asset_name,
asset_bytes.len()
);
let temp_db_filename = format!("temp_unencrypted_{}", asset_name);
let temp_db_path = app_handle
.path()
.resolve(&temp_db_filename, temp_base_dir)
.map_err(|e| {
format!(
"Fehler beim Auflösen des Pfads für die temporäre DB '{}': {}",
temp_db_filename, e
)
})?;
println!(
"Temporärer Pfad für unverschlüsselte DB: {}",
temp_db_path.display()
);
if let Some(parent) = temp_db_path.parent() {
if !parent.exists() {
fs::create_dir_all(parent).map_err(|e| {
format!(
"Fehler beim Erstellen des temporären Verzeichnisses '{}': {}",
parent.display(),
e
)
})?;
println!("Temporäres Verzeichnis '{}' erstellt.", parent.display());
}
}
if temp_db_path.exists() {
fs::remove_file(&temp_db_path).map_err(|e| {
format!(
"Fehler beim Löschen der alten temporären DB '{}': {}",
temp_db_path.display(),
e
)
})?;
println!("Alte temporäre DB '{}' gelöscht.", temp_db_path.display());
}
fs::write(&temp_db_path, &asset_bytes).map_err(|e| {
format!(
"Fehler beim Schreiben der Asset-DB nach '{}': {}",
temp_db_path.display(),
e
)
})?;
println!(
"Asset-DB erfolgreich nach '{}' geschrieben.",
temp_db_path.display()
);
Ok(temp_db_path)
}
/// Hilfsfunktion: Verschlüsselt eine Quelldatenbank in eine Zieldatenbank.
fn encrypt_database_from_source(
unencrypted_source_path: &Path,
target_encrypted_path_str: &str,
key: &str,
) -> Result<(), String> {
println!(
"Öffne temporäre Quelldatenbank '{}'...",
unencrypted_source_path.display()
);
let source_conn = Connection::open(unencrypted_source_path).map_err(|e| {
format!(
"Fehler beim Öffnen der Quelldatenbank '{}': {}",
unencrypted_source_path.display(),
e
)
})?;
println!(
"Verbindung zur Quelldatenbank '{}' geöffnet.",
unencrypted_source_path.display()
);
let final_encrypted_db_path = PathBuf::from(target_encrypted_path_str);
println!(
"Zielpfad für verschlüsselte DB: {}",
final_encrypted_db_path.display()
);
if let Some(parent) = final_encrypted_db_path.parent() {
if !parent.exists() {
fs::create_dir_all(parent).map_err(|e| {
format!(
"Fehler beim Erstellen des Zielverzeichnisses '{}': {}",
parent.display(),
e
)
})?;
println!("Zielverzeichnis '{}' erstellt.", parent.display());
}
}
if final_encrypted_db_path.exists() {
fs::remove_file(&final_encrypted_db_path).map_err(|e| {
format!(
"Fehler beim Löschen der alten verschlüsselten DB '{}': {}",
final_encrypted_db_path.display(),
e
)
})?;
println!(
"Alte verschlüsselte DB '{}' gelöscht.",
final_encrypted_db_path.display()
);
}
let attach_path_str = final_encrypted_db_path.to_str().ok_or_else(|| {
format!(
"Ungültiger UTF-8 Pfad für ATTACH: {}",
final_encrypted_db_path.display()
)
})?;
println!(
"Hänge neue verschlüsselte DB an: '{}' mit KEY '{}'",
attach_path_str, key
);
source_conn
.execute(
"ATTACH DATABASE ?1 AS encrypted_vault KEY ?2;",
&[attach_path_str, key],
)
.map_err(|e| format!("Fehler bei ATTACH DATABASE an '{}': {}", attach_path_str, e))?;
println!("Verschlüsselte DB 'encrypted_vault' erfolgreich angehängt.");
println!("Exportiere Daten von 'main' (Quelle) nach 'encrypted_vault'...");
if let Err(e) = source_conn.execute("SELECT sqlcipher_export('encrypted_vault');", []) {
eprintln!("!!! FEHLER während sqlcipher_export: {}", e);
source_conn
.execute("DETACH DATABASE encrypted_vault;", [])
.ok(); // Best-effort cleanup
return Err(format!("Fehler bei sqlcipher_export: {}", e));
}
println!("SQLCipher Export nach 'encrypted_vault' erfolgreich.");
println!("Löse 'encrypted_vault'...");
source_conn
.execute("DETACH DATABASE encrypted_vault;", [])
.map_err(|e| format!("Fehler bei DETACH DATABASE 'encrypted_vault': {}", e))?;
println!("'encrypted_vault' erfolgreich gelöst.");
// Verbindung zur Quelldatenbank wird hier durch drop(source_conn) geschlossen.
Ok(())
}
/// Hilfsfunktion: Öffnet eine verschlüsselte Datenbank und verifiziert sie.
/// Gibt die geöffnete und verifizierte Verbindung zurück.
fn open_and_verify_encrypted_db(db_path: &Path, key: &str) -> Result<Connection, String> {
println!(
"Öffne verschlüsselte DB '{}' zur Überprüfung...",
db_path.display()
);
let conn = Connection::open(db_path).map_err(|e| {
format!(
"Fehler beim Öffnen der verschlüsselten DB '{}' für Check: {}",
db_path.display(),
e
)
})?;
conn.pragma_update(None, "key", key).map_err(|e| {
format!(
"Fehler beim Setzen des PRAGMA key für DB '{}': {}",
db_path.display(),
e
)
})?;
println!("PRAGMA key für DB '{}' gesetzt.", db_path.display());
println!("Prüfe SQLCipher-Version auf DB '{}'...", db_path.display());
match conn.query_row("PRAGMA cipher_version;", [], |row| row.get::<_, String>(0)) {
Ok(version) => {
println!(
"SQLCipher ist aktiv auf DB '{}'! Version: {}",
db_path.display(),
version
);
match conn.query_row(
"SELECT count(*) FROM sqlite_master WHERE type='table';",
[],
|row| row.get::<_, i32>(0),
) {
Ok(count) => println!(
"Testabfrage erfolgreich: {} Tabelle(n) in DB '{}' gefunden.",
count,
db_path.display()
),
Err(e) => {
eprintln!(
"Fehler bei Testabfrage auf verschlüsselter DB '{}': {}",
db_path.display(),
e
);
return Err(format!(
"Testabfrage auf verschlüsselter DB '{}' fehlgeschlagen: {}",
db_path.display(),
e
));
}
}
}
Err(e) => {
eprintln!(
"FEHLER: SQLCipher scheint NICHT aktiv zu sein auf DB '{}'!",
db_path.display()
);
eprintln!("'PRAGMA cipher_version;' schlug fehl: {}", e);
return Err(format!(
"SQLCipher Aktivitätscheck für DB '{}' fehlgeschlagen: {}",
db_path.display(),
e
));
}
}
Ok(conn)
}
/// Hauptfunktion: Erstellt eine verschlüsselte Datenbank aus einem gebündelten Asset.
#[tauri::command]
pub fn create_encrypted_database(
app_handle: AppHandle<Wry>,
path: String,
key: String,
state: State<'_, DbConnection>,
) -> Result<String, String> {
let asset_name = "database/vault.db";
let temp_db_path: PathBuf; // Muss deklariert werden, um im Fehlerfall aufgeräumt werden zu können
// Schritt 1: Asset vorbereiten
match prepare_temporary_asset_db(&app_handle, &asset_name, BaseDirectory::AppData) {
Ok(path) => temp_db_path = path,
Err(e) => return Err(e),
}
// Schritt 2: Datenbank verschlüsseln
// Wir geben einen String-Slice für path, da die Funktion das erwartet.
if let Err(e) = encrypt_database_from_source(&temp_db_path, &path, &key) {
// Versuche, die temporäre Datei auch im Fehlerfall zu löschen
let _ = fs::remove_file(&temp_db_path); // Fehler beim Löschen hier ignorieren
return Err(e);
}
// Schritt 3: Temporäre Datei aufräumen
if let Err(e) = fs::remove_file(&temp_db_path) {
// Logge den Fehler, aber fahre fort, da die verschlüsselte DB erstellt wurde
eprintln!("Warnung: Fehler beim Löschen der temporären DB '{}': {}. Die verschlüsselte DB wurde jedoch erstellt.", temp_db_path.display(), e);
} else {
println!(
"Temporäre DB '{}' erfolgreich gelöscht.",
temp_db_path.display()
);
}
println!("Datenbank erfolgreich nach '{}' verschlüsselt.", path);
// Schritt 4: Neu erstellte verschlüsselte Datenbank öffnen und verifizieren
let final_encrypted_db_path = PathBuf::from(path.clone()); // Klonen, da String für Pfad benötigt wird
let final_conn = match open_and_verify_encrypted_db(&final_encrypted_db_path, &key) {
Ok(conn) => conn,
Err(e) => {
// Wenn das Öffnen/Verifizieren fehlschlägt, existiert die Datei vielleicht, ist aber unbrauchbar.
// Je nach Strategie könnte man hier die `final_encrypted_db_path` löschen.
return Err(e);
}
};
// Schritt 5: Datenbankverbindung im State aktualisieren
println!(
"Aktualisiere DB-Verbindung im State mit '{}'",
final_encrypted_db_path.display()
);
let mut db_state_lock = state
.0
.lock()
.map_err(|e| format!("Mutex-Fehler beim Sperren des DB-Status: {}", e.to_string()))?;
*db_state_lock = Some(final_conn);
Ok(format!(
"Verschlüsselte Datenbank erfolgreich erstellt, geprüft und im State gespeichert unter: {}",
final_encrypted_db_path.display()
))
}

View File

@ -12,6 +12,73 @@ pub fn run() {
let protocol_name = "haex-extension";
tauri::Builder::default()
.setup(|app| {
// --- START DER ASSET-INVENTUR (Korrigierte Version) ---
println!("\n[INVENTUR] App-Setup wird ausgeführt. Liste alle Assets im Bundle auf...");
let mut found_assets_count = 0;
// KORREKTE METHODE: Direkt über eine Referenz auf den AssetResolver iterieren
for asset_name in app.asset_resolver().iter() {
found_assets_count += 1;
// Wir geben jeden gefundenen Asset-Namen aus
println!("[INVENTUR] Gefundenes Asset: '{}'", asset_name.0);
}
if found_assets_count == 0 {
println!("[INVENTUR] Es wurden KEINE Assets im Bundle gefunden!");
} else {
println!(
"[INVENTUR] Inventur abgeschlossen. {} Assets gefunden.",
found_assets_count
);
}
println!("[INVENTUR] --- ENDE DER INVENTUR ---\n");
// --- ENDE DER ASSET-INVENTUR ---
// --- START DES DEFINITIVEN ASSET-TESTS ---
println!("\n[DEBUG] App-Setup wird ausgeführt. Versuche, die Datenbank zu laden...");
// BITTE SICHERSTELLEN: Dieser String muss EXAKT dem SCHLÜSSEL (KEY)
// in deiner tauri.conf.json entsprechen!
let asset_to_find = "database/vault.db";
println!(
"[DEBUG] Suche nach Asset mit dem Alias: '{}'",
asset_to_find
);
match app.asset_resolver().get(asset_to_find.to_string()) {
Some(asset) => {
// ERFOLG! Das Asset wurde gefunden.
println!("\n✅ ✅ ✅ ERFOLG! ✅ ✅ ✅");
println!(
"[DEBUG] Asset '{}' wurde im Bundle gefunden.",
asset_to_find
);
println!("[DEBUG] Größe der Datenbank: {} Bytes.", asset.bytes.len());
}
None => {
// FEHLER! Das Asset wurde nicht gefunden.
println!("\n❌ ❌ ❌ FEHLER! ❌ ❌ ❌");
println!(
"[DEBUG] Asset '{}' wurde NICHT im Bundle gefunden.",
asset_to_find
);
println!("[DEBUG] Mögliche Ursachen:");
println!("[DEBUG] 1. Der Alias-String im Code ist falsch (Tippfehler?).");
println!("[DEBUG] 2. Der Schlüssel in 'tauri.conf.json' ist anders.");
println!(
"[DEBUG] 3. Der Build-Cache ist veraltet (lösche 'src-tauri/target')."
);
}
}
println!("[DEBUG] --- ENDE DES ASSET-TESTS ---\n");
// --- ENDE DES DEFINITIVEN ASSET-TESTS ---
// Hier kann dein restlicher Setup-Code stehen bleiben
Ok(())
})
.register_uri_scheme_protocol(protocol_name, move |context, request| {
match extension::core::extension_protocol_handler(&context, &request) {
Ok(response) => response, // Wenn der Handler Ok ist, gib die Response direkt zurück
@ -42,11 +109,11 @@ pub fn run() {
}
}
})
.plugin(tauri_plugin_http::init())
.manage(DbConnection(Mutex::new(None)))
.manage(ExtensionState::default())
.plugin(tauri_plugin_dialog::init())
.plugin(tauri_plugin_fs::init())
.plugin(tauri_plugin_http::init())
.plugin(tauri_plugin_opener::init())
.plugin(tauri_plugin_os::init())
.plugin(tauri_plugin_store::Builder::new().build())

View File

@ -5,9 +5,9 @@
"identifier": "space.haex.hub",
"build": {
"beforeDevCommand": "pnpm dev",
"devUrl": "http://0.0.0.0:3001",
"devUrl": "http://localhost:3000",
"beforeBuildCommand": "pnpm generate",
"frontendDist": "../.output/public"
"frontendDist": "../dist"
},
"app": {
"windows": [
@ -40,7 +40,7 @@
},
"assetProtocol": {
"enable": true,
"scope": ["*"]
"scope": ["$APPDATA", "$RESOURCE"]
}
}
},
@ -54,22 +54,6 @@
"icons/icon.icns",
"icons/icon.ico"
],
"resources": {
"database/vault.db": "resources/vault.db"
},
"linux": {
"appimage": {
"bundleMediaFramework": false,
"files": {}
},
"deb": {
"files": {}
},
"rpm": {
"epoch": 0,
"files": {},
"release": "1"
}
}
"resources": ["test.txt"]
}
}

0
src-tauri/test.txt Normal file
View File