Files
2025-08-21 16:14:09 +02:00

215 lines
4.7 KiB
Go

package controller
import (
"context"
"time"
"github.com/go-errors/errors"
"github.com/gin-gonic/gin"
"github.com/phishingclub/phishingclub/data"
"github.com/phishingclub/phishingclub/errs"
"github.com/phishingclub/phishingclub/model"
"github.com/phishingclub/phishingclub/service"
"github.com/phishingclub/phishingclub/vo"
"go.uber.org/zap"
"gorm.io/gorm"
"gorm.io/gorm/logger"
)
type SetLevelRequest struct {
Level string `json:"level"`
DBLevel string `json:"dbLevel"`
}
type Log struct {
Common
OptionService *service.Option
Database *gorm.DB
LoggerAtom *zap.AtomicLevel
}
// Panic is a test utility
func (c *Log) Panic(g *gin.Context) {
session, _, ok := c.handleSession(g)
if !ok {
return
}
if session == nil {
if ok := c.handleErrors(g, errors.New("no session")); !ok {
return
}
}
c.Deeper()
}
func (c *Log) Deeper() {
panic("panic test")
}
// Slow is a test utility
func (c *Log) Slow(g *gin.Context) {
session, _, ok := c.handleSession(g)
if !ok {
return
}
if session == nil {
if ok := c.handleErrors(g, errors.New("no session")); !ok {
return
}
}
c.Logger.Debugf("Slow request testing start")
time.Sleep(10 * time.Second)
c.Logger.Debugf("Slow request testing stop")
c.Response.OK(g, gin.H{})
}
// GetLevel gets the log level
func (c *Log) GetLevel(g *gin.Context) {
session, _, ok := c.handleSession(g)
if !ok {
return
}
// get the log levels
logLevelOption, err := c.OptionService.GetOption(
g,
session,
data.OptionKeyLogLevel,
)
// handle errors
if ok := c.handleErrors(g, err); !ok {
return
}
dbLogLevelOption, err := c.OptionService.GetOption(g, session, data.OptionKeyDBLogLevel)
// handle response
if ok := c.handleErrors(g, err); !ok {
return
}
c.Response.OK(g, gin.H{
"level": logLevelOption.Value,
"dbLevel": dbLogLevelOption.Value,
})
}
// SetLevel sets the log level
func (c *Log) SetLevel(g *gin.Context) {
session, _, ok := c.handleSession(g)
if !ok {
return
}
// parse request
var request SetLevelRequest
if ok := c.handleParseRequest(g, &request); !ok {
return
}
if request.Level == "" && request.DBLevel == "" {
c.Response.BadRequestMessage(g, "level or dbLevel is required")
return
}
if request.DBLevel != "" {
switch request.DBLevel {
case "silent":
c.Database.Logger = c.Database.Logger.LogMode(logger.Silent)
case "info":
c.Database.Logger = c.Database.Logger.LogMode(logger.Info)
case "warn":
c.Database.Logger = c.Database.Logger.LogMode(logger.Warn)
case "error":
c.Database.Logger = c.Database.Logger.LogMode(logger.Error)
default:
c.Logger.Debugw("invalid db log level",
"level", request.DBLevel,
)
c.Response.BadRequestMessage(g, "unknown DB log level")
return
}
// set db log level in database
dbLevel := vo.NewOptionalString1MBMust(request.DBLevel)
dbLogLevelOption := model.Option{
Key: *vo.NewString64Must(data.OptionKeyDBLogLevel),
Value: *dbLevel,
}
err := c.persist(
g,
session,
&dbLogLevelOption,
)
// handle response
if ok := c.handleErrors(g, err); !ok {
return
}
}
if request.Level != "" {
switch request.Level {
case "debug":
c.LoggerAtom.SetLevel(zap.DebugLevel)
case "info":
c.LoggerAtom.SetLevel(zap.InfoLevel)
case "warn":
c.LoggerAtom.SetLevel(zap.WarnLevel)
case "error":
c.LoggerAtom.SetLevel(zap.ErrorLevel)
default:
c.Logger.Debugw("invalid log level",
"level", request.Level,
)
c.Response.BadRequestMessage(g, "Unknown log level")
return
}
// set log level in in memory logger struct
logLevel := model.Option{
Key: *vo.NewString64Must(data.OptionKeyLogLevel),
Value: *vo.NewOptionalString1MBMust(request.Level),
}
err := c.persist(
g,
session,
&logLevel,
)
if ok := c.handleErrors(g, err); !ok {
return
}
}
c.Response.OK(g, nil)
}
// TestLog tests the log
// Sends a log message for each log level debug, info, warn, error
func (c *Log) TestLog(g *gin.Context) {
session, _, ok := c.handleSession(g)
if !ok {
return
}
// check permissions
isAuthorized, err := service.IsAuthorized(session, data.PERMISSION_ALLOW_GLOBAL)
if err != nil && !errors.Is(err, errs.ErrAuthorizationFailed) {
handleServerError(g, c.Response, err)
return
}
if !isAuthorized {
// TODO audit log
c.Response.Unauthorized(g)
return
}
c.Logger.Debug("Log: DEBUG Test")
c.Logger.Info("Log: INFO Test")
c.Logger.Warn("Log: WARN Test")
c.Logger.Error("Log: ERROR Test")
c.Response.OK(g, nil)
}
// persit saves the log level
// TODO this has become empty and superflous
func (c *Log) persist(
ctx context.Context,
session *model.Session,
logLevel *model.Option,
) error {
return c.OptionService.SetOptionByKey(
ctx,
session,
logLevel,
)
}