添加用户表的初始化 SQL 脚本,重构用户模型,更新用户输入模型,优化用户存储库和服务以支持新用户注册功能
This commit is contained in:
parent
c49734430b
commit
ea98d5625a
29
init.sql
Normal file
29
init.sql
Normal 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');
|
||||||
@ -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>,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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>,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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! {
|
||||||
|
|||||||
@ -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(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user