Compare commits

...

2 Commits

Author SHA1 Message Date
4ac5b1c101 Fix error reponses
Signed-off-by: Asai Neko <sugar@sne.moe>
2026-01-21 10:01:13 +08:00
b7e6009706 Change logrus to slog
Signed-off-by: Asai Neko <sugar@sne.moe>
2026-01-21 09:52:54 +08:00
14 changed files with 113 additions and 107 deletions

View File

@@ -1,11 +1,10 @@
package config package config
import ( import (
"log/slog"
"os" "os"
"strings" "strings"
log "github.com/sirupsen/logrus"
"github.com/spf13/viper" "github.com/spf13/viper"
) )
@@ -30,9 +29,11 @@ func Init() {
conf := &config{} conf := &config{}
if err := viper.ReadInConfig(); err != nil { if err := viper.ReadInConfig(); err != nil {
// Dont generate config when using dev mode // Dont generate config when using dev mode
log.Fatalln("Can't read config!") slog.Error("[Config] Can't read config!", "err", err)
os.Exit(1)
} }
if err := viper.Unmarshal(conf); err != nil { if err := viper.Unmarshal(conf); err != nil {
log.Fatalln(err) slog.Error("[Condig] Can't unmarshal config!", "err", err)
os.Exit(1)
} }
} }

View File

@@ -228,13 +228,13 @@ func (self *Attendance) VerifyCheckinCode(checkinCode string) error {
val, err := Redis.Get(ctx, "checkin_code:"+checkinCode).Result() val, err := Redis.Get(ctx, "checkin_code:"+checkinCode).Result()
if err != nil { if err != nil {
return errors.New("invalid or expired checkin code") return errors.New("[Attendance Data] invalid or expired checkin code")
} }
// Expected format: user_id:<uuid>:event_id:<uuid> // Expected format: user_id:<uuid>:event_id:<uuid>
parts := strings.Split(val, ":") parts := strings.Split(val, ":")
if len(parts) != 4 { if len(parts) != 4 {
return errors.New("invalid checkin code format") return errors.New("[Attendance Data] invalid checkin code format")
} }
userIdStr := parts[1] userIdStr := parts[1]

View File

@@ -87,5 +87,5 @@ func (self *Client) ValidateRedirectURI(redirectURI string) error {
return nil return nil
} }
} }
return errors.New("redirect uri not match") return errors.New("[Client Data] redirect uri not match")
} }

View File

@@ -2,10 +2,12 @@ package data
import ( import (
"nixcn-cms/data/drivers" "nixcn-cms/data/drivers"
"os"
"log/slog"
"github.com/meilisearch/meilisearch-go" "github.com/meilisearch/meilisearch-go"
"github.com/redis/go-redis/v9" "github.com/redis/go-redis/v9"
log "github.com/sirupsen/logrus"
"github.com/spf13/viper" "github.com/spf13/viper"
"gorm.io/gorm" "gorm.io/gorm"
) )
@@ -25,19 +27,22 @@ func Init() {
} }
if dbType != "postgres" { if dbType != "postgres" {
log.Fatal("[Database] Only support postgras db!") slog.Error("[Database] Only support postgras db!")
os.Exit(1)
} }
// Conect to db // Conect to db
db, err := drivers.Postgres(exDSN) db, err := drivers.Postgres(exDSN)
if err != nil { if err != nil {
log.Fatal("[Database] Error connecting to db!") slog.Error("[Database] Error connecting to db!")
os.Exit(1)
} }
// Auto migrate // Auto migrate
err = db.AutoMigrate(&User{}, &Event{}, &Attendance{}, &Client{}) err = db.AutoMigrate(&User{}, &Event{}, &Attendance{}, &Client{})
if err != nil { if err != nil {
log.Error("[Database] Error migrating database: ", err) slog.Error("[Database] Error migrating database!", "err", err)
os.Exit(1)
} }
Database = db Database = db
@@ -52,7 +57,8 @@ func Init() {
} }
rdb, err := drivers.Redis(rDSN) rdb, err := drivers.Redis(rDSN)
if err != nil { if err != nil {
log.Fatal("[Redis] Error connecting to Redis: ", err) slog.Error("[Redis] Error connecting to Redis!", "err", err)
os.Exit(1)
} }
Redis = rdb Redis = rdb

