chore: update cosy

This commit is contained in:
0xJacky 2024-02-07 14:57:45 +08:00
parent e12e83c90a
commit 9be508c976
No known key found for this signature in database
GPG key ID: B6E4A6E4A561BAF0
10 changed files with 170 additions and 133 deletions

View file

@ -1,117 +1,117 @@
package cosy
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
func init() {
validate = validator.New()
validate = validator.New()
}
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] {
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] {
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] {
c.itemKey = key
return c
c.itemKey = key
return c
}
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] {
c.preloads = append(c.preloads, args...)
return c
c.preloads = append(c.preloads, args...)
return c
}
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] {
c.scan = scan
return c
c.scan = scan
return c
}
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) {
c.abort = true
errHandler(c.ctx, err)
c.abort = true
errHandler(c.ctx, err)
}
func (c *Ctx[T]) Abort() {
c.abort = true
c.abort = true
}

View file

@ -1,9 +1,9 @@
package cosy
import (
"github.com/gin-gonic/gin"
"github.com/0xJacky/Nginx-UI/api/cosy/map2struct"
"github.com/0xJacky/Nginx-UI/model"
"github.com/gin-gonic/gin"
"gorm.io/gorm/clause"
"net/http"
)
@ -52,12 +52,6 @@ func (c *Ctx[T]) Create() {
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 {
for _, v := range c.executedHookFunc {
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 {
(*c.nextHandler)(c.ctx)
} else {

View file

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

View file

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

View file

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

View file

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

View file

@ -49,13 +49,18 @@ func (c *Ctx[T]) result() (*gorm.DB, bool) {
result := model.UseDB()
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)
@ -99,52 +104,52 @@ func (c *Ctx[T]) ListAllData() (data any, ok bool) {
}
func (c *Ctx[T]) PagingListData() (*model.DataList, bool) {
result, ok := c.result()
if !ok {
return nil, false
}
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)
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)
}
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)
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
}
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)
}
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
data.Pagination = model.Pagination{
Total: totalRecords,
PerPage: pageSize,
CurrentPage: page,
TotalPages: model.TotalPage(totalRecords, pageSize),
}
return data, true
}
func (c *Ctx[T]) PagingList() {

View file

@ -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 {
return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {

View file

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