wip: user stuff
This commit is contained in:
2
go.mod
2
go.mod
@ -62,6 +62,8 @@ require (
|
||||
github.com/valyala/fasthttp v1.58.0 // indirect
|
||||
github.com/valyala/tcplisten v1.0.0 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.27.0 // indirect
|
||||
golang.org/x/arch v0.8.0 // indirect
|
||||
golang.org/x/crypto v0.31.0 // indirect
|
||||
golang.org/x/net v0.31.0 // indirect
|
||||
|
4
go.sum
4
go.sum
@ -148,6 +148,10 @@ github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
||||
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
|
||||
github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU=
|
||||
github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
|
||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
||||
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||
golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc=
|
||||
golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
|
||||
|
29
internal/api/api.go
Normal file
29
internal/api/api.go
Normal file
@ -0,0 +1,29 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"loveuer/utodo/internal/handler"
|
||||
"loveuer/utodo/internal/opt"
|
||||
g_handler "loveuer/utodo/pkg/handler"
|
||||
"loveuer/utodo/pkg/middleware/trace"
|
||||
|
||||
"github.com/gofiber/fiber/v3"
|
||||
l3 "github.com/gofiber/fiber/v3/middleware/logger"
|
||||
r3 "github.com/gofiber/fiber/v3/middleware/recover"
|
||||
)
|
||||
|
||||
func New(ctx context.Context) *fiber.App {
|
||||
app := fiber.New()
|
||||
app.Use(trace.New())
|
||||
app.Use(l3.New())
|
||||
app.Use(r3.New())
|
||||
|
||||
app.Get("/healthz", g_handler.Healthz(opt.Cfg.Name, opt.Cfg.Version))
|
||||
|
||||
{
|
||||
api := app.Group("/api/v1/auth")
|
||||
api.Post("/login", handler.Login())
|
||||
}
|
||||
|
||||
return app
|
||||
}
|
@ -2,6 +2,7 @@ package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"loveuer/utodo/internal/api"
|
||||
"loveuer/utodo/internal/model"
|
||||
"loveuer/utodo/internal/opt"
|
||||
g_api "loveuer/utodo/pkg/api"
|
||||
@ -34,7 +35,7 @@ func svcRun(cmd *cobra.Command, args []string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = model.Init(cmd.Context(), db.Default.Session(tool.Timeout(60))); err != nil {
|
||||
if err = model.Init(cmd.Context(), db.Default.Session(tool.Timeout(60), db.Config{Debug: opt.Cfg.Debug})); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -43,6 +44,7 @@ func svcRun(cmd *cobra.Command, args []string) error {
|
||||
g_api.WithAddress(opt.Cfg.Svc.Address),
|
||||
g_api.WithVersion(opt.Cfg.Version),
|
||||
g_api.WithName(opt.Cfg.Name),
|
||||
g_api.WithApp(api.New(cmd.Context())),
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
|
14
internal/handler/login.go
Normal file
14
internal/handler/login.go
Normal file
@ -0,0 +1,14 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"loveuer/utodo/pkg/logger"
|
||||
|
||||
"github.com/gofiber/fiber/v3"
|
||||
)
|
||||
|
||||
func Login() fiber.Handler {
|
||||
return func(c fiber.Ctx) error {
|
||||
logger.InfoCtx(c.Context(), "login")
|
||||
return c.SendString("Hello, World!")
|
||||
}
|
||||
}
|
@ -9,5 +9,7 @@ import (
|
||||
func Init(ctx context.Context, tx *gorm.DB) error {
|
||||
return tx.AutoMigrate(
|
||||
&Todo{},
|
||||
&User{},
|
||||
&Object{},
|
||||
)
|
||||
}
|
10
internal/model/object.go
Normal file
10
internal/model/object.go
Normal file
@ -0,0 +1,10 @@
|
||||
package model
|
||||
|
||||
type Object struct {
|
||||
Id int64 `json:"id" gorm:"column:id,primaryKey"`
|
||||
CreatedAt int64 `json:"created_at" gorm:"column:created_at,autoCreateTime:milli"`
|
||||
Key string `json:"key" gorm:"column:key;type:varchar(32);not null;unique"`
|
||||
ContentType string `json:"content_type" gorm:"column:content_type;type:varchar(255);not null"`
|
||||
Size int64 `json:"size" gorm:"column:size"`
|
||||
Blob []byte `json:"-" gorm:"column:blob;type:blob"`
|
||||
}
|
@ -27,7 +27,7 @@ func (t TodoStatus) MarshalJSON() ([]byte, error) {
|
||||
}
|
||||
|
||||
type Todo struct {
|
||||
Id int64 `json:"id" gorm:"column:id,primaryKey;autoIncrement"`
|
||||
Id int64 `json:"id" gorm:"column:id,primaryKey"`
|
||||
CreatedAt int64 `json:"created_at" gorm:"column:created_at,autoCreateTime:milli"`
|
||||
UpdatedAt int64 `json:"updated_at" gorm:"column:updated_at,autoUpdateTime:milli"`
|
||||
DeletedAt int64 `json:"deleted_at" gorm:"column:deleted_at"`
|
||||
|
14
internal/model/user.go
Normal file
14
internal/model/user.go
Normal file
@ -0,0 +1,14 @@
|
||||
package model
|
||||
|
||||
type User struct {
|
||||
Id int64 `json:"id" gorm:"column:id,primaryKey"`
|
||||
CreatedAt int64 `json:"created_at" gorm:"column:created_at,autoCreateTime:milli"`
|
||||
UpdatedAt int64 `json:"updated_at" gorm:"column:updated_at,autoUpdateTime:milli"`
|
||||
DeletedAt int64 `json:"deleted_at" gorm:"column:deleted_at"`
|
||||
Username string `json:"username" gorm:"column:username;type:varchar(255);not null"`
|
||||
Nickname string `json:"nickname" gorm:"column:nickname;type:varchar(255);not null"`
|
||||
Password string `json:"-" gorm:"column:password;type:varchar(255);not null"`
|
||||
Avatar string `json:"avatar" gorm:"column:avatar;type:varchar(32);not null"`
|
||||
Phone string `json:"phone" gorm:"column:phone;type:varchar(16);not null"`
|
||||
Email string `json:"email" gorm:"column:email;type:varchar(255);not null"`
|
||||
}
|
@ -5,9 +5,9 @@ import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"loveuer/utodo/pkg/handler"
|
||||
"loveuer/utodo/pkg/logger"
|
||||
"net"
|
||||
|
||||
"gitea.loveuer.com/yizhisec/packages/logger"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
l3 "github.com/gofiber/fiber/v3/middleware/logger"
|
||||
r3 "github.com/gofiber/fiber/v3/middleware/recover"
|
||||
@ -80,6 +80,9 @@ func Start(ctx context.Context, opts ...Option) (func(context.Context) error, er
|
||||
}
|
||||
|
||||
if opt.app == nil {
|
||||
logger.WarnCtx(ctx, "app is nil, use default app!!!")
|
||||
logger.WarnCtx(ctx, "app is nil, use default app!!!")
|
||||
logger.WarnCtx(ctx, "app is nil, use default app!!!")
|
||||
opt.app = fiber.New(fiber.Config{BodyLimit: 1024 * 1024 * 5})
|
||||
opt.app.Use(l3.New())
|
||||
opt.app.Use(r3.New())
|
||||
|
56
pkg/logger/ctx.go
Normal file
56
pkg/logger/ctx.go
Normal file
@ -0,0 +1,56 @@
|
||||
package logger
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
uuid2 "github.com/google/uuid"
|
||||
)
|
||||
|
||||
type ctxKey struct{}
|
||||
|
||||
var (
|
||||
CtxKey = ctxKey{}
|
||||
)
|
||||
|
||||
func traceId(ctx context.Context) string {
|
||||
if ctx == nil {
|
||||
uuid, _ := uuid2.NewV7()
|
||||
return uuid.String()
|
||||
}
|
||||
|
||||
if id, _ := ctx.Value(CtxKey).(string); id != "" {
|
||||
return id
|
||||
}
|
||||
|
||||
uuid, _ := uuid2.NewV7()
|
||||
return uuid.String()
|
||||
}
|
||||
|
||||
func DebugCtx(ctx context.Context, msg string, data ...any) {
|
||||
msg = traceId(ctx) + " | " + msg
|
||||
DefaultLogger.Debug(msg, data...)
|
||||
}
|
||||
func InfoCtx(ctx context.Context, msg string, data ...any) {
|
||||
msg = traceId(ctx) + " | " + msg
|
||||
DefaultLogger.Info(msg, data...)
|
||||
}
|
||||
|
||||
func WarnCtx(ctx context.Context, msg string, data ...any) {
|
||||
msg = traceId(ctx) + " | " + msg
|
||||
DefaultLogger.Warn(msg, data...)
|
||||
}
|
||||
|
||||
func ErrorCtx(ctx context.Context, msg string, data ...any) {
|
||||
msg = traceId(ctx) + " | " + msg
|
||||
DefaultLogger.Error(msg, data...)
|
||||
}
|
||||
|
||||
func PanicCtx(ctx context.Context, msg string, data ...any) {
|
||||
msg = traceId(ctx) + " | " + msg
|
||||
DefaultLogger.Panic(msg, data...)
|
||||
}
|
||||
|
||||
func FatalCtx(ctx context.Context, msg string, data ...any) {
|
||||
msg = traceId(ctx) + " | " + msg
|
||||
DefaultLogger.Fatal(msg, data...)
|
||||
}
|
97
pkg/logger/default.go
Normal file
97
pkg/logger/default.go
Normal file
@ -0,0 +1,97 @@
|
||||
package logger
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
pool = &sync.Pool{
|
||||
New: func() any {
|
||||
return &strings.Builder{}
|
||||
},
|
||||
}
|
||||
nilLogger = func(prefix, timestamp, msg string, data ...any) {}
|
||||
normalLogger = func(prefix, timestamp, msg string, data ...any) {
|
||||
buf := pool.Get().(*strings.Builder)
|
||||
buf.Reset()
|
||||
buf.WriteString(prefix)
|
||||
buf.WriteString(" | ")
|
||||
buf.WriteString(timestamp)
|
||||
buf.WriteString(" | ")
|
||||
buf.WriteString(msg)
|
||||
buf.WriteString("\n")
|
||||
fmt.Printf(buf.String(), data...)
|
||||
}
|
||||
|
||||
panicLogger = func(prefix, timestamp, msg string, data ...any) {
|
||||
buf := pool.Get().(*strings.Builder)
|
||||
buf.Reset()
|
||||
buf.WriteString(prefix)
|
||||
buf.WriteString(" | ")
|
||||
buf.WriteString(timestamp)
|
||||
buf.WriteString(" | ")
|
||||
buf.WriteString(msg)
|
||||
buf.WriteString("\n")
|
||||
panic(buf.String())
|
||||
}
|
||||
|
||||
fatalLogger = func(prefix, timestamp, msg string, data ...any) {
|
||||
buf := pool.Get().(*strings.Builder)
|
||||
buf.Reset()
|
||||
buf.WriteString(prefix)
|
||||
buf.WriteString(" | ")
|
||||
buf.WriteString(timestamp)
|
||||
buf.WriteString(" | ")
|
||||
buf.WriteString(msg)
|
||||
buf.WriteString("\n")
|
||||
fmt.Printf(buf.String(), data...)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
DefaultLogger = &logger{
|
||||
Mutex: sync.Mutex{},
|
||||
timeFormat: "2006-01-02T15:04:05",
|
||||
writer: os.Stdout,
|
||||
level: LogLevelInfo,
|
||||
debug: nilLogger,
|
||||
info: normalLogger,
|
||||
warn: normalLogger,
|
||||
error: normalLogger,
|
||||
panic: panicLogger,
|
||||
fatal: fatalLogger,
|
||||
}
|
||||
)
|
||||
|
||||
func SetTimeFormat(format string) {
|
||||
DefaultLogger.SetTimeFormat(format)
|
||||
}
|
||||
|
||||
func SetLogLevel(level LogLevel) {
|
||||
DefaultLogger.SetLogLevel(level)
|
||||
}
|
||||
|
||||
func Debug(msg string, data ...any) {
|
||||
DefaultLogger.Debug(msg, data...)
|
||||
}
|
||||
func Info(msg string, data ...any) {
|
||||
DefaultLogger.Info(msg, data...)
|
||||
}
|
||||
|
||||
func Warn(msg string, data ...any) {
|
||||
DefaultLogger.Warn(msg, data...)
|
||||
}
|
||||
|
||||
func Error(msg string, data ...any) {
|
||||
DefaultLogger.Error(msg, data...)
|
||||
}
|
||||
|
||||
func Panic(msg string, data ...any) {
|
||||
DefaultLogger.Panic(msg, data...)
|
||||
}
|
||||
|
||||
func Fatal(msg string, data ...any) {
|
||||
DefaultLogger.Fatal(msg, data...)
|
||||
}
|
116
pkg/logger/logger.go
Normal file
116
pkg/logger/logger.go
Normal file
@ -0,0 +1,116 @@
|
||||
package logger
|
||||
|
||||
import (
|
||||
"io"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/fatih/color"
|
||||
)
|
||||
|
||||
type LogLevel uint32
|
||||
|
||||
const (
|
||||
LogLevelDebug = iota
|
||||
LogLevelInfo
|
||||
LogLevelWarn
|
||||
LogLevelError
|
||||
LogLevelPanic
|
||||
LogLevelFatal
|
||||
)
|
||||
|
||||
type logger struct {
|
||||
sync.Mutex
|
||||
timeFormat string
|
||||
writer io.Writer
|
||||
level LogLevel
|
||||
debug func(prefix, timestamp, msg string, data ...any)
|
||||
info func(prefix, timestamp, msg string, data ...any)
|
||||
warn func(prefix, timestamp, msg string, data ...any)
|
||||
error func(prefix, timestamp, msg string, data ...any)
|
||||
panic func(prefix, timestamp, msg string, data ...any)
|
||||
fatal func(prefix, timestamp, msg string, data ...any)
|
||||
}
|
||||
|
||||
var (
|
||||
red = color.New(color.FgRed)
|
||||
hired = color.New(color.FgHiRed)
|
||||
green = color.New(color.FgGreen)
|
||||
yellow = color.New(color.FgYellow)
|
||||
white = color.New(color.FgWhite)
|
||||
)
|
||||
|
||||
func (l *logger) SetTimeFormat(format string) {
|
||||
l.Lock()
|
||||
defer l.Unlock()
|
||||
l.timeFormat = format
|
||||
}
|
||||
|
||||
func (l *logger) SetLogLevel(level LogLevel) {
|
||||
l.Lock()
|
||||
defer l.Unlock()
|
||||
|
||||
if level > LogLevelDebug {
|
||||
l.debug = nilLogger
|
||||
} else {
|
||||
l.debug = normalLogger
|
||||
}
|
||||
|
||||
if level > LogLevelInfo {
|
||||
l.info = nilLogger
|
||||
} else {
|
||||
l.info = normalLogger
|
||||
}
|
||||
|
||||
if level > LogLevelWarn {
|
||||
l.warn = nilLogger
|
||||
} else {
|
||||
l.warn = normalLogger
|
||||
}
|
||||
|
||||
if level > LogLevelError {
|
||||
l.error = nilLogger
|
||||
} else {
|
||||
l.error = normalLogger
|
||||
}
|
||||
|
||||
if level > LogLevelPanic {
|
||||
l.panic = nilLogger
|
||||
} else {
|
||||
l.panic = panicLogger
|
||||
}
|
||||
|
||||
if level > LogLevelFatal {
|
||||
l.fatal = nilLogger
|
||||
} else {
|
||||
l.fatal = fatalLogger
|
||||
}
|
||||
}
|
||||
|
||||
func (l *logger) Debug(msg string, data ...any) {
|
||||
l.debug(white.Sprint("Debug "), time.Now().Format(l.timeFormat), msg, data...)
|
||||
}
|
||||
|
||||
func (l *logger) Info(msg string, data ...any) {
|
||||
l.info(green.Sprint("Info "), time.Now().Format(l.timeFormat), msg, data...)
|
||||
}
|
||||
|
||||
func (l *logger) Warn(msg string, data ...any) {
|
||||
l.warn(yellow.Sprint("Warn "), time.Now().Format(l.timeFormat), msg, data...)
|
||||
}
|
||||
|
||||
func (l *logger) Error(msg string, data ...any) {
|
||||
l.error(red.Sprint("Error "), time.Now().Format(l.timeFormat), msg, data...)
|
||||
}
|
||||
|
||||
func (l *logger) Panic(msg string, data ...any) {
|
||||
l.panic(hired.Sprint("Panic "), time.Now().Format(l.timeFormat), msg, data...)
|
||||
}
|
||||
|
||||
func (l *logger) Fatal(msg string, data ...any) {
|
||||
l.fatal(hired.Sprint("Fatal "), time.Now().Format(l.timeFormat), msg, data...)
|
||||
}
|
||||
|
||||
type WroteLogger interface {
|
||||
Info(msg string, data ...any)
|
||||
}
|
21
pkg/logger/new.go
Normal file
21
pkg/logger/new.go
Normal file
@ -0,0 +1,21 @@
|
||||
package logger
|
||||
|
||||
import (
|
||||
"os"
|
||||
"sync"
|
||||
)
|
||||
|
||||
func New() *logger {
|
||||
return &logger{
|
||||
Mutex: sync.Mutex{},
|
||||
timeFormat: "2006-01-02T15:04:05",
|
||||
writer: os.Stdout,
|
||||
level: LogLevelInfo,
|
||||
debug: nilLogger,
|
||||
info: normalLogger,
|
||||
warn: normalLogger,
|
||||
error: normalLogger,
|
||||
panic: panicLogger,
|
||||
fatal: fatalLogger,
|
||||
}
|
||||
}
|
9
pkg/middleware/logger/logger.go
Normal file
9
pkg/middleware/logger/logger.go
Normal file
@ -0,0 +1,9 @@
|
||||
package logger
|
||||
|
||||
import "github.com/gofiber/fiber/v3"
|
||||
|
||||
func New() fiber.Handler {
|
||||
return func(c fiber.Ctx) error {
|
||||
return c.Next()
|
||||
}
|
||||
}
|
65
pkg/middleware/trace/trace.go
Normal file
65
pkg/middleware/trace/trace.go
Normal file
@ -0,0 +1,65 @@
|
||||
package trace
|
||||
|
||||
import (
|
||||
"context"
|
||||
"loveuer/utodo/pkg/logger"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type Option func(*option)
|
||||
|
||||
type option struct {
|
||||
traceKey string
|
||||
traceFn func(c fiber.Ctx) string
|
||||
}
|
||||
|
||||
func WithTraceKey(key string) Option {
|
||||
return func(o *option) {
|
||||
if key != "" {
|
||||
o.traceKey = key
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func WithTraceFn(fn func(c fiber.Ctx) string) Option {
|
||||
return func(o *option) {
|
||||
if fn != nil {
|
||||
o.traceFn = fn
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func New(opts ...Option) fiber.Handler {
|
||||
opt := &option{
|
||||
traceKey: "X-Trace-Id",
|
||||
traceFn: func(c fiber.Ctx) string {
|
||||
uid, err := uuid.NewV7()
|
||||
if err != nil {
|
||||
return strconv.FormatInt(time.Now().UnixNano(), 10)
|
||||
}
|
||||
|
||||
return uid.String()
|
||||
},
|
||||
}
|
||||
|
||||
for _, o := range opts {
|
||||
o(opt)
|
||||
}
|
||||
|
||||
return func(c fiber.Ctx) error {
|
||||
traceId := c.Get(opt.traceKey)
|
||||
if traceId == "" {
|
||||
traceId = opt.traceFn(c)
|
||||
c.Request().Header.Set(opt.traceKey, traceId)
|
||||
}
|
||||
|
||||
c.SetContext(context.WithValue(c.Context(), logger.CtxKey, traceId))
|
||||
c.Set(opt.traceKey, traceId)
|
||||
|
||||
return c.Next()
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user