login with user

This commit is contained in:
alex 2026-03-02 11:07:42 +08:00
parent 8902c27b1d
commit 00c5c67307
7 changed files with 158 additions and 25 deletions

32
Cargo.lock generated
View File

@ -2021,11 +2021,13 @@ dependencies = [
"quinn",
"rand 0.8.5",
"reqwest",
"rpassword",
"rsa",
"rustls",
"rustls-pemfile",
"sdlan-sn-rs",
"serde",
"serde_json",
"structopt",
"tokio",
"tokio-util",
@ -2303,6 +2305,17 @@ dependencies = [
"tracing-subscriber",
]
[[package]]
name = "rpassword"
version = "7.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "66d4c8b64f049c6721ec8ccec37ddfc3d641c4a7fca57e8f2a89de509c73df39"
dependencies = [
"libc",
"rtoolbox",
"windows-sys 0.59.0",
]
[[package]]
name = "rsa"
version = "0.9.10"
@ -2323,6 +2336,16 @@ dependencies = [
"zeroize",
]
[[package]]
name = "rtoolbox"
version = "0.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7cc970b249fbe527d6e02e0a227762c9108b2f49d81094fe357ffc6d14d7f6f"
dependencies = [
"libc",
"windows-sys 0.52.0",
]
[[package]]
name = "rustc-hash"
version = "2.1.1"
@ -3764,6 +3787,15 @@ dependencies = [
"windows-targets 0.52.6",
]
[[package]]
name = "windows-sys"
version = "0.59.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
dependencies = [
"windows-targets 0.52.6",
]
[[package]]
name = "windows-sys"
version = "0.60.2"

View File

@ -32,7 +32,9 @@ bytes = "1.11.1"
quinn = "0.11.9"
rustls = "0.23.37"
rustls-pemfile = "2.2.0"
clap = { version = "4.5.60", features = ["derive"] }
clap = { version = "4.5.60", features = ["derive", "env"] }
rpassword = "7.4.0"
serde_json = "1.0.149"
# rolling-file = { path = "../rolling-file" }
[target.'cfg(unix)'.dependencies]

View File

@ -26,7 +26,7 @@ struct UserPassLoginData<'a> {
#[derive(Debug, Deserialize)]
pub struct LoginResponse {
pub code: i8,
pub code: i32,
pub message: String,
pub data: Option<LoginData>,
}
@ -68,9 +68,15 @@ where T: Serialize,
};
println!("status: {}", response.status());
let Ok(data) = response.json().await else {
return Err(SDLanError::IOError("failed to jsonify response".to_owned()));
};
let text = response.text().await.unwrap();
println!("text = {}", text);
let data = serde_json::from_str(&text).unwrap();
// println!("response: {}", response.text().await.unwrap());
// let Ok(data) = response.json().await else {
// return Err(SDLanError::IOError("failed to jsonify response".to_owned()));
// };
// println!("got respose: {:?}", data);
Ok(data)

View File

