Skip to content

Commit 3adb94c

Browse files
liuslius
authored andcommitted
feat(updater): add installer fallback for protected paths
1 parent 51e888e commit 3adb94c

12 files changed

Lines changed: 389 additions & 29 deletions

File tree

src-tauri/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@ windows = { version = "0.61.1",features = [
9898
"Win32_System_Registry",
9999
"Win32_System_SystemInformation",
100100
"Win32_System_TpmBaseServices",
101+
"Win32_UI_Shell",
102+
"Win32_UI_WindowsAndMessaging",
101103
] }
102104

103105
[target.'cfg(any(target_os = "macos", windows, target_os = "linux"))'.dependencies]

src-tauri/config.development.toml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@ base_url = "http://127.0.0.1:40041/api/"
33
version = "v1"
44
secret_key = "p4y8uX1Jc22K7bAN52arpvJpVbduUvGNNNfo"
55

6-
[updater]
7-
check_url = "http://127.0.0.1:40042/api/v1/versions/check"
8-
updater_temp_dir = "updates"
6+
[updater]
7+
check_url = "http://127.0.0.1:40042/api/v1/versions/check"
8+
latest_json_url = "https://pub-39307a5e69c74324855a762027cbf9bf.r2.dev/latest.json"
9+
updater_temp_dir = "updates"
910

1011
[webview]
1112
downlaod_url = "https://pub-39307a5e69c74324855a762027cbf9bf.r2.dev/webview-fixed.zip"

src-tauri/config.production.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ secret_key = "p4y8uX1Jc22K7bAN52arpvJpVbduUvGNNNfo"
55

66
[updater]
77
check_url = "https://update.simprint.app/api/v1/versions/check"
8+
latest_json_url = "https://pub-39307a5e69c74324855a762027cbf9bf.r2.dev/latest.json"
89
updater_temp_dir = "updates"
910

1011
[webview]

src-tauri/config.test.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ secret_key = "p4y8uX1Jc22K7bAN52arpvJpVbduUvGNNNfo"
55

66
[updater]
77
check_url = "http://1.12.233.51:40042/api/v1/versions/check"
8+
latest_json_url = "https://pub-39307a5e69c74324855a762027cbf9bf.r2.dev/latest.json"
89
updater_temp_dir = "updates"
910

1011
[webview]

src-tauri/src/bin/updater.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,12 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
4040
});
4141
run_install(&tasks_file).await?;
4242
}
43+
"install-package" => {
44+
let installer_path = args.get(2).cloned().unwrap_or_else(|| {
45+
process::exit(1);
46+
});
47+
run_install_package(&installer_path)?;
48+
}
4349
_ => {
4450
process::exit(1);
4551
}
@@ -48,6 +54,24 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
4854
Ok(())
4955
}
5056

57+
fn run_install_package(installer_path: &str) -> Result<(), Box<dyn std::error::Error>> {
58+
let installer = PathBuf::from(installer_path);
59+
if !installer.exists() {
60+
return Err(format!("安装包不存在: {}", installer.display()).into());
61+
}
62+
63+
use std::process::Command;
64+
65+
Command::new(&installer)
66+
.arg("/P")
67+
.arg("/UPDATE")
68+
.arg("/R")
69+
.spawn()
70+
.map_err(|e| format!("启动安装包失败: {}", e))?;
71+
72+
Ok(())
73+
}
74+
5175
/// 安装模式
5276
///
5377
/// 从 JSON 文件读取安装任务,执行文件替换

src-tauri/src/core/config/types.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ pub struct SecurityConfig {
3636
#[derive(Deserialize, Debug, Clone)]
3737
pub struct UpdaterConfig {
3838
pub check_url: String,
39+
pub latest_json_url: String,
3940

4041
/// 下载的临时目录(可选)。
4142
/// - 若为空:默认使用统一根目录下的 `updates`

src-tauri/src/core/config/validator.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,20 @@ fn validate_updater_config(config: &AppConfig) -> Result<()> {
6161
));
6262
}
6363

