Refactor decryption logic to handle empty fields consistently across services
This commit is contained in:
@@ -14,6 +14,18 @@ export default function LoginPage() {
|
||||
const {lang, setLang} = useContext(LangContext);
|
||||
const [showOfflineWarning, setShowOfflineWarning] = useState(false);
|
||||
const [isOnline, setIsOnline] = useState(true);
|
||||
const [resetDone, setResetDone] = useState(false);
|
||||
|
||||
const isDev = process.env.NODE_ENV === 'development';
|
||||
|
||||
const handleDevReset = async () => {
|
||||
try {
|
||||
await tauri.devResetAll();
|
||||
setResetDone(true);
|
||||
} catch (error) {
|
||||
console.error('[DevReset]', error);
|
||||
}
|
||||
};
|
||||
|
||||
const toggleLanguage = () => {
|
||||
const newLang = lang === 'fr' ? 'en' : 'fr';
|
||||
@@ -148,6 +160,13 @@ export default function LoginPage() {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{isDev && (
|
||||
resetDone
|
||||
? <span className="mt-6 text-xs text-green-400">Reset OK</span>
|
||||
: <button onClick={handleDevReset} className="mt-6 px-4 py-2 text-xs text-red-400 border border-red-400/30 rounded-lg hover:bg-red-400/10 transition-colors">
|
||||
DEV: Reset All Data
|
||||
</button>
|
||||
)}
|
||||
</main>
|
||||
);
|
||||
}
|
||||
@@ -588,7 +588,7 @@ function ScribeContent() {
|
||||
const offlineStatus = await tauri.offlineModeGet();
|
||||
|
||||
if (offlineStatus.hasPin && offlineStatus.lastUserId) {
|
||||
setOfflineMode((prev:OfflineMode):OfflineMode => ({...prev, isOffline: true, isNetworkOnline: false}));
|
||||
setOfflineMode((prev:OfflineMode):OfflineMode => ({...prev, isOffline: true, isManuallyOffline: true, isNetworkOnline: false}));
|
||||
setShowPinVerify(true);
|
||||
setIsLoading(false);
|
||||
return;
|
||||
@@ -611,7 +611,7 @@ function ScribeContent() {
|
||||
const offlineStatus = await tauri.offlineModeGet();
|
||||
|
||||
if (offlineStatus.hasPin && offlineStatus.lastUserId) {
|
||||
setOfflineMode(prev => ({...prev, isOffline: true, isNetworkOnline: false}));
|
||||
setOfflineMode(prev => ({...prev, isOffline: true, isManuallyOffline: true, isNetworkOnline: false}));
|
||||
setShowPinVerify(true);
|
||||
setIsLoading(false);
|
||||
return;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import React, {useContext, useState} from "react";
|
||||
import * as tauri from '@/lib/tauri';
|
||||
import {ChapterProps, chapterVersions} from "@/lib/models/Chapter";
|
||||
import {ChapterContext} from "@/context/ChapterContext";
|
||||
import {BookContext} from "@/context/BookContext";
|
||||
@@ -39,11 +40,16 @@ export default function ScribeControllerBar() {
|
||||
|
||||
async function handleChapterVersionChanged(version: number) {
|
||||
try {
|
||||
const response: ChapterProps = await System.authGetQueryToServer<ChapterProps>(`chapter/whole`, session.accessToken, lang, {
|
||||
let response: ChapterProps | null;
|
||||
if (isCurrentlyOffline() || book?.localBook) {
|
||||
response = await tauri.getWholeChapter(chapter?.chapterId ?? '', version, book?.bookId ?? '');
|
||||
} else {
|
||||
response = await System.authGetQueryToServer<ChapterProps>(`chapter/whole`, session.accessToken, lang, {
|
||||
bookid: book?.bookId,
|
||||
id: chapter?.chapterId,
|
||||
version: version,
|
||||
});
|
||||
}
|
||||
if (!response) {
|
||||
errorMessage(t("controllerBar.chapterNotFound"));
|
||||
return;
|
||||
|
||||
@@ -204,11 +204,9 @@ export default function AddNewBookForm({setCloseForm}: { setCloseForm: Dispatch<
|
||||
setIsAddingBook(false);
|
||||
setCloseForm(false)
|
||||
} catch (e: unknown) {
|
||||
if (e instanceof Error) {
|
||||
errorMessage(e.message);
|
||||
} else {
|
||||
errorMessage(t('addNewBookForm.error.addingBook'));
|
||||
}
|
||||
console.error('[AddBook] Raw error:', e, typeof e, JSON.stringify(e));
|
||||
const msg = e instanceof Error ? e.message : typeof e === 'object' && e !== null && 'message' in e ? String((e as {message:string}).message) : typeof e === 'string' ? e : t('addNewBookForm.error.addingBook');
|
||||
errorMessage(msg);
|
||||
setIsAddingBook(false);
|
||||
}
|
||||
}
|
||||
@@ -250,7 +248,7 @@ export default function AddNewBookForm({setCloseForm}: { setCloseForm: Dispatch<
|
||||
|
||||
return (
|
||||
<div
|
||||
className="fixed inset-0 flex items-center justify-center bg-black/60 z-50 backdrop-blur-md animate-fadeIn">
|
||||
className="fixed inset-0 flex items-center justify-center bg-black/60 z-40 backdrop-blur-md animate-fadeIn">
|
||||
<div ref={modalRef}
|
||||
className="bg-tertiary/95 backdrop-blur-sm text-text-primary rounded-2xl border border-secondary/50 shadow-2xl md:w-3/4 xl:w-1/4 lg:w-2/4 sm:w-11/12 max-h-[85vh] flex flex-col">
|
||||
<div className="flex justify-between items-center bg-primary px-6 py-4 rounded-t-2xl shadow-lg">
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
/**
|
||||
* Clean error messages from Electron IPC prefix
|
||||
* Transforms: "Error invoking remote method 'channel': Error: Message"
|
||||
* Into: "Message"
|
||||
* Extract user-facing error message from various error formats.
|
||||
* Supports: Error objects, Tauri AppError { kind, message }, and plain strings.
|
||||
*/
|
||||
export function cleanErrorMessage(error: unknown): string {
|
||||
if (error instanceof Error) {
|
||||
return error.message.replace(/^Error invoking remote method '[^']+': Error: /, '');
|
||||
return error.message;
|
||||
}
|
||||
if (typeof error === 'object' && error !== null && 'message' in error) {
|
||||
return String((error as { message: string }).message);
|
||||
}
|
||||
if (typeof error === 'string') {
|
||||
return error.replace(/^Error invoking remote method '[^']+': Error: /, '');
|
||||
return error;
|
||||
}
|
||||
return 'An unknown error occurred';
|
||||
}
|
||||
|
||||
@@ -165,3 +165,7 @@ pub fn get_last_user_id() -> AppResult<Option<String>> {
|
||||
let vault = read_vault();
|
||||
Ok(vault.last_user_id)
|
||||
}
|
||||
|
||||
pub fn clear_vault() -> AppResult<()> {
|
||||
write_vault(&SecureVault::default())
|
||||
}
|
||||
|
||||
@@ -53,6 +53,14 @@ impl DatabaseManager {
|
||||
pub fn close(&mut self, user_id: &str) {
|
||||
self.connections.remove(user_id);
|
||||
}
|
||||
|
||||
pub fn close_all(&mut self) {
|
||||
self.connections.clear();
|
||||
}
|
||||
|
||||
pub fn base_path(&self) -> &PathBuf {
|
||||
&self.base_path
|
||||
}
|
||||
}
|
||||
|
||||
pub type DbManager = Arc<Mutex<DatabaseManager>>;
|
||||
|
||||
@@ -38,6 +38,7 @@ pub struct CreateBookData {
|
||||
pub title: String,
|
||||
pub sub_title: Option<String>,
|
||||
pub summary: Option<String>,
|
||||
#[serde(rename = "type")]
|
||||
pub book_type: String,
|
||||
pub serie_id: Option<i64>,
|
||||
pub desired_release_date: Option<String>,
|
||||
|
||||
@@ -722,8 +722,14 @@ pub fn get_books(conn: &Connection, user_id: &str, lang: Lang) -> AppResult<Vec<
|
||||
let mut book_props_list: Vec<BookProps> = Vec::with_capacity(books.len());
|
||||
for book in books {
|
||||
let decrypted_title: String = decrypt_data_with_user_key(&book.title, &user_key)?;
|
||||
let decrypted_sub_title: String = if let Some(ref sub_title) = book.sub_title { decrypt_data_with_user_key(sub_title, &user_key)? } else { String::new() };
|
||||
let decrypted_summary: String = if let Some(ref summary) = book.summary { decrypt_data_with_user_key(summary, &user_key)? } else { String::new() };
|
||||
let decrypted_sub_title: String = match book.sub_title.as_deref() {
|
||||
Some(sub_title) if !sub_title.is_empty() => decrypt_data_with_user_key(sub_title, &user_key)?,
|
||||
_ => String::new(),
|
||||
};
|
||||
let decrypted_summary: String = match book.summary.as_deref() {
|
||||
Some(summary) if !summary.is_empty() => decrypt_data_with_user_key(summary, &user_key)?,
|
||||
_ => String::new(),
|
||||
};
|
||||
|
||||
book_props_list.push(BookProps {
|
||||
book_id: book.book_id,
|
||||
@@ -769,6 +775,7 @@ pub fn add_book(
|
||||
let encrypted_title: String = encrypt_data_with_user_key(title, &user_key)?;
|
||||
let encrypted_sub_title: String = if sub_title.is_empty() { String::new() } else { encrypt_data_with_user_key(sub_title, &user_key)? };
|
||||
let encrypted_summary: String = if summary.is_empty() { String::new() } else { encrypt_data_with_user_key(summary, &user_key)? };
|
||||
|
||||
let hashed_title: String = hash_element(title);
|
||||
let hashed_sub_title: String = if sub_title.is_empty() { String::new() } else { hash_element(sub_title) };
|
||||
|
||||
@@ -795,8 +802,14 @@ pub fn get_book(conn: &Connection, user_id: &str, book_id: &str, lang: Lang) ->
|
||||
let series_id: Option<String> = repo::fetch_book_series_id(conn, book_id, lang);
|
||||
|
||||
let decrypted_title: String = decrypt_data_with_user_key(&book_data.title, &user_key)?;
|
||||
let decrypted_sub_title: String = if let Some(ref sub_title) = book_data.sub_title { decrypt_data_with_user_key(sub_title, &user_key)? } else { String::new() };
|
||||
let decrypted_summary: String = if let Some(ref summary) = book_data.summary { decrypt_data_with_user_key(summary, &user_key)? } else { String::new() };
|
||||
let decrypted_sub_title: String = match book_data.sub_title.as_deref() {
|
||||
Some(sub_title) if !sub_title.is_empty() => decrypt_data_with_user_key(sub_title, &user_key)?,
|
||||
_ => String::new(),
|
||||
};
|
||||
let decrypted_summary: String = match book_data.summary.as_deref() {
|
||||
Some(summary) if !summary.is_empty() => decrypt_data_with_user_key(summary, &user_key)?,
|
||||
_ => String::new(),
|
||||
};
|
||||
|
||||
Ok(BookProps {
|
||||
book_id: book_data.book_id,
|
||||
@@ -892,7 +905,7 @@ pub fn complete_book_data(conn: &Connection, user_id: &str, book_id: &str, lang:
|
||||
|
||||
for chapter in chapters {
|
||||
let decrypted_title: String = if chapter.title.is_empty() { String::new() } else { decrypt_data_with_user_key(&chapter.title, &user_key)? };
|
||||
let decrypted_content: String = if let Some(ref content) = chapter.content { decrypt_data_with_user_key(content, &user_key)? } else { String::new() };
|
||||
let decrypted_content: String = if let Some(ref content) = chapter.content { if content.is_empty() { String::new() } else { decrypt_data_with_user_key(content, &user_key)? } } else { String::new() };
|
||||
decrypted_chapters.push(CompleteChapterContent {
|
||||
id: String::new(),
|
||||
title: decrypted_title,
|
||||
@@ -907,12 +920,12 @@ pub fn complete_book_data(conn: &Connection, user_id: &str, book_id: &str, lang:
|
||||
Ok(CompleteBookData {
|
||||
book_id: book_id.to_string(),
|
||||
title: book_title,
|
||||
sub_title: if let Some(ref sub_title) = book_data.sub_title { decrypt_data_with_user_key(sub_title, &user_key)? } else { String::new() },
|
||||
summary: if let Some(ref summary) = book_data.summary { decrypt_data_with_user_key(summary, &user_key)? } else { String::new() },
|
||||
sub_title: if let Some(ref sub_title) = book_data.sub_title { if sub_title.is_empty() { String::new() } else { decrypt_data_with_user_key(sub_title, &user_key)? } } else { String::new() },
|
||||
summary: if let Some(ref summary) = book_data.summary { if summary.is_empty() { String::new() } else { decrypt_data_with_user_key(summary, &user_key)? } } else { String::new() },
|
||||
cover_image,
|
||||
user_infos: BookUserInfos {
|
||||
username: decrypt_data_with_user_key(&user_infos.username, &user_key)?,
|
||||
author_name: if let Some(ref author_name) = user_infos.author_name { decrypt_data_with_user_key(author_name, &user_key)? } else { String::new() },
|
||||
username: if user_infos.username.is_empty() { String::new() } else { decrypt_data_with_user_key(&user_infos.username, &user_key)? },
|
||||
author_name: if let Some(ref author_name) = user_infos.author_name { if author_name.is_empty() { String::new() } else { decrypt_data_with_user_key(author_name, &user_key)? } } else { String::new() },
|
||||
},
|
||||
chapters: decrypted_chapters,
|
||||
})
|
||||
|
||||
@@ -368,8 +368,8 @@ pub fn get_chapter_story(conn: &Connection, user_id: &str, chapter_id: &str, lan
|
||||
}
|
||||
|
||||
if let Some(ref _incident_id) = story_result.incident_id {
|
||||
let decrypted_incident_title: String = if let Some(ref incident_title) = story_result.incident_title { decrypt_data_with_user_key(incident_title, &user_encryption_key)? } else { String::new() };
|
||||
let decrypted_incident_summary: String = if let Some(ref incident_summary) = story_result.incident_summary { decrypt_data_with_user_key(incident_summary, &user_encryption_key)? } else { String::new() };
|
||||
let decrypted_incident_title: String = if let Some(ref incident_title) = story_result.incident_title { if incident_title.is_empty() { String::new() } else { decrypt_data_with_user_key(incident_title, &user_encryption_key)? } } else { String::new() };
|
||||
let decrypted_incident_summary: String = if let Some(ref incident_summary) = story_result.incident_summary { if incident_summary.is_empty() { String::new() } else { decrypt_data_with_user_key(incident_summary, &user_encryption_key)? } } else { String::new() };
|
||||
|
||||
let act_story = act_stories_map.get(&act_id).unwrap();
|
||||
let incident_already_exists: bool = act_story.incidents.iter().any(
|
||||
@@ -390,8 +390,8 @@ pub fn get_chapter_story(conn: &Connection, user_id: &str, chapter_id: &str, lan
|
||||
}
|
||||
|
||||
if let Some(ref _plot_point_id) = story_result.plot_point_id {
|
||||
let decrypted_plot_title: String = if let Some(ref plot_title) = story_result.plot_title { decrypt_data_with_user_key(plot_title, &user_encryption_key)? } else { String::new() };
|
||||
let decrypted_plot_summary: String = if let Some(ref plot_summary) = story_result.plot_summary { decrypt_data_with_user_key(plot_summary, &user_encryption_key)? } else { String::new() };
|
||||
let decrypted_plot_title: String = if let Some(ref plot_title) = story_result.plot_title { if plot_title.is_empty() { String::new() } else { decrypt_data_with_user_key(plot_title, &user_encryption_key)? } } else { String::new() };
|
||||
let decrypted_plot_summary: String = if let Some(ref plot_summary) = story_result.plot_summary { if plot_summary.is_empty() { String::new() } else { decrypt_data_with_user_key(plot_summary, &user_encryption_key)? } } else { String::new() };
|
||||
|
||||
let act_story = act_stories_map.get(&act_id).unwrap();
|
||||
let plot_point_already_exists: bool = act_story.plot_points.iter().any(
|
||||
|
||||
@@ -130,23 +130,23 @@ pub fn get_character_list(conn: &Connection, user_id: &str, book_id: &str, lang:
|
||||
id: encrypted_character.character_id,
|
||||
name: if encrypted_character.first_name.is_empty() { String::new() } else { decrypt_data_with_user_key(&encrypted_character.first_name, &user_key)? },
|
||||
last_name: if encrypted_character.last_name.is_empty() { String::new() } else { decrypt_data_with_user_key(&encrypted_character.last_name, &user_key)? },
|
||||
nickname: if let Some(ref value) = encrypted_character.nickname { decrypt_data_with_user_key(value, &user_key)? } else { String::new() },
|
||||
age: if let Some(ref value) = encrypted_character.age { Some(decrypt_data_with_user_key(value, &user_key)?.parse::<i64>().unwrap_or(0)) } else { None },
|
||||
gender: if let Some(ref value) = encrypted_character.gender { decrypt_data_with_user_key(value, &user_key)? } else { String::new() },
|
||||
species: if let Some(ref value) = encrypted_character.species { decrypt_data_with_user_key(value, &user_key)? } else { String::new() },
|
||||
nationality: if let Some(ref value) = encrypted_character.nationality { decrypt_data_with_user_key(value, &user_key)? } else { String::new() },
|
||||
status: if let Some(ref value) = encrypted_character.status { decrypt_data_with_user_key(value, &user_key)? } else { "alive".to_string() },
|
||||
nickname: if let Some(ref nickname) = encrypted_character.nickname { if nickname.is_empty() { String::new() } else { decrypt_data_with_user_key(nickname, &user_key)? } } else { String::new() },
|
||||
age: if let Some(ref age_val) = encrypted_character.age { if age_val.is_empty() { None } else { Some(decrypt_data_with_user_key(age_val, &user_key)?.parse::<i64>().unwrap_or(0)) } } else { None },
|
||||
gender: if let Some(ref gender) = encrypted_character.gender { if gender.is_empty() { String::new() } else { decrypt_data_with_user_key(gender, &user_key)? } } else { String::new() },
|
||||
species: if let Some(ref species) = encrypted_character.species { if species.is_empty() { String::new() } else { decrypt_data_with_user_key(species, &user_key)? } } else { String::new() },
|
||||
nationality: if let Some(ref nationality) = encrypted_character.nationality { if nationality.is_empty() { String::new() } else { decrypt_data_with_user_key(nationality, &user_key)? } } else { String::new() },
|
||||
status: if let Some(ref status) = encrypted_character.status { if status.is_empty() { "alive".to_string() } else { decrypt_data_with_user_key(status, &user_key)? } } else { "alive".to_string() },
|
||||
title: if encrypted_character.title.is_empty() { String::new() } else { decrypt_data_with_user_key(&encrypted_character.title, &user_key)? },
|
||||
category: if encrypted_character.category.is_empty() { String::new() } else { decrypt_data_with_user_key(&encrypted_character.category, &user_key)? },
|
||||
image: if encrypted_character.image.is_empty() { String::new() } else { decrypt_data_with_user_key(&encrypted_character.image, &user_key)? },
|
||||
role: if encrypted_character.role.is_empty() { String::new() } else { decrypt_data_with_user_key(&encrypted_character.role, &user_key)? },
|
||||
biography: if encrypted_character.biography.is_empty() { String::new() } else { decrypt_data_with_user_key(&encrypted_character.biography, &user_key)? },
|
||||
history: if encrypted_character.history.is_empty() { String::new() } else { decrypt_data_with_user_key(&encrypted_character.history, &user_key)? },
|
||||
speech_pattern: if let Some(ref value) = encrypted_character.speech_pattern { decrypt_data_with_user_key(value, &user_key)? } else { String::new() },
|
||||
catchphrase: if let Some(ref value) = encrypted_character.catchphrase { decrypt_data_with_user_key(value, &user_key)? } else { String::new() },
|
||||
residence: if let Some(ref value) = encrypted_character.residence { decrypt_data_with_user_key(value, &user_key)? } else { String::new() },
|
||||
notes: if let Some(ref value) = encrypted_character.notes { decrypt_data_with_user_key(value, &user_key)? } else { String::new() },
|
||||
color: if let Some(ref value) = encrypted_character.color { decrypt_data_with_user_key(value, &user_key)? } else { String::new() },
|
||||
speech_pattern: if let Some(ref speech_pattern) = encrypted_character.speech_pattern { if speech_pattern.is_empty() { String::new() } else { decrypt_data_with_user_key(speech_pattern, &user_key)? } } else { String::new() },
|
||||
catchphrase: if let Some(ref catchphrase) = encrypted_character.catchphrase { if catchphrase.is_empty() { String::new() } else { decrypt_data_with_user_key(catchphrase, &user_key)? } } else { String::new() },
|
||||
residence: if let Some(ref residence) = encrypted_character.residence { if residence.is_empty() { String::new() } else { decrypt_data_with_user_key(residence, &user_key)? } } else { String::new() },
|
||||
notes: if let Some(ref notes) = encrypted_character.notes { if notes.is_empty() { String::new() } else { decrypt_data_with_user_key(notes, &user_key)? } } else { String::new() },
|
||||
color: if let Some(ref color) = encrypted_character.color { if color.is_empty() { String::new() } else { decrypt_data_with_user_key(color, &user_key)? } } else { String::new() },
|
||||
series_character_id: encrypted_character.series_character_id,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -131,11 +131,11 @@ pub fn get_guide_line_ai(conn: &Connection, user_id: &str, book_id: &str, lang:
|
||||
Ok(GuideLineAI {
|
||||
narrative_type: ai_guide_line_data.narrative_type,
|
||||
dialogue_type: ai_guide_line_data.dialogue_type,
|
||||
global_resume: Some(if let Some(ref global_resume) = ai_guide_line_data.global_resume { decrypt_data_with_user_key(global_resume, &encryption_key)? } else { String::new() }),
|
||||
atmosphere: Some(if let Some(ref atmosphere) = ai_guide_line_data.atmosphere { decrypt_data_with_user_key(atmosphere, &encryption_key)? } else { String::new() }),
|
||||
global_resume: Some(if let Some(ref global_resume) = ai_guide_line_data.global_resume { if global_resume.is_empty() { String::new() } else { decrypt_data_with_user_key(global_resume, &encryption_key)? } } else { String::new() }),
|
||||
atmosphere: Some(if let Some(ref atmosphere) = ai_guide_line_data.atmosphere { if atmosphere.is_empty() { String::new() } else { decrypt_data_with_user_key(atmosphere, &encryption_key)? } } else { String::new() }),
|
||||
verbe_tense: ai_guide_line_data.verbe_tense,
|
||||
themes: Some(if let Some(ref themes) = ai_guide_line_data.themes { decrypt_data_with_user_key(themes, &encryption_key)? } else { String::new() }),
|
||||
current_resume: Some(if let Some(ref current_resume) = ai_guide_line_data.current_resume { decrypt_data_with_user_key(current_resume, &encryption_key)? } else { String::new() }),
|
||||
themes: Some(if let Some(ref themes) = ai_guide_line_data.themes { if themes.is_empty() { String::new() } else { decrypt_data_with_user_key(themes, &encryption_key)? } } else { String::new() }),
|
||||
current_resume: Some(if let Some(ref current_resume) = ai_guide_line_data.current_resume { if current_resume.is_empty() { String::new() } else { decrypt_data_with_user_key(current_resume, &encryption_key)? } } else { String::new() }),
|
||||
langue: ai_guide_line_data.langue,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ pub fn get_series_list(conn: &Connection, user_id: &str, lang: Lang) -> AppResul
|
||||
let mut series_list: Vec<SeriesListItemProps> = Vec::with_capacity(series_results.len());
|
||||
for series_item in series_results {
|
||||
let decrypted_name: String = decrypt_data_with_user_key(&series_item.name, &user_key)?;
|
||||
let decrypted_description: String = if let Some(ref description) = series_item.description { decrypt_data_with_user_key(description, &user_key)? } else { String::new() };
|
||||
let decrypted_description: String = if let Some(ref description) = series_item.description { if description.is_empty() { String::new() } else { decrypt_data_with_user_key(description, &user_key)? } } else { String::new() };
|
||||
let book_ids: Vec<String> = if let Some(ref book_ids_str) = series_item.book_ids { book_ids_str.split(',').map(|s| s.to_string()).collect() } else { vec![] };
|
||||
|
||||
series_list.push(SeriesListItemProps {
|
||||
@@ -102,7 +102,7 @@ pub fn get_series_detail(conn: &Connection, user_id: &str, series_id: &str, lang
|
||||
}
|
||||
|
||||
let decrypted_name: String = decrypt_data_with_user_key(&series_result.name, &user_key)?;
|
||||
let decrypted_description: String = if let Some(ref description) = series_result.description { decrypt_data_with_user_key(description, &user_key)? } else { String::new() };
|
||||
let decrypted_description: String = if let Some(ref description) = series_result.description { if description.is_empty() { String::new() } else { decrypt_data_with_user_key(description, &user_key)? } } else { String::new() };
|
||||
|
||||
Ok(SeriesDetailProps {
|
||||
id: series_result.series_id,
|
||||
|
||||
@@ -112,23 +112,23 @@ pub fn get_character_list(conn: &Connection, user_id: &str, series_id: &str, lan
|
||||
for character in characters {
|
||||
let decrypted_name: String = if !character.first_name.is_empty() { decrypt_data_with_user_key(&character.first_name, &user_key)? } else { String::new() };
|
||||
let decrypted_last_name: String = if !character.last_name.is_empty() { decrypt_data_with_user_key(&character.last_name, &user_key)? } else { String::new() };
|
||||
let decrypted_nickname: String = if let Some(ref nickname) = character.nickname { decrypt_data_with_user_key(nickname, &user_key)? } else { String::new() };
|
||||
let decrypted_age: Option<i64> = if let Some(ref age) = character.age { Some(decrypt_data_with_user_key(age, &user_key)?.parse::<i64>().unwrap_or(0)) } else { None };
|
||||
let decrypted_gender: String = if let Some(ref gender) = character.gender { decrypt_data_with_user_key(gender, &user_key)? } else { String::new() };
|
||||
let decrypted_species: String = if let Some(ref species) = character.species { decrypt_data_with_user_key(species, &user_key)? } else { String::new() };
|
||||
let decrypted_nationality: String = if let Some(ref nationality) = character.nationality { decrypt_data_with_user_key(nationality, &user_key)? } else { String::new() };
|
||||
let decrypted_status: String = if let Some(ref status) = character.status { decrypt_data_with_user_key(status, &user_key)? } else { "alive".to_string() };
|
||||
let decrypted_nickname: String = if let Some(ref nickname) = character.nickname { if nickname.is_empty() { String::new() } else { decrypt_data_with_user_key(nickname, &user_key)? } } else { String::new() };
|
||||
let decrypted_age: Option<i64> = if let Some(ref age) = character.age { if age.is_empty() { None } else { Some(decrypt_data_with_user_key(age, &user_key)?.parse::<i64>().unwrap_or(0)) } } else { None };
|
||||
let decrypted_gender: String = if let Some(ref gender) = character.gender { if gender.is_empty() { String::new() } else { decrypt_data_with_user_key(gender, &user_key)? } } else { String::new() };
|
||||
let decrypted_species: String = if let Some(ref species) = character.species { if species.is_empty() { String::new() } else { decrypt_data_with_user_key(species, &user_key)? } } else { String::new() };
|
||||
let decrypted_nationality: String = if let Some(ref nationality) = character.nationality { if nationality.is_empty() { String::new() } else { decrypt_data_with_user_key(nationality, &user_key)? } } else { String::new() };
|
||||
let decrypted_status: String = if let Some(ref status) = character.status { if status.is_empty() { "alive".to_string() } else { decrypt_data_with_user_key(status, &user_key)? } } else { "alive".to_string() };
|
||||
let decrypted_title: String = if !character.title.is_empty() { decrypt_data_with_user_key(&character.title, &user_key)? } else { String::new() };
|
||||
let decrypted_category: String = if !character.category.is_empty() { decrypt_data_with_user_key(&character.category, &user_key)? } else { String::new() };
|
||||
let decrypted_image: String = if !character.image.is_empty() { decrypt_data_with_user_key(&character.image, &user_key)? } else { String::new() };
|
||||
let decrypted_role: String = if !character.role.is_empty() { decrypt_data_with_user_key(&character.role, &user_key)? } else { String::new() };
|
||||
let decrypted_biography: String = if !character.biography.is_empty() { decrypt_data_with_user_key(&character.biography, &user_key)? } else { String::new() };
|
||||
let decrypted_history: String = if !character.history.is_empty() { decrypt_data_with_user_key(&character.history, &user_key)? } else { String::new() };
|
||||
let decrypted_speech_pattern: String = if let Some(ref speech_pattern) = character.speech_pattern { decrypt_data_with_user_key(speech_pattern, &user_key)? } else { String::new() };
|
||||
let decrypted_catchphrase: String = if let Some(ref catchphrase) = character.catchphrase { decrypt_data_with_user_key(catchphrase, &user_key)? } else { String::new() };
|
||||
let decrypted_residence: String = if let Some(ref residence) = character.residence { decrypt_data_with_user_key(residence, &user_key)? } else { String::new() };
|
||||
let decrypted_notes: String = if let Some(ref notes) = character.notes { decrypt_data_with_user_key(notes, &user_key)? } else { String::new() };
|
||||
let decrypted_color: String = if let Some(ref color) = character.color { decrypt_data_with_user_key(color, &user_key)? } else { String::new() };
|
||||
let decrypted_speech_pattern: String = if let Some(ref speech_pattern) = character.speech_pattern { if speech_pattern.is_empty() { String::new() } else { decrypt_data_with_user_key(speech_pattern, &user_key)? } } else { String::new() };
|
||||
let decrypted_catchphrase: String = if let Some(ref catchphrase) = character.catchphrase { if catchphrase.is_empty() { String::new() } else { decrypt_data_with_user_key(catchphrase, &user_key)? } } else { String::new() };
|
||||
let decrypted_residence: String = if let Some(ref residence) = character.residence { if residence.is_empty() { String::new() } else { decrypt_data_with_user_key(residence, &user_key)? } } else { String::new() };
|
||||
let decrypted_notes: String = if let Some(ref notes) = character.notes { if notes.is_empty() { String::new() } else { decrypt_data_with_user_key(notes, &user_key)? } } else { String::new() };
|
||||
let decrypted_color: String = if let Some(ref color) = character.color { if color.is_empty() { String::new() } else { decrypt_data_with_user_key(color, &user_key)? } } else { String::new() };
|
||||
|
||||
character_list.push(SeriesCharacterListProps {
|
||||
id: character.character_id,
|
||||
|
||||
@@ -318,13 +318,13 @@ pub fn get_complete_series_for_upload(conn: &Connection, user_id: &str, series_i
|
||||
user_id: s.user_id,
|
||||
name: decrypt_data_with_user_key(&s.name, &user_key)?,
|
||||
name_hash: s.name_hash,
|
||||
description: if let Some(ref val) = s.description { decrypt_data_with_user_key(val, &user_key)? } else { String::new() },
|
||||
appearance: if let Some(ref val) = s.appearance { decrypt_data_with_user_key(val, &user_key)? } else { String::new() },
|
||||
tags: if let Some(ref val) = s.tags { decrypt_data_with_user_key(val, &user_key)? } else { String::new() },
|
||||
power_level: if let Some(ref val) = s.power_level { Some(decrypt_data_with_user_key(val, &user_key)?) } else { None },
|
||||
components: if let Some(ref val) = s.components { Some(decrypt_data_with_user_key(val, &user_key)?) } else { None },
|
||||
limitations: if let Some(ref val) = s.limitations { Some(decrypt_data_with_user_key(val, &user_key)?) } else { None },
|
||||
notes: if let Some(ref val) = s.notes { Some(decrypt_data_with_user_key(val, &user_key)?) } else { None },
|
||||
description: if let Some(ref description) = s.description { if description.is_empty() { String::new() } else { decrypt_data_with_user_key(description, &user_key)? } } else { String::new() },
|
||||
appearance: if let Some(ref appearance) = s.appearance { if appearance.is_empty() { String::new() } else { decrypt_data_with_user_key(appearance, &user_key)? } } else { String::new() },
|
||||
tags: if let Some(ref tags) = s.tags { if tags.is_empty() { String::new() } else { decrypt_data_with_user_key(tags, &user_key)? } } else { String::new() },
|
||||
power_level: if let Some(ref power_level) = s.power_level { if power_level.is_empty() { None } else { Some(decrypt_data_with_user_key(power_level, &user_key)?) } } else { None },
|
||||
components: if let Some(ref components) = s.components { if components.is_empty() { None } else { Some(decrypt_data_with_user_key(components, &user_key)?) } } else { None },
|
||||
limitations: if let Some(ref limitations) = s.limitations { if limitations.is_empty() { None } else { Some(decrypt_data_with_user_key(limitations, &user_key)?) } } else { None },
|
||||
notes: if let Some(ref notes) = s.notes { if notes.is_empty() { None } else { Some(decrypt_data_with_user_key(notes, &user_key)?) } } else { None },
|
||||
last_update: s.last_update,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -71,11 +71,11 @@ pub fn get_world_list(conn: &Connection, user_id: &str, series_id: &str, lang: L
|
||||
worlds_map.insert(row.world_id.clone(), SeriesWorldListProps {
|
||||
id: row.world_id.clone(),
|
||||
name: if row.world_name.is_empty() { String::new() } else { decrypt_data_with_user_key(&row.world_name, &user_key)? },
|
||||
history: if let Some(ref history) = row.history { decrypt_data_with_user_key(history, &user_key)? } else { String::new() },
|
||||
politics: if let Some(ref politics) = row.politics { decrypt_data_with_user_key(politics, &user_key)? } else { String::new() },
|
||||
economy: if let Some(ref economy) = row.economy { decrypt_data_with_user_key(economy, &user_key)? } else { String::new() },
|
||||
religion: if let Some(ref religion) = row.religion { decrypt_data_with_user_key(religion, &user_key)? } else { String::new() },
|
||||
languages: if let Some(ref languages) = row.languages { decrypt_data_with_user_key(languages, &user_key)? } else { String::new() },
|
||||
history: if let Some(ref history) = row.history { if history.is_empty() { String::new() } else { decrypt_data_with_user_key(history, &user_key)? } } else { String::new() },
|
||||
politics: if let Some(ref politics) = row.politics { if politics.is_empty() { String::new() } else { decrypt_data_with_user_key(politics, &user_key)? } } else { String::new() },
|
||||
economy: if let Some(ref economy) = row.economy { if economy.is_empty() { String::new() } else { decrypt_data_with_user_key(economy, &user_key)? } } else { String::new() },
|
||||
religion: if let Some(ref religion) = row.religion { if religion.is_empty() { String::new() } else { decrypt_data_with_user_key(religion, &user_key)? } } else { String::new() },
|
||||
languages: if let Some(ref languages) = row.languages { if languages.is_empty() { String::new() } else { decrypt_data_with_user_key(languages, &user_key)? } } else { String::new() },
|
||||
laws: Vec::new(),
|
||||
biomes: Vec::new(),
|
||||
issues: Vec::new(),
|
||||
@@ -95,8 +95,8 @@ pub fn get_world_list(conn: &Connection, user_id: &str, series_id: &str, lang: L
|
||||
let world = worlds_map.get_mut(&row.world_id).unwrap();
|
||||
let element = SeriesWorldElementProps {
|
||||
id: element_id.clone(),
|
||||
name: if let Some(ref element_name) = row.element_name { decrypt_data_with_user_key(element_name, &user_key)? } else { String::new() },
|
||||
description: if let Some(ref element_description) = row.element_description { decrypt_data_with_user_key(element_description, &user_key)? } else { String::new() },
|
||||
name: if let Some(ref element_name) = row.element_name { if element_name.is_empty() { String::new() } else { decrypt_data_with_user_key(element_name, &user_key)? } } else { String::new() },
|
||||
description: if let Some(ref element_description) = row.element_description { if element_description.is_empty() { String::new() } else { decrypt_data_with_user_key(element_description, &user_key)? } } else { String::new() },
|
||||
};
|
||||
|
||||
if let Some(element_type) = row.element_type {
|
||||
|
||||
@@ -252,9 +252,9 @@ pub fn get_spell_detail(conn: &Connection, user_id: &str, spell_id: &str, lang:
|
||||
.ok_or_else(|| AppError::Internal(if lang == Lang::Fr { "Sort non trouvé.".to_string() } else { "Spell not found.".to_string() }))?;
|
||||
|
||||
let decrypted_name: String = decrypt_data_with_user_key(&spell.name, &user_key)?;
|
||||
let decrypted_description: String = if let Some(ref description) = spell.description { decrypt_data_with_user_key(description, &user_key)? } else { String::new() };
|
||||
let decrypted_appearance: String = if let Some(ref appearance) = spell.appearance { decrypt_data_with_user_key(appearance, &user_key)? } else { String::new() };
|
||||
let decrypted_tags: Option<String> = if let Some(ref tags) = spell.tags { Some(decrypt_data_with_user_key(tags, &user_key)?) } else { None };
|
||||
let decrypted_description: String = if let Some(ref description) = spell.description { if description.is_empty() { String::new() } else { decrypt_data_with_user_key(description, &user_key)? } } else { String::new() };
|
||||
let decrypted_appearance: String = if let Some(ref appearance) = spell.appearance { if appearance.is_empty() { String::new() } else { decrypt_data_with_user_key(appearance, &user_key)? } } else { String::new() };
|
||||
let decrypted_tags: Option<String> = if let Some(ref tags) = spell.tags { if tags.is_empty() { None } else { Some(decrypt_data_with_user_key(tags, &user_key)?) } } else { None };
|
||||
|
||||
let tag_ids: Vec<String> = match decrypted_tags {
|
||||
Some(ref tags_str) => serde_json::from_str(tags_str).unwrap_or_default(),
|
||||
|
||||
@@ -199,7 +199,7 @@ pub fn get_complete_sync_book(conn: &Connection, user_id: &str, sync_compare_dat
|
||||
book_id: act_summary_record.book_id.clone(),
|
||||
user_id: act_summary_record.user_id.clone(),
|
||||
act_number: act_summary_record.act_index,
|
||||
summary: if let Some(ref summary) = act_summary_record.summary { decrypt_data_with_user_key(summary, &user_encryption_key)? } else { String::new() },
|
||||
summary: if let Some(ref summary) = act_summary_record.summary { if summary.is_empty() { String::new() } else { decrypt_data_with_user_key(summary, &user_encryption_key)? } } else { String::new() },
|
||||
last_update: act_summary_record.last_update,
|
||||
});
|
||||
}
|
||||
@@ -529,12 +529,12 @@ pub fn get_complete_sync_book(conn: &Connection, user_id: &str, sync_compare_dat
|
||||
user_id: spell_record.user_id,
|
||||
name: decrypt_data_with_user_key(&spell_record.name, &user_encryption_key)?,
|
||||
name_hash: spell_record.name_hash,
|
||||
description: if let Some(ref description) = spell_record.description { decrypt_data_with_user_key(description, &user_encryption_key).ok().unwrap_or_default() } else { String::new() },
|
||||
appearance: if let Some(ref appearance) = spell_record.appearance { decrypt_data_with_user_key(appearance, &user_encryption_key).ok().unwrap_or_default() } else { String::new() },
|
||||
tags: if let Some(ref tags) = spell_record.tags { decrypt_data_with_user_key(tags, &user_encryption_key).ok().unwrap_or_default() } else { String::new() },
|
||||
power_level: if let Some(ref power_level) = spell_record.power_level { Some(decrypt_data_with_user_key(power_level, &user_encryption_key)?) } else { None },
|
||||
components: if let Some(ref components) = spell_record.components { Some(decrypt_data_with_user_key(components, &user_encryption_key)?) } else { None },
|
||||
limitations: if let Some(ref limitations) = spell_record.limitations { Some(decrypt_data_with_user_key(limitations, &user_encryption_key)?) } else { None },
|
||||
description: if let Some(ref description) = spell_record.description { if description.is_empty() { String::new() } else { decrypt_data_with_user_key(description, &user_encryption_key).ok().unwrap_or_default() } } else { String::new() },
|
||||
appearance: if let Some(ref appearance) = spell_record.appearance { if appearance.is_empty() { String::new() } else { decrypt_data_with_user_key(appearance, &user_encryption_key).ok().unwrap_or_default() } } else { String::new() },
|
||||
tags: if let Some(ref tags) = spell_record.tags { if tags.is_empty() { String::new() } else { decrypt_data_with_user_key(tags, &user_encryption_key).ok().unwrap_or_default() } } else { String::new() },
|
||||
power_level: if let Some(ref power_level) = spell_record.power_level { if power_level.is_empty() { None } else { Some(decrypt_data_with_user_key(power_level, &user_encryption_key)?) } } else { None },
|
||||
components: if let Some(ref components) = spell_record.components { if components.is_empty() { None } else { Some(decrypt_data_with_user_key(components, &user_encryption_key)?) } } else { None },
|
||||
limitations: if let Some(ref limitations) = spell_record.limitations { if limitations.is_empty() { None } else { Some(decrypt_data_with_user_key(limitations, &user_encryption_key)?) } } else { None },
|
||||
notes: if let Some(ref notes) = spell_record.notes { Some(decrypt_data_with_user_key(notes, &user_encryption_key)?) } else { None },
|
||||
last_update: spell_record.last_update,
|
||||
});
|
||||
@@ -1125,7 +1125,7 @@ pub fn get_synced_books(conn: &Connection, user_id: &str, lang: Lang) -> AppResu
|
||||
id: current_book_id.to_string(),
|
||||
book_type: book_record.book_type.clone(),
|
||||
title: decrypt_data_with_user_key(&book_record.title, &user_encryption_key).unwrap_or_default(),
|
||||
sub_title: if let Some(ref sub_title) = book_record.sub_title { decrypt_data_with_user_key(sub_title, &user_encryption_key).ok() } else { None },
|
||||
sub_title: if let Some(ref sub_title) = book_record.sub_title { if sub_title.is_empty() { None } else { decrypt_data_with_user_key(sub_title, &user_encryption_key).ok() } } else { None },
|
||||
last_update: book_record.last_update,
|
||||
chapters: book_chapters,
|
||||
characters: book_characters,
|
||||
@@ -1250,7 +1250,7 @@ pub fn get_synced_series(conn: &Connection, user_id: &str, lang: Lang) -> AppRes
|
||||
synced_series_list.push(SyncedSeries {
|
||||
id: series_id.to_string(),
|
||||
name: decrypt_data_with_user_key(&series.name, &user_encryption_key).unwrap_or_default(),
|
||||
description: if let Some(ref description) = series.description { decrypt_data_with_user_key(description, &user_encryption_key).ok() } else { None },
|
||||
description: if let Some(ref description) = series.description { if description.is_empty() { None } else { decrypt_data_with_user_key(description, &user_encryption_key).ok() } } else { None },
|
||||
last_update: series.last_update,
|
||||
books,
|
||||
characters,
|
||||
|
||||
@@ -100,7 +100,7 @@ pub fn upload_book_for_sync(conn: &Connection, user_id: &str, book_id: &str, lan
|
||||
|
||||
let mut act_summaries: Vec<BookActSummariesTable> = Vec::with_capacity(encrypted_act_summaries.len());
|
||||
for act_summary in encrypted_act_summaries {
|
||||
let decrypted_summary: String = if let Some(ref summary) = act_summary.summary { decrypt_data_with_user_key(summary, &user_encryption_key)? } else { String::new() };
|
||||
let decrypted_summary: String = if let Some(ref summary) = act_summary.summary { if summary.is_empty() { String::new() } else { decrypt_data_with_user_key(summary, &user_encryption_key)? } } else { String::new() };
|
||||
act_summaries.push(BookActSummariesTable {
|
||||
summary_id: act_summary.act_sum_id, book_id: act_summary.book_id,
|
||||
user_id: act_summary.user_id, act_number: act_summary.act_index,
|
||||
@@ -333,13 +333,13 @@ pub fn upload_book_for_sync(conn: &Connection, user_id: &str, book_id: &str, lan
|
||||
let mut spells: Vec<BookSpellsTable> = Vec::with_capacity(encrypted_spells.len());
|
||||
for spell in encrypted_spells {
|
||||
let decrypted_name: String = decrypt_data_with_user_key(&spell.name, &user_encryption_key)?;
|
||||
let decrypted_description: String = if let Some(ref description) = spell.description { decrypt_data_with_user_key(description, &user_encryption_key)? } else { String::new() };
|
||||
let decrypted_appearance: String = if let Some(ref appearance) = spell.appearance { decrypt_data_with_user_key(appearance, &user_encryption_key)? } else { String::new() };
|
||||
let decrypted_tags: String = if let Some(ref tags) = spell.tags { decrypt_data_with_user_key(tags, &user_encryption_key)? } else { String::new() };
|
||||
let decrypted_power_level: Option<String> = if let Some(ref power_level) = spell.power_level { Some(decrypt_data_with_user_key(power_level, &user_encryption_key)?) } else { None };
|
||||
let decrypted_components: Option<String> = if let Some(ref components) = spell.components { Some(decrypt_data_with_user_key(components, &user_encryption_key)?) } else { None };
|
||||
let decrypted_limitations: Option<String> = if let Some(ref limitations) = spell.limitations { Some(decrypt_data_with_user_key(limitations, &user_encryption_key)?) } else { None };
|
||||
let decrypted_notes: Option<String> = if let Some(ref notes) = spell.notes { Some(decrypt_data_with_user_key(notes, &user_encryption_key)?) } else { None };
|
||||
let decrypted_description: String = if let Some(ref description) = spell.description { if description.is_empty() { String::new() } else { decrypt_data_with_user_key(description, &user_encryption_key)? } } else { String::new() };
|
||||
let decrypted_appearance: String = if let Some(ref appearance) = spell.appearance { if appearance.is_empty() { String::new() } else { decrypt_data_with_user_key(appearance, &user_encryption_key)? } } else { String::new() };
|
||||
let decrypted_tags: String = if let Some(ref tags) = spell.tags { if tags.is_empty() { String::new() } else { decrypt_data_with_user_key(tags, &user_encryption_key)? } } else { String::new() };
|
||||
let decrypted_power_level: Option<String> = if let Some(ref power_level) = spell.power_level { if power_level.is_empty() { None } else { Some(decrypt_data_with_user_key(power_level, &user_encryption_key)?) } } else { None };
|
||||
let decrypted_components: Option<String> = if let Some(ref components) = spell.components { if components.is_empty() { None } else { Some(decrypt_data_with_user_key(components, &user_encryption_key)?) } } else { None };
|
||||
let decrypted_limitations: Option<String> = if let Some(ref limitations) = spell.limitations { if limitations.is_empty() { None } else { Some(decrypt_data_with_user_key(limitations, &user_encryption_key)?) } } else { None };
|
||||
let decrypted_notes: Option<String> = if let Some(ref notes) = spell.notes { if notes.is_empty() { None } else { Some(decrypt_data_with_user_key(notes, &user_encryption_key)?) } } else { None };
|
||||
spells.push(BookSpellsTable {
|
||||
spell_id: spell.spell_id, book_id: spell.book_id,
|
||||
user_id: spell.user_id, name: decrypted_name,
|
||||
|
||||
@@ -5,7 +5,7 @@ use crate::crypto::{encryption, key_manager};
|
||||
use crate::db::connection::DbManager;
|
||||
use crate::db::schema;
|
||||
use crate::domains::user::service;
|
||||
use crate::error::AppError;
|
||||
use crate::error::{AppError, AppResult};
|
||||
use crate::shared::session::SessionState;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
@@ -180,3 +180,37 @@ pub fn update_user_info(data: UpdateUserData, db: State<DbManager>, session: Sta
|
||||
|
||||
service::update_user_infos(conn, &user_key, &user_id, &data.username, &data.email, data.author_name.as_deref(), lang)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn dev_reset_all(db: State<DbManager>, session: State<SessionState>) -> AppResult<bool> {
|
||||
if !cfg!(debug_assertions) {
|
||||
return Err(AppError::Internal("dev_reset_all is only available in dev mode".to_string()));
|
||||
}
|
||||
|
||||
// 1. Close all DB connections
|
||||
let mut db_manager = db.lock().map_err(|e| AppError::Internal(format!("DB lock failed: {}", e)))?;
|
||||
let base_path = db_manager.base_path().clone();
|
||||
db_manager.close_all();
|
||||
drop(db_manager);
|
||||
|
||||
// 2. Delete all eritors-local-*.db files (+ WAL/SHM)
|
||||
if let Ok(entries) = std::fs::read_dir(&base_path) {
|
||||
for entry in entries.flatten() {
|
||||
let path = entry.path();
|
||||
if let Some(name) = path.file_name().and_then(|n| n.to_str()) {
|
||||
if name.starts_with("eritors-local-") {
|
||||
let _ = std::fs::remove_file(&path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Clear vault (tokens, encryption keys, PIN hashes)
|
||||
key_manager::clear_vault()?;
|
||||
|
||||
// 4. Reset session
|
||||
let mut session_guard = session.lock().map_err(|e| AppError::Internal(format!("Session lock failed: {}", e)))?;
|
||||
session_guard.user_id = None;
|
||||
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ pub fn return_user_infos(conn: &Connection, user_id: &str, lang: Lang) -> AppRes
|
||||
|
||||
let username: String = decrypt_data_with_user_key(&user_infos_data.username, &user_encryption_key)?;
|
||||
let email: String = decrypt_data_with_user_key(&user_infos_data.email, &user_encryption_key)?;
|
||||
let author_name: String = if let Some(ref author_name_val) = user_infos_data.author_name { decrypt_data_with_user_key(author_name_val, &user_encryption_key)? } else { String::new() };
|
||||
let author_name: String = if let Some(ref author_name_val) = user_infos_data.author_name { if author_name_val.is_empty() { String::new() } else { decrypt_data_with_user_key(author_name_val, &user_encryption_key)? } } else { String::new() };
|
||||
|
||||
Ok(UserInfoResponse {
|
||||
id: user_id.to_string(),
|
||||
|
||||
@@ -140,8 +140,8 @@ pub fn get_worlds(conn: &Connection, user_id: &str, book_id: &str, lang: Lang) -
|
||||
if let Some(element_type) = query_row.element_type {
|
||||
let world_element: WorldElement = WorldElement {
|
||||
id: query_row.element_id.clone().unwrap_or_default(),
|
||||
name: if let Some(ref element_name) = query_row.element_name { decrypt_data_with_user_key(element_name, &user_encryption_key)? } else { String::new() },
|
||||
description: if let Some(ref element_description) = query_row.element_description { decrypt_data_with_user_key(element_description, &user_encryption_key)? } else { String::new() },
|
||||
name: if let Some(ref element_name) = query_row.element_name { if element_name.is_empty() { String::new() } else { decrypt_data_with_user_key(element_name, &user_encryption_key)? } } else { String::new() },
|
||||
description: if let Some(ref element_description) = query_row.element_description { if element_description.is_empty() { String::new() } else { decrypt_data_with_user_key(element_description, &user_encryption_key)? } } else { String::new() },
|
||||
element_type: None,
|
||||
};
|
||||
push_element_to_world(&mut worlds[index], element_type, world_element);
|
||||
@@ -149,12 +149,12 @@ pub fn get_worlds(conn: &Connection, user_id: &str, book_id: &str, lang: Lang) -
|
||||
} else {
|
||||
let mut new_world: WorldProps = WorldProps {
|
||||
id: query_row.world_id.clone(),
|
||||
name: decrypt_data_with_user_key(&query_row.world_name, &user_encryption_key)?,
|
||||
history: if let Some(ref history) = query_row.history { decrypt_data_with_user_key(history, &user_encryption_key)? } else { String::new() },
|
||||
politics: if let Some(ref politics) = query_row.politics { decrypt_data_with_user_key(politics, &user_encryption_key)? } else { String::new() },
|
||||
economy: if let Some(ref economy) = query_row.economy { decrypt_data_with_user_key(economy, &user_encryption_key)? } else { String::new() },
|
||||
religion: if let Some(ref religion) = query_row.religion { decrypt_data_with_user_key(religion, &user_encryption_key)? } else { String::new() },
|
||||
languages: if let Some(ref languages) = query_row.languages { decrypt_data_with_user_key(languages, &user_encryption_key)? } else { String::new() },
|
||||
name: if query_row.world_name.is_empty() { String::new() } else { decrypt_data_with_user_key(&query_row.world_name, &user_encryption_key)? },
|
||||
history: if let Some(ref history) = query_row.history { if history.is_empty() { String::new() } else { decrypt_data_with_user_key(history, &user_encryption_key)? } } else { String::new() },
|
||||
politics: if let Some(ref politics) = query_row.politics { if politics.is_empty() { String::new() } else { decrypt_data_with_user_key(politics, &user_encryption_key)? } } else { String::new() },
|
||||
economy: if let Some(ref economy) = query_row.economy { if economy.is_empty() { String::new() } else { decrypt_data_with_user_key(economy, &user_encryption_key)? } } else { String::new() },
|
||||
religion: if let Some(ref religion) = query_row.religion { if religion.is_empty() { String::new() } else { decrypt_data_with_user_key(religion, &user_encryption_key)? } } else { String::new() },
|
||||
languages: if let Some(ref languages) = query_row.languages { if languages.is_empty() { String::new() } else { decrypt_data_with_user_key(languages, &user_encryption_key)? } } else { String::new() },
|
||||
laws: Vec::new(),
|
||||
biomes: Vec::new(),
|
||||
issues: Vec::new(),
|
||||
@@ -173,8 +173,8 @@ pub fn get_worlds(conn: &Connection, user_id: &str, book_id: &str, lang: Lang) -
|
||||
if let Some(element_type) = query_row.element_type {
|
||||
let world_element: WorldElement = WorldElement {
|
||||
id: query_row.element_id.clone().unwrap_or_default(),
|
||||
name: if let Some(ref element_name) = query_row.element_name { decrypt_data_with_user_key(element_name, &user_encryption_key)? } else { String::new() },
|
||||
description: if let Some(ref element_description) = query_row.element_description { decrypt_data_with_user_key(element_description, &user_encryption_key)? } else { String::new() },
|
||||
name: if let Some(ref element_name) = query_row.element_name { if element_name.is_empty() { String::new() } else { decrypt_data_with_user_key(element_name, &user_encryption_key)? } } else { String::new() },
|
||||
description: if let Some(ref element_description) = query_row.element_description { if element_description.is_empty() { String::new() } else { decrypt_data_with_user_key(element_description, &user_encryption_key)? } } else { String::new() },
|
||||
element_type: None,
|
||||
};
|
||||
push_element_to_world(&mut new_world, element_type, world_element);
|
||||
|
||||
@@ -35,26 +35,22 @@ impl Serialize for AppError {
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
use serde::ser::SerializeStruct;
|
||||
let mut state = serializer.serialize_struct("AppError", 2)?;
|
||||
state.serialize_field("kind", &self.error_kind())?;
|
||||
state.serialize_field("message", &self.to_string())?;
|
||||
state.end()
|
||||
serializer.serialize_str(&self.user_message())
|
||||
}
|
||||
}
|
||||
|
||||
impl AppError {
|
||||
fn error_kind(&self) -> &str {
|
||||
fn user_message(&self) -> String {
|
||||
match self {
|
||||
AppError::Database(_) => "DATABASE",
|
||||
AppError::Encryption(_) => "ENCRYPTION",
|
||||
AppError::Keyring(_) => "KEYRING",
|
||||
AppError::Auth(_) => "AUTH",
|
||||
AppError::NotFound(_) => "NOT_FOUND",
|
||||
AppError::Validation(_) => "VALIDATION",
|
||||
AppError::Io(_) => "IO",
|
||||
AppError::Json(_) => "JSON",
|
||||
AppError::Internal(_) => "INTERNAL",
|
||||
AppError::Database(e) => e.to_string(),
|
||||
AppError::Encryption(msg)
|
||||
| AppError::Keyring(msg)
|
||||
| AppError::Auth(msg)
|
||||
| AppError::NotFound(msg)
|
||||
| AppError::Validation(msg)
|
||||
| AppError::Internal(msg) => msg.clone(),
|
||||
AppError::Io(e) => e.to_string(),
|
||||
AppError::Json(e) => e.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ pub fn run() {
|
||||
domains::user::commands::get_user_info,
|
||||
domains::user::commands::sync_user,
|
||||
domains::user::commands::update_user_info,
|
||||
domains::user::commands::dev_reset_all,
|
||||
// ─── Offline ───────────────────────────────────
|
||||
domains::offline::commands::offline_pin_set,
|
||||
domains::offline::commands::offline_pin_verify,
|
||||
|
||||
0
src-tauri/src/shared/ai_models.rs
Normal file
0
src-tauri/src/shared/ai_models.rs
Normal file
24
src-tauri/src/shared/session.rs
Normal file
24
src-tauri/src/shared/session.rs
Normal file
@@ -0,0 +1,24 @@
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use crate::shared::types::Lang;
|
||||
|
||||
pub struct Session {
|
||||
pub user_id: Option<String>,
|
||||
pub lang: Lang,
|
||||
}
|
||||
|
||||
impl Session {
|
||||
pub fn new() -> Self {
|
||||
Self { user_id: None, lang: Lang::Fr }
|
||||
}
|
||||
|
||||
pub fn get_user_id(&self) -> Result<&str, String> {
|
||||
self.user_id.as_deref().ok_or_else(|| "No user session. Please log in first.".to_string())
|
||||
}
|
||||
}
|
||||
|
||||
pub type SessionState = Arc<Mutex<Session>>;
|
||||
|
||||
pub fn create_session() -> SessionState {
|
||||
Arc::new(Mutex::new(Session::new()))
|
||||
}
|
||||
Reference in New Issue
Block a user