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