Browse Source

chore: update cosy

0xJacky 1 year ago
parent
commit
9be508c976

+ 1 - 1
.air.toml

@@ -7,7 +7,7 @@ tmp_dir = "tmp"
 
 
 [build]
 [build]
 # Just plain old shell command. You could use `make` as well.
 # Just plain old shell command. You could use `make` as well.
-cmd = "CGO_ENABLED=1 go build -tags=jsoniter -ldflags=\"-X 'github.com/0xJacky/Nginx-UI/server/settings.buildTime=$(date +%s)'\" -o ./tmp/main ."
+cmd = "CGO_ENABLED=1 go build -tags=jsoniter -ldflags=\"-X 'github.com/0xJacky/Nginx-UI/server/settings.buildTime=$(date +%s)'\" -v -o ./tmp/main ."
 # Binary file yields from `cmd`.
 # Binary file yields from `cmd`.
 bin = "tmp/main"
 bin = "tmp/main"
 # Customize binary.
 # Customize binary.

+ 68 - 68
api/cosy/cosy.go

@@ -1,117 +1,117 @@
 package cosy
 package cosy
 
 
 import (
 import (
-	"github.com/0xJacky/Nginx-UI/internal/logger"
-	"github.com/gin-gonic/gin"
-	"github.com/go-playground/validator/v10"
-	"gorm.io/gorm"
+    "github.com/0xJacky/Nginx-UI/internal/logger"
+    "github.com/gin-gonic/gin"
+    "github.com/go-playground/validator/v10"
+    "gorm.io/gorm"
 )
 )
 
 
 var validate *validator.Validate
 var validate *validator.Validate
 
 
 func init() {
 func init() {
-	validate = validator.New()
+    validate = validator.New()
 }
 }
 
 
 type Ctx[T any] struct {
 type Ctx[T any] struct {
-	ctx                      *gin.Context
-	rules                    gin.H
-	Payload                  map[string]interface{}
-	Model                    T
-	OriginModel              T
-	table                    string
-	tableArgs                []interface{}
-	abort                    bool
-	nextHandler              *gin.HandlerFunc
-	skipAssociationsOnCreate bool
-	beforeDecodeHookFunc     []func(ctx *Ctx[T])
-	beforeExecuteHookFunc    []func(ctx *Ctx[T])
-	executedHookFunc         []func(ctx *Ctx[T])
-	gormScopes               []func(tx *gorm.DB) *gorm.DB
-	preloads                 []string
-	scan                     func(tx *gorm.DB) any
-	transformer              func(*T) any
-	permanentlyDelete        bool
-	SelectedFields           []string
-	itemKey                  string
+    ctx                      *gin.Context
+    rules                    gin.H
+    Payload                  map[string]interface{}
+    Model                    T
+    OriginModel              T
+    table                    string
+    tableArgs                []interface{}
+    abort                    bool
+    nextHandler              *gin.HandlerFunc
+    skipAssociationsOnCreate bool
+    beforeDecodeHookFunc     []func(ctx *Ctx[T])
+    beforeExecuteHookFunc    []func(ctx *Ctx[T])
+    executedHookFunc         []func(ctx *Ctx[T])
+    gormScopes               []func(tx *gorm.DB) *gorm.DB
+    preloads                 []string
+    scan                     func(tx *gorm.DB) any
+    transformer              func(*T) any
+    permanentlyDelete        bool
+    SelectedFields           []string
+    itemKey                  string
 }
 }
 
 
 func Core[T any](c *gin.Context) *Ctx[T] {
 func Core[T any](c *gin.Context) *Ctx[T] {
-	return &Ctx[T]{
-		ctx:                      c,
-		gormScopes:               make([]func(tx *gorm.DB) *gorm.DB, 0),
-		beforeExecuteHookFunc:    make([]func(ctx *Ctx[T]), 0),
-		beforeDecodeHookFunc:     make([]func(ctx *Ctx[T]), 0),
-		itemKey:                  "`id`",
-		skipAssociationsOnCreate: true,
-	}
+    return &Ctx[T]{
+        ctx:                      c,
+        gormScopes:               make([]func(tx *gorm.DB) *gorm.DB, 0),
+        beforeExecuteHookFunc:    make([]func(ctx *Ctx[T]), 0),
+        beforeDecodeHookFunc:     make([]func(ctx *Ctx[T]), 0),
+        itemKey:                  "`id`",
+        skipAssociationsOnCreate: true,
+    }
 }
 }
 
 
 func (c *Ctx[T]) SetTable(table string, args ...interface{}) *Ctx[T] {
 func (c *Ctx[T]) SetTable(table string, args ...interface{}) *Ctx[T] {
-	c.table = table
-	c.tableArgs = args
-	return c
+    c.table = table
+    c.tableArgs = args
+    return c
 }
 }
 
 
 func (c *Ctx[T]) SetItemKey(key string) *Ctx[T] {
 func (c *Ctx[T]) SetItemKey(key string) *Ctx[T] {
-	c.itemKey = key
-	return c
+    c.itemKey = key
+    return c
 }
 }
 
 
 func (c *Ctx[T]) SetValidRules(rules gin.H) *Ctx[T] {
 func (c *Ctx[T]) SetValidRules(rules gin.H) *Ctx[T] {
-	c.rules = rules
+    c.rules = rules
 
 
-	return c
+    return c
 }
 }
 
 
 func (c *Ctx[T]) SetPreloads(args ...string) *Ctx[T] {
 func (c *Ctx[T]) SetPreloads(args ...string) *Ctx[T] {
-	c.preloads = append(c.preloads, args...)
-	return c
+    c.preloads = append(c.preloads, args...)
+    return c
 }
 }
 
 
 func (c *Ctx[T]) validate() (errs gin.H) {
 func (c *Ctx[T]) validate() (errs gin.H) {
-	c.Payload = make(gin.H)
+    c.Payload = make(gin.H)
 
 
-	_ = c.ctx.ShouldBindJSON(&c.Payload)
+    _ = c.ctx.ShouldBindJSON(&c.Payload)
 
 
-	errs = validate.ValidateMap(c.Payload, c.rules)
+    errs = validate.ValidateMap(c.Payload, c.rules)
 
 
-	if len(errs) > 0 {
-		logger.Debug(errs)
-		for k := range errs {
-			errs[k] = c.rules[k]
-		}
-		return
-	}
-	// Make sure that the key in c.Payload is also the key of rules
-	validated := make(map[string]interface{})
+    if len(errs) > 0 {
+        logger.Debug(errs)
+        for k := range errs {
+            errs[k] = c.rules[k]
+        }
+        return
+    }
+    // Make sure that the key in c.Payload is also the key of rules
+    validated := make(map[string]interface{})
 
 
-	for k, v := range c.Payload {
-		if _, ok := c.rules[k]; ok {
-			validated[k] = v
-		}
-	}
+    for k, v := range c.Payload {
+        if _, ok := c.rules[k]; ok {
+            validated[k] = v
+        }
+    }
 
 
-	c.Payload = validated
+    c.Payload = validated
 
 
-	return
+    return
 }
 }
 
 
 func (c *Ctx[T]) SetScan(scan func(tx *gorm.DB) any) *Ctx[T] {
 func (c *Ctx[T]) SetScan(scan func(tx *gorm.DB) any) *Ctx[T] {
-	c.scan = scan
-	return c
+    c.scan = scan
+    return c
 }
 }
 
 
 func (c *Ctx[T]) SetTransformer(t func(m *T) any) *Ctx[T] {
 func (c *Ctx[T]) SetTransformer(t func(m *T) any) *Ctx[T] {
-	c.transformer = t
-	return c
+    c.transformer = t
+    return c
 }
 }
 
 
 func (c *Ctx[T]) AbortWithError(err error) {
 func (c *Ctx[T]) AbortWithError(err error) {
-	c.abort = true
-	errHandler(c.ctx, err)
+    c.abort = true
+    errHandler(c.ctx, err)
 }
 }
 
 
 func (c *Ctx[T]) Abort() {
 func (c *Ctx[T]) Abort() {
-	c.abort = true
+    c.abort = true
 }
 }

