From c2cadb92997625596ed5c1c35f3254c39e5e520a Mon Sep 17 00:00:00 2001 From: Adam Marcus Date: Sat, 9 Sep 2023 19:59:02 +0000 Subject: [PATCH] Registration and login work end-to-end --- src/error.rs | 18 ++++++++++++ tests/e2e.rs | 83 +++++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 93 insertions(+), 8 deletions(-) diff --git a/src/error.rs b/src/error.rs index fb1af239..c1b48aa8 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,11 +1,13 @@ use actix_web; use derive_more::{Display, Error}; use fernet; +use quoted_printable; use reqwest; use rusqlite; use serde::{Deserialize, Serialize}; use serde_json; use sqlx; +use std::string; #[derive(Debug, Deserialize, Display, Error, Serialize)] pub struct AybError { @@ -26,6 +28,14 @@ impl From for AybError { } } +impl From for AybError { + fn from(cause: quoted_printable::QuotedPrintableError) -> Self { + AybError { + message: format!("{:?}", cause), + } + } +} + impl From for AybError { fn from(cause: rusqlite::Error) -> Self { AybError { @@ -42,6 +52,14 @@ impl From for AybError { } } +impl From for AybError { + fn from(cause: string::FromUtf8Error) -> Self { + AybError { + message: format!("{:?}", cause), + } + } +} + impl From for AybError { fn from(cause: serde_json::Error) -> Self { AybError { diff --git a/tests/e2e.rs b/tests/e2e.rs index 87fa8588..53078268 100644 --- a/tests/e2e.rs +++ b/tests/e2e.rs @@ -1,5 +1,6 @@ use assert_cmd::prelude::*; use ayb::error::AybError; +use quoted_printable; use serde::{Deserialize, Serialize}; use std::fs; use std::process::Command; @@ -55,7 +56,10 @@ fn extract_token(email: &EmailEntry) -> Result { assert_eq!(email.subject, "Your login credentials"); for line in &email.content { if line.starts_with(prefix) && line.len() > prefix.len() { - return Ok(line[prefix.len()..].to_owned()); + return Ok(String::from_utf8(quoted_printable::decode( + line[prefix.len()..].to_owned(), + quoted_printable::ParseMode::Robust, + )?)?); } } return Err(AybError { @@ -106,7 +110,7 @@ fn client_server_integration( .success() .stdout("Check your email to finish registering e2e\n"); - // Can register an entity twice as long as you don't complete the process. + // Register the same entity with the same email address. Command::cargo_bin("ayb")? .args(["client", "register", "e2e", "e2e@example.org"]) .env("AYB_SERVER_URL", server_url) @@ -114,17 +118,80 @@ fn client_server_integration( .success() .stdout("Check your email to finish registering e2e\n"); + // Can start to register an entity twice as long as you don't + // complete the process. + Command::cargo_bin("ayb")? + .args(["client", "register", "e2e", "e2e-another@example.org"]) + .env("AYB_SERVER_URL", server_url) + .assert() + .success() + .stdout("Check your email to finish registering e2e\n"); + // Check that two emails were received let entries = parse_smtp_log(&format!("tests/smtp_data_{}/e2e@example.org", smtp_port))?; assert_eq!(entries.len(), 2); - // XYZ assert subjects, assert contents, get both tokens, first succeeds second fails - let token0 = extract_token(&entries[0]); - let token1 = extract_token(&entries[1]); - println!("{:?}, {:?}", token0, token1); + let token0 = extract_token(&entries[0])?; + let token1 = extract_token(&entries[1])?; + let entries = parse_smtp_log(&format!( + "tests/smtp_data_{}/e2e-another@example.org", + smtp_port + ))?; + assert_eq!(entries.len(), 1); + let token2 = extract_token(&entries[0])?; + + // Using a bad token (appending a letter) doesn't work. + Command::cargo_bin("ayb")? + .args(["client", "confirm", &format!("{}a", token0)]) + .env("AYB_SERVER_URL", server_url) + .assert() + .success() + .stdout("Error: Invalid or expired token\n"); - // XYZ Confirm registration + // Using either token first will register the account. The second + // token, which has the same email address, will still work + // (confirming an email the second time is like logging in). The + // third token, which was with a different email address for the + // same account, won't work now that there's already a confirmed + // email address on the account.. + Command::cargo_bin("ayb")? + .args(["client", "confirm", &token0]) + .env("AYB_SERVER_URL", server_url) + .assert() + .success() + .stdout("Successfully authenticated and saved token default/insecure, unimplemented\n"); - // XYZ Try logging in + Command::cargo_bin("ayb")? + .args(["client", "confirm", &token1]) + .env("AYB_SERVER_URL", server_url) + .assert() + .success() + .stdout("Successfully authenticated and saved token default/insecure, unimplemented\n"); + + Command::cargo_bin("ayb")? + .args(["client", "confirm", &token2]) + .env("AYB_SERVER_URL", server_url) + .assert() + .success() + .stdout("Error: e2e has already been registered\n"); + + // Logging in as the user emails the first email address, which + // can confirm using the token it received. + Command::cargo_bin("ayb")? + .args(["client", "log_in", "e2e"]) + .env("AYB_SERVER_URL", server_url) + .assert() + .success() + .stdout("Check your email to finish logging in e2e\n"); + + let entries = parse_smtp_log(&format!("tests/smtp_data_{}/e2e@example.org", smtp_port))?; + assert_eq!(entries.len(), 3); + let login_token = extract_token(&entries[2])?; + Command::cargo_bin("ayb")? + .args(["client", "confirm", &login_token]) + .env("AYB_SERVER_URL", server_url) + .assert() + .success() + .stdout("Successfully authenticated and saved token default/insecure, unimplemented\n"); // Create database. Command::cargo_bin("ayb")?