4
go.mod
View File

@@ -10,14 +10,13 @@ require (
github.com/aliyun/credentials-go v1.4.5 github.com/aliyun/credentials-go v1.4.5
github.com/gin-gonic/gin v1.11.0 github.com/gin-gonic/gin v1.11.0
github.com/go-viper/mapstructure/v2 v2.4.0 github.com/go-viper/mapstructure/v2 v2.4.0
github.com/goccy/go-json v0.10.5
github.com/golang-jwt/jwt/v5 v5.3.0 github.com/golang-jwt/jwt/v5 v5.3.0
github.com/google/uuid v1.6.0 github.com/google/uuid v1.6.0
github.com/meilisearch/meilisearch-go v0.35.0 github.com/meilisearch/meilisearch-go v0.35.0
github.com/redis/go-redis/v9 v9.17.2 github.com/redis/go-redis/v9 v9.17.2
github.com/sirupsen/logrus v1.9.3
github.com/spf13/viper v1.21.0 github.com/spf13/viper v1.21.0
golang.org/x/crypto v0.46.0 golang.org/x/crypto v0.46.0
golang.org/x/oauth2 v0.34.0
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
gorm.io/datatypes v1.2.7 gorm.io/datatypes v1.2.7
gorm.io/driver/postgres v1.6.0 gorm.io/driver/postgres v1.6.0
@@ -44,7 +43,6 @@ require (
github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.29.0 // indirect github.com/go-playground/validator/v10 v10.29.0 // indirect
github.com/go-sql-driver/mysql v1.8.1 // indirect github.com/go-sql-driver/mysql v1.8.1 // indirect
github.com/goccy/go-json v0.10.5 // indirect
github.com/goccy/go-yaml v1.19.1 // indirect github.com/goccy/go-yaml v1.19.1 // indirect
github.com/golang-jwt/jwt/v4 v4.5.2 // indirect github.com/golang-jwt/jwt/v4 v4.5.2 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect

5
go.sum
View File

@@ -193,8 +193,6 @@ github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjR
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc= github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc=
github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik= github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/assertions v1.1.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo= github.com/smartystreets/assertions v1.1.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
@@ -292,8 +290,6 @@ golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU= golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU=
golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY= golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.34.0 h1:hqK/t4AKgbqWkdkcAeI8XLmbK+4m4G5YeQRrmiotGlw=
golang.org/x/oauth2 v0.34.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -315,7 +311,6 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=

View File

@@ -21,7 +21,7 @@ func normalizeKey(key []byte) ([]byte, error) {
case 16, 24, 32: case 16, 24, 32:
return key, nil return key, nil
default: default:
return nil, errors.New("AES key length must be 16, 24, or 32 bytes") return nil, errors.New("[Cryptography AES] AES key length must be 16, 24, or 32 bytes")
} }
} }
@@ -74,7 +74,7 @@ func AESGCMDecrypt(encoded string, key []byte) ([]byte, error) {
} }
if len(data) < gcm.NonceSize() { if len(data) < gcm.NonceSize() {
return nil, errors.New("ciphertext too short") return nil, errors.New("[Cryptography AES] ciphertext too short")
} }
nonce := data[:gcm.NonceSize()] nonce := data[:gcm.NonceSize()]
@@ -92,11 +92,11 @@ func pkcs7Pad(data []byte, blockSize int) []byte {
func pkcs7Unpad(data []byte) ([]byte, error) { func pkcs7Unpad(data []byte) ([]byte, error) {
length := len(data) length := len(data)
if length == 0 { if length == 0 {
return nil, errors.New("invalid padding") return nil, errors.New("[Cryptography AES] invalid padding")
} }
padding := int(data[length-1]) padding := int(data[length-1])
if padding == 0 || padding > length { if padding == 0 || padding > length {
return nil, errors.New("invalid padding") return nil, errors.New("[Cryptography AES] invalid padding")
} }
return data[:length-padding], nil return data[:length-padding], nil
} }
@@ -143,7 +143,7 @@ func AESCBCDecrypt(encoded string, key []byte) ([]byte, error) {
} }
if len(data) < block.BlockSize() { if len(data) < block.BlockSize() {
return nil, errors.New("ciphertext too short") return nil, errors.New("[Cryptography AES] ciphertext too short")
} }
iv := data[:block.BlockSize()] iv := data[:block.BlockSize()]
@@ -195,7 +195,7 @@ func AESCFBDecrypt(encoded string, key []byte) ([]byte, error) {
} }
if len(data) < block.BlockSize() { if len(data) < block.BlockSize() {
return nil, errors.New("ciphertext too short") return nil, errors.New("[Cryptography AES] ciphertext too short")
} }
iv := data[:block.BlockSize()] iv := data[:block.BlockSize()]

