only confirmed users can login
Also uses a forked version of `maik` that supports getting mail bodies.
This commit is contained in:
parent
c7500ae6a3
commit
ef3cc5a11b
5 changed files with 35 additions and 14 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -1651,8 +1651,6 @@ checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "maik"
|
name = "maik"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ba8f0b47dc7cc74760332828e060ec705339b5e863894f575d81691546bbc836"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.22.1",
|
"base64 0.22.1",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
|
|
|
@ -50,3 +50,6 @@ test-log = { version = "0.2.12", default-features = false, features = ["trace"]
|
||||||
|
|
||||||
[profile.dev.package.sqlx-macros]
|
[profile.dev.package.sqlx-macros]
|
||||||
opt-level = 3
|
opt-level = 3
|
||||||
|
|
||||||
|
[patch.crates-io]
|
||||||
|
maik = { path = "../downloads/maik" }
|
||||||
|
|
|
@ -249,10 +249,9 @@ pub async fn login(
|
||||||
return Err(LoginError::CsrfValidationFailed);
|
return Err(LoginError::CsrfValidationFailed);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: `status = 'confirmed' AND `, need to be able to get email contents in test
|
|
||||||
let user = sqlx::query!(
|
let user = sqlx::query!(
|
||||||
r#"
|
r#"
|
||||||
SELECT id, password FROM users WHERE email = $1 LIMIT 1;
|
SELECT id, password FROM users WHERE status = 'confirmed' AND email = $1 LIMIT 1;
|
||||||
"#,
|
"#,
|
||||||
form.email
|
form.email
|
||||||
)
|
)
|
||||||
|
@ -461,7 +460,7 @@ pub async fn signup_confirm(
|
||||||
|
|
||||||
#[derive(thiserror::Error, Debug)]
|
#[derive(thiserror::Error, Debug)]
|
||||||
pub enum SignupConfirmError {
|
pub enum SignupConfirmError {
|
||||||
#[error("Not Logged In")]
|
#[error("Invalid Token")]
|
||||||
InvalidToken,
|
InvalidToken,
|
||||||
#[error("CSRF Validation Failed")]
|
#[error("CSRF Validation Failed")]
|
||||||
CsrfValidationFailed,
|
CsrfValidationFailed,
|
||||||
|
@ -472,7 +471,7 @@ pub enum SignupConfirmError {
|
||||||
impl IntoResponse for SignupConfirmError {
|
impl IntoResponse for SignupConfirmError {
|
||||||
fn into_response(self) -> axum::response::Response {
|
fn into_response(self) -> axum::response::Response {
|
||||||
let (status, message) = match self {
|
let (status, message) = match self {
|
||||||
SignupConfirmError::InvalidToken => (StatusCode::UNAUTHORIZED, "Unknown User"),
|
SignupConfirmError::InvalidToken => (StatusCode::UNAUTHORIZED, "Invalid Token"),
|
||||||
SignupConfirmError::CsrfValidationFailed => {
|
SignupConfirmError::CsrfValidationFailed => {
|
||||||
(StatusCode::BAD_REQUEST, "CSRF Validation Failed, Try Again")
|
(StatusCode::BAD_REQUEST, "CSRF Validation Failed, Try Again")
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ pub mod fixture;
|
||||||
use fixture::TestServer;
|
use fixture::TestServer;
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
use regex::Regex;
|
||||||
use test_log::test as traced;
|
use test_log::test as traced;
|
||||||
|
|
||||||
#[traced(tokio::test)]
|
#[traced(tokio::test)]
|
||||||
|
@ -19,6 +20,24 @@ async fn login_succeeds_with_valid_credentials() -> Result<()> {
|
||||||
|
|
||||||
assert_eq!(resp.status(), 200, "signup succeeds");
|
assert_eq!(resp.status(), 200, "signup succeeds");
|
||||||
|
|
||||||
|
let mail = server.mock_smtp_server.receive_mail().expect("recv mail");
|
||||||
|
let link_regex = Regex::new(r"/auth/confirm\?token\=([a-zA-Z0-9]+)")?;
|
||||||
|
let confirm_link = link_regex
|
||||||
|
.find(&mail.body)
|
||||||
|
.expect("find link in body")
|
||||||
|
.as_str();
|
||||||
|
|
||||||
|
println!("link: {confirm_link}");
|
||||||
|
|
||||||
|
// Confirm Account
|
||||||
|
let resp = client
|
||||||
|
.post(confirm_link)
|
||||||
|
.csrf_form::<[(&str, &str); 0]>(&[])
|
||||||
|
.send()
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
assert_eq!(resp.status(), 200, "confirm succeeds");
|
||||||
|
|
||||||
// Login
|
// Login
|
||||||
let resp = client
|
let resp = client
|
||||||
.post("/auth/login")
|
.post("/auth/login")
|
||||||
|
|
|
@ -2,8 +2,7 @@ pub mod fixture;
|
||||||
use fixture::TestServer;
|
use fixture::TestServer;
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use maik::MailAssertion;
|
use regex::Regex;
|
||||||
use regex::bytes::Regex;
|
|
||||||
use test_log::test as traced;
|
use test_log::test as traced;
|
||||||
|
|
||||||
#[traced(tokio::test)]
|
#[traced(tokio::test)]
|
||||||
|
@ -21,12 +20,15 @@ async fn subscribe_succeeds_with_valid_input() -> Result<()> {
|
||||||
|
|
||||||
assert_eq!(resp.status(), 200, "subscribe succeeds");
|
assert_eq!(resp.status(), 200, "subscribe succeeds");
|
||||||
|
|
||||||
assert!(
|
let mail = server.mock_smtp_server.receive_mail().expect("recv mail");
|
||||||
server
|
let link_regex =
|
||||||
.mock_smtp_server
|
Regex::new(r"http\:\/\/localhost\/subscriptions/confirm/\?token\=[a-zA-Z0-9]+")?;
|
||||||
.assert(MailAssertion::new().body_matches(Regex::new(r"http\:\/\/localhost\/")?)),
|
let link = link_regex
|
||||||
"email sent has link"
|
.find(&mail.body)
|
||||||
);
|
.expect("find link in body")
|
||||||
|
.as_str();
|
||||||
|
|
||||||
|
println!("link: {link}");
|
||||||
|
|
||||||
server.shutdown().await
|
server.shutdown().await
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue