| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125 |
- use uuid::Uuid;
- use chrono::{DateTime, Utc};
- use sqlx::{PgPool, FromRow};
- use serde::Serialize;
- use crate::http_error::HttpError;
- #[derive(FromRow)]
- pub struct User {
- pub id: Uuid,
- pub session_token: Uuid,
- pub name: String,
- pub email: String,
- pub pass_hash: String,
- pub tokens: i64,
- pub created_at: DateTime<Utc>
- }
- #[derive(Serialize)]
- pub struct ResponseUser {
- id: String,
- name: String,
- email: String,
- tokens: i64
- }
- impl User {
- pub fn new(name: String, email: String, pass_hash: String) -> Self {
- Self {
- id: Uuid::now_v7(),
- session_token: Uuid::new_v4(),
- name: name,
- email: email.to_lowercase(),
- pass_hash: pass_hash,
- tokens: 0,
- created_at: Utc::now()
- }
- }
- pub async fn insert_one(&self, db: &PgPool) -> Result<(), HttpError> {
- let result = sqlx::query(
- "INSERT into users(id, session_token, name, email, pass_hash, tokens, created_at)
- VALUES($1, $2, $3, $4, $5, $6, $7)"
- )
- .bind(&self.id)
- .bind(&self.session_token)
- .bind(&self.name)
- .bind(&self.email)
- .bind(&self.pass_hash)
- .bind(&self.tokens)
- .bind(&self.created_at)
- .execute(db)
- .await;
- match result {
- Ok(_) => Ok(()),
- Err(sqlx::Error::Database(db_err)) if db_err.code().as_deref() == Some("23505") => {
- Err(HttpError::InvalidInput("User with this email already exists".into()))
- },
- Err(e) => Err(HttpError::Database(e.into()))
- }
- }
- pub async fn find_one_by_session(
- db: &PgPool,
- user_id: Uuid,
- session_token: Uuid
- ) -> Result<User, HttpError> {
- let user = sqlx::query_as::<_, User>(
- "SELECT *
- FROM users
- WHERE id = $1
- and session_token = $2"
- )
- .bind(user_id)
- .bind(session_token)
- .fetch_optional(db)
- .await?;
- match user {
- Some(u) => Ok(u),
- None => Err(HttpError::Auth)
- }
- }
- pub async fn find_one_by_email(db: &PgPool, user_email: String) -> Result<User, HttpError> {
- let email = user_email.to_lowercase();
- let user = sqlx::query_as::<_, User>(
- "SELECT *
- FROM users
- WHERE email = $1"
- )
- .bind(email)
- .fetch_optional(db)
- .await?;
- match user {
- Some(u) => Ok(u),
- _ => Err(HttpError::NotFound("Invalid email/password combination".into()))
- }
- }
- pub async fn add_tokens(db: &PgPool, user: Uuid, new_tokens: i32) -> Result<(), HttpError> {
- sqlx::query(
- "UPDATE users
- SET tokens = tokens + $1
- WHERE id = $2"
- )
- .bind(new_tokens)
- .bind(user)
- .execute(db)
- .await?;
- Ok(())
- }
- pub fn response(self) -> ResponseUser {
- ResponseUser {
- id: self.id.to_string(),
- name: self.name,
- email: self.email,
- tokens: self.tokens
- }
- }
- }
|