summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock10
-rw-r--r--Cargo.toml1
-rw-r--r--src/error.rs10
-rw-r--r--src/model.rs14
-rw-r--r--src/routes.rs2
5 files changed, 31 insertions, 6 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 086b61a..3194485 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -363,6 +363,15 @@ dependencies = [
]
[[package]]
+name = "email_address"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2153bd83ebc09db15bcbdc3e2194d901804952e3dc96967e1cd3b0c5c32d112"
+dependencies = [
+ "serde",
+]
+
+[[package]]
name = "equivalent"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1956,6 +1965,7 @@ dependencies = [
"axum",
"axum-extra",
"dotenvy",
+ "email_address",
"http-body-util",
"mime",
"pgtemp",
diff --git a/Cargo.toml b/Cargo.toml
index fd2b28e..975ef91 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -10,6 +10,7 @@ argon2 = { version = "0.5.3", features = ["std"] }
axum = "0.7.4"
axum-extra = { version = "0.9.2", features = ["typed-routing"] }
dotenvy = "0.15.7"
+email_address = "0.2.4"
serde = { version = "1.0.197", features = ["derive"] }
serde_json = "1.0.114"
sqlx = { version = "0.7.3", features = ["postgres", "runtime-tokio", "uuid", "time"] }
diff --git a/src/error.rs b/src/error.rs
index 54075da..351c01a 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -35,11 +35,11 @@ pub enum Error {
#[error("User with that email already exists")]
EmailExists,
- #[error("Email is invalid")]
- EmailInvalid,
+ #[error("Invalid email: {0}")]
+ EmailInvalid(#[from] email_address::Error),
- #[error("Password is invalid")]
- PasswordInvalid,
+ #[error("Invalid email or password")]
+ LoginInvalid,
#[error("{0}")]
Other(String),
@@ -50,7 +50,7 @@ impl From<&Error> for StatusCode {
match value {
Error::UserNotFound => StatusCode::NOT_FOUND,
Error::EmailExists => StatusCode::CONFLICT,
- Error::EmailInvalid | Error::PasswordInvalid => StatusCode::UNPROCESSABLE_ENTITY,
+ Error::EmailInvalid(_) => StatusCode::UNPROCESSABLE_ENTITY,
_ => StatusCode::INTERNAL_SERVER_ERROR,
}
}
diff --git a/src/model.rs b/src/model.rs
index 5f6111e..51ce493 100644
--- a/src/model.rs
+++ b/src/model.rs
@@ -1,7 +1,12 @@
+use std::str::FromStr;
+
use serde::{Deserialize, Serialize};
+use sqlx::FromRow;
use time::OffsetDateTime;
-#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
+use crate::Error;
+
+#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, FromRow)]
#[serde(rename_all = "camelCase")]
pub struct User {
pub id: uuid::Uuid,
@@ -28,6 +33,13 @@ pub struct RegisterSchema {
pub password: String,
}
+impl RegisterSchema {
+ pub fn validate(&self) -> Result<(), Error> {
+ email_address::EmailAddress::from_str(&self.email)?;
+ Ok(())
+ }
+}
+
#[derive(Debug, Serialize, Deserialize)]
pub struct LoginSchema {
pub email: String,
diff --git a/src/routes.rs b/src/routes.rs
index 0bf34b2..2692f1a 100644
--- a/src/routes.rs
+++ b/src/routes.rs
@@ -77,6 +77,8 @@ impl Register {
State(state): State<Arc<AppState>>,
Json(register_schema): Json<RegisterSchema>,
) -> impl IntoResponse {
+ register_schema.validate()?;
+
let exists: Option<bool> =
sqlx::query_scalar("SELECT EXISTS(SELECT 1 FROM users WHERE email = $1)")
.bind(register_schema.email.to_ascii_lowercase())