mirror of
https://github.com/0xJacky/nginx-ui.git
synced 2025-05-11 10:25:52 +02:00
refactor: project directory structure
This commit is contained in:
parent
c1193a5b8c
commit
e5a5889931
367 changed files with 710 additions and 756 deletions
81
model/auth.go
Normal file
81
model/auth.go
Normal file
|
@ -0,0 +1,81 @@
|
|||
package model
|
||||
|
||||
import (
|
||||
"github.com/0xJacky/Nginx-UI/settings"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/golang-jwt/jwt"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Auth struct {
|
||||
Model
|
||||
|
||||
Name string `json:"name"`
|
||||
Password string `json:"-"`
|
||||
}
|
||||
|
||||
type AuthToken struct {
|
||||
Token string `json:"token"`
|
||||
}
|
||||
|
||||
type JWTClaims struct {
|
||||
Name string `json:"name"`
|
||||
jwt.StandardClaims
|
||||
}
|
||||
|
||||
func GetUser(name string) (user Auth, err error) {
|
||||
err = db.Where("name = ?", name).First(&user).Error
|
||||
if err != nil {
|
||||
return Auth{}, err
|
||||
}
|
||||
return user, err
|
||||
}
|
||||
|
||||
func GetUserList(c *gin.Context, username interface{}) (data DataList) {
|
||||
var total int64
|
||||
db.Model(&Auth{}).Count(&total)
|
||||
var users []Auth
|
||||
|
||||
result := db.Model(&Auth{}).Scopes(orderAndPaginate(c))
|
||||
|
||||
if username != "" {
|
||||
result = result.Where("name LIKE ?", "%"+username.(string)+"%")
|
||||
}
|
||||
|
||||
result.Find(&users)
|
||||
|
||||
data = GetListWithPagination(&users, c, total)
|
||||
return
|
||||
}
|
||||
|
||||
func DeleteToken(token string) error {
|
||||
return db.Where("token = ?", token).Delete(&AuthToken{}).Error
|
||||
}
|
||||
|
||||
func CheckToken(token string) int64 {
|
||||
return db.Where("token = ?", token).Find(&AuthToken{}).RowsAffected
|
||||
}
|
||||
|
||||
func GenerateJWT(name string) (string, error) {
|
||||
claims := JWTClaims{
|
||||
Name: name,
|
||||
StandardClaims: jwt.StandardClaims{
|
||||
ExpiresAt: time.Now().Add(24 * time.Hour).Unix(),
|
||||
},
|
||||
}
|
||||
unsignedToken := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||
signedToken, err := unsignedToken.SignedString([]byte(settings.ServerSettings.JwtSecret))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
err = db.Create(&AuthToken{
|
||||
Token: signedToken,
|
||||
}).Error
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return signedToken, err
|
||||
}
|
107
model/cert.go
Normal file
107
model/cert.go
Normal file
|
@ -0,0 +1,107 @@
|
|||
package model
|
||||
|
||||
import (
|
||||
"github.com/0xJacky/Nginx-UI/internal/nginx"
|
||||
"github.com/lib/pq"
|
||||
"os"
|
||||
)
|
||||
|
||||
const (
|
||||
AutoCertEnabled = 1
|
||||
AutoCertDisabled = -1
|
||||
)
|
||||
|
||||
type CertDomains []string
|
||||
|
||||
type Cert struct {
|
||||
Model
|
||||
Name string `json:"name"`
|
||||
Domains pq.StringArray `json:"domains" gorm:"type:text[]"`
|
||||
Filename string `json:"filename"`
|
||||
SSLCertificatePath string `json:"ssl_certificate_path"`
|
||||
SSLCertificateKeyPath string `json:"ssl_certificate_key_path"`
|
||||
AutoCert int `json:"auto_cert"`
|
||||
ChallengeMethod string `json:"challenge_method"`
|
||||
DnsCredentialID int `json:"dns_credential_id"`
|
||||
DnsCredential *DnsCredential `json:"dns_credential,omitempty"`
|
||||
Log string `json:"log"`
|
||||
}
|
||||
|
||||
func FirstCert(confName string) (c Cert, err error) {
|
||||
err = db.First(&c, &Cert{
|
||||
Filename: confName,
|
||||
}).Error
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func FirstOrCreateCert(confName string) (c Cert, err error) {
|
||||
err = db.FirstOrCreate(&c, &Cert{Filename: confName}).Error
|
||||
return
|
||||
}
|
||||
|
||||
func (c *Cert) Insert() error {
|
||||
return db.Create(c).Error
|
||||
}
|
||||
|
||||
func GetAutoCertList() (c []*Cert) {
|
||||
var t []*Cert
|
||||
if db == nil {
|
||||
return
|
||||
}
|
||||
db.Where("auto_cert", AutoCertEnabled).Find(&t)
|
||||
|
||||
// check if this domain is enabled
|
||||
enabledConfig, err := os.ReadDir(nginx.GetConfPath("sites-enabled"))
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
enabledConfigMap := make(map[string]bool)
|
||||
for i := range enabledConfig {
|
||||
enabledConfigMap[enabledConfig[i].Name()] = true
|
||||
}
|
||||
|
||||
for _, v := range t {
|
||||
if enabledConfigMap[v.Filename] == true {
|
||||
c = append(c, v)
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func GetCertList(name, domain string) (c []Cert) {
|
||||
tx := db
|
||||
if name != "" {
|
||||
tx = tx.Where("name LIKE ? or domain LIKE ?", "%"+name+"%", "%"+name+"%")
|
||||
}
|
||||
if domain != "" {
|
||||
tx = tx.Where("domain LIKE ?", "%"+domain+"%")
|
||||
}
|
||||
tx.Find(&c)
|
||||
return
|
||||
}
|
||||
|
||||
func FirstCertByID(id int) (c Cert, err error) {
|
||||
err = db.First(&c, id).Error
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (c *Cert) Updates(n *Cert) error {
|
||||
return db.Model(&Cert{}).Where("id", c.ID).Updates(n).Error
|
||||
}
|
||||
|
||||
func (c *Cert) ClearLog() {
|
||||
db.Model(&Cert{}).Where("id", c.ID).Update("log", "")
|
||||
}
|
||||
|
||||
func (c *Cert) Remove() error {
|
||||
if c.Filename == "" {
|
||||
return db.Delete(c).Error
|
||||
}
|
||||
|
||||
return db.Where("filename", c.Filename).Delete(c).Error
|
||||
}
|
35
model/chatgpt_log.go
Normal file
35
model/chatgpt_log.go
Normal file
|
@ -0,0 +1,35 @@
|
|||
package model
|
||||
|
||||
import (
|
||||
"database/sql/driver"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sashabaranov/go-openai"
|
||||
)
|
||||
|
||||
type JSON []openai.ChatCompletionMessage
|
||||
|
||||
// Scan scan value into Jsonb, implements sql.Scanner interface
|
||||
func (j *JSON) Scan(value interface{}) error {
|
||||
bytes, ok := value.([]byte)
|
||||
if !ok {
|
||||
return errors.New(fmt.Sprint("Failed to unmarshal JSONB value:", value))
|
||||
}
|
||||
|
||||
result := make([]openai.ChatCompletionMessage, 0)
|
||||
err := json.Unmarshal(bytes, &result)
|
||||
*j = result
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// Value return json value, implement driver.Valuer interface
|
||||
func (j *JSON) Value() (driver.Value, error) {
|
||||
return json.Marshal(*j)
|
||||
}
|
||||
|
||||
type ChatGPTLog struct {
|
||||
Name string `json:"name"`
|
||||
Content JSON `json:"content" gorm:"serializer:json"`
|
||||
}
|
49
model/config_backup.go
Normal file
49
model/config_backup.go
Normal file
|
@ -0,0 +1,49 @@
|
|||
package model
|
||||
|
||||
import (
|
||||
"github.com/0xJacky/Nginx-UI/internal/logger"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
type ConfigBackup struct {
|
||||
Model
|
||||
|
||||
Name string `json:"name"`
|
||||
FilePath string `json:"file_path"`
|
||||
Content string `json:"content" gorm:"type:text"`
|
||||
}
|
||||
|
||||
type ConfigBackupListItem struct {
|
||||
Model
|
||||
|
||||
Name string `json:"name"`
|
||||
FilePath string `json:"file_path"`
|
||||
}
|
||||
|
||||
func GetBackupList(path string) (configs []ConfigBackupListItem) {
|
||||
db.Model(&ConfigBackup{}).
|
||||
Where(&ConfigBackup{FilePath: path}).
|
||||
Find(&configs)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func GetBackup(id int) (config ConfigBackup) {
|
||||
db.First(&config, id)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func CreateBackup(path string) {
|
||||
content, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
logger.Error(err)
|
||||
}
|
||||
|
||||
config := ConfigBackup{Name: filepath.Base(path), FilePath: path, Content: string(content)}
|
||||
result := db.Create(&config)
|
||||
if result.Error != nil {
|
||||
logger.Error(result.Error)
|
||||
}
|
||||
}
|
12
model/dns_credential.go
Normal file
12
model/dns_credential.go
Normal file
|
@ -0,0 +1,12 @@
|
|||
package model
|
||||
|
||||
import (
|
||||
"github.com/0xJacky/Nginx-UI/internal/cert/dns"
|
||||
)
|
||||
|
||||
type DnsCredential struct {
|
||||
Model
|
||||
Name string `json:"name"`
|
||||
Config *dns.Config `json:"config,omitempty" gorm:"serializer:json"`
|
||||
Provider string `json:"provider"`
|
||||
}
|
53
model/environment.go
Normal file
53
model/environment.go
Normal file
|
@ -0,0 +1,53 @@
|
|||
package model
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Environment struct {
|
||||
Model
|
||||
Name string `json:"name"`
|
||||
URL string `json:"url"`
|
||||
Token string `json:"token"`
|
||||
OperationSync bool `json:"operation_sync"`
|
||||
SyncApiRegex string `json:"sync_api_regex"`
|
||||
}
|
||||
|
||||
func (e *Environment) GetWebSocketURL(uri string) (decodedUri string, err error) {
|
||||
baseUrl, err := url.Parse(e.URL)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
defaultPort := ""
|
||||
if baseUrl.Port() == "" {
|
||||
switch baseUrl.Scheme {
|
||||
default:
|
||||
fallthrough
|
||||
case "http":
|
||||
defaultPort = "80"
|
||||
case "https":
|
||||
defaultPort = "443"
|
||||
}
|
||||
|
||||
baseUrl.Host = baseUrl.Hostname() + ":" + defaultPort
|
||||
}
|
||||
|
||||
u, err := url.JoinPath(baseUrl.String(), uri)
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
decodedUri, err = url.QueryUnescape(u)
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// http will be replaced with ws, https will be replaced with wss
|
||||
decodedUri = strings.ReplaceAll(decodedUri, "http", "ws")
|
||||
|
||||
return
|
||||
}
|
7
model/log.go
Normal file
7
model/log.go
Normal file
|
@ -0,0 +1,7 @@
|
|||
package model
|
||||
|
||||
type Log struct {
|
||||
Model
|
||||
Title string `json:"title"`
|
||||
Content string `json:"content"`
|
||||
}
|
147
model/model.go
Normal file
147
model/model.go
Normal file
|
@ -0,0 +1,147 @@
|
|||
package model
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/0xJacky/Nginx-UI/internal/logger"
|
||||
"github.com/0xJacky/Nginx-UI/settings"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/spf13/cast"
|
||||
"gorm.io/driver/sqlite"
|
||||
"gorm.io/gen"
|
||||
"gorm.io/gorm"
|
||||
gormlogger "gorm.io/gorm/logger"
|
||||
"path"
|
||||
"time"
|
||||
)
|
||||
|
||||
var db *gorm.DB
|
||||
|
||||
type Model struct {
|
||||
ID int `gorm:"primary_key" json:"id"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
DeletedAt *gorm.DeletedAt `gorm:"index" json:"deleted_at"`
|
||||
}
|
||||
|
||||
func GenerateAllModel() []any {
|
||||
return []any{
|
||||
ConfigBackup{},
|
||||
Auth{},
|
||||
AuthToken{},
|
||||
Cert{},
|
||||
ChatGPTLog{},
|
||||
Site{},
|
||||
DnsCredential{},
|
||||
Environment{},
|
||||
}
|
||||
}
|
||||
|
||||
func logMode() gormlogger.Interface {
|
||||
switch settings.ServerSettings.RunMode {
|
||||
case gin.ReleaseMode:
|
||||
return gormlogger.Default.LogMode(gormlogger.Warn)
|
||||
default:
|
||||
fallthrough
|
||||
case gin.DebugMode:
|
||||
return gormlogger.Default.LogMode(gormlogger.Info)
|
||||
}
|
||||
}
|
||||
|
||||
func Init() *gorm.DB {
|
||||
dbPath := path.Join(path.Dir(settings.ConfPath), fmt.Sprintf("%s.db", settings.ServerSettings.Database))
|
||||
|
||||
var err error
|
||||
db, err = gorm.Open(sqlite.Open(dbPath), &gorm.Config{
|
||||
Logger: logMode(),
|
||||
PrepareStmt: true,
|
||||
DisableForeignKeyConstraintWhenMigrating: true,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
logger.Fatal(err.Error())
|
||||
}
|
||||
|
||||
// Migrate the schema
|
||||
err = db.AutoMigrate(GenerateAllModel()...)
|
||||
if err != nil {
|
||||
logger.Fatal(err.Error())
|
||||
}
|
||||
|
||||
return db
|
||||
}
|
||||
|
||||
func orderAndPaginate(c *gin.Context) func(db *gorm.DB) *gorm.DB {
|
||||
return func(db *gorm.DB) *gorm.DB {
|
||||
sort := c.DefaultQuery("sort", "desc")
|
||||
order := c.DefaultQuery("order_by", "id") +
|
||||
" " + sort
|
||||
|
||||
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 db.Order(order).Offset(offset).Limit(pageSize)
|
||||
}
|
||||
}
|
||||
|
||||
func totalPage(total int64, pageSize int) int64 {
|
||||
n := total / int64(pageSize)
|
||||
if total%int64(pageSize) > 0 {
|
||||
n++
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
type Pagination struct {
|
||||
Total int64 `json:"total"`
|
||||
PerPage int `json:"per_page"`
|
||||
CurrentPage int `json:"current_page"`
|
||||
TotalPages int64 `json:"total_pages"`
|
||||
}
|
||||
|
||||
type DataList struct {
|
||||
Data interface{} `json:"data"`
|
||||
Pagination Pagination `json:"pagination,omitempty"`
|
||||
}
|
||||
|
||||
func GetListWithPagination(models interface{},
|
||||
c *gin.Context, totalRecords int64) (result DataList) {
|
||||
|
||||
page := cast.ToInt(c.Query("page"))
|
||||
if page == 0 {
|
||||
page = 1
|
||||
}
|
||||
|
||||
result = DataList{}
|
||||
|
||||
result.Data = models
|
||||
|
||||
pageSize := settings.ServerSettings.PageSize
|
||||
reqPageSize := c.Query("page_size")
|
||||
if reqPageSize != "" {
|
||||
pageSize = cast.ToInt(reqPageSize)
|
||||
}
|
||||
|
||||
result.Pagination = Pagination{
|
||||
Total: totalRecords,
|
||||
PerPage: pageSize,
|
||||
CurrentPage: page,
|
||||
TotalPages: totalPage(totalRecords, pageSize),
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
type Method interface {
|
||||
// FirstByID Where("id=@id")
|
||||
FirstByID(id int) (*gen.T, error)
|
||||
// DeleteByID update @@table set deleted_at=strftime('%Y-%m-%d %H:%M:%S','now') where id=@id
|
||||
DeleteByID(id int) error
|
||||
}
|
7
model/site.go
Normal file
7
model/site.go
Normal file
|
@ -0,0 +1,7 @@
|
|||
package model
|
||||
|
||||
type Site struct {
|
||||
Model
|
||||
Path string `json:"path"`
|
||||
Advanced bool `json:"advanced"`
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue