fix
This commit is contained in:
+168
-22
@@ -1,6 +1,8 @@
|
||||
pub mod apps;
|
||||
pub mod sync;
|
||||
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use che_orm::SqliteBackend;
|
||||
use che_tauri::{
|
||||
ApiError, ApiRequest, AppConfig, AppState, AuthTokenResponse, DatabaseConfig, RemoteConfig,
|
||||
@@ -10,6 +12,108 @@ use tauri::Manager;
|
||||
|
||||
use crate::sync::SyncContractsResult;
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
const REMOTE_BASE_URL: &str = "http://10.0.2.2:8000";
|
||||
|
||||
#[cfg(not(target_os = "android"))]
|
||||
const REMOTE_BASE_URL: &str = "http://127.0.0.1:8000";
|
||||
|
||||
const DEFAULT_AUTH_PATH: &str = "/api-token-auth/";
|
||||
|
||||
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
|
||||
struct AppSettings {
|
||||
remote_base_url: String,
|
||||
auth_path: String,
|
||||
}
|
||||
|
||||
impl Default for AppSettings {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
remote_base_url: String::from(REMOTE_BASE_URL),
|
||||
auth_path: String::from(DEFAULT_AUTH_PATH),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn build_api(database_url: String, settings: AppSettings) -> Result<TauriApi, ApiError> {
|
||||
let config = AppConfig {
|
||||
database: DatabaseConfig { url: database_url },
|
||||
remote: Some(settings_to_remote_config(&settings)),
|
||||
};
|
||||
let db = SqliteBackend::connect(&config.database.url).await?;
|
||||
let state = AppState::new(config, db);
|
||||
|
||||
TauriApi::new(state)
|
||||
.install(apps::installed_apps())
|
||||
.build()
|
||||
.await
|
||||
}
|
||||
|
||||
fn settings_to_remote_config(settings: &AppSettings) -> RemoteConfig {
|
||||
RemoteConfig {
|
||||
base_url: normalize_base_url(&settings.remote_base_url),
|
||||
auth_path: Some(normalize_auth_path(&settings.auth_path)),
|
||||
}
|
||||
}
|
||||
|
||||
fn normalize_settings(settings: AppSettings) -> AppSettings {
|
||||
AppSettings {
|
||||
remote_base_url: normalize_base_url(&settings.remote_base_url),
|
||||
auth_path: normalize_auth_path(&settings.auth_path),
|
||||
}
|
||||
}
|
||||
|
||||
fn normalize_base_url(base_url: &str) -> String {
|
||||
base_url.trim().trim_end_matches('/').to_string()
|
||||
}
|
||||
|
||||
fn normalize_auth_path(auth_path: &str) -> String {
|
||||
let clean = auth_path.trim().trim_matches('/');
|
||||
if clean.is_empty() {
|
||||
String::from(DEFAULT_AUTH_PATH)
|
||||
} else {
|
||||
format!("/{clean}/")
|
||||
}
|
||||
}
|
||||
|
||||
fn validate_settings(settings: &AppSettings) -> Result<(), ApiError> {
|
||||
if !(settings.remote_base_url.starts_with("http://")
|
||||
|| settings.remote_base_url.starts_with("https://"))
|
||||
{
|
||||
return Err(ApiError::bad_request(
|
||||
"Удаленный URL должен начинаться с http:// или https://",
|
||||
));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn settings_path(app_data_dir: &Path) -> PathBuf {
|
||||
app_data_dir.join("settings.json")
|
||||
}
|
||||
|
||||
async fn load_settings(app_data_dir: &Path) -> Result<AppSettings, ApiError> {
|
||||
let path = settings_path(app_data_dir);
|
||||
match tokio::fs::read_to_string(path).await {
|
||||
Ok(content) => serde_json::from_str::<AppSettings>(&content)
|
||||
.map(normalize_settings)
|
||||
.map_err(|error| ApiError::new("settings_error", error.to_string())),
|
||||
Err(error) if error.kind() == std::io::ErrorKind::NotFound => Ok(AppSettings::default()),
|
||||
Err(error) => Err(ApiError::new("settings_error", error.to_string())),
|
||||
}
|
||||
}
|
||||
|
||||
async fn save_settings(app_data_dir: &Path, settings: &AppSettings) -> Result<(), ApiError> {
|
||||
tokio::fs::create_dir_all(app_data_dir)
|
||||
.await
|
||||
.map_err(|error| ApiError::new("settings_error", error.to_string()))?;
|
||||
let content = serde_json::to_string_pretty(settings)
|
||||
.map_err(|error| ApiError::new("settings_error", error.to_string()))?;
|
||||
tokio::fs::write(settings_path(app_data_dir), content)
|
||||
.await
|
||||
.map_err(|error| ApiError::new("settings_error", error.to_string()))
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize)]
|
||||
struct CurrentEmployee {
|
||||
id: i64,
|
||||
@@ -55,9 +159,57 @@ fn auth_status(api: tauri::State<'_, TauriApi>) -> bool {
|
||||
api.is_authenticated()
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn get_app_settings(app: tauri::AppHandle) -> Result<AppSettings, ApiError> {
|
||||
let app_data_dir = app
|
||||
.path()
|
||||
.app_data_dir()
|
||||
.map_err(|error| ApiError::new("settings_error", error.to_string()))?;
|
||||
load_settings(&app_data_dir).await
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn update_app_settings(
|
||||
app: tauri::AppHandle,
|
||||
api: tauri::State<'_, TauriApi>,
|
||||
settings: AppSettings,
|
||||
) -> Result<AppSettings, ApiError> {
|
||||
let settings = normalize_settings(settings);
|
||||
validate_settings(&settings)?;
|
||||
|
||||
let app_data_dir = app
|
||||
.path()
|
||||
.app_data_dir()
|
||||
.map_err(|error| ApiError::new("settings_error", error.to_string()))?;
|
||||
save_settings(&app_data_dir, &settings).await?;
|
||||
api.state()
|
||||
.set_remote_config(Some(settings_to_remote_config(&settings)));
|
||||
api.logout();
|
||||
|
||||
Ok(settings)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn reset_app_settings(
|
||||
app: tauri::AppHandle,
|
||||
api: tauri::State<'_, TauriApi>,
|
||||
) -> Result<AppSettings, ApiError> {
|
||||
let settings = AppSettings::default();
|
||||
let app_data_dir = app
|
||||
.path()
|
||||
.app_data_dir()
|
||||
.map_err(|error| ApiError::new("settings_error", error.to_string()))?;
|
||||
save_settings(&app_data_dir, &settings).await?;
|
||||
api.state()
|
||||
.set_remote_config(Some(settings_to_remote_config(&settings)));
|
||||
api.logout();
|
||||
|
||||
Ok(settings)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn current_employee(api: tauri::State<'_, TauriApi>) -> Result<CurrentEmployee, ApiError> {
|
||||
let remote = api.state().config.remote.as_ref().ok_or_else(|| {
|
||||
let remote = api.state().remote_config().ok_or_else(|| {
|
||||
ApiError::bad_request("current_employee requires [remote].base_url config")
|
||||
})?;
|
||||
|
||||
@@ -145,29 +297,20 @@ pub fn run() {
|
||||
std::env::set_var("WEBKIT_DISABLE_DMABUF_RENDERER", "1");
|
||||
}
|
||||
|
||||
let api = tauri::async_runtime::block_on(async {
|
||||
// let state = AppState::from_config_file("app.toml").await?;
|
||||
let config = AppConfig {
|
||||
database: DatabaseConfig {
|
||||
url: String::from("sqlite://ewa-mobile.sqlite?mode=rwc"),
|
||||
},
|
||||
remote: Some(RemoteConfig {
|
||||
base_url: String::from("http://127.0.0.1:8000/"),
|
||||
auth_path: Some(String::from(" /api-token-auth/")),
|
||||
}),
|
||||
};
|
||||
let db = SqliteBackend::connect(&config.database.url).await?;
|
||||
let state = AppState::new(config, db);
|
||||
TauriApi::new(state)
|
||||
.install(apps::installed_apps())
|
||||
.build()
|
||||
.await
|
||||
})
|
||||
.expect("failed to initialize che-tauri");
|
||||
|
||||
tauri::Builder::default()
|
||||
.manage(api)
|
||||
.plugin(tauri_plugin_opener::init())
|
||||
.setup(|app| {
|
||||
let app_data_dir = app.path().app_data_dir()?;
|
||||
std::fs::create_dir_all(&app_data_dir)?;
|
||||
let database_path = app_data_dir.join("ewa-mobile.sqlite");
|
||||
let database_url = format!("sqlite://{}?mode=rwc", database_path.to_string_lossy());
|
||||
let settings = tauri::async_runtime::block_on(load_settings(&app_data_dir))
|
||||
.map_err(|error| Box::<dyn std::error::Error>::from(error.to_string()))?;
|
||||
let api = tauri::async_runtime::block_on(build_api(database_url, settings))
|
||||
.map_err(|error| Box::<dyn std::error::Error>::from(error.to_string()))?;
|
||||
app.manage(api);
|
||||
Ok(())
|
||||
})
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
greet,
|
||||
che_api,
|
||||
@@ -175,6 +318,9 @@ pub fn run() {
|
||||
auth_set_token,
|
||||
auth_logout,
|
||||
auth_status,
|
||||
get_app_settings,
|
||||
update_app_settings,
|
||||
reset_app_settings,
|
||||
current_employee,
|
||||
sync_contracts,
|
||||
load_application_file
|
||||
|
||||
@@ -165,9 +165,7 @@ pub async fn sync_contracts(
|
||||
.auth_token()
|
||||
.ok_or_else(|| ApiError::new("not_authenticated", "authentication token is missing"))?;
|
||||
let remote = state
|
||||
.config
|
||||
.remote
|
||||
.as_ref()
|
||||
.remote_config()
|
||||
.ok_or_else(|| ApiError::bad_request("sync requires [remote].base_url config"))?;
|
||||
let client = reqwest::Client::new();
|
||||
sync_contract_categories(api, &client, &token, &remote.base_url).await?;
|
||||
|
||||
Reference in New Issue
Block a user