refactor: project directory structure

This commit is contained in:
0xJacky 2023-11-26 18:59:12 +08:00
parent c1193a5b8c
commit e5a5889931
No known key found for this signature in database
GPG key ID: B6E4A6E4A561BAF0
367 changed files with 710 additions and 756 deletions

81
model/auth.go Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View file

@ -0,0 +1,7 @@
package model
type Site struct {
Model
Path string `json:"path"`
Advanced bool `json:"advanced"`
}