Feature/start tunnel (#3037)

* fix live-build resolv.conf

* improved debuggability

* wip: start-tunnel

* fixes for trixie and tor

* non-free-firmware on trixie

* wip

* web server WIP

* wip: tls refactor

* FE patchdb, mocks, and most endpoints

* fix editing records and patch mocks

* refactor complete

* finish api

* build and formatter update

* minor change toi viewing addresses and fix build

* fixes

* more providers

* endpoint for getting config

* fix tests

* api fixes

* wip: separate port forward controller into parts

* simplify iptables rules

* bump sdk

* misc fixes

* predict next subnet and ip, use wan ips, and form validation

* refactor: break big components apart and address todos (#3043)

* refactor: break big components apart and address todos

* starttunnel readme, fix pf mocks, fix adding tor domain in startos

---------

Co-authored-by: Matt Hill <mattnine@protonmail.com>

* better tui

* tui tweaks

* fix: address comments

* better regex for subnet

* fixes

* better validation

* handle rpc errors

* build fixes

* fix: address comments (#3044)

* fix: address comments

* fix unread notification mocks

* fix row click for notification

---------

Co-authored-by: Matt Hill <mattnine@protonmail.com>

* fix raspi build

* fix build

* fix build

* fix build

* fix build

* try to fix build

* fix tests

* fix tests

* fix rsync tests

* delete useless effectful test

---------

Co-authored-by: Matt Hill <mattnine@protonmail.com>
Co-authored-by: Alex Inkin <alexander@inkin.ru>
This commit is contained in:
Aiden McClelland
2025-11-07 03:12:05 -07:00
committed by GitHub
parent 1ea525feaa
commit 68f401bfa3
229 changed files with 17255 additions and 10553 deletions

View File

@@ -5,6 +5,7 @@ use std::sync::Arc;
use chrono::Utc;
use clap::Parser;
use http::HeaderMap;
use imbl_value::InternedString;
use patch_db::PatchDb;
use reqwest::{Client, Proxy};
@@ -168,25 +169,38 @@ impl CallRemote<RegistryContext> for CliContext {
let url = if let Some(url) = self.registry_url.clone() {
url
} else if self.registry_hostname.is_some() {
format!(
let mut url: Url = format!(
"http://{}",
self.registry_listen.unwrap_or(DEFAULT_REGISTRY_LISTEN)
)
.parse()
.map_err(Error::from)?
.map_err(Error::from)?;
url.path_segments_mut()
.map_err(|_| Error::new(eyre!("cannot extend URL path"), ErrorKind::ParseUrl))?
.push("rpc")
.push("v0");
url
} else {
return Err(
Error::new(eyre!("`--registry` required"), ErrorKind::InvalidRequest).into(),
);
};
method = method.strip_prefix("registry.").unwrap_or(method);
let sig_context = self
.registry_hostname
.clone()
.or(url.host().as_ref().map(InternedString::from_display))
.or_not_found("registry hostname")?;
.or_else(|| url.host().as_ref().map(InternedString::from_display));
crate::middleware::signature::call_remote(self, url, &sig_context, method, params).await
crate::middleware::signature::call_remote(
self,
url,
HeaderMap::new(),
sig_context.as_deref(),
method,
params,
)
.await
}
}
@@ -195,61 +209,32 @@ impl CallRemote<RegistryContext, RegistryUrlParams> for RpcContext {
&self,
mut method: &str,
params: Value,
RegistryUrlParams { registry }: RegistryUrlParams,
RegistryUrlParams { mut registry }: RegistryUrlParams,
) -> Result<Value, RpcError> {
use reqwest::Method;
use reqwest::header::{ACCEPT, CONTENT_LENGTH, CONTENT_TYPE};
use rpc_toolkit::RpcResponse;
use rpc_toolkit::yajrc::{GenericRpcMethod, Id, RpcRequest};
let mut headers = HeaderMap::new();
headers.insert(
DEVICE_INFO_HEADER,
DeviceInfo::load(self).await?.to_header_value(),
);
registry
.path_segments_mut()
.map_err(|_| Error::new(eyre!("cannot extend URL path"), ErrorKind::ParseUrl))?
.push("rpc")
.push("v0");
let url = registry.join("rpc/v0")?;
method = method.strip_prefix("registry.").unwrap_or(method);
let sig_context = registry.host_str().map(InternedString::from);
let rpc_req = RpcRequest {
id: Some(Id::Number(0.into())),
method: GenericRpcMethod::<_, _, Value>::new(method),
crate::middleware::signature::call_remote(
self,
registry,
headers,
sig_context.as_deref(),
method,
params,
};
let body = serde_json::to_vec(&rpc_req)?;
let res = self
.client
.request(Method::POST, url)
.header(CONTENT_TYPE, "application/json")
.header(ACCEPT, "application/json")
.header(CONTENT_LENGTH, body.len())
.header(
DEVICE_INFO_HEADER,
DeviceInfo::load(self).await?.to_header_value(),
)
.body(body)
.send()
.await?;
if !res.status().is_success() {
let status = res.status();
let txt = res.text().await?;
let mut res = Err(Error::new(
eyre!("{}", status.canonical_reason().unwrap_or(status.as_str())),
ErrorKind::Network,
));
if !txt.is_empty() {
res = res.with_ctx(|_| (ErrorKind::Network, txt));
}
return res.map_err(From::from);
}
match res
.headers()
.get(CONTENT_TYPE)
.and_then(|v| v.to_str().ok())
{
Some("application/json") => {
serde_json::from_slice::<RpcResponse>(&*res.bytes().await?)
.with_kind(ErrorKind::Deserialization)?
.result
}
_ => Err(Error::new(eyre!("unknown content type"), ErrorKind::Network).into()),
}
)
.await
}
}

View File

@@ -175,7 +175,7 @@ impl Middleware<RegistryContext> for DeviceInfoMiddleware {
async move {
if metadata.get_device_info {
if let Some(device_info) = &self.device_info {
request.params["__device_info"] =
request.params["__DeviceInfo_device_info"] =
to_value(&DeviceInfo::from_header_value(device_info)?)?;
}
}

View File

@@ -141,9 +141,3 @@ pub fn registry_router(ctx: RegistryContext) -> Router {
}),
)
}
impl<A: Accept + Send + Sync + 'static> WebServer<A> {
pub fn serve_registry(&mut self, ctx: RegistryContext) {
self.serve_router(registry_router(ctx))
}
}

