@smbcloud / cli / commits / 0b9d01a

Fix signup with dialoguer

Seto Elkahfi committed Feb 28, 2023 at 23:30 UTC 0b9d01ace4abab31833105a68ce0e5eccce34147
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