✨ batch update server tag
This commit is contained in:
parent
41b84163b9
commit
9352d3d0e0
@ -167,6 +167,8 @@ type Data struct {
|
|||||||
Servers []*model.Server `json:"servers,omitempty"`
|
Servers []*model.Server `json:"servers,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var cloudflareCookiesValidator = regexp.MustCompile("^[A-Za-z0-9-_]+$")
|
||||||
|
|
||||||
func (cp *commonPage) ws(c *gin.Context) {
|
func (cp *commonPage) ws(c *gin.Context) {
|
||||||
conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
|
conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -285,7 +287,7 @@ func (cp *commonPage) terminal(c *gin.Context) {
|
|||||||
encodedCookies := strings.Split(cloudflareCookies, ".")
|
encodedCookies := strings.Split(cloudflareCookies, ".")
|
||||||
if len(encodedCookies) == 3 {
|
if len(encodedCookies) == 3 {
|
||||||
for i := 0; i < 3; i++ {
|
for i := 0; i < 3; i++ {
|
||||||
if valid, _ := regexp.MatchString("^[A-Za-z0-9-_]+$", encodedCookies[i]); !valid {
|
if !cloudflareCookiesValidator.MatchString(encodedCookies[i]) {
|
||||||
cloudflareCookies = ""
|
cloudflareCookies = ""
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/jinzhu/copier"
|
||||||
|
|
||||||
"github.com/naiba/nezha/model"
|
"github.com/naiba/nezha/model"
|
||||||
"github.com/naiba/nezha/pkg/mygin"
|
"github.com/naiba/nezha/pkg/mygin"
|
||||||
@ -39,6 +40,7 @@ func (ma *memberAPI) serve() {
|
|||||||
mr.POST("/cron", ma.addOrEditCron)
|
mr.POST("/cron", ma.addOrEditCron)
|
||||||
mr.GET("/cron/:id/manual", ma.manualTrigger)
|
mr.GET("/cron/:id/manual", ma.manualTrigger)
|
||||||
mr.POST("/force-update", ma.forceUpdate)
|
mr.POST("/force-update", ma.forceUpdate)
|
||||||
|
mr.POST("/batch-update-server-group", ma.batchUpdateServerGroup)
|
||||||
mr.POST("/notification", ma.addOrEditNotification)
|
mr.POST("/notification", ma.addOrEditNotification)
|
||||||
mr.POST("/alert-rule", ma.addOrEditAlertRule)
|
mr.POST("/alert-rule", ma.addOrEditAlertRule)
|
||||||
mr.POST("/setting", ma.updateSetting)
|
mr.POST("/setting", ma.updateSetting)
|
||||||
@ -537,6 +539,67 @@ func (ma *memberAPI) manualTrigger(c *gin.Context) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type BatchUpdateServerGroupRequest struct {
|
||||||
|
Servers []uint64
|
||||||
|
Group string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ma *memberAPI) batchUpdateServerGroup(c *gin.Context) {
|
||||||
|
var req BatchUpdateServerGroupRequest
|
||||||
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
|
c.JSON(http.StatusOK, model.Response{
|
||||||
|
Code: http.StatusBadRequest,
|
||||||
|
Message: err.Error(),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := singleton.DB.Model(&model.Server{}).Where("id in (?)", req.Servers).Update("tag", req.Group).Error; err != nil {
|
||||||
|
c.JSON(http.StatusOK, model.Response{
|
||||||
|
Code: http.StatusBadRequest,
|
||||||
|
Message: err.Error(),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
singleton.ServerLock.Lock()
|
||||||
|
|
||||||
|
for i := 0; i < len(req.Servers); i++ {
|
||||||
|
serverId := req.Servers[i]
|
||||||
|
var s model.Server
|
||||||
|
copier.Copy(&s, singleton.ServerList[serverId])
|
||||||
|
s.Tag = req.Group
|
||||||
|
// 如果修改了Tag
|
||||||
|
if s.Tag != singleton.ServerList[s.ID].Tag {
|
||||||
|
index := -1
|
||||||
|
for i := 0; i < len(singleton.ServerTagToIDList[s.Tag]); i++ {
|
||||||
|
if singleton.ServerTagToIDList[s.Tag][i] == s.ID {
|
||||||
|
index = i
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if index > -1 {
|
||||||
|
// 删除旧 Tag-ID 绑定关系
|
||||||
|
singleton.ServerTagToIDList[singleton.ServerList[s.ID].Tag] = append(singleton.ServerTagToIDList[singleton.ServerList[s.ID].Tag][:index], singleton.ServerTagToIDList[singleton.ServerList[s.ID].Tag][index+1:]...)
|
||||||
|
}
|
||||||
|
// 设置新的 Tag-ID 绑定关系
|
||||||
|
singleton.ServerTagToIDList[s.Tag] = append(singleton.ServerTagToIDList[s.Tag], s.ID)
|
||||||
|
if len(singleton.ServerTagToIDList[s.Tag]) == 0 {
|
||||||
|
delete(singleton.ServerTagToIDList, s.Tag)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
singleton.ServerList[s.ID] = &s
|
||||||
|
}
|
||||||
|
|
||||||
|
singleton.ServerLock.Unlock()
|
||||||
|
|
||||||
|
singleton.ReSortServer()
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, model.Response{
|
||||||
|
Code: http.StatusOK,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func (ma *memberAPI) forceUpdate(c *gin.Context) {
|
func (ma *memberAPI) forceUpdate(c *gin.Context) {
|
||||||
var forceUpdateServers []uint64
|
var forceUpdateServers []uint64
|
||||||
if err := c.ShouldBindJSON(&forceUpdateServers); err != nil {
|
if err := c.ShouldBindJSON(&forceUpdateServers); err != nil {
|
||||||
|
@ -13,7 +13,7 @@ import (
|
|||||||
"github.com/xanzy/go-gitlab"
|
"github.com/xanzy/go-gitlab"
|
||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
GitHubOauth2 "golang.org/x/oauth2/github"
|
GitHubOauth2 "golang.org/x/oauth2/github"
|
||||||
GitlabOauth2 "golang.org/x/oauth2/github"
|
GitlabOauth2 "golang.org/x/oauth2/gitlab"
|
||||||
|
|
||||||
"github.com/naiba/nezha/model"
|
"github.com/naiba/nezha/model"
|
||||||
"github.com/naiba/nezha/pkg/mygin"
|
"github.com/naiba/nezha/pkg/mygin"
|
||||||
@ -156,7 +156,7 @@ func (oa *oauth2controller) callback(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
var isAdmin bool
|
var isAdmin bool
|
||||||
for _, admin := range strings.Split(singleton.Conf.Oauth2.Admin, ",") {
|
for _, admin := range strings.Split(singleton.Conf.Oauth2.Admin, ",") {
|
||||||
if admin != "" && strings.ToLower(user.Login) == strings.ToLower(admin) {
|
if admin != "" && strings.EqualFold(user.Login, admin) {
|
||||||
isAdmin = true
|
isAdmin = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
6
resource/l10n/zh-CN.toml
vendored
6
resource/l10n/zh-CN.toml
vendored
@ -181,6 +181,12 @@ other = "启用"
|
|||||||
[AddServer]
|
[AddServer]
|
||||||
other = "添加服务器"
|
other = "添加服务器"
|
||||||
|
|
||||||
|
[BatchEditServerGroup]
|
||||||
|
other = "批量修改分组"
|
||||||
|
|
||||||
|
[InputServerGroupName]
|
||||||
|
other = "输入分组名称"
|
||||||
|
|
||||||
[ServerGroup]
|
[ServerGroup]
|
||||||
other = "服务器分组"
|
other = "服务器分组"
|
||||||
|
|
||||||
|
54
resource/template/dashboard-default/server.html
vendored
54
resource/template/dashboard-default/server.html
vendored
@ -5,6 +5,9 @@
|
|||||||
<div class="ui container">
|
<div class="ui container">
|
||||||
<div class="ui grid">
|
<div class="ui grid">
|
||||||
<div class="right floated right aligned twelve wide column">
|
<div class="right floated right aligned twelve wide column">
|
||||||
|
<button class="ui right labeled nezha-primary-btn icon button" onclick="batchEditServerGroup()"><i
|
||||||
|
class="edit icon"></i> {{tr "BatchEditServerGroup"}}
|
||||||
|
</button>
|
||||||
<button class="ui right labeled nezha-primary-btn icon button" onclick="addOrEditServer()"><i
|
<button class="ui right labeled nezha-primary-btn icon button" onclick="addOrEditServer()"><i
|
||||||
class="add icon"></i> {{tr "AddServer"}}
|
class="add icon"></i> {{tr "AddServer"}}
|
||||||
</button>
|
</button>
|
||||||
@ -128,5 +131,56 @@
|
|||||||
});
|
});
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
function batchEditServerGroup() {
|
||||||
|
let groupName = prompt('{{tr "InputServerGroupName"}}')
|
||||||
|
if (!groupName) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const servers = []
|
||||||
|
checkBoxList.forEach(cb => {
|
||||||
|
if (cb.checked) {
|
||||||
|
servers.push(parseInt(cb.value))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (servers.length == 0) {
|
||||||
|
$.suiAlert({
|
||||||
|
title: '{{tr "NoServerSelected"}}',
|
||||||
|
description: '',
|
||||||
|
type: 'warning',
|
||||||
|
time: '2',
|
||||||
|
position: 'top-center',
|
||||||
|
});
|
||||||
|
return
|
||||||
|
}
|
||||||
|
$.post('/api/batch-update-server-group', JSON.stringify({ servers: servers, group: groupName }))
|
||||||
|
.then((resp) => {
|
||||||
|
if (resp.code == 200) {
|
||||||
|
$.suiAlert({
|
||||||
|
title: '{{tr "ExecutionResults"}}',
|
||||||
|
description: resp.message,
|
||||||
|
type: 'success',
|
||||||
|
time: '3',
|
||||||
|
position: 'top-center',
|
||||||
|
});
|
||||||
|
window.location.reload()
|
||||||
|
} else {
|
||||||
|
$.suiAlert({
|
||||||
|
title: '',
|
||||||
|
description: resp.message,
|
||||||
|
type: 'error',
|
||||||
|
time: '3',
|
||||||
|
position: 'top-center',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}).catch(err => {
|
||||||
|
$.suiAlert({
|
||||||
|
title: '',
|
||||||
|
description: err,
|
||||||
|
type: 'error',
|
||||||
|
time: '3',
|
||||||
|
position: 'top-center',
|
||||||
|
});
|
||||||
|
})
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user