添加用户表的初始化 SQL 脚本,重构用户模型,更新用户输入模型,优化用户存储库和服务以支持新用户注册功能

This commit is contained in:
rsgl 2024-11-17 15:40:12 +08:00
parent c49734430b
commit ea98d5625a
5 changed files with 106 additions and 54 deletions

29
init.sql Normal file
View File

@ -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');

View File

@ -1,8 +1,13 @@
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct User { pub struct User {
pub id: Option<i32>, pub id: Option<i32>,
pub name: String, pub account: Option<String>,
pub age: i32, pub name: Option<String>,
pub email: String, pub birth: Option<String>,
pub password: String, pub email: Option<String>,
pub password: Option<String>,
pub phone: Option<String>,
pub status: Option<String>,
pub created_time: Option<String>,
pub updated_time: Option<String>,
} }

View File

@ -1,7 +1,6 @@
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct UserInput { pub struct UserInput {
pub account: Option<String>,
pub name: Option<String>, pub name: Option<String>,
pub age: Option<i32>,
pub email: Option<String>,
pub password: Option<String>, pub password: Option<String>,
} }

View File

@ -1,10 +1,11 @@
use crate::models::user::User;
use mysql::prelude::Queryable; use mysql::prelude::Queryable;
use mysql::{params, Error as MysqlError}; use mysql::{params, Error as MysqlError};
use r2d2::{Error as R2D2Error, Pool}; use r2d2::{Error as R2D2Error, Pool};
use r2d2_mysql::MySqlConnectionManager; use r2d2_mysql::MySqlConnectionManager;
use thiserror::Error; use thiserror::Error;
use crate::models::user::User;
#[derive(Error, Debug)] #[derive(Error, Debug)]
pub enum UserRepositoryError { pub enum UserRepositoryError {
#[error("mysql error: {0}")] #[error("mysql error: {0}")]
@ -26,22 +27,57 @@ impl UserRepository {
/** /**
* *
*/ */
pub fn create_user(&self, user: &User) -> Result<(), UserRepositoryError> { pub fn insert_user(
let mut conn = self.pool.get().unwrap(); &self,
let sql = r"INSERT INTO users (id, name, age, email, password) VALUES (:id, :name, :age, :email, :password)"; 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( conn.exec_drop(
sql, sql,
params! { params! {"account" => account, "name" => name, "password" => password},
"id" => &user.id, )
"name" => &user.name, .map_err(UserRepositoryError::MySqlError)?;
"age" => &user.age,
"email" => &user.email,
"password" => &user.password,
},
)?;
Ok(()) Ok(())
} }
/**
* account查询用户
*/
pub fn query_user_by_account(
&self,
account: &str,
) -> Result<Option<User>, 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<Option<User>, mysql::Error> {
// let mut conn = self.pool.get().unwrap();
// let result: Option<User> = 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<Option<User>, mysql::Error> { // pub fn query_user_by_name(&self, name: &str) -> Result<Option<User>, UserRepositoryError> {
// let mut conn = self.pool.get().unwrap(); // let mut conn = self.pool.get().map_err(UserRepositoryError::PoolError)?;
// conn.exec_first( // conn.exec_first(
// "SELECT id, name, age, email, password FROM users WHERE name = :name", // "SELECT id, name, age, email, password FROM users WHERE name = :name",
// params! { // params! {
@ -119,8 +141,9 @@ impl UserRepository {
// /** // /**
// * 根据邮箱查询用户 // * 根据邮箱查询用户
// */ // */
// pub fn query_user_by_email(&mut self, email: &str) -> Result<Option<User>, mysql::Error> { // pub fn query_user_by_email(&self, email: &str) -> Result<Option<User>, UserRepositoryError> {
// let mut conn = self.pool.get().unwrap(); // let mut conn = self.pool.get().map_err(UserRepositoryError::PoolError)?;
// conn.exec_first( // conn.exec_first(
// "SELECT id, name, age, email, password FROM users WHERE email = :email", // "SELECT id, name, age, email, password FROM users WHERE email = :email",
// params! { // params! {

View File

@ -1,5 +1,5 @@
use crate::{ use crate::{
models::{user::User, user_input::UserInput}, models::user_input::UserInput,
repositories::user_repository::{UserRepository, UserRepositoryError}, repositories::user_repository::{UserRepository, UserRepositoryError},
}; };
use bcrypt::{hash, DEFAULT_COST}; use bcrypt::{hash, DEFAULT_COST};
@ -14,6 +14,9 @@ pub enum UserServiceError {
#[error("Missing field: {0}")] #[error("Missing field: {0}")]
MissingField(&'static str), MissingField(&'static str),
#[error("User already exists")]
UserAlreadyExists,
#[error("Password hashing failed: {0}")] #[error("Password hashing failed: {0}")]
HashError(#[from] bcrypt::BcryptError), HashError(#[from] bcrypt::BcryptError),
} }
@ -31,35 +34,28 @@ impl UserService {
* *
*/ */
pub fn create_user(&self, user: &UserInput) -> Result<(), UserServiceError> { 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 let name = user
.name .name
.as_ref() .as_ref()
.ok_or(UserServiceError::MissingField("name"))? .ok_or(UserServiceError::MissingField("name"))?
.to_string(); .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 let password = user
.password .password
.as_ref() .as_ref()
.ok_or(UserServiceError::MissingField("password"))? .ok_or(UserServiceError::MissingField("password"))?
.to_string(); .to_string();
let mut new_user = User { if self.repository.query_user_by_account(&account)?.is_some() {
id: Some(0), return Err(UserServiceError::UserAlreadyExists);
name, }
age: *age,
email,
password: hash(password, DEFAULT_COST).unwrap(),
};
self.repository.create_user(&mut new_user)?; self.repository
.insert_user(&account, &name, &hash(password, DEFAULT_COST).unwrap())?;
Ok(()) Ok(())
} }
} }