用户表 ID 改为 UUID V7 并由业务层生成
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
-- 用户主表
|
-- 用户主表
|
||||||
CREATE TABLE IF NOT EXISTS user_main (
|
CREATE TABLE IF NOT EXISTS user_main (
|
||||||
id BIGSERIAL PRIMARY KEY,
|
id UUID PRIMARY KEY,
|
||||||
deleted BOOLEAN NOT NULL DEFAULT FALSE,
|
deleted BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
createdate TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
createdate TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
modifydate TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP
|
modifydate TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||||
@@ -8,8 +8,8 @@ CREATE TABLE IF NOT EXISTS user_main (
|
|||||||
|
|
||||||
-- 用户登录账号表
|
-- 用户登录账号表
|
||||||
CREATE TABLE IF NOT EXISTS user_login_account (
|
CREATE TABLE IF NOT EXISTS user_login_account (
|
||||||
id BIGSERIAL PRIMARY KEY,
|
id UUID PRIMARY KEY,
|
||||||
user_id BIGINT NOT NULL,
|
user_id UUID NOT NULL,
|
||||||
account VARCHAR(100) NOT NULL,
|
account VARCHAR(100) NOT NULL,
|
||||||
deleted BOOLEAN NOT NULL DEFAULT FALSE,
|
deleted BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
createdate TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
createdate TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
@@ -23,8 +23,8 @@ CREATE UNIQUE INDEX IF NOT EXISTS idx_user_login_account_active
|
|||||||
|
|
||||||
-- 用户密码表
|
-- 用户密码表
|
||||||
CREATE TABLE IF NOT EXISTS user_login_password (
|
CREATE TABLE IF NOT EXISTS user_login_password (
|
||||||
id BIGSERIAL PRIMARY KEY,
|
id UUID PRIMARY KEY,
|
||||||
user_id BIGINT NOT NULL,
|
user_id UUID NOT NULL,
|
||||||
password VARCHAR(255) NOT NULL,
|
password VARCHAR(255) NOT NULL,
|
||||||
deleted BOOLEAN NOT NULL DEFAULT FALSE,
|
deleted BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
createdate TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
createdate TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
@@ -39,13 +39,13 @@ CREATE INDEX IF NOT EXISTS idx_user_login_password_user_id
|
|||||||
-- bcrypt hash: $2b$12$REwMlLDCbzR4UpL6MWnzE.AacihwpFvQhGs7vDKTwwyNMb1qBWOTm
|
-- bcrypt hash: $2b$12$REwMlLDCbzR4UpL6MWnzE.AacihwpFvQhGs7vDKTwwyNMb1qBWOTm
|
||||||
DO $$
|
DO $$
|
||||||
DECLARE
|
DECLARE
|
||||||
v_user_id BIGINT;
|
v_user_id UUID := '018fa3e0-7e5c-7aaa-8b1d-9f6e4c3b2a10'::UUID;
|
||||||
BEGIN
|
BEGIN
|
||||||
INSERT INTO user_main DEFAULT VALUES RETURNING id INTO v_user_id;
|
INSERT INTO user_main (id) VALUES (v_user_id);
|
||||||
|
|
||||||
INSERT INTO user_login_account (user_id, account)
|
INSERT INTO user_login_account (id, user_id, account)
|
||||||
VALUES (v_user_id, 'admin');
|
VALUES ('018fa3e0-7e5c-7bbb-8b1d-9f6e4c3b2a10'::UUID, v_user_id, 'admin');
|
||||||
|
|
||||||
INSERT INTO user_login_password (user_id, password)
|
INSERT INTO user_login_password (id, user_id, password)
|
||||||
VALUES (v_user_id, '$2b$12$REwMlLDCbzR4UpL6MWnzE.AacihwpFvQhGs7vDKTwwyNMb1qBWOTm');
|
VALUES ('018fa3e0-7e5c-7ccc-8b1d-9f6e4c3b2a10'::UUID, v_user_id, '$2b$12$REwMlLDCbzR4UpL6MWnzE.AacihwpFvQhGs7vDKTwwyNMb1qBWOTm');
|
||||||
END $$;
|
END $$;
|
||||||
|
|||||||
@@ -14,7 +14,10 @@ serde = { version = "1.0", features = ["derive"] }
|
|||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
|
|
||||||
# 数据库
|
# 数据库
|
||||||
sqlx = { version = "0.8", features = ["runtime-tokio", "tls-rustls", "postgres", "chrono"] }
|
sqlx = { version = "0.8", features = ["runtime-tokio", "tls-rustls", "postgres", "chrono", "uuid"] }
|
||||||
|
|
||||||
|
# UUID
|
||||||
|
uuid = { version = "1", features = ["v7", "serde"] }
|
||||||
|
|
||||||
# Redis
|
# Redis
|
||||||
redis = { version = "0.29", features = ["tokio-comp"] }
|
redis = { version = "0.29", features = ["tokio-comp"] }
|
||||||
|
|||||||
@@ -11,7 +11,10 @@ tower = "0.5"
|
|||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
|
|
||||||
sqlx = { version = "0.8", features = ["runtime-tokio", "tls-rustls", "postgres", "chrono"] }
|
sqlx = { version = "0.8", features = ["runtime-tokio", "tls-rustls", "postgres", "chrono", "uuid"] }
|
||||||
|
|
||||||
|
# UUID
|
||||||
|
uuid = { version = "1", features = ["v7", "serde"] }
|
||||||
redis = { version = "0.29", features = ["tokio-comp"] }
|
redis = { version = "0.29", features = ["tokio-comp"] }
|
||||||
|
|
||||||
bcrypt = "0.17"
|
bcrypt = "0.17"
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ use sqlx::PgPool;
|
|||||||
use std::env;
|
use std::env;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tracing::{info, warn};
|
use tracing::{info, warn};
|
||||||
|
use uuid::Uuid;
|
||||||
use validator::Validate;
|
use validator::Validate;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@@ -31,7 +32,7 @@ struct RegisterRequest {
|
|||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
struct RegisterResponse {
|
struct RegisterResponse {
|
||||||
success: bool,
|
success: bool,
|
||||||
user_id: Option<i64>,
|
user_id: Option<Uuid>,
|
||||||
message: String,
|
message: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,7 +90,7 @@ async fn register_handler(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 检查账号是否已存在
|
// 检查账号是否已存在
|
||||||
let existing: Option<(i64,)> = sqlx::query_as(
|
let existing: Option<(Uuid,)> = sqlx::query_as(
|
||||||
"SELECT id FROM user_login_account WHERE account = $1 AND deleted = FALSE"
|
"SELECT id FROM user_login_account WHERE account = $1 AND deleted = FALSE"
|
||||||
)
|
)
|
||||||
.bind(&payload.username)
|
.bind(&payload.username)
|
||||||
@@ -140,32 +141,33 @@ async fn register_handler(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let result: Result<(i64,), sqlx::Error> = sqlx::query_as(
|
let user_id = Uuid::now_v7();
|
||||||
"INSERT INTO user_main DEFAULT VALUES RETURNING id"
|
|
||||||
)
|
|
||||||
.fetch_one(&mut *tx)
|
|
||||||
.await;
|
|
||||||
|
|
||||||
let user_id = match result {
|
|
||||||
Ok((id,)) => id,
|
|
||||||
Err(e) => {
|
|
||||||
warn!("Insert user_main failed: {}", e);
|
|
||||||
let _ = tx.rollback().await;
|
|
||||||
return (
|
|
||||||
StatusCode::INTERNAL_SERVER_ERROR,
|
|
||||||
Json(RegisterResponse {
|
|
||||||
success: false,
|
|
||||||
user_id: None,
|
|
||||||
message: "Registration failed".to_string(),
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Err(e) = sqlx::query(
|
if let Err(e) = sqlx::query(
|
||||||
"INSERT INTO user_login_account (user_id, account) VALUES ($1, $2)"
|
"INSERT INTO user_main (id) VALUES ($1)"
|
||||||
)
|
)
|
||||||
.bind(user_id)
|
.bind(user_id)
|
||||||
|
.execute(&mut *tx)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
warn!("Insert user_main failed: {}", e);
|
||||||
|
let _ = tx.rollback().await;
|
||||||
|
return (
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
Json(RegisterResponse {
|
||||||
|
success: false,
|
||||||
|
user_id: None,
|
||||||
|
message: "Registration failed".to_string(),
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let account_id = Uuid::now_v7();
|
||||||
|
if let Err(e) = sqlx::query(
|
||||||
|
"INSERT INTO user_login_account (id, user_id, account) VALUES ($1, $2, $3)"
|
||||||
|
)
|
||||||
|
.bind(account_id)
|
||||||
|
.bind(user_id)
|
||||||
.bind(&payload.username)
|
.bind(&payload.username)
|
||||||
.execute(&mut *tx)
|
.execute(&mut *tx)
|
||||||
.await
|
.await
|
||||||
@@ -182,9 +184,11 @@ async fn register_handler(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let password_id = Uuid::now_v7();
|
||||||
if let Err(e) = sqlx::query(
|
if let Err(e) = sqlx::query(
|
||||||
"INSERT INTO user_login_password (user_id, password) VALUES ($1, $2)"
|
"INSERT INTO user_login_password (id, user_id, password) VALUES ($1, $2, $3)"
|
||||||
)
|
)
|
||||||
|
.bind(password_id)
|
||||||
.bind(user_id)
|
.bind(user_id)
|
||||||
.bind(&password_hash)
|
.bind(&password_hash)
|
||||||
.execute(&mut *tx)
|
.execute(&mut *tx)
|
||||||
|
|||||||
Reference in New Issue
Block a user