up(notification): 添加修改删除通知、报警规则

This commit is contained in:
naiba 2020-12-19 23:11:16 +08:00
parent d19de0edc2
commit fcbd564bff
14 changed files with 156 additions and 85 deletions

View File

@ -32,9 +32,9 @@ func (ma *memberAPI) serve() {
mr.POST("/logout", ma.logout)
mr.POST("/server", ma.addOrEditServer)
mr.POST("/notification", ma.addOrEditNotification)
mr.POST("/alert-rule", ma.addOrEditAlertRule)
mr.POST("/setting", ma.updateSetting)
mr.DELETE("/server/:id", ma.delete)
mr.DELETE("/notification/:id", ma.deleteNotification)
mr.DELETE("/:model/:id", ma.delete)
}
func (ma *memberAPI) delete(c *gin.Context) {
@ -46,31 +46,22 @@ func (ma *memberAPI) delete(c *gin.Context) {
})
return
}
dao.ServerLock.Lock()
defer dao.ServerLock.Unlock()
if err := dao.DB.Delete(&model.Server{}, "id = ?", id).Error; err != nil {
c.JSON(http.StatusOK, model.Response{
Code: http.StatusBadRequest,
Message: fmt.Sprintf("数据库错误:%s", err),
})
return
}
delete(dao.ServerList, strconv.FormatUint(id, 10))
c.JSON(http.StatusOK, model.Response{
Code: http.StatusOK,
})
}
func (ma *memberAPI) deleteNotification(c *gin.Context) {
id, _ := strconv.ParseUint(c.Param("id"), 10, 64)
if id < 1 {
c.JSON(http.StatusOK, model.Response{
Code: http.StatusBadRequest,
Message: "错误的 Notification ID",
})
return
var err error
switch c.Param("model") {
case "server":
dao.ServerLock.Lock()
defer dao.ServerLock.Unlock()
err = dao.DB.Delete(&model.Server{}, "id = ?", id).Error
if err == nil {
delete(dao.ServerList, strconv.FormatUint(id, 10))
}
case "notification":
err = dao.DB.Delete(&model.Notification{}, "id = ?", id).Error
case "alert-rule":
err = dao.DB.Delete(&model.AlertRule{}, "id = ?", id).Error
}
if err := dao.DB.Delete(&model.Notification{}, "id = ?", id).Error; err != nil {
if err != nil {
c.JSON(http.StatusOK, model.Response{
Code: http.StatusBadRequest,
Message: fmt.Sprintf("数据库错误:%s", err),
@ -165,6 +156,51 @@ func (ma *memberAPI) addOrEditNotification(c *gin.Context) {
})
}
type alertRuleForm struct {
ID uint64
Name string
RulesRaw string
Enable string
}
func (ma *memberAPI) addOrEditAlertRule(c *gin.Context) {
var arf alertRuleForm
var r model.AlertRule
err := c.ShouldBindJSON(&arf)
if err == nil {
err = json.Unmarshal([]byte(arf.RulesRaw), &r.Rules)
if err == nil && len(r.Rules) == 0 {
c.JSON(http.StatusOK, model.Response{
Code: http.StatusBadRequest,
Message: fmt.Sprintf("请求错误:%s", "至少定义一条规则"),
})
return
}
}
if err == nil {
r.Name = arf.Name
r.RulesRaw = arf.RulesRaw
enable := arf.Enable == "on"
r.Enable = &enable
r.ID = arf.ID
if r.ID == 0 {
err = dao.DB.Create(&r).Error
} else {
err = dao.DB.Save(&r).Error
}
}
if err != nil {
c.JSON(http.StatusOK, model.Response{
Code: http.StatusBadRequest,
Message: fmt.Sprintf("请求错误:%s", err),
})
return
}
c.JSON(http.StatusOK, model.Response{
Code: http.StatusOK,
})
}
type logoutForm struct {
ID uint64
}

View File

@ -39,9 +39,12 @@ func (mp *memberPage) server(c *gin.Context) {
func (mp *memberPage) notification(c *gin.Context) {
var nf []model.Notification
dao.DB.Find(&nf)
var ar []model.AlertRule
dao.DB.Find(&ar)
c.HTML(http.StatusOK, "dashboard/notification", mygin.CommonEnvironment(c, gin.H{
"Title": "通知管理",
"Notifications": nf,
"AlertRules": ar,
}))
}

View File

@ -4,9 +4,9 @@ import (
"fmt"
"time"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/sqlite"
"github.com/patrickmn/go-cache"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
"github.com/naiba/nezha/cmd/dashboard/controller"
"github.com/naiba/nezha/cmd/dashboard/rpc"
@ -22,7 +22,7 @@ func init() {
if err != nil {
panic(err)
}
dao.DB, err = gorm.Open("sqlite3", "data/sqlite.db")
dao.DB, err = gorm.Open(sqlite.Open("data/sqlite.db"), &gorm.Config{})
if err != nil {
panic(err)
}
@ -34,7 +34,7 @@ func init() {
}
func initDB() {
dao.DB.AutoMigrate(model.Server{}, model.User{}, model.Notification{})
dao.DB.AutoMigrate(model.Server{}, model.User{}, model.Notification{}, model.AlertRule{})
// load cache
var servers []model.Server
dao.DB.Find(&servers)

3
go.mod
View File

@ -10,7 +10,6 @@ require (
github.com/golang/protobuf v1.4.2
github.com/google/go-github v17.0.0+incompatible
github.com/gorilla/websocket v1.4.2
github.com/jinzhu/gorm v1.9.16
github.com/naiba/com v0.0.0-20191104074000-318339dc72a5
github.com/onsi/ginkgo v1.7.0 // indirect
github.com/onsi/gomega v1.4.3 // indirect
@ -23,4 +22,6 @@ require (
google.golang.org/grpc v1.33.1
google.golang.org/protobuf v1.25.0
gopkg.in/yaml.v2 v2.2.8
gorm.io/driver/sqlite v1.1.4
gorm.io/gorm v1.20.8
)

32
go.sum
View File

@ -38,12 +38,10 @@ github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d h1:G0m3OIz70MZUWq3EgK3CesDbo8upS2Vm9/P3FtgI+Jk=
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
@ -74,16 +72,12 @@ github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd h1:83Wprp6ROGeiHFAP8WJdI2RoxALQYgdllERc3N5N2DM=
github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 h1:Yzb9+7DPaBjB8zlTR87/ElzFsnQfuHnVUVqpZZIcV5Y=
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
@ -110,13 +104,9 @@ github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD87
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY=
github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@ -211,12 +201,10 @@ github.com/inconshreveable/go-update v0.0.0-20160112193335-8152e7eb6ccf h1:WfD7V
github.com/inconshreveable/go-update v0.0.0-20160112193335-8152e7eb6ccf/go.mod h1:hyb9oH7vZsitZCiBt0ZvifOrB+qc8PS5IiilCIb87rg=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/jinzhu/gorm v1.9.16 h1:+IyIjPEABKRpsu/F8OvDPy9fyQlgsg2luMV2ZIH5i5o=
github.com/jinzhu/gorm v1.9.16/go.mod h1:G3LB3wezTOWM2ITLzPxEXgSkOXAntiLHS7UdBefADcs=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.0.1 h1:HjfetcXq097iXP0uoPCdnM4Efp5/9MsM0/M+XOTeR3M=
github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/jinzhu/now v1.1.1 h1:g39TucaRWyV3dwDO++eEc6qf8TVIQ/Da48WmqjZ3i7E=
github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
@ -237,8 +225,6 @@ github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/lib/pq v1.1.1 h1:sJZmqHoEaY7f+NPP8pgLB/WxulyR3fewgCM2qaSlBb4=
github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
@ -246,8 +232,8 @@ github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaO
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-sqlite3 v1.14.0 h1:mLyGNKR8+Vv9CAU7PphKa2hkEqxxhn8i32J6FPj1/QA=
github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus=
github.com/mattn/go-sqlite3 v1.14.5 h1:1IdxlwTNazvbKJQSxoJ5/9ECbEeaTTyeU7sEAZ5KKTQ=
github.com/mattn/go-sqlite3 v1.14.5/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
@ -362,13 +348,9 @@ golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnf
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c h1:Vj5n4GlwjmQteupaxJ9+0FNOmBrHfq7vN4btdGoDZgI=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd h1:GGJVjV8waZKRHrgwvtH66z9ZGVurTD1MT0n1Bb+q4aM=
golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@ -401,7 +383,6 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -659,6 +640,11 @@ gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/driver/sqlite v1.1.4 h1:PDzwYE+sI6De2+mxAneV9Xs11+ZyKV6oxD3wDGkaNvM=
gorm.io/driver/sqlite v1.1.4/go.mod h1:mJCeTFr7+crvS+TRnWc5Z3UvwxUN1BGBLMrf5LA9DYw=
gorm.io/gorm v1.20.7/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
gorm.io/gorm v1.20.8 h1:iToaOdZgjNvlc44NFkxfLa3U9q63qwaxt0FdNCiwOMs=
gorm.io/gorm v1.20.8/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

35
model/alertrule.go Normal file
View File

@ -0,0 +1,35 @@
package model
import (
"encoding/json"
"gorm.io/gorm"
)
type Rule struct {
Type string // 指标类型cpu、memory、swap、disk、net_in、net_out、net_all、transfer_in、transfer_out、transfer_all、offline
Min uint64 // 最小阈值 (百分比、字节 kb ÷ 1024)
Max uint64 // 最大阈值 (百分比、字节 kb ÷ 1024)
Duration uint64 // 持续时间 (秒)
}
type AlertRule struct {
Common
Name string
Rules []Rule `gorm:"-" json:"-"`
RulesRaw string
Enable *bool
}
func (r *AlertRule) BeforeSave(tx *gorm.DB) error {
data, err := json.Marshal(r.Rules)
if err != nil {
return err
}
r.RulesRaw = string(data)
return nil
}
func (r *AlertRule) AfterFind(tx *gorm.DB) error {
return json.Unmarshal([]byte(r.RulesRaw), r.Rules)
}

View File

@ -1,10 +0,0 @@
package model
type Rule struct {
Common
Name string
Type string // 指标类型cpu、memory、swap、disk、net_in、net_out、net_all、transfer_in、transfer_out、transfer_all、offline
Min uint64 // 最小阈值
Max uint64 // 最大阈值
Duration uint64 // 持续时间
}

View File

@ -14,8 +14,8 @@ type Server struct {
Name string
Secret string `json:"-"`
Host *Host
State *State
Host *Host `gorm:"-"`
State *State `gorm:"-"`
LastActive time.Time
Stream pb.NezhaService_HeartbeatServer `gorm:"-" json:"-"`

View File

@ -10,7 +10,7 @@ import (
// User ...
type User struct {
Common `json:"common,omitempty"`
Common
Login string `gorm:"UNIQUE_INDEX" json:"login,omitempty"` // 登录名
AvatarURL string `json:"avatar_url,omitempty"` // 头像地址
Name string `json:"name,omitempty"` // 昵称

View File

@ -70,6 +70,21 @@ function showFormModal(modelSelector, formID, URL, getData) {
}).modal('show')
}
function addOrEditAlertRule(rule) {
const modal = $('.rule.modal')
modal.children('.header').text((rule ? '修改' : '添加') + '报警规则')
modal.find('.positive.button').html(rule ? '修改<i class="edit icon"></i>' : '添加<i class="add icon"></i>')
modal.find('input[name=ID]').val(rule ? rule.ID : null)
modal.find('input[name=Name]').val(rule ? rule.Name : null)
modal.find('textarea[name=RulesRaw]').val(rule ? rule.RulesRaw : null)
if (rule && rule.Enable) {
modal.find('.ui.rule-enable.checkbox').checkbox('set checked')
} else {
modal.find('.ui.rule-enable.checkbox').checkbox('set unchecked')
}
showFormModal('.rule.modal', '#ruleForm', '/api/alert-rule')
}
function addOrEditNotification(notification) {
const modal = $('.notification.modal')
modal.children('.header').text((notification ? '修改' : '添加') + '通知方式')
@ -81,9 +96,9 @@ function addOrEditNotification(notification) {
modal.find('select[name=RequestMethod]').val(notification ? notification.RequestMethod : 1)
modal.find('select[name=RequestType]').val(notification ? notification.RequestType : 1)
if (notification && notification.VerifySSL) {
modal.find('.ui.checkbox').checkbox('set checked')
modal.find('.ui.nf-ssl.checkbox').checkbox('set checked')
} else {
modal.find('.ui.checkbox').checkbox('set unchecked')
modal.find('.ui.nf-ssl.checkbox').checkbox('set unchecked')
}
showFormModal('.notification.modal', '#notificationForm', '/api/notification')
}

View File

@ -31,7 +31,7 @@
<textarea name="RequestBody"></textarea>
</div>
<div class="field">
<div class="ui checkbox">
<div class="ui nf-ssl checkbox">
<input name="VerifySSL" type="checkbox" tabindex="0" class="hidden">
<label>验证SSL</label>
</div>

View File

@ -1,8 +1,8 @@
{{define "component/rule"}}
<div class="ui tiny notification modal transition hidden">
<div class="ui tiny rule modal transition hidden">
<div class="header">添加通知规则</div>
<div class="content">
<form id="notificationForm" class="ui form">
<form id="ruleForm" class="ui form">
<input type="hidden" name="ID">
<div class="field">
<label>备注</label>
@ -10,11 +10,11 @@
</div>
<div class="secret field">
<label>规则</label>
<textarea name="RequestBody"></textarea>
<textarea name="RulesRaw"></textarea>
</div>
<div class="field">
<div class="ui checkbox">
<input name="VerifySSL" type="checkbox" tabindex="0" class="hidden">
<div class="ui rule-enable checkbox">
<input name="Enable" type="checkbox" tabindex="0" class="hidden">
<label>启用</label>
</div>
</div>

View File

@ -16,6 +16,7 @@
<th>ID</th>
<th>备注</th>
<th>URL</th>
<th>验证SSL</th>
<th>管理</th>
</tr>
</thead>
@ -25,6 +26,7 @@
<td>{{$notification.ID}}</td>
<td>{{$notification.Name}}</td>
<td>{{$notification.URL}}</td>
<td>{{$notification.VerifySSL}}</td>
<td>
<div class="ui mini icon buttons">
<button class="ui button" onclick="addOrEditNotification({{$notification}})">
@ -42,8 +44,9 @@
</table>
<div class="ui grid">
<div class="right floated right aligned twelve wide column">
<button class="ui right labeled positive icon button" onclick="addOrEditNotification()"><i
class="add icon"></i> 添加报警规则
<button class="ui right labeled positive icon button" onclick="addOrEditAlertRule()"><i
class="add icon"></i>
添加报警规则
</button>
</div>
</div>
@ -52,23 +55,25 @@
<tr>
<th>ID</th>
<th>备注</th>
<th>URL</th>
<th>规则</th>
<th>启用</th>
<th>管理</th>
</tr>
</thead>
<tbody>
{{range $notification := .Notifications}}
{{range $rule := .AlertRules}}
<tr>
<td>{{$notification.ID}}</td>
<td>{{$notification.Name}}</td>
<td>{{$notification.URL}}</td>
<td>{{$rule.ID}}</td>
<td>{{$rule.Name}}</td>
<td>{{$rule.RulesRaw}}</td>
<td>{{$rule.Enable}}</td>
<td>
<div class="ui mini icon buttons">
<button class="ui button" onclick="addOrEditNotification({{$notification}})">
<button class="ui button" onclick="addOrEditAlertRule({{$rule}})">
<i class="edit icon"></i>
</button>
<button class="ui button"
onclick="showConfirm('删除通知方式','确认删除此通知方式?',deleteRequest,'/api/notification/'+{{$notification.ID}})">
onclick="showConfirm('删除通知方式','确认删除此通知方式?',deleteRequest,'/api/alert-rule/'+{{$rule.ID}})">
<i class="delete icon"></i>
</button>
</div>
@ -78,9 +83,9 @@
</tbody>
</table>
</div>
</div>
{{template "component/notification"}}
{{template "component/rule"}}
{{template "common/footer" .}}
<script>
$('.checkbox').checkbox()

View File

@ -3,8 +3,8 @@ package dao
import (
"sync"
"github.com/jinzhu/gorm"
"github.com/patrickmn/go-cache"
"gorm.io/gorm"
"github.com/naiba/nezha/model"
pb "github.com/naiba/nezha/proto"