Check user is validated before creating a new recipe
This commit is contained in:
parent
104ae6b38e
commit
c8e0aa918c
5 changed files with 62 additions and 3 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
|
@ -2460,6 +2460,7 @@ dependencies = [
|
|||
"clap",
|
||||
"common",
|
||||
"comrak",
|
||||
"cookie",
|
||||
"itertools",
|
||||
"lettre",
|
||||
"rand 0.9.1",
|
||||
|
|
|
|||
|
|
@ -50,6 +50,8 @@ lettre = { version = "0.11", default-features = false, features = [
|
|||
|
||||
thiserror = "2"
|
||||
|
||||
# Integration tests dependencies.
|
||||
[dev-dependencies]
|
||||
axum-test = "17"
|
||||
cookie = "0.18"
|
||||
scraper = "0.23"
|
||||
|
|
|
|||
|
|
@ -33,6 +33,9 @@ pub enum DBError {
|
|||
)]
|
||||
UnsupportedVersion(u32),
|
||||
|
||||
#[error("User not validated")]
|
||||
UserNotValidated,
|
||||
|
||||
#[error("Unknown error: {0}")]
|
||||
Other(String),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -281,6 +281,21 @@ FROM [Recipe] WHERE [id] = $1
|
|||
pub async fn create_recipe(&self, user_id: i64) -> Result<i64> {
|
||||
let mut tx = self.tx().await?;
|
||||
|
||||
// Check that the user is validated.
|
||||
if !sqlx::query_scalar(
|
||||
r#"
|
||||
SELECT COUNT(*) = 1
|
||||
FROM [User] WHERE
|
||||
[User].[id] = $1 AND [User].[validation_token] IS NULL
|
||||
"#,
|
||||
)
|
||||
.bind(user_id)
|
||||
.fetch_one(&mut *tx)
|
||||
.await?
|
||||
{
|
||||
return Err(DBError::UserNotValidated);
|
||||
}
|
||||
|
||||
// Search for an existing empty recipe and return its id instead of creating a new one.
|
||||
match sqlx::query_scalar::<_, i64>(
|
||||
r#"
|
||||
|
|
@ -944,6 +959,19 @@ mod tests {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn create_a_new_recipe_by_an_unvalidated_user() -> Result<()> {
|
||||
let connection = Connection::new_in_memory().await?;
|
||||
|
||||
let user_id = create_an_unvalidated_user(&connection).await?;
|
||||
match connection.create_recipe(user_id).await {
|
||||
Err(DBError::UserNotValidated) => (), // Nominal case.
|
||||
other => panic!("{:?}", other),
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn setters() -> Result<()> {
|
||||
let connection = Connection::new_in_memory().await?;
|
||||
|
|
@ -977,6 +1005,28 @@ mod tests {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
async fn create_an_unvalidated_user(connection: &Connection) -> Result<i64> {
|
||||
let user_id = 1;
|
||||
connection.execute_sql(
|
||||
sqlx::query(
|
||||
r#"
|
||||
INSERT INTO [User]
|
||||
([id], [email], [name], [creation_datetime], [password], [validation_token_datetime], [validation_token])
|
||||
VALUES
|
||||
($1, $2, $3, $4, $5, $6, $7)
|
||||
"#
|
||||
)
|
||||
.bind(user_id)
|
||||
.bind("paul@atreides.com")
|
||||
.bind("paul")
|
||||
.bind("")
|
||||
.bind("$argon2id$v=19$m=4096,t=3,p=1$G4fjepS05MkRbTqEImUdYg$GGziE8uVQe1L1oFHk37lBno10g4VISnVqynSkLCH3Lc")
|
||||
.bind("2022-11-29 22:05:04.121407300+00:00")
|
||||
.bind(Some("SOME_TOKEN")) // not 'null'.
|
||||
).await?;
|
||||
Ok(user_id)
|
||||
}
|
||||
|
||||
async fn create_a_user(connection: &Connection) -> Result<i64> {
|
||||
let user_id = 1;
|
||||
connection.execute_sql(
|
||||
|
|
|
|||
|
|
@ -27,7 +27,8 @@ pub enum UpdateUserResult {
|
|||
pub enum ValidationResult {
|
||||
UnknownUser,
|
||||
ValidationExpired,
|
||||
Ok(String, i64), // Returns token and user id.
|
||||
/// Returns token and user id.
|
||||
Ok(String, i64),
|
||||
}
|
||||
|
||||
#[derive(Debug, Display)]
|
||||
|
|
@ -35,13 +36,15 @@ pub enum SignInResult {
|
|||
UserNotFound,
|
||||
WrongPassword,
|
||||
AccountNotValidated,
|
||||
Ok(String, i64), // Returns token and user id.
|
||||
/// Returns token and user id.
|
||||
Ok(String, i64),
|
||||
}
|
||||
|
||||
#[derive(Debug, Display)]
|
||||
pub enum AuthenticationResult {
|
||||
NotValidToken,
|
||||
Ok(i64), // Returns user id.
|
||||
/// Returns user id.
|
||||
Ok(i64),
|
||||
}
|
||||
|
||||
#[derive(Debug, Display)]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue