Many improvemtns and fixes related to decoupling of svelte and rust on android.
🏗️ Build and Test JellyTau / Run Tests (push) Failing after 18s
🏗️ Build and Test JellyTau / Build Android APK (push) Has been skipped
Traceability Validation / Check Requirement Traces (push) Failing after 2s

This commit is contained in:
2026-02-28 19:50:47 +01:00
parent 07f3bf04ca
commit e8e37649fa
53 changed files with 2309 additions and 792 deletions
+32 -31
View File
@@ -102,12 +102,18 @@ impl AuthManager {
self.connectivity_monitor = Some(monitor);
}
/// Normalize and validate server URL
pub fn normalize_url(url: &str) -> String {
/// Normalize and validate server URL.
/// Enforces HTTPS — plain HTTP is rejected for security.
pub fn normalize_url(url: &str) -> Result<String, String> {
let mut normalized = url.trim().to_string();
// Reject plain HTTP — all connections must use HTTPS
if normalized.starts_with("http://") {
return Err("HTTP connections are not allowed. Please use HTTPS (e.g., https://your-server.com).".to_string());
}
// Add https:// if no protocol specified
if !normalized.starts_with("http://") && !normalized.starts_with("https://") {
if !normalized.starts_with("https://") {
normalized = format!("https://{}", normalized);
}
@@ -116,12 +122,12 @@ impl AuthManager {
normalized.pop();
}
normalized
Ok(normalized)
}
/// Connect to server and get server info
pub async fn connect_to_server(&self, server_url: &str) -> Result<ServerInfo, String> {
let normalized_url = Self::normalize_url(server_url);
let normalized_url = Self::normalize_url(server_url)?;
let endpoint = format!("{}/System/Info/Public", normalized_url);
log::info!("[AuthManager] Connecting to server: {}", normalized_url);
@@ -165,7 +171,7 @@ impl AuthManager {
password: &str,
device_id: &str,
) -> Result<AuthResult, String> {
let url = Self::normalize_url(server_url);
let url = Self::normalize_url(server_url)?;
let endpoint = format!("{}/Users/AuthenticateByName", url);
log::info!("[AuthManager] Authenticating user: {}", username);
@@ -227,7 +233,7 @@ impl AuthManager {
access_token: &str,
device_id: &str,
) -> Result<User, String> {
let url = Self::normalize_url(server_url);
let url = Self::normalize_url(server_url)?;
let endpoint = format!("{}/Users/{}", url, user_id);
log::info!("[AuthManager] Verifying session for user: {}", user_id);
@@ -290,7 +296,7 @@ impl AuthManager {
access_token: &str,
device_id: &str,
) -> Result<(), String> {
let url = Self::normalize_url(server_url);
let url = Self::normalize_url(server_url)?;
let endpoint = format!("{}/Sessions/Logout", url);
log::info!("[AuthManager] Logging out");
@@ -337,43 +343,43 @@ mod tests {
use super::*;
/// Test URL normalization - adds https:// when missing
///
/// Ensures that URLs without protocol are normalized to https://
/// This prevents "builder error" when constructing HTTP requests.
#[test]
fn test_normalize_url_adds_https() {
assert_eq!(
AuthManager::normalize_url("jellyfin.example.com"),
AuthManager::normalize_url("jellyfin.example.com").unwrap(),
"https://jellyfin.example.com"
);
assert_eq!(
AuthManager::normalize_url("192.168.1.100:8096"),
AuthManager::normalize_url("192.168.1.100:8096").unwrap(),
"https://192.168.1.100:8096"
);
}
/// Test URL normalization - preserves existing protocol
/// Test URL normalization - preserves existing https
#[test]
fn test_normalize_url_preserves_protocol() {
fn test_normalize_url_preserves_https() {
assert_eq!(
AuthManager::normalize_url("https://jellyfin.example.com"),
AuthManager::normalize_url("https://jellyfin.example.com").unwrap(),
"https://jellyfin.example.com"
);
assert_eq!(
AuthManager::normalize_url("http://localhost:8096"),
"http://localhost:8096"
);
}
/// Test URL normalization - rejects HTTP
#[test]
fn test_normalize_url_rejects_http() {
assert!(AuthManager::normalize_url("http://localhost:8096").is_err());
assert!(AuthManager::normalize_url("http://jellyfin.example.com").is_err());
}
/// Test URL normalization - removes trailing slash
#[test]
fn test_normalize_url_removes_trailing_slash() {
assert_eq!(
AuthManager::normalize_url("https://jellyfin.example.com/"),
AuthManager::normalize_url("https://jellyfin.example.com/").unwrap(),
"https://jellyfin.example.com"
);
assert_eq!(
AuthManager::normalize_url("jellyfin.example.com/"),
AuthManager::normalize_url("jellyfin.example.com/").unwrap(),
"https://jellyfin.example.com"
);
}
@@ -382,25 +388,20 @@ mod tests {
#[test]
fn test_normalize_url_trims_whitespace() {
assert_eq!(
AuthManager::normalize_url(" jellyfin.example.com "),
AuthManager::normalize_url(" jellyfin.example.com ").unwrap(),
"https://jellyfin.example.com"
);
assert_eq!(
AuthManager::normalize_url(" https://jellyfin.example.com/ "),
AuthManager::normalize_url(" https://jellyfin.example.com/ ").unwrap(),
"https://jellyfin.example.com"
);
}
/// Test URL normalization - complex case
///
/// This is the bug that caused the login issue: user enters URL
/// without protocol, it gets stored in DB, then fails when building
/// HTTP requests.
/// Test URL normalization - real world case
#[test]
fn test_normalize_url_real_world_case() {
// User input: "jellyfin.tourolle.paris"
let input = "jellyfin.tourolle.paris";
let normalized = AuthManager::normalize_url(input);
let normalized = AuthManager::normalize_url(input).unwrap();
assert_eq!(normalized, "https://jellyfin.tourolle.paris");
assert!(normalized.starts_with("https://"));