769a5a68e2
Phase 5: Replace all Box<dyn Error> return types with anyhow::Result<T>
throughout the codebase. Replace string-based Err("msg".into()) and
format!().into() patterns with bail!() and anyhow!() macros. Fix
dirs::home_dir().unwrap() in settings.rs to use a fallback path instead
of panicking when HOME is unset. Remove stray use std::error::Error
imports no longer needed.
Phase 6: Add From<&User> for CacheUser in models/user.rs and
From<&Laboratory>/From<&Laboratories> for CacheLaboratory/CacheLabsWrapper
in models/laboratory.rs. Simplify commands/login.rs to use .into()
conversions, removing the redundant to_cache_user() and to_cache_labs()
helper functions.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
59 lines
1.7 KiB
Rust
59 lines
1.7 KiB
Rust
use crate::connection::MDRSConnection;
|
|
use crate::models::user::User as ModelUser;
|
|
use serde::Deserialize;
|
|
use anyhow::{bail};
|
|
|
|
/// Full API response shape from GET v3/users/current/
|
|
#[derive(Debug, Deserialize)]
|
|
struct UsersApiCurrentResponse {
|
|
id: u32,
|
|
username: String,
|
|
laboratories: Vec<UsersCurrentResponseLaboratory>,
|
|
is_reviewer: bool,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
struct UsersCurrentResponseLaboratory {
|
|
id: u32,
|
|
}
|
|
|
|
#[derive(Deserialize)]
|
|
struct TokenRefreshResponse {
|
|
access: String,
|
|
}
|
|
|
|
impl MDRSConnection {
|
|
/// Fetch current user and return the slim 4-field model matching the Python cache format.
|
|
pub async fn get_current_user(&self) -> Result<ModelUser, reqwest::Error> {
|
|
let resp = self.get("v3/users/current/").await?;
|
|
let obj = resp.json::<UsersApiCurrentResponse>().await?;
|
|
let laboratory_ids = obj.laboratories.into_iter().map(|l| l.id).collect();
|
|
Ok(ModelUser {
|
|
id: obj.id,
|
|
username: obj.username,
|
|
laboratory_ids,
|
|
is_reviewer: obj.is_reviewer,
|
|
})
|
|
}
|
|
|
|
/// Refresh the access token using the refresh token.
|
|
/// POST v3/users/token/refresh/ {refresh: ...} -> {access: new_access}
|
|
pub async fn token_refresh(
|
|
&self,
|
|
refresh_token: &str,
|
|
) -> Result<String, anyhow::Error> {
|
|
let body = serde_json::json!({ "refresh": refresh_token });
|
|
let resp = self
|
|
.client
|
|
.post(self.build_url("v3/users/token/refresh/"))
|
|
.json(&body)
|
|
.send()
|
|
.await?;
|
|
if !resp.status().is_success() {
|
|
bail!("Token refresh failed: {}", resp.status());
|
|
}
|
|
let r: TokenRefreshResponse = resp.json().await?;
|
|
Ok(r.access)
|
|
}
|
|
}
|