feat(app): 添加用户退出登录功能
- 在 app.go 中新增 LogoutUser 方法及对应请求响应结构体 - 更新 app.json API 文档,移除旧 /logout 接口,新增 /user/logout 接口 - 在 app.proto 中定义 LogoutUserRequest 和 UserToken 消息类型 - 生成新的 app.pb.go 和 app_grpc.pb.go 文件以支持新接口 - 配置文件 app.yaml 中增加 RPC 调用的超时和重试设置 - 实现 gRPC 客户端和服务端对 LogoutUser 接口的支持
This commit is contained in:
parent
65ff8ddb62
commit
c3406ce964
49
api/app.json
49
api/app.json
|
|
@ -92,34 +92,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/logout": {
|
|
||||||
"post": {
|
|
||||||
"description": "登出",
|
|
||||||
"tags": [
|
|
||||||
"user"
|
|
||||||
],
|
|
||||||
"summary": "登出",
|
|
||||||
"operationId": "Logout",
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"name": "body",
|
|
||||||
"in": "body",
|
|
||||||
"schema": {
|
|
||||||
"type": "object",
|
|
||||||
"$ref": "#/definitions/IDReq"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": "BaseDataInfo",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/BaseDataInfo"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"/register": {
|
"/register": {
|
||||||
"post": {
|
"post": {
|
||||||
"description": "Register | 注册",
|
"description": "Register | 注册",
|
||||||
|
|
@ -206,11 +178,10 @@
|
||||||
},
|
},
|
||||||
"/user/info": {
|
"/user/info": {
|
||||||
"post": {
|
"post": {
|
||||||
"description": "@ Get UserInfo detail By Token | 获取用户信息",
|
"description": "Get UserInfo detail By Token | 获取用户信息",
|
||||||
"tags": [
|
"tags": [
|
||||||
"user"
|
"user"
|
||||||
],
|
],
|
||||||
"summary": "@ Get UserInfo detail By Token | 获取用户信息",
|
|
||||||
"operationId": "GetUserInfoByToken",
|
"operationId": "GetUserInfoByToken",
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
|
|
@ -250,6 +221,24 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/user/logout": {
|
||||||
|
"post": {
|
||||||
|
"description": "Logout | 退出登录 不传参数,默认使用请求头的token",
|
||||||
|
"tags": [
|
||||||
|
"user"
|
||||||
|
],
|
||||||
|
"summary": "Logout | 退出登录 不传参数,默认使用请求头的token",
|
||||||
|
"operationId": "Logout",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "BaseMsgResp",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/BaseMsgResp"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/user/oauthAuthorize": {
|
"/user/oauthAuthorize": {
|
||||||
"post": {
|
"post": {
|
||||||
"description": "OauthAuthorize | 第三方登录接口",
|
"description": "OauthAuthorize | 第三方登录接口",
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,6 @@ type (
|
||||||
CaptchaCode string `json:"captchaCode,optional"`
|
CaptchaCode string `json:"captchaCode,optional"`
|
||||||
// 过期时间
|
// 过期时间
|
||||||
ExpireTime uint32 `json:"expireTime,optional"`
|
ExpireTime uint32 `json:"expireTime,optional"`
|
||||||
|
|
||||||
}
|
}
|
||||||
RegisterReq {
|
RegisterReq {
|
||||||
// 账户注册类型:手机或邮箱
|
// 账户注册类型:手机或邮箱
|
||||||
|
|
@ -31,89 +30,83 @@ type (
|
||||||
Value string `json:"value,optional"`
|
Value string `json:"value,optional"`
|
||||||
// 昵称
|
// 昵称
|
||||||
NickName string `json:"nickName,optional"`
|
NickName string `json:"nickName,optional"`
|
||||||
// 性别
|
// 性别
|
||||||
Sex uint8 `json:"sex,optional"`
|
Sex uint8 `json:"sex,optional"`
|
||||||
//生日
|
//生日
|
||||||
Birthday uint32 `json:"birthday,optional"`
|
Birthday uint32 `json:"birthday,optional"`
|
||||||
// 密码加密后的值
|
// 密码加密后的值
|
||||||
PasswordHash *string `json:"passwordHash,optional"`
|
PasswordHash *string `json:"passwordHash,optional"`
|
||||||
//验证码
|
//验证码
|
||||||
Captcha string `json:"captcha,optional"`
|
Captcha string `json:"captcha,optional"`
|
||||||
// 验证码ID
|
// 验证码ID
|
||||||
CaptchaId string `json:"captchaId,optional"`
|
CaptchaId string `json:"captchaId,optional"`
|
||||||
//VerificationType 类型 1 手机 2 邮箱
|
//VerificationType 类型 1 手机 2 邮箱
|
||||||
VerificationType *uint32 `json:"verificationType,optional"`
|
VerificationType *uint32 `json:"verificationType,optional"`
|
||||||
// Gender male or female or other , 男,女,其他
|
// Gender male or female or other , 男,女,其他
|
||||||
Gender *string `json:"gender,optional"`
|
Gender *string `json:"gender,optional"`
|
||||||
// 注册来源 app,pc
|
// 注册来源 app,pc
|
||||||
RegisterSource *string `json:"registerSource,optional"`
|
RegisterSource *string `json:"registerSource,optional"`
|
||||||
}
|
}
|
||||||
|
RegisterResp {
|
||||||
|
// token信息
|
||||||
RegisterResp{
|
AuthToken *AuthToken `json:"authToken,optional"`
|
||||||
// token信息
|
User *UserInfo `json:"userInfo,optional"`
|
||||||
AuthToken *AuthToken `json:"authToken,optional"`
|
|
||||||
User *UserInfo `json:"userInfo,optional"`
|
|
||||||
}
|
}
|
||||||
|
AuthToken {
|
||||||
AuthToken{
|
// access_token
|
||||||
// access_token
|
AccessToken string `json:"accessToken,optional"`
|
||||||
AccessToken string `json:"accessToken,optional"`
|
// refresh_token
|
||||||
// refresh_token
|
RefreshToken string `json:"refreshToken,optional"`
|
||||||
RefreshToken string `json:"refreshToken,optional"`
|
// token_type 类型
|
||||||
// token_type 类型
|
TokenType string `json:"tokenType,optional"`
|
||||||
TokenType string `json:"tokenType,optional"`
|
//access_token_expires
|
||||||
//access_token_expires
|
AccessTokenExpires int64 `json:"accessTokenExpires,optional"`
|
||||||
AccessTokenExpires int64 `json:"accessTokenExpires,optional"`
|
//refresh_token_expires
|
||||||
//refresh_token_expires
|
RefreshTokenExpires int64 `json:"refreshTokenExpires,optional"`
|
||||||
RefreshTokenExpires int64 `json:"refreshTokenExpires,optional"`
|
|
||||||
}
|
}
|
||||||
|
UserInfo {
|
||||||
UserInfo{
|
|
||||||
BaseIDInfo
|
|
||||||
// 昵称
|
|
||||||
NickName string `json:"nickName,optional"`
|
|
||||||
//生日
|
|
||||||
Birthday *int64 `json:"birthday,optional"`
|
|
||||||
// 头像
|
|
||||||
Avatar *string `json:"avatar,optional"`
|
|
||||||
// Gender male or female or other , 男,女,其他
|
|
||||||
Gender *string `json:"gender,optional"`
|
|
||||||
// 账户注册类型:
|
|
||||||
// 1 手机 2 邮箱
|
|
||||||
RegisterType *uint32 `json:"registerType,optional"`
|
|
||||||
// 手机号
|
|
||||||
Mobile *string `json:"mobile,optional"`
|
|
||||||
// 用户名
|
|
||||||
Username *string `json:"username,optional"`
|
|
||||||
//邮箱
|
|
||||||
Email *string `json:"email,optional"`
|
|
||||||
}
|
|
||||||
|
|
||||||
LoginReq{
|
|
||||||
// UserName or Email or Mobile
|
|
||||||
UserName string `json:"userName,optional"`
|
|
||||||
// Password
|
|
||||||
Password string `json:"password"`
|
|
||||||
// ClientIP
|
|
||||||
ClientIP string `json:"clientIp"`
|
|
||||||
// 登录方式
|
|
||||||
LoginType string `json:"loginType"`
|
|
||||||
// 登录系统
|
|
||||||
LoginPlatform string `json:"loginPlatform"`
|
|
||||||
}
|
|
||||||
LoginResp{
|
|
||||||
BaseMsgResp
|
|
||||||
AuthToken *AuthToken
|
|
||||||
UserInfo *UserInfo
|
|
||||||
}
|
|
||||||
UserInfoResp{
|
|
||||||
BaseIDInfo
|
BaseIDInfo
|
||||||
// UserInfo information | UserInfo信息数据
|
// 昵称
|
||||||
Data UserInfo `json:"data"`
|
NickName string `json:"nickName,optional"`
|
||||||
|
//生日
|
||||||
|
Birthday *int64 `json:"birthday,optional"`
|
||||||
|
// 头像
|
||||||
|
Avatar *string `json:"avatar,optional"`
|
||||||
|
// Gender male or female or other , 男,女,其他
|
||||||
|
Gender *string `json:"gender,optional"`
|
||||||
|
// 账户注册类型:
|
||||||
|
// 1 手机 2 邮箱
|
||||||
|
RegisterType *uint32 `json:"registerType,optional"`
|
||||||
|
// 手机号
|
||||||
|
Mobile *string `json:"mobile,optional"`
|
||||||
|
// 用户名
|
||||||
|
Username *string `json:"username,optional"`
|
||||||
|
//邮箱
|
||||||
|
Email *string `json:"email,optional"`
|
||||||
}
|
}
|
||||||
|
LoginReq {
|
||||||
UserListReq{
|
// UserName or Email or Mobile
|
||||||
|
UserName string `json:"userName,optional"`
|
||||||
|
// Password
|
||||||
|
Password string `json:"password"`
|
||||||
|
// ClientIP
|
||||||
|
ClientIP string `json:"clientIp"`
|
||||||
|
// 登录方式
|
||||||
|
LoginType string `json:"loginType"`
|
||||||
|
// 登录系统
|
||||||
|
LoginPlatform string `json:"loginPlatform"`
|
||||||
|
}
|
||||||
|
LoginResp {
|
||||||
|
BaseMsgResp
|
||||||
|
AuthToken *AuthToken
|
||||||
|
UserInfo *UserInfo
|
||||||
|
}
|
||||||
|
UserInfoResp {
|
||||||
|
BaseIDInfo
|
||||||
|
// UserInfo information | UserInfo信息数据
|
||||||
|
Data UserInfo `json:"data"`
|
||||||
|
}
|
||||||
|
UserListReq {
|
||||||
// Page
|
// Page
|
||||||
PageInfo
|
PageInfo
|
||||||
// UserName or Email or Mobile
|
// UserName or Email or Mobile
|
||||||
|
|
@ -125,89 +118,88 @@ type (
|
||||||
// Status 1: normal 2: ban | 状态 1 正常 2 禁用
|
// Status 1: normal 2: ban | 状态 1 正常 2 禁用
|
||||||
Status *string `json:"status,optional"`
|
Status *string `json:"status,optional"`
|
||||||
}
|
}
|
||||||
|
// The response data of user list | User信息列表数据
|
||||||
// The response data of user list | User信息列表数据
|
|
||||||
UserListResp {
|
UserListResp {
|
||||||
BaseDataInfo
|
BaseDataInfo
|
||||||
// The device list data | USer信息列表数据
|
// The device list data | USer信息列表数据
|
||||||
Data UserListInfo `json:"data"`
|
Data UserListInfo `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// The device list data | User信息列表数据
|
// The device list data | User信息列表数据
|
||||||
UserListInfo {
|
UserListInfo {
|
||||||
BaseListInfo
|
BaseListInfo
|
||||||
// The device list data | User信息列表数据
|
// The device list data | User信息列表数据
|
||||||
Data []UserInfo `json:"data"`
|
Data []UserInfo `json:"data"`
|
||||||
}
|
}
|
||||||
OauthAuthorizeReq {
|
OauthAuthorizeReq {}
|
||||||
|
|
||||||
|
|
||||||
|
OauthAuthorizeResp {
|
||||||
|
BaseMsgResp
|
||||||
|
}
|
||||||
|
PassWordResetReq {
|
||||||
|
// UserName or Email or Mobile
|
||||||
|
UserName string `json:"userName,optional"`
|
||||||
|
// Password
|
||||||
|
Password string `json:"password"`
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
OauthAuthorizeResp {
|
|
||||||
BaseMsgResp
|
|
||||||
}
|
|
||||||
PassWordResetReq {
|
|
||||||
// UserName or Email or Mobile
|
|
||||||
UserName string `json:"userName,optional"`
|
|
||||||
// Password
|
|
||||||
Password string `json:"password"`
|
|
||||||
}
|
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
@server (
|
@server (
|
||||||
group: user_public
|
group: user_public
|
||||||
)
|
)
|
||||||
|
|
||||||
service App {
|
service App {
|
||||||
// GetVerifyCode | 获取验证码
|
// GetVerifyCode | 获取验证码
|
||||||
@handler getVerifyCode
|
@handler getVerifyCode
|
||||||
post /get/verifyCode (VerifyCodeReq) returns (VerifyCodeResp)
|
post /get/verifyCode (VerifyCodeReq) returns (VerifyCodeResp)
|
||||||
|
|
||||||
// Register | 注册
|
// Register | 注册
|
||||||
@handler register
|
@handler register
|
||||||
post /register (RegisterReq) returns (RegisterResp)
|
post /register (RegisterReq) returns (RegisterResp)
|
||||||
// Login | 登录
|
|
||||||
@handler login
|
|
||||||
post /login (LoginReq) returns (LoginResp)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Login | 登录
|
||||||
|
@handler login
|
||||||
|
post /login (LoginReq) returns (LoginResp)
|
||||||
|
}
|
||||||
|
|
||||||
@server (
|
@server (
|
||||||
group: user
|
group: user
|
||||||
middleware: Authority
|
middleware: Authority
|
||||||
)
|
)
|
||||||
|
|
||||||
service App {
|
service App {
|
||||||
// Get userInfo detail by ID | 获取用户信息
|
// Get userInfo detail by ID | 获取用户信息
|
||||||
@handler getUserInfoById
|
@handler getUserInfoById
|
||||||
post /user (IDReq) returns (UserInfo)
|
post /user (IDReq) returns (UserInfo)
|
||||||
|
|
||||||
// Get UserInfo detail By Token | 获取用户信息
|
// Get UserInfo detail By Token | 获取用户信息
|
||||||
@handler getUserInfoByToken
|
@handler getUserInfoByToken
|
||||||
post /user/info () returns (UserInfo)
|
post /user/info returns (UserInfo)
|
||||||
|
|
||||||
//List userInfo | 获取用户列表
|
//List userInfo | 获取用户列表
|
||||||
@handler listUserInfo
|
@handler listUserInfo
|
||||||
post /user/list (UserListReq) returns (UserListResp)
|
post /user/list (UserListReq) returns (UserListResp)
|
||||||
|
|
||||||
//Update userInfo | 更新用户信息
|
//Update userInfo | 更新用户信息
|
||||||
@handler updateUserInfo
|
@handler updateUserInfo
|
||||||
post /user/update (UserInfo) returns (BaseDataInfo)
|
post /user/update (UserInfo) returns (BaseMsgResp)
|
||||||
|
|
||||||
// Logout | 退出登录
|
// Logout | 退出登录 不传参数,默认使用请求头的token
|
||||||
@handler logout
|
@handler logout
|
||||||
post /user/logout (IDReq) returns (BaseDataInfo)
|
post /user/logout () returns (BaseMsgResp)
|
||||||
|
|
||||||
// PassWordReset | 修改密码
|
// PassWordReset | 修改密码
|
||||||
@handler passWordReset
|
@handler passWordReset
|
||||||
post /user/passWordReset (PassWordResetReq) returns (BaseDataInfo)
|
post /user/passWordReset (PassWordResetReq) returns (BaseDataInfo)
|
||||||
|
|
||||||
// CheckLogin | 检测登录状态
|
// CheckLogin | 检测登录状态
|
||||||
@handler checkLogin
|
@handler checkLogin
|
||||||
post /user/checkLogin (IDReq) returns (BaseDataInfo)
|
post /user/checkLogin (IDReq) returns (BaseDataInfo)
|
||||||
|
|
||||||
//OauthAuthorize | 第三方登录接口
|
//OauthAuthorize | 第三方登录接口
|
||||||
@handler oauthAuthorize
|
@handler oauthAuthorize
|
||||||
post /user/oauthAuthorize (OauthAuthorizeReq) returns (OauthAuthorizeResp)
|
post /user/oauthAuthorize (OauthAuthorizeReq) returns (OauthAuthorizeResp)
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,4 +33,7 @@ AppRpc:
|
||||||
Hosts:
|
Hosts:
|
||||||
- 192.168.201.58:2379 # 共享etcd地址
|
- 192.168.201.58:2379 # 共享etcd地址
|
||||||
Key: app.rpc
|
Key: app.rpc
|
||||||
Enabled: true
|
Enabled: true
|
||||||
|
NonBlock: true
|
||||||
|
Timeout: 3000
|
||||||
|
RetryCount: 1 # 重试次数,如果为1,则最多调用2次(包括第一次)
|
||||||
|
|
@ -11,9 +11,8 @@ import (
|
||||||
|
|
||||||
// swagger:route post /user/info user GetUserInfoByToken
|
// swagger:route post /user/info user GetUserInfoByToken
|
||||||
//
|
//
|
||||||
//@ Get UserInfo detail By Token | 获取用户信息
|
|
||||||
//
|
//
|
||||||
//@ Get UserInfo detail By Token | 获取用户信息
|
// Get UserInfo detail By Token | 获取用户信息
|
||||||
//
|
//
|
||||||
// Responses:
|
// Responses:
|
||||||
// 200: UserInfo
|
// 200: UserInfo
|
||||||
|
|
|
||||||
|
|
@ -7,34 +7,21 @@ import (
|
||||||
|
|
||||||
"mingyang-admin-app-api/internal/logic/user"
|
"mingyang-admin-app-api/internal/logic/user"
|
||||||
"mingyang-admin-app-api/internal/svc"
|
"mingyang-admin-app-api/internal/svc"
|
||||||
"mingyang-admin-app-api/internal/types"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// swagger:route post /logout user Logout
|
// swagger:route post /user/logout user Logout
|
||||||
//
|
//
|
||||||
//登出
|
// Logout | 退出登录 不传参数,默认使用请求头的token
|
||||||
//
|
//
|
||||||
//登出
|
// Logout | 退出登录 不传参数,默认使用请求头的token
|
||||||
//
|
|
||||||
// Parameters:
|
|
||||||
// + name: body
|
|
||||||
// require: true
|
|
||||||
// in: body
|
|
||||||
// type: IDReq
|
|
||||||
//
|
//
|
||||||
// Responses:
|
// Responses:
|
||||||
// 200: BaseDataInfo
|
// 200: BaseMsgResp
|
||||||
|
|
||||||
func LogoutHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
func LogoutHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
var req types.IDReq
|
|
||||||
if err := httpx.Parse(r, &req, true); err != nil {
|
|
||||||
httpx.ErrorCtx(r.Context(), w, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
l := user.NewLogoutLogic(r.Context(), svcCtx)
|
l := user.NewLogoutLogic(r.Context(), svcCtx)
|
||||||
resp, err := l.Logout(&req)
|
resp, err := l.Logout()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = svcCtx.Trans.TransError(r.Context(), err)
|
err = svcCtx.Trans.TransError(r.Context(), err)
|
||||||
httpx.ErrorCtx(r.Context(), w, err)
|
httpx.ErrorCtx(r.Context(), w, err)
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,17 @@
|
||||||
package user
|
package user
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"github.com/saas-mingyang/mingyang-admin-common/i18n"
|
||||||
"mingyang-admin-app-api/internal/svc"
|
"mingyang-admin-app-api/internal/svc"
|
||||||
"mingyang-admin-app-api/internal/types"
|
"mingyang-admin-app-api/internal/types"
|
||||||
|
"mingyang-admin-app-rpc/types/app"
|
||||||
|
"net/http"
|
||||||
|
"runtime"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/zeromicro/go-zero/core/logx"
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
)
|
)
|
||||||
|
|
@ -23,8 +30,96 @@ func NewLogoutLogic(ctx context.Context, svcCtx *svc.ServiceContext) *LogoutLogi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *LogoutLogic) Logout(req *types.IDReq) (resp *types.BaseDataInfo, err error) {
|
// Logout 在API层添加调用栈信息
|
||||||
// todo: add your logic here and delete this line
|
func (l *LogoutLogic) Logout() (resp *types.BaseMsgResp, err error) {
|
||||||
|
// 打印调用栈
|
||||||
|
buf := make([]byte, 1024)
|
||||||
|
n := runtime.Stack(buf, false)
|
||||||
|
l.Logger.Infof("Logout call stack:\n%s", buf[:n])
|
||||||
|
|
||||||
return
|
token := l.getTokenFromContext()
|
||||||
|
l.Infof("Starting Logout RPC call at: %v", time.Now())
|
||||||
|
|
||||||
|
// 记录goroutine ID
|
||||||
|
goID := getGoroutineID()
|
||||||
|
l.Logger.Infof("Goroutine ID: %d", goID)
|
||||||
|
|
||||||
|
_, err = l.svcCtx.AppRpc.LogoutUser(l.ctx, &app.UserToken{
|
||||||
|
AccessToken: token,
|
||||||
|
UserId: l.getUserIDFromContext(),
|
||||||
|
})
|
||||||
|
|
||||||
|
l.Logger.Infof("Finished Logout RPC call at: %v", time.Now())
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &types.BaseMsgResp{Msg: l.svcCtx.Trans.Trans(l.ctx, i18n.Success)}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取goroutine ID
|
||||||
|
func getGoroutineID() uint64 {
|
||||||
|
b := make([]byte, 64)
|
||||||
|
b = b[:runtime.Stack(b, false)]
|
||||||
|
b = bytes.TrimPrefix(b, []byte("goroutine "))
|
||||||
|
b = b[:bytes.IndexByte(b, ' ')]
|
||||||
|
n, _ := strconv.ParseUint(string(b), 10, 64)
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
// 从上下文中获取 Token
|
||||||
|
func (l *LogoutLogic) getTokenFromContext() string {
|
||||||
|
// 尝试不同的 key 从上下文中获取 Token
|
||||||
|
keys := []string{"token", "access_token", "jwt_token", "auth_token"}
|
||||||
|
|
||||||
|
for _, key := range keys {
|
||||||
|
if token, ok := l.ctx.Value(key).(string); ok && token != "" {
|
||||||
|
return l.cleanToken(token)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清理 Token 字符串,移除 "Bearer " 前缀
|
||||||
|
func (l *LogoutLogic) cleanToken(token string) string {
|
||||||
|
if token == "" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
token = strings.TrimSpace(token)
|
||||||
|
// 移除 "Bearer " 前缀
|
||||||
|
if strings.HasPrefix(strings.ToLower(token), "bearer ") {
|
||||||
|
token = token[7:]
|
||||||
|
}
|
||||||
|
return token
|
||||||
|
}
|
||||||
|
|
||||||
|
// 从 Authorization Header 中提取 Token
|
||||||
|
func (l *LogoutLogic) extractTokenFromAuthHeader(ctx context.Context) string {
|
||||||
|
// 尝试从请求上下文获取 Request 对象
|
||||||
|
if req, ok := ctx.Value("http_request").(*http.Request); ok {
|
||||||
|
authHeader := req.Header.Get("Authorization")
|
||||||
|
if authHeader != "" {
|
||||||
|
return l.cleanToken(authHeader)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// 从上下文中获取用户ID
|
||||||
|
func (l *LogoutLogic) getUserIDFromContext() uint64 {
|
||||||
|
// 在AuthMiddleware中,我们将用户ID放入了context
|
||||||
|
if userID, ok := l.ctx.Value("userId").(uint64); ok {
|
||||||
|
return userID
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取 Token 过期时间
|
||||||
|
func (l *LogoutLogic) getTokenExpireTime(token string) (time.Time, error) {
|
||||||
|
// 使用 JWTManager 验证并获取 Claims
|
||||||
|
claims, err := l.svcCtx.AppRpc.AuthToken(l.ctx, &app.AuthReq{Token: token})
|
||||||
|
if err != nil {
|
||||||
|
return time.Time{}, err
|
||||||
|
}
|
||||||
|
return claims.Claims.ExpiresAt.Timestamp.AsTime(), nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,9 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/golang-jwt/jwt/v4"
|
"github.com/golang-jwt/jwt/v4"
|
||||||
"github.com/redis/go-redis/v9"
|
"github.com/redis/go-redis/v9"
|
||||||
|
"github.com/saas-mingyang/mingyang-admin-common/config"
|
||||||
|
jwt2 "github.com/saas-mingyang/mingyang-admin-common/utils/jwt"
|
||||||
|
"github.com/zeromicro/go-zero/rest/enum"
|
||||||
"mingyang-admin-app-api/internal/types"
|
"mingyang-admin-app-api/internal/types"
|
||||||
"mingyang-admin-app-rpc/appclient"
|
"mingyang-admin-app-rpc/appclient"
|
||||||
"mingyang-admin-app-rpc/types/app"
|
"mingyang-admin-app-rpc/types/app"
|
||||||
|
|
@ -16,12 +19,6 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// 定义上下文键类型
|
// 定义上下文键类型
|
||||||
type contextKey string
|
|
||||||
|
|
||||||
const (
|
|
||||||
UserIDKey contextKey = "user_id"
|
|
||||||
UserInfoKey contextKey = "user_info"
|
|
||||||
)
|
|
||||||
|
|
||||||
type AuthorityMiddleware struct {
|
type AuthorityMiddleware struct {
|
||||||
Rds redis.UniversalClient
|
Rds redis.UniversalClient
|
||||||
|
|
@ -61,36 +58,21 @@ func (m *AuthorityMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc {
|
||||||
writeError(w, 401, "Authorization header is required")
|
writeError(w, 401, "Authorization header is required")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
fromToken := jwt2.StripBearerPrefixFromToken(r.Header.Get("Authorization"))
|
||||||
// 2. 验证 Bearer Token 格式
|
|
||||||
if !strings.HasPrefix(authHeader, "Bearer ") {
|
|
||||||
writeError(w, 401, "Invalid authorization format, must be 'Bearer <token>'")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. 提取 Token
|
|
||||||
tokenString := strings.TrimSpace(strings.TrimPrefix(authHeader, "Bearer"))
|
|
||||||
if tokenString == "" {
|
|
||||||
writeError(w, 401, "Token cannot be empty")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4. 检查 Redis 缓存(可选)
|
|
||||||
if m.Rds != nil {
|
if m.Rds != nil {
|
||||||
cacheKey := fmt.Sprintf("token:%s", tokenString)
|
cacheKey := config.RedisTokenPrefix + fromToken
|
||||||
|
fmt.Printf("cacheKey: %s\n", cacheKey)
|
||||||
cachedUserID, err := m.Rds.Get(r.Context(), cacheKey).Result()
|
cachedUserID, err := m.Rds.Get(r.Context(), cacheKey).Result()
|
||||||
if err == nil && cachedUserID != "" {
|
if err == nil && cachedUserID != "" {
|
||||||
// 从缓存中获取到用户ID
|
// 从缓存中获取到用户ID
|
||||||
ctx := context.WithValue(r.Context(), UserIDKey, cachedUserID)
|
ctx := context.WithValue(r.Context(), enum.UserIdRpcCtxKey, cachedUserID)
|
||||||
r = r.WithContext(ctx)
|
r = r.WithContext(ctx)
|
||||||
next(w, r)
|
next(w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5. 调用 RPC 验证 Token
|
// 5. 调用 RPC 验证 Token
|
||||||
fmt.Printf("Validating token: %s\n", tokenString)
|
token, err := m.AppRpc.AuthToken(r.Context(), &app.AuthReq{Token: fromToken})
|
||||||
token, err := m.AppRpc.AuthToken(r.Context(), &app.AuthReq{Token: tokenString})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Error validating token: %v\n", err)
|
fmt.Printf("Error validating token: %v\n", err)
|
||||||
// 根据错误类型返回不同的错误信息
|
// 根据错误类型返回不同的错误信息
|
||||||
|
|
@ -120,15 +102,30 @@ func (m *AuthorityMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc {
|
||||||
|
|
||||||
// 7. 缓存到 Redis(可选)
|
// 7. 缓存到 Redis(可选)
|
||||||
if m.Rds != nil {
|
if m.Rds != nil {
|
||||||
cacheKey := fmt.Sprintf("token:%s", tokenString)
|
cacheKey := fmt.Sprintf("token:%s", fromToken)
|
||||||
// 设置缓存,过期时间30分钟
|
// 设置缓存,过期时间30分钟
|
||||||
m.Rds.Set(r.Context(), cacheKey, id, 30*time.Minute)
|
m.Rds.Set(r.Context(), cacheKey, id, 30*time.Minute)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 8. 设置到上下文
|
// 创建新的上下文,包含 Token 和用户信息
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
ctx = context.WithValue(ctx, UserIDKey, id)
|
ctx = context.WithValue(ctx, "token", fromToken)
|
||||||
ctx = context.WithValue(ctx, UserInfoKey, token)
|
ctx = context.WithValue(ctx, "userId", token.UserId)
|
||||||
|
ctx = context.WithValue(ctx, "tokenClaims", token)
|
||||||
|
|
||||||
|
// 获取客户端 IP
|
||||||
|
clientIP := getClientIP(r)
|
||||||
|
ctx = context.WithValue(ctx, "client_ip", clientIP)
|
||||||
|
|
||||||
|
// 获取 User-Agent
|
||||||
|
userAgent := r.UserAgent()
|
||||||
|
ctx = context.WithValue(ctx, "user_agent", userAgent)
|
||||||
|
|
||||||
|
// 将新上下文设置到请求中
|
||||||
|
r = r.WithContext(ctx)
|
||||||
|
|
||||||
|
// 调用下一个处理器
|
||||||
|
next(w, r)
|
||||||
|
|
||||||
// 9. 记录请求日志(可选)
|
// 9. 记录请求日志(可选)
|
||||||
fmt.Printf("[%s] %s - UserID: %d - Duration: %v\n",
|
fmt.Printf("[%s] %s - UserID: %d - Duration: %v\n",
|
||||||
|
|
@ -136,9 +133,25 @@ func (m *AuthorityMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc {
|
||||||
r.URL.Path,
|
r.URL.Path,
|
||||||
id,
|
id,
|
||||||
time.Since(startTime))
|
time.Since(startTime))
|
||||||
|
|
||||||
// 10. 继续处理请求
|
|
||||||
r = r.WithContext(ctx)
|
|
||||||
next(w, r)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取客户端 IP
|
||||||
|
func getClientIP(r *http.Request) string {
|
||||||
|
// 尝试从 X-Forwarded-For 获取
|
||||||
|
if forwarded := r.Header.Get("X-Forwarded-For"); forwarded != "" {
|
||||||
|
// 可能有多个 IP,取第一个
|
||||||
|
ips := strings.Split(forwarded, ",")
|
||||||
|
if len(ips) > 0 {
|
||||||
|
return strings.TrimSpace(ips[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 从 RemoteAddr 获取
|
||||||
|
ip := r.RemoteAddr
|
||||||
|
if colonIndex := strings.LastIndex(ip, ":"); colonIndex != -1 {
|
||||||
|
ip = ip[:colonIndex]
|
||||||
|
}
|
||||||
|
|
||||||
|
return ip
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -95,6 +95,10 @@ message LoginResponse {
|
||||||
AuthToken auth_token = 2;
|
AuthToken auth_token = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message LogoutUserRequest {
|
||||||
|
string access_token = 1;
|
||||||
|
}
|
||||||
|
|
||||||
// NumericDate 使用 timestamp 表示 JWT 中的时间字段
|
// NumericDate 使用 timestamp 表示 JWT 中的时间字段
|
||||||
message NumericDate {
|
message NumericDate {
|
||||||
google.protobuf.Timestamp timestamp = 1;
|
google.protobuf.Timestamp timestamp = 1;
|
||||||
|
|
@ -191,6 +195,11 @@ message UserInfo {
|
||||||
optional int64 updated_at = 24;
|
optional int64 updated_at = 24;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message UserToken {
|
||||||
|
string access_token = 1;
|
||||||
|
uint64 user_id = 2;
|
||||||
|
}
|
||||||
|
|
||||||
message VerifyCodeReq {
|
message VerifyCodeReq {
|
||||||
VerifyCodeType type = 1;
|
VerifyCodeType type = 1;
|
||||||
AccountType account_type = 2;
|
AccountType account_type = 2;
|
||||||
|
|
@ -219,6 +228,9 @@ service App {
|
||||||
// 分页查询用户信息
|
// 分页查询用户信息
|
||||||
// group: user
|
// group: user
|
||||||
rpc ListUsers(PageUserRequest) returns (PageUserResponse);
|
rpc ListUsers(PageUserRequest) returns (PageUserResponse);
|
||||||
|
// 用户退出登录
|
||||||
|
// group: user
|
||||||
|
rpc LogoutUser(UserToken) returns (LogoutUserRequest);
|
||||||
// group: base
|
// group: base
|
||||||
rpc InitDatabase(Empty) returns (BaseResp);
|
rpc InitDatabase(Empty) returns (BaseResp);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ type (
|
||||||
IDsReq = app.IDsReq
|
IDsReq = app.IDsReq
|
||||||
LoginRequest = app.LoginRequest
|
LoginRequest = app.LoginRequest
|
||||||
LoginResponse = app.LoginResponse
|
LoginResponse = app.LoginResponse
|
||||||
|
LogoutUserRequest = app.LogoutUserRequest
|
||||||
NumericDate = app.NumericDate
|
NumericDate = app.NumericDate
|
||||||
PageInfoReq = app.PageInfoReq
|
PageInfoReq = app.PageInfoReq
|
||||||
PageUserRequest = app.PageUserRequest
|
PageUserRequest = app.PageUserRequest
|
||||||
|
|
@ -36,6 +37,7 @@ type (
|
||||||
UUIDReq = app.UUIDReq
|
UUIDReq = app.UUIDReq
|
||||||
UUIDsReq = app.UUIDsReq
|
UUIDsReq = app.UUIDsReq
|
||||||
UserInfo = app.UserInfo
|
UserInfo = app.UserInfo
|
||||||
|
UserToken = app.UserToken
|
||||||
VerifyCodeReq = app.VerifyCodeReq
|
VerifyCodeReq = app.VerifyCodeReq
|
||||||
VerifyCodeResp = app.VerifyCodeResp
|
VerifyCodeResp = app.VerifyCodeResp
|
||||||
|
|
||||||
|
|
@ -50,6 +52,8 @@ type (
|
||||||
LoginUser(ctx context.Context, in *LoginRequest, opts ...grpc.CallOption) (*LoginResponse, error)
|
LoginUser(ctx context.Context, in *LoginRequest, opts ...grpc.CallOption) (*LoginResponse, error)
|
||||||
// 分页查询用户信息
|
// 分页查询用户信息
|
||||||
ListUsers(ctx context.Context, in *PageUserRequest, opts ...grpc.CallOption) (*PageUserResponse, error)
|
ListUsers(ctx context.Context, in *PageUserRequest, opts ...grpc.CallOption) (*PageUserResponse, error)
|
||||||
|
// 用户退出登录
|
||||||
|
LogoutUser(ctx context.Context, in *UserToken, opts ...grpc.CallOption) (*LogoutUserRequest, error)
|
||||||
InitDatabase(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*BaseResp, error)
|
InitDatabase(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*BaseResp, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -94,6 +98,12 @@ func (m *defaultApp) ListUsers(ctx context.Context, in *PageUserRequest, opts ..
|
||||||
return client.ListUsers(ctx, in, opts...)
|
return client.ListUsers(ctx, in, opts...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 用户退出登录
|
||||||
|
func (m *defaultApp) LogoutUser(ctx context.Context, in *UserToken, opts ...grpc.CallOption) (*LogoutUserRequest, error) {
|
||||||
|
client := app.NewAppClient(m.cli.Conn())
|
||||||
|
return client.LogoutUser(ctx, in, opts...)
|
||||||
|
}
|
||||||
|
|
||||||
func (m *defaultApp) InitDatabase(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*BaseResp, error) {
|
func (m *defaultApp) InitDatabase(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*BaseResp, error) {
|
||||||
client := app.NewAppClient(m.cli.Conn())
|
client := app.NewAppClient(m.cli.Conn())
|
||||||
return client.InitDatabase(ctx, in, opts...)
|
return client.InitDatabase(ctx, in, opts...)
|
||||||
|
|
|
||||||
|
|
@ -84,8 +84,13 @@ message PageUserResponse {
|
||||||
uint64 total = 1;
|
uint64 total = 1;
|
||||||
repeated UserInfo data = 2;
|
repeated UserInfo data = 2;
|
||||||
}
|
}
|
||||||
|
message UserToken {
|
||||||
|
string access_token = 1;
|
||||||
|
uint64 user_id = 2;
|
||||||
|
}
|
||||||
|
message LogoutUserRequest {
|
||||||
|
string access_token = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// App 服务定义
|
// App 服务定义
|
||||||
|
|
@ -99,4 +104,7 @@ service App {
|
||||||
// 分页查询用户信息
|
// 分页查询用户信息
|
||||||
// group: user
|
// group: user
|
||||||
rpc ListUsers(PageUserRequest) returns (PageUserResponse);
|
rpc ListUsers(PageUserRequest) returns (PageUserResponse);
|
||||||
|
// 用户退出登录
|
||||||
|
// group: user
|
||||||
|
rpc LogoutUser(UserToken) returns (LogoutUserRequest);
|
||||||
}
|
}
|
||||||
|
|
@ -1,111 +1,100 @@
|
||||||
package jwt_manager
|
package jwt_manager
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
"crypto/md5"
|
||||||
|
"encoding/hex"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/golang-jwt/jwt/v5"
|
|
||||||
"mingyang-admin-app-rpc/internal/config"
|
"mingyang-admin-app-rpc/internal/config"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/golang-jwt/jwt/v5"
|
||||||
|
"github.com/redis/go-redis/v9"
|
||||||
)
|
)
|
||||||
|
|
||||||
type JWTManager struct {
|
// TokenType 令牌类型
|
||||||
accessTokenSecret []byte
|
type TokenType string
|
||||||
refreshTokenSecret []byte
|
|
||||||
accessTokenExpiry time.Duration
|
|
||||||
refreshTokenExpiry time.Duration
|
|
||||||
issuer string
|
|
||||||
}
|
|
||||||
|
|
||||||
|
const (
|
||||||
|
AccessToken TokenType = "access"
|
||||||
|
RefreshToken TokenType = "refresh"
|
||||||
|
)
|
||||||
|
|
||||||
|
// JWTConfig JWT 配置
|
||||||
|
|
||||||
|
// Claims JWT Claims 结构体
|
||||||
type Claims struct {
|
type Claims struct {
|
||||||
UserID uint64 `json:"user_id"`
|
UserID uint64 `json:"user_id"`
|
||||||
Type string `json:"type"` // "access" or "refresh"
|
Type TokenType `json:"type"`
|
||||||
jwt.RegisteredClaims
|
jwt.RegisteredClaims
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewJWTManager(config *config.JWTConfig) *JWTManager {
|
// TokenPair 令牌对
|
||||||
|
type TokenPair struct {
|
||||||
|
AccessToken string `json:"access_token"`
|
||||||
|
RefreshToken string `json:"refresh_token"`
|
||||||
|
AccessTokenExpiresAt time.Time `json:"access_token_expires_at"`
|
||||||
|
RefreshTokenExpiresAt time.Time `json:"refresh_token_expires_at"`
|
||||||
|
TokenType string `json:"token_type"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// JWTManager JWT 管理器
|
||||||
|
type JWTManager struct {
|
||||||
|
accessSecret []byte
|
||||||
|
refreshSecret []byte
|
||||||
|
accessExpiry time.Duration
|
||||||
|
refreshExpiry time.Duration
|
||||||
|
issuer string
|
||||||
|
redis redis.UniversalClient
|
||||||
|
prefix string // Redis 键前缀
|
||||||
|
ctx context.Context
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewJWTManager 创建新的 JWT 管理器
|
||||||
|
func NewJWTManager(config *config.JWTConfig, redisClient redis.UniversalClient) *JWTManager {
|
||||||
|
if config.AccessTokenSecret == "" || config.RefreshTokenSecret == "" {
|
||||||
|
panic("JWT 配置错误")
|
||||||
|
}
|
||||||
return &JWTManager{
|
return &JWTManager{
|
||||||
accessTokenSecret: []byte(config.AccessTokenSecret),
|
accessSecret: []byte(config.AccessTokenSecret),
|
||||||
refreshTokenSecret: []byte(config.RefreshTokenSecret),
|
refreshSecret: []byte(config.RefreshTokenSecret),
|
||||||
accessTokenExpiry: config.AccessTokenExpiry,
|
accessExpiry: config.AccessTokenExpiry,
|
||||||
refreshTokenExpiry: config.RefreshTokenExpiry,
|
refreshExpiry: config.RefreshTokenExpiry,
|
||||||
issuer: config.Issuer,
|
issuer: config.Issuer,
|
||||||
|
redis: redisClient,
|
||||||
|
prefix: "jwt:",
|
||||||
|
ctx: context.Background(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenerateAccessToken 生成访问令牌
|
// WithContext 设置上下文
|
||||||
func (m *JWTManager) GenerateAccessToken(userID uint64) (string, *Claims, error) {
|
func (m *JWTManager) WithContext(ctx context.Context) *JWTManager {
|
||||||
return m.generateToken(userID, "access", m.accessTokenExpiry, m.accessTokenSecret)
|
m.ctx = ctx
|
||||||
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenerateRefreshToken 生成刷新令牌
|
// ==================== Token 生成方法 ====================
|
||||||
func (m *JWTManager) GenerateRefreshToken(userID uint64) (string, *Claims, error) {
|
|
||||||
return m.generateToken(userID, "refresh", m.refreshTokenExpiry, m.refreshTokenSecret)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *JWTManager) generateToken(userID uint64, tokenType string, expiry time.Duration, secret []byte) (string, *Claims, error) {
|
// GenerateTokenPair 生成访问令牌和刷新令牌对
|
||||||
fmt.Printf("userID: %d, tokenType: %s, expiry: %s, secret: %s\n", userID, tokenType, expiry, secret)
|
|
||||||
claims := &Claims{
|
|
||||||
UserID: userID,
|
|
||||||
Type: tokenType,
|
|
||||||
RegisteredClaims: jwt.RegisteredClaims{
|
|
||||||
ExpiresAt: jwt.NewNumericDate(time.Now().Add(expiry)),
|
|
||||||
IssuedAt: jwt.NewNumericDate(time.Now()),
|
|
||||||
Issuer: m.issuer,
|
|
||||||
Subject: fmt.Sprint(userID),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
|
||||||
tokenString, err := token.SignedString(secret)
|
|
||||||
if err != nil {
|
|
||||||
return "", nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return tokenString, claims, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// VerifyAccessToken 验证访问令牌
|
|
||||||
func (m *JWTManager) VerifyAccessToken(tokenString string) (*Claims, error) {
|
|
||||||
return m.verifyToken(tokenString, m.accessTokenSecret, "access")
|
|
||||||
}
|
|
||||||
|
|
||||||
// VerifyRefreshToken 验证刷新令牌
|
|
||||||
func (m *JWTManager) VerifyRefreshToken(tokenString string) (*Claims, error) {
|
|
||||||
return m.verifyToken(tokenString, m.refreshTokenSecret, "refresh")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *JWTManager) verifyToken(tokenString string, secret []byte, expectedType string) (*Claims, error) {
|
|
||||||
token, err := jwt.ParseWithClaims(tokenString, &Claims{}, func(token *jwt.Token) (interface{}, error) {
|
|
||||||
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
|
|
||||||
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
|
|
||||||
}
|
|
||||||
return secret, nil
|
|
||||||
})
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if claims, ok := token.Claims.(*Claims); ok && token.Valid {
|
|
||||||
if claims.Type != expectedType {
|
|
||||||
return nil, errors.New("invalid token type")
|
|
||||||
}
|
|
||||||
return claims, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, errors.New("invalid token")
|
|
||||||
}
|
|
||||||
|
|
||||||
// GenerateTokenPair 生成令牌对
|
|
||||||
func (m *JWTManager) GenerateTokenPair(userID uint64) (*TokenPair, error) {
|
func (m *JWTManager) GenerateTokenPair(userID uint64) (*TokenPair, error) {
|
||||||
accessToken, accessClaims, err := m.GenerateAccessToken(userID)
|
// 生成访问令牌
|
||||||
|
accessToken, accessClaims, err := m.generateToken(userID, AccessToken, m.accessSecret, m.accessExpiry)
|
||||||
|
fmt.Printf("accessToken: %v\n", accessToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, fmt.Errorf("生成访问令牌失败: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
refreshToken, refreshClaims, err := m.GenerateRefreshToken(userID)
|
// 生成刷新令牌
|
||||||
|
refreshToken, refreshClaims, err := m.generateToken(userID, RefreshToken, m.refreshSecret, m.refreshExpiry)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, fmt.Errorf("生成刷新令牌失败: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 存储令牌到 Redis(用于追踪和管理)
|
||||||
|
if m.redis != nil {
|
||||||
|
m.storeToken(userID, accessToken, accessClaims.ExpiresAt.Time)
|
||||||
|
m.storeToken(userID, refreshToken, refreshClaims.ExpiresAt.Time)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &TokenPair{
|
return &TokenPair{
|
||||||
|
|
@ -117,10 +106,484 @@ func (m *JWTManager) GenerateTokenPair(userID uint64) (*TokenPair, error) {
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type TokenPair struct {
|
// GenerateAccessToken 生成访问令牌
|
||||||
AccessToken string `json:"access_token"`
|
func (m *JWTManager) GenerateAccessToken(userID uint64) (string, *Claims, error) {
|
||||||
RefreshToken string `json:"refresh_token"`
|
token, claims, err := m.generateToken(userID, AccessToken, m.accessSecret, m.accessExpiry)
|
||||||
AccessTokenExpiresAt time.Time `json:"access_token_expires_at"`
|
if err != nil {
|
||||||
RefreshTokenExpiresAt time.Time `json:"refresh_token_expires_at"`
|
return "", nil, err
|
||||||
TokenType string `json:"token_type"`
|
}
|
||||||
|
|
||||||
|
// 存储到 Redis
|
||||||
|
if m.redis != nil {
|
||||||
|
m.storeToken(userID, token, claims.ExpiresAt.Time)
|
||||||
|
}
|
||||||
|
|
||||||
|
return token, claims, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GenerateRefreshToken 生成刷新令牌
|
||||||
|
func (m *JWTManager) GenerateRefreshToken(userID uint64) (string, *Claims, error) {
|
||||||
|
token, claims, err := m.generateToken(userID, RefreshToken, m.refreshSecret, m.refreshExpiry)
|
||||||
|
if err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 存储到 Redis
|
||||||
|
if m.redis != nil {
|
||||||
|
m.storeToken(userID, token, claims.ExpiresAt.Time)
|
||||||
|
}
|
||||||
|
|
||||||
|
return token, claims, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// generateToken 内部方法:生成令牌
|
||||||
|
func (m *JWTManager) generateToken(userID uint64, tokenType TokenType, secret []byte, expiry time.Duration) (string, *Claims, error) {
|
||||||
|
now := time.Now()
|
||||||
|
expireAt := now.Add(expiry)
|
||||||
|
|
||||||
|
claims := &Claims{
|
||||||
|
UserID: userID,
|
||||||
|
Type: tokenType,
|
||||||
|
RegisteredClaims: jwt.RegisteredClaims{
|
||||||
|
ExpiresAt: jwt.NewNumericDate(expireAt),
|
||||||
|
IssuedAt: jwt.NewNumericDate(now),
|
||||||
|
Issuer: m.issuer,
|
||||||
|
Subject: fmt.Sprintf("%d", userID),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||||
|
tokenString, err := token.SignedString(secret)
|
||||||
|
if err != nil {
|
||||||
|
return "", nil, fmt.Errorf("签名令牌失败: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return tokenString, claims, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== Token 验证方法 ====================
|
||||||
|
|
||||||
|
// VerifyAccessToken 验证访问令牌(包含黑名单检查)
|
||||||
|
func (m *JWTManager) VerifyAccessToken(tokenString string) (*Claims, error) {
|
||||||
|
return m.verifyToken(tokenString, AccessToken, m.accessSecret)
|
||||||
|
}
|
||||||
|
|
||||||
|
// VerifyRefreshToken 验证刷新令牌(包含黑名单检查)
|
||||||
|
func (m *JWTManager) VerifyRefreshToken(tokenString string) (*Claims, error) {
|
||||||
|
return m.verifyToken(tokenString, RefreshToken, m.refreshSecret)
|
||||||
|
}
|
||||||
|
|
||||||
|
// verifyToken 内部方法:验证令牌
|
||||||
|
func (m *JWTManager) verifyToken(tokenString string, expectedType TokenType, secret []byte) (*Claims, error) {
|
||||||
|
// 1. 检查令牌是否在黑名单中
|
||||||
|
if m.redis != nil {
|
||||||
|
blacklisted, err := m.isTokenBlacklisted(tokenString, expectedType)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("检查黑名单失败: %w", err)
|
||||||
|
}
|
||||||
|
if blacklisted {
|
||||||
|
return nil, errors.New("令牌已失效,请重新登录")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 验证 JWT
|
||||||
|
token, err := jwt.ParseWithClaims(tokenString, &Claims{}, func(token *jwt.Token) (interface{}, error) {
|
||||||
|
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
|
||||||
|
return nil, fmt.Errorf("不支持的签名方法: %v", token.Header["alg"])
|
||||||
|
}
|
||||||
|
return secret, nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("解析令牌失败: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if claims, ok := token.Claims.(*Claims); ok && token.Valid {
|
||||||
|
// 3. 检查令牌类型
|
||||||
|
if claims.Type != expectedType {
|
||||||
|
return nil, errors.New("令牌类型不匹配")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 检查令牌是否过期
|
||||||
|
if claims.ExpiresAt.Time.Before(time.Now()) {
|
||||||
|
return nil, errors.New("令牌已过期")
|
||||||
|
}
|
||||||
|
|
||||||
|
return claims, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, errors.New("无效的令牌")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== 黑名单管理 ====================
|
||||||
|
|
||||||
|
// BlacklistToken 将令牌加入黑名单
|
||||||
|
func (m *JWTManager) BlacklistToken(tokenString string) error {
|
||||||
|
if m.redis == nil {
|
||||||
|
return errors.New("redis 客户端未初始化")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 尝试解析令牌
|
||||||
|
claims, err := m.parseTokenWithoutBlacklistCheck(tokenString)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("无法识别令牌: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return m.addToBlacklist(tokenString, claims.Type, claims.ExpiresAt.Time)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BlacklistAccessToken 将访问令牌加入黑名单
|
||||||
|
func (m *JWTManager) BlacklistAccessToken(tokenString string) error {
|
||||||
|
if m.redis == nil {
|
||||||
|
return errors.New("redis 客户端未初始化")
|
||||||
|
}
|
||||||
|
|
||||||
|
claims, err := m.VerifyAccessToken(tokenString)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("无效的访问令牌: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return m.addToBlacklist(tokenString, AccessToken, claims.ExpiresAt.Time)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BlacklistRefreshToken 将刷新令牌加入黑名单
|
||||||
|
func (m *JWTManager) BlacklistRefreshToken(tokenString string) error {
|
||||||
|
if m.redis == nil {
|
||||||
|
return errors.New("redis 客户端未初始化")
|
||||||
|
}
|
||||||
|
|
||||||
|
claims, err := m.VerifyRefreshToken(tokenString)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("无效的刷新令牌: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return m.addToBlacklist(tokenString, RefreshToken, claims.ExpiresAt.Time)
|
||||||
|
}
|
||||||
|
|
||||||
|
// addToBlacklist 内部方法:将令牌加入黑名单
|
||||||
|
func (m *JWTManager) addToBlacklist(tokenString string, tokenType TokenType, expireTime time.Time) error {
|
||||||
|
remaining := time.Until(expireTime)
|
||||||
|
if remaining <= 0 {
|
||||||
|
// 令牌已过期,不需要加入黑名单
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
tokenHash := m.hashToken(tokenString)
|
||||||
|
blacklistKey := m.getBlacklistKey(tokenHash, tokenType)
|
||||||
|
|
||||||
|
// 设置黑名单,过期时间等于令牌剩余有效期
|
||||||
|
err := m.redis.Set(m.ctx, blacklistKey, "1", remaining).Err()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("设置黑名单失败: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 记录用户与令牌的关联(用于按用户清理)
|
||||||
|
if claims, err := m.parseTokenWithoutBlacklistCheck(tokenString); err == nil {
|
||||||
|
userTokenKey := m.getUserTokenKey(claims.UserID, tokenHash)
|
||||||
|
m.redis.Set(m.ctx, userTokenKey, tokenString, remaining)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsTokenBlacklisted 检查令牌是否在黑名单中
|
||||||
|
func (m *JWTManager) IsTokenBlacklisted(tokenString string) (bool, error) {
|
||||||
|
if m.redis == nil {
|
||||||
|
return false, errors.New("redis 客户端未初始化")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查所有类型的黑名单
|
||||||
|
tokenHash := m.hashToken(tokenString)
|
||||||
|
|
||||||
|
// 检查访问令牌黑名单
|
||||||
|
accessBlacklistKey := m.getBlacklistKey(tokenHash, AccessToken)
|
||||||
|
exists, err := m.redis.Exists(m.ctx, accessBlacklistKey).Result()
|
||||||
|
if err != nil {
|
||||||
|
return false, fmt.Errorf("检查访问令牌黑名单失败: %w", err)
|
||||||
|
}
|
||||||
|
if exists > 0 {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查刷新令牌黑名单
|
||||||
|
refreshBlacklistKey := m.getBlacklistKey(tokenHash, RefreshToken)
|
||||||
|
exists, err = m.redis.Exists(m.ctx, refreshBlacklistKey).Result()
|
||||||
|
if err != nil {
|
||||||
|
return false, fmt.Errorf("检查刷新令牌黑名单失败: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return exists > 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// isTokenBlacklisted 内部方法:检查令牌是否在黑名单中
|
||||||
|
func (m *JWTManager) isTokenBlacklisted(tokenString string, tokenType TokenType) (bool, error) {
|
||||||
|
if m.redis == nil {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
tokenHash := m.hashToken(tokenString)
|
||||||
|
blacklistKey := m.getBlacklistKey(tokenHash, tokenType)
|
||||||
|
|
||||||
|
exists, err := m.redis.Exists(m.ctx, blacklistKey).Result()
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return exists > 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveFromBlacklist 从黑名单中移除令牌
|
||||||
|
func (m *JWTManager) RemoveFromBlacklist(tokenString string) error {
|
||||||
|
if m.redis == nil {
|
||||||
|
return errors.New("redis 客户端未初始化")
|
||||||
|
}
|
||||||
|
|
||||||
|
tokenHash := m.hashToken(tokenString)
|
||||||
|
|
||||||
|
// 尝试移除两种类型的黑名单
|
||||||
|
accessBlacklistKey := m.getBlacklistKey(tokenHash, AccessToken)
|
||||||
|
refreshBlacklistKey := m.getBlacklistKey(tokenHash, RefreshToken)
|
||||||
|
|
||||||
|
err := m.redis.Del(m.ctx, accessBlacklistKey, refreshBlacklistKey).Err()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// RevokeUserTokens 撤销用户所有令牌
|
||||||
|
func (m *JWTManager) RevokeUserTokens(userID uint64) error {
|
||||||
|
if m.redis == nil {
|
||||||
|
return errors.New("redis 客户端未初始化")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取用户的所有令牌
|
||||||
|
tokens, err := m.GetUserTokens(userID)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("获取用户令牌失败: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将所有令牌加入黑名单
|
||||||
|
for _, token := range tokens {
|
||||||
|
m.BlacklistToken(token)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清理用户令牌集合
|
||||||
|
userTokenSetKey := m.getUserTokenSetKey(userID)
|
||||||
|
err = m.redis.Del(m.ctx, userTokenSetKey).Err()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("清理用户令牌集合失败: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== 用户令牌管理 ====================
|
||||||
|
|
||||||
|
// storeToken 存储用户令牌
|
||||||
|
func (m *JWTManager) storeToken(userID uint64, tokenString string, expireTime time.Time) {
|
||||||
|
if m.redis == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将令牌添加到用户的令牌集合
|
||||||
|
userTokenSetKey := m.getUserTokenSetKey(userID)
|
||||||
|
err := m.redis.SAdd(m.ctx, userTokenSetKey, tokenString).Err()
|
||||||
|
if err != nil {
|
||||||
|
// 记录错误但继续执行
|
||||||
|
fmt.Printf("存储用户令牌失败: %v\n", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置集合的过期时间(比令牌晚 1 小时)
|
||||||
|
expireAt := expireTime.Add(time.Hour)
|
||||||
|
err = m.redis.ExpireAt(m.ctx, userTokenSetKey, expireAt).Err()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("设置集合过期时间失败: %v\n", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUserTokens 获取用户的所有令牌
|
||||||
|
func (m *JWTManager) GetUserTokens(userID uint64) ([]string, error) {
|
||||||
|
if m.redis == nil {
|
||||||
|
return nil, errors.New("redis 客户端未初始化")
|
||||||
|
}
|
||||||
|
|
||||||
|
userTokenSetKey := m.getUserTokenSetKey(userID)
|
||||||
|
return m.redis.SMembers(m.ctx, userTokenSetKey).Result()
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveUserToken 移除用户的特定令牌
|
||||||
|
func (m *JWTManager) RemoveUserToken(userID uint64, tokenString string) error {
|
||||||
|
if m.redis == nil {
|
||||||
|
return errors.New("redis 客户端未初始化")
|
||||||
|
}
|
||||||
|
|
||||||
|
userTokenSetKey := m.getUserTokenSetKey(userID)
|
||||||
|
err := m.redis.SRem(m.ctx, userTokenSetKey, tokenString).Err()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== 令牌刷新 ====================
|
||||||
|
|
||||||
|
// RefreshTokens 使用刷新令牌获取新的令牌对
|
||||||
|
func (m *JWTManager) RefreshTokens(refreshToken string) (*TokenPair, error) {
|
||||||
|
// 验证刷新令牌
|
||||||
|
claims, err := m.VerifyRefreshToken(refreshToken)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("刷新令牌验证失败: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将旧的刷新令牌加入黑名单
|
||||||
|
if err := m.BlacklistRefreshToken(refreshToken); err != nil {
|
||||||
|
// 记录日志但继续执行
|
||||||
|
fmt.Printf("警告:将旧刷新令牌加入黑名单失败: %v\n", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成新的令牌对
|
||||||
|
return m.GenerateTokenPair(claims.UserID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== 辅助方法 ====================
|
||||||
|
|
||||||
|
// parseTokenWithoutBlacklistCheck 解析令牌但不检查黑名单
|
||||||
|
func (m *JWTManager) parseTokenWithoutBlacklistCheck(tokenString string) (*Claims, error) {
|
||||||
|
// 尝试作为访问令牌解析
|
||||||
|
token, err := jwt.ParseWithClaims(tokenString, &Claims{}, func(token *jwt.Token) (interface{}, error) {
|
||||||
|
return m.accessSecret, nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if err == nil && token.Valid {
|
||||||
|
if claims, ok := token.Claims.(*Claims); ok {
|
||||||
|
return claims, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 尝试作为刷新令牌解析
|
||||||
|
token, err = jwt.ParseWithClaims(tokenString, &Claims{}, func(token *jwt.Token) (interface{}, error) {
|
||||||
|
return m.refreshSecret, nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if claims, ok := token.Claims.(*Claims); ok && token.Valid {
|
||||||
|
return claims, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, errors.New("无法解析令牌")
|
||||||
|
}
|
||||||
|
|
||||||
|
// hashToken 生成令牌的哈希值
|
||||||
|
func (m *JWTManager) hashToken(token string) string {
|
||||||
|
hash := md5.Sum([]byte(token))
|
||||||
|
return hex.EncodeToString(hash[:])
|
||||||
|
}
|
||||||
|
|
||||||
|
// getBlacklistKey 获取黑名单键名
|
||||||
|
func (m *JWTManager) getBlacklistKey(tokenHash string, tokenType TokenType) string {
|
||||||
|
return fmt.Sprintf("%sblacklist:%s:%s", m.prefix, tokenType, tokenHash)
|
||||||
|
}
|
||||||
|
|
||||||
|
// getUserTokenSetKey 获取用户令牌集合键名
|
||||||
|
func (m *JWTManager) getUserTokenSetKey(userID uint64) string {
|
||||||
|
return fmt.Sprintf("%suser:tokens:%d", m.prefix, userID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// getUserTokenKey 获取用户令牌键名
|
||||||
|
func (m *JWTManager) getUserTokenKey(userID uint64, tokenHash string) string {
|
||||||
|
return fmt.Sprintf("%suser:%d:token:%s", m.prefix, userID, tokenHash)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== 工具方法 ====================
|
||||||
|
|
||||||
|
// GetTokenInfo 获取令牌信息
|
||||||
|
func (m *JWTManager) GetTokenInfo(tokenString string) (map[string]interface{}, error) {
|
||||||
|
claims, err := m.parseTokenWithoutBlacklistCheck(tokenString)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
info := map[string]interface{}{
|
||||||
|
"user_id": claims.UserID,
|
||||||
|
"token_type": claims.Type,
|
||||||
|
"issued_at": claims.IssuedAt.Time.Format(time.RFC3339),
|
||||||
|
"expires_at": claims.ExpiresAt.Time.Format(time.RFC3339),
|
||||||
|
"issuer": claims.Issuer,
|
||||||
|
"subject": claims.Subject,
|
||||||
|
"remaining": time.Until(claims.ExpiresAt.Time).String(),
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否在黑名单中
|
||||||
|
if m.redis != nil {
|
||||||
|
blacklisted, _ := m.IsTokenBlacklisted(tokenString)
|
||||||
|
info["blacklisted"] = blacklisted
|
||||||
|
}
|
||||||
|
|
||||||
|
return info, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidateAndExtract 验证令牌并提取用户ID
|
||||||
|
func (m *JWTManager) ValidateAndExtract(tokenString string) (uint64, error) {
|
||||||
|
claims, err := m.VerifyAccessToken(tokenString)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return claims.UserID, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cleanup 清理过期的令牌数据
|
||||||
|
func (m *JWTManager) Cleanup() error {
|
||||||
|
if m.redis == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Redis 会自动清理过期的键
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetBlacklistStats 获取黑名单统计信息
|
||||||
|
func (m *JWTManager) GetBlacklistStats() (map[string]interface{}, error) {
|
||||||
|
if m.redis == nil {
|
||||||
|
return nil, errors.New("redis 客户端未初始化")
|
||||||
|
}
|
||||||
|
|
||||||
|
stats := make(map[string]interface{})
|
||||||
|
|
||||||
|
// 获取访问令牌黑名单数量
|
||||||
|
accessPattern := fmt.Sprintf("%sblacklist:access:*", m.prefix)
|
||||||
|
accessKeys, err := m.redis.Keys(m.ctx, accessPattern).Result()
|
||||||
|
if err == nil {
|
||||||
|
stats["access_token_blacklist_count"] = len(accessKeys)
|
||||||
|
} else {
|
||||||
|
stats["access_token_blacklist_count"] = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取刷新令牌黑名单数量
|
||||||
|
refreshPattern := fmt.Sprintf("%sblacklist:refresh:*", m.prefix)
|
||||||
|
refreshKeys, err := m.redis.Keys(m.ctx, refreshPattern).Result()
|
||||||
|
if err == nil {
|
||||||
|
stats["refresh_token_blacklist_count"] = len(refreshKeys)
|
||||||
|
} else {
|
||||||
|
stats["refresh_token_blacklist_count"] = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return stats, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ping 检查 Redis 连接
|
||||||
|
func (m *JWTManager) Ping() error {
|
||||||
|
if m.redis == nil {
|
||||||
|
return errors.New("redis 客户端未初始化")
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := m.redis.Ping(m.ctx).Result()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close 关闭 Redis 连接
|
||||||
|
func (m *JWTManager) Close() error {
|
||||||
|
if m.redis == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return m.redis.Close()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ func NewAuthTokenLogic(ctx context.Context, svcCtx *svc.ServiceContext) *TokenLo
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
svcCtx: svcCtx,
|
svcCtx: svcCtx,
|
||||||
Logger: logx.WithContext(ctx),
|
Logger: logx.WithContext(ctx),
|
||||||
jwtManager: jwt_manager.NewJWTManager(&svcCtx.Config.JWTConf),
|
jwtManager: jwt_manager.NewJWTManager(&svcCtx.Config.JWTConf, svcCtx.Redis),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -36,7 +36,7 @@ func (l *TokenLogic) AuthToken(in *app.AuthReq) (*app.AuthInfoResp, error) {
|
||||||
}
|
}
|
||||||
return &app.AuthInfoResp{
|
return &app.AuthInfoResp{
|
||||||
UserId: token.UserID,
|
UserId: token.UserID,
|
||||||
Type: token.Type,
|
Type: string(token.Type),
|
||||||
Claims: &app.RegisteredClaims{
|
Claims: &app.RegisteredClaims{
|
||||||
IssuedAt: &app.NumericDate{
|
IssuedAt: &app.NumericDate{
|
||||||
Timestamp: ×tamppb.Timestamp{
|
Timestamp: ×tamppb.Timestamp{
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ func NewLoginUserLogic(ctx context.Context, svcCtx *svc.ServiceContext) *LoginUs
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
svcCtx: svcCtx,
|
svcCtx: svcCtx,
|
||||||
Logger: logx.WithContext(ctx),
|
Logger: logx.WithContext(ctx),
|
||||||
jwt: jwt_manager.NewJWTManager(&svcCtx.Config.JWTConf),
|
jwt: jwt_manager.NewJWTManager(&svcCtx.Config.JWTConf, nil),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
package user
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"mingyang-admin-app-rpc/internal/jwt_manager"
|
||||||
|
"mingyang-admin-app-rpc/internal/util/dberrorhandler"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"mingyang-admin-app-rpc/internal/svc"
|
||||||
|
"mingyang-admin-app-rpc/types/app"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type LogoutUserLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
jwtManager *jwt_manager.JWTManager
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewLogoutUserLogic(ctx context.Context, svcCtx *svc.ServiceContext) *LogoutUserLogic {
|
||||||
|
return &LogoutUserLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
jwtManager: jwt_manager.NewJWTManager(&svcCtx.Config.JWTConf, svcCtx.Redis),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// LogoutUser 用户退出登录
|
||||||
|
func (l *LogoutUserLogic) LogoutUser(in *app.UserToken) (*app.LogoutUserRequest, error) {
|
||||||
|
// 记录开始时间
|
||||||
|
start := time.Now()
|
||||||
|
l.Logger.Info("LogoutUser started token =", in.AccessToken)
|
||||||
|
accessToken := in.GetAccessToken()
|
||||||
|
_, err := l.jwtManager.VerifyAccessToken(accessToken)
|
||||||
|
if err != nil {
|
||||||
|
l.Logger.Error("Verify access token failed", "error", err, "time", time.Since(start))
|
||||||
|
return nil, dberrorhandler.DefaultEntError(l.Logger, err, in)
|
||||||
|
}
|
||||||
|
err = l.jwtManager.BlacklistToken(accessToken)
|
||||||
|
if err != nil {
|
||||||
|
l.Logger.Error("Blacklist token failed", "error", err, "time", time.Since(start))
|
||||||
|
return nil, dberrorhandler.DefaultEntError(l.Logger, err, in)
|
||||||
|
}
|
||||||
|
return &app.LogoutUserRequest{
|
||||||
|
AccessToken: accessToken,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
@ -30,7 +30,7 @@ func NewRegisterUserLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Regi
|
||||||
return &RegisterUserLogic{
|
return &RegisterUserLogic{
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
svcCtx: svcCtx,
|
svcCtx: svcCtx,
|
||||||
jwtManager: jwt_manager.NewJWTManager(&svcCtx.Config.JWTConf),
|
jwtManager: jwt_manager.NewJWTManager(&svcCtx.Config.JWTConf, svcCtx.Redis),
|
||||||
Logger: logx.WithContext(ctx),
|
Logger: logx.WithContext(ctx),
|
||||||
cacheRepo: cacherepo.NewCacheRepository(ctx, svcCtx),
|
cacheRepo: cacherepo.NewCacheRepository(ctx, svcCtx),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,12 @@ func (s *AppServer) ListUsers(ctx context.Context, in *app.PageUserRequest) (*ap
|
||||||
return l.ListUsers(in)
|
return l.ListUsers(in)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 用户退出登录
|
||||||
|
func (s *AppServer) LogoutUser(ctx context.Context, in *app.UserToken) (*app.LogoutUserRequest, error) {
|
||||||
|
l := user.NewLogoutUserLogic(ctx, s.svcCtx)
|
||||||
|
return l.LogoutUser(in)
|
||||||
|
}
|
||||||
|
|
||||||
func (s *AppServer) InitDatabase(ctx context.Context, in *app.Empty) (*app.BaseResp, error) {
|
func (s *AppServer) InitDatabase(ctx context.Context, in *app.Empty) (*app.BaseResp, error) {
|
||||||
l := base.NewInitDatabaseLogic(ctx, s.svcCtx)
|
l := base.NewInitDatabaseLogic(ctx, s.svcCtx)
|
||||||
return l.InitDatabase(in)
|
return l.InitDatabase(in)
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
package service
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.36.10
|
// protoc-gen-go v1.36.10
|
||||||
// protoc v3.21.11
|
// protoc v3.19.4
|
||||||
// source: app.proto
|
// source: app.proto
|
||||||
|
|
||||||
package app
|
package app
|
||||||
|
|
@ -821,6 +821,50 @@ func (x *LoginResponse) GetAuthToken() *AuthToken {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type LogoutUserRequest struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
AccessToken string `protobuf:"bytes,1,opt,name=access_token,json=accessToken,proto3" json:"access_token"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *LogoutUserRequest) Reset() {
|
||||||
|
*x = LogoutUserRequest{}
|
||||||
|
mi := &file_app_proto_msgTypes[13]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *LogoutUserRequest) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*LogoutUserRequest) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *LogoutUserRequest) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_app_proto_msgTypes[13]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use LogoutUserRequest.ProtoReflect.Descriptor instead.
|
||||||
|
func (*LogoutUserRequest) Descriptor() ([]byte, []int) {
|
||||||
|
return file_app_proto_rawDescGZIP(), []int{13}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *LogoutUserRequest) GetAccessToken() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.AccessToken
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
// NumericDate 使用 timestamp 表示 JWT 中的时间字段
|
// NumericDate 使用 timestamp 表示 JWT 中的时间字段
|
||||||
type NumericDate struct {
|
type NumericDate struct {
|
||||||
state protoimpl.MessageState `protogen:"open.v1"`
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
|
@ -831,7 +875,7 @@ type NumericDate struct {
|
||||||
|
|
||||||
func (x *NumericDate) Reset() {
|
func (x *NumericDate) Reset() {
|
||||||
*x = NumericDate{}
|
*x = NumericDate{}
|
||||||
mi := &file_app_proto_msgTypes[13]
|
mi := &file_app_proto_msgTypes[14]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
|
|
@ -843,7 +887,7 @@ func (x *NumericDate) String() string {
|
||||||
func (*NumericDate) ProtoMessage() {}
|
func (*NumericDate) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *NumericDate) ProtoReflect() protoreflect.Message {
|
func (x *NumericDate) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_app_proto_msgTypes[13]
|
mi := &file_app_proto_msgTypes[14]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
|
@ -856,7 +900,7 @@ func (x *NumericDate) ProtoReflect() protoreflect.Message {
|
||||||
|
|
||||||
// Deprecated: Use NumericDate.ProtoReflect.Descriptor instead.
|
// Deprecated: Use NumericDate.ProtoReflect.Descriptor instead.
|
||||||
func (*NumericDate) Descriptor() ([]byte, []int) {
|
func (*NumericDate) Descriptor() ([]byte, []int) {
|
||||||
return file_app_proto_rawDescGZIP(), []int{13}
|
return file_app_proto_rawDescGZIP(), []int{14}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *NumericDate) GetTimestamp() *timestamppb.Timestamp {
|
func (x *NumericDate) GetTimestamp() *timestamppb.Timestamp {
|
||||||
|
|
@ -876,7 +920,7 @@ type PageInfoReq struct {
|
||||||
|
|
||||||
func (x *PageInfoReq) Reset() {
|
func (x *PageInfoReq) Reset() {
|
||||||
*x = PageInfoReq{}
|
*x = PageInfoReq{}
|
||||||
mi := &file_app_proto_msgTypes[14]
|
mi := &file_app_proto_msgTypes[15]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
|
|
@ -888,7 +932,7 @@ func (x *PageInfoReq) String() string {
|
||||||
func (*PageInfoReq) ProtoMessage() {}
|
func (*PageInfoReq) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *PageInfoReq) ProtoReflect() protoreflect.Message {
|
func (x *PageInfoReq) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_app_proto_msgTypes[14]
|
mi := &file_app_proto_msgTypes[15]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
|
@ -901,7 +945,7 @@ func (x *PageInfoReq) ProtoReflect() protoreflect.Message {
|
||||||
|
|
||||||
// Deprecated: Use PageInfoReq.ProtoReflect.Descriptor instead.
|
// Deprecated: Use PageInfoReq.ProtoReflect.Descriptor instead.
|
||||||
func (*PageInfoReq) Descriptor() ([]byte, []int) {
|
func (*PageInfoReq) Descriptor() ([]byte, []int) {
|
||||||
return file_app_proto_rawDescGZIP(), []int{14}
|
return file_app_proto_rawDescGZIP(), []int{15}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *PageInfoReq) GetPage() uint64 {
|
func (x *PageInfoReq) GetPage() uint64 {
|
||||||
|
|
@ -933,7 +977,7 @@ type PageUserRequest struct {
|
||||||
|
|
||||||
func (x *PageUserRequest) Reset() {
|
func (x *PageUserRequest) Reset() {
|
||||||
*x = PageUserRequest{}
|
*x = PageUserRequest{}
|
||||||
mi := &file_app_proto_msgTypes[15]
|
mi := &file_app_proto_msgTypes[16]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
|
|
@ -945,7 +989,7 @@ func (x *PageUserRequest) String() string {
|
||||||
func (*PageUserRequest) ProtoMessage() {}
|
func (*PageUserRequest) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *PageUserRequest) ProtoReflect() protoreflect.Message {
|
func (x *PageUserRequest) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_app_proto_msgTypes[15]
|
mi := &file_app_proto_msgTypes[16]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
|
@ -958,7 +1002,7 @@ func (x *PageUserRequest) ProtoReflect() protoreflect.Message {
|
||||||
|
|
||||||
// Deprecated: Use PageUserRequest.ProtoReflect.Descriptor instead.
|
// Deprecated: Use PageUserRequest.ProtoReflect.Descriptor instead.
|
||||||
func (*PageUserRequest) Descriptor() ([]byte, []int) {
|
func (*PageUserRequest) Descriptor() ([]byte, []int) {
|
||||||
return file_app_proto_rawDescGZIP(), []int{15}
|
return file_app_proto_rawDescGZIP(), []int{16}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *PageUserRequest) GetPage() uint64 {
|
func (x *PageUserRequest) GetPage() uint64 {
|
||||||
|
|
@ -1020,7 +1064,7 @@ type PageUserResponse struct {
|
||||||
|
|
||||||
func (x *PageUserResponse) Reset() {
|
func (x *PageUserResponse) Reset() {
|
||||||
*x = PageUserResponse{}
|
*x = PageUserResponse{}
|
||||||
mi := &file_app_proto_msgTypes[16]
|
mi := &file_app_proto_msgTypes[17]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
|
|
@ -1032,7 +1076,7 @@ func (x *PageUserResponse) String() string {
|
||||||
func (*PageUserResponse) ProtoMessage() {}
|
func (*PageUserResponse) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *PageUserResponse) ProtoReflect() protoreflect.Message {
|
func (x *PageUserResponse) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_app_proto_msgTypes[16]
|
mi := &file_app_proto_msgTypes[17]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
|
@ -1045,7 +1089,7 @@ func (x *PageUserResponse) ProtoReflect() protoreflect.Message {
|
||||||
|
|
||||||
// Deprecated: Use PageUserResponse.ProtoReflect.Descriptor instead.
|
// Deprecated: Use PageUserResponse.ProtoReflect.Descriptor instead.
|
||||||
func (*PageUserResponse) Descriptor() ([]byte, []int) {
|
func (*PageUserResponse) Descriptor() ([]byte, []int) {
|
||||||
return file_app_proto_rawDescGZIP(), []int{16}
|
return file_app_proto_rawDescGZIP(), []int{17}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *PageUserResponse) GetTotal() uint64 {
|
func (x *PageUserResponse) GetTotal() uint64 {
|
||||||
|
|
@ -1080,7 +1124,7 @@ type RegisterUserRequest struct {
|
||||||
|
|
||||||
func (x *RegisterUserRequest) Reset() {
|
func (x *RegisterUserRequest) Reset() {
|
||||||
*x = RegisterUserRequest{}
|
*x = RegisterUserRequest{}
|
||||||
mi := &file_app_proto_msgTypes[17]
|
mi := &file_app_proto_msgTypes[18]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
|
|
@ -1092,7 +1136,7 @@ func (x *RegisterUserRequest) String() string {
|
||||||
func (*RegisterUserRequest) ProtoMessage() {}
|
func (*RegisterUserRequest) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *RegisterUserRequest) ProtoReflect() protoreflect.Message {
|
func (x *RegisterUserRequest) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_app_proto_msgTypes[17]
|
mi := &file_app_proto_msgTypes[18]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
|
@ -1105,7 +1149,7 @@ func (x *RegisterUserRequest) ProtoReflect() protoreflect.Message {
|
||||||
|
|
||||||
// Deprecated: Use RegisterUserRequest.ProtoReflect.Descriptor instead.
|
// Deprecated: Use RegisterUserRequest.ProtoReflect.Descriptor instead.
|
||||||
func (*RegisterUserRequest) Descriptor() ([]byte, []int) {
|
func (*RegisterUserRequest) Descriptor() ([]byte, []int) {
|
||||||
return file_app_proto_rawDescGZIP(), []int{17}
|
return file_app_proto_rawDescGZIP(), []int{18}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *RegisterUserRequest) GetEmail() string {
|
func (x *RegisterUserRequest) GetEmail() string {
|
||||||
|
|
@ -1190,7 +1234,7 @@ type RegisterUserResponse struct {
|
||||||
|
|
||||||
func (x *RegisterUserResponse) Reset() {
|
func (x *RegisterUserResponse) Reset() {
|
||||||
*x = RegisterUserResponse{}
|
*x = RegisterUserResponse{}
|
||||||
mi := &file_app_proto_msgTypes[18]
|
mi := &file_app_proto_msgTypes[19]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
|
|
@ -1202,7 +1246,7 @@ func (x *RegisterUserResponse) String() string {
|
||||||
func (*RegisterUserResponse) ProtoMessage() {}
|
func (*RegisterUserResponse) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *RegisterUserResponse) ProtoReflect() protoreflect.Message {
|
func (x *RegisterUserResponse) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_app_proto_msgTypes[18]
|
mi := &file_app_proto_msgTypes[19]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
|
@ -1215,7 +1259,7 @@ func (x *RegisterUserResponse) ProtoReflect() protoreflect.Message {
|
||||||
|
|
||||||
// Deprecated: Use RegisterUserResponse.ProtoReflect.Descriptor instead.
|
// Deprecated: Use RegisterUserResponse.ProtoReflect.Descriptor instead.
|
||||||
func (*RegisterUserResponse) Descriptor() ([]byte, []int) {
|
func (*RegisterUserResponse) Descriptor() ([]byte, []int) {
|
||||||
return file_app_proto_rawDescGZIP(), []int{18}
|
return file_app_proto_rawDescGZIP(), []int{19}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *RegisterUserResponse) GetUser() *UserInfo {
|
func (x *RegisterUserResponse) GetUser() *UserInfo {
|
||||||
|
|
@ -1269,7 +1313,7 @@ type RegisteredClaims struct {
|
||||||
|
|
||||||
func (x *RegisteredClaims) Reset() {
|
func (x *RegisteredClaims) Reset() {
|
||||||
*x = RegisteredClaims{}
|
*x = RegisteredClaims{}
|
||||||
mi := &file_app_proto_msgTypes[19]
|
mi := &file_app_proto_msgTypes[20]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
|
|
@ -1281,7 +1325,7 @@ func (x *RegisteredClaims) String() string {
|
||||||
func (*RegisteredClaims) ProtoMessage() {}
|
func (*RegisteredClaims) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *RegisteredClaims) ProtoReflect() protoreflect.Message {
|
func (x *RegisteredClaims) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_app_proto_msgTypes[19]
|
mi := &file_app_proto_msgTypes[20]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
|
@ -1294,7 +1338,7 @@ func (x *RegisteredClaims) ProtoReflect() protoreflect.Message {
|
||||||
|
|
||||||
// Deprecated: Use RegisteredClaims.ProtoReflect.Descriptor instead.
|
// Deprecated: Use RegisteredClaims.ProtoReflect.Descriptor instead.
|
||||||
func (*RegisteredClaims) Descriptor() ([]byte, []int) {
|
func (*RegisteredClaims) Descriptor() ([]byte, []int) {
|
||||||
return file_app_proto_rawDescGZIP(), []int{19}
|
return file_app_proto_rawDescGZIP(), []int{20}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *RegisteredClaims) GetIssuer() string {
|
func (x *RegisteredClaims) GetIssuer() string {
|
||||||
|
|
@ -1355,7 +1399,7 @@ type UUIDReq struct {
|
||||||
|
|
||||||
func (x *UUIDReq) Reset() {
|
func (x *UUIDReq) Reset() {
|
||||||
*x = UUIDReq{}
|
*x = UUIDReq{}
|
||||||
mi := &file_app_proto_msgTypes[20]
|
mi := &file_app_proto_msgTypes[21]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
|
|
@ -1367,7 +1411,7 @@ func (x *UUIDReq) String() string {
|
||||||
func (*UUIDReq) ProtoMessage() {}
|
func (*UUIDReq) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *UUIDReq) ProtoReflect() protoreflect.Message {
|
func (x *UUIDReq) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_app_proto_msgTypes[20]
|
mi := &file_app_proto_msgTypes[21]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
|
@ -1380,7 +1424,7 @@ func (x *UUIDReq) ProtoReflect() protoreflect.Message {
|
||||||
|
|
||||||
// Deprecated: Use UUIDReq.ProtoReflect.Descriptor instead.
|
// Deprecated: Use UUIDReq.ProtoReflect.Descriptor instead.
|
||||||
func (*UUIDReq) Descriptor() ([]byte, []int) {
|
func (*UUIDReq) Descriptor() ([]byte, []int) {
|
||||||
return file_app_proto_rawDescGZIP(), []int{20}
|
return file_app_proto_rawDescGZIP(), []int{21}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *UUIDReq) GetId() string {
|
func (x *UUIDReq) GetId() string {
|
||||||
|
|
@ -1399,7 +1443,7 @@ type UUIDsReq struct {
|
||||||
|
|
||||||
func (x *UUIDsReq) Reset() {
|
func (x *UUIDsReq) Reset() {
|
||||||
*x = UUIDsReq{}
|
*x = UUIDsReq{}
|
||||||
mi := &file_app_proto_msgTypes[21]
|
mi := &file_app_proto_msgTypes[22]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
|
|
@ -1411,7 +1455,7 @@ func (x *UUIDsReq) String() string {
|
||||||
func (*UUIDsReq) ProtoMessage() {}
|
func (*UUIDsReq) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *UUIDsReq) ProtoReflect() protoreflect.Message {
|
func (x *UUIDsReq) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_app_proto_msgTypes[21]
|
mi := &file_app_proto_msgTypes[22]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
|
@ -1424,7 +1468,7 @@ func (x *UUIDsReq) ProtoReflect() protoreflect.Message {
|
||||||
|
|
||||||
// Deprecated: Use UUIDsReq.ProtoReflect.Descriptor instead.
|
// Deprecated: Use UUIDsReq.ProtoReflect.Descriptor instead.
|
||||||
func (*UUIDsReq) Descriptor() ([]byte, []int) {
|
func (*UUIDsReq) Descriptor() ([]byte, []int) {
|
||||||
return file_app_proto_rawDescGZIP(), []int{21}
|
return file_app_proto_rawDescGZIP(), []int{22}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *UUIDsReq) GetIds() []string {
|
func (x *UUIDsReq) GetIds() []string {
|
||||||
|
|
@ -1464,7 +1508,7 @@ type UserInfo struct {
|
||||||
|
|
||||||
func (x *UserInfo) Reset() {
|
func (x *UserInfo) Reset() {
|
||||||
*x = UserInfo{}
|
*x = UserInfo{}
|
||||||
mi := &file_app_proto_msgTypes[22]
|
mi := &file_app_proto_msgTypes[23]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
|
|
@ -1476,7 +1520,7 @@ func (x *UserInfo) String() string {
|
||||||
func (*UserInfo) ProtoMessage() {}
|
func (*UserInfo) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *UserInfo) ProtoReflect() protoreflect.Message {
|
func (x *UserInfo) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_app_proto_msgTypes[22]
|
mi := &file_app_proto_msgTypes[23]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
|
@ -1489,7 +1533,7 @@ func (x *UserInfo) ProtoReflect() protoreflect.Message {
|
||||||
|
|
||||||
// Deprecated: Use UserInfo.ProtoReflect.Descriptor instead.
|
// Deprecated: Use UserInfo.ProtoReflect.Descriptor instead.
|
||||||
func (*UserInfo) Descriptor() ([]byte, []int) {
|
func (*UserInfo) Descriptor() ([]byte, []int) {
|
||||||
return file_app_proto_rawDescGZIP(), []int{22}
|
return file_app_proto_rawDescGZIP(), []int{23}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *UserInfo) GetId() uint64 {
|
func (x *UserInfo) GetId() uint64 {
|
||||||
|
|
@ -1646,6 +1690,58 @@ func (x *UserInfo) GetUpdatedAt() int64 {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type UserToken struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
AccessToken string `protobuf:"bytes,1,opt,name=access_token,json=accessToken,proto3" json:"access_token"`
|
||||||
|
UserId uint64 `protobuf:"varint,2,opt,name=user_id,json=userId,proto3" json:"user_id"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *UserToken) Reset() {
|
||||||
|
*x = UserToken{}
|
||||||
|
mi := &file_app_proto_msgTypes[24]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *UserToken) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*UserToken) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *UserToken) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_app_proto_msgTypes[24]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use UserToken.ProtoReflect.Descriptor instead.
|
||||||
|
func (*UserToken) Descriptor() ([]byte, []int) {
|
||||||
|
return file_app_proto_rawDescGZIP(), []int{24}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *UserToken) GetAccessToken() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.AccessToken
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *UserToken) GetUserId() uint64 {
|
||||||
|
if x != nil {
|
||||||
|
return x.UserId
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
type VerifyCodeReq struct {
|
type VerifyCodeReq struct {
|
||||||
state protoimpl.MessageState `protogen:"open.v1"`
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
Type VerifyCodeType `protobuf:"varint,1,opt,name=type,proto3,enum=app.VerifyCodeType" json:"type"`
|
Type VerifyCodeType `protobuf:"varint,1,opt,name=type,proto3,enum=app.VerifyCodeType" json:"type"`
|
||||||
|
|
@ -1657,7 +1753,7 @@ type VerifyCodeReq struct {
|
||||||
|
|
||||||
func (x *VerifyCodeReq) Reset() {
|
func (x *VerifyCodeReq) Reset() {
|
||||||
*x = VerifyCodeReq{}
|
*x = VerifyCodeReq{}
|
||||||
mi := &file_app_proto_msgTypes[23]
|
mi := &file_app_proto_msgTypes[25]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
|
|
@ -1669,7 +1765,7 @@ func (x *VerifyCodeReq) String() string {
|
||||||
func (*VerifyCodeReq) ProtoMessage() {}
|
func (*VerifyCodeReq) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *VerifyCodeReq) ProtoReflect() protoreflect.Message {
|
func (x *VerifyCodeReq) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_app_proto_msgTypes[23]
|
mi := &file_app_proto_msgTypes[25]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
|
@ -1682,7 +1778,7 @@ func (x *VerifyCodeReq) ProtoReflect() protoreflect.Message {
|
||||||
|
|
||||||
// Deprecated: Use VerifyCodeReq.ProtoReflect.Descriptor instead.
|
// Deprecated: Use VerifyCodeReq.ProtoReflect.Descriptor instead.
|
||||||
func (*VerifyCodeReq) Descriptor() ([]byte, []int) {
|
func (*VerifyCodeReq) Descriptor() ([]byte, []int) {
|
||||||
return file_app_proto_rawDescGZIP(), []int{23}
|
return file_app_proto_rawDescGZIP(), []int{25}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *VerifyCodeReq) GetType() VerifyCodeType {
|
func (x *VerifyCodeReq) GetType() VerifyCodeType {
|
||||||
|
|
@ -1716,7 +1812,7 @@ type VerifyCodeResp struct {
|
||||||
|
|
||||||
func (x *VerifyCodeResp) Reset() {
|
func (x *VerifyCodeResp) Reset() {
|
||||||
*x = VerifyCodeResp{}
|
*x = VerifyCodeResp{}
|
||||||
mi := &file_app_proto_msgTypes[24]
|
mi := &file_app_proto_msgTypes[26]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
|
|
@ -1728,7 +1824,7 @@ func (x *VerifyCodeResp) String() string {
|
||||||
func (*VerifyCodeResp) ProtoMessage() {}
|
func (*VerifyCodeResp) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *VerifyCodeResp) ProtoReflect() protoreflect.Message {
|
func (x *VerifyCodeResp) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_app_proto_msgTypes[24]
|
mi := &file_app_proto_msgTypes[26]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
|
@ -1741,7 +1837,7 @@ func (x *VerifyCodeResp) ProtoReflect() protoreflect.Message {
|
||||||
|
|
||||||
// Deprecated: Use VerifyCodeResp.ProtoReflect.Descriptor instead.
|
// Deprecated: Use VerifyCodeResp.ProtoReflect.Descriptor instead.
|
||||||
func (*VerifyCodeResp) Descriptor() ([]byte, []int) {
|
func (*VerifyCodeResp) Descriptor() ([]byte, []int) {
|
||||||
return file_app_proto_rawDescGZIP(), []int{24}
|
return file_app_proto_rawDescGZIP(), []int{26}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *VerifyCodeResp) GetCaptchaCode() string {
|
func (x *VerifyCodeResp) GetCaptchaCode() string {
|
||||||
|
|
@ -1809,7 +1905,9 @@ const file_app_proto_rawDesc = "" +
|
||||||
"\rLoginResponse\x12!\n" +
|
"\rLoginResponse\x12!\n" +
|
||||||
"\x04user\x18\x01 \x01(\v2\r.app.UserInfoR\x04user\x12-\n" +
|
"\x04user\x18\x01 \x01(\v2\r.app.UserInfoR\x04user\x12-\n" +
|
||||||
"\n" +
|
"\n" +
|
||||||
"auth_token\x18\x02 \x01(\v2\x0e.app.AuthTokenR\tauthToken\"G\n" +
|
"auth_token\x18\x02 \x01(\v2\x0e.app.AuthTokenR\tauthToken\"6\n" +
|
||||||
|
"\x11LogoutUserRequest\x12!\n" +
|
||||||
|
"\faccess_token\x18\x01 \x01(\tR\vaccessToken\"G\n" +
|
||||||
"\vNumericDate\x128\n" +
|
"\vNumericDate\x128\n" +
|
||||||
"\ttimestamp\x18\x01 \x01(\v2\x1a.google.protobuf.TimestampR\ttimestamp\">\n" +
|
"\ttimestamp\x18\x01 \x01(\v2\x1a.google.protobuf.TimestampR\ttimestamp\">\n" +
|
||||||
"\vPageInfoReq\x12\x12\n" +
|
"\vPageInfoReq\x12\x12\n" +
|
||||||
|
|
@ -1923,7 +2021,10 @@ const file_app_proto_rawDesc = "" +
|
||||||
"\x14_registration_sourceB\x0e\n" +
|
"\x14_registration_sourceB\x0e\n" +
|
||||||
"\f_birthday_atB\r\n" +
|
"\f_birthday_atB\r\n" +
|
||||||
"\v_created_atB\r\n" +
|
"\v_created_atB\r\n" +
|
||||||
"\v_updated_at\"\x83\x01\n" +
|
"\v_updated_at\"G\n" +
|
||||||
|
"\tUserToken\x12!\n" +
|
||||||
|
"\faccess_token\x18\x01 \x01(\tR\vaccessToken\x12\x17\n" +
|
||||||
|
"\auser_id\x18\x02 \x01(\x04R\x06userId\"\x83\x01\n" +
|
||||||
"\rVerifyCodeReq\x12'\n" +
|
"\rVerifyCodeReq\x12'\n" +
|
||||||
"\x04type\x18\x01 \x01(\x0e2\x13.app.VerifyCodeTypeR\x04type\x123\n" +
|
"\x04type\x18\x01 \x01(\x0e2\x13.app.VerifyCodeTypeR\x04type\x123\n" +
|
||||||
"\faccount_type\x18\x02 \x01(\x0e2\x10.app.AccountTypeR\vaccountType\x12\x14\n" +
|
"\faccount_type\x18\x02 \x01(\x0e2\x10.app.AccountTypeR\vaccountType\x12\x14\n" +
|
||||||
|
|
@ -1947,13 +2048,15 @@ const file_app_proto_rawDesc = "" +
|
||||||
"\fUPDATE_PHONE\x10\x05\x12\x10\n" +
|
"\fUPDATE_PHONE\x10\x05\x12\x10\n" +
|
||||||
"\fUPDATE_EMAIL\x10\x06\x12\f\n" +
|
"\fUPDATE_EMAIL\x10\x06\x12\f\n" +
|
||||||
"\bWITHDRAW\x10\a\x12\x17\n" +
|
"\bWITHDRAW\x10\a\x12\x17\n" +
|
||||||
"\x13CHANGE_PAY_PASSWORD\x10\b2\xcb\x02\n" +
|
"\x13CHANGE_PAY_PASSWORD\x10\b2\x81\x03\n" +
|
||||||
"\x03App\x12,\n" +
|
"\x03App\x12,\n" +
|
||||||
"\tAuthToken\x12\f.app.AuthReq\x1a\x11.app.AuthInfoResp\x128\n" +
|
"\tAuthToken\x12\f.app.AuthReq\x1a\x11.app.AuthInfoResp\x128\n" +
|
||||||
"\rGetVerifyCode\x12\x12.app.VerifyCodeReq\x1a\x13.app.VerifyCodeResp\x12C\n" +
|
"\rGetVerifyCode\x12\x12.app.VerifyCodeReq\x1a\x13.app.VerifyCodeResp\x12C\n" +
|
||||||
"\fRegisterUser\x12\x18.app.RegisterUserRequest\x1a\x19.app.RegisterUserResponse\x122\n" +
|
"\fRegisterUser\x12\x18.app.RegisterUserRequest\x1a\x19.app.RegisterUserResponse\x122\n" +
|
||||||
"\tLoginUser\x12\x11.app.LoginRequest\x1a\x12.app.LoginResponse\x128\n" +
|
"\tLoginUser\x12\x11.app.LoginRequest\x1a\x12.app.LoginResponse\x128\n" +
|
||||||
"\tListUsers\x12\x14.app.PageUserRequest\x1a\x15.app.PageUserResponse\x12)\n" +
|
"\tListUsers\x12\x14.app.PageUserRequest\x1a\x15.app.PageUserResponse\x124\n" +
|
||||||
|
"\n" +
|
||||||
|
"LogoutUser\x12\x0e.app.UserToken\x1a\x16.app.LogoutUserRequest\x12)\n" +
|
||||||
"\fInitDatabase\x12\n" +
|
"\fInitDatabase\x12\n" +
|
||||||
".app.Empty\x1a\r.app.BaseRespB\aZ\x05./appb\x06proto3"
|
".app.Empty\x1a\r.app.BaseRespB\aZ\x05./appb\x06proto3"
|
||||||
|
|
||||||
|
|
@ -1970,7 +2073,7 @@ func file_app_proto_rawDescGZIP() []byte {
|
||||||
}
|
}
|
||||||
|
|
||||||
var file_app_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
|
var file_app_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
|
||||||
var file_app_proto_msgTypes = make([]protoimpl.MessageInfo, 25)
|
var file_app_proto_msgTypes = make([]protoimpl.MessageInfo, 27)
|
||||||
var file_app_proto_goTypes = []any{
|
var file_app_proto_goTypes = []any{
|
||||||
(AccountType)(0), // 0: app.AccountType
|
(AccountType)(0), // 0: app.AccountType
|
||||||
(VerifyCodeType)(0), // 1: app.VerifyCodeType
|
(VerifyCodeType)(0), // 1: app.VerifyCodeType
|
||||||
|
|
@ -1987,53 +2090,57 @@ var file_app_proto_goTypes = []any{
|
||||||
(*IDsReq)(nil), // 12: app.IDsReq
|
(*IDsReq)(nil), // 12: app.IDsReq
|
||||||
(*LoginRequest)(nil), // 13: app.LoginRequest
|
(*LoginRequest)(nil), // 13: app.LoginRequest
|
||||||
(*LoginResponse)(nil), // 14: app.LoginResponse
|
(*LoginResponse)(nil), // 14: app.LoginResponse
|
||||||
(*NumericDate)(nil), // 15: app.NumericDate
|
(*LogoutUserRequest)(nil), // 15: app.LogoutUserRequest
|
||||||
(*PageInfoReq)(nil), // 16: app.PageInfoReq
|
(*NumericDate)(nil), // 16: app.NumericDate
|
||||||
(*PageUserRequest)(nil), // 17: app.PageUserRequest
|
(*PageInfoReq)(nil), // 17: app.PageInfoReq
|
||||||
(*PageUserResponse)(nil), // 18: app.PageUserResponse
|
(*PageUserRequest)(nil), // 18: app.PageUserRequest
|
||||||
(*RegisterUserRequest)(nil), // 19: app.RegisterUserRequest
|
(*PageUserResponse)(nil), // 19: app.PageUserResponse
|
||||||
(*RegisterUserResponse)(nil), // 20: app.RegisterUserResponse
|
(*RegisterUserRequest)(nil), // 20: app.RegisterUserRequest
|
||||||
(*RegisteredClaims)(nil), // 21: app.RegisteredClaims
|
(*RegisterUserResponse)(nil), // 21: app.RegisterUserResponse
|
||||||
(*UUIDReq)(nil), // 22: app.UUIDReq
|
(*RegisteredClaims)(nil), // 22: app.RegisteredClaims
|
||||||
(*UUIDsReq)(nil), // 23: app.UUIDsReq
|
(*UUIDReq)(nil), // 23: app.UUIDReq
|
||||||
(*UserInfo)(nil), // 24: app.UserInfo
|
(*UUIDsReq)(nil), // 24: app.UUIDsReq
|
||||||
(*VerifyCodeReq)(nil), // 25: app.VerifyCodeReq
|
(*UserInfo)(nil), // 25: app.UserInfo
|
||||||
(*VerifyCodeResp)(nil), // 26: app.VerifyCodeResp
|
(*UserToken)(nil), // 26: app.UserToken
|
||||||
(*timestamppb.Timestamp)(nil), // 27: google.protobuf.Timestamp
|
(*VerifyCodeReq)(nil), // 27: app.VerifyCodeReq
|
||||||
(*structpb.Struct)(nil), // 28: google.protobuf.Struct
|
(*VerifyCodeResp)(nil), // 28: app.VerifyCodeResp
|
||||||
|
(*timestamppb.Timestamp)(nil), // 29: google.protobuf.Timestamp
|
||||||
|
(*structpb.Struct)(nil), // 30: google.protobuf.Struct
|
||||||
}
|
}
|
||||||
var file_app_proto_depIdxs = []int32{
|
var file_app_proto_depIdxs = []int32{
|
||||||
21, // 0: app.AuthInfoResp.claims:type_name -> app.RegisteredClaims
|
22, // 0: app.AuthInfoResp.claims:type_name -> app.RegisteredClaims
|
||||||
27, // 1: app.AuthReq.time:type_name -> google.protobuf.Timestamp
|
29, // 1: app.AuthReq.time:type_name -> google.protobuf.Timestamp
|
||||||
27, // 2: app.AuthToken.access_token_expires:type_name -> google.protobuf.Timestamp
|
29, // 2: app.AuthToken.access_token_expires:type_name -> google.protobuf.Timestamp
|
||||||
27, // 3: app.AuthToken.refresh_token_expires:type_name -> google.protobuf.Timestamp
|
29, // 3: app.AuthToken.refresh_token_expires:type_name -> google.protobuf.Timestamp
|
||||||
24, // 4: app.LoginResponse.user:type_name -> app.UserInfo
|
25, // 4: app.LoginResponse.user:type_name -> app.UserInfo
|
||||||
4, // 5: app.LoginResponse.auth_token:type_name -> app.AuthToken
|
4, // 5: app.LoginResponse.auth_token:type_name -> app.AuthToken
|
||||||
27, // 6: app.NumericDate.timestamp:type_name -> google.protobuf.Timestamp
|
29, // 6: app.NumericDate.timestamp:type_name -> google.protobuf.Timestamp
|
||||||
24, // 7: app.PageUserResponse.data:type_name -> app.UserInfo
|
25, // 7: app.PageUserResponse.data:type_name -> app.UserInfo
|
||||||
24, // 8: app.RegisterUserResponse.user:type_name -> app.UserInfo
|
25, // 8: app.RegisterUserResponse.user:type_name -> app.UserInfo
|
||||||
4, // 9: app.RegisterUserResponse.auth_token:type_name -> app.AuthToken
|
4, // 9: app.RegisterUserResponse.auth_token:type_name -> app.AuthToken
|
||||||
9, // 10: app.RegisteredClaims.audience:type_name -> app.ClaimStrings
|
9, // 10: app.RegisteredClaims.audience:type_name -> app.ClaimStrings
|
||||||
15, // 11: app.RegisteredClaims.expires_at:type_name -> app.NumericDate
|
16, // 11: app.RegisteredClaims.expires_at:type_name -> app.NumericDate
|
||||||
15, // 12: app.RegisteredClaims.not_before:type_name -> app.NumericDate
|
16, // 12: app.RegisteredClaims.not_before:type_name -> app.NumericDate
|
||||||
15, // 13: app.RegisteredClaims.issued_at:type_name -> app.NumericDate
|
16, // 13: app.RegisteredClaims.issued_at:type_name -> app.NumericDate
|
||||||
28, // 14: app.UserInfo.metadata:type_name -> google.protobuf.Struct
|
30, // 14: app.UserInfo.metadata:type_name -> google.protobuf.Struct
|
||||||
1, // 15: app.VerifyCodeReq.type:type_name -> app.VerifyCodeType
|
1, // 15: app.VerifyCodeReq.type:type_name -> app.VerifyCodeType
|
||||||
0, // 16: app.VerifyCodeReq.account_type:type_name -> app.AccountType
|
0, // 16: app.VerifyCodeReq.account_type:type_name -> app.AccountType
|
||||||
3, // 17: app.App.AuthToken:input_type -> app.AuthReq
|
3, // 17: app.App.AuthToken:input_type -> app.AuthReq
|
||||||
25, // 18: app.App.GetVerifyCode:input_type -> app.VerifyCodeReq
|
27, // 18: app.App.GetVerifyCode:input_type -> app.VerifyCodeReq
|
||||||
19, // 19: app.App.RegisterUser:input_type -> app.RegisterUserRequest
|
20, // 19: app.App.RegisterUser:input_type -> app.RegisterUserRequest
|
||||||
13, // 20: app.App.LoginUser:input_type -> app.LoginRequest
|
13, // 20: app.App.LoginUser:input_type -> app.LoginRequest
|
||||||
17, // 21: app.App.ListUsers:input_type -> app.PageUserRequest
|
18, // 21: app.App.ListUsers:input_type -> app.PageUserRequest
|
||||||
10, // 22: app.App.InitDatabase:input_type -> app.Empty
|
26, // 22: app.App.LogoutUser:input_type -> app.UserToken
|
||||||
2, // 23: app.App.AuthToken:output_type -> app.AuthInfoResp
|
10, // 23: app.App.InitDatabase:input_type -> app.Empty
|
||||||
26, // 24: app.App.GetVerifyCode:output_type -> app.VerifyCodeResp
|
2, // 24: app.App.AuthToken:output_type -> app.AuthInfoResp
|
||||||
20, // 25: app.App.RegisterUser:output_type -> app.RegisterUserResponse
|
28, // 25: app.App.GetVerifyCode:output_type -> app.VerifyCodeResp
|
||||||
14, // 26: app.App.LoginUser:output_type -> app.LoginResponse
|
21, // 26: app.App.RegisterUser:output_type -> app.RegisterUserResponse
|
||||||
18, // 27: app.App.ListUsers:output_type -> app.PageUserResponse
|
14, // 27: app.App.LoginUser:output_type -> app.LoginResponse
|
||||||
7, // 28: app.App.InitDatabase:output_type -> app.BaseResp
|
19, // 28: app.App.ListUsers:output_type -> app.PageUserResponse
|
||||||
23, // [23:29] is the sub-list for method output_type
|
15, // 29: app.App.LogoutUser:output_type -> app.LogoutUserRequest
|
||||||
17, // [17:23] is the sub-list for method input_type
|
7, // 30: app.App.InitDatabase:output_type -> app.BaseResp
|
||||||
|
24, // [24:31] is the sub-list for method output_type
|
||||||
|
17, // [17:24] is the sub-list for method input_type
|
||||||
17, // [17:17] is the sub-list for extension type_name
|
17, // [17:17] is the sub-list for extension type_name
|
||||||
17, // [17:17] is the sub-list for extension extendee
|
17, // [17:17] is the sub-list for extension extendee
|
||||||
0, // [0:17] is the sub-list for field type_name
|
0, // [0:17] is the sub-list for field type_name
|
||||||
|
|
@ -2045,16 +2152,16 @@ func file_app_proto_init() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
file_app_proto_msgTypes[11].OneofWrappers = []any{}
|
file_app_proto_msgTypes[11].OneofWrappers = []any{}
|
||||||
file_app_proto_msgTypes[15].OneofWrappers = []any{}
|
file_app_proto_msgTypes[16].OneofWrappers = []any{}
|
||||||
file_app_proto_msgTypes[17].OneofWrappers = []any{}
|
file_app_proto_msgTypes[18].OneofWrappers = []any{}
|
||||||
file_app_proto_msgTypes[22].OneofWrappers = []any{}
|
file_app_proto_msgTypes[23].OneofWrappers = []any{}
|
||||||
type x struct{}
|
type x struct{}
|
||||||
out := protoimpl.TypeBuilder{
|
out := protoimpl.TypeBuilder{
|
||||||
File: protoimpl.DescBuilder{
|
File: protoimpl.DescBuilder{
|
||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_app_proto_rawDesc), len(file_app_proto_rawDesc)),
|
RawDescriptor: unsafe.Slice(unsafe.StringData(file_app_proto_rawDesc), len(file_app_proto_rawDesc)),
|
||||||
NumEnums: 2,
|
NumEnums: 2,
|
||||||
NumMessages: 25,
|
NumMessages: 27,
|
||||||
NumExtensions: 0,
|
NumExtensions: 0,
|
||||||
NumServices: 1,
|
NumServices: 1,
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// - protoc-gen-go-grpc v1.6.0
|
// - protoc-gen-go-grpc v1.5.1
|
||||||
// - protoc v3.21.11
|
// - protoc v3.19.4
|
||||||
// source: app.proto
|
// source: app.proto
|
||||||
|
|
||||||
package app
|
package app
|
||||||
|
|
@ -24,6 +24,7 @@ const (
|
||||||
App_RegisterUser_FullMethodName = "/app.App/RegisterUser"
|
App_RegisterUser_FullMethodName = "/app.App/RegisterUser"
|
||||||
App_LoginUser_FullMethodName = "/app.App/LoginUser"
|
App_LoginUser_FullMethodName = "/app.App/LoginUser"
|
||||||
App_ListUsers_FullMethodName = "/app.App/ListUsers"
|
App_ListUsers_FullMethodName = "/app.App/ListUsers"
|
||||||
|
App_LogoutUser_FullMethodName = "/app.App/LogoutUser"
|
||||||
App_InitDatabase_FullMethodName = "/app.App/InitDatabase"
|
App_InitDatabase_FullMethodName = "/app.App/InitDatabase"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -48,6 +49,9 @@ type AppClient interface {
|
||||||
// 分页查询用户信息
|
// 分页查询用户信息
|
||||||
// group: user
|
// group: user
|
||||||
ListUsers(ctx context.Context, in *PageUserRequest, opts ...grpc.CallOption) (*PageUserResponse, error)
|
ListUsers(ctx context.Context, in *PageUserRequest, opts ...grpc.CallOption) (*PageUserResponse, error)
|
||||||
|
// 用户退出登录
|
||||||
|
// group: user
|
||||||
|
LogoutUser(ctx context.Context, in *UserToken, opts ...grpc.CallOption) (*LogoutUserRequest, error)
|
||||||
// group: base
|
// group: base
|
||||||
InitDatabase(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*BaseResp, error)
|
InitDatabase(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*BaseResp, error)
|
||||||
}
|
}
|
||||||
|
|
@ -110,6 +114,16 @@ func (c *appClient) ListUsers(ctx context.Context, in *PageUserRequest, opts ...
|
||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *appClient) LogoutUser(ctx context.Context, in *UserToken, opts ...grpc.CallOption) (*LogoutUserRequest, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
|
out := new(LogoutUserRequest)
|
||||||
|
err := c.cc.Invoke(ctx, App_LogoutUser_FullMethodName, in, out, cOpts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *appClient) InitDatabase(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*BaseResp, error) {
|
func (c *appClient) InitDatabase(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*BaseResp, error) {
|
||||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(BaseResp)
|
out := new(BaseResp)
|
||||||
|
|
@ -141,6 +155,9 @@ type AppServer interface {
|
||||||
// 分页查询用户信息
|
// 分页查询用户信息
|
||||||
// group: user
|
// group: user
|
||||||
ListUsers(context.Context, *PageUserRequest) (*PageUserResponse, error)
|
ListUsers(context.Context, *PageUserRequest) (*PageUserResponse, error)
|
||||||
|
// 用户退出登录
|
||||||
|
// group: user
|
||||||
|
LogoutUser(context.Context, *UserToken) (*LogoutUserRequest, error)
|
||||||
// group: base
|
// group: base
|
||||||
InitDatabase(context.Context, *Empty) (*BaseResp, error)
|
InitDatabase(context.Context, *Empty) (*BaseResp, error)
|
||||||
mustEmbedUnimplementedAppServer()
|
mustEmbedUnimplementedAppServer()
|
||||||
|
|
@ -154,22 +171,25 @@ type AppServer interface {
|
||||||
type UnimplementedAppServer struct{}
|
type UnimplementedAppServer struct{}
|
||||||
|
|
||||||
func (UnimplementedAppServer) AuthToken(context.Context, *AuthReq) (*AuthInfoResp, error) {
|
func (UnimplementedAppServer) AuthToken(context.Context, *AuthReq) (*AuthInfoResp, error) {
|
||||||
return nil, status.Error(codes.Unimplemented, "method AuthToken not implemented")
|
return nil, status.Errorf(codes.Unimplemented, "method AuthToken not implemented")
|
||||||
}
|
}
|
||||||
func (UnimplementedAppServer) GetVerifyCode(context.Context, *VerifyCodeReq) (*VerifyCodeResp, error) {
|
func (UnimplementedAppServer) GetVerifyCode(context.Context, *VerifyCodeReq) (*VerifyCodeResp, error) {
|
||||||
return nil, status.Error(codes.Unimplemented, "method GetVerifyCode not implemented")
|
return nil, status.Errorf(codes.Unimplemented, "method GetVerifyCode not implemented")
|
||||||
}
|
}
|
||||||
func (UnimplementedAppServer) RegisterUser(context.Context, *RegisterUserRequest) (*RegisterUserResponse, error) {
|
func (UnimplementedAppServer) RegisterUser(context.Context, *RegisterUserRequest) (*RegisterUserResponse, error) {
|
||||||
return nil, status.Error(codes.Unimplemented, "method RegisterUser not implemented")
|
return nil, status.Errorf(codes.Unimplemented, "method RegisterUser not implemented")
|
||||||
}
|
}
|
||||||
func (UnimplementedAppServer) LoginUser(context.Context, *LoginRequest) (*LoginResponse, error) {
|
func (UnimplementedAppServer) LoginUser(context.Context, *LoginRequest) (*LoginResponse, error) {
|
||||||
return nil, status.Error(codes.Unimplemented, "method LoginUser not implemented")
|
return nil, status.Errorf(codes.Unimplemented, "method LoginUser not implemented")
|
||||||
}
|
}
|
||||||
func (UnimplementedAppServer) ListUsers(context.Context, *PageUserRequest) (*PageUserResponse, error) {
|
func (UnimplementedAppServer) ListUsers(context.Context, *PageUserRequest) (*PageUserResponse, error) {
|
||||||
return nil, status.Error(codes.Unimplemented, "method ListUsers not implemented")
|
return nil, status.Errorf(codes.Unimplemented, "method ListUsers not implemented")
|
||||||
|
}
|
||||||
|
func (UnimplementedAppServer) LogoutUser(context.Context, *UserToken) (*LogoutUserRequest, error) {
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method LogoutUser not implemented")
|
||||||
}
|
}
|
||||||
func (UnimplementedAppServer) InitDatabase(context.Context, *Empty) (*BaseResp, error) {
|
func (UnimplementedAppServer) InitDatabase(context.Context, *Empty) (*BaseResp, error) {
|
||||||
return nil, status.Error(codes.Unimplemented, "method InitDatabase not implemented")
|
return nil, status.Errorf(codes.Unimplemented, "method InitDatabase not implemented")
|
||||||
}
|
}
|
||||||
func (UnimplementedAppServer) mustEmbedUnimplementedAppServer() {}
|
func (UnimplementedAppServer) mustEmbedUnimplementedAppServer() {}
|
||||||
func (UnimplementedAppServer) testEmbeddedByValue() {}
|
func (UnimplementedAppServer) testEmbeddedByValue() {}
|
||||||
|
|
@ -182,7 +202,7 @@ type UnsafeAppServer interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
func RegisterAppServer(s grpc.ServiceRegistrar, srv AppServer) {
|
func RegisterAppServer(s grpc.ServiceRegistrar, srv AppServer) {
|
||||||
// If the following call panics, it indicates UnimplementedAppServer was
|
// If the following call pancis, it indicates UnimplementedAppServer was
|
||||||
// embedded by pointer and is nil. This will cause panics if an
|
// embedded by pointer and is nil. This will cause panics if an
|
||||||
// unimplemented method is ever invoked, so we test this at initialization
|
// unimplemented method is ever invoked, so we test this at initialization
|
||||||
// time to prevent it from happening at runtime later due to I/O.
|
// time to prevent it from happening at runtime later due to I/O.
|
||||||
|
|
@ -282,6 +302,24 @@ func _App_ListUsers_Handler(srv interface{}, ctx context.Context, dec func(inter
|
||||||
return interceptor(ctx, in, info, handler)
|
return interceptor(ctx, in, info, handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func _App_LogoutUser_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(UserToken)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(AppServer).LogoutUser(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: App_LogoutUser_FullMethodName,
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(AppServer).LogoutUser(ctx, req.(*UserToken))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
func _App_InitDatabase_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
func _App_InitDatabase_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
in := new(Empty)
|
in := new(Empty)
|
||||||
if err := dec(in); err != nil {
|
if err := dec(in); err != nil {
|
||||||
|
|
@ -327,6 +365,10 @@ var App_ServiceDesc = grpc.ServiceDesc{
|
||||||
MethodName: "ListUsers",
|
MethodName: "ListUsers",
|
||||||
Handler: _App_ListUsers_Handler,
|
Handler: _App_ListUsers_Handler,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
MethodName: "LogoutUser",
|
||||||
|
Handler: _App_LogoutUser_Handler,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
MethodName: "InitDatabase",
|
MethodName: "InitDatabase",
|
||||||
Handler: _App_InitDatabase_Handler,
|
Handler: _App_InitDatabase_Handler,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue