gorm update
This commit is contained in:
parent
68606c76f9
commit
38ee553cf3
@ -40,7 +40,7 @@ var erpCmd = &cobra.Command{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func runErp() error {
|
func runErp() error {
|
||||||
config, err := config.New(configPath)
|
conf, err := config.New(configPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -50,14 +50,14 @@ func runErp() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
mux, fn, err := erpserver.NewWire(config, l)
|
mux, fn, err := erpserver.NewWire(conf, l)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
defer fn()
|
defer fn()
|
||||||
|
|
||||||
address := fmt.Sprintf("%s:%d", config.App.Host, config.App.Port)
|
address := fmt.Sprintf("%s:%d", conf.App.Host, conf.App.Port)
|
||||||
log.Printf("Starting manage server on %s", address)
|
log.Printf("Starting manage server on %s", address)
|
||||||
|
|
||||||
if runtime.GOOS == "windows" {
|
if runtime.GOOS == "windows" {
|
||||||
|
|||||||
@ -6,8 +6,9 @@ import (
|
|||||||
|
|
||||||
"management/internal/erpserver/model/dto"
|
"management/internal/erpserver/model/dto"
|
||||||
"management/internal/pkg/config"
|
"management/internal/pkg/config"
|
||||||
"management/internal/pkg/middleware"
|
"management/internal/pkg/know"
|
||||||
"management/internal/pkg/render"
|
"management/internal/pkg/render"
|
||||||
|
"management/internal/pkg/session"
|
||||||
|
|
||||||
"github.com/drhin/logger"
|
"github.com/drhin/logger"
|
||||||
)
|
)
|
||||||
@ -15,21 +16,21 @@ import (
|
|||||||
type Handler struct {
|
type Handler struct {
|
||||||
Config *config.Config
|
Config *config.Config
|
||||||
Log *logger.Logger
|
Log *logger.Logger
|
||||||
Middleware middleware.Middleware
|
|
||||||
|
|
||||||
|
session session.Manager
|
||||||
render render.Render
|
render render.Render
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHandler(
|
func NewHandler(
|
||||||
config *config.Config,
|
config *config.Config,
|
||||||
log *logger.Logger,
|
log *logger.Logger,
|
||||||
middleware middleware.Middleware,
|
session session.Manager,
|
||||||
render render.Render,
|
render render.Render,
|
||||||
) *Handler {
|
) *Handler {
|
||||||
return &Handler{
|
return &Handler{
|
||||||
Config: config,
|
Config: config,
|
||||||
Log: log,
|
Log: log,
|
||||||
Middleware: middleware,
|
session: session,
|
||||||
render: render,
|
render: render,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -38,7 +39,19 @@ func NewHandler(
|
|||||||
// middleware 帮助方法
|
// middleware 帮助方法
|
||||||
|
|
||||||
func (h *Handler) AuthUser(ctx context.Context) dto.AuthorizeUser {
|
func (h *Handler) AuthUser(ctx context.Context) dto.AuthorizeUser {
|
||||||
return h.Middleware.AuthUser(ctx)
|
u, err := h.session.GetUser(ctx, know.StoreName)
|
||||||
|
if err != nil {
|
||||||
|
return dto.AuthorizeUser{}
|
||||||
|
}
|
||||||
|
return *u
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) RenewToken(ctx context.Context) error {
|
||||||
|
return h.session.RenewToken(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) Destroy(ctx context.Context) error {
|
||||||
|
return h.session.Destroy(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// =====================================================================================================================
|
// =====================================================================================================================
|
||||||
|
|||||||
@ -167,11 +167,15 @@ func (h *UserHandler) Login(w http.ResponseWriter, r *http.Request) {
|
|||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
switch r.Method {
|
switch r.Method {
|
||||||
case http.MethodGet:
|
case http.MethodGet:
|
||||||
if h.Middleware.IsAuth(ctx) && h.Middleware.RefreshToken(ctx) {
|
user := h.AuthUser(ctx)
|
||||||
|
if user.ID > 0 {
|
||||||
|
if err := h.RenewToken(ctx); err == nil {
|
||||||
http.Redirect(w, r, "/home.html", http.StatusFound)
|
http.Redirect(w, r, "/home.html", http.StatusFound)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_ = h.Middleware.Destroy(ctx)
|
}
|
||||||
|
|
||||||
|
_ = h.Destroy(ctx)
|
||||||
h.HTML(w, r, "oauth/login.tmpl", nil)
|
h.HTML(w, r, "oauth/login.tmpl", nil)
|
||||||
case http.MethodPost:
|
case http.MethodPost:
|
||||||
defer func(Body io.ReadCloser) {
|
defer func(Body io.ReadCloser) {
|
||||||
@ -207,7 +211,7 @@ func (h *UserHandler) Login(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *UserHandler) Logout(w http.ResponseWriter, r *http.Request) {
|
func (h *UserHandler) Logout(w http.ResponseWriter, r *http.Request) {
|
||||||
err := h.Middleware.Destroy(r.Context())
|
err := h.Destroy(r.Context())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.Log.Error(err.Error(), err)
|
h.Log.Error(err.Error(), err)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,14 +5,20 @@ import (
|
|||||||
|
|
||||||
"management/internal/erpserver/handler/common"
|
"management/internal/erpserver/handler/common"
|
||||||
"management/internal/erpserver/handler/system"
|
"management/internal/erpserver/handler/system"
|
||||||
|
v1 "management/internal/erpserver/service/v1"
|
||||||
mi "management/internal/pkg/middleware"
|
mi "management/internal/pkg/middleware"
|
||||||
|
"management/internal/pkg/session"
|
||||||
|
|
||||||
|
"github.com/drhin/logger"
|
||||||
"github.com/go-chi/chi/v5"
|
"github.com/go-chi/chi/v5"
|
||||||
"github.com/go-chi/chi/v5/middleware"
|
"github.com/go-chi/chi/v5/middleware"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewHTTPServer(
|
func NewHTTPServer(
|
||||||
mi mi.Middleware,
|
sm session.Manager,
|
||||||
|
log *logger.Logger,
|
||||||
|
menuService v1.MenuService,
|
||||||
|
auditLogService v1.AuditLogService,
|
||||||
captchaHandler *common.CaptchaHandler,
|
captchaHandler *common.CaptchaHandler,
|
||||||
uploadHandler *common.UploadHandler,
|
uploadHandler *common.UploadHandler,
|
||||||
configHandler *system.ConfigHandler,
|
configHandler *system.ConfigHandler,
|
||||||
@ -34,33 +40,39 @@ func NewHTTPServer(
|
|||||||
staticServer := http.FileServer(http.Dir("./web/statics/"))
|
staticServer := http.FileServer(http.Dir("./web/statics/"))
|
||||||
r.Handle("/statics/*", http.StripPrefix("/statics", staticServer))
|
r.Handle("/statics/*", http.StripPrefix("/statics", staticServer))
|
||||||
|
|
||||||
uploadServer := http.FileServer(http.Dir("./upload/"))
|
uploadServer := http.FileServer(http.Dir("./public/"))
|
||||||
r.Handle("/upload/*", http.StripPrefix("/upload", uploadServer))
|
r.Handle("/public/*", http.StripPrefix("/public", uploadServer))
|
||||||
|
|
||||||
r.Group(func(r chi.Router) {
|
r.Group(func(r chi.Router) {
|
||||||
r.Use(mi.NoSurf) // CSRF
|
r.Use(mi.NoSurf) // CSRF
|
||||||
r.Use(mi.LoadSession) // Session
|
r.Use(mi.LoadSession(sm)) // Session
|
||||||
|
|
||||||
r.Get("/captcha", captchaHandler.Captcha)
|
|
||||||
|
|
||||||
r.With(mi.Authorize, mi.Audit).Post("/upload/img", uploadHandler.Img)
|
|
||||||
r.With(mi.Authorize, mi.Audit).Post("/upload/file", uploadHandler.File)
|
|
||||||
r.With(mi.Authorize, mi.Audit).Post("/upload/multi_files", uploadHandler.MultiFiles)
|
|
||||||
|
|
||||||
r.Get("/", userHandler.Login)
|
r.Get("/", userHandler.Login)
|
||||||
|
r.Get("/captcha", captchaHandler.Captcha)
|
||||||
r.Post("/login", userHandler.Login)
|
r.Post("/login", userHandler.Login)
|
||||||
|
|
||||||
|
r.Group(func(r chi.Router) {
|
||||||
|
r.Use(mi.Authorize(sm, menuService))
|
||||||
|
|
||||||
r.Get("/logout", userHandler.Logout)
|
r.Get("/logout", userHandler.Logout)
|
||||||
|
|
||||||
r.With(mi.Authorize).Get("/home.html", homeHandler.Home)
|
r.Get("/home.html", homeHandler.Home)
|
||||||
r.With(mi.Authorize).Get("/dashboard", homeHandler.Dashboard)
|
r.Get("/dashboard", homeHandler.Dashboard)
|
||||||
|
r.Get("/pear.json", configHandler.Pear)
|
||||||
|
|
||||||
r.With(mi.Authorize).Get("/pear.json", configHandler.Pear)
|
r.Route("/upload", func(r chi.Router) {
|
||||||
|
r.Use(mi.Audit(sm, auditLogService, log))
|
||||||
|
r.Get("/img", uploadHandler.Img)
|
||||||
|
r.Get("/file", uploadHandler.File)
|
||||||
|
r.Get("/multi_files", uploadHandler.MultiFiles)
|
||||||
|
})
|
||||||
|
|
||||||
r.Route("/system", func(r chi.Router) {
|
r.Route("/system", func(r chi.Router) {
|
||||||
r.Use(mi.Authorize)
|
r.Use(mi.Audit(sm, auditLogService, log))
|
||||||
|
|
||||||
|
r.Get("/menus", menuHandler.Menus)
|
||||||
|
|
||||||
r.Route("/config", func(r chi.Router) {
|
r.Route("/config", func(r chi.Router) {
|
||||||
r.Use(mi.Audit)
|
|
||||||
r.Get("/list", configHandler.List)
|
r.Get("/list", configHandler.List)
|
||||||
r.Post("/list", configHandler.List)
|
r.Post("/list", configHandler.List)
|
||||||
r.Get("/add", configHandler.Add)
|
r.Get("/add", configHandler.Add)
|
||||||
@ -70,9 +82,7 @@ func NewHTTPServer(
|
|||||||
r.Post("/reset_pear", configHandler.ResetPear)
|
r.Post("/reset_pear", configHandler.ResetPear)
|
||||||
})
|
})
|
||||||
|
|
||||||
r.Get("/menus", menuHandler.Menus)
|
|
||||||
r.Route("/menu", func(r chi.Router) {
|
r.Route("/menu", func(r chi.Router) {
|
||||||
r.Use(mi.Audit)
|
|
||||||
r.Get("/list", menuHandler.List)
|
r.Get("/list", menuHandler.List)
|
||||||
r.Post("/list", menuHandler.List)
|
r.Post("/list", menuHandler.List)
|
||||||
r.Get("/add", menuHandler.Add)
|
r.Get("/add", menuHandler.Add)
|
||||||
@ -84,8 +94,6 @@ func NewHTTPServer(
|
|||||||
})
|
})
|
||||||
|
|
||||||
r.Route("/department", func(r chi.Router) {
|
r.Route("/department", func(r chi.Router) {
|
||||||
r.Use(mi.Audit)
|
|
||||||
|
|
||||||
r.Get("/list", departmentHandler.List)
|
r.Get("/list", departmentHandler.List)
|
||||||
r.Post("/list", departmentHandler.List)
|
r.Post("/list", departmentHandler.List)
|
||||||
r.Get("/add", departmentHandler.Add)
|
r.Get("/add", departmentHandler.Add)
|
||||||
@ -98,8 +106,6 @@ func NewHTTPServer(
|
|||||||
})
|
})
|
||||||
|
|
||||||
r.Route("/role", func(r chi.Router) {
|
r.Route("/role", func(r chi.Router) {
|
||||||
r.Use(mi.Audit)
|
|
||||||
|
|
||||||
r.Get("/list", roleHandler.List)
|
r.Get("/list", roleHandler.List)
|
||||||
r.Post("/list", roleHandler.List)
|
r.Post("/list", roleHandler.List)
|
||||||
r.Get("/add", roleHandler.Add)
|
r.Get("/add", roleHandler.Add)
|
||||||
@ -136,5 +142,7 @@ func NewHTTPServer(
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|||||||
@ -45,7 +45,7 @@ func NewAuditLog(r *http.Request, email, os, browser string, start, end time.Tim
|
|||||||
contentType := r.Header.Get("Content-Type")
|
contentType := r.Header.Get("Content-Type")
|
||||||
if strings.Contains(contentType, "application/json") {
|
if strings.Contains(contentType, "application/json") {
|
||||||
body := make([]byte, r.ContentLength)
|
body := make([]byte, r.ContentLength)
|
||||||
r.Body.Read(body)
|
_, _ = r.Body.Read(body)
|
||||||
params = string(body)
|
params = string(body)
|
||||||
} else if strings.Contains(contentType, "application/x-www-form-urlencoded") {
|
} else if strings.Contains(contentType, "application/x-www-form-urlencoded") {
|
||||||
params = r.Form.Encode()
|
params = r.Form.Encode()
|
||||||
|
|||||||
@ -11,14 +11,14 @@ import (
|
|||||||
type Service struct {
|
type Service struct {
|
||||||
Log *logger.Logger
|
Log *logger.Logger
|
||||||
Tx repository.Transaction
|
Tx repository.Transaction
|
||||||
Session session.Session
|
Session session.Manager
|
||||||
Redis redis.Cache
|
Redis redis.Cache
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewService(
|
func NewService(
|
||||||
log *logger.Logger,
|
log *logger.Logger,
|
||||||
tx repository.Transaction,
|
tx repository.Transaction,
|
||||||
session session.Session,
|
session session.Manager,
|
||||||
redis redis.Cache,
|
redis redis.Cache,
|
||||||
) *Service {
|
) *Service {
|
||||||
return &Service{
|
return &Service{
|
||||||
|
|||||||
@ -2,7 +2,6 @@ package system
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
"errors"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
@ -181,7 +180,7 @@ func (s *userService) login(ctx context.Context, req *form.Login) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *userService) loginSuccess(ctx context.Context, user *system.User, req *form.Login) error {
|
func (s *userService) loginSuccess(ctx context.Context, user *system.User, req *form.Login) error {
|
||||||
auth := dto.AuthorizeUser{
|
return s.Session.PutUser(ctx, know.StoreName, &dto.AuthorizeUser{
|
||||||
ID: user.ID,
|
ID: user.ID,
|
||||||
Uuid: user.Uuid,
|
Uuid: user.Uuid,
|
||||||
Email: user.Email,
|
Email: user.Email,
|
||||||
@ -191,13 +190,5 @@ func (s *userService) loginSuccess(ctx context.Context, user *system.User, req *
|
|||||||
OS: req.Os,
|
OS: req.Os,
|
||||||
IP: req.Ip,
|
IP: req.Ip,
|
||||||
Browser: req.Browser,
|
Browser: req.Browser,
|
||||||
}
|
})
|
||||||
|
|
||||||
gob, err := json.Marshal(auth)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
s.Session.Put(ctx, know.StoreName, gob)
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,7 +13,6 @@ import (
|
|||||||
commonService "management/internal/erpserver/service/v1/common"
|
commonService "management/internal/erpserver/service/v1/common"
|
||||||
systemService "management/internal/erpserver/service/v1/system"
|
systemService "management/internal/erpserver/service/v1/system"
|
||||||
"management/internal/pkg/config"
|
"management/internal/pkg/config"
|
||||||
"management/internal/pkg/middleware"
|
|
||||||
"management/internal/pkg/redis"
|
"management/internal/pkg/redis"
|
||||||
"management/internal/pkg/render"
|
"management/internal/pkg/render"
|
||||||
"management/internal/pkg/session"
|
"management/internal/pkg/session"
|
||||||
@ -72,9 +71,8 @@ func NewWire(*config.Config, *logger.Logger) (*chi.Mux, func(), error) {
|
|||||||
panic(wire.Build(
|
panic(wire.Build(
|
||||||
repositorySet,
|
repositorySet,
|
||||||
redis.New,
|
redis.New,
|
||||||
session.New,
|
session.NewSCSManager,
|
||||||
serviceSet,
|
serviceSet,
|
||||||
middleware.New,
|
|
||||||
render.New,
|
render.New,
|
||||||
handlerSet,
|
handlerSet,
|
||||||
serverSet,
|
serverSet,
|
||||||
|
|||||||
@ -19,7 +19,6 @@ import (
|
|||||||
"management/internal/erpserver/service/v1/common"
|
"management/internal/erpserver/service/v1/common"
|
||||||
system2 "management/internal/erpserver/service/v1/system"
|
system2 "management/internal/erpserver/service/v1/system"
|
||||||
"management/internal/pkg/config"
|
"management/internal/pkg/config"
|
||||||
"management/internal/pkg/middleware"
|
|
||||||
"management/internal/pkg/redis"
|
"management/internal/pkg/redis"
|
||||||
"management/internal/pkg/render"
|
"management/internal/pkg/render"
|
||||||
"management/internal/pkg/session"
|
"management/internal/pkg/session"
|
||||||
@ -32,7 +31,11 @@ func NewWire(configConfig *config.Config, loggerLogger *logger.Logger) (*chi.Mux
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
sessionSession := session.New(db, configConfig)
|
manager, err := session.NewSCSManager(db, configConfig)
|
||||||
|
if err != nil {
|
||||||
|
cleanup()
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
repositoryRepository := repository.NewRepository(db, loggerLogger)
|
repositoryRepository := repository.NewRepository(db, loggerLogger)
|
||||||
transaction := repository.NewTransaction(repositoryRepository)
|
transaction := repository.NewTransaction(repositoryRepository)
|
||||||
cache, cleanup2, err := redis.New(configConfig, loggerLogger)
|
cache, cleanup2, err := redis.New(configConfig, loggerLogger)
|
||||||
@ -40,7 +43,7 @@ func NewWire(configConfig *config.Config, loggerLogger *logger.Logger) (*chi.Mux
|
|||||||
cleanup()
|
cleanup()
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
serviceService := service.NewService(loggerLogger, transaction, sessionSession, cache)
|
serviceService := service.NewService(loggerLogger, transaction, manager, cache)
|
||||||
menuRepository := system.NewMenuRepository(repositoryRepository)
|
menuRepository := system.NewMenuRepository(repositoryRepository)
|
||||||
roleRepository := system.NewRoleRepository(repositoryRepository)
|
roleRepository := system.NewRoleRepository(repositoryRepository)
|
||||||
roleService := system2.NewRoleService(serviceService, roleRepository)
|
roleService := system2.NewRoleService(serviceService, roleRepository)
|
||||||
@ -49,14 +52,13 @@ func NewWire(configConfig *config.Config, loggerLogger *logger.Logger) (*chi.Mux
|
|||||||
menuService := system2.NewMenuService(serviceService, menuRepository, roleService, roleMenuService)
|
menuService := system2.NewMenuService(serviceService, menuRepository, roleService, roleMenuService)
|
||||||
auditLogRepository := system.NewAuditLogRepository(repositoryRepository)
|
auditLogRepository := system.NewAuditLogRepository(repositoryRepository)
|
||||||
auditLogService := system2.NewAuditLogService(serviceService, auditLogRepository)
|
auditLogService := system2.NewAuditLogService(serviceService, auditLogRepository)
|
||||||
middlewareMiddleware := middleware.New(sessionSession, menuService, auditLogService)
|
renderRender, err := render.New(manager, menuService)
|
||||||
renderRender, err := render.New(sessionSession, menuService)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cleanup2()
|
cleanup2()
|
||||||
cleanup()
|
cleanup()
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
handlerHandler := handler.NewHandler(configConfig, loggerLogger, middlewareMiddleware, renderRender)
|
handlerHandler := handler.NewHandler(configConfig, loggerLogger, manager, renderRender)
|
||||||
captchaService := common.NewCaptchaService()
|
captchaService := common.NewCaptchaService()
|
||||||
captchaHandler := common2.NewCaptchaHandler(handlerHandler, captchaService)
|
captchaHandler := common2.NewCaptchaHandler(handlerHandler, captchaService)
|
||||||
uploadHandler := common2.NewUploadHandler(handlerHandler)
|
uploadHandler := common2.NewUploadHandler(handlerHandler)
|
||||||
@ -76,7 +78,7 @@ func NewWire(configConfig *config.Config, loggerLogger *logger.Logger) (*chi.Mux
|
|||||||
menuHandler := system3.NewMenuHandler(handlerHandler, menuService)
|
menuHandler := system3.NewMenuHandler(handlerHandler, menuService)
|
||||||
roleHandler := system3.NewRoleHandler(handlerHandler, roleService, menuService)
|
roleHandler := system3.NewRoleHandler(handlerHandler, roleService, menuService)
|
||||||
departmentHandler := system3.NewDepartmentHandler(handlerHandler, departmentService)
|
departmentHandler := system3.NewDepartmentHandler(handlerHandler, departmentService)
|
||||||
mux := NewHTTPServer(middlewareMiddleware, captchaHandler, uploadHandler, configHandler, homeHandler, userHandler, loginLogHandler, auditHandler, menuHandler, roleHandler, departmentHandler)
|
mux := NewHTTPServer(manager, loggerLogger, menuService, auditLogService, captchaHandler, uploadHandler, configHandler, homeHandler, userHandler, loginLogHandler, auditHandler, menuHandler, roleHandler, departmentHandler)
|
||||||
return mux, func() {
|
return mux, func() {
|
||||||
cleanup2()
|
cleanup2()
|
||||||
cleanup()
|
cleanup()
|
||||||
|
|||||||
@ -150,7 +150,7 @@ func UploadFile(file *multipart.FileHeader, t FileType) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func GetPath() string {
|
func GetPath() string {
|
||||||
return fmt.Sprintf("upload/%s/%s/%s/", time.Now().Format("2006"), time.Now().Format("01"), time.Now().Format("02"))
|
return fmt.Sprintf("public/%s/%s/%s/", time.Now().Format("2006"), time.Now().Format("01"), time.Now().Format("02"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func GenFilename(ext string) string {
|
func GenFilename(ext string) string {
|
||||||
|
|||||||
@ -1,33 +1,52 @@
|
|||||||
package middleware
|
package middleware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"errors"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
systemmodel "management/internal/erpserver/model/system"
|
systemmodel "management/internal/erpserver/model/system"
|
||||||
|
v1 "management/internal/erpserver/service/v1"
|
||||||
|
"management/internal/pkg/know"
|
||||||
|
"management/internal/pkg/session"
|
||||||
|
|
||||||
|
"github.com/drhin/logger"
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (m *middleware) Audit(next http.Handler) http.Handler {
|
func Audit(sess session.Manager, auditLogService v1.AuditLogService, log *logger.Logger) func(http.Handler) http.Handler {
|
||||||
fn := func(w http.ResponseWriter, r *http.Request) {
|
return func(next http.Handler) http.Handler {
|
||||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
defer func(res http.ResponseWriter, req *http.Request) {
|
defer func() {
|
||||||
// 记录审计日志
|
go func() {
|
||||||
go m.writeLog(req, start)
|
ctx := r.Context()
|
||||||
}(w, r)
|
user, err := sess.GetUser(ctx, know.StoreName)
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err.Error(), err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if user.ID == 0 {
|
||||||
|
log.Error("scs get user is empty", errors.New("scs get user is empty"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
al := systemmodel.NewAuditLog(r, user.Email, user.OS, user.Browser, start, time.Now())
|
||||||
|
if err := auditLogService.Create(ctx, al); err != nil {
|
||||||
|
log.Error(err.Error(), err,
|
||||||
|
zap.Int32("user_id", user.ID),
|
||||||
|
zap.String("user", user.Email),
|
||||||
|
zap.String("ip", al.Ip),
|
||||||
|
zap.String("os", al.Os),
|
||||||
|
zap.String("method", al.Method),
|
||||||
|
zap.String("path", al.Url),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}()
|
||||||
|
|
||||||
next.ServeHTTP(w, r)
|
next.ServeHTTP(w, r)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return http.HandlerFunc(fn)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *middleware) writeLog(req *http.Request, start time.Time) {
|
|
||||||
end := time.Now()
|
|
||||||
user := m.AuthUser(req.Context())
|
|
||||||
al := systemmodel.NewAuditLog(req, user.Email, user.OS, user.Browser, start, end)
|
|
||||||
|
|
||||||
c, cancel := context.WithTimeout(context.Background(), time.Second*3)
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
_ = m.auditLogService.Create(c, al)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,94 +1,59 @@
|
|||||||
package middleware
|
package middleware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"encoding/json"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"management/internal/erpserver/model/dto"
|
"management/internal/erpserver/model/dto"
|
||||||
|
v1 "management/internal/erpserver/service/v1"
|
||||||
"management/internal/pkg/know"
|
"management/internal/pkg/know"
|
||||||
|
"management/internal/pkg/session"
|
||||||
)
|
)
|
||||||
|
|
||||||
var defaultMenus = map[string]bool{
|
var publicRoutes = map[string]bool{
|
||||||
"/home.html": true,
|
"/home.html": true,
|
||||||
"/dashboard": true,
|
"/dashboard": true,
|
||||||
"/system/menus": true,
|
"/system/menus": true,
|
||||||
"/upload/img": true,
|
"/upload/img": true,
|
||||||
"/upload/file": true,
|
"/upload/file": true,
|
||||||
"/upload/mutilfile": true,
|
"/upload/multi_files": true,
|
||||||
"/pear.json": true,
|
"/pear.json": true,
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *middleware) Authorize(next http.Handler) http.Handler {
|
func Authorize(
|
||||||
fn := func(w http.ResponseWriter, r *http.Request) {
|
sess session.Manager,
|
||||||
|
menuService v1.MenuService,
|
||||||
|
) func(http.Handler) http.Handler {
|
||||||
|
return func(next http.Handler) http.Handler {
|
||||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
user, ok := m.isLogin(ctx)
|
path := r.URL.Path
|
||||||
if !ok {
|
|
||||||
|
// 登陆检查
|
||||||
|
user, err := sess.GetUser(ctx, know.StoreName)
|
||||||
|
if err != nil || user.ID == 0 {
|
||||||
http.Redirect(w, r, "/", http.StatusFound)
|
http.Redirect(w, r, "/", http.StatusFound)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 登陆成功 判断权限
|
// 公共路由放行
|
||||||
path := r.URL.Path
|
if publicRoutes[path] {
|
||||||
if b, ok := defaultMenus[path]; ok && b {
|
|
||||||
next.ServeHTTP(w, r)
|
next.ServeHTTP(w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
menus, err := m.menuService.ListByRoleIDToMap(ctx, user.RoleID)
|
// 权限检查
|
||||||
if err != nil {
|
menus, err := menuService.ListByRoleIDToMap(ctx, user.RoleID)
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
if err != nil || !hasPermission(menus, path) {
|
||||||
|
http.Error(w, "Forbidden", http.StatusForbidden)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := menus[path]; ok {
|
|
||||||
next.ServeHTTP(w, r)
|
next.ServeHTTP(w, r)
|
||||||
return
|
})
|
||||||
}
|
|
||||||
|
|
||||||
http.Error(w, "Unauthorized", http.StatusUnauthorized)
|
|
||||||
}
|
|
||||||
|
|
||||||
return http.HandlerFunc(fn)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *middleware) isLogin(ctx context.Context) (*dto.AuthorizeUser, bool) {
|
|
||||||
if exists := m.session.Exists(ctx, know.StoreName); exists {
|
|
||||||
b := m.session.GetBytes(ctx, know.StoreName)
|
|
||||||
var user dto.AuthorizeUser
|
|
||||||
if err := json.Unmarshal(b, &user); err == nil && user.ID > 0 {
|
|
||||||
return &user, true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, false
|
func hasPermission(menus map[string]*dto.OwnerMenuDto, path string) bool {
|
||||||
}
|
_, ok := menus[path]
|
||||||
|
return ok
|
||||||
func (m *middleware) AuthUser(ctx context.Context) dto.AuthorizeUser {
|
|
||||||
var user dto.AuthorizeUser
|
|
||||||
if exists := m.session.Exists(ctx, know.StoreName); exists {
|
|
||||||
b := m.session.GetBytes(ctx, know.StoreName)
|
|
||||||
_ = json.Unmarshal(b, &user)
|
|
||||||
}
|
|
||||||
return user
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *middleware) IsAuth(ctx context.Context) bool {
|
|
||||||
var user dto.AuthorizeUser
|
|
||||||
b := m.session.GetBytes(ctx, know.StoreName)
|
|
||||||
if err := json.Unmarshal(b, &user); err == nil && user.ID > 0 {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *middleware) RefreshToken(ctx context.Context) bool {
|
|
||||||
if err := m.session.RenewToken(ctx); err == nil {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *middleware) Destroy(ctx context.Context) error {
|
|
||||||
return m.session.Destroy(ctx)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,6 +6,6 @@ import (
|
|||||||
"github.com/justinas/nosurf"
|
"github.com/justinas/nosurf"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (m *middleware) NoSurf(next http.Handler) http.Handler {
|
func NoSurf(next http.Handler) http.Handler {
|
||||||
return nosurf.New(next)
|
return nosurf.New(next)
|
||||||
}
|
}
|
||||||
@ -1,35 +0,0 @@
|
|||||||
package middleware
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"management/internal/erpserver/model/dto"
|
|
||||||
v1 "management/internal/erpserver/service/v1"
|
|
||||||
"management/internal/pkg/session"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Middleware interface {
|
|
||||||
Audit(next http.Handler) http.Handler
|
|
||||||
NoSurf(next http.Handler) http.Handler
|
|
||||||
LoadSession(next http.Handler) http.Handler
|
|
||||||
Authorize(next http.Handler) http.Handler
|
|
||||||
AuthUser(ctx context.Context) dto.AuthorizeUser
|
|
||||||
IsAuth(ctx context.Context) bool
|
|
||||||
RefreshToken(ctx context.Context) bool
|
|
||||||
Destroy(ctx context.Context) error
|
|
||||||
}
|
|
||||||
|
|
||||||
type middleware struct {
|
|
||||||
session session.Session
|
|
||||||
menuService v1.MenuService
|
|
||||||
auditLogService v1.AuditLogService
|
|
||||||
}
|
|
||||||
|
|
||||||
func New(session session.Session, menuService v1.MenuService, auditLogService v1.AuditLogService) Middleware {
|
|
||||||
return &middleware{
|
|
||||||
session: session,
|
|
||||||
menuService: menuService,
|
|
||||||
auditLogService: auditLogService,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -2,8 +2,10 @@ package middleware
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"management/internal/pkg/session"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (m *middleware) LoadSession(next http.Handler) http.Handler {
|
func LoadSession(sm session.Manager) func(http.Handler) http.Handler {
|
||||||
return m.session.LoadAndSave(next)
|
return sm.Load
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,7 +3,6 @@ package render
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"html/template"
|
"html/template"
|
||||||
"net/http"
|
"net/http"
|
||||||
@ -60,15 +59,15 @@ func (r *render) setDefaultData(req *http.Request, data map[string]any) map[stri
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctx := req.Context()
|
ctx := req.Context()
|
||||||
isAuth := r.session.Exists(ctx, know.StoreName)
|
|
||||||
data["IsAuthenticated"] = isAuth
|
|
||||||
if isAuth {
|
|
||||||
var authUser dto.AuthorizeUser
|
|
||||||
u := r.session.GetBytes(ctx, know.StoreName)
|
|
||||||
_ = json.Unmarshal(u, &authUser)
|
|
||||||
|
|
||||||
|
authUser, err := r.session.GetUser(ctx, know.StoreName)
|
||||||
|
if err != nil || authUser == nil {
|
||||||
|
data["IsAuthenticated"] = false
|
||||||
|
} else {
|
||||||
|
data["IsAuthenticated"] = true
|
||||||
data["AuthorizeMenus"] = r.getCurrentPathButtons(ctx, authUser.RoleID, req.URL.Path)
|
data["AuthorizeMenus"] = r.getCurrentPathButtons(ctx, authUser.RoleID, req.URL.Path)
|
||||||
}
|
}
|
||||||
|
|
||||||
token := nosurf.Token(req)
|
token := nosurf.Token(req)
|
||||||
data["CsrfToken"] = token
|
data["CsrfToken"] = token
|
||||||
data["CsrfTokenField"] = template.HTML(fmt.Sprintf(`<input type="hidden" name="csrf_token" value="%s" />`, token))
|
data["CsrfTokenField"] = template.HTML(fmt.Sprintf(`<input type="hidden" name="csrf_token" value="%s" />`, token))
|
||||||
|
|||||||
@ -28,12 +28,12 @@ type jsonRender interface {
|
|||||||
type render struct {
|
type render struct {
|
||||||
templateConfig *TemplateConfig
|
templateConfig *TemplateConfig
|
||||||
templates map[string]*template.Template
|
templates map[string]*template.Template
|
||||||
session session.Session
|
session session.Manager
|
||||||
|
|
||||||
menuService v1.MenuService
|
menuService v1.MenuService
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(session session.Session, menuService v1.MenuService) (Render, error) {
|
func New(session session.Manager, menuService v1.MenuService) (Render, error) {
|
||||||
r := &render{
|
r := &render{
|
||||||
templateConfig: &TemplateConfig{
|
templateConfig: &TemplateConfig{
|
||||||
Root: ".",
|
Root: ".",
|
||||||
|
|||||||
@ -2,9 +2,12 @@ package session
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"management/internal/erpserver/model/dto"
|
||||||
"management/internal/pkg/config"
|
"management/internal/pkg/config"
|
||||||
|
|
||||||
"github.com/alexedwards/scs/postgresstore"
|
"github.com/alexedwards/scs/postgresstore"
|
||||||
@ -12,20 +15,22 @@ import (
|
|||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Session interface {
|
var ErrNoSession = errors.New("session user not found")
|
||||||
Destroy(ctx context.Context) error
|
|
||||||
LoadAndSave(next http.Handler) http.Handler
|
// Manager 抽象核心会话操作
|
||||||
Put(ctx context.Context, key string, val any)
|
type Manager interface {
|
||||||
GetBytes(ctx context.Context, key string) []byte
|
Load(next http.Handler) http.Handler
|
||||||
Exists(ctx context.Context, key string) bool
|
GetUser(ctx context.Context, key string) (*dto.AuthorizeUser, error)
|
||||||
|
PutUser(ctx context.Context, key string, user *dto.AuthorizeUser) error
|
||||||
RenewToken(ctx context.Context) error
|
RenewToken(ctx context.Context) error
|
||||||
|
Destroy(ctx context.Context) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type session struct {
|
type SCSSession struct {
|
||||||
sessionManager *scs.SessionManager
|
manager *scs.SessionManager
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(db *gorm.DB, config *config.Config) Session {
|
func NewSCSManager(db *gorm.DB, config *config.Config) (Manager, error) {
|
||||||
sessionManager := scs.New()
|
sessionManager := scs.New()
|
||||||
sessionManager.Lifetime = 24 * time.Hour
|
sessionManager.Lifetime = 24 * time.Hour
|
||||||
sessionManager.IdleTimeout = 2 * time.Hour
|
sessionManager.IdleTimeout = 2 * time.Hour
|
||||||
@ -35,7 +40,11 @@ func New(db *gorm.DB, config *config.Config) Session {
|
|||||||
sessionManager.Cookie.SameSite = http.SameSiteStrictMode
|
sessionManager.Cookie.SameSite = http.SameSiteStrictMode
|
||||||
sessionManager.Cookie.Secure = config.App.Prod
|
sessionManager.Cookie.Secure = config.App.Prod
|
||||||
|
|
||||||
sqlDB, _ := db.DB()
|
sqlDB, err := db.DB()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
// postgres
|
// postgres
|
||||||
// github.com/alexedwards/scs/postgresstore
|
// github.com/alexedwards/scs/postgresstore
|
||||||
sessionManager.Store = postgresstore.New(sqlDB)
|
sessionManager.Store = postgresstore.New(sqlDB)
|
||||||
@ -44,32 +53,39 @@ func New(db *gorm.DB, config *config.Config) Session {
|
|||||||
// sessionManager.Store = pgxstore.New(pool)
|
// sessionManager.Store = pgxstore.New(pool)
|
||||||
// redis
|
// redis
|
||||||
// sessionManager.Store = newRedisStore()
|
// sessionManager.Store = newRedisStore()
|
||||||
|
return &SCSSession{manager: sessionManager}, nil
|
||||||
return &session{
|
|
||||||
sessionManager: sessionManager,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *session) Destroy(ctx context.Context) error {
|
func (s *SCSSession) Load(next http.Handler) http.Handler {
|
||||||
return s.sessionManager.Destroy(ctx)
|
return s.manager.LoadAndSave(next)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *session) LoadAndSave(next http.Handler) http.Handler {
|
func (s *SCSSession) GetUser(ctx context.Context, key string) (*dto.AuthorizeUser, error) {
|
||||||
return s.sessionManager.LoadAndSave(next)
|
data, ok := s.manager.Get(ctx, key).([]byte)
|
||||||
|
if !ok || len(data) == 0 {
|
||||||
|
return nil, ErrNoSession
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *session) Put(ctx context.Context, key string, val any) {
|
var user dto.AuthorizeUser
|
||||||
s.sessionManager.Put(ctx, key, val)
|
if err := json.Unmarshal(data, &user); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &user, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *session) GetBytes(ctx context.Context, key string) []byte {
|
func (s *SCSSession) PutUser(ctx context.Context, key string, user *dto.AuthorizeUser) error {
|
||||||
return s.sessionManager.GetBytes(ctx, key)
|
data, err := json.Marshal(user)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
s.manager.Put(ctx, key, data)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *session) Exists(ctx context.Context, key string) bool {
|
func (s *SCSSession) RenewToken(ctx context.Context) error {
|
||||||
return s.sessionManager.Exists(ctx, key)
|
return s.manager.RenewToken(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *session) RenewToken(ctx context.Context) error {
|
func (s *SCSSession) Destroy(ctx context.Context) error {
|
||||||
return s.sessionManager.RenewToken(ctx)
|
return s.manager.Destroy(ctx)
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user