add Refresh
CI / changes (push) Successful in 6s
CI / docker-bff (push) Successful in 8s
CI / docker-product (push) Failing after 2s

This commit is contained in:
2026-08-10 18:05:29 +08:00
parent 7228d3fedc
commit 9865f7dae9
16 changed files with 390 additions and 245 deletions
+54 -13
View File
@@ -510,6 +510,42 @@ func (x *AdminLoginRequest) GetPassword() string {
return ""
}
type AdminEmptyRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *AdminEmptyRequest) Reset() {
*x = AdminEmptyRequest{}
mi := &file_proto_admin_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *AdminEmptyRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*AdminEmptyRequest) ProtoMessage() {}
func (x *AdminEmptyRequest) ProtoReflect() protoreflect.Message {
mi := &file_proto_admin_proto_msgTypes[8]
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 AdminEmptyRequest.ProtoReflect.Descriptor instead.
func (*AdminEmptyRequest) Descriptor() ([]byte, []int) {
return file_proto_admin_proto_rawDescGZIP(), []int{8}
}
var File_proto_admin_proto protoreflect.FileDescriptor
const file_proto_admin_proto_rawDesc = "" +
@@ -547,7 +583,8 @@ const file_proto_admin_proto_rawDesc = "" +
"\x06status\x18\a \x01(\x05R\x06status\"K\n" +
"\x11AdminLoginRequest\x12\x1a\n" +
"\busername\x18\x01 \x01(\tR\busername\x12\x1a\n" +
"\bpassword\x18\x02 \x01(\tR\bpassword2\xfe\x04\n" +
"\bpassword\x18\x02 \x01(\tR\bpassword\"\x13\n" +
"\x11AdminEmptyRequest2\xd7\x05\n" +
"\x05Admin\x12V\n" +
"\tAdminEdit\x12\x17.admin.AdminEditRequest\x1a\x0f.admin.Response\"\x1f\x82\xd3\xe4\x93\x02\x19:\x01*\"\x14/admin/v3/admin/edit\x12W\n" +
"\vAdminStatus\x12\x14.admin.StatusRequest\x1a\x0f.admin.Response\"!\x82\xd3\xe4\x93\x02\x1b:\x01*\"\x16/admin/v3/admin/status\x12X\n" +
@@ -557,7 +594,8 @@ const file_proto_admin_proto_rawDesc = "" +
"\n" +
"AdminItems\x12\x18.admin.AdminItemsRequest\x1a\x0f.admin.Response\" \x82\xd3\xe4\x93\x02\x1a:\x01*\x12\x15/admin/v3/admin/items\x12S\n" +
"\n" +
"AdminLogin\x12\x18.admin.AdminLoginRequest\x1a\x0f.admin.Response\"\x1a\x82\xd3\xe4\x93\x02\x14:\x01*\"\x0f/admin/v3/loginB\tZ\a./adminb\x06proto3"
"AdminLogin\x12\x18.admin.AdminLoginRequest\x1a\x0f.admin.Response\"\x1a\x82\xd3\xe4\x93\x02\x14:\x01*\"\x0f/admin/v3/login\x12W\n" +
"\fAdminRefresh\x12\x18.admin.AdminEmptyRequest\x1a\x0f.admin.Response\"\x1c\x82\xd3\xe4\x93\x02\x16:\x01*\"\x11/admin/v3/refreshB\tZ\a./adminb\x06proto3"
var (
file_proto_admin_proto_rawDescOnce sync.Once
@@ -571,7 +609,7 @@ func file_proto_admin_proto_rawDescGZIP() []byte {
return file_proto_admin_proto_rawDescData
}
var file_proto_admin_proto_msgTypes = make([]protoimpl.MessageInfo, 8)
var file_proto_admin_proto_msgTypes = make([]protoimpl.MessageInfo, 9)
var file_proto_admin_proto_goTypes = []any{
(*AdminEditRequest)(nil), // 0: admin.AdminEditRequest
(*StatusRequest)(nil), // 1: admin.StatusRequest
@@ -581,6 +619,7 @@ var file_proto_admin_proto_goTypes = []any{
(*AdminInfoRequest)(nil), // 5: admin.AdminInfoRequest
(*AdminItemsRequest)(nil), // 6: admin.AdminItemsRequest
(*AdminLoginRequest)(nil), // 7: admin.AdminLoginRequest
(*AdminEmptyRequest)(nil), // 8: admin.AdminEmptyRequest
}
var file_proto_admin_proto_depIdxs = []int32{
0, // 0: admin.Admin.AdminEdit:input_type -> admin.AdminEditRequest
@@ -590,15 +629,17 @@ var file_proto_admin_proto_depIdxs = []int32{
5, // 4: admin.Admin.AdminInfo:input_type -> admin.AdminInfoRequest
6, // 5: admin.Admin.AdminItems:input_type -> admin.AdminItemsRequest
7, // 6: admin.Admin.AdminLogin:input_type -> admin.AdminLoginRequest
2, // 7: admin.Admin.AdminEdit:output_type -> admin.Response
2, // 8: admin.Admin.AdminStatus:output_type -> admin.Response
2, // 9: admin.Admin.Password:output_type -> admin.Response
2, // 10: admin.Admin.OwnPassword:output_type -> admin.Response
2, // 11: admin.Admin.AdminInfo:output_type -> admin.Response
2, // 12: admin.Admin.AdminItems:output_type -> admin.Response
2, // 13: admin.Admin.AdminLogin:output_type -> admin.Response
7, // [7:14] is the sub-list for method output_type
0, // [0:7] is the sub-list for method input_type
8, // 7: admin.Admin.AdminRefresh:input_type -> admin.AdminEmptyRequest
2, // 8: admin.Admin.AdminEdit:output_type -> admin.Response
2, // 9: admin.Admin.AdminStatus:output_type -> admin.Response
2, // 10: admin.Admin.Password:output_type -> admin.Response
2, // 11: admin.Admin.OwnPassword:output_type -> admin.Response
2, // 12: admin.Admin.AdminInfo:output_type -> admin.Response
2, // 13: admin.Admin.AdminItems:output_type -> admin.Response
2, // 14: admin.Admin.AdminLogin:output_type -> admin.Response
2, // 15: admin.Admin.AdminRefresh:output_type -> admin.Response
8, // [8:16] is the sub-list for method output_type
0, // [0:8] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
@@ -615,7 +656,7 @@ func file_proto_admin_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_proto_admin_proto_rawDesc), len(file_proto_admin_proto_rawDesc)),
NumEnums: 0,
NumMessages: 8,
NumMessages: 9,
NumExtensions: 0,
NumServices: 1,
},
+45 -7
View File
@@ -19,13 +19,14 @@ import (
const _ = grpc.SupportPackageIsVersion9
const (
Admin_AdminEdit_FullMethodName = "/admin.Admin/AdminEdit"
Admin_AdminStatus_FullMethodName = "/admin.Admin/AdminStatus"
Admin_Password_FullMethodName = "/admin.Admin/Password"
Admin_OwnPassword_FullMethodName = "/admin.Admin/OwnPassword"
Admin_AdminInfo_FullMethodName = "/admin.Admin/AdminInfo"
Admin_AdminItems_FullMethodName = "/admin.Admin/AdminItems"
Admin_AdminLogin_FullMethodName = "/admin.Admin/AdminLogin"
Admin_AdminEdit_FullMethodName = "/admin.Admin/AdminEdit"
Admin_AdminStatus_FullMethodName = "/admin.Admin/AdminStatus"
Admin_Password_FullMethodName = "/admin.Admin/Password"
Admin_OwnPassword_FullMethodName = "/admin.Admin/OwnPassword"
Admin_AdminInfo_FullMethodName = "/admin.Admin/AdminInfo"
Admin_AdminItems_FullMethodName = "/admin.Admin/AdminItems"
Admin_AdminLogin_FullMethodName = "/admin.Admin/AdminLogin"
Admin_AdminRefresh_FullMethodName = "/admin.Admin/AdminRefresh"
)
// AdminClient is the client API for Admin service.
@@ -39,6 +40,7 @@ type AdminClient interface {
AdminInfo(ctx context.Context, in *AdminInfoRequest, opts ...grpc.CallOption) (*Response, error)
AdminItems(ctx context.Context, in *AdminItemsRequest, opts ...grpc.CallOption) (*Response, error)
AdminLogin(ctx context.Context, in *AdminLoginRequest, opts ...grpc.CallOption) (*Response, error)
AdminRefresh(ctx context.Context, in *AdminEmptyRequest, opts ...grpc.CallOption) (*Response, error)
}
type adminClient struct {
@@ -119,6 +121,16 @@ func (c *adminClient) AdminLogin(ctx context.Context, in *AdminLoginRequest, opt
return out, nil
}
func (c *adminClient) AdminRefresh(ctx context.Context, in *AdminEmptyRequest, opts ...grpc.CallOption) (*Response, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(Response)
err := c.cc.Invoke(ctx, Admin_AdminRefresh_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// AdminServer is the server API for Admin service.
// All implementations must embed UnimplementedAdminServer
// for forward compatibility.
@@ -130,6 +142,7 @@ type AdminServer interface {
AdminInfo(context.Context, *AdminInfoRequest) (*Response, error)
AdminItems(context.Context, *AdminItemsRequest) (*Response, error)
AdminLogin(context.Context, *AdminLoginRequest) (*Response, error)
AdminRefresh(context.Context, *AdminEmptyRequest) (*Response, error)
mustEmbedUnimplementedAdminServer()
}
@@ -161,6 +174,9 @@ func (UnimplementedAdminServer) AdminItems(context.Context, *AdminItemsRequest)
func (UnimplementedAdminServer) AdminLogin(context.Context, *AdminLoginRequest) (*Response, error) {
return nil, status.Error(codes.Unimplemented, "method AdminLogin not implemented")
}
func (UnimplementedAdminServer) AdminRefresh(context.Context, *AdminEmptyRequest) (*Response, error) {
return nil, status.Error(codes.Unimplemented, "method AdminRefresh not implemented")
}
func (UnimplementedAdminServer) mustEmbedUnimplementedAdminServer() {}
func (UnimplementedAdminServer) testEmbeddedByValue() {}
@@ -308,6 +324,24 @@ func _Admin_AdminLogin_Handler(srv interface{}, ctx context.Context, dec func(in
return interceptor(ctx, in, info, handler)
}
func _Admin_AdminRefresh_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(AdminEmptyRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(AdminServer).AdminRefresh(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: Admin_AdminRefresh_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(AdminServer).AdminRefresh(ctx, req.(*AdminEmptyRequest))
}
return interceptor(ctx, in, info, handler)
}
// Admin_ServiceDesc is the grpc.ServiceDesc for Admin service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
@@ -343,6 +377,10 @@ var Admin_ServiceDesc = grpc.ServiceDesc{
MethodName: "AdminLogin",
Handler: _Admin_AdminLogin_Handler,
},
{
MethodName: "AdminRefresh",
Handler: _Admin_AdminRefresh_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "proto/admin.proto",
+7 -6
View File
@@ -15,6 +15,7 @@ import (
type (
AdminEditRequest = admin.AdminEditRequest
AdminEmptyRequest = admin.AdminEmptyRequest
AdminInfoRequest = admin.AdminInfoRequest
AdminItemsRequest = admin.AdminItemsRequest
AdminLoginRequest = admin.AdminLoginRequest
@@ -24,7 +25,6 @@ type (
StatusRequest = admin.StatusRequest
Admin interface {
AdminAdd(ctx context.Context, in *AdminEditRequest, opts ...grpc.CallOption) (*Response, error)
AdminEdit(ctx context.Context, in *AdminEditRequest, opts ...grpc.CallOption) (*Response, error)
AdminStatus(ctx context.Context, in *StatusRequest, opts ...grpc.CallOption) (*Response, error)
Password(ctx context.Context, in *PasswordRequest, opts ...grpc.CallOption) (*Response, error)
@@ -32,6 +32,7 @@ type (
AdminInfo(ctx context.Context, in *AdminInfoRequest, opts ...grpc.CallOption) (*Response, error)
AdminItems(ctx context.Context, in *AdminItemsRequest, opts ...grpc.CallOption) (*Response, error)
AdminLogin(ctx context.Context, in *AdminLoginRequest, opts ...grpc.CallOption) (*Response, error)
AdminRefresh(ctx context.Context, in *AdminEmptyRequest, opts ...grpc.CallOption) (*Response, error)
}
defaultAdmin struct {
@@ -45,11 +46,6 @@ func NewAdmin(cli zrpc.Client) Admin {
}
}
func (m *defaultAdmin) AdminAdd(ctx context.Context, in *AdminEditRequest, opts ...grpc.CallOption) (*Response, error) {
client := admin.NewAdminClient(m.cli.Conn())
return client.AdminAdd(ctx, in, opts...)
}
func (m *defaultAdmin) AdminEdit(ctx context.Context, in *AdminEditRequest, opts ...grpc.CallOption) (*Response, error) {
client := admin.NewAdminClient(m.cli.Conn())
return client.AdminEdit(ctx, in, opts...)
@@ -84,3 +80,8 @@ func (m *defaultAdmin) AdminLogin(ctx context.Context, in *AdminLoginRequest, op
client := admin.NewAdminClient(m.cli.Conn())
return client.AdminLogin(ctx, in, opts...)
}
func (m *defaultAdmin) AdminRefresh(ctx context.Context, in *AdminEmptyRequest, opts ...grpc.CallOption) (*Response, error) {
client := admin.NewAdminClient(m.cli.Conn())
return client.AdminRefresh(ctx, in, opts...)
}
+2 -1
View File
@@ -16,7 +16,8 @@ type JwtInfo struct {
}
type Token struct {
Token string `json:"token"`
Token string `json:"token"`
Refresh string `json:"refresh"`
}
type JwtInfoServices struct {
+32 -15
View File
@@ -75,31 +75,48 @@ func (l *AdminLoginLogic) AdminLogin(in *admin.AdminLoginRequest) (*admin.Respon
retData := dao.Token{
Token: utils.MD5Encrypt(data.Phone + utils.Now().String()),
}
retData.Refresh = utils.MD5Encrypt(data.Phone + retData.Token)
l.setLogin(retData.Token, data)
l.setLogin(retData.Token, retData.Refresh, data)
return l.ok(retData), nil
}
func (l *AdminLoginLogic) setLogin(token string, data dao.JwtInfo) {
func (l *AdminLoginLogic) setLogin(token, refresh string, data dao.JwtInfo) {
//获取登录过期时间
expireMin := utils.GetConfigInt("base.login_out_time")
var expire time.Duration
// 默认使用配置时长
expire = time.Duration(expireMin) * time.Minute
// 如果用户自定义了过期时间则覆盖
if data.Time > utils.NumberZero {
expire = time.Duration(data.Time) * time.Minute
}
expire := time.Duration(expireMin) * time.Minute
//获取刷新登录过期时间
refreshMin := utils.GetConfigInt("base.login_refresh_out_time")
refreshExpire := time.Duration(refreshMin) * time.Minute
//登录信息写入redis
redisKey := utils.GetLoginKey(utils.LoginTypeAdmin, token)
l.Logger.Error(redisKey)
userStr, _ := jsoniter.Marshal(data)
ctx := context.Background()
redis.Client.Set(ctx, redisKey, userStr, expire).Result()
redisKeysKey := utils.GetLoginKeysKey(utils.LoginTypeAdmin)
oldAuth, oldErr := redis.Client.HGet(ctx, redisKeysKey, strconv.Itoa(int(data.Id))).Result()
//获取原来的token与refresh
redisKeysKey := utils.GetLoginKeysKey(utils.LoginTypeAdmin, strconv.FormatInt(data.Id, 10))
var LoginInfo utils.LoginRedis
oldAuth, oldErr := redis.Client.Get(ctx, redisKeysKey).Result()
//如果获取到了数据情况之前的
if oldErr == nil {
redis.Client.Del(ctx, utils.GetLoginKey(utils.LoginTypeAdmin, oldAuth)).Result()
_ = jsoniter.Unmarshal([]byte(oldAuth), &LoginInfo)
if len(LoginInfo.Token) > utils.NumberOne {
redis.Client.Del(ctx, utils.GetLoginKey(utils.LoginTypeAdmin, LoginInfo.Token)).Result()
}
if len(LoginInfo.Refresh) > utils.NumberOne {
redis.Client.Del(ctx, utils.GetLoginRefreshKey(utils.LoginTypeAdmin, LoginInfo.Refresh)).Result()
}
}
redis.Client.HSet(ctx, redisKeysKey, strconv.Itoa(int(data.Id)), token).Result()
//更新新的数据
LoginInfo.Token = token
LoginInfo.Refresh = refresh
LoginInfo.Info = userStr
newStr, _ := jsoniter.Marshal(LoginInfo)
redis.Client.Set(ctx, redisKeysKey, newStr, refreshExpire).Result()
//登录刷新信息写入redis
refreshKey := utils.GetLoginRefreshKey(utils.LoginTypeAdmin, refresh)
redis.Client.Set(ctx, refreshKey, strconv.FormatInt(data.Id, 10), refreshExpire).Result()
}
+86
View File
@@ -0,0 +1,86 @@
package logic
import (
"admin/internal/dao"
"context"
"time"
"admin/admin"
"admin/internal/svc"
jsoniter "github.com/json-iterator/go"
"github.com/zeromicro/go-zero/core/logx"
"pkg.local/redis"
"pkg.local/utils"
)
type AdminRefreshLogic struct {
ctx context.Context
svcCtx *svc.ServiceContext
logx.Logger
BaseLogic
}
func NewAdminRefreshLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminRefreshLogic {
return &AdminRefreshLogic{
ctx: ctx,
svcCtx: svcCtx,
Logger: logx.WithContext(ctx),
}
}
func (l *AdminRefreshLogic) AdminRefresh(in *admin.AdminEmptyRequest) (*admin.Response, error) {
adminInfo := utils.GetUserFromCtx(l.ctx)
l.Logger.Error(adminInfo)
if len(adminInfo.Refresh) < utils.NumberOne {
return l.fail(utils.ErrorNoLoginInfo), nil
}
//获取登录过期时间
expireMin := utils.GetConfigInt("base.login_out_time")
expire := time.Duration(expireMin) * time.Minute
//获取刷新登录过期时间
refreshMin := utils.GetConfigInt("base.login_refresh_out_time")
refreshExpire := time.Duration(refreshMin) * time.Minute
//登录信息写入redis
refreshKey := utils.GetLoginRefreshKey(utils.LoginTypeAdmin, adminInfo.Refresh)
ctx := context.Background()
id, err := redis.Client.Get(ctx, refreshKey).Result()
if err != nil {
return l.fail(utils.ErrorNoLoginInfo), nil
}
//获取原来的token与refresh
redisKeysKey := utils.GetLoginKeysKey(utils.LoginTypeAdmin, id)
var LoginInfo utils.LoginRedis
oldAuth, oldErr := redis.Client.Get(ctx, redisKeysKey).Result()
if oldErr != nil {
return l.fail(utils.ErrorNoLoginInfo), nil
}
_ = jsoniter.Unmarshal([]byte(oldAuth), &LoginInfo)
if len(LoginInfo.Token) > utils.NumberOne {
redis.Client.Del(ctx, utils.GetLoginKey(utils.LoginTypeAdmin, LoginInfo.Token)).Result()
}
if len(LoginInfo.Refresh) > utils.NumberOne {
redis.Client.Del(ctx, utils.GetLoginRefreshKey(utils.LoginTypeAdmin, LoginInfo.Refresh)).Result()
}
retData := dao.Token{
Token: utils.MD5Encrypt(id + utils.Now().String()),
}
retData.Refresh = utils.MD5Encrypt(id + retData.Token)
redisKey := utils.GetLoginKey(utils.LoginTypeAdmin, retData.Token)
redis.Client.Set(ctx, redisKey, LoginInfo.Info, expire).Result()
//更新新的数据
LoginInfo.Token = retData.Token
LoginInfo.Refresh = retData.Refresh
newStr, _ := jsoniter.Marshal(LoginInfo)
redis.Client.Set(ctx, redisKeysKey, newStr, refreshExpire).Result()
//登录刷新信息写入redis
newRefreshKey := utils.GetLoginRefreshKey(utils.LoginTypeAdmin, retData.Refresh)
redis.Client.Set(ctx, newRefreshKey, id, refreshExpire).Result()
return l.ok(retData), nil
}
+5
View File
@@ -57,3 +57,8 @@ func (s *AdminServer) AdminLogin(ctx context.Context, in *admin.AdminLoginReques
l := logic.NewAdminLoginLogic(ctx, s.svcCtx)
return l.AdminLogin(in)
}
func (s *AdminServer) AdminRefresh(ctx context.Context, in *admin.AdminEmptyRequest) (*admin.Response, error) {
l := logic.NewAdminRefreshLogic(ctx, s.svcCtx)
return l.AdminRefresh(in)
}
+9
View File
@@ -55,6 +55,9 @@ message AdminLoginRequest {
string password = 2;
}
message AdminEmptyRequest {
}
service Admin {
rpc AdminEdit(AdminEditRequest) returns(Response){
option (google.api.http) = {
@@ -98,4 +101,10 @@ service Admin {
body: "*"
};
};
rpc AdminRefresh(AdminEmptyRequest) returns(Response){
option (google.api.http) = {
post: "/admin/v3/refresh"
body: "*"
};
};
}