Repository: diesel-rs/diesel
File: examples/postgres/advanced-blog-cli/src/auth.rs (Rust)

Code before:
        .first::<UserWithPassword>(conn)
        .optional()
        .map_err(AuthenticationError::DatabaseError)?;

    if let Some(user_and_password) = user_and_password {
        let parsed_hash = PasswordHash::new(&user_and_password.password)?;
        Argon2::default()
            .verify_password(password.as_bytes(), &parsed_hash)
            .map_err(|e| match e {
                argon2::password_hash::Error::Password => IncorrectPassword,
                _ => AuthenticationError::Argon2Error(e),
            })?;
        Ok(Some(user_and_password.user))
    } else {
        Ok(None)
    }
}

fn register_user(
    conn: &mut PgConnection,
    username: &str,
    password: &str,
) -> Result<User, AuthenticationError> {
    let salt = SaltString::from_b64(SALT_STRING)?;
    let argon2 = Argon2::default();
    let hashed_password = argon2
        .hash_password(password.as_bytes(), &salt)?
        .to_string();
    insert_into(users::table)
        .values((
            users::username.eq(username),
            users::hashed_password.eq(hashed_password),
        ))
        .returning((users::id, users::username))
        .get_result(conn)
        .map_err(AuthenticationError::DatabaseError)
}

fn get_username() -> Result<String, AuthenticationError> {
    if_not_present(dotenvy::var("BLOG_USERNAME"), NoUsernameSet)
}

fn get_password() -> Result<String, AuthenticationError> {
    if_not_present(dotenvy::var("BLOG_PASSWORD"), NoPasswordSet)
}

fn if_not_present<T>(
    res: Result<T, dotenvy::Error>,
    on_not_present: AuthenticationError,
) -> Result<T, AuthenticationError> {
    use std::env::VarError::NotPresent;

Review comment (suggestion):
```suggestion
    // In real applications you should never use a constant salt!!
    // Checkout https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#salting for details
    let salt = SaltString::from_b64(SALT_STRING)?;
```

Code after:
        .first::<UserWithPassword>(conn)
        .optional()
        .map_err(AuthenticationError::DatabaseError)?;

    if let Some(user_and_password) = user_and_password {
        let parsed_hash = PasswordHash::new(&user_and_password.password)?;
        Argon2::default()
            .verify_password(password.as_bytes(), &parsed_hash)
            .map_err(|e| match e {
                argon2::password_hash::Error::Password => IncorrectPassword,
                _ => AuthenticationError::Argon2Error(e),
            })?;
        Ok(Some(user_and_password.user))
    } else {
        Ok(None)
    }
}

fn register_user(
    conn: &mut PgConnection,
    username: &str,
    password: &str,
) -> Result<User, AuthenticationError> {
    // In real applications you should never use a constant salt!!
    // Checkout https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#salting for details
    let salt = SaltString::from_b64(SALT_STRING)?;
    let argon2 = Argon2::default();
    let hashed_password = argon2
        .hash_password(password.as_bytes(), &salt)?
        .to_string();
    insert_into(users::table)
        .values((
            users::username.eq(username),
            users::hashed_password.eq(hashed_password),
        ))
        .returning((users::id, users::username))
        .get_result(conn)
        .map_err(AuthenticationError::DatabaseError)
}

fn get_username() -> Result<String, AuthenticationError> {
    if_not_present(dotenvy::var("BLOG_USERNAME"), NoUsernameSet)
}

fn get_password() -> Result<String, AuthenticationError> {
    if_not_present(dotenvy::var("BLOG_PASSWORD"), NoPasswordSet)
}

fn if_not_present<T>(
    res: Result<T, dotenvy::Error>,
    on_not_present: AuthenticationError,