From ea98d5625a5319163814fc09ce26e987d1dd36d4 Mon Sep 17 00:00:00 2001 From: rsgl Date: Sun, 17 Nov 2024 15:40:12 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E7=94=A8=E6=88=B7=E8=A1=A8?= =?UTF-8?q?=E7=9A=84=E5=88=9D=E5=A7=8B=E5=8C=96=20SQL=20=E8=84=9A=E6=9C=AC?= =?UTF-8?q?=EF=BC=8C=E9=87=8D=E6=9E=84=E7=94=A8=E6=88=B7=E6=A8=A1=E5=9E=8B?= =?UTF-8?q?=EF=BC=8C=E6=9B=B4=E6=96=B0=E7=94=A8=E6=88=B7=E8=BE=93=E5=85=A5?= =?UTF-8?q?=E6=A8=A1=E5=9E=8B=EF=BC=8C=E4=BC=98=E5=8C=96=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E5=AD=98=E5=82=A8=E5=BA=93=E5=92=8C=E6=9C=8D=E5=8A=A1=E4=BB=A5?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E6=96=B0=E7=94=A8=E6=88=B7=E6=B3=A8=E5=86=8C?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- init.sql | 29 ++++++++++ src/models/user.rs | 13 +++-- src/models/user_input.rs | 3 +- src/repositories/user_repository.rs | 83 ++++++++++++++++++----------- src/services/user_service.rs | 32 +++++------ 5 files changed, 106 insertions(+), 54 deletions(-) create mode 100644 init.sql diff --git a/init.sql b/init.sql new file mode 100644 index 0000000..1cdb9fa --- /dev/null +++ b/init.sql @@ -0,0 +1,29 @@ +CREATE TABLE users ( + id INT AUTO_INCREMENT PRIMARY KEY, + account VARCHAR(255) UNIQUE NOT NULL, + name VARCHAR(255) NOT NULL, + birth DATE, + email VARCHAR(255), + password VARCHAR(255) NOT NULL, + phone VARCHAR(20), + status ENUM( + 'active', + 'inactive', + 'suspended', + 'deleted', + 'locked', + 'pending verfication' + ) DEFAULT 'active', + created_time DATETIME DEFAULT CURRENT_TIMESTAMP, + updated_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP +); + +INSERT INTO + test_server.users (id, account, name, birth, password) +VALUES + (0, '123', 'hyh', '2000-0-03', '1'); + +INSERT INTO + test_server.users (account, name, password) +VALUES + ('123', 'hyh', '1'); \ No newline at end of file diff --git a/src/models/user.rs b/src/models/user.rs index f3d9d8f..9283bc6 100644 --- a/src/models/user.rs +++ b/src/models/user.rs @@ -1,8 +1,13 @@ #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] pub struct User { pub id: Option, - pub name: String, - pub age: i32, - pub email: String, - pub password: String, + pub account: Option, + pub name: Option, + pub birth: Option, + pub email: Option, + pub password: Option, + pub phone: Option, + pub status: Option, + pub created_time: Option, + pub updated_time: Option, } diff --git a/src/models/user_input.rs b/src/models/user_input.rs index 68857cf..33bd787 100644 --- a/src/models/user_input.rs +++ b/src/models/user_input.rs @@ -1,7 +1,6 @@ #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] pub struct UserInput { + pub account: Option, pub name: Option, - pub age: Option, - pub email: Option, pub password: Option, } diff --git a/src/repositories/user_repository.rs b/src/repositories/user_repository.rs index 5c5ef96..b504f54 100644 --- a/src/repositories/user_repository.rs +++ b/src/repositories/user_repository.rs @@ -1,10 +1,11 @@ -use crate::models::user::User; use mysql::prelude::Queryable; use mysql::{params, Error as MysqlError}; use r2d2::{Error as R2D2Error, Pool}; use r2d2_mysql::MySqlConnectionManager; use thiserror::Error; +use crate::models::user::User; + #[derive(Error, Debug)] pub enum UserRepositoryError { #[error("mysql error: {0}")] @@ -26,22 +27,57 @@ impl UserRepository { /** * 新建用户 */ - pub fn create_user(&self, user: &User) -> Result<(), UserRepositoryError> { - let mut conn = self.pool.get().unwrap(); - let sql = r"INSERT INTO users (id, name, age, email, password) VALUES (:id, :name, :age, :email, :password)"; + pub fn insert_user( + &self, + account: &str, + name: &str, + password: &str, + ) -> Result<(), UserRepositoryError> { + let mut conn = self.pool.get().map_err(UserRepositoryError::PoolError)?; + let sql = "INSERT INTO users (account, name, password) VALUES (:account, :name, :password)"; conn.exec_drop( sql, - params! { - "id" => &user.id, - "name" => &user.name, - "age" => &user.age, - "email" => &user.email, - "password" => &user.password, - }, - )?; + params! {"account" => account, "name" => name, "password" => password}, + ) + .map_err(UserRepositoryError::MySqlError)?; Ok(()) } + /** + * 根据account查询用户 + */ + pub fn query_user_by_account( + &self, + account: &str, + ) -> Result, UserRepositoryError> { + let mut conn = self + .pool + .get() + .map_err(|e| UserRepositoryError::PoolError(e))?; + + let sql = "SELECT account, name FROM users WHERE account = :account"; + + match conn.exec_first(sql, params! {"account" => account}) { + Ok(Some(row)) => { + let (account, name) = mysql::from_row(row); + Ok(Some(User { + id: None, + name, + password: None, + account, + birth: None, + email: None, + phone: None, + status: None, + created_time: None, + updated_time: None, + })) + } + Ok(None) => Ok(None), + Err(e) => Err(UserRepositoryError::MySqlError(e)), + } + } + // /** // * 删除用户 // */ @@ -89,25 +125,11 @@ impl UserRepository { // ) // } - // /** - // * 根据ID查询用户 - // */ - // pub fn query_user_by_id(&mut self, id: i32) -> Result, mysql::Error> { - // let mut conn = self.pool.get().unwrap(); - // let result: Option = conn.exec_first( - // "SELECT id, name, age, email, password FROM users WHERE id = :id", - // params! { - // "id" => id, - // }, - // )?; - // Ok(result) - // } - // /** // * 根据用户名查询用户 // */ - // pub fn query_user_by_name(&mut self, name: &str) -> Result, mysql::Error> { - // let mut conn = self.pool.get().unwrap(); + // pub fn query_user_by_name(&self, name: &str) -> Result, UserRepositoryError> { + // let mut conn = self.pool.get().map_err(UserRepositoryError::PoolError)?; // conn.exec_first( // "SELECT id, name, age, email, password FROM users WHERE name = :name", // params! { @@ -119,8 +141,9 @@ impl UserRepository { // /** // * 根据邮箱查询用户 // */ - // pub fn query_user_by_email(&mut self, email: &str) -> Result, mysql::Error> { - // let mut conn = self.pool.get().unwrap(); + // pub fn query_user_by_email(&self, email: &str) -> Result, UserRepositoryError> { + // let mut conn = self.pool.get().map_err(UserRepositoryError::PoolError)?; + // conn.exec_first( // "SELECT id, name, age, email, password FROM users WHERE email = :email", // params! { diff --git a/src/services/user_service.rs b/src/services/user_service.rs index 249f4cf..64943b7 100644 --- a/src/services/user_service.rs +++ b/src/services/user_service.rs @@ -1,5 +1,5 @@ use crate::{ - models::{user::User, user_input::UserInput}, + models::user_input::UserInput, repositories::user_repository::{UserRepository, UserRepositoryError}, }; use bcrypt::{hash, DEFAULT_COST}; @@ -14,6 +14,9 @@ pub enum UserServiceError { #[error("Missing field: {0}")] MissingField(&'static str), + #[error("User already exists")] + UserAlreadyExists, + #[error("Password hashing failed: {0}")] HashError(#[from] bcrypt::BcryptError), } @@ -31,35 +34,28 @@ impl UserService { * 新建用户 */ pub fn create_user(&self, user: &UserInput) -> Result<(), UserServiceError> { + let account = user + .account + .as_ref() + .ok_or(UserServiceError::MissingField("account"))? + .to_string(); let name = user .name .as_ref() .ok_or(UserServiceError::MissingField("name"))? .to_string(); - let age = user - .age - .as_ref() - .ok_or(UserServiceError::MissingField("age"))?; - let email = user - .email - .as_ref() - .ok_or(UserServiceError::MissingField("email"))? - .to_string(); let password = user .password .as_ref() .ok_or(UserServiceError::MissingField("password"))? .to_string(); - let mut new_user = User { - id: Some(0), - name, - age: *age, - email, - password: hash(password, DEFAULT_COST).unwrap(), - }; + if self.repository.query_user_by_account(&account)?.is_some() { + return Err(UserServiceError::UserAlreadyExists); + } - self.repository.create_user(&mut new_user)?; + self.repository + .insert_user(&account, &name, &hash(password, DEFAULT_COST).unwrap())?; Ok(()) } }