64+
if config.updater.latest_json_url.is_empty() {
65+
return Err(Error::ConfigValidationFailed(
66+
"updater.latest_json_url cannot be empty".to_string(),
67+
));
68+
}
69+
70+
if !config.updater.latest_json_url.starts_with("http://")
71+
&& !config.updater.latest_json_url.starts_with("https://")
72+
{
73+
return Err(Error::ConfigValidationFailed(
74+
"updater.latest_json_url must start with http:// or https://".to_string(),
75+
));
76+
}
77+
6478
Ok(())
6579
}
6680

src-tauri/src/infrastructure/updater/service.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,18 @@ pub async fn take_update_plan() -> Result<UpdatePlan> {
152152
.ok_or_else(|| anyhow!("更新计划不存在,请重新执行检查"))
153153
}
154154

155+
pub async fn store_installer_package_path(path: String) {
156+
crate::infrastructure::updater::state::store_installer_package_path(path).await;
157+
}
158+
159+
pub async fn take_installer_package_path() -> Option<String> {
160+
crate::infrastructure::updater::state::take_installer_package_path().await
161+
}
162+
163+
pub async fn clear_installer_package_path() {
164+
crate::infrastructure::updater::state::clear_installer_package_path().await;
165+
}
166+
155167
/// 保存安装任务到文件
156168
///
157169
/// # 参数

src-tauri/src/infrastructure/updater/state.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ static UPDATE_CHECK_AND_DOWNLOAD_LOCK: Lazy<Arc<TokioMutex<()>>> =
1515
static UPDATE_PLAN_CACHE: Lazy<TokioMutex<Option<UpdatePlan>>> =
1616
Lazy::new(|| TokioMutex::new(None));
1717

18+
/// 安装包升级路径缓存
19+
static INSTALLER_PACKAGE_PATH_CACHE: Lazy<TokioMutex<Option<String>>> =
20+
Lazy::new(|| TokioMutex::new(None));
21+
1822
/// 尝试获取更新检查和下载任务锁(非阻塞)
1923
///
2024
/// # 返回
@@ -38,3 +42,18 @@ pub async fn take_update_plan() -> Option<UpdatePlan> {
3842
let mut guard = UPDATE_PLAN_CACHE.lock().await;
3943
guard.take()
4044
}
45+
46+
pub async fn store_installer_package_path(path: String) {
47+
let mut guard = INSTALLER_PACKAGE_PATH_CACHE.lock().await;
48+
*guard = Some(path);
49+
}
50+
51+
pub async fn take_installer_package_path() -> Option<String> {
52+
let mut guard = INSTALLER_PACKAGE_PATH_CACHE.lock().await;
53+
guard.take()
54+
}
55+
56+
pub async fn clear_installer_package_path() {
57+
let mut guard = INSTALLER_PACKAGE_PATH_CACHE.lock().await;
58+
*guard = None;
59+
}

src-tauri/src/infrastructure/updater/types.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,13 @@ pub struct InstallTasks {
131131
pub tasks: Vec<InstallTask>,
132132
}
133133

134+
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
135+
#[serde(rename_all = "snake_case")]
136+
pub enum InstallStrategy {
137+
DirectReplace,
138+
InstallerPackage,
139+
}
140+
134141
/// 更新计划(用于检查后保存,供下载使用)
135142
#[derive(Debug, Clone, Serialize, Deserialize)]
136143
pub struct UpdatePlan {
@@ -198,6 +205,23 @@ pub struct Manifest {
198205
pub last_updated: String, // ISO 8601 时间戳
199206
}
200207

208+
#[derive(Debug, Clone, Serialize, Deserialize)]
209+
pub struct LatestRelease {
210+
pub version: String,
211+
#[serde(default)]
212+
pub notes: String,
213+
pub pub_date: String,
214+
pub platforms: HashMap<String, LatestReleasePlatform>,
215+
}
216+
217+
#[derive(Debug, Clone, Serialize, Deserialize)]
218+
pub struct LatestReleasePlatform {
219+
#[serde(default)]
220+
pub url: String,
221+
#[serde(default)]
222+
pub r2_url: String,
223+
}
224+
201225
/// 客户端信息
202226
#[derive(Debug, Clone, Serialize, Deserialize)]
203227
pub struct ClientInfo {

0 commit comments

Comments
 (0)