Compare commits
2 Commits
20ec64cf1c
...
55a91b1459
| Author | SHA1 | Date | |
|---|---|---|---|
| 55a91b1459 | |||
| d9695be153 |
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Serialize, Default)]
|
#[derive(Debug, Clone, Deserialize, Serialize, Default)]
|
||||||
pub struct GuiConfig {
|
pub struct GuiConfig {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub force_proxy: bool,
|
pub force_proxy: bool,
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
https_listen_address = "127.0.0.1:4433"
|
https_listen_address = "127.0.0.1:4433"
|
||||||
http_listen_address = "127.0.0.1:8080"
|
http_listen_address = "127.0.0.1:8080"
|
||||||
mumble_server_url = "[SERVER_URL_HERE]"
|
mumble_server_url = "[SERVER_URL_HERE]"
|
||||||
gui_path = "target/dx/mumble-web2-gui/release/web/public"
|
|
||||||
|
|
||||||
[gui]
|
[gui]
|
||||||
force_proxy = true
|
force_proxy = true
|
||||||
|
|||||||
@@ -4,8 +4,6 @@ http_listen_address = "127.0.0.1:4400"
|
|||||||
#key_path = "./key.pem"
|
#key_path = "./key.pem"
|
||||||
#mumble_server_url = "voip.ohea.xyz:64738"
|
#mumble_server_url = "voip.ohea.xyz:64738"
|
||||||
mumble_server_url = "127.0.0.1:64738"
|
mumble_server_url = "127.0.0.1:64738"
|
||||||
#gui_path = "./target/dx/mumble-web2-gui/release/web/public"
|
|
||||||
gui_path = "./target/dx/mumble-web2-gui/debug/web/public"
|
|
||||||
|
|
||||||
[gui]
|
[gui]
|
||||||
force_proxy = true
|
force_proxy = true
|
||||||
|
|||||||
+25
-23
@@ -9,7 +9,7 @@ use sir::{css, global_css};
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use tracing::error;
|
use tracing::error;
|
||||||
|
|
||||||
use crate::{imp, CONFIG};
|
use crate::imp;
|
||||||
|
|
||||||
pub type ChannelId = u32;
|
pub type ChannelId = u32;
|
||||||
pub type UserId = u32;
|
pub type UserId = u32;
|
||||||
@@ -26,6 +26,7 @@ pub enum Command {
|
|||||||
Connect {
|
Connect {
|
||||||
address: String,
|
address: String,
|
||||||
username: String,
|
username: String,
|
||||||
|
config: GuiConfig,
|
||||||
},
|
},
|
||||||
SendChat {
|
SendChat {
|
||||||
markdown: String,
|
markdown: String,
|
||||||
@@ -436,9 +437,7 @@ pub fn ChatView() -> Element {
|
|||||||
//},
|
//},
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn ControlView() -> Element {
|
pub fn ControlView(config: Resource<GuiConfig>) -> Element {
|
||||||
let config_future = use_resource(|| CONFIG.get());
|
|
||||||
|
|
||||||
let net: Coroutine<Command> = use_coroutine_handle();
|
let net: Coroutine<Command> = use_coroutine_handle();
|
||||||
let status = &STATE.status;
|
let status = &STATE.status;
|
||||||
let server = STATE.server.read();
|
let server = STATE.server.read();
|
||||||
@@ -457,7 +456,7 @@ pub fn ControlView() -> Element {
|
|||||||
|
|
||||||
let current_channel_name = server.channels[&channel].name.clone();
|
let current_channel_name = server.channels[&channel].name.clone();
|
||||||
|
|
||||||
let Some(proxy_url) = config_future
|
let Some(proxy_url) = config
|
||||||
.read_unchecked()
|
.read_unchecked()
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|gui_config| gui_config.proxy_url.clone())
|
.and_then(|gui_config| gui_config.proxy_url.clone())
|
||||||
@@ -706,7 +705,7 @@ pub fn ControlView() -> Element {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn ServerView() -> Element {
|
pub fn ServerView(config: Resource<GuiConfig>) -> Element {
|
||||||
let net: Coroutine<Command> = use_coroutine_handle();
|
let net: Coroutine<Command> = use_coroutine_handle();
|
||||||
let server = STATE.server.read();
|
let server = STATE.server.read();
|
||||||
let Some(&UserState {
|
let Some(&UserState {
|
||||||
@@ -797,25 +796,26 @@ pub fn ServerView() -> Element {
|
|||||||
}
|
}
|
||||||
div {
|
div {
|
||||||
class: "{control_box}",
|
class: "{control_box}",
|
||||||
ControlView {}
|
ControlView { config }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn LoginView() -> Element {
|
pub fn LoginView(config: Resource<GuiConfig>) -> Element {
|
||||||
let net: Coroutine<Command> = use_coroutine_handle();
|
let net: Coroutine<Command> = use_coroutine_handle();
|
||||||
|
|
||||||
let config_future = use_resource(|| CONFIG.get());
|
let mut address_input = use_signal(|| None::<String>);
|
||||||
|
let mut address = use_memo(move || {
|
||||||
let default_address = &*config_future
|
if let Some(addr) = address_input() {
|
||||||
.read_unchecked()
|
addr.clone()
|
||||||
.as_ref()
|
} else {
|
||||||
.and_then(|gui_config| gui_config.proxy_url.clone())
|
config()
|
||||||
.unwrap_or("".to_string());
|
.and_then(|c| c.proxy_url.clone())
|
||||||
|
.unwrap_or_default()
|
||||||
let mut address = use_signal(|| default_address.to_string());
|
}
|
||||||
|
});
|
||||||
|
|
||||||
let previous_username = imp::load_username();
|
let previous_username = imp::load_username();
|
||||||
let mut username = use_signal(|| previous_username.unwrap_or(String::new()));
|
let mut username = use_signal(|| previous_username.unwrap_or(String::new()));
|
||||||
@@ -869,6 +869,7 @@ pub fn LoginView() -> Element {
|
|||||||
net.send(Connect {
|
net.send(Connect {
|
||||||
address: address.read().clone(),
|
address: address.read().clone(),
|
||||||
username: username.read().clone(),
|
username: username.read().clone(),
|
||||||
|
config: config.read().clone().unwrap_or_default(),
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
let status = &STATE.status;
|
let status = &STATE.status;
|
||||||
@@ -918,7 +919,7 @@ pub fn LoginView() -> Element {
|
|||||||
placeholder: "server address",
|
placeholder: "server address",
|
||||||
value: "{address.read()}",
|
value: "{address.read()}",
|
||||||
autofocus: "true",
|
autofocus: "true",
|
||||||
oninput: move |evt| address.set(evt.value().clone()),
|
oninput: move |evt| address_input.set(Some(evt.value().clone())),
|
||||||
}
|
}
|
||||||
{bottom}
|
{bottom}
|
||||||
}
|
}
|
||||||
@@ -927,9 +928,10 @@ pub fn LoginView() -> Element {
|
|||||||
|
|
||||||
pub fn app() -> Element {
|
pub fn app() -> Element {
|
||||||
use_coroutine(|rx: UnboundedReceiver<Command>| super::network_entrypoint(rx));
|
use_coroutine(|rx: UnboundedReceiver<Command>| super::network_entrypoint(rx));
|
||||||
use_future(|| async move {
|
let config = use_resource(|| async move {
|
||||||
if let Err(err) = imp::load_config().await {
|
match imp::load_config().await {
|
||||||
error!("{}", err)
|
Ok(config) => config,
|
||||||
|
Err(_) => GuiConfig::default(),
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1006,8 +1008,8 @@ pub fn app() -> Element {
|
|||||||
|
|
||||||
sir::AppStyle { }
|
sir::AppStyle { }
|
||||||
match *STATE.status.read() {
|
match *STATE.status.read() {
|
||||||
Connected => rsx!(ServerView {}),
|
Connected => rsx!(ServerView { config }),
|
||||||
_ => rsx!(LoginView {}),
|
_ => rsx!(LoginView { config }),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ use tokio_rustls::rustls::ClientConfig;
|
|||||||
use tokio_rustls::rustls::DigitallySignedStruct;
|
use tokio_rustls::rustls::DigitallySignedStruct;
|
||||||
use tokio_rustls::TlsConnector;
|
use tokio_rustls::TlsConnector;
|
||||||
use tokio_util::compat::{TokioAsyncReadCompatExt as _, TokioAsyncWriteCompatExt as _};
|
use tokio_util::compat::{TokioAsyncReadCompatExt as _, TokioAsyncWriteCompatExt as _};
|
||||||
use tracing::{error, warn};
|
use tracing::{error, info, instrument, warn};
|
||||||
|
|
||||||
pub use tokio::task::spawn;
|
pub use tokio::task::spawn;
|
||||||
pub use tokio::time::sleep;
|
pub use tokio::time::sleep;
|
||||||
@@ -183,11 +183,15 @@ impl ServerCertVerifier for NoCertificateVerification {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument]
|
||||||
pub async fn network_connect(
|
pub async fn network_connect(
|
||||||
address: String,
|
address: String,
|
||||||
username: String,
|
username: String,
|
||||||
event_rx: &mut UnboundedReceiver<Command>,
|
event_rx: &mut UnboundedReceiver<Command>,
|
||||||
|
gui_config: &GuiConfig,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
|
info!("connecting");
|
||||||
|
|
||||||
let config = ClientConfig::builder()
|
let config = ClientConfig::builder()
|
||||||
.dangerous()
|
.dangerous()
|
||||||
.with_custom_certificate_verifier(Arc::new(NoCertificateVerification))
|
.with_custom_certificate_verifier(Arc::new(NoCertificateVerification))
|
||||||
|
|||||||
+21
-24
@@ -1,5 +1,4 @@
|
|||||||
use crate::app::Command;
|
use crate::app::Command;
|
||||||
use crate::CONFIG;
|
|
||||||
use color_eyre::eyre::{bail, eyre, Error};
|
use color_eyre::eyre::{bail, eyre, Error};
|
||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
use futures::{AsyncRead, AsyncWrite};
|
use futures::{AsyncRead, AsyncWrite};
|
||||||
@@ -9,7 +8,9 @@ use mumble_protocol::control::{ClientControlCodec, ControlPacket};
|
|||||||
use mumble_protocol::voice::{VoicePacket, VoicePacketPayload};
|
use mumble_protocol::voice::{VoicePacket, VoicePacketPayload};
|
||||||
use mumble_protocol::Serverbound;
|
use mumble_protocol::Serverbound;
|
||||||
use mumble_web2_common::GuiConfig;
|
use mumble_web2_common::GuiConfig;
|
||||||
|
use reqwest::Url;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
use tracing::level_filters::LevelFilter;
|
||||||
use tracing::{debug, error, info, instrument};
|
use tracing::{debug, error, info, instrument};
|
||||||
use wasm_bindgen::prelude::*;
|
use wasm_bindgen::prelude::*;
|
||||||
use wasm_bindgen_futures::JsFuture;
|
use wasm_bindgen_futures::JsFuture;
|
||||||
@@ -308,8 +309,9 @@ pub async fn network_connect(
|
|||||||
address: String,
|
address: String,
|
||||||
username: String,
|
username: String,
|
||||||
event_rx: &mut UnboundedReceiver<Command>,
|
event_rx: &mut UnboundedReceiver<Command>,
|
||||||
|
gui_config: &GuiConfig,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
info!("Rust via WASM!");
|
info!("connecting");
|
||||||
|
|
||||||
let object = web_sys::js_sys::Object::new();
|
let object = web_sys::js_sys::Object::new();
|
||||||
|
|
||||||
@@ -320,8 +322,7 @@ pub async fn network_connect(
|
|||||||
)
|
)
|
||||||
.ey()?;
|
.ey()?;
|
||||||
|
|
||||||
if let Some(server_hash) = &CONFIG.try_get().and_then(|cfg| cfg.cert_hash) {
|
if let Some(server_hash) = &gui_config.cert_hash {
|
||||||
error!("{:?}", server_hash);
|
|
||||||
let hash = web_sys::js_sys::Uint8Array::from(server_hash.as_slice());
|
let hash = web_sys::js_sys::Uint8Array::from(server_hash.as_slice());
|
||||||
web_sys::js_sys::Reflect::set(&object, &"value".into(), &hash).ey()?;
|
web_sys::js_sys::Reflect::set(&object, &"value".into(), &hash).ey()?;
|
||||||
}
|
}
|
||||||
@@ -387,27 +388,20 @@ pub fn load_username() -> Option<String> {
|
|||||||
.ok()?
|
.ok()?
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_config_from_window() -> Option<GuiConfig> {
|
pub async fn load_config() -> color_eyre::Result<GuiConfig> {
|
||||||
serde_wasm_bindgen::from_value(Reflect::get(window()?.as_ref(), &"config".into()).ok()?).ok()
|
let config_url = match option_env!("MUMBLE_WEB2_GUI_CONFIG_URL") {
|
||||||
}
|
Some(url) => Url::parse(url)?,
|
||||||
|
None => {
|
||||||
|
let window: web_sys::Window = web_sys::window().expect("no global `window` exists");
|
||||||
|
let location = window.location();
|
||||||
|
Url::parse(&location.href().ey()?)?.join("config")?
|
||||||
|
}
|
||||||
|
};
|
||||||
|
info!("loading config from {}", config_url);
|
||||||
|
|
||||||
fn load_config_from_env() -> Option<GuiConfig> {
|
let config = reqwest::get(config_url).await?.json::<GuiConfig>().await?;
|
||||||
serde_json::from_str(option_env!("MUMBLE_WEB2_GUI_CONFIG")?).ok()?
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn load_config() -> color_eyre::Result<()> {
|
Ok(config)
|
||||||
let config_url = option_env!("MUMBLE_WEB2_GUI_CONFIG_URL").ok_or(eyre!("foo"))?;
|
|
||||||
|
|
||||||
let config = reqwest::get(config_url)
|
|
||||||
.await
|
|
||||||
.unwrap()
|
|
||||||
.json::<GuiConfig>()
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
crate::CONFIG.set(config);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init_logging() {
|
pub fn init_logging() {
|
||||||
@@ -420,11 +414,14 @@ pub fn init_logging() {
|
|||||||
let fmt_layer = tracing_subscriber::fmt::layer()
|
let fmt_layer = tracing_subscriber::fmt::layer()
|
||||||
.with_ansi(false) // Only partially supported across browsers
|
.with_ansi(false) // Only partially supported across browsers
|
||||||
.without_time() // std::time is not available in browsers
|
.without_time() // std::time is not available in browsers
|
||||||
.with_writer(MakeWebConsoleWriter::new()); // write events to the console
|
.with_writer(MakeWebConsoleWriter::new()) // write events to the console
|
||||||
|
.with_filter(LevelFilter::DEBUG);
|
||||||
let perf_layer = performance_layer().with_details_from_fields(Pretty::default());
|
let perf_layer = performance_layer().with_details_from_fields(Pretty::default());
|
||||||
|
|
||||||
tracing_subscriber::registry()
|
tracing_subscriber::registry()
|
||||||
.with(fmt_layer)
|
.with(fmt_layer)
|
||||||
.with(perf_layer)
|
.with(perf_layer)
|
||||||
.init();
|
.init();
|
||||||
|
|
||||||
|
info!("logging initiated");
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-5
@@ -33,18 +33,20 @@ pub mod app;
|
|||||||
pub mod imp;
|
pub mod imp;
|
||||||
mod msghtml;
|
mod msghtml;
|
||||||
|
|
||||||
//pub static CONFIG: Lazy<GuiConfig> = Lazy::new(|| imp::load_config().unwrap_or_default());
|
|
||||||
pub static CONFIG: async_cell::sync::AsyncCell<GuiConfig> = async_cell::sync::AsyncCell::new();
|
|
||||||
|
|
||||||
pub async fn network_entrypoint(mut event_rx: UnboundedReceiver<Command>) {
|
pub async fn network_entrypoint(mut event_rx: UnboundedReceiver<Command>) {
|
||||||
loop {
|
loop {
|
||||||
let Some(Command::Connect { address, username }) = event_rx.next().await else {
|
let Some(Command::Connect {
|
||||||
|
address,
|
||||||
|
username,
|
||||||
|
config,
|
||||||
|
}) = event_rx.next().await
|
||||||
|
else {
|
||||||
panic!("did not receive connect command")
|
panic!("did not receive connect command")
|
||||||
};
|
};
|
||||||
|
|
||||||
*STATE.server.write() = Default::default();
|
*STATE.server.write() = Default::default();
|
||||||
*STATE.status.write() = ConnectionState::Connecting;
|
*STATE.status.write() = ConnectionState::Connecting;
|
||||||
if let Err(error) = imp::network_connect(address, username, &mut event_rx).await {
|
if let Err(error) = imp::network_connect(address, username, &mut event_rx, &config).await {
|
||||||
error!("could not connect {:?}", error);
|
error!("could not connect {:?}", error);
|
||||||
*STATE.status.write() = ConnectionState::Failed(error.to_string());
|
*STATE.status.write() = ConnectionState::Failed(error.to_string());
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+21
-25
@@ -31,7 +31,7 @@ fn default_cert_alt_names() -> Vec<String> {
|
|||||||
vec!["localhost".into()]
|
vec!["localhost".into()]
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
struct Config {
|
struct Config {
|
||||||
https_listen_address: SocketAddr,
|
https_listen_address: SocketAddr,
|
||||||
http_listen_address: Option<SocketAddr>,
|
http_listen_address: Option<SocketAddr>,
|
||||||
@@ -41,7 +41,7 @@ struct Config {
|
|||||||
cert_alt_names: Vec<String>,
|
cert_alt_names: Vec<String>,
|
||||||
mumble_server_url: String,
|
mumble_server_url: String,
|
||||||
mumble_server_address: Option<SocketAddr>,
|
mumble_server_address: Option<SocketAddr>,
|
||||||
gui_path: PathBuf,
|
gui_path: Option<PathBuf>,
|
||||||
gui: Mutex<GuiConfig>,
|
gui: Mutex<GuiConfig>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,8 +52,15 @@ static CONFIG: OnceCell<Config> = OnceCell::new();
|
|||||||
async fn serve_gui_index_html(req: &Request, res: &mut Response) {
|
async fn serve_gui_index_html(req: &Request, res: &mut Response) {
|
||||||
let config = CONFIG.get().unwrap();
|
let config = CONFIG.get().unwrap();
|
||||||
|
|
||||||
|
let path = match &config.gui_path {
|
||||||
|
Some(p) => p.join("index.html"),
|
||||||
|
None => {
|
||||||
|
res.status_code(StatusCode::NOT_FOUND);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Load the HTML file
|
// Load the HTML file
|
||||||
let path = config.gui_path.join("index.html");
|
|
||||||
let html = match fs::read_to_string(&path).await {
|
let html = match fs::read_to_string(&path).await {
|
||||||
Ok(content) => content,
|
Ok(content) => content,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
@@ -74,10 +81,9 @@ async fn serve_gui_index_html(req: &Request, res: &mut Response) {
|
|||||||
res.render(Text::Html(modified_html));
|
res.render(Text::Html(modified_html));
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn init_config() -> Result<()> {
|
fn init_config() -> Result<()> {
|
||||||
let mut config: Config = toml::from_str(
|
let mut config: Config = toml::from_str(
|
||||||
&fs::read_to_string("./config.toml")
|
&std::fs::read_to_string("./config.toml")
|
||||||
.await
|
|
||||||
.context("reading config.toml (try making a copy of config.toml.example)")?,
|
.context("reading config.toml (try making a copy of config.toml.example)")?,
|
||||||
)?;
|
)?;
|
||||||
let mumble_server_addr = config
|
let mumble_server_addr = config
|
||||||
@@ -102,10 +108,9 @@ async fn init_config() -> Result<()> {
|
|||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<()> {
|
async fn main() -> Result<()> {
|
||||||
init_logging();
|
init_logging();
|
||||||
init_config().await?;
|
init_config()?;
|
||||||
let config = CONFIG.get().unwrap();
|
let config = CONFIG.get().unwrap();
|
||||||
info!("config\n{}", toml::to_string_pretty(&config.gui)?);
|
info!("config\n{}", toml::to_string_pretty(&config)?);
|
||||||
info!("gui config\n{}", serde_json::to_string_pretty(&config.gui)?);
|
|
||||||
|
|
||||||
rustls::crypto::aws_lc_rs::default_provider()
|
rustls::crypto::aws_lc_rs::default_provider()
|
||||||
.install_default()
|
.install_default()
|
||||||
@@ -150,20 +155,18 @@ async fn main() -> Result<()> {
|
|||||||
let rustls_config = RustlsConfig::new(Keycert::new().cert(cert.as_slice()).key(key.as_slice()));
|
let rustls_config = RustlsConfig::new(Keycert::new().cert(cert.as_slice()).key(key.as_slice()));
|
||||||
|
|
||||||
let config_craft = ConfigCraft {
|
let config_craft = ConfigCraft {
|
||||||
client_config: MumbleClientConfig {
|
client_config: config.gui.lock().unwrap().clone(),
|
||||||
force_proxy: true,
|
|
||||||
proxy_url: "https://localhost:4433".to_string(),
|
|
||||||
cert_hash: config.gui.lock().unwrap().cert_hash.clone().unwrap(),
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Server routing
|
// Server routing
|
||||||
let router = Router::new()
|
let mut router = Router::new()
|
||||||
.get(serve_gui_index_html)
|
.get(serve_gui_index_html)
|
||||||
.push(Router::with_path("/proxy").goal(connect_proxy))
|
.push(Router::with_path("/proxy").goal(connect_proxy))
|
||||||
.push(Router::with_path("/config").get(config_craft.get_config()))
|
.push(Router::with_path("/config").get(config_craft.get_config()))
|
||||||
.push(Router::with_path("/<*+rest>").get(StaticDir::new(config.gui_path.clone())))
|
|
||||||
.hoop(Logger::new());
|
.hoop(Logger::new());
|
||||||
|
if let Some(gui_path) = config.gui_path.clone() {
|
||||||
|
router = router.push(Router::with_path("/<*+rest>").get(StaticDir::new(gui_path)));
|
||||||
|
}
|
||||||
|
|
||||||
let cors = Cors::new().allow_origin(AllowOrigin::any()).into_handler();
|
let cors = Cors::new().allow_origin(AllowOrigin::any()).into_handler();
|
||||||
|
|
||||||
@@ -190,22 +193,15 @@ async fn main() -> Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Clone)]
|
|
||||||
struct MumbleClientConfig {
|
|
||||||
force_proxy: bool,
|
|
||||||
proxy_url: String,
|
|
||||||
cert_hash: Vec<u8>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ConfigCraft {
|
pub struct ConfigCraft {
|
||||||
client_config: MumbleClientConfig,
|
client_config: GuiConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[craft]
|
#[craft]
|
||||||
impl ConfigCraft {
|
impl ConfigCraft {
|
||||||
#[craft(handler)]
|
#[craft(handler)]
|
||||||
async fn get_config(&self) -> Json<MumbleClientConfig> {
|
async fn get_config(&self) -> Json<GuiConfig> {
|
||||||
Json(self.client_config.clone())
|
Json(self.client_config.clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user