This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum TransferProtocol {
|
||||
Sftp,
|
||||
Zmodem,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum TransferDirection {
|
||||
Upload,
|
||||
Download,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct TransferRequest {
|
||||
pub protocol: TransferProtocol,
|
||||
pub direction: TransferDirection,
|
||||
pub local_path: String,
|
||||
pub remote_path: String,
|
||||
}
|
||||
|
||||
impl TransferRequest {
|
||||
pub fn validate(&self) -> Result<(), String> {
|
||||
if self.local_path.trim().is_empty() {
|
||||
return Err("local path is required".to_string());
|
||||
}
|
||||
if self.remote_path.trim().is_empty() {
|
||||
return Err("remote path is required".to_string());
|
||||
}
|
||||
if self.local_path.contains("..") {
|
||||
return Err("local path traversal is not allowed".to_string());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum TransferEvent {
|
||||
Queued,
|
||||
Progress { bytes_done: u64, bytes_total: u64 },
|
||||
Completed,
|
||||
Failed(String),
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn validates_sftp_download_request() {
|
||||
let request = TransferRequest {
|
||||
protocol: TransferProtocol::Sftp,
|
||||
direction: TransferDirection::Download,
|
||||
local_path: "downloads/file.txt".to_string(),
|
||||
remote_path: "/home/tom/file.txt".to_string(),
|
||||
};
|
||||
|
||||
assert!(request.validate().is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn validates_zmodem_upload_request() {
|
||||
let request = TransferRequest {
|
||||
protocol: TransferProtocol::Zmodem,
|
||||
direction: TransferDirection::Upload,
|
||||
local_path: "uploads/firmware.bin".to_string(),
|
||||
remote_path: "firmware.bin".to_string(),
|
||||
};
|
||||
|
||||
assert!(request.validate().is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rejects_local_path_traversal() {
|
||||
let request = TransferRequest {
|
||||
protocol: TransferProtocol::Sftp,
|
||||
direction: TransferDirection::Download,
|
||||
local_path: "../secret".to_string(),
|
||||
remote_path: "/tmp/secret".to_string(),
|
||||
};
|
||||
|
||||
assert!(request.validate().unwrap_err().contains("traversal"));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user