mirror of
https://github.com/0xJacky/nginx-ui.git
synced 2025-05-11 18:35:51 +02:00
refactor: migrate to new cosy
This commit is contained in:
parent
6082aef5d5
commit
33a996e777
111 changed files with 1163 additions and 1772 deletions
|
@ -1,7 +1,7 @@
|
|||
package analytic
|
||||
|
||||
import (
|
||||
"github.com/0xJacky/Nginx-UI/internal/logger"
|
||||
"github.com/uozi-tech/cosy/logger"
|
||||
"github.com/shirou/gopsutil/v3/net"
|
||||
"time"
|
||||
)
|
||||
|
|
|
@ -2,7 +2,7 @@ package analytic
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/0xJacky/Nginx-UI/internal/logger"
|
||||
"github.com/uozi-tech/cosy/logger"
|
||||
"github.com/0xJacky/Nginx-UI/internal/transport"
|
||||
"github.com/0xJacky/Nginx-UI/internal/upgrader"
|
||||
"github.com/0xJacky/Nginx-UI/model"
|
||||
|
|
|
@ -3,7 +3,7 @@ package analytic
|
|||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"github.com/0xJacky/Nginx-UI/internal/logger"
|
||||
"github.com/uozi-tech/cosy/logger"
|
||||
"github.com/0xJacky/Nginx-UI/model"
|
||||
"github.com/0xJacky/Nginx-UI/query"
|
||||
"github.com/gorilla/websocket"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package analytic
|
||||
|
||||
import (
|
||||
"github.com/0xJacky/Nginx-UI/internal/logger"
|
||||
"github.com/uozi-tech/cosy/logger"
|
||||
"github.com/shirou/gopsutil/v3/cpu"
|
||||
"github.com/shirou/gopsutil/v3/load"
|
||||
"github.com/shirou/gopsutil/v3/net"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package analytic
|
||||
|
||||
import (
|
||||
"github.com/0xJacky/Nginx-UI/internal/logger"
|
||||
"github.com/uozi-tech/cosy/logger"
|
||||
"github.com/shirou/gopsutil/v3/cpu"
|
||||
"github.com/shirou/gopsutil/v3/disk"
|
||||
"github.com/shirou/gopsutil/v3/net"
|
||||
|
|
2
internal/cache/cache.go
vendored
2
internal/cache/cache.go
vendored
|
@ -1,7 +1,7 @@
|
|||
package cache
|
||||
|
||||
import (
|
||||
"github.com/0xJacky/Nginx-UI/internal/logger"
|
||||
"github.com/uozi-tech/cosy/logger"
|
||||
"github.com/dgraph-io/ristretto"
|
||||
"time"
|
||||
)
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
package cert
|
||||
|
||||
import (
|
||||
"github.com/0xJacky/Nginx-UI/internal/logger"
|
||||
"github.com/0xJacky/Nginx-UI/internal/notification"
|
||||
"github.com/0xJacky/Nginx-UI/model"
|
||||
"github.com/0xJacky/Nginx-UI/settings"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/uozi-tech/cosy/logger"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
@ -60,8 +60,8 @@ func autoCert(certModel *model.Cert) {
|
|||
notification.Error("Renew Certificate Error", strings.Join(certModel.Domains, ", "))
|
||||
return
|
||||
}
|
||||
if int(time.Now().Sub(certInfo.NotBefore).Hours()/24) < settings.ServerSettings.GetCertRenewalInterval() {
|
||||
// not after settings.ServerSettings.CertRenewalInterval, ignore
|
||||
if int(time.Now().Sub(certInfo.NotBefore).Hours()/24) < settings.CertSettings.GetCertRenewalInterval() {
|
||||
// not after settings.ServerSettings.RenewalInterval, ignore
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@ package cert
|
|||
|
||||
import (
|
||||
"github.com/0xJacky/Nginx-UI/internal/cert/dns"
|
||||
"github.com/0xJacky/Nginx-UI/internal/logger"
|
||||
"github.com/0xJacky/Nginx-UI/internal/nginx"
|
||||
"github.com/0xJacky/Nginx-UI/internal/transport"
|
||||
"github.com/0xJacky/Nginx-UI/query"
|
||||
|
@ -13,6 +12,7 @@ import (
|
|||
legolog "github.com/go-acme/lego/v4/log"
|
||||
dnsproviders "github.com/go-acme/lego/v4/providers/dns"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/uozi-tech/cosy/logger"
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
|
@ -87,7 +87,7 @@ func IssueCert(payload *ConfigPayload, logChan chan string, errChan chan error)
|
|||
l.Println("[INFO] [Nginx UI] Setting HTTP01 challenge provider")
|
||||
err = client.Challenge.SetHTTP01Provider(
|
||||
http01.NewProviderServer("",
|
||||
settings.ServerSettings.HTTPChallengePort,
|
||||
settings.CertSettings.HTTPChallengePort,
|
||||
),
|
||||
)
|
||||
case DNS01:
|
||||
|
@ -125,9 +125,9 @@ func IssueCert(payload *ConfigPayload, logChan chan string, errChan chan error)
|
|||
}
|
||||
challengeOptions := make([]dns01.ChallengeOption, 0)
|
||||
|
||||
if len(settings.ServerSettings.RecursiveNameservers) > 0 {
|
||||
if len(settings.CertSettings.RecursiveNameservers) > 0 {
|
||||
challengeOptions = append(challengeOptions,
|
||||
dns01.AddRecursiveNameservers(settings.ServerSettings.RecursiveNameservers),
|
||||
dns01.AddRecursiveNameservers(settings.CertSettings.RecursiveNameservers),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ package cert
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/0xJacky/Nginx-UI/internal/logger"
|
||||
"github.com/uozi-tech/cosy/logger"
|
||||
"github.com/0xJacky/Nginx-UI/model"
|
||||
"strings"
|
||||
"time"
|
||||
|
|
|
@ -2,7 +2,7 @@ package cert
|
|||
|
||||
import (
|
||||
"github.com/0xJacky/Nginx-UI/internal/helper"
|
||||
"github.com/0xJacky/Nginx-UI/internal/logger"
|
||||
"github.com/uozi-tech/cosy/logger"
|
||||
"github.com/0xJacky/Nginx-UI/internal/nginx"
|
||||
"github.com/0xJacky/Nginx-UI/model"
|
||||
"github.com/0xJacky/Nginx-UI/query"
|
||||
|
|
|
@ -1,23 +1,25 @@
|
|||
package cert
|
||||
|
||||
import (
|
||||
"github.com/0xJacky/Nginx-UI/internal/logger"
|
||||
"github.com/0xJacky/Nginx-UI/model"
|
||||
"github.com/0xJacky/Nginx-UI/query"
|
||||
"github.com/0xJacky/Nginx-UI/settings"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/uozi-tech/cosy/logger"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// InitRegister init the default user for acme
|
||||
func InitRegister() {
|
||||
if settings.ServerSettings.Email == "" {
|
||||
email := settings.CertSettings.Email
|
||||
if settings.CertSettings.Email == "" {
|
||||
return
|
||||
}
|
||||
caDir := settings.CertSettings.GetCADir()
|
||||
u := query.AcmeUser
|
||||
|
||||
_, err := u.Where(u.Email.Eq(settings.ServerSettings.Email),
|
||||
u.CADir.Eq(settings.ServerSettings.GetCADir())).First()
|
||||
_, err := u.Where(u.Email.Eq(email),
|
||||
u.CADir.Eq(caDir)).First()
|
||||
|
||||
if err == nil {
|
||||
return
|
||||
|
@ -31,8 +33,8 @@ func InitRegister() {
|
|||
// Create a new user
|
||||
user := &model.AcmeUser{
|
||||
Name: "System Initial User",
|
||||
Email: settings.ServerSettings.Email,
|
||||
CADir: settings.ServerSettings.GetCADir(),
|
||||
Email: email,
|
||||
CADir: caDir,
|
||||
}
|
||||
|
||||
err = user.Register()
|
||||
|
@ -52,8 +54,8 @@ func InitRegister() {
|
|||
|
||||
func GetDefaultACMEUser() (user *model.AcmeUser, err error) {
|
||||
u := query.AcmeUser
|
||||
user, err = u.Where(u.Email.Eq(settings.ServerSettings.Email),
|
||||
u.CADir.Eq(settings.ServerSettings.GetCADir())).First()
|
||||
user, err = u.Where(u.Email.Eq(settings.CertSettings.Email),
|
||||
u.CADir.Eq(settings.CertSettings.GetCADir())).First()
|
||||
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, "get default user error")
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/0xJacky/Nginx-UI/internal/helper"
|
||||
"github.com/0xJacky/Nginx-UI/internal/logger"
|
||||
"github.com/uozi-tech/cosy/logger"
|
||||
"github.com/0xJacky/Nginx-UI/internal/nginx"
|
||||
"github.com/0xJacky/Nginx-UI/internal/notification"
|
||||
"github.com/0xJacky/Nginx-UI/internal/transport"
|
||||
|
|
|
@ -2,7 +2,7 @@ package chatbot
|
|||
|
||||
import (
|
||||
"github.com/0xJacky/Nginx-UI/internal/helper"
|
||||
"github.com/0xJacky/Nginx-UI/internal/logger"
|
||||
"github.com/uozi-tech/cosy/logger"
|
||||
"github.com/0xJacky/Nginx-UI/internal/nginx"
|
||||
"github.com/sashabaranov/go-openai"
|
||||
"os"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package cluster
|
||||
|
||||
import (
|
||||
"github.com/0xJacky/Nginx-UI/internal/logger"
|
||||
"github.com/uozi-tech/cosy/logger"
|
||||
"github.com/0xJacky/Nginx-UI/model"
|
||||
"github.com/0xJacky/Nginx-UI/query"
|
||||
"github.com/0xJacky/Nginx-UI/settings"
|
||||
|
|
|
@ -6,7 +6,6 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/0xJacky/Nginx-UI/internal/helper"
|
||||
"github.com/0xJacky/Nginx-UI/internal/logger"
|
||||
"github.com/0xJacky/Nginx-UI/internal/nginx"
|
||||
"github.com/0xJacky/Nginx-UI/internal/notification"
|
||||
"github.com/0xJacky/Nginx-UI/internal/transport"
|
||||
|
@ -14,6 +13,7 @@ import (
|
|||
"github.com/0xJacky/Nginx-UI/query"
|
||||
"github.com/0xJacky/Nginx-UI/settings"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/uozi-tech/cosy/logger"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
|
@ -205,7 +205,7 @@ func (p *RenameConfigPayload) rename(env *model.Environment) (err error) {
|
|||
|
||||
client := http.Client{
|
||||
Transport: &http.Transport{
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: settings.ServerSettings.InsecureSkipVerify},
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: settings.HTTPSettings.InsecureSkipVerify},
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
@ -1,117 +0,0 @@
|
|||
package cosy
|
||||
|
||||
import (
|
||||
"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()
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Ctx[T]) SetTable(table string, args ...interface{}) *Ctx[T] {
|
||||
c.table = table
|
||||
c.tableArgs = args
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Ctx[T]) SetItemKey(key string) *Ctx[T] {
|
||||
c.itemKey = key
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Ctx[T]) SetValidRules(rules gin.H) *Ctx[T] {
|
||||
c.rules = rules
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Ctx[T]) SetPreloads(args ...string) *Ctx[T] {
|
||||
c.preloads = append(c.preloads, args...)
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Ctx[T]) validate() (errs gin.H) {
|
||||
c.Payload = make(gin.H)
|
||||
|
||||
_ = c.ctx.ShouldBindJSON(&c.Payload)
|
||||
|
||||
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{})
|
||||
|
||||
for k, v := range c.Payload {
|
||||
if _, ok := c.rules[k]; ok {
|
||||
validated[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
c.Payload = validated
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (c *Ctx[T]) SetScan(scan func(tx *gorm.DB) any) *Ctx[T] {
|
||||
c.scan = scan
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Ctx[T]) SetTransformer(t func(m *T) any) *Ctx[T] {
|
||||
c.transformer = t
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Ctx[T]) AbortWithError(err error) {
|
||||
c.abort = true
|
||||
errHandler(c.ctx, err)
|
||||
}
|
||||
|
||||
func (c *Ctx[T]) Abort() {
|
||||
c.abort = true
|
||||
}
|
|
@ -1,81 +0,0 @@
|
|||
package cosy
|
||||
|
||||
import (
|
||||
"github.com/0xJacky/Nginx-UI/internal/cosy/map2struct"
|
||||
"github.com/0xJacky/Nginx-UI/model"
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm/clause"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func (c *Ctx[T]) Create() {
|
||||
|
||||
errs := c.validate()
|
||||
|
||||
if len(errs) > 0 {
|
||||
c.ctx.JSON(http.StatusNotAcceptable, gin.H{
|
||||
"message": "Requested with wrong parameters",
|
||||
"errors": errs,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
db := model.UseDB()
|
||||
|
||||
c.beforeDecodeHook()
|
||||
|
||||
if c.abort {
|
||||
return
|
||||
}
|
||||
|
||||
err := map2struct.WeakDecode(c.Payload, &c.Model)
|
||||
|
||||
if err != nil {
|
||||
errHandler(c.ctx, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.beforeExecuteHook()
|
||||
|
||||
if c.abort {
|
||||
return
|
||||
}
|
||||
|
||||
if c.skipAssociationsOnCreate {
|
||||
err = db.Omit(clause.Associations).Create(&c.Model).Error
|
||||
} else {
|
||||
err = db.Create(&c.Model).Error
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
errHandler(c.ctx, err)
|
||||
return
|
||||
}
|
||||
|
||||
if len(c.executedHookFunc) > 0 {
|
||||
for _, v := range c.executedHookFunc {
|
||||
v(c)
|
||||
|
||||
if c.abort {
|
||||
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 c.nextHandler != nil {
|
||||
(*c.nextHandler)(c.ctx)
|
||||
} else {
|
||||
c.ctx.JSON(http.StatusOK, c.Model)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Ctx[T]) WithAssociations() *Ctx[T] {
|
||||
c.skipAssociationsOnCreate = false
|
||||
return c
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
package cosy
|
||||
|
||||
import (
|
||||
"github.com/0xJacky/Nginx-UI/internal/cosy/map2struct"
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func (c *Ctx[T]) Custom(fx func(ctx *Ctx[T])) {
|
||||
if c.abort {
|
||||
return
|
||||
}
|
||||
errs := c.validate()
|
||||
|
||||
if len(errs) > 0 {
|
||||
c.ctx.JSON(http.StatusNotAcceptable, gin.H{
|
||||
"message": "Requested with wrong parameters",
|
||||
"errors": errs,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.beforeDecodeHook()
|
||||
|
||||
for k := range c.Payload {
|
||||
c.SelectedFields = append(c.SelectedFields, k)
|
||||
}
|
||||
|
||||
err := map2struct.WeakDecode(c.Payload, &c.Model)
|
||||
|
||||
if err != nil {
|
||||
errHandler(c.ctx, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.beforeExecuteHook()
|
||||
|
||||
fx(c)
|
||||
}
|
|
@ -1,113 +0,0 @@
|
|||
package cosy
|
||||
|
||||
import (
|
||||
"github.com/0xJacky/Nginx-UI/model"
|
||||
"github.com/spf13/cast"
|
||||
"gorm.io/gorm"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func (c *Ctx[T]) PermanentlyDelete() {
|
||||
c.permanentlyDelete = true
|
||||
c.Destroy()
|
||||
}
|
||||
|
||||
func (c *Ctx[T]) Destroy() {
|
||||
if c.abort {
|
||||
return
|
||||
}
|
||||
id := c.ctx.Param("id")
|
||||
|
||||
c.beforeExecuteHook()
|
||||
|
||||
db := model.UseDB()
|
||||
|
||||
result := db
|
||||
|
||||
if cast.ToBool(c.ctx.Query("permanent")) || c.permanentlyDelete {
|
||||
result = result.Unscoped()
|
||||
}
|
||||
|
||||
if len(c.gormScopes) > 0 {
|
||||
result = result.Scopes(c.gormScopes...)
|
||||
}
|
||||
|
||||
var err error
|
||||
session := result.Session(&gorm.Session{})
|
||||
if c.table != "" {
|
||||
err = session.Table(c.table, c.tableArgs...).Take(c.OriginModel, id).Error
|
||||
} else {
|
||||
err = session.First(&c.OriginModel, id).Error
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
errHandler(c.ctx, err)
|
||||
return
|
||||
}
|
||||
|
||||
err = result.Delete(&c.OriginModel).Error
|
||||
if err != nil {
|
||||
errHandler(c.ctx, err)
|
||||
return
|
||||
}
|
||||
|
||||
if len(c.executedHookFunc) > 0 {
|
||||
for _, v := range c.executedHookFunc {
|
||||
v(c)
|
||||
|
||||
if c.abort {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
c.ctx.JSON(http.StatusNoContent, nil)
|
||||
}
|
||||
|
||||
func (c *Ctx[T]) Recover() {
|
||||
if c.abort {
|
||||
return
|
||||
}
|
||||
id := c.ctx.Param("id")
|
||||
|
||||
c.beforeExecuteHook()
|
||||
|
||||
db := model.UseDB()
|
||||
var dbModel T
|
||||
|
||||
result := db.Unscoped()
|
||||
if len(c.gormScopes) > 0 {
|
||||
result = result.Scopes(c.gormScopes...)
|
||||
}
|
||||
|
||||
var err error
|
||||
session := result.Session(&gorm.Session{})
|
||||
if c.table != "" {
|
||||
err = session.Table(c.table).Take(&dbModel, id).Error
|
||||
} else {
|
||||
err = session.First(&dbModel, id).Error
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
errHandler(c.ctx, err)
|
||||
return
|
||||
}
|
||||
|
||||
err = result.Model(&dbModel).Update("deleted_at", nil).Error
|
||||
if err != nil {
|
||||
errHandler(c.ctx, err)
|
||||
return
|
||||
}
|
||||
|
||||
if len(c.executedHookFunc) > 0 {
|
||||
for _, v := range c.executedHookFunc {
|
||||
v(c)
|
||||
|
||||
if c.abort {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
c.ctx.JSON(http.StatusNoContent, nil)
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
package cosy
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/0xJacky/Nginx-UI/internal/logger"
|
||||
"github.com/gin-gonic/gin"
|
||||
"go.uber.org/zap"
|
||||
"gorm.io/gorm"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func errHandler(c *gin.Context, err error) {
|
||||
logger.GetLogger().WithOptions(zap.AddCallerSkip(1)).Errorln(err)
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
c.JSON(http.StatusNotFound, gin.H{
|
||||
"message": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"message": err.Error(),
|
||||
})
|
||||
}
|
|
@ -1,212 +0,0 @@
|
|||
package cosy
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/0xJacky/Nginx-UI/internal/logger"
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/clause"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func (c *Ctx[T]) SetFussy(keys ...string) *Ctx[T] {
|
||||
c.gormScopes = append(c.gormScopes, func(tx *gorm.DB) *gorm.DB {
|
||||
return QueryToFussySearch(c.ctx, tx, keys...)
|
||||
})
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Ctx[T]) SetFussyKeys(value string, keys ...string) *Ctx[T] {
|
||||
c.gormScopes = append(c.gormScopes, func(tx *gorm.DB) *gorm.DB {
|
||||
return QueryToFussyKeysSearch(c.ctx, tx, value, keys...)
|
||||
})
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Ctx[T]) SetEqual(keys ...string) *Ctx[T] {
|
||||
c.gormScopes = append(c.gormScopes, func(tx *gorm.DB) *gorm.DB {
|
||||
return QueryToEqualSearch(c.ctx, tx, keys...)
|
||||
})
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Ctx[T]) SetIn(keys ...string) *Ctx[T] {
|
||||
c.gormScopes = append(c.gormScopes, func(tx *gorm.DB) *gorm.DB {
|
||||
return QueryToInSearch(c.ctx, tx, keys...)
|
||||
})
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Ctx[T]) SetOrFussy(keys ...string) *Ctx[T] {
|
||||
c.gormScopes = append(c.gormScopes, func(tx *gorm.DB) *gorm.DB {
|
||||
return QueryToOrFussySearch(c.ctx, tx, keys...)
|
||||
})
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Ctx[T]) SetOrEqual(keys ...string) *Ctx[T] {
|
||||
c.gormScopes = append(c.gormScopes, func(tx *gorm.DB) *gorm.DB {
|
||||
return QueryToOrEqualSearch(c.ctx, tx, keys...)
|
||||
})
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Ctx[T]) SetOrIn(keys ...string) *Ctx[T] {
|
||||
c.gormScopes = append(c.gormScopes, func(tx *gorm.DB) *gorm.DB {
|
||||
return QueryToOrInSearch(c.ctx, tx, keys...)
|
||||
})
|
||||
return c
|
||||
}
|
||||
|
||||
func QueryToInSearch(c *gin.Context, db *gorm.DB, keys ...string) *gorm.DB {
|
||||
for _, v := range keys {
|
||||
queryArray := c.QueryArray(v + "[]")
|
||||
if len(queryArray) == 0 {
|
||||
queryArray = c.QueryArray(v)
|
||||
}
|
||||
if len(queryArray) == 1 && queryArray[0] == "" {
|
||||
continue
|
||||
}
|
||||
if len(queryArray) >= 1 {
|
||||
var builder strings.Builder
|
||||
stmt := db.Statement
|
||||
|
||||
stmt.QuoteTo(&builder, clause.Column{Table: stmt.Table, Name: v})
|
||||
builder.WriteString(" IN ?")
|
||||
|
||||
db = db.Where(builder.String(), queryArray)
|
||||
}
|
||||
}
|
||||
return db
|
||||
}
|
||||
|
||||
func QueryToEqualSearch(c *gin.Context, db *gorm.DB, keys ...string) *gorm.DB {
|
||||
for _, v := range keys {
|
||||
if c.Query(v) != "" {
|
||||
var sb strings.Builder
|
||||
|
||||
_, err := fmt.Fprintf(&sb, "`%s` = ?", v)
|
||||
if err != nil {
|
||||
logger.Error(err)
|
||||
continue
|
||||
}
|
||||
|
||||
db = db.Where(sb.String(), c.Query(v))
|
||||
}
|
||||
}
|
||||
return db
|
||||
}
|
||||
|
||||
func QueryToFussySearch(c *gin.Context, db *gorm.DB, keys ...string) *gorm.DB {
|
||||
for _, v := range keys {
|
||||
if c.Query(v) != "" {
|
||||
var sb strings.Builder
|
||||
|
||||
_, err := fmt.Fprintf(&sb, "`%s` LIKE ?", v)
|
||||
if err != nil {
|
||||
logger.Error(err)
|
||||
continue
|
||||
}
|
||||
|
||||
var sbValue strings.Builder
|
||||
|
||||
_, err = fmt.Fprintf(&sbValue, "%%%s%%", c.Query(v))
|
||||
|
||||
if err != nil {
|
||||
logger.Error(err)
|
||||
continue
|
||||
}
|
||||
|
||||
db = db.Where(sb.String(), sbValue.String())
|
||||
}
|
||||
}
|
||||
return db
|
||||
}
|
||||
|
||||
func QueryToFussyKeysSearch(c *gin.Context, db *gorm.DB, value string, keys ...string) *gorm.DB {
|
||||
if c.Query(value) == "" {
|
||||
return db
|
||||
}
|
||||
|
||||
var condition *gorm.DB
|
||||
for i, v := range keys {
|
||||
sb := v + " LIKE ?"
|
||||
sv := "%" + c.Query(value) + "%"
|
||||
|
||||
switch i {
|
||||
case 0:
|
||||
condition = db.Where(db.Where(sb, sv))
|
||||
default:
|
||||
condition = condition.Or(sb, sv)
|
||||
}
|
||||
}
|
||||
|
||||
return db.Where(condition)
|
||||
}
|
||||
|
||||
func QueryToOrInSearch(c *gin.Context, db *gorm.DB, keys ...string) *gorm.DB {
|
||||
for _, v := range keys {
|
||||
queryArray := c.QueryArray(v + "[]")
|
||||
if len(queryArray) == 0 {
|
||||
queryArray = c.QueryArray(v)
|
||||
}
|
||||
if len(queryArray) == 1 && queryArray[0] == "" {
|
||||
continue
|
||||
}
|
||||
if len(queryArray) >= 1 {
|
||||
var sb strings.Builder
|
||||
|
||||
_, err := fmt.Fprintf(&sb, "`%s` IN ?", v)
|
||||
if err != nil {
|
||||
logger.Error(err)
|
||||
continue
|
||||
}
|
||||
|
||||
db = db.Or(sb.String(), queryArray)
|
||||
}
|
||||
}
|
||||
return db
|
||||
}
|
||||
|
||||
func QueryToOrEqualSearch(c *gin.Context, db *gorm.DB, keys ...string) *gorm.DB {
|
||||
for _, v := range keys {
|
||||
if c.Query(v) != "" {
|
||||
var sb strings.Builder
|
||||
|
||||
_, err := fmt.Fprintf(&sb, "`%s` = ?", v)
|
||||
if err != nil {
|
||||
logger.Error(err)
|
||||
continue
|
||||
}
|
||||
|
||||
db = db.Or(sb.String(), c.Query(v))
|
||||
}
|
||||
}
|
||||
return db
|
||||
}
|
||||
|
||||
func QueryToOrFussySearch(c *gin.Context, db *gorm.DB, keys ...string) *gorm.DB {
|
||||
for _, v := range keys {
|
||||
if c.Query(v) != "" {
|
||||
var sb strings.Builder
|
||||
|
||||
_, err := fmt.Fprintf(&sb, "`%s` LIKE ?", v)
|
||||
if err != nil {
|
||||
logger.Error(err)
|
||||
continue
|
||||
}
|
||||
|
||||
var sbValue strings.Builder
|
||||
|
||||
_, err = fmt.Fprintf(&sbValue, "%%%s%%", c.Query(v))
|
||||
|
||||
if err != nil {
|
||||
logger.Error(err)
|
||||
continue
|
||||
}
|
||||
|
||||
db = db.Or(sb.String(), sbValue.String())
|
||||
}
|
||||
}
|
||||
return db
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
package cosy
|
||||
|
||||
import "gorm.io/gorm"
|
||||
|
||||
func (c *Ctx[T]) GormScope(hook func(tx *gorm.DB) *gorm.DB) *Ctx[T] {
|
||||
c.gormScopes = append(c.gormScopes, hook)
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Ctx[T]) beforeExecuteHook() {
|
||||
if len(c.beforeExecuteHookFunc) > 0 {
|
||||
for _, v := range c.beforeExecuteHookFunc {
|
||||
v(c)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Ctx[T]) beforeDecodeHook() {
|
||||
if len(c.beforeDecodeHookFunc) > 0 {
|
||||
for _, v := range c.beforeDecodeHookFunc {
|
||||
v(c)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Ctx[T]) BeforeDecodeHook(hook ...func(ctx *Ctx[T])) *Ctx[T] {
|
||||
c.beforeDecodeHookFunc = append(c.beforeDecodeHookFunc, hook...)
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Ctx[T]) BeforeExecuteHook(hook ...func(ctx *Ctx[T])) *Ctx[T] {
|
||||
c.beforeExecuteHookFunc = append(c.beforeExecuteHookFunc, hook...)
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Ctx[T]) ExecutedHook(hook ...func(ctx *Ctx[T])) *Ctx[T] {
|
||||
c.executedHookFunc = append(c.executedHookFunc, hook...)
|
||||
return c
|
||||
}
|
|
@ -1,172 +0,0 @@
|
|||
package cosy
|
||||
|
||||
import (
|
||||
"github.com/0xJacky/Nginx-UI/internal/logger"
|
||||
"github.com/0xJacky/Nginx-UI/model"
|
||||
"github.com/0xJacky/Nginx-UI/settings"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/spf13/cast"
|
||||
"gorm.io/gorm"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func GetPagingParams(c *gin.Context) (page, offset, pageSize int) {
|
||||
page = cast.ToInt(c.Query("page"))
|
||||
if page == 0 {
|
||||
page = 1
|
||||
}
|
||||
pageSize = settings.ServerSettings.PageSize
|
||||
reqPageSize := c.Query("page_size")
|
||||
if reqPageSize != "" {
|
||||
pageSize = cast.ToInt(reqPageSize)
|
||||
}
|
||||
offset = (page - 1) * pageSize
|
||||
return
|
||||
}
|
||||
|
||||
func (c *Ctx[T]) combineStdSelectorRequest() {
|
||||
StdSelectorInitID := c.ctx.QueryArray("id[]")
|
||||
|
||||
if len(StdSelectorInitID) > 0 {
|
||||
c.GormScope(func(tx *gorm.DB) *gorm.DB {
|
||||
return tx.Where(c.itemKey+" IN ?", StdSelectorInitID)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Ctx[T]) result() (*gorm.DB, bool) {
|
||||
for _, v := range c.preloads {
|
||||
t := v
|
||||
c.GormScope(func(tx *gorm.DB) *gorm.DB {
|
||||
tx = tx.Preload(t)
|
||||
return tx
|
||||
})
|
||||
}
|
||||
|
||||
c.beforeExecuteHook()
|
||||
|
||||
var dbModel T
|
||||
result := model.UseDB()
|
||||
|
||||
if cast.ToBool(c.ctx.Query("trash")) {
|
||||
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(tableName + ".deleted_at IS NOT NULL")
|
||||
}
|
||||
|
||||
result = result.Model(&dbModel)
|
||||
if c.table != "" {
|
||||
result = result.Table(c.table, c.tableArgs...)
|
||||
}
|
||||
|
||||
c.combineStdSelectorRequest()
|
||||
|
||||
if len(c.gormScopes) > 0 {
|
||||
result = result.Scopes(c.gormScopes...)
|
||||
}
|
||||
|
||||
return result, true
|
||||
}
|
||||
|
||||
func (c *Ctx[T]) ListAllData() (data any, ok bool) {
|
||||
result, ok := c.result()
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
result = result.Scopes(c.SortOrder())
|
||||
if c.scan == nil {
|
||||
models := make([]*T, 0)
|
||||
result.Find(&models)
|
||||
|
||||
if c.transformer != nil {
|
||||
transformed := make([]any, 0)
|
||||
for k := range models {
|
||||
transformed = append(transformed, c.transformer(models[k]))
|
||||
}
|
||||
data = transformed
|
||||
} else {
|
||||
data = models
|
||||
}
|
||||
} else {
|
||||
data = c.scan(result)
|
||||
}
|
||||
return data, true
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
func (c *Ctx[T]) PagingList() {
|
||||
data, ok := c.PagingListData()
|
||||
if ok {
|
||||
c.ctx.JSON(http.StatusOK, data)
|
||||
}
|
||||
}
|
||||
|
||||
// EmptyPagingList return empty list
|
||||
func (c *Ctx[T]) EmptyPagingList() {
|
||||
pageSize := settings.ServerSettings.PageSize
|
||||
if reqPageSize := c.ctx.Query("page_size"); reqPageSize != "" {
|
||||
pageSize = cast.ToInt(reqPageSize)
|
||||
}
|
||||
|
||||
data := &model.DataList{Data: make([]any, 0)}
|
||||
data.Pagination.PerPage = pageSize
|
||||
c.ctx.JSON(http.StatusOK, data)
|
||||
}
|
|
@ -1,96 +0,0 @@
|
|||
package map2struct
|
||||
|
||||
import (
|
||||
"github.com/mitchellh/mapstructure"
|
||||
"github.com/shopspring/decimal"
|
||||
"github.com/spf13/cast"
|
||||
"gopkg.in/guregu/null.v4"
|
||||
"reflect"
|
||||
"time"
|
||||
)
|
||||
|
||||
var timeLocation *time.Location
|
||||
|
||||
func init() {
|
||||
timeLocation, _ = time.LoadLocation("Asia/Shanghai")
|
||||
}
|
||||
|
||||
func ToTimeHookFunc() 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:
|
||||
return cast.ToTimeInDefaultLocationE(data, timeLocation)
|
||||
case reflect.Float64:
|
||||
return time.Unix(0, int64(data.(float64))*int64(time.Millisecond)), nil
|
||||
case reflect.Int64:
|
||||
return time.Unix(0, data.(int64)*int64(time.Millisecond)), nil
|
||||
default:
|
||||
return data, nil
|
||||
}
|
||||
// Convert it by parsing
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
if t == reflect.TypeOf(decimal.Decimal{}) {
|
||||
if f.Kind() == reflect.Float64 {
|
||||
return decimal.NewFromFloat(data.(float64)), nil
|
||||
}
|
||||
|
||||
if input := data.(string); input != "" {
|
||||
return decimal.NewFromString(data.(string))
|
||||
}
|
||||
return decimal.Decimal{}, nil
|
||||
}
|
||||
|
||||
return data, nil
|
||||
}
|
||||
}
|
||||
|
||||
func ToNullableStringHookFunc() mapstructure.DecodeHookFunc {
|
||||
return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
|
||||
if t == reflect.TypeOf(null.String{}) {
|
||||
return null.StringFrom(data.(string)), nil
|
||||
}
|
||||
|
||||
return data, nil
|
||||
}
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
package map2struct
|
||||
|
||||
import (
|
||||
"github.com/mitchellh/mapstructure"
|
||||
)
|
||||
|
||||
func WeakDecode(input, output interface{}) error {
|
||||
config := &mapstructure.DecoderConfig{
|
||||
Metadata: nil,
|
||||
Result: output,
|
||||
WeaklyTypedInput: true,
|
||||
DecodeHook: mapstructure.ComposeDecodeHookFunc(
|
||||
ToDecimalHookFunc(), ToTimeHookFunc(), ToNullableStringHookFunc(),
|
||||
ToTimePtrHookFunc(),
|
||||
),
|
||||
TagName: "json",
|
||||
}
|
||||
|
||||
decoder, err := mapstructure.NewDecoder(config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return decoder.Decode(input)
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
package cosy
|
||||
|
||||
import (
|
||||
"github.com/0xJacky/Nginx-UI/api"
|
||||
"github.com/0xJacky/Nginx-UI/model"
|
||||
"gorm.io/gorm"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func (c *Ctx[T]) UpdateOrder() {
|
||||
var json struct {
|
||||
TargetID int `json:"target_id"`
|
||||
Direction int `json:"direction" binding:"oneof=-1 1"`
|
||||
AffectedIDs []int `json:"affected_ids"`
|
||||
}
|
||||
|
||||
if !api.BindAndValid(c.ctx, &json) {
|
||||
return
|
||||
}
|
||||
|
||||
affectedLen := len(json.AffectedIDs)
|
||||
|
||||
db := model.UseDB()
|
||||
|
||||
if c.table != "" {
|
||||
db = db.Table(c.table, c.tableArgs...)
|
||||
}
|
||||
|
||||
// update target
|
||||
err := db.Model(&c.Model).Where("id = ?", json.TargetID).Update("order_id", gorm.Expr("order_id + ?", affectedLen*(-json.Direction))).Error
|
||||
|
||||
if err != nil {
|
||||
api.ErrHandler(c.ctx, err)
|
||||
return
|
||||
}
|
||||
|
||||
// update affected
|
||||
err = db.Model(&c.Model).Where("id in ?", json.AffectedIDs).Update("order_id", gorm.Expr("order_id + ?", json.Direction)).Error
|
||||
|
||||
if err != nil {
|
||||
api.ErrHandler(c.ctx, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.ctx.JSON(http.StatusOK, json)
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
package cosy
|
||||
|
||||
import (
|
||||
"github.com/0xJacky/Nginx-UI/internal/logger"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/schema"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
func (c *Ctx[T]) SortOrder() func(db *gorm.DB) *gorm.DB {
|
||||
return func(db *gorm.DB) *gorm.DB {
|
||||
order := c.ctx.DefaultQuery("order", "desc")
|
||||
if order != "desc" && order != "asc" {
|
||||
order = "desc"
|
||||
}
|
||||
|
||||
sortBy := c.ctx.DefaultQuery("sort_by", c.itemKey)
|
||||
|
||||
s, _ := schema.Parse(c.Model, &sync.Map{}, schema.NamingStrategy{})
|
||||
if _, ok := s.FieldsByDBName[sortBy]; !ok && sortBy != c.itemKey {
|
||||
logger.Error("invalid order field:", sortBy)
|
||||
return db
|
||||
}
|
||||
|
||||
var sb strings.Builder
|
||||
sb.WriteString(sortBy)
|
||||
sb.WriteString(" ")
|
||||
sb.WriteString(order)
|
||||
|
||||
return db.Order(sb.String())
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Ctx[T]) OrderAndPaginate() func(db *gorm.DB) *gorm.DB {
|
||||
return func(db *gorm.DB) *gorm.DB {
|
||||
db = c.SortOrder()(db)
|
||||
_, offset, pageSize := GetPagingParams(c.ctx)
|
||||
return db.Offset(offset).Limit(pageSize)
|
||||
}
|
||||
}
|
|
@ -1,101 +0,0 @@
|
|||
package cosy
|
||||
|
||||
import (
|
||||
"github.com/0xJacky/Nginx-UI/internal/cosy/map2struct"
|
||||
"github.com/0xJacky/Nginx-UI/model"
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/clause"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func (c *Ctx[T]) SetNextHandler(handler gin.HandlerFunc) *Ctx[T] {
|
||||
c.nextHandler = &handler
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Ctx[T]) Modify() {
|
||||
if c.abort {
|
||||
return
|
||||
}
|
||||
id := c.ctx.Param("id")
|
||||
errs := c.validate()
|
||||
|
||||
if len(errs) > 0 {
|
||||
c.ctx.JSON(http.StatusNotAcceptable, gin.H{
|
||||
"message": "Requested with wrong parameters",
|
||||
"errors": errs,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
db := model.UseDB()
|
||||
|
||||
result := db
|
||||
if len(c.gormScopes) > 0 {
|
||||
result = result.Scopes(c.gormScopes...)
|
||||
}
|
||||
|
||||
err := result.Session(&gorm.Session{}).First(&c.OriginModel, id).Error
|
||||
|
||||
if err != nil {
|
||||
c.AbortWithError(err)
|
||||
return
|
||||
}
|
||||
|
||||
c.beforeDecodeHook()
|
||||
if c.abort {
|
||||
return
|
||||
}
|
||||
|
||||
var selectedFields []string
|
||||
|
||||
for k := range c.Payload {
|
||||
selectedFields = append(selectedFields, k)
|
||||
}
|
||||
|
||||
err = map2struct.WeakDecode(c.Payload, &c.Model)
|
||||
|
||||
if err != nil {
|
||||
errHandler(c.ctx, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.beforeExecuteHook()
|
||||
if c.abort {
|
||||
return
|
||||
}
|
||||
|
||||
if c.table != "" {
|
||||
db = db.Table(c.table, c.tableArgs...)
|
||||
}
|
||||
err = db.Model(&c.OriginModel).Select(selectedFields).Updates(&c.Model).Error
|
||||
|
||||
if err != nil {
|
||||
c.AbortWithError(err)
|
||||
return
|
||||
}
|
||||
|
||||
err = db.Preload(clause.Associations).First(&c.Model, id).Error
|
||||
|
||||
if err != nil {
|
||||
c.AbortWithError(err)
|
||||
return
|
||||
}
|
||||
|
||||
if len(c.executedHookFunc) > 0 {
|
||||
for _, v := range c.executedHookFunc {
|
||||
v(c)
|
||||
|
||||
if c.abort {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if c.nextHandler != nil {
|
||||
(*c.nextHandler)(c.ctx)
|
||||
} else {
|
||||
c.ctx.JSON(http.StatusOK, c.Model)
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@ package cron
|
|||
|
||||
import (
|
||||
"github.com/0xJacky/Nginx-UI/internal/cert"
|
||||
"github.com/0xJacky/Nginx-UI/internal/logger"
|
||||
"github.com/uozi-tech/cosy/logger"
|
||||
"github.com/0xJacky/Nginx-UI/internal/logrotate"
|
||||
"github.com/0xJacky/Nginx-UI/query"
|
||||
"github.com/0xJacky/Nginx-UI/settings"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package helper
|
||||
|
||||
import (
|
||||
"github.com/0xJacky/Nginx-UI/internal/logger"
|
||||
"github.com/uozi-tech/cosy/logger"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
|
|
@ -3,7 +3,7 @@ package helper
|
|||
import (
|
||||
"crypto/sha512"
|
||||
"fmt"
|
||||
"github.com/0xJacky/Nginx-UI/internal/logger"
|
||||
"github.com/uozi-tech/cosy/logger"
|
||||
"io"
|
||||
"os"
|
||||
)
|
||||
|
|
|
@ -8,14 +8,18 @@ import (
|
|||
"github.com/0xJacky/Nginx-UI/internal/cert"
|
||||
"github.com/0xJacky/Nginx-UI/internal/cluster"
|
||||
"github.com/0xJacky/Nginx-UI/internal/cron"
|
||||
"github.com/0xJacky/Nginx-UI/internal/logger"
|
||||
"github.com/0xJacky/Nginx-UI/internal/passkey"
|
||||
"github.com/0xJacky/Nginx-UI/internal/validation"
|
||||
"github.com/0xJacky/Nginx-UI/model"
|
||||
"github.com/0xJacky/Nginx-UI/query"
|
||||
"github.com/0xJacky/Nginx-UI/settings"
|
||||
"github.com/google/uuid"
|
||||
"github.com/uozi-tech/cosy"
|
||||
sqlite "github.com/uozi-tech/cosy-driver-sqlite"
|
||||
"github.com/uozi-tech/cosy/logger"
|
||||
cSettings "github.com/uozi-tech/cosy/settings"
|
||||
"mime"
|
||||
"path"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
|
@ -23,6 +27,7 @@ func Boot() {
|
|||
defer recovery()
|
||||
|
||||
async := []func(){
|
||||
settings.Init,
|
||||
InitJsExtensionType,
|
||||
InitDatabase,
|
||||
InitNodeSecret,
|
||||
|
@ -70,12 +75,13 @@ func recovery() {
|
|||
|
||||
func InitDatabase() {
|
||||
// Skip install
|
||||
if settings.ServerSettings.SkipInstallation {
|
||||
if settings.NodeSettings.SkipInstallation {
|
||||
skipInstall()
|
||||
}
|
||||
|
||||
if "" != settings.ServerSettings.JwtSecret {
|
||||
db := model.Init()
|
||||
if "" != cSettings.AppSettings.JwtSecret {
|
||||
db := cosy.InitDB(sqlite.Open(path.Dir(cSettings.ConfPath), cSettings.DataBaseSettings))
|
||||
model.Use(db)
|
||||
query.Init(db)
|
||||
|
||||
InitAfterDatabase()
|
||||
|
@ -83,21 +89,22 @@ func InitDatabase() {
|
|||
}
|
||||
|
||||
func InitNodeSecret() {
|
||||
if "" == settings.ServerSettings.NodeSecret {
|
||||
logger.Warn("NodeSecret is empty, generating...")
|
||||
settings.ServerSettings.NodeSecret = uuid.New().String()
|
||||
if "" == settings.NodeSettings.Secret {
|
||||
logger.Info("Secret is empty, generating...")
|
||||
uuidStr := uuid.New().String()
|
||||
settings.NodeSettings.Secret = uuidStr
|
||||
|
||||
err := settings.Save()
|
||||
if err != nil {
|
||||
logger.Error("Error save settings", err)
|
||||
}
|
||||
logger.Warn("Generated NodeSecret: ", settings.ServerSettings.NodeSecret)
|
||||
logger.Info("Generated Secret: ", uuidStr)
|
||||
}
|
||||
}
|
||||
|
||||
func InitCryptoSecret() {
|
||||
if "" == settings.CryptoSettings.Secret {
|
||||
logger.Warn("Secret is empty, generating...")
|
||||
logger.Info("Secret is empty, generating...")
|
||||
|
||||
key := make([]byte, 32)
|
||||
if _, err := rand.Read(key); err != nil {
|
||||
|
@ -111,7 +118,7 @@ func InitCryptoSecret() {
|
|||
if err != nil {
|
||||
logger.Error("Error save settings", err)
|
||||
}
|
||||
logger.Warn("Secret Generated")
|
||||
logger.Info("Secret Generated")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package kernal
|
||||
|
||||
import (
|
||||
"github.com/0xJacky/Nginx-UI/internal/logger"
|
||||
"github.com/uozi-tech/cosy/logger"
|
||||
"github.com/0xJacky/Nginx-UI/query"
|
||||
)
|
||||
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
package kernal
|
||||
|
||||
import (
|
||||
"github.com/0xJacky/Nginx-UI/internal/logger"
|
||||
"github.com/0xJacky/Nginx-UI/model"
|
||||
"github.com/0xJacky/Nginx-UI/query"
|
||||
"github.com/0xJacky/Nginx-UI/settings"
|
||||
"github.com/caarlos0/env/v11"
|
||||
"github.com/google/uuid"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/uozi-tech/cosy/logger"
|
||||
cSettings "github.com/uozi-tech/cosy/settings"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
@ -20,13 +21,13 @@ type predefinedUser struct {
|
|||
func skipInstall() {
|
||||
logger.Info("Skip installation mode enabled")
|
||||
|
||||
if settings.ServerSettings.JwtSecret == "" {
|
||||
settings.ServerSettings.JwtSecret = uuid.New().String()
|
||||
if cSettings.AppSettings.JwtSecret == "" {
|
||||
cSettings.AppSettings.JwtSecret = uuid.New().String()
|
||||
}
|
||||
|
||||
if settings.ServerSettings.NodeSecret == "" {
|
||||
settings.ServerSettings.NodeSecret = uuid.New().String()
|
||||
logger.Infof("NodeSecret: %s", settings.ServerSettings.NodeSecret)
|
||||
if settings.NodeSettings.Secret == "" {
|
||||
settings.NodeSettings.Secret = uuid.New().String()
|
||||
logger.Infof("Secret: %s", settings.NodeSettings.Secret)
|
||||
}
|
||||
|
||||
err := settings.Save()
|
||||
|
@ -37,7 +38,7 @@ func skipInstall() {
|
|||
|
||||
func registerPredefinedUser() {
|
||||
// when skip installation mode is enabled, the predefined user will be created
|
||||
if !settings.ServerSettings.SkipInstallation {
|
||||
if !settings.NodeSettings.SkipInstallation {
|
||||
return
|
||||
}
|
||||
pUser := &predefinedUser{}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package logrotate
|
||||
|
||||
import (
|
||||
"github.com/0xJacky/Nginx-UI/internal/logger"
|
||||
"github.com/uozi-tech/cosy/logger"
|
||||
"github.com/0xJacky/Nginx-UI/settings"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
|
|
@ -3,36 +3,17 @@ package middleware
|
|||
import (
|
||||
"encoding/base64"
|
||||
"github.com/0xJacky/Nginx-UI/app"
|
||||
"github.com/0xJacky/Nginx-UI/internal/logger"
|
||||
"github.com/0xJacky/Nginx-UI/internal/user"
|
||||
"github.com/0xJacky/Nginx-UI/settings"
|
||||
"github.com/gin-contrib/static"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/uozi-tech/cosy/logger"
|
||||
"io/fs"
|
||||
"net/http"
|
||||
"path"
|
||||
"runtime"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func Recovery() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
buf := make([]byte, 1024)
|
||||
runtime.Stack(buf, false)
|
||||
logger.Errorf("%s\n%s", err, buf)
|
||||
|
||||
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{
|
||||
"message": err.(error).Error(),
|
||||
})
|
||||
}
|
||||
}()
|
||||
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
||||
func AuthRequired() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
abortWithAuthFailure := func() {
|
||||
|
@ -43,8 +24,8 @@ func AuthRequired() gin.HandlerFunc {
|
|||
|
||||
token := c.GetHeader("Authorization")
|
||||
if token == "" {
|
||||
if token = c.GetHeader("X-Node-Secret"); token != "" && token == settings.ServerSettings.NodeSecret {
|
||||
c.Set("NodeSecret", token)
|
||||
if token = c.GetHeader("X-Node-Secret"); token != "" && token == settings.NodeSettings.Secret {
|
||||
c.Set("Secret", token)
|
||||
c.Next()
|
||||
return
|
||||
} else {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package middleware
|
||||
|
||||
import (
|
||||
"github.com/0xJacky/Nginx-UI/internal/logger"
|
||||
"github.com/uozi-tech/cosy/logger"
|
||||
"github.com/0xJacky/Nginx-UI/internal/transport"
|
||||
"github.com/0xJacky/Nginx-UI/query"
|
||||
"github.com/gin-gonic/gin"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package middleware
|
||||
|
||||
import (
|
||||
"github.com/0xJacky/Nginx-UI/internal/logger"
|
||||
"github.com/uozi-tech/cosy/logger"
|
||||
"github.com/0xJacky/Nginx-UI/query"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/pretty66/websocketproxy"
|
||||
|
|
|
@ -2,7 +2,7 @@ package nginx
|
|||
|
||||
import (
|
||||
"github.com/0xJacky/Nginx-UI/internal/helper"
|
||||
"github.com/0xJacky/Nginx-UI/internal/logger"
|
||||
"github.com/uozi-tech/cosy/logger"
|
||||
"github.com/0xJacky/Nginx-UI/settings"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package passkey
|
||||
|
||||
import (
|
||||
"github.com/0xJacky/Nginx-UI/internal/logger"
|
||||
"github.com/uozi-tech/cosy/logger"
|
||||
"github.com/0xJacky/Nginx-UI/settings"
|
||||
"github.com/go-webauthn/webauthn/protocol"
|
||||
"github.com/go-webauthn/webauthn/webauthn"
|
||||
|
@ -10,7 +10,7 @@ import (
|
|||
var instance *webauthn.WebAuthn
|
||||
|
||||
func Init() {
|
||||
options := &settings.WebAuthnSettings
|
||||
options := settings.WebAuthnSettings
|
||||
|
||||
if !Enabled() {
|
||||
logger.Debug("WebAuthn settings are not configured")
|
||||
|
@ -34,7 +34,7 @@ func Init() {
|
|||
}
|
||||
|
||||
func Enabled() bool {
|
||||
options := &settings.WebAuthnSettings
|
||||
options := settings.WebAuthnSettings
|
||||
if options.RPDisplayName == "" || options.RPID == "" || len(options.RPOrigins) == 0 {
|
||||
return false
|
||||
}
|
||||
|
|
|
@ -2,11 +2,11 @@ package pty
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/0xJacky/Nginx-UI/internal/logger"
|
||||
"github.com/0xJacky/Nginx-UI/settings"
|
||||
"github.com/creack/pty"
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/uozi-tech/cosy/logger"
|
||||
"os"
|
||||
"os/exec"
|
||||
"time"
|
||||
|
@ -27,7 +27,7 @@ type Message struct {
|
|||
const bufferSize = 2048
|
||||
|
||||
func NewPipeLine(conn *websocket.Conn) (p *Pipeline, err error) {
|
||||
c := exec.Command(settings.ServerSettings.StartCmd)
|
||||
c := exec.Command(settings.TerminalSettings.StartCmd)
|
||||
|
||||
ptmx, err := pty.StartWithSize(c, &pty.Winsize{Cols: 90, Rows: 60})
|
||||
if err != nil {
|
||||
|
|
|
@ -3,7 +3,6 @@ package template
|
|||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"github.com/0xJacky/Nginx-UI/internal/logger"
|
||||
"github.com/0xJacky/Nginx-UI/internal/nginx"
|
||||
"github.com/0xJacky/Nginx-UI/settings"
|
||||
templ "github.com/0xJacky/Nginx-UI/template"
|
||||
|
@ -11,6 +10,8 @@ import (
|
|||
"github.com/gin-gonic/gin"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/tufanbarisyildirim/gonginx/parser"
|
||||
"github.com/uozi-tech/cosy/logger"
|
||||
cSettings "github.com/uozi-tech/cosy/settings"
|
||||
"io"
|
||||
"io/fs"
|
||||
"path/filepath"
|
||||
|
@ -115,8 +116,8 @@ func ParseTemplate(path, name string, bindData map[string]Variable) (c ConfigDet
|
|||
}
|
||||
|
||||
data := gin.H{
|
||||
"HTTPPORT": settings.ServerSettings.HttpPort,
|
||||
"HTTP01PORT": settings.ServerSettings.HTTPChallengePort,
|
||||
"HTTPPORT": cSettings.ServerSettings.Port,
|
||||
"HTTP01PORT": settings.CertSettings.HTTPChallengePort,
|
||||
}
|
||||
|
||||
for k, v := range bindData {
|
||||
|
|
|
@ -11,7 +11,7 @@ import (
|
|||
func NewTransport(options ...func(transport *http.Transport) error) (t *http.Transport, err error) {
|
||||
t = &http.Transport{
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: settings.ServerSettings.InsecureSkipVerify},
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: settings.HTTPSettings.InsecureSkipVerify},
|
||||
}
|
||||
|
||||
for _, option := range options {
|
||||
|
|
|
@ -5,11 +5,11 @@ import (
|
|||
"fmt"
|
||||
_github "github.com/0xJacky/Nginx-UI/.github"
|
||||
"github.com/0xJacky/Nginx-UI/internal/helper"
|
||||
"github.com/0xJacky/Nginx-UI/internal/logger"
|
||||
"github.com/0xJacky/Nginx-UI/settings"
|
||||
"github.com/jpillora/overseer"
|
||||
"github.com/minio/selfupdate"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/uozi-tech/cosy/logger"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
@ -138,8 +138,9 @@ func (u *Upgrader) DownloadLatestRelease(progressChan chan float64) (tarName str
|
|||
return
|
||||
}
|
||||
|
||||
if settings.ServerSettings.GithubProxy != "" {
|
||||
digest.BrowserDownloadUrl, err = url.JoinPath(settings.ServerSettings.GithubProxy, digest.BrowserDownloadUrl)
|
||||
githubProxy := settings.HTTPSettings.GithubProxy
|
||||
if githubProxy != "" {
|
||||
digest.BrowserDownloadUrl, err = url.JoinPath(githubProxy, digest.BrowserDownloadUrl)
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, "service.DownloadLatestRelease url.JoinPath error")
|
||||
return
|
||||
|
@ -156,8 +157,8 @@ func (u *Upgrader) DownloadLatestRelease(progressChan chan float64) (tarName str
|
|||
|
||||
dir := filepath.Dir(u.ExPath)
|
||||
|
||||
if settings.ServerSettings.GithubProxy != "" {
|
||||
downloadUrl, err = url.JoinPath(settings.ServerSettings.GithubProxy, downloadUrl)
|
||||
if githubProxy != "" {
|
||||
downloadUrl, err = url.JoinPath(githubProxy, downloadUrl)
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, "service.DownloadLatestRelease url.JoinPath error")
|
||||
return
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
package user
|
||||
|
||||
import (
|
||||
"github.com/0xJacky/Nginx-UI/internal/logger"
|
||||
"github.com/0xJacky/Nginx-UI/model"
|
||||
"github.com/0xJacky/Nginx-UI/query"
|
||||
"github.com/0xJacky/Nginx-UI/settings"
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/uozi-tech/cosy/logger"
|
||||
cSettings "github.com/uozi-tech/cosy/settings"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
@ -68,7 +68,7 @@ func GenerateJWT(user *model.User) (string, error) {
|
|||
}
|
||||
|
||||
unsignedToken := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||
signedToken, err := unsignedToken.SignedString([]byte(settings.ServerSettings.JwtSecret))
|
||||
signedToken, err := unsignedToken.SignedString([]byte(cSettings.AppSettings.JwtSecret))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -96,7 +96,7 @@ func ValidateJWT(token string) (claims *JWTClaims, err error) {
|
|||
token,
|
||||
&JWTClaims{},
|
||||
func(token *jwt.Token) (interface{}, error) {
|
||||
return []byte(settings.ServerSettings.JwtSecret), nil
|
||||
return []byte(cSettings.AppSettings.JwtSecret), nil
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package validation
|
||||
|
||||
import (
|
||||
"github.com/0xJacky/Nginx-UI/internal/logger"
|
||||
"github.com/uozi-tech/cosy/logger"
|
||||
"github.com/gin-gonic/gin/binding"
|
||||
val "github.com/go-playground/validator/v10"
|
||||
)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue