@smbcloud / cli / commits / ea5cca1

fix login logout confirmation

Seto Elkahfi committed Sep 11, 2023 at 12:48 UTC ea5cca1d577bc486bcac92268d207f69c0f7cc05
3 files changed +107 -73
smbpndk-cli/src/account/lib.rs
+12 -29
@@ -1,12 +1,11 @@
1 +use super::{model::User, signup::GithubEmail};
2 use anyhow::{anyhow, Result};
3 use console::style;
4 use log::debug;
5 use regex::Regex;
6 use reqwest::{Client, Response, StatusCode};
7 use serde::{Deserialize, Serialize};
7 -
8 use serde_repr::Deserialize_repr;
9 -use smbpndk_model::CommandResult;
9 use smbpndk_networking::smb_base_url_builder;
10 use spinners::Spinner;
11 use std::{
@@ -19,8 +18,6 @@ use std::{
18 };
19 use url_builder::URLBuilder;
20
22 -use super::{model::User, signup::GithubEmail};
23 -
21 // This is smb authorization model.
22 #[derive(Debug, Serialize, Deserialize)]
23 pub struct SmbAuthorization {
@@ -173,33 +170,33 @@ pub async fn process_connect_github(code: String) -> Result<SmbAuthorization> {
170 .bold()
171 .to_string(),
172 );
176 - println!("Response: {:#?}", &response);
173 + // println!("Response: {:#?}", &response);
174 match response.status() {
175 StatusCode::OK => {
176 // Account authorized and token received
180 - spinner.stop_and_persist("✅", "You're logged in with your GitHub account!".into());
177 + spinner.stop_and_persist("✅", "You are logged in with your GitHub account!".into());
178 save_token(&response).await?;
179 let result = response.json().await?;
183 - println!("Result: {:#?}", &result);
180 + // println!("Result: {:#?}", &result);
181 Ok(result)
182 }
183 StatusCode::NOT_FOUND => {
184 // Account not found and we show signup option
185 spinner.stop_and_persist("🥲", "Account not found. Please signup!".into());
186 let result = response.json().await?;
190 - println!("Result: {:#?}", &result);
187 + // println!("Result: {:#?}", &result);
188 Ok(result)
189 }
190 StatusCode::UNPROCESSABLE_ENTITY => {
191 // Account found but email not verified
192 spinner.stop_and_persist("🥹", "Unverified email!".into());
193 let result = response.json().await?;
197 - println!("Result: {:#?}", &result);
194 + // println!("Result: {:#?}", &result);
195 Ok(result)
196 }
197 _ => {
198 // Other errors
202 - let error = anyhow!("Error while authorizing token.");
199 + let error = anyhow!("Error while authorizing with GitHub.");
200 Err(error)
201 }
202 }
@@ -237,9 +234,9 @@ fn github_base_url_builder() -> URLBuilder {
234 url_builder
235 }
236
240 -pub async fn save_token(response: &Response) -> Result<CommandResult> {
237 +pub async fn save_token(response: &Response) -> Result<()> {
238 let headers = response.headers();
242 - println!("Headers: {:#?}", &headers);
239 + // println!("Headers: {:#?}", &headers);
240 match headers.get("Authorization") {
241 Some(token) => {
242 debug!("{}", token.to_str()?);
@@ -252,25 +249,11 @@ pub async fn save_token(response: &Response) -> Result<CommandResult> {
249 .write(true)
250 .open([path.to_str().unwrap(), "/.smb/token"].join(""))?;
251 file.write_all(token.to_str()?.as_bytes())?;
255 -
256 - Ok(CommandResult {
257 - spinner: Spinner::new(
258 - spinners::Spinners::SimpleDotsScrolling,
259 - style("Logging you in...").green().bold().to_string(),
260 - ),
261 - symbol: "✅".to_owned(),
262 - msg: "You are logged in!".to_owned(),
263 - })
264 - }
265 - None => {
266 - let error = anyhow!("Failed to get home directory.");
267 - return Err(error);
252 + Ok(())
253 }
254 + None => Err(anyhow!("Failed to get home directory.")),
255 }
256 }
271 - None => {
272 - let error = anyhow!("Failed to get token. Probably a backend issue.");
273 - return Err(error);
274 - }
257 + None => Err(anyhow!("Failed to get token. Probably a backend issue.")),
258 }
259 }
smbpndk-cli/src/account/login/process.rs
+94 -43
@@ -13,7 +13,7 @@ use log::debug;
13 use reqwest::{Client, StatusCode};
14 use serde::{Deserialize, Serialize};
15 use smbpndk_model::CommandResult;
16 -use smbpndk_networking::{smb_base_url_builder, smb_token_file_path};
16 +use smbpndk_networking::{get_smb_token, smb_base_url_builder, smb_token_file_path};
17 use smbpndk_utils::email_validation;
18 use spinners::Spinner;
19 use std::fs::{self};
@@ -67,6 +67,59 @@ pub async fn process_login() -> Result<CommandResult> {
67 }
68 }
69
70 +pub async fn process_logout() -> Result<CommandResult> {
71 + // Logout if user confirms
72 + if let Some(token_path) = smb_token_file_path() {
73 + let confirm = Confirm::with_theme(&ColorfulTheme::default())
74 + .with_prompt("Do you want to logout? y/n")
75 + .interact()
76 + .unwrap();
77 + if !confirm {
78 + return Ok(CommandResult {
79 + spinner: Spinner::new(
80 + spinners::Spinners::SimpleDotsScrolling,
81 + style("Cancel operation.").green().bold().to_string(),
82 + ),
83 + symbol: "✅".to_owned(),
84 + msg: "Doing nothing.".to_owned(),
85 + });
86 + }
87 +
88 + let mut spinner = Spinner::new(
89 + spinners::Spinners::SimpleDotsScrolling,
90 + style("Logging you out...").green().bold().to_string(),
91 + );
92 +
93 + // Call backend
94 + match do_process_logout().await {
95 + Ok(_) => {
96 + spinner.stop_and_persist("✅", "Done.".to_owned());
97 + fs::remove_file(token_path)?;
98 + Ok(CommandResult {
99 + spinner: Spinner::new(
100 + spinners::Spinners::SimpleDotsScrolling,
101 + style("Loading...").green().bold().to_string(),
102 + ),
103 + symbol: "✅".to_owned(),
104 + msg: "You are now logged out!".to_owned(),
105 + })
106 + }
107 + Err(e) => Err(anyhow!("{e}")),
108 + }
109 + } else {
110 + Ok(CommandResult {
111 + spinner: Spinner::new(
112 + spinners::Spinners::SimpleDotsScrolling,
113 + style("Loading...").green().bold().to_string(),
114 + ),
115 + symbol: "😏".to_owned(),
116 + msg: "You are not logged in.".to_owned(),
117 + })
118 + }
119 +}
120 +
121 +// Private functions
122 +
123 async fn login_with_github() -> Result<CommandResult> {
124 match authorize_github().await {
125 Ok(result) => process_authorization(result).await,
@@ -95,18 +148,18 @@ async fn process_authorization(auth: SmbAuthorization) -> Result<CommandResult>
148 }
149 }
150
98 - // Logged in with GitHub
151 + // Logged in with GitHub!
152 + // Token handling is in the lib.rs account module.
153 if let Some(user) = auth.user {
100 - println!("You are logged in with GitHub as {}.", user);
154 let spinner = Spinner::new(
155 spinners::Spinners::SimpleDotsScrolling,
156 style("Logging you in...").green().bold().to_string(),
157 );
105 - // We're logged in with GitHub, but not with SMB.
158 + // We're logged in with GitHub.
159 return Ok(CommandResult {
160 spinner,
161 symbol: "✅".to_owned(),
109 - msg: "You are logged in!".to_owned(),
162 + msg: format!("You are logged in with GitHub as {}.", user.email),
163 });
164 }
165
@@ -241,7 +294,15 @@ async fn do_process_login(args: LoginArgs) -> Result<CommandResult> {
294 match response.status() {
295 StatusCode::OK => {
296 // Login successful
244 - save_token(&response).await
297 + save_token(&response).await?;
298 + Ok(CommandResult {
299 + spinner: Spinner::new(
300 + spinners::Spinners::SimpleDotsScrolling,
301 + style("Loading...").green().bold().to_string(),
302 + ),
303 + symbol: "✅".to_owned(),
304 + msg: "You are now logged in!".to_owned(),
305 + })
306 }
307 StatusCode::NOT_FOUND => {
308 // Account not found and we show signup option
@@ -257,13 +318,10 @@ async fn do_process_login(args: LoginArgs) -> Result<CommandResult> {
318 StatusCode::UNPROCESSABLE_ENTITY => {
319 // Account found but email not verified / password not set
320 let result: SmbAuthorization = response.json().await?;
260 - println!("Result: {:#?}", &result);
261 - return verify_or_set_password(result).await;
262 - }
263 - _ => {
264 - let error = anyhow!("Login failed. Check your username and password.");
265 - return Err(error);
321 + // println!("Result: {:#?}", &result);
322 + verify_or_set_password(result).await
323 }
324 + _ => Err(anyhow!("Login failed. Check your username and password.")),
325 }
326 }
327
@@ -272,18 +330,12 @@ async fn verify_or_set_password(result: SmbAuthorization) -> Result<CommandResul
330 Some(error_code) => {
331 debug!("{}", error_code);
332 match error_code {
275 - ErrorCode::EmailUnverified => return send_email_verification(result.user).await,
276 - ErrorCode::PasswordNotSet => return send_reset_password(result.user).await,
277 - _ => {
278 - let error = anyhow!("Shouldn't be here.");
279 - return Err(error);
280 - }
333 + ErrorCode::EmailUnverified => send_email_verification(result.user).await,
334 + ErrorCode::PasswordNotSet => send_reset_password(result.user).await,
335 + _ => Err(anyhow!("Shouldn't be here.")),
336 }
337 }
283 - None => {
284 - let error = anyhow!("Shouldn't be here.");
285 - return Err(error);
286 - }
338 + None => Err(anyhow!("Shouldn't be here.")),
339 }
340 }
341
@@ -392,36 +444,35 @@ async fn input_reset_password_token() -> Result<CommandResult> {
444 }
445 }
446
395 -pub async fn process_logout() -> Result<CommandResult> {
396 - let spinner = Spinner::new(
397 - spinners::Spinners::SimpleDotsScrolling,
398 - style("Logging you out...").green().bold().to_string(),
399 - );
400 - if let Some(token_path) = smb_token_file_path() {
401 - // Call backend
402 - fs::remove_file(token_path)?;
403 - Ok(CommandResult {
404 - spinner,
405 - symbol: "✅".to_owned(),
406 - msg: "You are now logged out!".to_owned(),
407 - })
408 - } else {
409 - Ok(CommandResult {
410 - spinner,
411 - symbol: "😏".to_owned(),
412 - msg: "You are not logged in.".to_owned(),
413 - })
447 +async fn do_process_logout() -> Result<()> {
448 + let token = get_smb_token().await?;
449 +
450 + let response = Client::new()
451 + .delete(build_smb_logout_url())
452 + .header("Authorization", token)
453 + .header("Accept", "application/json")
454 + .header("Content-Type", "application/x-www-form-urlencoded")
455 + .send()
456 + .await?;
457 +
458 + match response.status() {
459 + StatusCode::OK => Ok(()),
460 + _ => Err(anyhow!("Failed to logout.")),
461 }
462 }
463
417 -// Private functions
418 -
464 fn build_smb_login_url() -> String {
465 let mut url_builder = smb_base_url_builder();
466 url_builder.add_route("v1/users/sign_in");
467 url_builder.build()
468 }
469
470 +fn build_smb_logout_url() -> String {
471 + let mut url_builder = smb_base_url_builder();
472 + url_builder.add_route("v1/users/sign_out");
473 + url_builder.build()
474 +}
475 +
476 fn build_smb_resend_email_verification_url() -> String {
477 let mut url_builder = smb_base_url_builder();
478 url_builder.add_route("v1/resend_confirmation");
smbpndk-cli/src/project/mod.rs
+1 -1
@@ -192,7 +192,7 @@ pub async fn process_project(commands: Commands) -> Result<CommandResult> {
192
193 fn show_projects(projects: Vec<Project>) {
194 // println!("Projects: {projects:#?}");
195 - if projects.len() == 0 {
195 + if projects.is_empty() {
196 return;
197 }
198 println!(