mirror of https://github.com/ospab/ostp.git
fix(server): return API token support for Relay servers sync
This commit is contained in:
parent
7b81f617ad
commit
03e113fccf
|
|
@ -42,6 +42,7 @@ pub struct ApiState {
|
|||
pub user_stats: Arc<RwLock<HashMap<String, Arc<UserStats>>>>,
|
||||
pub start_time: Instant,
|
||||
pub session_token: Arc<RwLock<Option<String>>>,
|
||||
pub api_token: Option<String>,
|
||||
pub webpath: String,
|
||||
pub username: String,
|
||||
pub password_hash: String,
|
||||
|
|
@ -59,6 +60,7 @@ pub struct ApiState {
|
|||
pub struct ApiConfig {
|
||||
pub enabled: bool,
|
||||
pub bind: String,
|
||||
pub token: Option<String>,
|
||||
#[serde(default)]
|
||||
pub webpath: String,
|
||||
#[serde(default)]
|
||||
|
|
@ -72,6 +74,7 @@ impl Default for ApiConfig {
|
|||
Self {
|
||||
enabled: false,
|
||||
bind: "127.0.0.1:9090".to_string(),
|
||||
token: None,
|
||||
webpath: String::new(),
|
||||
username: String::new(),
|
||||
password_hash: String::new(),
|
||||
|
|
@ -257,6 +260,7 @@ pub async fn start_api_server(
|
|||
user_stats,
|
||||
start_time: Instant::now(),
|
||||
session_token: Arc::new(RwLock::new(None)),
|
||||
api_token: config.token.clone(),
|
||||
webpath: config.webpath.clone(),
|
||||
username: config.username.clone(),
|
||||
password_hash: config.password_hash.clone(),
|
||||
|
|
@ -287,26 +291,40 @@ pub async fn start_api_server(
|
|||
// ── Middleware: token check ──────────────────────────────────────────────────
|
||||
|
||||
fn check_token(state: &ApiState, headers: &axum::http::HeaderMap) -> bool {
|
||||
// Both session token (for web UI) and static API token (for relays) are checked
|
||||
let mut allowed = false;
|
||||
|
||||
// If no credentials configured, panel is open (unsafe but possible)
|
||||
if state.username.is_empty() && state.password_hash.is_empty() {
|
||||
if state.username.is_empty() && state.password_hash.is_empty() && state.api_token.is_none() {
|
||||
return true;
|
||||
}
|
||||
|
||||
match headers.get("authorization") {
|
||||
Some(value) => {
|
||||
let val = value.to_str().unwrap_or("");
|
||||
if let Some(value) = headers.get("authorization") {
|
||||
if let Ok(val) = value.to_str() {
|
||||
if let Some(token) = val.strip_prefix("Bearer ") {
|
||||
let current_session = state.session_token.read().unwrap().clone();
|
||||
if let Some(session) = current_session {
|
||||
if token == session {
|
||||
return true;
|
||||
allowed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(ref api_tok) = state.api_token {
|
||||
if token == api_tok {
|
||||
allowed = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if let Some(ref api_tok) = state.api_token {
|
||||
if val == api_tok {
|
||||
allowed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
None => false,
|
||||
}
|
||||
|
||||
allowed
|
||||
}
|
||||
|
||||
async fn handle_login(
|
||||
|
|
@ -904,6 +922,7 @@ mod tests {
|
|||
user_stats: Arc::new(RwLock::new(HashMap::new())),
|
||||
start_time: std::time::Instant::now(),
|
||||
session_token: Arc::new(RwLock::new(None)),
|
||||
api_token: Some("test-token".to_string()),
|
||||
webpath: webpath.to_string(),
|
||||
username: "admin".to_string(),
|
||||
password_hash: "hash".to_string(),
|
||||
|
|
|
|||
|
|
@ -294,6 +294,7 @@ impl ListenConfig {
|
|||
struct ApiConfig {
|
||||
enabled: Option<bool>,
|
||||
bind: Option<String>,
|
||||
token: Option<String>,
|
||||
webpath: Option<String>,
|
||||
username: Option<String>,
|
||||
password_hash: Option<String>,
|
||||
|
|
@ -631,10 +632,12 @@ async fn run_app() -> Result<()> {
|
|||
]
|
||||
}},
|
||||
|
||||
// Web control panel
|
||||
// Web control panel & Management API
|
||||
"api": {{
|
||||
"enabled": false,
|
||||
"bind": "0.0.0.0:9090",
|
||||
// Static API token for Relay servers (optional)
|
||||
"token": "",
|
||||
// Secret URL path to hide panel from scanners (e.g. "mySecret123")
|
||||
"webpath": "",
|
||||
// Login credentials for web panel (password stored as SHA256 hash)
|
||||
|
|
@ -904,6 +907,7 @@ async fn run_app() -> Result<()> {
|
|||
let api_config = server_cfg.api.map(|a| ostp_server::ApiConfig {
|
||||
enabled: a.enabled.unwrap_or(false),
|
||||
bind: a.bind.unwrap_or_else(|| "127.0.0.1:9090".to_string()),
|
||||
token: a.token.clone(),
|
||||
webpath: a.webpath.unwrap_or_default(),
|
||||
username: a.username.unwrap_or_default(),
|
||||
password_hash: a.password_hash.unwrap_or_default(),
|
||||
|
|
|
|||
Loading…
Reference in New Issue