Skip to content

Commit

Permalink
Refactor authentication components, update dependencies, and improve …
Browse files Browse the repository at this point in the history
…error handling
  • Loading branch information
Dessera committed Apr 7, 2024
1 parent fd22109 commit c702e34
Show file tree
Hide file tree
Showing 13 changed files with 142 additions and 169 deletions.
8 changes: 4 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "jlud"
version = "0.1.0"
version = "0.1.5"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
Expand All @@ -11,7 +11,7 @@ name = "app_lib"
[dependencies]
aes-gcm = { version = "0.10.3", features = ["std"] }
clap = { version = "4.5.4", features = ["derive"] }
dirs = "5.0.1"
directories = "5.0.1"
dotenv = "0.15.0"
dotenv_codegen = "0.15.0"
hostname = "0.4.0"
Expand Down
22 changes: 9 additions & 13 deletions src/cli/auth/challenge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,62 +11,58 @@ use crate::{
};

#[derive(Debug)]
pub struct Challenger;
pub struct ChallengeSender;

impl Challenger {
impl ChallengeSender {
pub fn new() -> Self {
Self {}
}

fn get_challenge_data(try_times: i32) -> Vec<u8> {
fn get_challenge_data(try_times: u8) -> Vec<u8> {
let mut data = vec![0; 20];
data[0] = 0x01;
data[1] = 0x02 + (try_times as u8);
data[1] = 0x02 + try_times;
data[2] = random();
data[3] = random();
data[4] = 0x6a;
data
}
}

impl Component for Challenger {
#[tracing::instrument(skip_all)]
impl Component for ChallengeSender {
#[tracing::instrument(skip_all, name = "challenge_sender")]
async fn run(&mut self, context: Arc<Mutex<Context>>) -> JludResult<()> {
let mut ctx = context.lock().await;
let mut try_times = 0;

let mut recv_buf = [0; 32];

info!("Starting challenge");

while try_times < 5 {
let data = Challenger::get_challenge_data(try_times);
for try_times in 0..5 {
let data = ChallengeSender::get_challenge_data(try_times);
match ctx.interface.send(&data).await {
Ok(_) => {}
Err(e) => {
warn!("Failed to send challenge data: {}", e);
try_times += 1;
continue;
}
};
match ctx.interface.recv_with_timeout(&mut recv_buf).await {
Ok(_) => {}
Err(e) => {
warn!("Failed to receive challenge data: {}", e);
try_times += 1;
continue;
}
}

if recv_buf[0] == 0x02 {
ctx.common.salt.copy_from_slice(&recv_buf[4..8]);
ctx.common.client_ip.copy_from_slice(&recv_buf[20..24]);
info!("Challenge completed");
info!("Challenge succeeded");
return Ok(());
}

warn!("Challenge failed, retrying");
try_times += 1;
}

error!("Failed to complete challenge");
Expand Down
4 changes: 2 additions & 2 deletions src/cli/auth/keep_alive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::sync::Arc;

use rand::random;
use tokio::sync::Mutex;
use tracing::{error, info, warn};
use tracing::info;

use crate::{
common::data::crc, component::Component, context::Context, error::JludResult,
Expand Down Expand Up @@ -89,7 +89,7 @@ impl KeepAliveSender {
}

impl Component for KeepAliveSender {
#[tracing::instrument(skip_all)]
#[tracing::instrument(skip_all, name = "keep_alive_sender")]
async fn run(&mut self, context: Arc<Mutex<Context>>) -> JludResult<()> {
let mut ctx = context.lock().await;

Expand Down
24 changes: 5 additions & 19 deletions src/cli/auth/login.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::sync::Arc;
use pnet::datalink;
use rand::random;
use tokio::sync::Mutex;
use tracing::{error, info, warn};
use tracing::{error, info};

use crate::{
common::{
Expand Down Expand Up @@ -172,28 +172,14 @@ impl LoginSender {
}

impl Component for LoginSender {
#[tracing::instrument(skip_all)]
#[tracing::instrument(skip_all, name = "login_sender")]
async fn run(&mut self, context: Arc<Mutex<Context>>) -> JludResult<()> {
let mut ctx = context.lock().await;

info!("Sending login request");
info!("Starting login");

let username_opt = ctx.user.username.clone();
let username = match username_opt {
Some(username) => username,
None => {
error!("Username is not set");
return Err(JludError::MissingField("username".to_string()));
}
};
let password_opt = ctx.user.password.clone();
let password = match password_opt {
Some(password) => password,
None => {
error!("Password is not set");
return Err(JludError::MissingField("password".to_string()));
}
};
let username = ctx.user.username.clone();
let password = ctx.user.password.clone();
let interface = ctx.interface.config.interface.clone();
let interfaces = datalink::interfaces();
let target = interfaces
Expand Down
13 changes: 9 additions & 4 deletions src/cli/auth/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use crate::{
};

use self::{
challenge::Challenger, keep_alive::KeepAliveSender, login::LoginSender,
challenge::ChallengeSender, keep_alive::KeepAliveSender, login::LoginSender,
user::UserInfoCollector,
};

Expand All @@ -29,7 +29,7 @@ impl Component for Auth {
let ctx = context.lock().await;
(ctx.common.config.retry, ctx.common.config.retry_interval)
};
RetryGuard::new(max_retries, interval, AuthImpl {})
RetryGuard::new(max_retries, interval, AuthImpl::new())
.run(context)
.await
}
Expand All @@ -38,13 +38,18 @@ impl Component for Auth {
#[derive(Debug)]
pub struct AuthImpl;

impl AuthImpl {
pub fn new() -> Self {
Self {}
}
}

impl Component for AuthImpl {
async fn run(&mut self, context: Arc<Mutex<Context>>) -> JludResult<()> {
UserInfoCollector::new().run(context.clone()).await?;

Challenger::new().run(context.clone()).await?;
ChallengeSender::new().run(context.clone()).await?;
LoginSender::new().run(context.clone()).await?;

InfiniteGuard::new(20, KeepAliveSender::new())
.run(context.clone())
.await
Expand Down
43 changes: 20 additions & 23 deletions src/cli/auth/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,7 @@ use std::sync::Arc;
use tokio::sync::Mutex;
use tracing::{info, warn};

use crate::{
component::Component,
context::Context,
error::{JludError, JludResult},
};
use crate::{component::Component, context::Context, error::JludResult};

#[derive(Debug)]
pub struct UserInfoCollector;
Expand All @@ -19,30 +15,31 @@ impl UserInfoCollector {
}

impl Component for UserInfoCollector {
#[tracing::instrument(skip_all, name = "user_info_collector")]
async fn run(&mut self, context: Arc<Mutex<Context>>) -> JludResult<()> {
let user_ctx = &mut context.lock().await.user;
if user_ctx.config.save_user {
// read user info from config file
match user_ctx.load_from_config().await {
Ok(_) => {}
Err(e) => match e {
JludError::Io(_) => {
// prompt user for info
warn!("Could not read user info from config file, prompting user for info");
user_ctx.read_user_info_from_prompt()?;
user_ctx.save_to_config().await?;
}
_ => return Err(e),
},
let ctx = &mut context.lock().await;
let user_path = ctx.path.user.clone();

info!("Starting user info collection");

if ctx.user.config.save_user {
info!("Loading user info from passwd file");
if let Err(e) = ctx.user.load_from_config(&user_path).await {
warn!(
"Could not read user info from config file: {}, prompting user for info", e
);
ctx.user.read_user_info_from_prompt()?;
if let Err(e) = ctx.user.save_to_config(&user_path).await {
warn!("Failed to save user info to user file: {}", e);
}
}
} else {
// prompt user for info
user_ctx.read_user_info_from_prompt()?;
info!("Prompting user for info");
ctx.user.read_user_info_from_prompt()?;
}

if let Some(ref username) = user_ctx.username {
info!("User {:?} info collected", username);
}
info!("User {:?} info collected", ctx.user.username);

Ok(())
}
Expand Down
5 changes: 4 additions & 1 deletion src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,13 @@ pub struct Cli {
#[arg(value_enum, short, long, default_value = "info")]
pub log_level: LogLevel,

// default to app default config directory
/// Specify the path to the configuration file
#[arg(short, long)]
pub config: Option<String>,

/// Specify the path to the user data file (No effect when save_user is false)
#[arg(short, long)]
pub user: Option<String>,
}

#[derive(Subcommand, Debug)]
Expand Down
40 changes: 24 additions & 16 deletions src/common/path.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,33 @@
use std::path::PathBuf;

use dirs;
use directories::ProjectDirs;
use dotenv_codegen::dotenv;

pub fn app_config_dir() -> Option<PathBuf> {
dirs::config_dir().map(|mut p| {
p.push(dotenv!("JLUD_APP_NAME"));
p
})
#[derive(Debug)]
pub struct JludPath {
/// Path to the configuration file
pub config: PathBuf,
/// Path to the user data file
pub user: PathBuf,
}

pub fn app_config_file() -> Option<PathBuf> {
app_config_dir().map(|mut p| {
p.push(dotenv!("JLUD_APP_CONFIG_FILE"));
p
})
impl JludPath {
pub fn new(config: PathBuf, user: PathBuf) -> Self {
Self { config, user }
}
}

pub fn app_password_file() -> Option<PathBuf> {
app_config_dir().map(|mut p| {
p.push(dotenv!("JLUD_APP_PASSWORD_FILE"));
p
})
impl From<ProjectDirs> for JludPath {
fn from(dirs: ProjectDirs) -> Self {
Self {
config: dirs
.config_dir()
.to_path_buf()
.join(dotenv!("JLUD_APP_CONFIG_FILE")),
user: dirs
.cache_dir()
.to_path_buf()
.join(dotenv!("JLUD_APP_PASSWORD_FILE")),
}
}
}
4 changes: 3 additions & 1 deletion src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ pub mod common;
pub mod interface;
pub mod user;

use std::path::PathBuf;

use serde::{Deserialize, Serialize};
use tokio::{fs::File, io::AsyncReadExt};

Expand All @@ -28,7 +30,7 @@ pub struct Config {
}

impl Config {
pub async fn try_from_file(path: &str) -> JludResult<Self> {
pub async fn try_from_file(path: &PathBuf) -> JludResult<Self> {
let mut file = File::open(path).await?;
let mut contents = String::new();
file.read_to_string(&mut contents).await?;
Expand Down
11 changes: 9 additions & 2 deletions src/context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,32 @@ pub mod common;
pub mod interface;
pub mod user;

use crate::{config::Config, error::JludResult};
use crate::{common::path::JludPath, config::Config, error::JludResult};

use self::{
common::CommonContext, interface::InterfaceContext, user::UserContext,
};

/// 程序上下文对象
#[derive(Debug)]
pub struct Context {
/// 用户上下文,用于用户信息API
pub user: UserContext,
/// 网络接口上下文,用于网络接口API
pub interface: InterfaceContext,
/// 通用上下文,用于通用API和运行时数据
pub common: CommonContext,
/// 用于存储程序路径信息
pub path: JludPath,
}

impl Context {
pub async fn create(config: Config) -> JludResult<Self> {
pub async fn create(config: Config, path: JludPath) -> JludResult<Self> {
Ok(Self {
user: UserContext::new(config.user),
interface: InterfaceContext::create(config.interface).await?,
common: CommonContext::new(config.common),
path,
})
}
}
Loading

0 comments on commit c702e34

Please sign in to comment.