feat: add iframe store page

This commit is contained in:
DecDuck
2025-04-08 16:17:03 +10:00
parent 6b9b9e3606
commit 40eb19cf8b
6 changed files with 110 additions and 8 deletions

View File

@ -1,3 +1,4 @@
<template></template> <template>
<script setup lang="ts"> <iframe src="server://drop.local/store" class="w-full h-full" />
</script> </template>
<script setup lang="ts"></script>

View File

@ -28,6 +28,7 @@ pub struct DatabaseAuth {
pub private: String, pub private: String,
pub cert: String, pub cert: String,
pub client_id: String, pub client_id: String,
pub web_token: Option<String>,
} }
// Strings are version names for a particular game // Strings are version names for a particular game
@ -76,7 +77,6 @@ pub struct GameVersion {
#[serde(default = "default_template")] #[serde(default = "default_template")]
pub setup_command_template: String, pub setup_command_template: String,
pub only_setup: bool, pub only_setup: bool,
pub version_index: usize, pub version_index: usize,
@ -107,10 +107,14 @@ pub struct Database {
pub base_url: String, pub base_url: String,
pub applications: DatabaseApplications, pub applications: DatabaseApplications,
pub prev_database: Option<PathBuf>, pub prev_database: Option<PathBuf>,
pub cache_dir: PathBuf pub cache_dir: PathBuf,
} }
impl Database { impl Database {
fn new<T: Into<PathBuf>>(games_base_dir: T, prev_database: Option<PathBuf>, cache_dir: PathBuf) -> Self { fn new<T: Into<PathBuf>>(
games_base_dir: T,
prev_database: Option<PathBuf>,
cache_dir: PathBuf,
) -> Self {
Self { Self {
applications: DatabaseApplications { applications: DatabaseApplications {
install_dirs: vec![games_base_dir.into()], install_dirs: vec![games_base_dir.into()],
@ -214,7 +218,7 @@ fn handle_invalid_database(
_e: RustbreakError, _e: RustbreakError,
db_path: PathBuf, db_path: PathBuf,
games_base_dir: PathBuf, games_base_dir: PathBuf,
cache_dir: PathBuf cache_dir: PathBuf,
) -> rustbreak::Database<Database, rustbreak::backend::PathBackend, DropDatabaseSerializer> { ) -> rustbreak::Database<Database, rustbreak::backend::PathBackend, DropDatabaseSerializer> {
let new_path = { let new_path = {
let time = Utc::now().timestamp(); let time = Utc::now().timestamp();
@ -231,7 +235,7 @@ fn handle_invalid_database(
let db = Database::new( let db = Database::new(
games_base_dir.into_os_string().into_string().unwrap(), games_base_dir.into_os_string().into_string().unwrap(),
Some(new_path), Some(new_path),
cache_dir cache_dir,
); );
PathDatabase::create_at_path(db_path, db).expect("Database could not be created") PathDatabase::create_at_path(db_path, db).expect("Database could not be created")

View File

@ -51,6 +51,7 @@ use remote::commands::{
}; };
use remote::fetch_object::{fetch_object, fetch_object_offline}; use remote::fetch_object::{fetch_object, fetch_object_offline};
use remote::requests::make_request; use remote::requests::make_request;
use remote::server_proto::{handle_server_proto, handle_server_proto_offline};
use reqwest::blocking::Body; use reqwest::blocking::Body;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::env; use std::env;
@ -383,6 +384,17 @@ pub fn run() {
responder responder
); );
}) })
.register_asynchronous_uri_scheme_protocol("server", move |ctx, request, responder| {
let state: tauri::State<'_, Mutex<AppState>> = ctx.app_handle().state();
offline!(
state,
handle_server_proto,
handle_server_proto_offline,
request,
responder
);
})
.on_window_event(|window, event| { .on_window_event(|window, event| {
if let WindowEvent::CloseRequested { api, .. } = event { if let WindowEvent::CloseRequested { api, .. } = event {
window.hide().unwrap(); window.hide().unwrap();

View File

@ -114,11 +114,29 @@ fn recieve_handshake_logic(app: &AppHandle, path: String) -> Result<(), RemoteAc
private: response_struct.private, private: response_struct.private,
cert: response_struct.certificate, cert: response_struct.certificate,
client_id: response_struct.id, client_id: response_struct.id,
web_token: None, // gets created later
}); });
drop(handle); drop(handle);
save_db(); save_db();
} }
let web_token = {
let header = generate_authorization_header();
let token = client
.post(base_url.join("/api/v1/client/user/webtoken").unwrap())
.header("Authorization", header)
.send()
.unwrap();
token.text().unwrap()
};
let mut handle = borrow_db_mut_checked();
let mut_auth = handle.auth.as_mut().unwrap();
mut_auth.web_token = Some(web_token);
drop(handle);
save_db();
{ {
let app_state = app.state::<Mutex<AppState>>(); let app_state = app.state::<Mutex<AppState>>();
let mut app_state_handle = app_state.lock().unwrap(); let mut app_state_handle = app_state.lock().unwrap();

View File

@ -5,3 +5,4 @@ pub mod commands;
pub mod fetch_object; pub mod fetch_object;
pub mod remote; pub mod remote;
pub mod requests; pub mod requests;
pub mod server_proto;

View File

@ -0,0 +1,66 @@
use std::{path::PathBuf, str::FromStr};
use http::{
uri::{Authority, PathAndQuery},
Request, Response, StatusCode, Uri,
};
use log::info;
use reqwest::blocking::Client;
use tauri::UriSchemeResponder;
use crate::database::db::borrow_db_checked;
pub fn handle_server_proto_offline(_request: Request<Vec<u8>>, responder: UriSchemeResponder) {
let four_oh_four = Response::builder()
.status(StatusCode::NOT_FOUND)
.body(Vec::new())
.unwrap();
responder.respond(four_oh_four);
}
pub fn handle_server_proto(request: Request<Vec<u8>>, responder: UriSchemeResponder) {
let db_handle = borrow_db_checked();
let web_token = match &db_handle.auth.as_ref().unwrap().web_token {
Some(e) => e,
None => return,
};
let remote_uri = db_handle.base_url.parse::<Uri>().unwrap();
let path = request.uri().path();
let mut new_uri = request.uri().clone().into_parts();
new_uri.path_and_query =
Some(PathAndQuery::from_str(&format!("{}?noWrapper=true", path)).unwrap());
new_uri.authority = remote_uri.authority().cloned();
new_uri.scheme = remote_uri.scheme().cloned();
let new_uri = Uri::from_parts(new_uri).unwrap();
let whitelist_prefix = vec!["/store", "/api", "/_", "/fonts"];
if whitelist_prefix
.iter()
.map(|f| !path.starts_with(f))
.all(|f| f)
{
webbrowser::open(&new_uri.to_string()).unwrap();
return;
}
let client = Client::new();
let response = client
.request(request.method().clone(), new_uri.to_string())
.header("Authorization", format!("Bearer {}", web_token))
.headers(request.headers().clone())
.send()
.unwrap();
let response_status = response.status();
let response_body = response.bytes().unwrap();
let http_response = Response::builder()
.status(response_status)
.body(response_body.to_vec())
.unwrap();
responder.respond(http_response);
}