mirror of
https://github.com/go-nunu/nunu-layout-advanced.git
synced 2025-09-27 04:45:52 +08:00
feat: Add English comments
This commit is contained in:
@@ -21,7 +21,7 @@ log:
|
|||||||
log_level: debug
|
log_level: debug
|
||||||
encoding: console # json or console
|
encoding: console # json or console
|
||||||
log_file_name: "./storage/logs/server.log"
|
log_file_name: "./storage/logs/server.log"
|
||||||
max_backups: 30 # 日志文件最多保存多少个备份
|
max_backups: 30
|
||||||
max_age: 7 # 文件最多保存多少天
|
max_age: 7
|
||||||
max_size: 1024 # 每个日志文件保存的最大尺寸 单位:M
|
max_size: 1024
|
||||||
compress: true # 是否压缩
|
compress: true
|
@@ -21,7 +21,7 @@ log:
|
|||||||
log_level: info
|
log_level: info
|
||||||
encoding: json # json or console
|
encoding: json # json or console
|
||||||
log_file_name: "./storage/logs/server.log"
|
log_file_name: "./storage/logs/server.log"
|
||||||
max_backups: 30 # 日志文件最多保存多少个备份
|
max_backups: 30
|
||||||
max_age: 7 # 文件最多保存多少天
|
max_age: 7
|
||||||
max_size: 1024 # 每个日志文件保存的最大尺寸 单位:M
|
max_size: 1024
|
||||||
compress: true # 是否压缩
|
compress: true
|
@@ -17,7 +17,7 @@ import (
|
|||||||
func RequestLogMiddleware(logger *log.Logger) gin.HandlerFunc {
|
func RequestLogMiddleware(logger *log.Logger) gin.HandlerFunc {
|
||||||
return func(ctx *gin.Context) {
|
return func(ctx *gin.Context) {
|
||||||
|
|
||||||
// 每次请求都初始化一次配置
|
// The configuration is initialized once per request
|
||||||
trace := md5.Md5(uuid.GenUUID())
|
trace := md5.Md5(uuid.GenUUID())
|
||||||
logger.NewContext(ctx, zap.String("trace", trace))
|
logger.NewContext(ctx, zap.String("trace", trace))
|
||||||
logger.NewContext(ctx, zap.String("request_method", ctx.Request.Method))
|
logger.NewContext(ctx, zap.String("request_method", ctx.Request.Method))
|
||||||
|
@@ -3,6 +3,7 @@ package migration
|
|||||||
import (
|
import (
|
||||||
"github.com/go-nunu/nunu-layout-advanced/internal/model"
|
"github.com/go-nunu/nunu-layout-advanced/internal/model"
|
||||||
"github.com/go-nunu/nunu-layout-advanced/pkg/log"
|
"github.com/go-nunu/nunu-layout-advanced/pkg/log"
|
||||||
|
"go.uber.org/zap"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -18,6 +19,9 @@ func NewMigrate(db *gorm.DB, log *log.Logger) *Migrate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
func (m *Migrate) Run() {
|
func (m *Migrate) Run() {
|
||||||
m.db.AutoMigrate(&model.User{})
|
if err := m.db.AutoMigrate(&model.User{}); err != nil {
|
||||||
|
m.log.Error("user migrate error", zap.Error(err))
|
||||||
|
return
|
||||||
|
}
|
||||||
m.log.Info("AutoMigrate end")
|
m.log.Info("AutoMigrate end")
|
||||||
}
|
}
|
||||||
|
@@ -19,11 +19,12 @@ func NewServerHTTP(
|
|||||||
r.Use(
|
r.Use(
|
||||||
middleware.CORSMiddleware(),
|
middleware.CORSMiddleware(),
|
||||||
middleware.ResponseLogMiddleware(logger),
|
middleware.ResponseLogMiddleware(logger),
|
||||||
|
middleware.RequestLogMiddleware(logger),
|
||||||
//middleware.SignMiddleware(log),
|
//middleware.SignMiddleware(log),
|
||||||
)
|
)
|
||||||
|
|
||||||
// 无权限路由
|
// No route group has permission
|
||||||
noAuthRouter := r.Group("/").Use(middleware.RequestLogMiddleware(logger))
|
noAuthRouter := r.Group("/")
|
||||||
{
|
{
|
||||||
|
|
||||||
noAuthRouter.GET("/", func(ctx *gin.Context) {
|
noAuthRouter.GET("/", func(ctx *gin.Context) {
|
||||||
@@ -36,14 +37,14 @@ func NewServerHTTP(
|
|||||||
noAuthRouter.POST("/register", userHandler.Register)
|
noAuthRouter.POST("/register", userHandler.Register)
|
||||||
noAuthRouter.POST("/login", userHandler.Login)
|
noAuthRouter.POST("/login", userHandler.Login)
|
||||||
}
|
}
|
||||||
// 非严格权限路由
|
// Non-strict permission routing group
|
||||||
noStrictAuthRouter := r.Group("/").Use(middleware.NoStrictAuth(jwt, logger), middleware.RequestLogMiddleware(logger))
|
noStrictAuthRouter := r.Group("/").Use(middleware.NoStrictAuth(jwt, logger))
|
||||||
{
|
{
|
||||||
noStrictAuthRouter.GET("/user", userHandler.GetProfile)
|
noStrictAuthRouter.GET("/user", userHandler.GetProfile)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 严格权限路由
|
// Strict permission routing group
|
||||||
strictAuthRouter := r.Group("/").Use(middleware.StrictAuth(jwt, logger), middleware.RequestLogMiddleware(logger))
|
strictAuthRouter := r.Group("/").Use(middleware.StrictAuth(jwt, logger))
|
||||||
{
|
{
|
||||||
strictAuthRouter.PUT("/user", userHandler.UpdateProfile)
|
strictAuthRouter.PUT("/user", userHandler.UpdateProfile)
|
||||||
}
|
}
|
||||||
|
@@ -36,7 +36,6 @@ type UserService interface {
|
|||||||
Login(ctx context.Context, req *LoginRequest) (string, error)
|
Login(ctx context.Context, req *LoginRequest) (string, error)
|
||||||
GetProfile(ctx context.Context, userId string) (*model.User, error)
|
GetProfile(ctx context.Context, userId string) (*model.User, error)
|
||||||
UpdateProfile(ctx context.Context, userId string, req *UpdateProfileRequest) error
|
UpdateProfile(ctx context.Context, userId string, req *UpdateProfileRequest) error
|
||||||
GenerateToken(ctx context.Context, userId string) (string, error)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type userService struct {
|
type userService struct {
|
||||||
@@ -61,12 +60,12 @@ func (s *userService) Register(ctx context.Context, req *RegisterRequest) error
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "failed to hash password")
|
return errors.Wrap(err, "failed to hash password")
|
||||||
}
|
}
|
||||||
// 生成用户ID
|
// Generate user ID
|
||||||
userId, err := s.sid.GenString()
|
userId, err := s.sid.GenString()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "failed to generate user ID")
|
return errors.Wrap(err, "failed to generate user ID")
|
||||||
}
|
}
|
||||||
// 创建用户
|
// Create a user
|
||||||
user := &model.User{
|
user := &model.User{
|
||||||
UserId: userId,
|
UserId: userId,
|
||||||
Username: req.Username,
|
Username: req.Username,
|
||||||
@@ -90,8 +89,7 @@ func (s *userService) Login(ctx context.Context, req *LoginRequest) (string, err
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return "", errors.Wrap(err, "failed to hash password")
|
return "", errors.Wrap(err, "failed to hash password")
|
||||||
}
|
}
|
||||||
// 生成JWT token
|
token, err := s.jwt.GenToken(user.UserId, time.Now().Add(time.Hour*24*90))
|
||||||
token, err := s.GenerateToken(ctx, user.UserId)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", errors.Wrap(err, "failed to generate JWT token")
|
return "", errors.Wrap(err, "failed to generate JWT token")
|
||||||
}
|
}
|
||||||
@@ -123,13 +121,3 @@ func (s *userService) UpdateProfile(ctx context.Context, userId string, req *Upd
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *userService) GenerateToken(ctx context.Context, userId string) (string, error) {
|
|
||||||
// 生成JWT token
|
|
||||||
token, err := s.jwt.GenToken(userId, time.Now().Add(time.Hour*24*90))
|
|
||||||
if err != nil {
|
|
||||||
return "", errors.Wrap(err, "failed to generate JWT token")
|
|
||||||
}
|
|
||||||
|
|
||||||
return token, nil
|
|
||||||
}
|
|
||||||
|
@@ -36,21 +36,6 @@ func (m *MockUserService) EXPECT() *MockUserServiceMockRecorder {
|
|||||||
return m.recorder
|
return m.recorder
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenerateToken mocks base method.
|
|
||||||
func (m *MockUserService) GenerateToken(ctx context.Context, userId string) (string, error) {
|
|
||||||
m.ctrl.T.Helper()
|
|
||||||
ret := m.ctrl.Call(m, "GenerateToken", ctx, userId)
|
|
||||||
ret0, _ := ret[0].(string)
|
|
||||||
ret1, _ := ret[1].(error)
|
|
||||||
return ret0, ret1
|
|
||||||
}
|
|
||||||
|
|
||||||
// GenerateToken indicates an expected call of GenerateToken.
|
|
||||||
func (mr *MockUserServiceMockRecorder) GenerateToken(ctx, userId interface{}) *gomock.Call {
|
|
||||||
mr.mock.ctrl.T.Helper()
|
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GenerateToken", reflect.TypeOf((*MockUserService)(nil).GenerateToken), ctx, userId)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetProfile mocks base method.
|
// GetProfile mocks base method.
|
||||||
func (m *MockUserService) GetProfile(ctx context.Context, userId string) (*model.User, error) {
|
func (m *MockUserService) GetProfile(ctx context.Context, userId string) (*model.User, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
|
@@ -18,15 +18,12 @@ func NewSid() *Sid {
|
|||||||
return &Sid{sf}
|
return &Sid{sf}
|
||||||
}
|
}
|
||||||
func (s Sid) GenString() (string, error) {
|
func (s Sid) GenString() (string, error) {
|
||||||
// 生成分布式ID
|
|
||||||
id, err := s.sf.NextID()
|
id, err := s.sf.NextID()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", errors.Wrap(err, "failed to generate sonyflake ID")
|
return "", errors.Wrap(err, "failed to generate sonyflake ID")
|
||||||
}
|
}
|
||||||
// 将ID转换为字符串
|
|
||||||
return convert.IntToBase62(int(id)), nil
|
return convert.IntToBase62(int(id)), nil
|
||||||
}
|
}
|
||||||
func (s Sid) GenUint64() (uint64, error) {
|
func (s Sid) GenUint64() (uint64, error) {
|
||||||
// 生成分布式ID
|
|
||||||
return s.sf.NextID()
|
return s.sf.NextID()
|
||||||
}
|
}
|
||||||
|
@@ -21,9 +21,8 @@ func NewLog(conf *viper.Viper) *Logger {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func initZap(conf *viper.Viper) *Logger {
|
func initZap(conf *viper.Viper) *Logger {
|
||||||
// 日志地址 "out.log" 自定义
|
// log address "out.log" User-defined
|
||||||
lp := conf.GetString("log.log_file_name")
|
lp := conf.GetString("log.log_file_name")
|
||||||
// 日志级别 DEBUG,ERROR, INFO
|
|
||||||
lv := conf.GetString("log.log_level")
|
lv := conf.GetString("log.log_level")
|
||||||
var level zapcore.Level
|
var level zapcore.Level
|
||||||
//debug<info<warn<error<fatal<panic
|
//debug<info<warn<error<fatal<panic
|
||||||
@@ -40,11 +39,11 @@ func initZap(conf *viper.Viper) *Logger {
|
|||||||
level = zap.InfoLevel
|
level = zap.InfoLevel
|
||||||
}
|
}
|
||||||
hook := lumberjack.Logger{
|
hook := lumberjack.Logger{
|
||||||
Filename: lp, // 日志文件路径
|
Filename: lp, // Log file path
|
||||||
MaxSize: conf.GetInt("log.max_size"), // 每个日志文件保存的最大尺寸 单位:M
|
MaxSize: conf.GetInt("log.max_size"), // Maximum size unit for each log file: M
|
||||||
MaxBackups: conf.GetInt("log.max_backups"), // 日志文件最多保存多少个备份
|
MaxBackups: conf.GetInt("log.max_backups"), // The maximum number of backups that can be saved for log files
|
||||||
MaxAge: conf.GetInt("log.max_age"), // 文件最多保存多少天
|
MaxAge: conf.GetInt("log.max_age"), // Maximum number of days the file can be saved
|
||||||
Compress: conf.GetBool("log.compress"), // 是否压缩
|
Compress: conf.GetBool("log.compress"), // Compression or not
|
||||||
}
|
}
|
||||||
|
|
||||||
var encoder zapcore.Encoder
|
var encoder zapcore.Encoder
|
||||||
@@ -79,9 +78,9 @@ func initZap(conf *viper.Viper) *Logger {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
core := zapcore.NewCore(
|
core := zapcore.NewCore(
|
||||||
encoder, // 编码器配置
|
encoder,
|
||||||
zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stdout), zapcore.AddSync(&hook)), // 打印到控制台和文件
|
zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stdout), zapcore.AddSync(&hook)), // Print to console and file
|
||||||
level, // 日志级别
|
level,
|
||||||
)
|
)
|
||||||
if conf.GetString("env") != "prod" {
|
if conf.GetString("env") != "prod" {
|
||||||
return &Logger{zap.New(core, zap.Development(), zap.AddCaller(), zap.AddStacktrace(zap.ErrorLevel))}
|
return &Logger{zap.New(core, zap.Development(), zap.AddCaller(), zap.AddStacktrace(zap.ErrorLevel))}
|
||||||
@@ -90,18 +89,17 @@ func initZap(conf *viper.Viper) *Logger {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 自定义时间编码器
|
|
||||||
func timeEncoder(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
|
func timeEncoder(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
|
||||||
//enc.AppendString(t.Format("2006-01-02 15:04:05"))
|
//enc.AppendString(t.Format("2006-01-02 15:04:05"))
|
||||||
enc.AppendString(t.Format("2006-01-02 15:04:05.000000000"))
|
enc.AppendString(t.Format("2006-01-02 15:04:05.000000000"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewContext 给指定的context添加字段
|
// NewContext Adds a field to the specified context
|
||||||
func (l *Logger) NewContext(ctx *gin.Context, fields ...zapcore.Field) {
|
func (l *Logger) NewContext(ctx *gin.Context, fields ...zapcore.Field) {
|
||||||
ctx.Set(LOGGER_KEY, l.WithContext(ctx).With(fields...))
|
ctx.Set(LOGGER_KEY, l.WithContext(ctx).With(fields...))
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithContext 从指定的context返回一个zap实例
|
// WithContext Returns a zap instance from the specified context
|
||||||
func (l *Logger) WithContext(ctx *gin.Context) *Logger {
|
func (l *Logger) WithContext(ctx *gin.Context) *Logger {
|
||||||
if ctx == nil {
|
if ctx == nil {
|
||||||
return l
|
return l
|
||||||
|
@@ -26,7 +26,10 @@ var (
|
|||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
fmt.Println("begin")
|
fmt.Println("begin")
|
||||||
|
|
||||||
os.Setenv("APP_CONF", "../../../config/local.yml")
|
err := os.Setenv("APP_CONF", "../../../config/local.yml")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
conf := config.NewConfig()
|
conf := config.NewConfig()
|
||||||
|
|
||||||
@@ -208,20 +211,3 @@ func TestUserService_UpdateProfile_UserNotFound(t *testing.T) {
|
|||||||
|
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUserService_GenerateToken(t *testing.T) {
|
|
||||||
ctrl := gomock.NewController(t)
|
|
||||||
defer ctrl.Finish()
|
|
||||||
|
|
||||||
mockUserRepo := mock_repository.NewMockUserRepository(ctrl)
|
|
||||||
|
|
||||||
userService := service.NewUserService(srv, mockUserRepo)
|
|
||||||
|
|
||||||
ctx := context.Background()
|
|
||||||
userId := "123"
|
|
||||||
|
|
||||||
result, err := userService.GenerateToken(ctx, userId)
|
|
||||||
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.NotEmpty(t, result)
|
|
||||||
}
|
|
||||||
|
Reference in New Issue
Block a user