forked from AxTps/Starlight_Lancher
feat: complete hosted mod sync and launcher interface updates
Add pack sync markers, tagged mod updates, parallel progress, JWT downloads and retry recovery. Include pending onboarding, about scene, compatibility data pack and download fixes.
This commit is contained in:
@ -14,7 +14,9 @@ use uuid::Uuid;
|
||||
pub fn init<R: tauri::Runtime>() -> tauri::plugin::TauriPlugin<R> {
|
||||
tauri::plugin::Builder::new("install")
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
hosted_catalog,
|
||||
hosted_default,
|
||||
hosted_set_session,
|
||||
hosted_create,
|
||||
hosted_binding,
|
||||
hosted_sync,
|
||||
hosted_instance_mode,
|
||||
@ -54,9 +56,18 @@ pub fn init<R: tauri::Runtime>() -> tauri::plugin::TauriPlugin<R> {
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn hosted_catalog() -> Result<Vec<theseus::pack::hosted::Publication>>
|
||||
{
|
||||
Ok(theseus::pack::hosted::catalog().await?)
|
||||
pub async fn hosted_set_session(token: Option<String>) -> Result<()> {
|
||||
Ok(theseus::pack::hosted::set_session(token).await?)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn hosted_default() -> Result<theseus::pack::hosted::Publication> {
|
||||
Ok(theseus::pack::hosted::default_publication().await?)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn hosted_create() -> Result<String> {
|
||||
Ok(theseus::pack::hosted::create().await?)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
@ -84,9 +95,8 @@ pub async fn hosted_binding(
|
||||
#[tauri::command]
|
||||
pub async fn hosted_sync(
|
||||
instance_id: String,
|
||||
pack_id: String,
|
||||
) -> Result<theseus::pack::hosted::SyncResult> {
|
||||
Ok(theseus::pack::hosted::synchronize(&instance_id, &pack_id).await?)
|
||||
Ok(theseus::pack::hosted::synchronize(&instance_id).await?)
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
@ -140,6 +150,14 @@ pub async fn install_get_modpack_preview(
|
||||
pub async fn install_create_instance(
|
||||
request: InstallCreateInstanceRequest,
|
||||
) -> Result<InstallJobSnapshot> {
|
||||
if request.instance_mode == theseus::data::InstanceMode::StarLight {
|
||||
return Err(theseus::ErrorKind::InputError(
|
||||
"StarLight 实例的版本由服务器决定,请使用官方整合包自动安装入口"
|
||||
.into(),
|
||||
)
|
||||
.as_error()
|
||||
.into());
|
||||
}
|
||||
let job = theseus::install::create_instance_with_adjuncts(
|
||||
request.name.trim().to_string(),
|
||||
request.game_version,
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
// Runs inside the embedded skin site only. The JWT never leaves that origin.
|
||||
// Only the allowlisted launcher parent may request a JWT for native pack downloads.
|
||||
;(() => {
|
||||
if (location.origin !== 'https://skin.starlight.cool' || window.parent === window) return
|
||||
|
||||
@ -202,11 +202,7 @@
|
||||
},
|
||||
)
|
||||
const skinBody = await skinResponse.json().catch(() => null)
|
||||
if (
|
||||
!skinResponse.ok ||
|
||||
!skinBody?.payload ||
|
||||
typeof skinBody.payload !== 'object'
|
||||
)
|
||||
if (!skinResponse.ok || !skinBody?.payload || typeof skinBody.payload !== 'object')
|
||||
return { player, skinData: null }
|
||||
return { player, skinData: skinBody.payload }
|
||||
} catch {
|
||||
@ -437,6 +433,23 @@
|
||||
void checkSession(true)
|
||||
return
|
||||
}
|
||||
if (
|
||||
event.data?.type === 'starlight-pack-token-request' &&
|
||||
parentOrigin === event.origin &&
|
||||
typeof event.data.requestId === 'string' &&
|
||||
/^pack-token-\d+-\d+$/.test(event.data.requestId)
|
||||
) {
|
||||
let token = null
|
||||
try {
|
||||
token = localStorage.getItem('loginToken') || null
|
||||
} catch {}
|
||||
if (snapshot.status !== 'signed-in' || token !== lastToken) token = null
|
||||
window.parent.postMessage(
|
||||
{ type: 'starlight-pack-token-result', requestId: event.data.requestId, token },
|
||||
parentOrigin,
|
||||
)
|
||||
return
|
||||
}
|
||||
if (
|
||||
event.data?.type === 'starlight-skin-luck-request' &&
|
||||
parentOrigin === event.origin &&
|
||||
|
||||
@ -157,6 +157,30 @@ test('logout, invalid token, network error and account switching replace old sta
|
||||
assert.equal(h.messages.at(-1).data.status, 'signed-out')
|
||||
})
|
||||
|
||||
test('pack JWT is returned only for an explicit request from the connected launcher', async () => {
|
||||
const h = harness()
|
||||
h.token('pack.jwt.secret')
|
||||
const request = { type: 'starlight-pack-token-request', requestId: 'pack-token-1-1' }
|
||||
await h.message(request)
|
||||
await h.connect('https://evil.example')
|
||||
assert.equal(h.messages.length, 0)
|
||||
await h.connect()
|
||||
assert.ok(!JSON.stringify(h.messages).includes('pack.jwt.secret'))
|
||||
await h.message(request, 'https://evil.example')
|
||||
await h.message(request, 'http://localhost:5201', {})
|
||||
assert.ok(!JSON.stringify(h.messages).includes('pack.jwt.secret'))
|
||||
await h.message(request)
|
||||
assert.equal(h.messages.at(-1).data.type, 'starlight-pack-token-result')
|
||||
assert.equal(h.messages.at(-1).data.token, 'pack.jwt.secret')
|
||||
assert.equal(h.messages.at(-1).target, 'http://localhost:5201')
|
||||
h.token('unverified.account.token')
|
||||
await h.message({ ...request, requestId: 'pack-token-1-2' })
|
||||
assert.equal(h.messages.at(-1).data.token, null)
|
||||
h.token(null)
|
||||
await h.message({ ...request, requestId: 'pack-token-1-3' })
|
||||
assert.equal(h.messages.at(-1).data.token, null)
|
||||
})
|
||||
|
||||
test('a delayed response cannot restore the user after logout', async () => {
|
||||
const h = harness()
|
||||
let finish
|
||||
|
||||
Reference in New Issue
Block a user