View File

@@ -1,46 +0,0 @@
package logger
import (
"io"
"os"
"github.com/gin-gonic/gin"
"github.com/sirupsen/logrus"
)
func Init() {
levelStr := os.Getenv("LOG_LEVEL")
level, err := logrus.ParseLevel(levelStr)
if err != nil {
level = logrus.InfoLevel
}
logrus.SetLevel(level)
if level == logrus.DebugLevel {
gin.SetMode(gin.DebugMode)
} else {
gin.SetMode(gin.ReleaseMode)
gin.DisableConsoleColor()
}
logrus.SetFormatter(&logrus.JSONFormatter{
TimestampFormat: "2006-01-02 15:04:05",
})
logrus.SetReportCaller(true)
file, err := os.OpenFile("app.log", os.O_APPEND|os.O_CREATE|os.O_RDWR, 0666)
if err != nil {
logrus.SetOutput(os.Stdout)
logrus.Errorf("Error to create log file: %v", err)
} else {
logrus.SetOutput(io.MultiWriter(os.Stdout, file))
}
logrus.RegisterExitHandler(func() {
if file != nil {
file.Sync()
file.Close()
}
})
}

47
logger/slog.go Normal file
View File

@@ -0,0 +1,47 @@
package logger
import (
"io"
"log/slog"
"os"
"strings"
)
func Init() {
levelStr := strings.ToLower(os.Getenv("LOG_LEVEL"))
var level slog.Level
switch levelStr {
case "debug":
level = slog.LevelDebug
case "warn":
level = slog.LevelWarn
case "error":
level = slog.LevelError
default:
level = slog.LevelInfo
}
file, err := os.OpenFile("app.log", os.O_APPEND|os.O_CREATE|os.O_RDWR, 0666)
var writer io.Writer = os.Stdout
if err != nil {
slog.Error("Error to create log file", "err", err)
} else {
writer = io.MultiWriter(os.Stdout, file)
}
opts := &slog.HandlerOptions{
Level: level,
AddSource: true,
ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr {
if a.Key == slog.TimeKey {
return slog.String(a.Key, a.Value.Time().Format("2006-01-02 15:04:05"))
}
return a
},
}
handler := slog.NewJSONHandler(writer, opts)
logger := slog.New(handler)
slog.SetDefault(logger)
}

View File

@@ -2,12 +2,12 @@ package middleware
import ( import (
"bytes" "bytes"
"encoding/json"
"io" "io"
"log/slog"
"time" "time"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/sirupsen/logrus"
log "github.com/sirupsen/logrus"
) )
func GinLogger() gin.HandlerFunc { func GinLogger() gin.HandlerFunc {
@@ -18,6 +18,8 @@ func GinLogger() gin.HandlerFunc {
c.Request.Body = io.NopCloser(bytes.NewBuffer(body)) c.Request.Body = io.NopCloser(bytes.NewBuffer(body))
} }
headerJSON, _ := json.Marshal(c.Request.Header)
startTime := time.Now() startTime := time.Now()
c.Next() c.Next()
@@ -27,23 +29,25 @@ func GinLogger() gin.HandlerFunc {
errorMessage = c.Errors.String() errorMessage = c.Errors.String()
} }
entry := log.WithFields(logrus.Fields{ fields := []any{
"status": c.Writer.Status(), "status", c.Writer.Status(),
"method": c.Request.Method, "method", c.Request.Method,
"uri": c.Request.RequestURI, "uri", c.Request.RequestURI,
"ip": c.ClientIP(), "ip", c.ClientIP(),
"latency": time.Since(startTime).String(), "latency", time.Since(startTime).String(),
"user_agent": c.Request.UserAgent(), "user_agent", c.Request.UserAgent(),
"request_body": string(body), "headers", string(headerJSON),
"errors": errorMessage, "request_body", string(body),
}) "errors", errorMessage,
}
if len(c.Errors) > 0 || c.Writer.Status() >= 500 { status := c.Writer.Status()
entry.Error("HTTP_ERROR") if len(c.Errors) > 0 || status >= 500 {
} else if c.Writer.Status() >= 400 { slog.Error("HTTP_ERROR", fields...)
entry.Warn("HTTP_CLIENT_ERROR") } else if status >= 400 {
slog.Warn("HTTP_CLIENT_ERROR", fields...)
} else { } else {
entry.Info("HTTP_SUCCESS") slog.Info("HTTP_SUCCESS", fields...)
} }
} }
} }