@ -1,26 +1,66 @@
mod api;
use std::process;
use std::env;
use clap::Parser;
use punchnet::CommandLineInput2;
use punchnet::Commands;
use punchnet::create_or_load_mac;
use punchnet::get_base_dir;
use punchnet::get_edge;
use punchnet::mod_hostname;
use punchnet::restore_dns;
use punchnet::run_sdlan;
use punchnet::set_access_token;
use punchnet::set_base_dir;
use punchnet::CommandLine;
use punchnet::CommandLineInput;
use sdlan_sn_rs::log;
use sdlan_sn_rs::utils::Result;
use sdlan_sn_rs::utils::create_or_load_uuid;
use tokio::io::AsyncWriteExt;
use tokio::io::stdout;
use tracing::error;
use std::net::ToSocketAddrs;
use structopt::StructOpt;
use crate::api::LoginData;
use crate::api::LoginResponse;
use crate::api::TEST_PREFIX;
use crate::api::login_with_token;
use crate::api::login_with_user_pass;
const APP_USER_ENV_NAME: &str = "PUNCH_USER";
const APP_PASS_ENV_NAME: &str = "PUNCH_PASS";
const APP_TOKEN_ENV_NAME: &str = "PUNCH_TOKEN";
fn parse_login_result(res: Result<LoginResponse>) -> LoginData {
match res {
Err(e) => {
eprintln!("login error: {}", e.as_str());
process::exit(-1);
}
Ok(data) => {
if data.code != 0 {
eprintln!("login error: {}", data.message);
process::exit(-1);
}
let Some(data) = data.data else {
eprintln!("login error: empty data");
process::exit(-1);
};
if let Err(_e) = set_access_token(&data.access_token) {
eprintln!("failed to save access_token");
}
data
}
}
}
#[tokio::main]
async fn main() {
@ -28,15 +68,39 @@ async fn main() {
let _guard = log::init_log(&format!("{}/.output", get_base_dir()));
let client_id = create_or_load_uuid(&format!("{}/.id", get_base_dir()), None).unwrap();
let token = "49722584273728716817720074439183";
let test_token = "49722584273728716817720074439183";
let mac = create_or_load_mac();
let system = "linux";
let version = "1.0.0";
let cmd = CommandLineInput::from_args();
// let cmd = CommandLineInput::from_args();
let cmd = CommandLineInput2::parse();
// println!("port is {}", cmd.port);
match cmd.cmd {
Commands::Login(user) => {
// TODO: do login with user
let data = parse_login_result(
login_with_user_pass(TEST_PREFIX, &client_id, &user.username, &user.password, mac, system, version).await
);
}
Commands::TokenLogin(tk) => {
}
Commands::AutoRun(tk) => {
}
Commands::Start => {
}
Commands::Stop => {
}
}
let (tx, rx) = std::sync::mpsc::channel();
let hostname = "punchnet.aioe.tech".to_owned();
@ -55,7 +119,7 @@ async fn main() {
println!("server is {}", server);
mod_hostname::get_hostname();
// mod_hostname::get_hostname();
/*
let hostname = if cmd.hostname.len() == 0 {
mod_hostname::get_hostname()
@ -63,6 +127,7 @@ async fn main() {
Some(cmd.hostname)
};
*/
/*
let hostname = if cmd.hostname.len() == 0 {
None
} else {
@ -70,6 +135,7 @@ async fn main() {
};
// let hostname = mod_hostname::get_hostname();
println!("hostname = {:?}", hostname);
*/
let _ = run_sdlan(
client_id,
@ -85,15 +151,15 @@ async fn main() {
mtu: 1400,
name: "tau".to_owned(),
tos: 0,
local_port: cmd.port,
token: cmd.token.clone(),
local_port: 0,
// token: cmd.token.clone(),
// network_code: cmd.network_code.clone(),
allow_p2p: true,
},
tx,
&punchnet::get_install_channel(),
server,
hostname,
Some(hostname),
None,
)
.await;

View File

@ -19,7 +19,7 @@ use tokio::net::UdpSocket;
use tokio::sync::mpsc::{channel, Sender};
use tokio_util::sync::CancellationToken;
use tracing::{debug, error};
pub use utils::{CommandLine, CommandLineInput, mod_hostname, create_or_load_mac};
pub use utils::*;
pub use config::{get_base_dir, set_base_dir};

View File

@ -1,17 +1,25 @@
use structopt::StructOpt;
use clap::{Parser, Subcommand, Args};
#[derive(Parser)]
const APP_TOKEN_ENV_NAME: &str = "PUNCH_TOKEN";
const APP_USER_ENV_NAME: &str = "PUNCH_USER";
const APP_PASS_ENV_NAME: &str = "PUNCH_PASS";
#[derive(Parser, Debug)]
pub struct CommandLineInput2 {
#[command(subcommand)]
cmd: Commands,
pub cmd: Commands,
}
#[derive(Subcommand)]
#[derive(Subcommand, Debug)]
pub enum Commands {
Login(UserLogin),
TokenLogin(TokenLogin),
/// if logined in, just start,
/// else, use the token to login, and start
AutoRun(TokenLogin),
/// after login, we can use start to
/// connect to the remote
Start,
@ -20,17 +28,21 @@ pub enum Commands {
Stop,
}
#[derive(Args)]
#[derive(Args, Debug)]
pub struct UserLogin {
#[arg(short, long)]
username: String,
#[arg(short, long, env = APP_USER_ENV_NAME)]
pub username: String,
// #[arg(long, env="APP_SECRET", hide_env_values = true, hide=true)]
// password: String,
#[arg(short, long, env = APP_PASS_ENV_NAME, required=false)]
pub password: String,
}
#[derive(Args)]
pub struct TokenLogin {}
#[derive(Args, Debug)]
pub struct TokenLogin {
#[arg(long, env=APP_TOKEN_ENV_NAME, required=false)]
pub token: String,
}
#[derive(StructOpt, Debug)]
@ -89,8 +101,8 @@ pub struct CommandLine {
#[structopt(long = "tos", default_value = "0")]
pub tos: u32,
#[structopt(long = "token", default_value = "")]
pub token: String,
// #[structopt(long = "token", default_value = "")]
// pub token: String,
// #[structopt(long = "code", default_value = "")]
// pub network_code: String,
@ -114,7 +126,7 @@ impl Clone for CommandLine {
local_port: self.local_port,
name: self.name.clone(),
tos: self.tos,
token: self.token.clone(),
// token: self.token.clone(),
// network_code: self.network_code.clone(),
allow_p2p: self.allow_p2p,
nat_server1: self.nat_server1.clone(),

View File

@ -21,6 +21,21 @@ pub fn caculate_crc(data: &[u8]) -> u32 {
res
}
pub fn get_access_token() -> Option<String> {
let path = format!("{}/.access_token", get_base_dir());
if let Ok(content) = std::fs::read(&path) {
let result = String::from_utf8_lossy(&content);
return Some(result.to_string());
}
None
}
pub fn set_access_token(tk: &str) -> Result<()> {
let path = format!("{}/.access_token", get_base_dir());
std::fs::write(path, tk)?;
Ok(())
}
pub fn create_or_load_mac() -> Mac {
let path = format!("{}/.mac", get_base_dir());
if let Ok(content) = std::fs::read(&path) {