+ 8 - 7
api/cosy/create.go

@@ -1,9 +1,9 @@
 package cosy
 package cosy
 
 
 import (
 import (
-	"github.com/gin-gonic/gin"
 	"github.com/0xJacky/Nginx-UI/api/cosy/map2struct"
 	"github.com/0xJacky/Nginx-UI/api/cosy/map2struct"
 	"github.com/0xJacky/Nginx-UI/model"
 	"github.com/0xJacky/Nginx-UI/model"
+	"github.com/gin-gonic/gin"
 	"gorm.io/gorm/clause"
 	"gorm.io/gorm/clause"
 	"net/http"
 	"net/http"
 )
 )
@@ -52,12 +52,6 @@ func (c *Ctx[T]) Create() {
 		return
 		return
 	}
 	}
 
 
-	tx := db.Preload(clause.Associations)
-	for _, v := range c.preloads {
-		tx = tx.Preload(v)
-	}
-	tx.Table(c.table, c.tableArgs...).First(&c.Model)
-
 	if len(c.executedHookFunc) > 0 {
 	if len(c.executedHookFunc) > 0 {
 		for _, v := range c.executedHookFunc {
 		for _, v := range c.executedHookFunc {
 			v(c)
 			v(c)
@@ -67,6 +61,13 @@ func (c *Ctx[T]) Create() {
 			}
 			}
 		}
 		}
 	}
 	}
