Fix code quality: trailing whitespace, unused imports, clippy warnings

- Fix trailing whitespace in kex.rs and s3.rs
- Add missing KexProposal import in kex_complete.rs
- Auto-fix clippy warnings across all crates
- All 153 tests pass
This commit is contained in:
Warren
2026-06-19 05:21:38 +08:00
parent 4b37e524cf
commit d94cb2df4c
135 changed files with 7256 additions and 4321 deletions

View File

@@ -28,15 +28,15 @@ impl UserPermission {
admin_access: admin,
}
}
pub fn readonly(username: String) -> Self {
UserPermission::new(username, true, false, false)
}
pub fn full_access(username: String) -> Self {
UserPermission::new(username, true, true, false)
}
pub fn admin(username: String) -> Self {
UserPermission::new(username, true, true, true)
}
@@ -57,28 +57,32 @@ impl AccessControlList {
max_connections: 10,
}
}
pub fn add_user(&mut self, permission: UserPermission) {
if let Some(existing) = self.users.iter_mut().find(|u| u.username == permission.username) {
if let Some(existing) = self
.users
.iter_mut()
.find(|u| u.username == permission.username)
{
*existing = permission;
} else {
self.users.push(permission);
}
}
pub fn remove_user(&mut self, username: &str) {
self.users.retain(|u| u.username != username);
}
pub fn get_user(&self, username: &str) -> Option<&UserPermission> {
self.users.iter().find(|u| u.username == username)
}
pub fn has_access(&self, username: &str, require_write: bool) -> bool {
if self.guest_access && !require_write {
return true;
}
self.get_user(username)
.map(|u| {
if require_write {
@@ -89,4 +93,4 @@ impl AccessControlList {
})
.unwrap_or(false)
}
}
}

View File

@@ -1,5 +1,5 @@
use anyhow::Result;
use crate::acl::AccessControlList;
use anyhow::Result;
pub struct AuthManager {
acl: AccessControlList,
@@ -9,26 +9,26 @@ impl AuthManager {
pub fn new(acl: AccessControlList) -> Self {
AuthManager { acl }
}
pub fn authenticate(&self, username: &str, password: Option<&str>) -> Result<bool> {
if self.acl.guest_access && password.is_none() {
return Ok(true);
}
if password.is_none() {
return Err(anyhow::anyhow!("Password required for user {}", username));
}
if self.acl.get_user(username).is_none() {
return Err(anyhow::anyhow!("User {} not in ACL", username));
}
Ok(true)
}
pub fn check_permission(&self, username: &str, action: &str) -> Result<bool> {
let require_write = action == "write" || action == "delete" || action == "create";
if !self.acl.has_access(username, require_write) {
return Err(anyhow::anyhow!(
"User {} does not have {} permission",
@@ -36,15 +36,15 @@ impl AuthManager {
action
));
}
Ok(true)
}
pub fn get_acl(&self) -> &AccessControlList {
&self.acl
}
pub fn update_acl(&mut self, acl: AccessControlList) {
self.acl = acl;
}
}
}

View File

@@ -34,7 +34,7 @@ impl SMBConfig {
allow_users: vec!["accusys".to_string()],
}
}
pub fn to_smb_conf(&self) -> String {
format!(
"[{}]\n path = {}\n comment = {}\n read only = {}\n browseable = {}\n valid users = {}\n",
@@ -46,4 +46,4 @@ impl SMBConfig {
self.allow_users.join(", ")
)
}
}
}

View File

@@ -1,11 +1,11 @@
pub mod config;
pub mod manager;
pub mod acl;
pub mod auth;
pub mod config;
pub mod manager;
pub mod monitor;
pub use config::SMBConfig;
pub use manager::SMBManager;
pub use acl::{AccessControlList, UserPermission};
pub use auth::AuthManager;
pub use monitor::{SMBMonitor, ConnectionStats, AccessLogEntry};
pub use config::SMBConfig;
pub use manager::SMBManager;
pub use monitor::{AccessLogEntry, ConnectionStats, SMBMonitor};

View File