View File

@@ -83,7 +83,7 @@ pub struct AddAssetParams {
pub platform: InternedString,
#[ts(type = "string")]
pub url: Url,
#[serde(rename = "__auth_signer")]
#[serde(rename = "__Auth_signer")]
#[ts(skip)]
pub signer: AnyVerifyingKey,
pub signature: AnySignature,
@@ -289,7 +289,7 @@ pub struct RemoveAssetParams {
pub version: Version,
#[ts(type = "string")]
pub platform: InternedString,
#[serde(rename = "__auth_signer")]
#[serde(rename = "__Auth_signer")]
#[ts(skip)]
pub signer: AnyVerifyingKey,
}

View File

@@ -56,7 +56,7 @@ pub struct SignAssetParams {
#[ts(type = "string")]
platform: InternedString,
#[ts(skip)]
#[serde(rename = "__auth_signer")]
#[serde(rename = "__Auth_signer")]
signer: AnyVerifyingKey,
signature: AnySignature,
}

View File

@@ -68,7 +68,7 @@ pub struct AddVersionParams {
pub source_version: VersionRange,
#[arg(skip)]
#[ts(skip)]
#[serde(rename = "__auth_signer")]
#[serde(rename = "__Auth_signer")]
pub signer: Option<AnyVerifyingKey>,
}
@@ -146,7 +146,7 @@ pub struct GetOsVersionParams {
platform: Option<InternedString>,
#[ts(skip)]
#[arg(skip)]
#[serde(rename = "__device_info")]
#[serde(rename = "__DeviceInfo_device_info")]
pub device_info: Option<DeviceInfo>,
}

View File

@@ -31,7 +31,7 @@ pub struct AddPackageParams {
#[ts(type = "string")]
pub url: Url,
#[ts(skip)]
#[serde(rename = "__auth_signer")]
#[serde(rename = "__Auth_signer")]
pub uploader: AnyVerifyingKey,
pub commitment: MerkleArchiveCommitment,
pub signature: AnySignature,
@@ -169,7 +169,7 @@ pub struct RemovePackageParams {
pub version: VersionString,
#[ts(skip)]
#[arg(skip)]
#[serde(rename = "__auth_signer")]
#[serde(rename = "__Auth_signer")]
pub signer: Option<AnyVerifyingKey>,
}

View File

@@ -51,7 +51,7 @@ pub struct GetPackageParams {
pub source_version: Option<VersionString>,
#[ts(skip)]
#[arg(skip)]
#[serde(rename = "__device_info")]
#[serde(rename = "__DeviceInfo_device_info")]
pub device_info: Option<DeviceInfo>,
#[serde(default)]
#[arg(default_value = "none")]