添加用户表的初始化 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)]
pub struct User {
pub id: Option<i32>,
pub name: String,
pub age: i32,
pub email: String,
pub password: String,
pub account: Option<String>,
pub name: Option<String>,
pub birth: Option<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)]
pub struct UserInput {
pub account: Option<String>,
pub name: Option<String>,
pub age: Option<i32>,
pub email: Option<String>,
pub password: Option<String>,
}

View File

@ -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<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> {
// let mut conn = self.pool.get().unwrap();
// pub fn query_user_by_name(&self, name: &str) -> Result<Option<User>, 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<Option<User>, mysql::Error> {
// let mut conn = self.pool.get().unwrap();
// pub fn query_user_by_email(&self, email: &str) -> Result<Option<User>, 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! {

View File

@ -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(())
}
}