Skip to content

Commit

Permalink
Add sqlx
Browse files Browse the repository at this point in the history
  • Loading branch information
Your Name committed May 30, 2024
1 parent 4ba1bfd commit 3ae7960
Show file tree
Hide file tree
Showing 4 changed files with 159 additions and 2 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions crates/web-server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ tokio = { version = "1", features = ["rt-multi-thread"] }
markup = "0"
validator = { version = "0.12", features = ["derive"] }

# Use this for access to hcaptcha
reqwest = { version = "0", default-features = false, features = ["json", "rustls-tls"] }

# Used by the proxy
url = "2.0"

Expand Down
71 changes: 71 additions & 0 deletions crates/web-server/src/auth/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,78 @@
pub mod sign_in;
use std::collections::HashSet;

use axum::Router;
use axum_extra::routing::RouterExt;
use serde::{Deserialize, Deserializer};

pub fn routes() -> Router {
Router::new().typed_get(sign_in::sign_in)
}

#[derive(PartialEq, Eq, Hash, Debug)]
pub enum Code {
MissingSecret,
InvalidSecret,
MissingResponse,
InvalidResponse,
BadRequest,
Unknown(String),
}

impl<'de> Deserialize<'de> for Code {
fn deserialize<D>(de: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let code = String::deserialize(de)?;
Ok(match &*code {
"missing-input-secret" => Code::MissingSecret,
"invalid-input-secret" => Code::InvalidSecret,
"missing-input-response" => Code::MissingResponse,
"invalid-input-response" => Code::InvalidResponse,
"bad-request" => Code::BadRequest,
_ => Code::Unknown(code),
})
}
}

#[derive(Debug, Deserialize)]
pub struct RecaptchaResponse {
pub success: bool,
#[serde(rename = "error-codes")]
pub error_codes: Option<HashSet<Code>>,
}

/***pub async fn verify_hcaptcha(
hcaptcha_config: &Option<config::HCaptchaConfig>,
response: &Option<String>,
) -> bool {
if let Some(hcaptcha) = hcaptcha_config {
if let Some(resp) = response {
let mut url = Url::parse("https://hcaptcha.com/siteverify").unwrap();
let secret_key: &str = &hcaptcha.hcaptcha_secret_key;
url.query_pairs_mut()
.extend_pairs(&[("secret", secret_key), ("response", resp)]);
let response = reqwest::get(url).await;
if let Ok(resp) = response {
let recaptcha_response = resp.json::<RecaptchaResponse>().await;
if let Ok(status) = recaptcha_response {
if status.success {
return true;
} else {
dbg!(status);
}
}
}
}
return false;
}
true
}**/
86 changes: 84 additions & 2 deletions crates/web-server/src/auth/sign_in.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@

use super::super::errors::CustomError;
use crate::config::Config;
use crate::layouts;
use crate::routes::auth::{self, ResetRequest, SignUp};
use crate::{components::forms, config};
use axum::extract::Extension;
use axum::response::IntoResponse;
use db::Pool;
use serde::{Deserialize, Serialize};
use validator::ValidationErrors;

Expand All @@ -19,7 +19,6 @@ pub struct Login {

pub async fn sign_in(
auth::SignIn {}: auth::SignIn,
Extension(_pool): Extension<Pool>,
Extension(config): Extension<Config>,
) -> Result<impl IntoResponse, CustomError> {
let body = LoginPage {
Expand All @@ -37,6 +36,89 @@ pub async fn sign_in(
))
}


/***pub async fn process_login(
auth::SignIn {}: auth::SignIn,
Extension(pool): Extension<Pool>,
Extension(config): Extension<Config>,
identity: Identity,
Form(form): Form<Login>,
) -> Result<impl IntoResponse, CustomError> {
let mut validation_errors = ValidationErrors::default();
let valid = super::verify_hcaptcha(&config.hcaptcha_config, &form.h_captcha_response).await;
if valid {
let users = sqlx::query_as::<_, User>(&format!(
"
SELECT id, hashed_password FROM {} WHERE email = $1
",
config.user_table_name
))
.bind(&form.email.to_lowercase())
.fetch_all(pool.get_ref()) // -> Vec<Person>
.await?;
if !users.is_empty() {
// Passwords must be normalised
let normalised_password = &form.password.nfkc().collect::<String>();
let valid = crate::encryption::verify_hash(
normalised_password,
&users[0].hashed_password,
config.use_bcrypt_instead_of_argon,
)
.await?;
if valid {
// Generate a session
create_session(&config, pool, identity, users[0].id, None).await?;
return Ok(HttpResponse::SeeOther()
.append_header((http::header::LOCATION, config.redirect_url.clone()))
.finish());
}
}
validation_errors.add(
"email",
ValidationError {
message: Some(Cow::from("Invalid email or password")),
code: Cow::from("0"),
params: Default::default(),
},
);
} else {
validation_errors.add(
"email",
ValidationError {
message: Some(Cow::from("Invalid hCaptcha")),
code: Cow::from("0"),
params: Default::default(),
},
);
}
let login = Login {
email: form.email.clone(),
..Default::default()
};
let body = LoginPage {
form: &login,
hcaptcha_config: &config.hcaptcha_config,
sign_up: SignUp {}.to_string(),
reset_password: ResetRequest {}.to_string(),
errors: &validation_errors,
};
Ok(layouts::session_layout(
"Login",
&body.to_string(),
config.hcaptcha_config.is_some(),
))
}**/

markup::define! {
LoginPage<'a>(form: &'a Login,
hcaptcha_config: &'a Option<config::HCaptchaConfig>,
Expand Down

0 comments on commit 3ae7960

Please sign in to comment.