View File

@@ -129,14 +129,14 @@ func (self *Token) RefreshAccessToken(refreshToken string) (string, error) {
// read refresh token bind data // read refresh token bind data
dataMap, err := data.Redis.HGetAll(ctx, key).Result() dataMap, err := data.Redis.HGetAll(ctx, key).Result()
if err != nil || len(dataMap) == 0 { if err != nil || len(dataMap) == 0 {
return "", errors.New("invalid refresh token") return "", errors.New("[Auth Token] invalid refresh token")
} }
userIdStr := dataMap["user_id"] userIdStr := dataMap["user_id"]
clientId := dataMap["client_id"] clientId := dataMap["client_id"]
if userIdStr == "" || clientId == "" { if userIdStr == "" || clientId == "" {
return "", errors.New("refresh token corrupted") return "", errors.New("[Auth Token] refresh token corrupted")
} }
userId, err := uuid.Parse(userIdStr) userId, err := uuid.Parse(userIdStr)
@@ -157,14 +157,14 @@ func (self *Token) RenewRefreshToken(refreshToken string) (string, error) {
// read old refresh token bind data // read old refresh token bind data
dataMap, err := data.Redis.HGetAll(ctx, oldKey).Result() dataMap, err := data.Redis.HGetAll(ctx, oldKey).Result()
if err != nil || len(dataMap) == 0 { if err != nil || len(dataMap) == 0 {
return "", errors.New("invalid refresh token") return "", errors.New("[Auth Token] invalid refresh token")
} }
userIdStr := dataMap["user_id"] userIdStr := dataMap["user_id"]
clientId := dataMap["client_id"] clientId := dataMap["client_id"]
if userIdStr == "" || clientId == "" { if userIdStr == "" || clientId == "" {
return "", errors.New("refresh token corrupted") return "", errors.New("[Auth Token] refresh token corrupted")
} }
// generate new refresh token // generate new refresh token
@@ -254,7 +254,7 @@ func (self *Token) HeaderVerify(header string) (string, error) {
// Split header to 2 // Split header to 2
parts := strings.SplitN(header, " ", 2) parts := strings.SplitN(header, " ", 2)
if len(parts) != 2 || parts[0] != "Bearer" { if len(parts) != 2 || parts[0] != "Bearer" {
return "", errors.New("invalid Authorization header format") return "", errors.New("[Auth Token] invalid Authorization header format")
} }
tokenStr := parts[1] tokenStr := parts[1]
@@ -266,11 +266,11 @@ func (self *Token) HeaderVerify(header string) (string, error) {
claims, claims,
func(token *jwt.Token) (any, error) { func(token *jwt.Token) (any, error) {
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, errors.New("unexpected signing method") return nil, errors.New("[Auth Token] unexpected signing method")
} }
if claims.ClientId == "" { if claims.ClientId == "" {
return nil, errors.New("client_id missing in token") return nil, errors.New("[Auth Token] client_id missing in token")
} }
clientData, err := new(data.Client).GetClientByClientId(claims.ClientId) clientData, err := new(data.Client).GetClientByClientId(claims.ClientId)
@@ -289,7 +289,7 @@ func (self *Token) HeaderVerify(header string) (string, error) {
if err != nil || !token.Valid { if err != nil || !token.Valid {
fmt.Println(err) fmt.Println(err)
return "", errors.New("invalid or expired token") return "", errors.New("[Auth Token] invalid or expired token")
} }
return claims.UserID.String(), nil return claims.UserID.String(), nil

View File

@@ -30,11 +30,11 @@ func (self *Client) NewSMTPClient() (*Client, error) {
insecure := viper.GetBool("email.insecure_skip_verify") insecure := viper.GetBool("email.insecure_skip_verify")
if host == "" || port == 0 || user == "" { if host == "" || port == 0 || user == "" {
return nil, errors.New("SMTP config not set") return nil, errors.New("[Email] SMTP config not set")
} }
if pass == "" { if pass == "" {
return nil, errors.New("SMTP basic auth requires email.password") return nil, errors.New("[Email] SMTP basic auth requires email.password")
} }
dialer := gomail.NewDialer(host, port, user, pass) dialer := gomail.NewDialer(host, port, user, pass)
@@ -52,7 +52,7 @@ func (self *Client) NewSMTPClient() (*Client, error) {
dialer.SSL = false dialer.SSL = false
dialer.TLSConfig = nil dialer.TLSConfig = nil
default: default:
return nil, errors.New("unknown smtp security mode: " + security) return nil, errors.New("[Email] unknown smtp security mode: " + security)
} }
return &Client{ return &Client{
@@ -67,7 +67,7 @@ func (self *Client) NewSMTPClient() (*Client, error) {
func (c *Client) Send(from, to, subject, html string) (string, error) { func (c *Client) Send(from, to, subject, html string) (string, error) {
if c.dialer == nil { if c.dialer == nil {
return "", errors.New("SMTP dialer not initialized") return "", errors.New("[Email] SMTP dialer not initialized")
} }
m := gomail.NewMessage() m := gomail.NewMessage()

View File

@@ -21,12 +21,12 @@ import (
func DecodeB64Json(b64Json string) (*KycInfo, error) { func DecodeB64Json(b64Json string) (*KycInfo, error) {
rawJson, err := base64.StdEncoding.DecodeString(b64Json) rawJson, err := base64.StdEncoding.DecodeString(b64Json)
if err != nil { if err != nil {
return nil, errors.New("invalid base64 json") return nil, errors.New("[KYC] invalid base64 json")
} }
var kyc KycInfo var kyc KycInfo
if err := json.Unmarshal(rawJson, &kyc); err != nil { if err := json.Unmarshal(rawJson, &kyc); err != nil {
return nil, errors.New("invalid json structure") return nil, errors.New("[KYC] invalid json structure")
} }
return &kyc, nil return &kyc, nil
@@ -56,7 +56,7 @@ func DecodeAES(cipherStr string) (*KycInfo, error) {
var kyc KycInfo var kyc KycInfo
if err := json.Unmarshal(plainBytes, &kyc); err != nil { if err := json.Unmarshal(plainBytes, &kyc); err != nil {
return nil, errors.New("invalid decrypted json") return nil, errors.New("[KYC] invalid decrypted json")
} }
return &kyc, nil return &kyc, nil

View File

@@ -1,18 +1,19 @@
package server package server
import ( import (
"log/slog"
"net/http" "net/http"
"nixcn-cms/middleware" "nixcn-cms/middleware"
"time" "time"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
log "github.com/sirupsen/logrus"
"github.com/spf13/viper" "github.com/spf13/viper"
) )
func Start() { func Start() {
if !viper.GetBool("server.debug_mode") { if !viper.GetBool("server.debug_mode") {
gin.SetMode(gin.ReleaseMode) gin.SetMode(gin.ReleaseMode)
gin.DisableConsoleColor()
} }
r := gin.New() r := gin.New()
@@ -29,8 +30,8 @@ func Start() {
MaxHeaderBytes: 1 << 20, MaxHeaderBytes: 1 << 20,
} }
log.Info("Starting server on " + viper.GetString("server.address")) slog.Info("[Server] Starting server on " + viper.GetString("server.address"))
if err := server.ListenAndServe(); err != nil { if err := server.ListenAndServe(); err != nil {
log.Errorf("Error starting server: %v\n", err) slog.Error("[Server] Error starting server!", "err", err)
} }
} }