@@ -1,5 +1,7 @@
use clap::Parser;
use markbase_smb::{SMBConfig, SMBManager, AccessControlList, UserPermission, AuthManager, SMBMonitor};
use markbase_smb::{
AccessControlList, AuthManager, SMBConfig, SMBManager, SMBMonitor, UserPermission,
};
#[derive(Parser)]
#[command(name = "markbase-smb")]
@@ -16,34 +18,34 @@ enum Commands {
/// Share name
#[arg(short, long, default_value = "markbase")]
name: String,
/// Path to share
#[arg(short, long, default_value = "/Users/accusys/momentry/var/sftpgo/data")]
path: String,
},
/// Remove SMB share
Remove {
/// Share name
#[arg(short, long)]
name: String,
},
/// List existing SMB shares
List,
/// Show SMB status
Status,
/// Manage user permissions
User {
#[command(subcommand)]
action: UserCommands,
},
/// Show monitoring stats
Stats,
/// Show access logs
Logs {
/// Number of log entries to show
@@ -58,24 +60,24 @@ enum UserCommands {
Add {
#[arg(short, long)]
username: String,
#[arg(short, long, default_value = "readonly")]
permission: String,
},
/// Remove user permission
Remove {
#[arg(short, long)]
username: String,
},
/// List all user permissions
List,
}
fn main() -> anyhow::Result<()> {
let cli = Cli::parse();
match cli.command {
Commands::Create { name, path } => {
let config = SMBConfig::new(name, path);
@@ -104,32 +106,33 @@ fn main() -> anyhow::Result<()> {
let status = manager.status()?;
println!("{}", serde_json::to_string_pretty(&status)?);
}
Commands::User { action } => {
match action {
UserCommands::Add { username, permission } => {
let acl = AccessControlList::new();
let perm = match permission.as_str() {
"readonly" => UserPermission::readonly(username),
"full" => UserPermission::full_access(username),
"admin" => UserPermission::admin(username),
_ => UserPermission::readonly(username),
};
println!("User permission configuration:");
println!("{}", serde_json::to_string_pretty(&perm)?);
println!("\nTo apply, update system SMB configuration with this user.");
}
UserCommands::Remove { username } => {
println!("Removing user '{}' from ACL", username);
println!("To apply, update system SMB configuration.");
}
UserCommands::List => {
let acl = AccessControlList::new();
println!("Default ACL configuration:");
println!("{}", serde_json::to_string_pretty(&acl)?);
}
Commands::User { action } => match action {
UserCommands::Add {
username,
permission,
} => {
let acl = AccessControlList::new();
let perm = match permission.as_str() {
"readonly" => UserPermission::readonly(username),
"full" => UserPermission::full_access(username),
"admin" => UserPermission::admin(username),
_ => UserPermission::readonly(username),
};
println!("User permission configuration:");
println!("{}", serde_json::to_string_pretty(&perm)?);
println!("\nTo apply, update system SMB configuration with this user.");
}
}
UserCommands::Remove { username } => {
println!("Removing user '{}' from ACL", username);
println!("To apply, update system SMB configuration.");
}
UserCommands::List => {
let acl = AccessControlList::new();
println!("Default ACL configuration:");
println!("{}", serde_json::to_string_pretty(&acl)?);
}
},
Commands::Stats => {
let monitor = SMBMonitor::new();
let stats = monitor.get_stats();
@@ -149,6 +152,6 @@ fn main() -> anyhow::Result<()> {
}
}
}
Ok(())
}
}

View File

@@ -12,72 +12,68 @@ impl SMBManager {
pub fn new(config: SMBConfig) -> Self {
SMBManager { config }
}
pub fn check_smb_service() -> Result<bool> {
let output = Command::new("sharing")
.arg("-l")
.output()?;
let output = Command::new("sharing").arg("-l").output()?;
let status = String::from_utf8_lossy(&output.stdout);
Ok(!status.contains("No share point records"))
}
pub fn create_share(&self) -> Result<()> {
let path = Path::new(&self.config.path);
if !path.exists() {
return Err(anyhow::anyhow!("Path does not exist: {}", self.config.path));
}
eprintln!("Creating SMB share '{}' for path: {}", self.config.share_name, self.config.path);
eprintln!(
"Creating SMB share '{}' for path: {}",
self.config.share_name, self.config.path
);
let smb_conf_content = self.config.to_smb_conf();
eprintln!("Generated smb.conf section:\n{}", smb_conf_content);
eprintln!("\nTo enable SMB sharing, run:");
eprintln!("sudo sharing -a \"{}\" -S \"{}\"", self.config.path, self.config.share_name);
eprintln!(
"sudo sharing -a \"{}\" -S \"{}\"",
self.config.path, self.config.share_name
);
Ok(())
}
pub fn remove_share(&self) -> Result<()> {
eprintln!("Removing SMB share '{}'...", self.config.share_name);
eprintln!("To remove SMB sharing, run:");
eprintln!("sudo sharing -r \"{}\"", self.config.share_name);
Ok(())
}
pub fn list_shares() -> Result<Vec<String>> {
let output = Command::new("sharing")
.arg("-l")
.output()?;
let output = Command::new("sharing").arg("-l").output()?;
let status = String::from_utf8_lossy(&output.stdout);
if status.contains("No share point records") {
return Ok(vec![]);
}
let shares: Vec<String> = status
.lines()
.filter(|line| line.contains("name:"))
.map(|line| {
line.split(":")
.nth(1)
.unwrap_or("")
.trim()
.to_string()
})
.map(|line| line.split(":").nth(1).unwrap_or("").trim().to_string())
.collect();
Ok(shares)
}
pub fn status(&self) -> Result<serde_json::Value> {
let service_running = Self::check_smb_service()?;
let shares = Self::list_shares()?;
Ok(serde_json::json!({
"service_running": service_running,
"share_name": self.config.share_name,
@@ -86,4 +82,4 @@ impl SMBManager {
"config": self.config,
}))
}
}
}

View File

@@ -2,6 +2,7 @@ use serde::{Deserialize, Serialize};
use std::time::{Duration, SystemTime};
#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Default)]
pub struct ConnectionStats {
pub total_connections: u64,
pub active_connections: u32,
@@ -12,19 +13,6 @@ pub struct ConnectionStats {
pub uptime_seconds: u64,
}
impl Default for ConnectionStats {
fn default() -> Self {
ConnectionStats {
total_connections: 0,
active_connections: 0,
read_operations: 0,
write_operations: 0,
errors: 0,
bytes_transferred: 0,
uptime_seconds: 0,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AccessLogEntry {
@@ -38,12 +26,19 @@ pub struct AccessLogEntry {
}
impl AccessLogEntry {
pub fn new(username: String, action: String, path: String, success: bool, bytes: u64, duration: Duration) -> Self {
pub fn new(
username: String,
action: String,
path: String,
success: bool,
bytes: u64,
duration: Duration,
) -> Self {
let timestamp = SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.unwrap()
.as_secs();
AccessLogEntry {
timestamp: timestamp.to_string(),
username,
@@ -62,6 +57,12 @@ pub struct SMBMonitor {
start_time: SystemTime,
}
impl Default for SMBMonitor {
fn default() -> Self {
Self::new()
}
}
impl SMBMonitor {
pub fn new() -> Self {
SMBMonitor {
@@ -70,10 +71,10 @@ impl SMBMonitor {
start_time: SystemTime::now(),
}
}
pub fn log_access(&mut self, entry: AccessLogEntry) {
self.logs.push(entry.clone());
if entry.success {
if entry.action == "read" {
self.stats.read_operations += 1;
@@ -85,28 +86,28 @@ impl SMBMonitor {
self.stats.errors += 1;
}
}
pub fn connection_opened(&mut self) {
self.stats.total_connections += 1;
self.stats.active_connections += 1;
}
pub fn connection_closed(&mut self) {
self.stats.active_connections -= 1;
}
pub fn get_stats(&self) -> ConnectionStats {
let uptime = SystemTime::now()
.duration_since(self.start_time)
.unwrap()
.as_secs();
let mut stats = self.stats.clone();
stats.uptime_seconds = uptime;
stats
}
pub fn get_logs(&self, limit: usize) -> Vec<AccessLogEntry> {
self.logs.iter().rev().take(limit).cloned().collect()
}
}
}