diff --git a/cmd/config/database.go b/cmd/config/database.go index b96ac89..5115a6e 100644 --- a/cmd/config/database.go +++ b/cmd/config/database.go @@ -2,6 +2,7 @@ package config import ( "reCoreD-UI/controllers" + "reCoreD-UI/database" "github.com/urfave/cli/v2" ) @@ -26,11 +27,9 @@ func init() { } func migrateDatabase(c *cli.Context) error { - controller, err := controllers.NewController(c.String("mysql-dsn")) - if err != nil { + if err := database.Connect(c.String("mysql-dsn")); err != nil { return err } - defer controller.Close() - return controller.Migrate() + return controllers.Migrate() } diff --git a/cmd/config/dns.go b/cmd/config/dns.go index 4dc9872..cf2c3c5 100644 --- a/cmd/config/dns.go +++ b/cmd/config/dns.go @@ -2,6 +2,7 @@ package config import ( "reCoreD-UI/controllers" + "reCoreD-UI/database" "github.com/urfave/cli/v2" ) @@ -10,13 +11,13 @@ var DNSCommand *cli.Command func init() { DNSCommand = &cli.Command{ - Name: "dns", + Name: "dns", Usage: "Config DNS Settings", Flags: []cli.Flag{ &cli.StringSliceFlag{ - Name: "servers", - Usage: "dns servers", - Aliases: []string{"s"}, + Name: "servers", + Usage: "dns servers", + Aliases: []string{"s"}, Required: true, }, }, @@ -25,11 +26,9 @@ func init() { } func setDNS(c *cli.Context) error { - controller, err := controllers.NewController(c.String("mysql-dsn")) - if err != nil { + if err := database.Connect(c.String("mysql-dsn")); err != nil { return err } - defer controller.Close() - return controller.SetupDNS(c.StringSlice("servers")...) + return controllers.SetupDNS(c.StringSlice("servers")...) } diff --git a/cmd/config/user.go b/cmd/config/user.go index 895920f..dafc096 100644 --- a/cmd/config/user.go +++ b/cmd/config/user.go @@ -2,6 +2,7 @@ package config import ( "reCoreD-UI/controllers" + "reCoreD-UI/database" "github.com/urfave/cli/v2" ) @@ -33,10 +34,8 @@ func init() { } func setUser(c *cli.Context) error { - controller, err := controllers.NewController(c.String("mysql-dsn")) - if err != nil { + if err := database.Connect(c.String("mysql-dsn")); err != nil { return err } - defer controller.Close() - return controller.SetupAdmin(c.String("username"), c.String("password")) + return controllers.SetupAdmin(c.String("username"), c.String("password")) } diff --git a/controllers/dns.go b/controllers/dns.go deleted file mode 100644 index a28790c..0000000 --- a/controllers/dns.go +++ /dev/null @@ -1,29 +0,0 @@ -package controllers - -import ( - "reCoreD-UI/models" - "strings" - - "gorm.io/gorm" -) - -const dnsSep = "," - -func (c *Controller) SetupDNS(dns ...string) error { - return c.DB.Transaction(func(tx *gorm.DB) error { - settings := &models.Settings{} - - return tx.Where(&models.Settings{Key: models.SettingsKeyDNSServer}). - Attrs(&models.Settings{Value: strings.Join(dns, dnsSep)}). - FirstOrCreate(&settings).Error - }) -} - -func (c *Controller) GetDNS() ([]string, error) { - settings := &models.Settings{} - if err := c.DB.Where(&models.Settings{Key: models.SettingsKeyDNSServer}).Find(&settings).Error; err != nil { - return nil, err - } - - return strings.Split(settings.Value, dnsSep), nil -} diff --git a/controllers/domain.go b/controllers/domain.go index 4e32d85..82c7580 100644 --- a/controllers/domain.go +++ b/controllers/domain.go @@ -2,144 +2,148 @@ package controllers import ( "fmt" + "reCoreD-UI/database" "reCoreD-UI/models" "strconv" dns "github.com/cloud66-oss/coredns_mysql" - - "gorm.io/gorm" ) -func (c *Controller) CreateDomain(d *models.Domain) (*models.Domain, error) { - nss, err := c.GetDNS() +type domainsDAO struct { + database.BaseDAO[models.Domain] +} + +func CreateDomain(d *models.Domain) (*models.Domain, error) { + nss, err := GetDNS() if err != nil { return nil, err } - if err := c.DB.Transaction(func(tx *gorm.DB) error { - if err := tx.Create(d).Error; err != nil { - return err - } - - r := &models.RecordWithType[dns.SOARecord]{} - r.Zone = d.WithDotEnd() - r.Name = "@" - r.RecordType = models.RecordTypeSOA - r.Content.Ns = d.MainDNS - r.Content.MBox = d.EmailSOAForamt() - r.Content.Refresh = d.RefreshInterval - r.Content.Retry = d.RetryInterval - r.Content.Expire = d.ExpiryPeriod - r.Content.MinTtl = d.NegativeTtl - if err := r.CheckZone(); err != nil { - return err - } - - if err := tx.Create(r.ToRecord()).Error; err != nil { - return err - } - - for i, ns := range nss { - record := &models.RecordWithType[dns.NSRecord]{} - record.Zone = d.DomainName - record.RecordType = models.RecordTypeNS - record.Content.Host = ns - record.Name = fmt.Sprintf("ns%d", i+1) - - if err := tx.Create(record.ToRecord()).Error; err != nil { - return err - } - } - - return nil - }); err != nil { + tx := database.Client.Begin() + if _, err := (domainsDAO{}).Create(tx, *d); err != nil { + tx.Rollback() return nil, err } + r := &models.RecordWithType[dns.SOARecord]{} + r.Zone = d.WithDotEnd() + r.Name = "@" + r.RecordType = models.RecordTypeSOA + r.Content.Ns = d.MainDNS + r.Content.MBox = d.EmailSOAForamt() + r.Content.Refresh = d.RefreshInterval + r.Content.Retry = d.RetryInterval + r.Content.Expire = d.ExpiryPeriod + r.Content.MinTtl = d.NegativeTtl + if err := r.CheckZone(); err != nil { + tx.Rollback() + return nil, err + } + + if _, err := (recordsDAO{}).Create(tx, *r.ToRecord()); err != nil { + tx.Rollback() + return nil, err + } + + for i, ns := range nss { + record := &models.RecordWithType[dns.NSRecord]{} + record.Zone = d.WithDotEnd() + record.RecordType = models.RecordTypeNS + record.Content.Host = ns + record.Name = fmt.Sprintf("ns%d", i+1) + + if _, err := (recordsDAO{}).Create(tx, *record.ToRecord()); err != nil { + tx.Rollback() + return nil, err + } + } + + tx.Commit() return d, err } -func (c *Controller) GetDomains(domain string) ([]models.Domain, error) { - var domains []models.Domain - - tx := c.DB - +func GetDomains(domain string) ([]models.Domain, error) { if domain != "" { - tx = tx.Where(&models.Domain{DomainName: domain}) + return (domainsDAO{}).GetAll(database.Client, models.Domain{DomainName: domain}) + } else { + return (domainsDAO{}).GetAll(database.Client, models.Domain{}) } - - if err := tx.Find(&domains).Error; err != nil { - return nil, err - } - - return domains, nil } -func (c *Controller) UpdateDomain(d *models.Domain) error { - return c.DB.Transaction(func(tx *gorm.DB) error { - if err := tx.Model(d).Updates(d).Error; err != nil { - return err - } +func UpdateDomain(d *models.Domain) error { + tx := database.Client.Begin() + if _, err := (domainsDAO{}).Update(tx, *d); err != nil { + tx.Rollback() + return err + } - record := &models.Record{} - if err := tx.Where("record_type = ?", models.RecordTypeSOA).Where("zone = ?", d.DomainName).First(record).Error; err != nil { - return err - } - - r := &models.RecordWithType[dns.SOARecord]{} - if err := r.FromRecord(record); err != nil { - return err - } - - r.Content.Ns = d.MainDNS - r.Content.MBox = d.EmailSOAForamt() - r.Content.Refresh = d.RefreshInterval - r.Content.Retry = d.RetryInterval - r.Content.Expire = d.ExpiryPeriod - r.Content.MinTtl = d.NegativeTtl - - if err := r.CheckZone(); err != nil { - return err - } - - if err := tx.Where("record_type = ?", models.RecordTypeSOA).Where("zone = ?", d.DomainName).Save(r.ToRecord()).Error; err != nil { - return err - } - - return nil + soa, err := (recordsDAO{}).GetOne(tx, models.Record{ + RecordType: models.RecordTypeSOA, Zone: d.WithDotEnd(), }) + if err != nil { + tx.Rollback() + return err + } + + r := &models.RecordWithType[dns.SOARecord]{} + if err := r.FromRecord(&soa); err != nil { + tx.Rollback() + return err + } + + r.Content.Ns = d.MainDNS + r.Content.MBox = d.EmailSOAForamt() + r.Content.Refresh = d.RefreshInterval + r.Content.Retry = d.RetryInterval + r.Content.Expire = d.ExpiryPeriod + r.Content.MinTtl = d.NegativeTtl + if err := r.CheckZone(); err != nil { + tx.Rollback() + return err + } + + if _, err := (recordsDAO{}).Update(tx, *r.ToRecord()); err != nil { + tx.Rollback() + return err + } + + tx.Commit() + return nil + } -func (c *Controller) DeleteDomain(id string) error { +func DeleteDomain(id string) error { ID, err := strconv.Atoi(id) if err != nil { return err } - return c.DB.Transaction(func(tx *gorm.DB) error { - domain := &models.Domain{ - ID: ID, - } - if err := tx.First(&domain).Error; err != nil { - return err - } + tx := database.Client.Begin() + domain, err := (domainsDAO{}).GetOne(tx, models.Domain{ID: ID}) + if err != nil { + tx.Rollback() + return err + } - if err := tx.Where("zone = ?", domain.DomainName).Delete(&models.Record{}).Error; err != nil { - return err - } + if err := (domainsDAO{}).Delete(tx, models.Domain{ID: ID}); err != nil { + tx.Rollback() + return err + } - if err := tx.Delete(&domain).Error; err != nil { - return err - } + if err := (recordsDAO{}).Delete(tx, models.Record{Zone: domain.WithDotEnd()}); err != nil { + tx.Rollback() + return err + } - return nil - }) + tx.Commit() + return nil } -func (c *Controller) getDomainCounts() (float64, error) { - var count int64 - if err := c.DB.Model(models.Domain{}).Count(&count).Error; err != nil { +// for metrics +func getDomainCounts() (float64, error) { + c, err := (domainsDAO{}).GetAll(database.Client, models.Domain{}) + if err != nil { return 0, err } - return float64(count), nil + return float64(len(c)), nil } diff --git a/controllers/init.go b/controllers/init.go deleted file mode 100644 index 326126d..0000000 --- a/controllers/init.go +++ /dev/null @@ -1,27 +0,0 @@ -package controllers - -import ( - "reCoreD-UI/database" - - "gorm.io/gorm" -) - -type Controller struct { - DB *gorm.DB -} - -func NewController(DSN string) (*Controller, error) { - db, err := database.Connect(DSN) - return &Controller{ - DB: db, - }, err -} - -func (c *Controller) Close() error { - d, err := c.DB.DB() - if err != nil { - return err - } - - return d.Close() -} diff --git a/controllers/metrics.go b/controllers/metrics.go index efadfb4..e8b6d64 100644 --- a/controllers/metrics.go +++ b/controllers/metrics.go @@ -22,8 +22,7 @@ var ( }, []string{"domain"}) ) -func (c *Controller) RegisterMetrics() { - +func RegisterMetrics() { prometheus.MustRegister(GaugeDomainCounts, GaugeRecordCounts) GormMetrics := ormMetric.New(ormMetric.Config{ @@ -42,14 +41,14 @@ func (c *Controller) RegisterMetrics() { } } -func (c *Controller) RefreshMetrics() error { - domainCounts, err := c.getDomainCounts() +func RefreshMetrics() error { + domainCounts, err := getDomainCounts() if err != nil { return err } GaugeDomainCounts.Set(domainCounts) - recordCounts, err := c.getRecordCounts() + recordCounts, err := getRecordCounts() if err != nil { return err } diff --git a/controllers/migrate.go b/controllers/migrate.go index e3ea504..648efc9 100644 --- a/controllers/migrate.go +++ b/controllers/migrate.go @@ -1,11 +1,22 @@ package controllers -import "reCoreD-UI/models" +import ( + "reCoreD-UI/database" + "reCoreD-UI/models" +) -func (c *Controller) Migrate() error { - return c.DB.Set("gorm:table_options", "CHARSET=utf8mb4").AutoMigrate( - &models.Domain{}, - &models.Record{}, - &models.Settings{}, - ) +func Migrate() error { + if err := (domainsDAO{}).Migrate(database.Client, models.Domain{}); err != nil { + return err + } + + if err := (recordsDAO{}).Migrate(database.Client, models.Record{}); err != nil { + return err + } + + if err := (settingsDAO{}).Migrate(database.Client, models.Settings{}); err != nil { + return err + } + + return nil } diff --git a/controllers/record.go b/controllers/record.go index 11a289b..fa69d2b 100644 --- a/controllers/record.go +++ b/controllers/record.go @@ -2,96 +2,102 @@ package controllers import ( "fmt" + "reCoreD-UI/database" "reCoreD-UI/models" + "strconv" "gorm.io/gorm" ) -func (c *Controller) CreateRecord(r *models.Record) (*models.Record, error) { +type recordsDAO struct { + database.BaseDAO[models.Record] +} + +func CreateRecord(r *models.Record) (*models.Record, error) { if r.RecordType != models.RecordTypeSOA { - domains, err := c.GetDomains(r.Zone) + _, err := GetDomains(r.WithOutDotTail()) if err != nil { return nil, err } - - if len(domains) == 0 || domains[0].DomainName == r.Zone { - return nil, fmt.Errorf("no such domain") - } } if err := r.CheckZone(); err != nil { return nil, err } - if err := c.DB.Transaction(func(tx *gorm.DB) error { - return tx.Create(r).Error - }); err != nil { - return nil, err - } - - return r, nil + res, err := (recordsDAO{}).Create(database.Client, *r) + return &res, err } -func (c *Controller) CreateRecords(rs []*models.Record) error { - return c.DB.Transaction(func(tx *gorm.DB) error { - for _, r := range rs { - if err := r.CheckZone(); err != nil { - return err - } - - if err := tx.Create(r).Error; err != nil { - return err - } +func CreateRecords(rs []*models.Record) error { + tx := database.Client.Begin() + for _, r := range rs { + if err := r.CheckZone(); err != nil { + tx.Rollback() + return err } - return nil - }) -} -func (c *Controller) GetRecords(cond map[string]string) ([]models.Record, error) { - var records []models.Record - - if err := c.DB.Where(cond).Find(&records).Error; err != nil { - return nil, err + if _, err := (recordsDAO{}).Create(tx, *r); err != nil { + tx.Rollback() + return err + } } - - return records, nil + tx.Commit() + return nil } -func (c *Controller) UpdateRecord(r *models.Record) error { +func GetRecords(cond models.Record) ([]models.Record, error) { + return (recordsDAO{}).GetAll(database.Client, cond) +} + +func UpdateRecord(r *models.Record) error { if err := r.CheckZone(); err != nil { return err } - return c.DB.Transaction(func(tx *gorm.DB) error { - return tx.Model(r).Updates(r).Error - }) + if _, err := (recordsDAO{}).Update(database.Client, *r); err != nil { + return err + } + return nil } -func (c *Controller) DeleteRecord(domain, id string) error { - return c.DB.Transaction(func(tx *gorm.DB) error { - return tx.Where("record_type != ?", models.RecordTypeSOA). - Where("id = ?", id). - Where("zone = ?", domain). - Delete(&models.Record{}).Error - }) +func DeleteRecord(domain, id string) error { + ID, err := strconv.Atoi(id) + if err != nil { + return err + } + + tx := database.Client.Begin() + record, err := (recordsDAO{}).GetOne(tx, models.Record{ID: ID, Zone: fmt.Sprintf("%s.", domain)}) + if err != nil { + tx.Rollback() + return err + } + + if record.RecordType == models.RecordTypeSOA { + tx.Rollback() + return gorm.ErrRecordNotFound + } + + if err := (recordsDAO{}).Delete(tx, record); err != nil { + tx.Rollback() + return err + } + + tx.Commit() + return nil } -func (c *Controller) getRecordCounts() (map[string]float64, error) { - rows, err := c.DB.Model(models.Record{}).Select("zone", "count(*) as count").Group("zone").Rows() +// for metrics +func getRecordCounts() (map[string]float64, error) { + rows, err := (recordsDAO{}).GetAll(database.Client, models.Record{}) if err != nil { return nil, err } - defer rows.Close() result := make(map[string]float64) - for rows.Next() { - var domain string - var count int64 - if err := rows.Scan(&domain, &count); err != nil { - return nil, err - } - result[domain] = float64(count) + for _, row := range rows { + result[row.Zone] += 1 } - return result, nil } diff --git a/controllers/settings.go b/controllers/settings.go new file mode 100644 index 0000000..d04be81 --- /dev/null +++ b/controllers/settings.go @@ -0,0 +1,73 @@ +package controllers + +import ( + "reCoreD-UI/database" + "reCoreD-UI/models" + "strings" +) + +const dnsSep = "," + +type settingsDAO struct { + database.BaseDAO[models.Settings] +} + +func SetupDNS(dns ...string) error { + settings := models.Settings{Key: models.SettingsKeyDNSServer, Value: strings.Join(dns, dnsSep)} + + if _, err := (settingsDAO{}).UpdateOrCreate(database.Client, settings); err != nil { + return err + } + + return nil +} + +func GetDNS() ([]string, error) { + settings, err := (settingsDAO{}).GetOne(database.Client, models.Settings{Key: models.SettingsKeyDNSServer}) + if err != nil { + return nil, err + } + + return strings.Split(settings.Value, dnsSep), nil +} + +func SetupAdmin(username, password string) error { + settingUsername := models.Settings{ + Key: models.SettingsKeyAdminUsername, + Value: username, + } + settingPassword := models.Settings{ + Key: models.SettingsKeyAdminPassword, + Value: password, + } + + tx := database.Client.Begin() + if _, err := (settingsDAO{}).UpdateOrCreate(tx, settingUsername); err != nil { + tx.Rollback() + return err + } + + if _, err := (settingsDAO{}).UpdateOrCreate(tx, settingPassword); err != nil { + tx.Rollback() + return err + } + + tx.Commit() + return nil +} + +func GetAdmin() (string, string, error) { + settings, err := (settingsDAO{}).GetOne(database.Client, models.Settings{Key: models.SettingsKeyAdminUsername}) + if err != nil { + return "", "", err + } + username := settings.Value + + settings, err = (settingsDAO{}).GetOne(database.Client, models.Settings{Key: models.SettingsKeyAdminPassword}) + if err != nil { + return "", "", err + } + password := settings.Value + + return username, password, nil +} diff --git a/controllers/user.go b/controllers/user.go deleted file mode 100644 index d08dbe0..0000000 --- a/controllers/user.go +++ /dev/null @@ -1,41 +0,0 @@ -package controllers - -import ( - "reCoreD-UI/models" - - "gorm.io/gorm" -) - -func (c *Controller) SetupAdmin(username, password string) error { - return c.DB.Transaction(func(tx *gorm.DB) error { - settings := &models.Settings{} - - if err := tx.Where(&models.Settings{Key: models.SettingsKeyAdminUsername}). - Attrs(&models.Settings{Value: username}). - FirstOrCreate(settings).Error; err != nil { - return err - } - - if err := tx.Where(&models.Settings{Key: models.SettingsKeyAdminPassword}). - Attrs(&models.Settings{Value: password}). - FirstOrCreate(settings).Error; err != nil { - return err - } - return nil - }) -} - -func (c *Controller) GetAdmin() (string, string, error) { - settings := &models.Settings{} - if err := c.DB.Where(&models.Settings{Key: models.SettingsKeyAdminUsername}).First(settings).Error; err != nil { - return "", "", err - } - username := settings.Value - - if err := c.DB.Where(&models.Settings{Key: models.SettingsKeyAdminPassword}).First(settings).Error; err != nil { - return "", "", err - } - password := settings.Value - - return username, password, nil -} diff --git a/database/basedao.go b/database/basedao.go new file mode 100644 index 0000000..6a16a5a --- /dev/null +++ b/database/basedao.go @@ -0,0 +1,89 @@ +package database + +import ( + "errors" + + "gorm.io/gorm" +) + +type BaseDAO[T any] struct{} + +func (b BaseDAO[T]) Migrate(db *gorm.DB, e T) error { + return db.Set("gorm:table_options", "CHARSET=utf8mb4").AutoMigrate(e) +} + +func (BaseDAO[T]) GetAll(db *gorm.DB, e T) ([]T, error) { + var r []T + if err := db.Find(&r, e).Error; err != nil { + return nil, err + } + return r, nil +} + +func (BaseDAO[T]) GetOne(db *gorm.DB, e T) (T, error) { + var r T + if err := db.First(&r, e).Error; err != nil { + return r, err + } + return r, nil +} + +func (BaseDAO[T]) GetSome(db *gorm.DB, e T, limit, offset int) ([]T, error) { + var r []T + if err := db.Find(&r, e).Limit(limit).Offset(offset).Error; err != nil { + return nil, err + } + return r, nil +} + +func (BaseDAO[T]) Create(db *gorm.DB, e T) (T, error) { + if err := db.Create(&e).Error; err != nil { + return e, err + } + return e, nil +} + +func (BaseDAO[T]) FirstOrCreate(db *gorm.DB, e T) (T, error) { + if err := db.FirstOrCreate(&e).Error; err != nil { + return e, err + } + return e, nil +} + +func (BaseDAO[T]) Update(db *gorm.DB, e T) (T, error) { + if err := db.Updates(&e).Error; err != nil { + return e, err + } + return e, nil +} + +func (b BaseDAO[T]) UpdateOrCreate(db *gorm.DB, e T) (T, error) { + e, err := b.Update(db, e) + if errors.Is(err, gorm.ErrRecordNotFound) { + return b.Create(db, e) + } + return e, err +} + +func (BaseDAO[T]) Delete(db *gorm.DB, e T) error { + if err := db.Delete(e).Error; err != nil { + return err + } + return nil +} + +type IBaseDAO interface { + Migrate() + + GetAll() + GetOne() + GetSome() + + Create() + FirstOrCreate() + + Update() + UpdateOrCreate() + + Delete() +} diff --git a/database/basemapper.go b/database/basemapper.go deleted file mode 100644 index e37ce0b..0000000 --- a/database/basemapper.go +++ /dev/null @@ -1,76 +0,0 @@ -package database - -import ( - "errors" - - "gorm.io/gorm" -) - -type BaseDAO[T any] struct { - db *gorm.DB -} - -func NewDAO[T any](db *gorm.DB) *BaseDAO[T] { - return &BaseDAO[T]{ - db: db, - } -} - -/* Single Table Operations */ - -func (b *BaseDAO[T]) GetAll(e T) ([]T, error) { - var r []T - if err := b.db.Find(&r, e).Error; err != nil { - return nil, err - } - return r, nil -} - -func (b *BaseDAO[T]) GetOne(e T) (T, error) { - var r T - if err := b.db.First(&r, e).Error; err != nil { - return r, err - } - return r, nil -} - -func (b *BaseDAO[T]) GetSome(e T, limit, offset int) ([]T, error) { - var r []T - if err := b.db.Find(&r, e).Limit(limit).Offset(offset).Error; err != nil { - return nil, err - } - return r, nil -} - -func (b *BaseDAO[T]) Create(e T) (T, error) { - if err := b.db.Create(&e).Error; err != nil { - return e, err - } - return e, nil -} - -func (b *BaseDAO[T]) Update(e T) (T, error) { - if err := b.db.Updates(&e).Error; err != nil { - return e, err - } - return e, nil -} - -func (b *BaseDAO[T]) UpdateOrCreate(e T) (T, error) { - var r T - err := b.db.First(&r, e).Error - if err != nil { - if errors.Is(err, gorm.ErrRecordNotFound) { - return b.Create(e) - } - return e, err - } - return b.Update(e) -} - -func (b *BaseDAO[T]) Delete(e T) error { - if err := b.db.Delete(e).Error; err != nil { - return err - } - return nil -} diff --git a/database/database.go b/database/database.go index 065ea24..c50d8d9 100644 --- a/database/database.go +++ b/database/database.go @@ -5,6 +5,13 @@ import ( "gorm.io/gorm" ) -func Connect(DSN string) (*gorm.DB, error) { - return gorm.Open(mysql.Open(DSN), &gorm.Config{}) +var Client *gorm.DB + +func Connect(DSN string) error { + var err error + Client, err = gorm.Open(mysql.Open(DSN), &gorm.Config{}) + if err != nil { + return err + } + return nil } diff --git a/models/record.go b/models/record.go index d2a6f7b..8ea5a8f 100644 --- a/models/record.go +++ b/models/record.go @@ -32,13 +32,17 @@ func (Record) TableName() string { return "coredns_record" } -func (r *Record) CheckZone() error { +func (r Record) CheckZone() error { if strings.HasSuffix(r.Zone, ".") { return fmt.Errorf("zone should end with '.'") } return nil } +func (r Record) WithOutDotTail() string { + return strings.TrimRight(r.Zone, ".") +} + type RecordContentTypes interface { dns.ARecord | dns.AAAARecord | dns.CNAMERecord | dns.CAARecord | dns.NSRecord | dns.MXRecord | dns.SOARecord | dns.SRVRecord | dns.TXTRecord } diff --git a/server/handlers_domains.go b/server/handlers_domains.go index af1758c..394cf89 100644 --- a/server/handlers_domains.go +++ b/server/handlers_domains.go @@ -2,13 +2,14 @@ package server import ( "net/http" + "reCoreD-UI/controllers" "reCoreD-UI/models" "github.com/gin-gonic/gin" ) func (s *Server) getDomains(c *gin.Context) { - domains, err := s.controller.GetDomains("") + domains, err := controllers.GetDomains("") if err != nil { errorHandler(c, err) return @@ -31,7 +32,7 @@ func (s *Server) createDomain(c *gin.Context) { return } - domain, err := s.controller.CreateDomain(domain) + domain, err := controllers.CreateDomain(domain) if err != nil { errorHandler(c, err) return @@ -54,7 +55,7 @@ func (s *Server) updateDomain(c *gin.Context) { return } - if err := s.controller.UpdateDomain(domain); err != nil { + if err := controllers.UpdateDomain(domain); err != nil { errorHandler(c, err) return } @@ -66,7 +67,7 @@ func (s *Server) updateDomain(c *gin.Context) { func (s *Server) deleteDomain(c *gin.Context) { id := c.Param("id") - if err := s.controller.DeleteDomain(id); err != nil { + if err := controllers.DeleteDomain(id); err != nil { errorHandler(c, err) return } diff --git a/server/handlers_records.go b/server/handlers_records.go index ad5c855..d73fdbf 100644 --- a/server/handlers_records.go +++ b/server/handlers_records.go @@ -1,14 +1,16 @@ package server import ( + "fmt" "net/http" + "reCoreD-UI/controllers" "reCoreD-UI/models" "github.com/gin-gonic/gin" ) func (s *Server) getRecords(c *gin.Context) { - query := make(map[string]string) + query := models.Record{} if err := c.BindQuery(&query); err != nil { c.JSON(http.StatusBadRequest, Response{ Succeed: false, @@ -17,9 +19,9 @@ func (s *Server) getRecords(c *gin.Context) { return } domain := c.Param("domain") - query["zone"] = domain + query.Zone = fmt.Sprintf("%s.", domain) - records, err := s.controller.GetRecords(query) + records, err := controllers.GetRecords(query) if err != nil { errorHandler(c, err) return @@ -50,15 +52,15 @@ func (s *Server) createRecord(c *gin.Context) { return } - record, err := s.controller.CreateRecord(record) - if err != nil { + record, err := controllers.CreateRecord(record) + if err != nil { errorHandler(c, err) return } c.JSON(http.StatusCreated, Response{ Succeed: true, - Data: record, + Data: record, }) } @@ -72,7 +74,7 @@ func (s *Server) createRecords(c *gin.Context) { return } - if err := s.controller.CreateRecords(records); err != nil { + if err := controllers.CreateRecords(records); err != nil { errorHandler(c, err) return } @@ -101,7 +103,7 @@ func (s *Server) updateRecord(c *gin.Context) { return } - if err := s.controller.UpdateRecord(record); err != nil { + if err := controllers.UpdateRecord(record); err != nil { errorHandler(c, err) return } @@ -115,7 +117,7 @@ func (s *Server) deleteRecord(c *gin.Context) { domain := c.Param("domain") id := c.Param("id") - if err := s.controller.DeleteRecord(domain, id); err != nil { + if err := controllers.DeleteRecord(domain, id); err != nil { errorHandler(c, err) return } diff --git a/server/response.go b/server/response.go index 35c23fa..d33859e 100644 --- a/server/response.go +++ b/server/response.go @@ -1,10 +1,12 @@ package server import ( + "errors" "net/http" "github.com/gin-gonic/gin" "github.com/sirupsen/logrus" + "gorm.io/gorm" ) type Response struct { @@ -15,9 +17,16 @@ type Response struct { func errorHandler(c *gin.Context, err error) { logrus.Error(err) - c.JSON(http.StatusInternalServerError, Response{ - Succeed: false, - Message: err.Error(), - Data: nil, - }) + if errors.Is(err, gorm.ErrRecordNotFound) { + c.JSON(http.StatusNotFound, Response{ + Succeed: false, + Message: err.Error(), + }) + } else { + c.JSON(http.StatusInternalServerError, Response{ + Succeed: false, + Message: err.Error(), + Data: nil, + }) + } } diff --git a/server/route.go b/server/route.go index 457048b..ef59a62 100644 --- a/server/route.go +++ b/server/route.go @@ -2,6 +2,7 @@ package server import ( "path" + "reCoreD-UI/controllers" "strings" "github.com/gin-gonic/gin" @@ -15,14 +16,14 @@ const ( ) func (s *Server) setupRoute() { - username, password, err := s.controller.GetAdmin() + username, password, err := controllers.GetAdmin() if err != nil { logrus.Fatal(err) } metricHandler := gin.New() metricHandler.GET(metricPrefix, func(ctx *gin.Context) { - if err := s.controller.RefreshMetrics(); err != nil { + if err := controllers.RefreshMetrics(); err != nil { logrus.Error(err) } promhttp.Handler().ServeHTTP(ctx.Writer, ctx.Request) diff --git a/server/server.go b/server/server.go index 0e23ca6..b0209df 100644 --- a/server/server.go +++ b/server/server.go @@ -2,7 +2,7 @@ package server import ( "net" - "reCoreD-UI/controllers" + "reCoreD-UI/database" "github.com/gin-gonic/gin" "github.com/sirupsen/logrus" @@ -10,21 +10,18 @@ import ( ) type Server struct { - controller *controllers.Controller - webServer *gin.Engine - listen string - prefix string + webServer *gin.Engine + listen string + prefix string } func NewServer(c *cli.Context) (*Server, error) { - controller, err := controllers.NewController(c.String("mysql-dsn")) - if err != nil { + if err := database.Connect(c.String("mysql-dsn")); err != nil { return nil, err } return &Server{ - controller: controller, - webServer: gin.New(), + webServer: gin.New(), listen: net.JoinHostPort( c.String("listen"), c.String("port"),