2021-07-14 22:45:52 +08:00
// 动作选择
Vue . component ( "http-firewall-actions-box" , {
2023-07-02 16:24:01 +08:00
props : [ "v-actions" , "v-firewall-policy" , "v-action-configs" , "v-group-type" ] ,
2021-07-14 22:45:52 +08:00
mounted : function ( ) {
let that = this
Tea . action ( "/servers/iplists/levelOptions" )
. success ( function ( resp ) {
that . ipListLevels = resp . data . levels
} )
. post ( )
this . loadJS ( function ( ) {
let box = document . getElementById ( "actions-box" )
Sortable . create ( box , {
draggable : ".label" ,
handle : ".icon.handle" ,
onStart : function ( ) {
that . cancel ( )
} ,
onUpdate : function ( event ) {
let labels = box . getElementsByClassName ( "label" )
let newConfigs = [ ]
for ( let i = 0 ; i < labels . length ; i ++ ) {
let index = parseInt ( labels [ i ] . getAttribute ( "data-index" ) )
newConfigs . push ( that . configs [ index ] )
}
that . configs = newConfigs
}
} )
} )
} ,
data : function ( ) {
if ( this . vFirewallPolicy . inbound == null ) {
this . vFirewallPolicy . inbound = { }
}
if ( this . vFirewallPolicy . inbound . groups == null ) {
this . vFirewallPolicy . inbound . groups = [ ]
}
2023-07-02 16:24:01 +08:00
if ( this . vFirewallPolicy . outbound == null ) {
this . vFirewallPolicy . outbound = { }
}
if ( this . vFirewallPolicy . outbound . groups == null ) {
this . vFirewallPolicy . outbound . groups = [ ]
}
2021-07-14 22:45:52 +08:00
let id = 0
let configs = [ ]
if ( this . vActionConfigs != null ) {
configs = this . vActionConfigs
configs . forEach ( function ( v ) {
v . id = ( id ++ )
} )
}
2021-10-25 19:40:28 +08:00
var defaultPageBody = ` <!DOCTYPE html>
2023-08-25 15:03:31 +08:00
< html lang = "en" >
2024-01-20 10:15:05 +08:00
< head >
\ t < title > 403 Forbidden < / t i t l e >
2023-08-25 15:03:31 +08:00
\ t < style >
\ t \ taddress { line - height : 1.8 ; }
\ t < / s t y l e >
2024-01-20 10:15:05 +08:00
< / h e a d >
2021-10-25 19:40:28 +08:00
< body >
2021-12-02 14:45:51 +08:00
< h1 > 403 Forbidden < / h 1 >
2023-08-25 15:03:31 +08:00
< address > Connection : \ $ { remoteAddr } ( Client ) - & gt ; \ $ { serverAddr } ( Server ) < / a d d r e s s >
< address > Request ID : \ $ { requestId } < / a d d r e s s >
2021-10-25 19:40:28 +08:00
< / b o d y >
< / h t m l > `
2021-07-14 22:45:52 +08:00
return {
id : id ,
actions : this . vActions ,
configs : configs ,
isAdding : false ,
editingIndex : - 1 ,
action : null ,
actionCode : "" ,
actionOptions : { } ,
// IPList相关
ipListLevels : [ ] ,
// 动作参数
2021-07-18 15:52:50 +08:00
blockTimeout : "" ,
2023-03-01 19:18:22 +08:00
blockTimeoutMax : "" ,
2021-10-18 20:09:06 +08:00
blockScope : "global" ,
2021-07-14 22:45:52 +08:00
captchaLife : "" ,
2022-01-16 16:54:20 +08:00
captchaMaxFails : "" ,
captchaFailBlockTimeout : "" ,
2022-08-25 15:35:16 +08:00
2021-07-14 22:45:52 +08:00
get302Life : "" ,
2022-08-25 15:35:16 +08:00
2021-07-14 22:45:52 +08:00
post307Life : "" ,
2022-08-25 15:35:16 +08:00
2021-07-14 22:45:52 +08:00
recordIPType : "black" ,
recordIPLevel : "critical" ,
recordIPTimeout : "" ,
recordIPListId : 0 ,
recordIPListName : "" ,
tagTags : [ ] ,
2024-01-20 16:17:28 +08:00
pageUseDefault : true ,
2021-10-25 19:40:28 +08:00
pageStatus : 403 ,
pageBody : defaultPageBody ,
defaultPageBody : defaultPageBody ,
2023-05-28 17:11:45 +08:00
redirectStatus : 307 ,
redirectURL : "" ,
2021-07-14 22:45:52 +08:00
goGroupName : "" ,
goGroupId : 0 ,
goGroup : null ,
goSetId : 0 ,
2022-08-25 15:35:16 +08:00
goSetName : "" ,
jsCookieLife : "" ,
jsCookieMaxFails : "" ,
2023-05-28 17:22:20 +08:00
jsCookieFailBlockTimeout : "" ,
statusOptions : [
{ "code" : 301 , "text" : "Moved Permanently" } ,
{ "code" : 308 , "text" : "Permanent Redirect" } ,
{ "code" : 302 , "text" : "Found" } ,
{ "code" : 303 , "text" : "See Other" } ,
{ "code" : 307 , "text" : "Temporary Redirect" }
]
2021-07-14 22:45:52 +08:00
}
} ,
watch : {
actionCode : function ( code ) {
this . action = this . actions . $find ( function ( k , v ) {
return v . code == code
} )
this . actionOptions = { }
} ,
2021-07-18 15:52:50 +08:00
blockTimeout : function ( v ) {
2021-07-14 22:45:52 +08:00
v = parseInt ( v )
if ( isNaN ( v ) ) {
2021-07-18 15:52:50 +08:00
this . actionOptions [ "timeout" ] = 0
2021-07-14 22:45:52 +08:00
} else {
2021-07-18 15:52:50 +08:00
this . actionOptions [ "timeout" ] = v
2021-07-14 22:45:52 +08:00
}
} ,
2023-03-01 19:18:22 +08:00
blockTimeoutMax : function ( v ) {
v = parseInt ( v )
if ( isNaN ( v ) ) {
this . actionOptions [ "timeoutMax" ] = 0
} else {
this . actionOptions [ "timeoutMax" ] = v
}
} ,
2021-10-18 20:09:06 +08:00
blockScope : function ( v ) {
this . actionOptions [ "scope" ] = v
} ,
2021-07-14 22:45:52 +08:00
captchaLife : function ( v ) {
v = parseInt ( v )
if ( isNaN ( v ) ) {
this . actionOptions [ "life" ] = 0
} else {
this . actionOptions [ "life" ] = v
}
} ,
2022-01-16 16:54:20 +08:00
captchaMaxFails : function ( v ) {
v = parseInt ( v )
if ( isNaN ( v ) ) {
this . actionOptions [ "maxFails" ] = 0
} else {
this . actionOptions [ "maxFails" ] = v
}
} ,
captchaFailBlockTimeout : function ( v ) {
v = parseInt ( v )
if ( isNaN ( v ) ) {
this . actionOptions [ "failBlockTimeout" ] = 0
} else {
this . actionOptions [ "failBlockTimeout" ] = v
}
} ,
2021-07-14 22:45:52 +08:00
get302Life : function ( v ) {
v = parseInt ( v )
if ( isNaN ( v ) ) {
this . actionOptions [ "life" ] = 0
} else {
this . actionOptions [ "life" ] = v
}
} ,
post307Life : function ( v ) {
v = parseInt ( v )
if ( isNaN ( v ) ) {
this . actionOptions [ "life" ] = 0
} else {
this . actionOptions [ "life" ] = v
}
} ,
2021-07-18 15:52:50 +08:00
recordIPType : function ( v ) {
2021-07-14 22:45:52 +08:00
this . recordIPListId = 0
} ,
recordIPTimeout : function ( v ) {
v = parseInt ( v )
if ( isNaN ( v ) ) {
this . actionOptions [ "timeout" ] = 0
} else {
this . actionOptions [ "timeout" ] = v
}
} ,
goGroupId : function ( groupId ) {
let group = this . vFirewallPolicy . inbound . groups . $find ( function ( k , v ) {
return v . id == groupId
} )
this . goGroup = group
if ( group == null ) {
2023-07-02 16:24:01 +08:00
// search outbound groups
group = this . vFirewallPolicy . outbound . groups . $find ( function ( k , v ) {
return v . id == groupId
} )
if ( group == null ) {
this . goGroupName = ""
} else {
this . goGroup = group
this . goGroupName = group . name
}
2021-07-14 22:45:52 +08:00
} else {
this . goGroupName = group . name
}
this . goSetId = 0
this . goSetName = ""
} ,
goSetId : function ( setId ) {
if ( this . goGroup == null ) {
return
}
let set = this . goGroup . sets . $find ( function ( k , v ) {
return v . id == setId
} )
if ( set == null ) {
this . goSetId = 0
this . goSetName = ""
} else {
this . goSetName = set . name
}
2022-08-25 15:35:16 +08:00
} ,
jsCookieLife : function ( v ) {
v = parseInt ( v )
if ( isNaN ( v ) ) {
this . actionOptions [ "life" ] = 0
} else {
this . actionOptions [ "life" ] = v
}
} ,
jsCookieMaxFails : function ( v ) {
v = parseInt ( v )
if ( isNaN ( v ) ) {
this . actionOptions [ "maxFails" ] = 0
} else {
this . actionOptions [ "maxFails" ] = v
}
} ,
jsCookieFailBlockTimeout : function ( v ) {
v = parseInt ( v )
if ( isNaN ( v ) ) {
this . actionOptions [ "failBlockTimeout" ] = 0
} else {
this . actionOptions [ "failBlockTimeout" ] = v
}
} ,
2021-07-14 22:45:52 +08:00
} ,
methods : {
add : function ( ) {
this . action = null
2024-01-19 11:13:01 +08:00
this . actionCode = "page"
2021-07-14 22:45:52 +08:00
this . isAdding = true
this . actionOptions = { }
// 动作参数
2021-07-18 15:52:50 +08:00
this . blockTimeout = ""
2023-03-01 19:18:22 +08:00
this . blockTimeoutMax = ""
2021-10-18 20:09:06 +08:00
this . blockScope = "global"
2022-08-25 15:35:16 +08:00
2021-07-14 22:45:52 +08:00
this . captchaLife = ""
2022-01-16 16:54:20 +08:00
this . captchaMaxFails = ""
this . captchaFailBlockTimeout = ""
2022-08-25 15:35:16 +08:00
this . jsCookieLife = ""
this . jsCookieMaxFails = ""
this . jsCookieFailBlockTimeout = ""
2021-07-14 22:45:52 +08:00
this . get302Life = ""
2022-08-25 15:35:16 +08:00
2021-07-14 22:45:52 +08:00
this . post307Life = ""
this . recordIPLevel = "critical"
this . recordIPType = "black"
this . recordIPTimeout = ""
this . recordIPListId = 0
this . recordIPListName = ""
this . tagTags = [ ]
2024-01-20 16:17:28 +08:00
this . pageUseDefault = true
2021-10-25 19:40:28 +08:00
this . pageStatus = 403
this . pageBody = this . defaultPageBody
2023-05-28 17:11:45 +08:00
this . redirectStatus = 307
this . redirectURL = ""
2021-07-14 22:45:52 +08:00
this . goGroupName = ""
this . goGroupId = 0
this . goGroup = null
this . goSetId = 0
this . goSetName = ""
let that = this
this . action = this . vActions . $find ( function ( k , v ) {
return v . code == that . actionCode
} )
2021-07-18 15:52:50 +08:00
// 滚到界面底部
this . scroll ( )
2021-07-14 22:45:52 +08:00
} ,
remove : function ( index ) {
2021-07-18 15:52:50 +08:00
this . isAdding = false
this . editingIndex = - 1
2021-07-14 22:45:52 +08:00
this . configs . $remove ( index )
} ,
update : function ( index , config ) {
if ( this . isAdding && this . editingIndex == index ) {
this . cancel ( )
return
}
this . add ( )
this . isAdding = true
this . editingIndex = index
this . actionCode = config . code
2023-11-18 08:51:50 +08:00
this . action = this . actions . $find ( function ( k , v ) {
return v . code == config . code
} )
2021-07-14 22:45:52 +08:00
switch ( config . code ) {
case "block" :
2021-07-18 15:52:50 +08:00
this . blockTimeout = ""
2023-03-01 19:18:22 +08:00
this . blockTimeoutMax = ""
2021-07-18 15:52:50 +08:00
if ( config . options . timeout != null || config . options . timeout > 0 ) {
this . blockTimeout = config . options . timeout . toString ( )
2021-07-14 22:45:52 +08:00
}
2023-03-01 19:18:22 +08:00
if ( config . options . timeoutMax != null || config . options . timeoutMax > 0 ) {
this . blockTimeoutMax = config . options . timeoutMax . toString ( )
}
2021-10-18 20:09:06 +08:00
if ( config . options . scope != null && config . options . scope . length > 0 ) {
this . blockScope = config . options . scope
} else {
2021-11-16 19:17:08 +08:00
this . blockScope = "global" // 兼容先前版本遗留的默认值
2021-10-18 20:09:06 +08:00
}
2021-07-14 22:45:52 +08:00
break
case "allow" :
break
case "log" :
break
case "captcha" :
this . captchaLife = ""
if ( config . options . life != null || config . options . life > 0 ) {
this . captchaLife = config . options . life . toString ( )
}
2022-01-16 16:54:20 +08:00
this . captchaMaxFails = ""
if ( config . options . maxFails != null || config . options . maxFails > 0 ) {
this . captchaMaxFails = config . options . maxFails . toString ( )
}
this . captchaFailBlockTimeout = ""
if ( config . options . failBlockTimeout != null || config . options . failBlockTimeout > 0 ) {
this . captchaFailBlockTimeout = config . options . failBlockTimeout . toString ( )
}
2021-07-14 22:45:52 +08:00
break
2022-08-25 16:02:26 +08:00
case "js_cookie" :
2022-08-25 15:35:16 +08:00
this . jsCookieLife = ""
if ( config . options . life != null || config . options . life > 0 ) {
this . jsCookieLife = config . options . life . toString ( )
}
this . jsCookieMaxFails = ""
if ( config . options . maxFails != null || config . options . maxFails > 0 ) {
this . jsCookieMaxFails = config . options . maxFails . toString ( )
}
this . jsCookieFailBlockTimeout = ""
if ( config . options . failBlockTimeout != null || config . options . failBlockTimeout > 0 ) {
this . jsCookieFailBlockTimeout = config . options . failBlockTimeout . toString ( )
}
break
2021-07-14 22:45:52 +08:00
case "notify" :
break
case "get_302" :
this . get302Life = ""
if ( config . options . life != null || config . options . life > 0 ) {
this . get302Life = config . options . life . toString ( )
}
break
case "post_307" :
this . post307Life = ""
if ( config . options . life != null || config . options . life > 0 ) {
this . post307Life = config . options . life . toString ( )
}
break ;
case "record_ip" :
if ( config . options != null ) {
this . recordIPLevel = config . options . level
this . recordIPType = config . options . type
if ( config . options . timeout > 0 ) {
this . recordIPTimeout = config . options . timeout . toString ( )
}
2021-07-18 15:52:50 +08:00
let that = this
// VUE需要在函数执行完之后才会调用watch函数, 这样会导致设置的值被覆盖, 所以这里使用setTimeout
setTimeout ( function ( ) {
that . recordIPListId = config . options . ipListId
that . recordIPListName = config . options . ipListName
} )
2021-07-14 22:45:52 +08:00
}
break
case "tag" :
this . tagTags = [ ]
if ( config . options . tags != null ) {
this . tagTags = config . options . tags
}
2021-10-25 19:40:28 +08:00
break
case "page" :
2024-01-20 16:17:28 +08:00
this . pageUseDefault = true
2021-10-25 19:40:28 +08:00
this . pageStatus = 403
this . pageBody = this . defaultPageBody
2024-01-20 16:17:28 +08:00
if ( typeof config . options . useDefault === "boolean" ) {
this . pageUseDefault = config . options . useDefault
} else {
this . pageUseDefault = false
}
2021-10-25 19:40:28 +08:00
if ( config . options . status != null ) {
this . pageStatus = config . options . status
}
if ( config . options . body != null ) {
this . pageBody = config . options . body
}
2023-05-28 17:11:45 +08:00
break
case "redirect" :
this . redirectStatus = 307
this . redirectURL = ""
if ( config . options . status != null ) {
this . redirectStatus = config . options . status
}
if ( config . options . url != null ) {
this . redirectURL = config . options . url
}
2021-07-14 22:45:52 +08:00
break
case "go_group" :
if ( config . options != null ) {
this . goGroupName = config . options . groupName
this . goGroupId = config . options . groupId
this . goGroup = this . vFirewallPolicy . inbound . groups . $find ( function ( k , v ) {
return v . id == config . options . groupId
} )
}
break
case "go_set" :
if ( config . options != null ) {
this . goGroupName = config . options . groupName
this . goGroupId = config . options . groupId
this . goGroup = this . vFirewallPolicy . inbound . groups . $find ( function ( k , v ) {
return v . id == config . options . groupId
} )
2021-07-18 15:52:50 +08:00
// VUE需要在函数执行完之后才会调用watch函数, 这样会导致设置的值被覆盖, 所以这里使用setTimeout
let that = this
setTimeout ( function ( ) {
that . goSetId = config . options . setId
if ( that . goGroup != null ) {
let set = that . goGroup . sets . $find ( function ( k , v ) {
return v . id == config . options . setId
} )
if ( set != null ) {
that . goSetName = set . name
}
2021-07-14 22:45:52 +08:00
}
2021-07-18 15:52:50 +08:00
} )
2021-07-14 22:45:52 +08:00
}
break
}
2021-07-18 15:52:50 +08:00
// 滚到界面底部
this . scroll ( )
2021-07-14 22:45:52 +08:00
} ,
cancel : function ( ) {
this . isAdding = false
this . editingIndex = - 1
} ,
confirm : function ( ) {
if ( this . action == null ) {
return
}
if ( this . actionOptions == null ) {
this . actionOptions = { }
}
// record_ip
if ( this . actionCode == "record_ip" ) {
let timeout = parseInt ( this . recordIPTimeout )
if ( isNaN ( timeout ) ) {
timeout = 0
}
2023-10-15 09:34:07 +08:00
if ( this . recordIPListId < 0 ) {
2021-07-14 22:45:52 +08:00
return
}
2023-10-15 09:34:07 +08:00
// recordIPListId can be 0
2021-07-14 22:45:52 +08:00
this . actionOptions = {
type : this . recordIPType ,
level : this . recordIPLevel ,
timeout : timeout ,
ipListId : this . recordIPListId ,
ipListName : this . recordIPListName
}
} else if ( this . actionCode == "tag" ) { // tag
if ( this . tagTags == null || this . tagTags . length == 0 ) {
return
}
this . actionOptions = {
tags : this . tagTags
}
2021-10-25 19:40:28 +08:00
} else if ( this . actionCode == "page" ) {
let pageStatus = this . pageStatus . toString ( )
if ( ! pageStatus . match ( /^\d{3}$/ ) ) {
pageStatus = 403
} else {
pageStatus = parseInt ( pageStatus )
}
this . actionOptions = {
2024-01-20 16:17:28 +08:00
useDefault : this . pageUseDefault ,
2021-10-25 19:40:28 +08:00
status : pageStatus ,
body : this . pageBody
}
2023-05-28 17:11:45 +08:00
} else if ( this . actionCode == "redirect" ) {
let redirectStatus = this . redirectStatus . toString ( )
if ( ! redirectStatus . match ( /^\d{3}$/ ) ) {
redirectStatus = 307
} else {
redirectStatus = parseInt ( redirectStatus )
}
if ( this . redirectURL . length == 0 ) {
teaweb . warn ( "请输入跳转到URL" )
return
}
this . actionOptions = {
status : redirectStatus ,
url : this . redirectURL
}
2021-07-14 22:45:52 +08:00
} else if ( this . actionCode == "go_group" ) { // go_group
let groupId = this . goGroupId
if ( typeof ( groupId ) == "string" ) {
groupId = parseInt ( groupId )
if ( isNaN ( groupId ) ) {
groupId = 0
}
}
if ( groupId <= 0 ) {
return
}
this . actionOptions = {
2021-07-18 15:52:50 +08:00
groupId : groupId . toString ( ) ,
2021-07-14 22:45:52 +08:00
groupName : this . goGroupName
}
} else if ( this . actionCode == "go_set" ) { // go_set
let groupId = this . goGroupId
if ( typeof ( groupId ) == "string" ) {
groupId = parseInt ( groupId )
if ( isNaN ( groupId ) ) {
groupId = 0
}
}
let setId = this . goSetId
if ( typeof ( setId ) == "string" ) {
setId = parseInt ( setId )
if ( isNaN ( setId ) ) {
setId = 0
}
}
if ( setId <= 0 ) {
return
}
this . actionOptions = {
2021-07-18 15:52:50 +08:00
groupId : groupId . toString ( ) ,
2021-07-14 22:45:52 +08:00
groupName : this . goGroupName ,
2021-07-18 15:52:50 +08:00
setId : setId . toString ( ) ,
2021-07-14 22:45:52 +08:00
setName : this . goSetName
}
}
let options = { }
for ( let k in this . actionOptions ) {
if ( this . actionOptions . hasOwnProperty ( k ) ) {
options [ k ] = this . actionOptions [ k ]
}
}
if ( this . editingIndex > - 1 ) {
this . configs [ this . editingIndex ] = {
id : this . configs [ this . editingIndex ] . id ,
code : this . actionCode ,
name : this . action . name ,
options : options
}
} else {
this . configs . push ( {
id : ( this . id ++ ) ,
code : this . actionCode ,
name : this . action . name ,
options : options
} )
}
this . cancel ( )
} ,
removeRecordIPList : function ( ) {
this . recordIPListId = 0
} ,
selectRecordIPList : function ( ) {
let that = this
teaweb . popup ( "/servers/iplists/selectPopup?type=" + this . recordIPType , {
width : "50em" ,
height : "30em" ,
callback : function ( resp ) {
that . recordIPListId = resp . data . list . id
that . recordIPListName = resp . data . list . name
}
} )
} ,
changeTags : function ( tags ) {
this . tagTags = tags
} ,
loadJS : function ( callback ) {
if ( typeof Sortable != "undefined" ) {
callback ( )
return
}
// 引入js
let jsFile = document . createElement ( "script" )
jsFile . setAttribute ( "src" , "/js/sortable.min.js" )
jsFile . addEventListener ( "load" , function ( ) {
callback ( )
} )
document . head . appendChild ( jsFile )
2021-07-18 15:52:50 +08:00
} ,
scroll : function ( ) {
setTimeout ( function ( ) {
let mainDiv = document . getElementsByClassName ( "main" )
if ( mainDiv . length > 0 ) {
mainDiv [ 0 ] . scrollTo ( 0 , 1000 )
}
} , 10 )
2021-07-14 22:45:52 +08:00
}
} ,
template : ` <div>
< input type = "hidden" name = "actionsJSON" : value = "JSON.stringify(configs)" / >
< div v - show = "configs.length > 0" style = "margin-bottom: 0.5em" id = "actions-box" >
< div v - for = "(config, index) in configs" : data - index = "index" : key = "config.id" class = "ui label small basic" : class = "{blue: index == editingIndex}" style = "margin-bottom: 0.4em" >
2021-10-18 20:09:06 +08:00
{ { config . name } } < span class = "small" > ( { { config . code . toUpperCase ( ) } } ) < / s p a n >
2021-07-14 22:45:52 +08:00
2021-07-18 15:52:50 +08:00
<!-- block -- >
2023-03-01 19:18:22 +08:00
< span v - if = "config.code == 'block' && config.options.timeout > 0" > : 封禁时长 { { config . options . timeout } } < span v - if = "config.options.timeoutMax > config.options.timeout" > - { { config . options . timeoutMax } } < / s p a n > 秒 < / s p a n >
2021-07-18 15:52:50 +08:00
<!-- captcha -- >
2022-05-20 22:07:04 +08:00
< span v - if = "config.code == 'captcha' && config.options.life > 0" > : 有效期 { { config . options . life } } 秒
< span v - if = "config.options.maxFails > 0" > / 最 多 失 败 { { c o n f i g . o p t i o n s . m a x F a i l s } } 次 < / s p a n >
< / s p a n >
2021-07-18 15:52:50 +08:00
2022-08-25 15:35:16 +08:00
<!-- js cookie -- >
< span v - if = "config.code == 'js_cookie' && config.options.life > 0" > : 有效期 { { config . options . life } } 秒
< span v - if = "config.options.maxFails > 0" > / 最 多 失 败 { { c o n f i g . o p t i o n s . m a x F a i l s } } 次 < / s p a n >
< / s p a n >
2021-07-18 15:52:50 +08:00
<!-- get 302 -- >
< span v - if = "config.code == 'get_302' && config.options.life > 0" > : 有效期 { { config . options . life } } 秒 < / s p a n >
<!-- post 307 -- >
< span v - if = "config.code == 'post_307' && config.options.life > 0" > : 有效期 { { config . options . life } } 秒 < / s p a n >
2021-07-14 22:45:52 +08:00
<!-- record _ip -- >
2023-09-13 17:25:03 +08:00
< span v - if = "config.code == 'record_ip'" > : < span : class = "{red: config.options.ipListIsDeleted}" > { { config . options . ipListName } } < / s p a n > < / s p a n >
2021-07-14 22:45:52 +08:00
<!-- tag -- >
< span v - if = "config.code == 'tag'" > : { { config . options . tags . join ( ", " ) } } < / s p a n >
2021-10-25 19:40:28 +08:00
<!-- page -- >
2024-01-20 16:17:28 +08:00
< span v - if = "config.code == 'page'" > : [ { { config . options . status } } ] < span v - if = "config.options.useDefault" > & nbsp ; [ 默认页面 ] < / s p a n > < / s p a n >
2021-10-25 19:40:28 +08:00
2023-05-28 17:22:20 +08:00
<!-- redirect -- >
< span v - if = "config.code == 'redirect'" > : { { config . options . url } } < / s p a n >
2021-07-14 22:45:52 +08:00
<!-- go _group -- >
< span v - if = "config.code == 'go_group'" > : { { config . options . groupName } } < / s p a n >
<!-- go _set -- >
< span v - if = "config.code == 'go_set'" > : { { config . options . groupName } } / { { config . options . setName } } < / s p a n >
2021-10-18 20:09:06 +08:00
<!-- 范围 -- >
< span v - if = "config.options.scope != null && config.options.scope.length > 0" class = "small grey" >
& nbsp ;
2023-07-02 16:24:01 +08:00
< span v - if = "config.options.scope == 'global'" > [ 所有网站 ] < / s p a n >
< span v - if = "config.options.scope == 'service'" > [ 当前网站 ] < / s p a n >
2021-10-18 20:09:06 +08:00
< / s p a n >
2021-07-14 22:45:52 +08:00
<!-- 操作按钮 -- >
& nbsp ; < a href = "" title = "修改" @ click . prevent = "update(index, config)" > < i class = "icon pencil small" > < / i > < / a > & n b s p ; < a h r e f = " " t i t l e = " 删 除 " @ c l i c k . p r e v e n t = " r e m o v e ( i n d e x ) " > < i c l a s s = " i c o n r e m o v e s m a l l " > < / i > < / a > & n b s p ; < a h r e f = " " t i t l e = " 拖 动 改 变 顺 序 " > < i c l a s s = " i c o n b a r s h a n d l e " > < / i > < / a >
< / d i v >
< div class = "ui divider" > < / d i v >
< / d i v >
< div style = "margin-bottom: 0.5em" v - if = "isAdding" >
< table class = "ui table" : class = "{blue: editingIndex > -1}" >
< tr >
< td class = "title" > 动作类型 * < / t d >
< td >
< select class = "ui dropdown auto-width" v - model = "actionCode" >
< option v - for = "action in actions" : value = "action.code" > { { action . name } } ( { { action . code . toUpperCase ( ) } } ) < / o p t i o n >
< / s e l e c t >
< p class = "comment" v - if = "action != null && action.description.length > 0" > { { action . description } } < / p >
< / t d >
< / t r >
<!-- block -- >
2023-03-01 19:18:22 +08:00
< tr v - if = "actionCode == 'block'" >
< td > 封禁范围 < / t d >
< td >
< select class = "ui dropdown auto-width" v - model = "blockScope" >
2023-07-02 16:24:01 +08:00
< option value = "service" > 当前网站 < / o p t i o n >
< option value = "global" > 所有网站 < / o p t i o n >
2023-03-01 19:18:22 +08:00
< / s e l e c t >
2023-04-21 17:51:25 +08:00
< p class = "comment" v - if = "blockScope == 'service'" > 只封禁用户对当前网站的访问 , 其他服务不受影响 。 < / p >
< p class = "comment" v - if = "blockScope =='global'" > 封禁用户对所有网站的访问 。 < / p >
2023-03-01 19:18:22 +08:00
< / t d >
< / t r >
2021-07-14 22:45:52 +08:00
< tr v - if = "actionCode == 'block'" >
2023-03-01 18:59:42 +08:00
< td > 封禁时长 < / t d >
2021-07-14 22:45:52 +08:00
< td >
< div class = "ui input right labeled" >
2022-01-03 11:17:33 +08:00
< input type = "text" style = "width: 5em" maxlength = "9" v - model = "blockTimeout" @ keyup . enter = "confirm()" @ keypress . enter . prevent = "1" / >
2021-07-14 22:45:52 +08:00
< span class = "ui label" > 秒 < / s p a n >
< / d i v >
< / t d >
< / t r >
2021-10-18 20:09:06 +08:00
< tr v - if = "actionCode == 'block'" >
2023-03-01 19:18:22 +08:00
< td > 最大封禁时长 < / t d >
2021-10-18 20:09:06 +08:00
< td >
2023-03-01 19:18:22 +08:00
< div class = "ui input right labeled" >
< input type = "text" style = "width: 5em" maxlength = "9" v - model = "blockTimeoutMax" @ keyup . enter = "confirm()" @ keypress . enter . prevent = "1" / >
< span class = "ui label" > 秒 < / s p a n >
< / d i v >
< p class = "comment" > 选填项 。 如果同时填写了封禁时长和最大封禁时长 , 则会在两者之间随机选择一个数字作为最终的封禁时长 。 < / p >
2021-10-18 20:09:06 +08:00
< / t d >
< / t r >
2021-07-14 22:45:52 +08:00
<!-- captcha -- >
< tr v - if = "actionCode == 'captcha'" >
< td > 有效时间 < / t d >
< td >
< div class = "ui input right labeled" >
2022-01-03 11:17:33 +08:00
< input type = "text" style = "width: 5em" maxlength = "9" v - model = "captchaLife" @ keyup . enter = "confirm()" @ keypress . enter . prevent = "1" / >
2021-07-14 22:45:52 +08:00
< span class = "ui label" > 秒 < / s p a n >
< / d i v >
2022-05-21 20:00:39 +08:00
< p class = "comment" > 验证通过后在这个时间内不再验证 ; 如果为空或者为0表示默认 。 < / p >
2021-07-14 22:45:52 +08:00
< / t d >
< / t r >
2022-01-16 16:54:20 +08:00
< tr v - if = "actionCode == 'captcha'" >
< td > 最多失败次数 < / t d >
< td >
< div class = "ui input right labeled" >
< input type = "text" style = "width: 5em" maxlength = "9" v - model = "captchaMaxFails" @ keyup . enter = "confirm()" @ keypress . enter . prevent = "1" / >
< span class = "ui label" > 次 < / s p a n >
< / d i v >
2023-11-19 15:43:37 +08:00
< p class = "comment" > < span v - if = "captchaMaxFails > 0 && captchaMaxFails < 5" class = "red" > 建议填入一个不小于5的数字 , 以减少误判几率 。 < / s p a n > 允 许 用 户 失 败 尝 试 的 最 多 次 数 , 超 过 这 个 次 数 将 被 自 动 加 入 黑 名 单 ; 如 果 为 空 或 者 为 0 表 示 默 认 。 < / p >
2022-01-16 16:54:20 +08:00
< / t d >
< / t r >
< tr v - if = "actionCode == 'captcha'" >
< td > 失败拦截时间 < / t d >
< td >
< div class = "ui input right labeled" >
< input type = "text" style = "width: 5em" maxlength = "9" v - model = "captchaFailBlockTimeout" @ keyup . enter = "confirm()" @ keypress . enter . prevent = "1" / >
< span class = "ui label" > 秒 < / s p a n >
< / d i v >
2022-05-21 20:00:39 +08:00
< p class = "comment" > 在达到最多失败次数 ( 大于0 ) 时 , 自动拦截的时间 ; 如果为空或者为0表示默认 。 < / p >
2022-01-16 16:54:20 +08:00
< / t d >
< / t r >
2021-07-14 22:45:52 +08:00
2022-08-25 15:35:16 +08:00
<!-- js cookie -- >
< tr v - if = "actionCode == 'js_cookie'" >
< td > 有效时间 < / t d >
< td >
< div class = "ui input right labeled" >
< input type = "text" style = "width: 5em" maxlength = "9" v - model = "jsCookieLife" @ keyup . enter = "confirm()" @ keypress . enter . prevent = "1" / >
< span class = "ui label" > 秒 < / s p a n >
< / d i v >
< p class = "comment" > 验证通过后在这个时间内不再验证 ; 如果为空或者为0表示默认 。 < / p >
< / t d >
< / t r >
< tr v - if = "actionCode == 'js_cookie'" >
< td > 最多失败次数 < / t d >
< td >
< div class = "ui input right labeled" >
< input type = "text" style = "width: 5em" maxlength = "9" v - model = "jsCookieMaxFails" @ keyup . enter = "confirm()" @ keypress . enter . prevent = "1" / >
< span class = "ui label" > 次 < / s p a n >
< / d i v >
< p class = "comment" > 允许用户失败尝试的最多次数 , 超过这个次数将被自动加入黑名单 ; 如果为空或者为0表示默认 。 < / p >
< / t d >
< / t r >
< tr v - if = "actionCode == 'js_cookie'" >
< td > 失败拦截时间 < / t d >
< td >
< div class = "ui input right labeled" >
< input type = "text" style = "width: 5em" maxlength = "9" v - model = "jsCookieFailBlockTimeout" @ keyup . enter = "confirm()" @ keypress . enter . prevent = "1" / >
< span class = "ui label" > 秒 < / s p a n >
< / d i v >
< p class = "comment" > 在达到最多失败次数 ( 大于0 ) 时 , 自动拦截的时间 ; 如果为空或者为0表示默认 。 < / p >
< / t d >
< / t r >
2021-07-14 22:45:52 +08:00
<!-- get _302 -- >
< tr v - if = "actionCode == 'get_302'" >
< td > 有效时间 < / t d >
< td >
< div class = "ui input right labeled" >
2022-01-03 11:17:33 +08:00
< input type = "text" style = "width: 5em" maxlength = "9" v - model = "get302Life" @ keyup . enter = "confirm()" @ keypress . enter . prevent = "1" / >
2021-07-14 22:45:52 +08:00
< span class = "ui label" > 秒 < / s p a n >
< / d i v >
< p class = "comment" > 验证通过后在这个时间内不再验证 。 < / p >
< / t d >
< / t r >
<!-- post _307 -- >
< tr v - if = "actionCode == 'post_307'" >
< td > 有效时间 < / t d >
< td >
< div class = "ui input right labeled" >
2022-01-03 11:17:33 +08:00
< input type = "text" style = "width: 5em" maxlength = "9" v - model = "post307Life" @ keyup . enter = "confirm()" @ keypress . enter . prevent = "1" / >
2021-07-14 22:45:52 +08:00
< span class = "ui label" > 秒 < / s p a n >
< / d i v >
< p class = "comment" > 验证通过后在这个时间内不再验证 。 < / p >
< / t d >
< / t r >
<!-- record _ip -- >
< tr v - if = "actionCode == 'record_ip'" >
< td > IP名单类型 * < / t d >
< td >
< select class = "ui dropdown auto-width" v - model = "recordIPType" >
< option value = "black" > 黑名单 < / o p t i o n >
< option value = "white" > 白名单 < / o p t i o n >
< / s e l e c t >
< / t d >
< / t r >
< tr v - if = "actionCode == 'record_ip'" >
2023-10-15 09:34:07 +08:00
< td > 选择IP名单 < / t d >
2021-07-14 22:45:52 +08:00
< td >
< div v - if = "recordIPListId > 0" class = "ui label basic small" > { { recordIPListName } } < a href = "" @ click . prevent = "removeRecordIPList" > < i class = "icon remove small" > < / i > < / a > < / d i v >
< button type = "button" class = "ui button tiny" @ click . prevent = "selectRecordIPList" > + < / b u t t o n >
< p class = "comment" > 如不选择 , 则自动添加到当前策略的IP名单中 。 < / p >
< / t d >
< / t r >
< tr v - if = "actionCode == 'record_ip'" >
< td > 级别 < / t d >
< td >
< select class = "ui dropdown auto-width" v - model = "recordIPLevel" >
< option v - for = "level in ipListLevels" : value = "level.code" > { { level . name } } < / o p t i o n >
< / s e l e c t >
< / t d >
< / t r >
< tr v - if = "actionCode == 'record_ip'" >
< td > 超时时间 < / t d >
< td >
< div class = "ui input right labeled" >
2022-01-03 11:17:33 +08:00
< input type = "text" style = "width: 6em" maxlength = "9" v - model = "recordIPTimeout" @ keyup . enter = "confirm()" @ keypress . enter . prevent = "1" / >
2021-07-14 22:45:52 +08:00
< span class = "ui label" > 秒 < / s p a n >
< / d i v >
< p class = "comment" > 0 表示不超时 。 < / p >
< / t d >
< / t r >
<!-- tag -- >
< tr v - if = "actionCode == 'tag'" >
< td > 标签 * < / t d >
< td >
< values - box @ change = "changeTags" : values = "tagTags" > < / v a l u e s - b o x >
< / t d >
< / t r >
2021-10-25 19:40:28 +08:00
<!-- page -- >
< tr v - if = "actionCode == 'page'" >
2024-01-20 16:17:28 +08:00
< td > 使用默认提示 < / t d >
< td >
< checkbox v - model = "pageUseDefault" > < / c h e c k b o x >
< / t d >
< / t r >
< tr v - if = "actionCode == 'page' && !pageUseDefault" >
< td class = "color-border" > 状态码 * < / t d >
2021-10-25 19:40:28 +08:00
< td > < input type = "text" style = "width: 4em" maxlength = "3" v - model = "pageStatus" / > < / t d >
< / t r >
2024-01-20 16:17:28 +08:00
< tr v - if = "actionCode == 'page' && !pageUseDefault" >
< td class = "color-border" > 网页内容 < / t d >
2021-10-25 19:40:28 +08:00
< td >
< textarea v - model = "pageBody" > < / t e x t a r e a >
< / t d >
< / t r >
2023-05-28 17:11:45 +08:00
<!-- redirect -- >
< tr v - if = "actionCode == 'redirect'" >
< td > 状态码 * < / t d >
2023-05-28 17:22:20 +08:00
< td >
< select class = "ui dropdown auto-width" v - model = "redirectStatus" >
< option v - for = "status in statusOptions" : value = "status.code" > { { status . code } } { { status . text } } < / o p t i o n >
< / s e l e c t >
< / t d >
2023-05-28 17:11:45 +08:00
< / t r >
< tr v - if = "actionCode == 'redirect'" >
< td > 跳转到URL < / t d >
< td >
< input type = "text" v - model = "redirectURL" / >
< / t d >
< / t r >
2021-07-14 22:45:52 +08:00
<!-- 规则分组 -- >
< tr v - if = "actionCode == 'go_group'" >
< td > 下一个分组 * < / t d >
< td >
< select class = "ui dropdown auto-width" v - model = "goGroupId" >
< option value = "0" > [ 选择分组 ] < / o p t i o n >
2023-07-02 16:24:01 +08:00
< option v - if = "vFirewallPolicy.inbound != null && vFirewallPolicy.inbound.groups != null" v - for = "group in vFirewallPolicy.inbound.groups" : value = "group.id" > 入站 : { { group . name } } < / o p t i o n >
< option v - if = "vGroupType == 'outbound' && vFirewallPolicy.outbound != null && vFirewallPolicy.outbound.groups != null" v - for = "group in vFirewallPolicy.outbound.groups" : value = "group.id" > 出站 : { { group . name } } < / o p t i o n >
2021-07-14 22:45:52 +08:00
< / s e l e c t >
< / t d >
< / t r >
<!-- 规则集 -- >
< tr v - if = "actionCode == 'go_set'" >
< td > 下一个分组 * < / t d >
< td >
< select class = "ui dropdown auto-width" v - model = "goGroupId" >
< option value = "0" > [ 选择分组 ] < / o p t i o n >
2023-07-02 16:24:01 +08:00
< option v - if = "vFirewallPolicy.inbound != null && vFirewallPolicy.inbound.groups != null" v - for = "group in vFirewallPolicy.inbound.groups" : value = "group.id" > 入站 : { { group . name } } < / o p t i o n >
< option v - if = "vGroupType == 'outbound' && vFirewallPolicy.outbound != null && vFirewallPolicy.outbound.groups != null" v - for = "group in vFirewallPolicy.outbound.groups" : value = "group.id" > 出站 : { { group . name } } < / o p t i o n >
2021-07-14 22:45:52 +08:00
< / s e l e c t >
< / t d >
< / t r >
< tr v - if = "actionCode == 'go_set' && goGroup != null" >
< td > 下一个规则集 * < / t d >
< td >
< select class = "ui dropdown auto-width" v - model = "goSetId" >
< option value = "0" > [ 选择规则集 ] < / o p t i o n >
< option v - for = "set in goGroup.sets" : value = "set.id" > { { set . name } } < / o p t i o n >
< / s e l e c t >
< / t d >
< / t r >
< / t a b l e >
< button class = "ui button tiny" type = "button" @ click . prevent = "confirm" > 确定 < / b u t t o n > & n b s p ;
< a href = "" @ click . prevent = "cancel" title = "取消" > < i class = "icon remove small" > < / i > < / a >
< / d i v >
< div v - if = "!isAdding" >
< button class = "ui button tiny" type = "button" @ click . prevent = "add" > + < / b u t t o n >
< / d i v >
2021-07-18 15:52:50 +08:00
< p class = "comment" > 系统总是会先执行记录日志 、 标签等不会修改请求的动作 , 再执行阻止 、 验证码等可能改变请求的动作 。 < / p >
2021-07-14 22:45:52 +08:00
< / d i v > `
} )