Complete private authentication, server integrations and activity reporting

Add Fabric/Forge version builds and Paper integration, preserve permanent player identities across renames, harden session authorization, and surface privacy-conscious launcher/server activity in the panel.
This commit is contained in:
SCOPEDD committed 2026-09-28 13:31:17 -04:00
commit a1f19e86c6
74 files changed
+2108 -95

No files matched your search

+19 -7
View File
@@ -42,16 +42,28 @@ pub fn host_of(url: &str) -> String {
host.split(':').next().unwrap_or(host).to_string()
}
/// Client IP: the first `X-Forwarded-For` hop, `X-Real-IP`, or the socket.
/// Forwarded addresses are accepted only from explicitly trusted proxies.
pub struct ClientIp(pub Option<String>);
impl<S: Send + Sync> FromRequestParts<S> for ClientIp {
impl FromRequestParts<AppState> for ClientIp {
type Rejection = AppError;
async fn from_request_parts(parts: &mut Parts, _: &S) -> Result<Self, Self::Rejection> {
let forwarded = header(&parts.headers, "x-forwarded-for").and_then(|v| v.split(',').next()).map(|v| v.trim().to_string());
let real = header(&parts.headers, "x-real-ip").map(String::from);
let socket = parts.extensions.get::<ConnectInfo<SocketAddr>>().map(|c| c.0.ip().to_string());
Ok(ClientIp(forwarded.or(real).or(socket)))
async fn from_request_parts(parts: &mut Parts, state: &AppState) -> Result<Self, Self::Rejection> {
let peer = parts.extensions.get::<ConnectInfo<SocketAddr>>().map(|c| c.0.ip());
if peer.is_some_and(|ip| state.cfg.trusted_proxies.contains(&ip)) {
// Walk right-to-left so a client-supplied prefix cannot spoof its IP.
if let Some(chain) = header(&parts.headers, "x-forwarded-for") {
for hop in chain.rsplit(',') {
let Ok(ip) = hop.trim().parse::<std::net::IpAddr>() else { return Ok(ClientIp(None)) };
if !state.cfg.trusted_proxies.contains(&ip) {
return Ok(ClientIp(Some(ip.to_string())));
}
}
}
if let Some(ip) = header(&parts.headers, "x-real-ip").and_then(|v| v.parse::<std::net::IpAddr>().ok()) {
return Ok(ClientIp(Some(ip.to_string())));
}
}
Ok(ClientIp(peer.map(|ip| ip.to_string())))
}
}