fix(desktop): secure extension ping handler & fix UI alignment in settings

This commit is contained in:
NimBold
2026-06-14 12:26:17 +03:30
parent 4cfd59b45b
commit b1b17b7ad8
2 changed files with 48 additions and 21 deletions
+44 -17
View File
@@ -90,12 +90,30 @@ pub async fn start_server(
Ok(()) Ok(())
} }
async fn ping_handler(State(state): State<ServerState>) -> StatusCode { async fn ping_handler(
if state.frontend_ready.load(Ordering::Acquire) { State(state): State<ServerState>,
StatusCode::OK headers: HeaderMap,
} else { body: Bytes,
StatusCode::SERVICE_UNAVAILABLE ) -> StatusCode {
if !state.frontend_ready.load(Ordering::Acquire) {
return StatusCode::SERVICE_UNAVAILABLE;
} }
let signature = match headers.get("x-firelink-signature").and_then(|v| v.to_str().ok()) {
Some(v) => v,
None => return StatusCode::FORBIDDEN,
};
let timestamp_str = match headers.get("x-firelink-timestamp").and_then(|v| v.to_str().ok()) {
Some(v) => v,
None => return StatusCode::FORBIDDEN,
};
if verify_signature(signature, timestamp_str, &body, &state.pairing_token).is_err() {
return StatusCode::FORBIDDEN;
}
StatusCode::OK
} }
async fn download_handler( async fn download_handler(
@@ -107,25 +125,34 @@ async fn download_handler(
return Err(StatusCode::SERVICE_UNAVAILABLE); return Err(StatusCode::SERVICE_UNAVAILABLE);
} }
let signature = headers let signature = match headers.get("x-firelink-signature").and_then(|v| v.to_str().ok()) {
.get("x-firelink-signature") Some(v) => v,
.and_then(|v| v.to_str().ok()) None => return Err(StatusCode::FORBIDDEN),
.ok_or(StatusCode::FORBIDDEN)?; };
let timestamp_str = headers let timestamp_str = match headers.get("x-firelink-timestamp").and_then(|v| v.to_str().ok()) {
.get("x-firelink-timestamp") Some(v) => v,
.and_then(|v| v.to_str().ok()) None => return Err(StatusCode::FORBIDDEN),
.ok_or(StatusCode::FORBIDDEN)?; };
let timestamp = verify_signature(signature, timestamp_str, &body, &state.pairing_token) let timestamp = match verify_signature(signature, timestamp_str, &body, &state.pairing_token) {
.map_err(|_| StatusCode::FORBIDDEN)?; Ok(v) => v,
Err(_) => return Err(StatusCode::FORBIDDEN),
};
if !claim_request(signature, timestamp, &state.replay_cache) { if !claim_request(signature, timestamp, &state.replay_cache) {
return Err(StatusCode::FORBIDDEN); return Err(StatusCode::FORBIDDEN);
} }
let payload: ExtensionRequest = serde_json::from_slice(&body).map_err(|_| StatusCode::BAD_REQUEST)?; let payload: ExtensionRequest = match serde_json::from_slice(&body) {
let download = normalize_download(payload).ok_or(StatusCode::BAD_REQUEST)?; Ok(v) => v,
Err(_) => return Err(StatusCode::BAD_REQUEST),
};
let download = match normalize_download(payload) {
Some(v) => v,
None => return Err(StatusCode::BAD_REQUEST),
};
if let Some(window) = state.app_handle.get_webview_window("main") { if let Some(window) = state.app_handle.get_webview_window("main") {
let _ = window.show(); let _ = window.show();
+4 -4
View File
@@ -510,11 +510,11 @@ export default function SettingsView() {
<div className="flex gap-2"> <div className="flex gap-2">
<input <input
type="text" readOnly placeholder="Choose base folder..." type="text" readOnly placeholder="Choose base folder..."
className="app-control w-48 text-text-muted text-[11px]" className="app-control w-64 text-text-muted text-[11px] px-2"
/> />
<button <button
onClick={handleBrowseBulk} onClick={handleBrowseBulk}
className="app-icon-button bg-accent/10 hover:bg-accent/20 text-accent font-semibold px-3" className="app-button px-3 text-xs font-semibold text-accent border border-accent/20 bg-accent/10 hover:bg-accent/20"
> >
Browse Browse
</button> </button>
@@ -529,11 +529,11 @@ export default function SettingsView() {
type="text" type="text"
value={(settings.downloadDirectories || {})[category] || ''} value={(settings.downloadDirectories || {})[category] || ''}
onChange={(e) => settings.setCategoryDirectory(category, e.target.value)} onChange={(e) => settings.setCategoryDirectory(category, e.target.value)}
className="app-control w-48 text-[11px]" className="app-control w-64 text-[11px] px-2"
/> />
<button <button
onClick={() => handleBrowseCategory(category)} onClick={() => handleBrowseCategory(category)}
className="app-icon-button hover:bg-item-hover text-text-secondary px-3" className="app-button px-3 text-xs text-text-secondary hover:bg-item-hover"
> >
Browse Browse
</button> </button>