diff --git a/api/migrations/10232024_initial.sql b/api/migrations/10232024_initial.sql index 147664f..5d6f45c 100644 --- a/api/migrations/10232024_initial.sql +++ b/api/migrations/10232024_initial.sql @@ -62,10 +62,12 @@ CREATE INDEX ON metars (observation_time DESC); CREATE TABLE IF NOT EXISTS users ( email TEXT PRIMARY KEY NOT NULL, + email_verified BOOLEAN NOT NULL DEFAULT false, password_hash TEXT NOT NULL, role TEXT NOT NULL, first_name TEXT NOT NULL, last_name TEXT NOT NULL, + avatar TEXT, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); \ No newline at end of file diff --git a/api/src/account/routes.rs b/api/src/account/routes.rs index 47e614a..b865141 100644 --- a/api/src/account/routes.rs +++ b/api/src/account/routes.rs @@ -188,10 +188,12 @@ async fn change_password( let update_user = UpdateUser { email: None, + email_verified: None, password: Some(password.into_inner()), role: None, first_name: None, last_name: None, + avatar: None, }; match update_user.update(&email).await { diff --git a/api/src/airports/model/airport.rs b/api/src/airports/model/airport.rs index cf9c64c..d690475 100644 --- a/api/src/airports/model/airport.rs +++ b/api/src/airports/model/airport.rs @@ -489,8 +489,6 @@ impl Airport { airport.into() }) .collect(); - Runway::insert_all(&all_runway_rows).await?; - Frequency::insert_all(&all_frequency_rows).await?; for chunk in airport_rows.chunks(chunk_size) { let mut query_builder: QueryBuilder = QueryBuilder::new( @@ -519,6 +517,9 @@ impl Airport { query.execute(pool).await?; } + Runway::insert_all(&all_runway_rows).await?; + Frequency::insert_all(&all_frequency_rows).await?; + Ok(()) } @@ -577,7 +578,7 @@ impl Airport { column: &str, field: &'a Option, ) { - if let Some(ref value_str) = field { + if let Some(value_str) = field { // Split on commas, trim whitespace, and drop empties. let values: Vec<&str> = value_str .split(',') @@ -606,7 +607,7 @@ impl Airport { field: &'a Option, ) { // Query column like - if let Some(ref value) = field { + if let Some(value) = field { if !*has_where { builder.push(" WHERE "); *has_where = true; @@ -627,7 +628,7 @@ impl Airport { field: &'a Option, ) -> ApiResult<()> { // Query bounds - if let Some(ref bounds_string) = field { + if let Some(bounds_string) = field { if !*has_where { builder.push(" WHERE "); *has_where = true; diff --git a/api/src/main.rs b/api/src/main.rs index 6e1aec7..c7d74f5 100644 --- a/api/src/main.rs +++ b/api/src/main.rs @@ -4,6 +4,7 @@ use actix_cors::Cors; use actix_web::{App, HttpServer, middleware::Logger, web}; use dotenv::from_filename; use reqwest::Certificate; +use uuid::Uuid; use crate::account::hash; use crate::users::{User, ADMIN_ROLE}; @@ -43,10 +44,12 @@ async fn main() -> Result<(), Box> { } let admin_user = User { email, + email_verified: true, password_hash, role: ADMIN_ROLE.to_string(), first_name: "Admin".to_string(), last_name: "".to_string(), + avatar: None, updated_at: Default::default(), created_at: Default::default(), }; diff --git a/api/src/users/model.rs b/api/src/users/model.rs index 8d89c20..fef8b07 100644 --- a/api/src/users/model.rs +++ b/api/src/users/model.rs @@ -21,9 +21,8 @@ impl RegisterRequest { pub fn to_user(self) -> ApiResult { let password_hash = hash(&self.password)?; Ok(User { - id: Uuid::new_v4(), email: self.email.to_lowercase(), - emailVerified: false, + email_verified: false, password_hash, role: USER_ROLE.to_string(), first_name: self.first_name, @@ -43,7 +42,6 @@ pub struct LoginRequest { #[derive(Debug, Serialize)] pub struct UserResponse { - pub id: Uuid, pub email_verified: bool, pub role: String, pub first_name: String, @@ -55,8 +53,7 @@ pub struct UserResponse { impl From for UserResponse { fn from(user: User) -> Self { UserResponse { - id: user.id, - email_verified: user.emailVerified, + email_verified: user.email_verified, role: user.role, first_name: user.first_name, last_name: user.last_name, @@ -67,8 +64,8 @@ impl From for UserResponse { #[derive(Debug, Deserialize, sqlx::FromRow)] pub struct UpdateUser { - pub id: Uuid, pub email: Option, + pub email_verified: Option, pub password: Option, pub role: Option, pub first_name: Option, @@ -98,6 +95,11 @@ impl UpdateUser { query_builder.push("email = "); query_builder.push_bind(email); } + if let Some(ref email_verified) = self.email_verified { + push_comma(&mut query_builder); + query_builder.push("email_verified = "); + query_builder.push_bind(email_verified); + } if let Some(ref password) = self.password { push_comma(&mut query_builder); let password_hash = hash(password)?; @@ -119,6 +121,11 @@ impl UpdateUser { query_builder.push("last_name = "); query_builder.push_bind(last_name); } + if let Some(ref avatar) = self.avatar { + push_comma(&mut query_builder); + query_builder.push("avatar = "); + query_builder.push_bind(avatar); + } push_comma(&mut query_builder); query_builder.push("updated_at = "); query_builder.push_bind(Utc::now()); @@ -136,9 +143,8 @@ impl UpdateUser { #[derive(Debug, Serialize, Deserialize, sqlx::FromRow)] pub struct User { - pub id: Uuid, pub email: String, - pub emailVerified: bool, + pub email_verified: bool, pub password_hash: String, pub role: String, pub first_name: String, @@ -188,23 +194,27 @@ impl User { r#" INSERT INTO {} ( email, + email_verified, password_hash, role, first_name, last_name, + avatar, created_at, updated_at ) - VALUES ($1, $2, $3, $4, $5, $6, $7) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) RETURNING * "#, TABLE_NAME, )) .bind(&self.email) + .bind(&self.email_verified) .bind(&self.password_hash) .bind(&self.role) .bind(&self.first_name) .bind(&self.last_name) + .bind(&self.avatar) .bind(self.created_at) .bind(self.updated_at) .fetch_one(pool)