5 files changed
+49
-19
Cargo.lock
+12
@@ -14,6 +14,15 @@ dependencies = [
14
"version_check",
15
]
16
17
+[[package]]
18
+name = "aho-corasick"
19
+version = "0.7.20"
20
+source = "registry+https://github.com/rust-lang/crates.io-index"
21
+checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac"
22
+dependencies = [
23
+ "memchr",
24
+]
25
+
26
[[package]]
27
name = "anyhow"
28
version = "1.0.69"
@@ -754,6 +763,8 @@ version = "1.7.1"
763
source = "registry+https://github.com/rust-lang/crates.io-index"
764
checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733"
765
dependencies = [
766
+ "aho-corasick",
767
+ "memchr",
768
"regex-syntax",
769
]
770
@@ -973,6 +984,7 @@ dependencies = [
984
"console",
985
"dialoguer",
986
"home",
987
+ "regex",
988
"reqwest",
989
"serde",
990
"serde_json",
Cargo.toml
+1
@@ -19,6 +19,7 @@ clap = { version = "4.1.6", features = ["derive"] }
19
console = "0.15.0"
20
dialoguer = "0.10.3"
21
home = "0.5.4"
22
+regex = "1.3.1"
23
reqwest = { version = "0.11", features = ["json"] }
24
serde = { version = "1", features = ["derive"] }
25
serde_json = "1.0.82"
src/cli/mod.rs
+5
-8
@@ -13,14 +13,11 @@ pub struct Cli {
13
14
#[derive(Subcommand)]
15
pub enum Commands {
16
- #[clap(about = "Create an account")]
17
- Signup {
18
- #[clap(short, long)]
19
- username: String,
20
- #[clap(short, long)]
21
- password: String,
22
- },
16
+ #[clap(about = "Create an account. Use your email as your username.")]
17
+ Signup {},
18
24
- #[clap(about = "Login to your account. To create an account, visit https://smbpndk.com")]
19
+ #[clap(
20
+ about = "Login to your account. To create an account, use smb signup or visit https://smbpndk.com"
21
+ )]
22
Login {},
23
}
src/main.rs
+27
-9
@@ -1,9 +1,10 @@
1
-use std::{fs::OpenOptions, path::PathBuf, str::FromStr, time::Duration};
1
+use std::{fs::OpenOptions, path::PathBuf, str::FromStr};
2
3
use anyhow::{anyhow, Result};
4
use clap::Parser;
5
use console::style;
6
use dialoguer::{theme::ColorfulTheme, Input, Password};
7
+use regex::Regex;
8
use smbpndk_cli::{
9
cli::{Cli, Commands},
10
constants::ERROR_EMOJI,
@@ -11,7 +12,7 @@ use smbpndk_cli::{
12
signup::{process_signup, SignupArgs},
13
};
14
use spinners::Spinner;
14
-use tokio::time::sleep;
15
+
16
use tracing::subscriber::set_global_default;
17
use tracing_bunyan_formatter::{BunyanFormattingLayer, JsonStorageLayer};
18
use tracing_subscriber::{filter::LevelFilter, prelude::*, EnvFilter};
@@ -116,22 +117,39 @@ async fn run() -> Result<CommandResult> {
117
}
118
}
119
}
119
- Commands::Signup { username, password } => {
120
+ Commands::Signup {} => {
121
+ println!("Use your email address as your username.");
122
+ let username = Input::<String>::with_theme(&ColorfulTheme::default())
123
+ .with_prompt("Username")
124
+ .validate_with(|input: &String| -> Result<(), &str> {
125
+ let email_regex = Regex::new(r"^([a-z0-9_+]([a-z0-9_+.]*[a-z0-9_+])?)@([a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,6})").unwrap();
126
+
127
+ if email_regex.is_match(input) {
128
+ Ok(())
129
+ } else {
130
+ Err("Username must be an email address")
131
+ }
132
+ })
133
+ .interact()
134
+ .unwrap();
135
+ let password = Password::with_theme(&ColorfulTheme::default())
136
+ .with_prompt("Password")
137
+ .with_confirmation("Confirm password", "Passwords do not match")
138
+ .interact()
139
+ .unwrap();
140
+
141
let spinner = Spinner::new(
142
spinners::Spinners::BouncingBall,
143
style("Signing up...").green().bold().to_string(),
144
);
124
- let join_handle = tokio::spawn(async move {
125
- let _future = process_signup(SignupArgs { username, password }).await;
126
- sleep(Duration::from_millis(5000)).await;
127
- });
145
129
- match join_handle.await {
146
+ match process_signup(SignupArgs { username, password }).await {
147
Ok(_) => {
148
return Ok(CommandResult {
149
spinner: spinner,
150
symbol: "✅".to_owned(),
134
- msg: "You are signed up!".to_owned(),
151
+ msg: "You are signed up! Check your email to confirm your account."
152
+ .to_owned(),
153
});
154
}
155
Err(e) => {
src/signup/process.rs
+4
-2
@@ -1,6 +1,7 @@
1
-use anyhow::Result;
1
+use anyhow::{anyhow, Result};
2
use reqwest::Client;
3
use serde::Serialize;
4
+use tokio::sync::watch::error;
5
6
use crate::{constants::BASE_URL, login::User};
7
pub struct SignupArgs {
@@ -32,7 +33,8 @@ pub async fn process_signup(args: SignupArgs) -> Result<()> {
33
println!("token: {}", token);
34
}
35
_ => {
35
- println!("Error: {}", response.status());
36
+ let error = anyhow!("Failed to signup: {}", response.status());
37
+ return Err(error);
38
}
39
}
40