+
+	tx := db.Preload(clause.Associations)
+	for _, v := range c.preloads {
+		tx = tx.Preload(v)
+	}
+	tx.Table(c.table, c.tableArgs...).First(&c.Model)
+
 	if c.nextHandler != nil {
 	if c.nextHandler != nil {
 		(*c.nextHandler)(c.ctx)
 		(*c.nextHandler)(c.ctx)
 	} else {
 	} else {

+ 1 - 1
api/cosy/custom.go

@@ -1,8 +1,8 @@
 package cosy
 package cosy
 
 
 import (
 import (
-	"github.com/gin-gonic/gin"
 	"github.com/0xJacky/Nginx-UI/api/cosy/map2struct"
 	"github.com/0xJacky/Nginx-UI/api/cosy/map2struct"
+	"github.com/gin-gonic/gin"
 	"net/http"
 	"net/http"
 )
 )
 
 

+ 9 - 8
api/cosy/delete.go

@@ -2,6 +2,7 @@ package cosy
 
 
 import (
 import (
 	"github.com/0xJacky/Nginx-UI/model"
 	"github.com/0xJacky/Nginx-UI/model"
+	"github.com/spf13/cast"
 	"gorm.io/gorm"
 	"gorm.io/gorm"
 	"net/http"
 	"net/http"
 )
 )
@@ -20,9 +21,13 @@ func (c *Ctx[T]) Destroy() {
 	c.beforeExecuteHook()
 	c.beforeExecuteHook()
 
 
 	db := model.UseDB()
 	db := model.UseDB()
-	var dbModel T
 
 
 	result := db
 	result := db
+
+	if cast.ToBool(c.ctx.Query("permanent")) || c.permanentlyDelete {
+		result = result.Unscoped()
+	}
+
 	if len(c.gormScopes) > 0 {
 	if len(c.gormScopes) > 0 {
 		result = result.Scopes(c.gormScopes...)
 		result = result.Scopes(c.gormScopes...)
 	}
 	}
@@ -30,9 +35,9 @@ func (c *Ctx[T]) Destroy() {
 	var err error
 	var err error
 	session := result.Session(&gorm.Session{})
 	session := result.Session(&gorm.Session{})
 	if c.table != "" {
 	if c.table != "" {
-		err = session.Table(c.table, c.tableArgs...).Take(&dbModel, id).Error
+		err = session.Table(c.table, c.tableArgs...).Take(c.OriginModel, id).Error
 	} else {
 	} else {
-		err = session.First(&dbModel, id).Error
+		err = session.First(&c.OriginModel, id).Error
 	}
 	}
 
 
 	if err != nil {
 	if err != nil {
@@ -40,11 +45,7 @@ func (c *Ctx[T]) Destroy() {
 		return
 		return
 	}
 	}
 
 
-	if c.permanentlyDelete {
-		result = result.Unscoped()
-	}
-
-	err = result.Delete(&dbModel).Error
+	err = result.Delete(&c.OriginModel).Error
 	if err != nil {
 	if err != nil {
 		errHandler(c.ctx, err)
 		errHandler(c.ctx, err)
 		return
 		return

+ 1 - 1
api/cosy/error.go

@@ -2,8 +2,8 @@ package cosy
 
 
 import (
 import (
 	"errors"
 	"errors"
-	"github.com/gin-gonic/gin"
 	"github.com/0xJacky/Nginx-UI/internal/logger"
 	"github.com/0xJacky/Nginx-UI/internal/logger"
+	"github.com/gin-gonic/gin"
 	"go.uber.org/zap"
 	"go.uber.org/zap"
 	"gorm.io/gorm"
 	"gorm.io/gorm"
 	"net/http"
 	"net/http"

+ 1 - 1
api/cosy/filter.go

@@ -2,8 +2,8 @@ package cosy
 
 
 import (
 import (
 	"fmt"
 	"fmt"
-	"github.com/gin-gonic/gin"
 	"github.com/0xJacky/Nginx-UI/internal/logger"
 	"github.com/0xJacky/Nginx-UI/internal/logger"
+	"github.com/gin-gonic/gin"
 	"gorm.io/gorm"
 	"gorm.io/gorm"
 	"gorm.io/gorm/clause"
 	"gorm.io/gorm/clause"
 	"strings"
 	"strings"

+ 57 - 52
api/cosy/list.go

@@ -49,13 +49,18 @@ func (c *Ctx[T]) result() (*gorm.DB, bool) {
 	result := model.UseDB()
 	result := model.UseDB()
 
 
 	if cast.ToBool(c.ctx.Query("trash")) {
 	if cast.ToBool(c.ctx.Query("trash")) {
-		stmt := &gorm.Statement{DB: model.UseDB()}
-		err := stmt.Parse(&dbModel)
-		if err != nil {
-			logger.Error(err)
-			return nil, false
+		tableName := c.table
+		if c.table == "" {
+			stmt := &gorm.Statement{DB: model.UseDB()}
+			err := stmt.Parse(&dbModel)
+			if err != nil {
+				logger.Error(err)
+				return nil, false
+			}
+			tableName = stmt.Schema.Table
 		}
 		}
-		result = result.Unscoped().Where(stmt.Schema.Table + ".deleted_at IS NOT NULL")
+
+		result = result.Unscoped().Where(tableName + ".deleted_at IS NOT NULL")
 	}
 	}
 
 
 	result = result.Model(&dbModel)
 	result = result.Model(&dbModel)
@@ -99,52 +104,52 @@ func (c *Ctx[T]) ListAllData() (data any, ok bool) {
 }
 }
 
 
 func (c *Ctx[T]) PagingListData() (*model.DataList, bool) {
 func (c *Ctx[T]) PagingListData() (*model.DataList, bool) {
-    result, ok := c.result()
-    if !ok {
-        return nil, false
-    }
-
-    scopesResult := result.Scopes(c.OrderAndPaginate())
-    data := &model.DataList{}
-    if c.scan == nil {
-        models := make([]*T, 0)
-        scopesResult.Find(&models)
-
-        if c.transformer != nil {
-            transformed := make([]any, 0)
-            for k := range models {
-                transformed = append(transformed, c.transformer(models[k]))
-            }
-            data.Data = transformed
-        } else {
-            data.Data = models
-        }
-    } else {
-        data.Data = c.scan(scopesResult)
-    }
-
-    var totalRecords int64
-    delete(result.Statement.Clauses, "ORDER BY")
-    delete(result.Statement.Clauses, "LIMIT")
-    result.Count(&totalRecords)
-
-    page := cast.ToInt(c.ctx.Query("page"))
-    if page == 0 {
-        page = 1
-    }
-
-    pageSize := settings.ServerSettings.PageSize
-    if reqPageSize := c.ctx.Query("page_size"); reqPageSize != "" {
-        pageSize = cast.ToInt(reqPageSize)
-    }
-
-    data.Pagination = model.Pagination{
-        Total:       totalRecords,
-        PerPage:     pageSize,
-        CurrentPage: page,
-        TotalPages:  model.TotalPage(totalRecords, pageSize),
-    }
-    return data, true
+	result, ok := c.result()
+	if !ok {
+		return nil, false
+	}
+
+	scopesResult := result.Scopes(c.OrderAndPaginate())
+	data := &model.DataList{}
+	if c.scan == nil {
+		models := make([]*T, 0)
+		scopesResult.Find(&models)
+
+		if c.transformer != nil {
+			transformed := make([]any, 0)
+			for k := range models {
+				transformed = append(transformed, c.transformer(models[k]))
+			}
+			data.Data = transformed
+		} else {
+			data.Data = models
+		}
+	} else {
+		data.Data = c.scan(scopesResult)
+	}
+
+	var totalRecords int64
+	delete(result.Statement.Clauses, "ORDER BY")
+	delete(result.Statement.Clauses, "LIMIT")
+	result.Count(&totalRecords)
+
+	page := cast.ToInt(c.ctx.Query("page"))
+	if page == 0 {
+		page = 1
+	}
+
+	pageSize := settings.ServerSettings.PageSize
+	if reqPageSize := c.ctx.Query("page_size"); reqPageSize != "" {
+		pageSize = cast.ToInt(reqPageSize)
+	}
+
+	data.Pagination = model.Pagination{
+		Total:       totalRecords,
+		PerPage:     pageSize,
+		CurrentPage: page,
+		TotalPages:  model.TotalPage(totalRecords, pageSize),
+	}
+	return data, true
 }
 }
 
 
 func (c *Ctx[T]) PagingList() {
 func (c *Ctx[T]) PagingList() {

+ 29 - 0
api/cosy/map2struct/hook.go

@@ -38,6 +38,35 @@ func ToTimeHookFunc() mapstructure.DecodeHookFunc {
 	}
 	}
 }
 }
 
 
+func ToTimePtrHookFunc() mapstructure.DecodeHookFunc {
+	return func(
+		f reflect.Type,
+		t reflect.Type,
+		data interface{}) (interface{}, error) {
+		if t != reflect.TypeOf(&time.Time{}) {
+			return data, nil
+		}
+
+		switch f.Kind() {
+		case reflect.String:
+			if data == "" {
+				return nil, nil
+			}
+			v, err := cast.ToTimeInDefaultLocationE(data, timeLocation)
+			return &v, err
+		case reflect.Float64:
+			v := time.Unix(0, int64(data.(float64))*int64(time.Millisecond))
+			return &v, nil
+		case reflect.Int64:
+			v := time.Unix(0, data.(int64)*int64(time.Millisecond))
+			return &v, nil
+		default:
+			return data, nil
+		}
+		// Convert it by parsing
+	}
+}
+
 func ToDecimalHookFunc() mapstructure.DecodeHookFunc {
 func ToDecimalHookFunc() mapstructure.DecodeHookFunc {
 	return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
 	return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
 
 

+ 1 - 0
api/cosy/map2struct/map2struct.go

@@ -11,6 +11,7 @@ func WeakDecode(input, output interface{}) error {
 		WeaklyTypedInput: true,
 		WeaklyTypedInput: true,
 		DecodeHook: mapstructure.ComposeDecodeHookFunc(
 		DecodeHook: mapstructure.ComposeDecodeHookFunc(
 			ToDecimalHookFunc(), ToTimeHookFunc(), ToNullableStringHookFunc(),
 			ToDecimalHookFunc(), ToTimeHookFunc(), ToNullableStringHookFunc(),
+			ToTimePtrHookFunc(),
 		),
 		),
 		TagName: "json",
 		TagName: "json",
 	}
 	}