add: user accomplished

This commit is contained in:
wwweww
2026-02-27 05:42:13 +08:00
parent 659168fe32
commit a0c720eb2f
90 changed files with 9592 additions and 1180 deletions
+17
View File
@@ -7,6 +7,10 @@ info (
)
type (
EmptyResp {}
ForgotPasswordReq {
Email string `json:"email"`
}
SendVerificationCodeReq {
Email string `json:"email" binding:"required,email"`
Scene string `json:"scene" binding:"required,oneof=register login reset_password bind_email"`
@@ -30,5 +34,18 @@ service email-api {
)
@handler SendVerificationCode
post /verification-code/send (SendVerificationCodeReq) returns (SendVerificationCodeResp)
}
@server (
group: user
prefix: /api/v1/auth
)
service email-api {
@doc "忘记密码-发送验证码"
@handler ForgotPassword
post /forgot-password/send (ForgotPasswordReq) returns (EmptyResp)
}
+149 -111
View File
@@ -1,126 +1,164 @@
syntax = "v1"
info (
author: "Asadz"
date: "2024-06-19"
version: "1.0"
info(
author: "Asadz"
date: "2024-06-19"
version: "1.0"
)
type (
RegisterReq {
Username string `json:"username" binding:"required,min=3,max=50"`
Password string `json:"password" binding:"required,min=6,max=128"`
Email string `json:"email,omitempty" binding:"omitempty,email"`
Phone string `json:"phone,omitempty" binding:"omitempty,len=11"`
Vcode int32 `json:"vcode"`
}
RegisterResp {
UserId int64 `json:"userId"`
Username string `json:"username"`
Email string `json:"email"`
Message string `json:"message"`
}
LoginReq {
Username string `json:"username" binding:"required"`
Password string `json:"password" binding:"required"`
}
LoginResp {
UserId int64 `json:"userId"`
Username string `json:"username"`
Email string `json:"email"`
Token string `json:"token"`
Expires int64 `json:"expires"`
}
GetUserInfoReq {
UserId int64 `path:"userId" binding:"required,gt=0"`
}
UserInfo {
UserId int64 `json:"userId"`
Username string `json:"username"`
Email string `json:"email"`
Phone string `json:"phone"`
Avatar string `json:"avatar"`
Status int `json:"status"`
CreateAt int64 `json:"createAt"`
UpdateAt int64 `json:"updateAt"`
}
UpdateUserInfoReq {
UserId int64 `path:"userId" binding:"required,gt=0"`
Email string `json:"email" binding:"omitempty,email"`
Phone string `json:"phone" binding:"omitempty,len=11"`
Avatar string `json:"avatar" binding:"omitempty,url"`
}
UpdateUserInfoResp {
UserId int64 `json:"userId"`
Message string `json:"message"`
}
UpdatePasswordReq {
UserId int64 `path:"userId" binding:"required,gt=0"`
OldPassword string `json:"oldPassword" binding:"required"`
NewPassword string `json:"newPassword" binding:"required,min=6,max=128"`
}
UpdatePasswordResp {
Message string `json:"message"`
}
LogoutReq {
UserId int64 `path:"userId" binding:"required,gt=0"`
Token string `header:"Authorization" binding:"required"`
}
LogoutResp {
Message string `json:"message"`
}
ErrorResp {
Code int `json:"code"`
Message string `json:"message"`
}
EmptyResp {
}
SearchUserResp {
Username string `json:"username"`
UserId int64 `json:"userId"`
Nickname string `json:"nickname"`
Avatar string `json:"avatar"`
Bio string `json:"bio"`
Page int64 `json:"page"`
Limit int64 `json:"limit"`
}
ResetPasswordByVcode {
Email string `json:"email"`
Password string `json:"password"`
Vcode string `json:"vcode"`
}
RegisterReq {
Username string `json:"username" binding:"required,min=3,max=50"`
Password string `json:"password" binding:"required,min=6,max=128"`
Email string `json:"email,omitempty" binding:"omitempty,email"`
Phone string `json:"phone,omitempty" binding:"omitempty,len=11"`
Vcode int32 `json:"vcode"`
}
RegisterResp {
UserId int64 `json:"userId"`
Username string `json:"username"`
Email string `json:"email"`
Message string `json:"message"`
}
LoginReq {
Username string `json:"username" binding:"required"`
Password string `json:"password" binding:"required"`
}
LoginResp {
UserId int64 `json:"userId"`
Username string `json:"username"`
Email string `json:"email"`
Token string `json:"token"`
Expires int64 `json:"expires"`
}
GetUserInfoReq {
UserId int64 `path:"userId" binding:"required,gt=0"`
}
UserInfo {
UserId int64 `json:"userId"`
Username string `json:"username"`
Email string `json:"email"`
Phone string `json:"phone"`
Avatar string `json:"avatar"`
Status int `json:"status"`
CreateAt int64 `json:"createAt"`
UpdateAt int64 `json:"updateAt"`
}
UpdateUserInfoReq {
Nickname *string `json:"nickname,omitempty"`
Avatar *string `json:"avatar,omitempty"`
Bio *string `json:"bio,omitempty"`
}
UpdateUserInfoResp {
UserId int64 `json:"userId"`
Message string `json:"message"`
}
UpdatePasswordReq {
UserId int64 `path:"userId" binding:"required,gt=0"`
OldPassword string `json:"oldPassword" binding:"required"`
NewPassword string `json:"newPassword" binding:"required,min=6,max=128"`
}
UpdatePasswordResp {
Message string `json:"message"`
}
LogoutReq {
UserId int64 `path:"userId" binding:"required,gt=0"`
Token string `header:"Authorization" binding:"required"`
}
LogoutResp {
Message string `json:"message"`
}
ErrorResp {
Code int `json:"code"`
Message string `json:"message"`
}
)
@server (
group: user
prefix: /api/users
middleware: Logger
@server(
group: user
prefix: /api/v1/auth
middleware: Logger
)
service user-api {
@doc (
summary: "用户注册接口"
description: "通过用户名、密码、邮箱、电话号码注册新用户账户"
)
@handler Register
post /register (RegisterReq) returns (RegisterResp)
@doc(
summary: "用户注册接口"
description: "通过用户名、密码、邮箱、电话号码注册新用户账户"
)
@handler Register
post /register (RegisterReq) returns (RegisterResp)
@doc (
summary: "用户登录接口"
description: "使用用户名和密码进行登录,返回访问令牌和用户信息"
)
@handler Login
post /login (LoginReq) returns (LoginResp)
@doc(
summary: "用户登录接口"
description: "使用用户名和密码进行登录,返回访问令牌和用户信息"
)
@handler Login
post /login (LoginReq) returns (LoginResp)
@doc (
summary: "获取用户信息"
description: "根据用户ID获取用户的详细信息,包含个人资料和账户状态"
)
@handler GetUserInfo
get /:userId (GetUserInfoReq) returns (UserInfo)
@doc(
summary: "修改用户密码"
description: "验证旧密码后修改为新密码,需要提供原密码"
)
@handler UpdatePassword
put /:userId/password (UpdatePasswordReq) returns (UpdatePasswordResp)
@doc (
summary: "修改用户信息"
description: "修改用户的邮箱、电话号码、头像等信息"
)
@handler UpdateUserInfo
put /:userId (UpdateUserInfoReq) returns (UpdateUserInfoResp)
@doc(
summary: "用户登出"
description: "需要携带 Authorization 令牌,清除用户会话并使令牌失效"
)
@handler Logout
post /:userId/logout (LogoutReq) returns (LogoutResp)
@doc (
summary: "修改用户密码"
description: "验证旧密码后修改为新密码,需要提供原密码"
)
@handler UpdatePassword
put /:userId/password (UpdatePasswordReq) returns (UpdatePasswordResp)
@doc (
summary: "用户登出"
description: "需要携带 Authorization 令牌,清除用户会话并使令牌失效"
)
@handler Logout
post /:userId/logout (LogoutReq) returns (LogoutResp)
@doc "修改密码-使用验证码"
@handler UpdatePasswordByVcode
put /forgot-password/reset (ResetPasswordByVcode) returns (EmptyResp)
}
@server(
group: user
prefix: /api/v1/user
middleware: Logger
)
service user-api {
@doc "获取当前登录用户信息"
@handler GetMe
get /me returns (UserInfo)
@doc "通过用户名搜索用户"
@handler SearchUsersByUsername
get /search () returns ([]UserInfo)
@doc "更改当前登录用户信息"
@handler UpdateMe
put /me (UpdateUserInfoReq) returns (UserInfo)
@doc(
summary: "获取用户信息"
description: "根据用户ID获取用户的详细信息,包含个人资料和账户状态"
)
@handler GetUserInfo
get /:userId (GetUserInfoReq) returns (UserInfo)
@doc(
summary: "修改用户信息"
description: "修改用户的邮箱、电话号码、头像等信息"
)
@handler UpdateUserInfo
put /:userId (UpdateUserInfoReq) returns (UpdateUserInfoResp)
}
+105
View File
@@ -0,0 +1,105 @@
syntax = "proto3";
option go_package ="./pb";
package pb;
// ------------------------------------
// Messages
// ------------------------------------
//--------------------------------userVerifications--------------------------------
message UserVerifications {
int64 id = 1; //id
int64 userId = 2; //userId
string role = 3; //role
string status = 4; //status
string materials = 5; //materials
string rejectReason = 6; //rejectReason
int64 reviewedBy = 7; //reviewedBy
int64 reviewedAt = 8; //reviewedAt
int64 createdAt = 9; //createdAt
int64 updatedAt = 10; //updatedAt
}
message AddUserVerificationsReq {
int64 userId = 1; //userId
string role = 2; //role
string status = 3; //status
string materials = 4; //materials
string rejectReason = 5; //rejectReason
int64 reviewedBy = 6; //reviewedBy
int64 reviewedAt = 7; //reviewedAt
int64 createdAt = 8; //createdAt
int64 updatedAt = 9; //updatedAt
}
message AddUserVerificationsResp {
}
message UpdateUserVerificationsReq {
int64 id = 1; //id
int64 userId = 2; //userId
string role = 3; //role
string status = 4; //status
string materials = 5; //materials
string rejectReason = 6; //rejectReason
int64 reviewedBy = 7; //reviewedBy
int64 reviewedAt = 8; //reviewedAt
int64 createdAt = 9; //createdAt
int64 updatedAt = 10; //updatedAt
}
message UpdateUserVerificationsResp {
}
message DelUserVerificationsReq {
int64 id = 1; //id
}
message DelUserVerificationsResp {
}
message GetUserVerificationsByIdReq {
int64 id = 1; //id
}
message GetUserVerificationsByIdResp {
UserVerifications userVerifications = 1; //userVerifications
}
message SearchUserVerificationsReq {
int64 page = 1; //page
int64 limit = 2; //limit
int64 id = 3; //id
int64 userId = 4; //userId
string role = 5; //role
string status = 6; //status
string materials = 7; //materials
string rejectReason = 8; //rejectReason
int64 reviewedBy = 9; //reviewedBy
int64 reviewedAt = 10; //reviewedAt
int64 createdAt = 11; //createdAt
int64 updatedAt = 12; //updatedAt
}
message SearchUserVerificationsResp {
repeated UserVerifications userVerifications = 1; //userVerifications
}
// ------------------------------------
// Rpc Func
// ------------------------------------
service user_verifications{
//-----------------------userVerifications-----------------------
rpc AddUserVerifications(AddUserVerificationsReq) returns (AddUserVerificationsResp);
rpc UpdateUserVerifications(UpdateUserVerificationsReq) returns (UpdateUserVerificationsResp);
rpc DelUserVerifications(DelUserVerificationsReq) returns (DelUserVerificationsResp);
rpc GetUserVerificationsById(GetUserVerificationsByIdReq) returns (GetUserVerificationsByIdResp);
rpc SearchUserVerifications(SearchUserVerificationsReq) returns (SearchUserVerificationsResp);
}
+75 -48
View File
@@ -8,50 +8,62 @@ package pb;
// Messages
// ------------------------------------
//--------------------------------users--------------------------------
//--------------------------------users--------------------------------
message Users {
int64 userId = 1; //userId
int64 id = 1; //id
string username = 2; //username
string passwd = 3; //passwd
string nickname = 4; //nickname
string phone = 5; //phone
int64 roleType = 6; //roleType
bool isVerified = 7; //isVerified
bool state = 8; //state
int64 createdAt = 9; //createdAt
int64 updatedAt = 10; //updatedAt
int64 deletedAt = 11; //deletedAt
string passwordHash = 3; //passwordHash
string phone = 4; //phone
string email = 5; //email
string nickname = 6; //nickname
string avatar = 7; //avatar
string bio = 8; //bio
string currentRole = 9; //currentRole
repeated string verifiedRoles = 10; //verifiedRoles
string verificationStatus = 11; //verificationStatus
bool isAdmin = 12; //isAdmin
int64 createdAt = 13; //createdAt
int64 updatedAt = 14; //updatedAt
int64 deletedAt = 15; //deletedAt
}
message AddUsersReq {
int64 userId = 1; //userId
string username = 2; //username
string passwd = 3; //passwd
string nickname = 4; //nickname
string phone = 5; //phone
int64 roleType = 6; //roleType
bool isVerified = 7; //isVerified
bool state = 8; //state
int64 createdAt = 9; //createdAt
int64 updatedAt = 10; //updatedAt
int64 deletedAt = 11; //deletedAt
string username = 1; //username
string passwordHash = 2; //passwordHash
string phone = 3; //phone
string email = 4; //email
string nickname = 5; //nickname
string avatar = 6; //avatar
string bio = 7; //bio
string currentRole = 8; //currentRole
repeated string verifiedRoles = 9; //verifiedRoles
string verificationStatus = 10; //verificationStatus
bool isAdmin = 11; //isAdmin
int64 createdAt = 12; //createdAt
int64 updatedAt = 13; //updatedAt
int64 deletedAt = 14; //deletedAt
}
message AddUsersResp {
}
message UpdateUsersReq {
int64 userId = 1; //userId
string username = 2; //username
string passwd = 3; //passwd
string nickname = 4; //nickname
string phone = 5; //phone
int64 roleType = 6; //roleType
bool isVerified = 7; //isVerified
bool state = 8; //state
int64 createdAt = 9; //createdAt
int64 updatedAt = 10; //updatedAt
int64 deletedAt = 11; //deletedAt
int64 id = 1; //id
optional string username = 2; //username
optional string passwordHash = 3; //passwordHash
optional string phone = 4; //phone
optional string email = 5; //email
optional string nickname = 6; //nickname
optional string avatar = 7; //avatar
optional string bio = 8; //bio
optional string currentRole = 9; //currentRole
repeated string verifiedRoles = 10; //verifiedRoles
optional string verificationStatus = 11; //verificationStatus
optional bool isAdmin = 12; //isAdmin
optional int64 createdAt = 13; //createdAt
optional int64 updatedAt = 14; //updatedAt
optional int64 deletedAt = 15; //deletedAt
}
message UpdateUsersResp {
@@ -73,19 +85,23 @@ message GetUsersByIdResp {
}
message SearchUsersReq {
int64 page = 1; //page
int64 limit = 2; //limit
int64 userId = 3; //userId
string username = 4; //username
string passwd = 5; //passwd
string nickname = 6; //nickname
string phone = 7; //phone
int64 roleType = 8; //roleType
bool isVerified = 9; //isVerified
bool state = 10; //state
int64 createdAt = 11; //createdAt
int64 updatedAt = 12; //updatedAt
int64 deletedAt = 13; //deletedAt
optional int64 page = 1; //page
optional int64 limit = 2; //limit
optional int64 id = 3; //id
optional string username = 4; //username
optional string passwordHash = 5; //passwordHash
optional string phone = 6; //phone
optional string email = 7; //email
optional string nickname = 8; //nickname
optional string avatar = 9; //avatar
optional string bio = 10; //bio
optional string currentRole = 11; //currentRole
repeated string verifiedRoles = 12; //verifiedRoles
optional string verificationStatus = 13; //verificationStatus
optional bool isAdmin = 14; //isAdmin
optional int64 createdAt = 15; //createdAt
optional int64 updatedAt = 16; //updatedAt
optional int64 deletedAt = 17; //deletedAt
}
message SearchUsersResp {
@@ -121,7 +137,7 @@ message ValidateTokenResp {
bool valid = 1; // token 是否有效(不在黑名单中)
string message = 2; // 验证失败原因
int64 userId = 3; // 用户ID
int64 roleType = 4; // 用户角色
string roleType = 4; // 用户角色
}
message CheckPermissionReq {
@@ -156,7 +172,17 @@ message LogoutResp {
}
// ------------------------------------
message ResetPasswordReq {
string newPassword = 1;
string email = 2;
string requestId = 3;
string vcode = 4;
}
message ResetPasswordResp {
}
// ------------------------------------
// Rpc Func
// ------------------------------------
@@ -174,4 +200,5 @@ service usercenter {
rpc ValidateToken(ValidateTokenReq) returns (ValidateTokenResp);
rpc CheckPermission(CheckPermissionReq) returns (CheckPermissionResp);
rpc Logout(LogoutReq) returns (LogoutResp);
}
rpc ResetPassword(ResetPasswordReq) returns (ResetPasswordResp);
}
-20
View File
@@ -1,20 +0,0 @@
-- create
-- extension if not exists "uuid-ossp";
create
extension if not exists "pg_trgm";
create table users
(
user_id BIGINT primary key not null,
username VARCHAR(50) UNIQUE NOT NULL,
passwd VARCHAR(255) NOT NULL,
nickname VARCHAR(50) NOT NULL DEFAULT ('user_' || substr(md5(random()::text), 1, 10)),
phone VARCHAR(20) UNIQUE NOT NULL default '',
email varchar(50) unique not null default '',
role_type SMALLINT NOT NULL default 1, -- 1:玩家, 2:打手, 3:店长
is_verified BOOLEAN DEFAULT false,
state BOOLEAN NOT NULL DEFAULT true,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
updated_at timestamp with time zone default current_timestamp,
deleted_at timestamp with time zone
);
+35
View File
@@ -0,0 +1,35 @@
CREATE TABLE user_verifications (
id BIGINT PRIMARY KEY,
user_id BIGINT NOT NULL REFERENCES users(id),
role VARCHAR(20) NOT NULL,
status VARCHAR(20) NOT NULL DEFAULT 'pending',
materials JSONB NOT NULL,
reject_reason TEXT,
reviewed_by BIGINT,
reviewed_at TIMESTAMPTZ,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
CONSTRAINT chk_verification_status CHECK (status IN ('pending', 'approved', 'rejected')),
UNIQUE(user_id, role) -- 每个角色只有一条最新的认证记录
);
-- NoteAuto update verification_status of users table
CREATE OR REPLACE FUNCTION sync_user_verification_status()
RETURNS TRIGGER AS $$
DECLARE
status_json JSONB;
BEGIN
SELECT jsonb_object_agg(role, status)
INTO status_json
FROM user_verifications
WHERE user_id = NEW.user_id;
UPDATE users SET verification_status = status_json WHERE id = NEW.user_id;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER trigger_sync_verifications
AFTER INSERT OR UPDATE ON user_verifications
FOR EACH ROW EXECUTE FUNCTION sync_user_verification_status();
+29
View File
@@ -0,0 +1,29 @@
CREATE EXTENSION IF NOT EXISTS pg_trgm; -- 三元组模糊搜索
CREATE EXTENSION IF NOT EXISTS btree_gin; -- 复合 GIN 索引
CREATE EXTENSION IF NOT EXISTS pgcrypto; -- 加密函数
CREATE TABLE users
(
id BIGINT PRIMARY KEY,
username VARCHAR(50) UNIQUE NOT NULL,
password_hash VARCHAR(255) NOT NULL,
phone VARCHAR(20) UNIQUE,
email VARCHAR(100) UNIQUE,
nickname VARCHAR(100) NOT NULL,
avatar TEXT,
bio TEXT,
"current_role" VARCHAR(20) NOT NULL DEFAULT 'consumer',
verified_roles TEXT[] DEFAULT ARRAY ['consumer']::TEXT[],
-- 结构: {"player": "pending", "owner": "rejected", "consumer": "approved"}
verification_status JSONB DEFAULT '{"consumer": "approved"}'::JSONB,
is_admin BOOLEAN DEFAULT FALSE,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
deleted_at TIMESTAMPTZ,
CONSTRAINT chk_current_role CHECK (current_role IN ('consumer', 'player', 'owner', 'admin'))
);
-- 索引
CREATE INDEX idx_users_phone ON users (phone) WHERE deleted_at IS NULL;
CREATE INDEX idx_users_username_trgm ON users USING gin (username gin_trgm_ops) WHERE deleted_at IS NULL;