fix(security): redact sensitive identifiers and secrets from backend logs
cx
This commit is contained in:
13 files changed
+36
-67
No files matched your search
@@ -124,7 +124,7 @@ impl ListenBrainzClient {
|
|||||||
config.user_name = Some(user_name.clone());
|
config.user_name = Some(user_name.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
log::info!("ListenBrainz connected as: {}", user_name);
|
log::info!("ListenBrainz connected");
|
||||||
|
|
||||||
Ok(UserInfo { user_name })
|
Ok(UserInfo { user_name })
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -184,7 +184,7 @@ fn extract_secrets(bundle: &str) -> Result<Vec<String>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log::info!("Extracted {} secrets", secrets.len());
|
log::info!("Extracted app secrets from bundle");
|
||||||
Ok(secrets)
|
Ok(secrets)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -259,7 +259,7 @@ impl QobuzClient {
|
|||||||
let json: serde_json::Value = login_response.json().await?;
|
let json: serde_json::Value = login_response.json().await?;
|
||||||
let session = super::auth::parse_login_response(&json)?;
|
let session = super::auth::parse_login_response(&json)?;
|
||||||
*self.session.write().await = Some(session.clone());
|
*self.session.write().await = Some(session.clone());
|
||||||
log::info!("[OAuth] Session established for user {}", session.user_id);
|
log::info!("[OAuth] Session established");
|
||||||
Ok(session)
|
Ok(session)
|
||||||
}
|
}
|
||||||
StatusCode::UNAUTHORIZED => Err(ApiError::AuthenticationError(
|
StatusCode::UNAUTHORIZED => Err(ApiError::AuthenticationError(
|
||||||
@@ -285,7 +285,8 @@ impl QobuzClient {
|
|||||||
|
|
||||||
/// Get current user ID
|
/// Get current user ID
|
||||||
pub async fn get_user_id(&self) -> Option<u64> {
|
pub async fn get_user_id(&self) -> Option<u64> {
|
||||||
self.session.read().await.as_ref().map(|s| s.user_id)
|
let session = self.session.read().await;
|
||||||
|
session.as_ref().map(|entry| entry.user_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get user auth token header value (public for catalog search)
|
/// Get user auth token header value (public for catalog search)
|
||||||
@@ -1260,11 +1261,8 @@ impl QobuzClient {
|
|||||||
match self.get_stream_url(track_id, *quality).await {
|
match self.get_stream_url(track_id, *quality).await {
|
||||||
Ok(url) if !url.has_restrictions() => {
|
Ok(url) if !url.has_restrictions() => {
|
||||||
log::info!(
|
log::info!(
|
||||||
"Got stream URL - requested format_id={}, got format_id={}, sample_rate={}Hz, bit_depth={:?}",
|
"Got stream URL for requested quality format_id={}",
|
||||||
quality.id(),
|
quality.id()
|
||||||
url.format_id,
|
|
||||||
url.sampling_rate,
|
|
||||||
url.bit_depth
|
|
||||||
);
|
);
|
||||||
return Ok(url);
|
return Ok(url);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -181,7 +181,7 @@ fn extract_secrets(bundle: &str) -> Result<Vec<String>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log::info!("Extracted {} secrets", secrets.len());
|
log::info!("Extracted app secrets from bundle");
|
||||||
Ok(secrets)
|
Ok(secrets)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -267,7 +267,7 @@ impl QobuzClient {
|
|||||||
let login_json: Value = login_resp.json().await?;
|
let login_json: Value = login_resp.json().await?;
|
||||||
let session = parse_login_response(&login_json)?;
|
let session = parse_login_response(&login_json)?;
|
||||||
*self.session.write().await = Some(session.clone());
|
*self.session.write().await = Some(session.clone());
|
||||||
log::info!("[OAuth] Session established for user {}", session.user_id);
|
log::info!("[OAuth] Session established");
|
||||||
Ok(session)
|
Ok(session)
|
||||||
}
|
}
|
||||||
StatusCode::UNAUTHORIZED => Err(ApiError::AuthenticationError(
|
StatusCode::UNAUTHORIZED => Err(ApiError::AuthenticationError(
|
||||||
@@ -324,7 +324,7 @@ impl QobuzClient {
|
|||||||
let json: Value = resp.json().await?;
|
let json: Value = resp.json().await?;
|
||||||
let session = parse_login_response(&json)?;
|
let session = parse_login_response(&json)?;
|
||||||
*self.session.write().await = Some(session.clone());
|
*self.session.write().await = Some(session.clone());
|
||||||
log::info!("[OAuth] Session restored for user {}", session.user_id);
|
log::info!("[OAuth] Session restored");
|
||||||
Ok(session)
|
Ok(session)
|
||||||
}
|
}
|
||||||
StatusCode::UNAUTHORIZED => Err(ApiError::AuthenticationError(
|
StatusCode::UNAUTHORIZED => Err(ApiError::AuthenticationError(
|
||||||
@@ -350,7 +350,8 @@ impl QobuzClient {
|
|||||||
|
|
||||||
/// Get current user ID
|
/// Get current user ID
|
||||||
pub async fn get_user_id(&self) -> Option<u64> {
|
pub async fn get_user_id(&self) -> Option<u64> {
|
||||||
self.session.read().await.as_ref().map(|s| s.user_id)
|
let session = self.session.read().await;
|
||||||
|
session.as_ref().map(|entry| entry.user_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get user auth token header value (public for catalog search)
|
/// Get user auth token header value (public for catalog search)
|
||||||
@@ -1902,11 +1903,8 @@ impl QobuzClient {
|
|||||||
match self.get_stream_url(track_id, *quality).await {
|
match self.get_stream_url(track_id, *quality).await {
|
||||||
Ok(url) if !url.has_restrictions() => {
|
Ok(url) if !url.has_restrictions() => {
|
||||||
log::info!(
|
log::info!(
|
||||||
"Got stream URL - requested format_id={}, got format_id={}, sample_rate={}Hz, bit_depth={:?}",
|
"Got stream URL for requested quality format_id={}",
|
||||||
quality.id(),
|
quality.id()
|
||||||
url.format_id,
|
|
||||||
url.sampling_rate,
|
|
||||||
url.bit_depth
|
|
||||||
);
|
);
|
||||||
return Ok(url);
|
return Ok(url);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -537,23 +537,17 @@ pub async fn runtime_bootstrap(
|
|||||||
let last_user_id_hint = crate::user_data::UserDataPaths::load_last_user_id();
|
let last_user_id_hint = crate::user_data::UserDataPaths::load_last_user_id();
|
||||||
|
|
||||||
if let Ok(Some(creds)) = creds {
|
if let Ok(Some(creds)) = creds {
|
||||||
if let Some(uid) = last_user_id_hint {
|
if last_user_id_hint.is_some() {
|
||||||
log::info!(
|
log::info!("[Runtime] Found saved credentials, attempting auto-login");
|
||||||
"[Runtime] Found saved credentials, attempting auto-login (user hint: {})",
|
|
||||||
uid
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
log::info!("[Runtime] Found saved credentials, attempting auto-login (no user hint)");
|
log::info!("[Runtime] Found saved credentials, attempting auto-login (no hint)");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Login to legacy client
|
// Login to legacy client
|
||||||
let client = app_state.client.read().await;
|
let client = app_state.client.read().await;
|
||||||
match client.login(&creds.email, &creds.password).await {
|
match client.login(&creds.email, &creds.password).await {
|
||||||
Ok(session) => {
|
Ok(session) => {
|
||||||
log::info!(
|
log::info!("[Runtime] Legacy auth successful");
|
||||||
"[Runtime] Legacy auth successful for user {}",
|
|
||||||
session.user_id
|
|
||||||
);
|
|
||||||
manager.set_legacy_auth(true, Some(session.user_id)).await;
|
manager.set_legacy_auth(true, Some(session.user_id)).await;
|
||||||
let _ = app.emit(
|
let _ = app.emit(
|
||||||
"runtime:event",
|
"runtime:event",
|
||||||
@@ -665,10 +659,7 @@ pub async fn runtime_bootstrap(
|
|||||||
let client = app_state.client.read().await;
|
let client = app_state.client.read().await;
|
||||||
match client.login_with_token(&oauth_token).await {
|
match client.login_with_token(&oauth_token).await {
|
||||||
Ok(session) => {
|
Ok(session) => {
|
||||||
log::info!(
|
log::info!("[Runtime] OAuth token re-auth successful");
|
||||||
"[Runtime] OAuth token re-auth successful for user {}",
|
|
||||||
session.user_id
|
|
||||||
);
|
|
||||||
manager.set_legacy_auth(true, Some(session.user_id)).await;
|
manager.set_legacy_auth(true, Some(session.user_id)).await;
|
||||||
let _ = app.emit(
|
let _ = app.emit(
|
||||||
"runtime:event",
|
"runtime:event",
|
||||||
@@ -928,7 +919,7 @@ pub async fn v2_auto_login(
|
|||||||
};
|
};
|
||||||
drop(client);
|
drop(client);
|
||||||
|
|
||||||
log::info!("[V2] Legacy auth successful for user {}", session.user_id);
|
log::info!("[V2] Legacy auth successful");
|
||||||
manager.set_legacy_auth(true, Some(session.user_id)).await;
|
manager.set_legacy_auth(true, Some(session.user_id)).await;
|
||||||
let _ = app.emit(
|
let _ = app.emit(
|
||||||
"runtime:event",
|
"runtime:event",
|
||||||
@@ -1067,7 +1058,7 @@ pub async fn v2_manual_login(
|
|||||||
};
|
};
|
||||||
drop(client);
|
drop(client);
|
||||||
|
|
||||||
log::info!("[V2] Legacy auth successful for user {}", session.user_id);
|
log::info!("[V2] Legacy auth successful");
|
||||||
manager.set_legacy_auth(true, Some(session.user_id)).await;
|
manager.set_legacy_auth(true, Some(session.user_id)).await;
|
||||||
let _ = app.emit(
|
let _ = app.emit(
|
||||||
"runtime:event",
|
"runtime:event",
|
||||||
@@ -1368,7 +1359,7 @@ pub async fn v2_start_oauth_login(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
log::info!("[V2] OAuth session established for user {}", session.user_id);
|
log::info!("[V2] OAuth session established");
|
||||||
manager.set_legacy_auth(true, Some(session.user_id)).await;
|
manager.set_legacy_auth(true, Some(session.user_id)).await;
|
||||||
let _ = app.emit(
|
let _ = app.emit(
|
||||||
"runtime:event",
|
"runtime:event",
|
||||||
@@ -1688,10 +1679,7 @@ pub async fn v2_login(
|
|||||||
.map_err(|e| RuntimeError::Internal(e.to_string()))?
|
.map_err(|e| RuntimeError::Internal(e.to_string()))?
|
||||||
};
|
};
|
||||||
manager.set_legacy_auth(true, Some(session.user_id)).await;
|
manager.set_legacy_auth(true, Some(session.user_id)).await;
|
||||||
log::info!(
|
log::info!("[v2_login] Legacy auth successful");
|
||||||
"[v2_login] Legacy auth successful for user {}",
|
|
||||||
session.user_id
|
|
||||||
);
|
|
||||||
|
|
||||||
// Step 2: CoreBridge auth
|
// Step 2: CoreBridge auth
|
||||||
let bridge_guard = bridge.get().await;
|
let bridge_guard = bridge.get().await;
|
||||||
@@ -1709,7 +1697,7 @@ pub async fn v2_login(
|
|||||||
rollback_auth_state(&manager, &app).await;
|
rollback_auth_state(&manager, &app).await;
|
||||||
return Err(RuntimeError::Internal(e));
|
return Err(RuntimeError::Internal(e));
|
||||||
}
|
}
|
||||||
log::info!("[v2_login] Session activated for user {}", session.user_id);
|
log::info!("[v2_login] Session activated");
|
||||||
|
|
||||||
// Persist ToS acceptance now that login succeeded.
|
// Persist ToS acceptance now that login succeeded.
|
||||||
accept_tos_best_effort(&legal_state);
|
accept_tos_best_effort(&legal_state);
|
||||||
|
|||||||
@@ -137,15 +137,6 @@ impl LastFmV2State {
|
|||||||
*self.pending_token.lock().await = None;
|
*self.pending_token.lock().await = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get session key for persistence
|
|
||||||
pub async fn get_session_key(&self) -> Option<String> {
|
|
||||||
self.client
|
|
||||||
.lock()
|
|
||||||
.await
|
|
||||||
.session_key()
|
|
||||||
.map(|s| s.to_string())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Store pending token during auth flow
|
/// Store pending token during auth flow
|
||||||
pub async fn set_pending_token(&self, token: String) {
|
pub async fn set_pending_token(&self, token: String) {
|
||||||
*self.pending_token.lock().await = Some(token);
|
*self.pending_token.lock().await = Some(token);
|
||||||
|
|||||||
@@ -448,7 +448,7 @@ pub fn run() {
|
|||||||
.ok()
|
.ok()
|
||||||
});
|
});
|
||||||
if let Some(settings) = user_settings {
|
if let Some(settings) = user_settings {
|
||||||
log::info!("Loaded tray settings from last active user {}", last_uid);
|
log::info!("Loaded tray settings from last active user profile");
|
||||||
settings
|
settings
|
||||||
} else {
|
} else {
|
||||||
config::tray_settings::TraySettingsStore::new()
|
config::tray_settings::TraySettingsStore::new()
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ impl ListenBrainzClient {
|
|||||||
config.user_name = Some(user_name.clone());
|
config.user_name = Some(user_name.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
log::info!("ListenBrainz connected as: {}", user_name);
|
log::info!("ListenBrainz connected");
|
||||||
|
|
||||||
Ok(UserInfo { user_name })
|
Ok(UserInfo { user_name })
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ impl ListenBrainzSharedState {
|
|||||||
let client = ListenBrainzClient::with_config(config);
|
let client = ListenBrainzClient::with_config(config);
|
||||||
|
|
||||||
if token.is_some() && user_name.is_some() {
|
if token.is_some() && user_name.is_some() {
|
||||||
log::info!("ListenBrainz: restored session for user {:?}", user_name);
|
log::info!("ListenBrainz: restored session from persisted credentials");
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
@@ -115,7 +115,7 @@ impl ListenBrainzSharedState {
|
|||||||
let client = self.client.lock().await;
|
let client = self.client.lock().await;
|
||||||
client.set_enabled(enabled).await;
|
client.set_enabled(enabled).await;
|
||||||
if let (Some(tok), Some(uname)) = (token, user_name) {
|
if let (Some(tok), Some(uname)) = (token, user_name) {
|
||||||
log::info!("ListenBrainz: restoring session for user {:?}", uname);
|
log::info!("ListenBrainz: restoring persisted session");
|
||||||
client.restore_token(tok, uname).await;
|
client.restore_token(tok, uname).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ pub fn migrate_flat_to_user(user_id: u64) -> Result<(), String> {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
log::info!("Starting flat-to-user migration for user {}", user_id);
|
log::info!("Starting flat-to-user migration");
|
||||||
|
|
||||||
let user_data_dir = global_data_dir.join("users").join(user_id.to_string());
|
let user_data_dir = global_data_dir.join("users").join(user_id.to_string());
|
||||||
let user_cache_dir = global_cache_dir.join("users").join(user_id.to_string());
|
let user_cache_dir = global_cache_dir.join("users").join(user_id.to_string());
|
||||||
@@ -109,7 +109,7 @@ pub fn migrate_flat_to_user(user_id: u64) -> Result<(), String> {
|
|||||||
std::fs::write(&marker_path, format!("migrated_to_user={}\n", user_id))
|
std::fs::write(&marker_path, format!("migrated_to_user={}\n", user_id))
|
||||||
.map_err(|e| format!("Failed to write migration marker: {}", e))?;
|
.map_err(|e| format!("Failed to write migration marker: {}", e))?;
|
||||||
|
|
||||||
log::info!("Migration completed for user {}", user_id);
|
log::info!("Migration completed");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,12 +144,12 @@ fn move_directory(src: &Path, dst: &Path) {
|
|||||||
|
|
||||||
// Don't overwrite if destination already exists
|
// Don't overwrite if destination already exists
|
||||||
if dst.exists() {
|
if dst.exists() {
|
||||||
log::debug!("Destination {} already exists, skipping", dst.display());
|
log::debug!("Migration destination already exists, skipping directory move");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
match std::fs::rename(src, dst) {
|
match std::fs::rename(src, dst) {
|
||||||
Ok(()) => log::debug!("Moved dir {} -> {}", src.display(), dst.display()),
|
Ok(()) => log::debug!("Moved migration directory"),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::warn!(
|
log::warn!(
|
||||||
"Rename dir failed for {}, trying recursive copy: {}",
|
"Rename dir failed for {}, trying recursive copy: {}",
|
||||||
|
|||||||
@@ -24,10 +24,7 @@ use crate::user_data::UserDataPaths;
|
|||||||
/// Note: This is the core logic extracted from `activate_user_session` command.
|
/// Note: This is the core logic extracted from `activate_user_session` command.
|
||||||
/// It can be called from runtime_bootstrap, v2_login, or the command itself.
|
/// It can be called from runtime_bootstrap, v2_login, or the command itself.
|
||||||
pub async fn activate_session(app: &tauri::AppHandle, user_id: u64) -> Result<(), String> {
|
pub async fn activate_session(app: &tauri::AppHandle, user_id: u64) -> Result<(), String> {
|
||||||
log::info!(
|
log::info!("[SessionLifecycle] Activating session");
|
||||||
"[SessionLifecycle] Activating session for user_id={}",
|
|
||||||
user_id
|
|
||||||
);
|
|
||||||
|
|
||||||
// Get all required states from AppHandle
|
// Get all required states from AppHandle
|
||||||
let user_paths = app.state::<UserDataPaths>();
|
let user_paths = app.state::<UserDataPaths>();
|
||||||
@@ -217,10 +214,7 @@ pub async fn activate_session(app: &tauri::AppHandle, user_id: u64) -> Result<()
|
|||||||
RuntimeEvent::UserSessionActivated { user_id },
|
RuntimeEvent::UserSessionActivated { user_id },
|
||||||
);
|
);
|
||||||
|
|
||||||
log::info!(
|
log::info!("[SessionLifecycle] Session activated");
|
||||||
"[SessionLifecycle] Session activated for user_id={}",
|
|
||||||
user_id
|
|
||||||
);
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ impl UserDataPaths {
|
|||||||
.user_id
|
.user_id
|
||||||
.write()
|
.write()
|
||||||
.expect("UserDataPaths write lock poisoned") = Some(user_id);
|
.expect("UserDataPaths write lock poisoned") = Some(user_id);
|
||||||
log::info!("UserDataPaths: active user set to {}", user_id);
|
log::info!("UserDataPaths: active user set");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Clear the current user on logout
|
/// Clear the current user on logout
|
||||||
@@ -106,7 +106,7 @@ impl UserDataPaths {
|
|||||||
}
|
}
|
||||||
std::fs::write(&path, user_id.to_string())
|
std::fs::write(&path, user_id.to_string())
|
||||||
.map_err(|e| format!("Failed to save last user id: {}", e))?;
|
.map_err(|e| format!("Failed to save last user id: {}", e))?;
|
||||||
log::info!("Saved last_user_id={} to {:?}", user_id, path);
|
log::info!("Saved last_user_id marker");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user