mirror of
				https://github.com/TeaOSLab/EdgeAdmin.git
				synced 2025-11-04 21:50:28 +08:00 
			
		
		
		
	[WAF]规则中增加请求Header长度限制和响应Header长度限制
This commit is contained in:
		@@ -1,7 +1,7 @@
 | 
				
			|||||||
package teaconst
 | 
					package teaconst
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
	Version = "0.0.1"
 | 
						Version = "0.0.2"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ProductName   = "Edge Admin"
 | 
						ProductName   = "Edge Admin"
 | 
				
			||||||
	ProcessName   = "edge-admin"
 | 
						ProcessName   = "edge-admin"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,15 +22,16 @@ func (this *CreateRulePopupAction) RunGet(params struct {
 | 
				
			|||||||
}) {
 | 
					}) {
 | 
				
			||||||
	// check points
 | 
						// check points
 | 
				
			||||||
	checkpointList := []maps.Map{}
 | 
						checkpointList := []maps.Map{}
 | 
				
			||||||
	for _, def := range firewallconfigs.AllCheckpoints {
 | 
						for _, checkpoint := range firewallconfigs.AllCheckpoints {
 | 
				
			||||||
		if (params.Type == "inbound" && def.IsRequest) || (params.Type == "outbound" && !def.IsRequest) {
 | 
							if (params.Type == "inbound" && checkpoint.IsRequest) || (params.Type == "outbound" && !checkpoint.IsRequest) {
 | 
				
			||||||
			checkpointList = append(checkpointList, maps.Map{
 | 
								checkpointList = append(checkpointList, maps.Map{
 | 
				
			||||||
				"name":        def.Name,
 | 
									"name":        checkpoint.Name,
 | 
				
			||||||
				"prefix":      def.Prefix,
 | 
									"prefix":      checkpoint.Prefix,
 | 
				
			||||||
				"description": def.Description,
 | 
									"description": checkpoint.Description,
 | 
				
			||||||
				"hasParams":   len(def.Params) > 0,
 | 
									"hasParams":   len(checkpoint.Params) > 0,
 | 
				
			||||||
				"params":      def.Params,
 | 
									"params":      checkpoint.Params,
 | 
				
			||||||
				"options":     def.Options,
 | 
									"options":     checkpoint.Options,
 | 
				
			||||||
 | 
									"isComposed":  checkpoint.IsComposed,
 | 
				
			||||||
			})
 | 
								})
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -89,7 +90,7 @@ func (this *CreateRulePopupAction) RunPost(params struct {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		rule.CheckpointOptions = map[string]interface{}{}
 | 
							rule.CheckpointOptions = map[string]interface{}{}
 | 
				
			||||||
		for _, option := range options {
 | 
							for _, option := range options {
 | 
				
			||||||
			rule.CheckpointOptions[option.GetString("code")] = option.GetString("value")
 | 
								rule.CheckpointOptions[option.GetString("code")] = option.Get("value")
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -86,15 +86,15 @@ func (this *GroupAction) RunGet(params struct {
 | 
				
			|||||||
			"name": set.Name,
 | 
								"name": set.Name,
 | 
				
			||||||
			"rules": lists.Map(set.Rules, func(k int, v interface{}) interface{} {
 | 
								"rules": lists.Map(set.Rules, func(k int, v interface{}) interface{} {
 | 
				
			||||||
				rule := v.(*firewallconfigs.HTTPFirewallRule)
 | 
									rule := v.(*firewallconfigs.HTTPFirewallRule)
 | 
				
			||||||
 | 
					 | 
				
			||||||
				return maps.Map{
 | 
									return maps.Map{
 | 
				
			||||||
					"param":             rule.Param,
 | 
										"param":             rule.Param,
 | 
				
			||||||
					"operator":          rule.Operator,
 | 
										"operator":          rule.Operator,
 | 
				
			||||||
					"value":             rule.Value,
 | 
										"value":             rule.Value,
 | 
				
			||||||
					"isCaseInsensitive": rule.IsCaseInsensitive,
 | 
										"isCaseInsensitive": rule.IsCaseInsensitive,
 | 
				
			||||||
 | 
										"isComposed":        firewallconfigs.CheckCheckpointIsComposed(rule.Prefix()),
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}),
 | 
								}),
 | 
				
			||||||
			"isOn":            set.IsOn,
 | 
								"isOn":          set.IsOn,
 | 
				
			||||||
			"action":        strings.ToUpper(set.Action),
 | 
								"action":        strings.ToUpper(set.Action),
 | 
				
			||||||
			"actionOptions": set.ActionOptions,
 | 
								"actionOptions": set.ActionOptions,
 | 
				
			||||||
			"actionName":    firewallconfigs.FindActionName(set.Action),
 | 
								"actionName":    firewallconfigs.FindActionName(set.Action),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,6 +3,7 @@ package waf
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
 | 
						"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
 | 
				
			||||||
	"github.com/TeaOSLab/EdgeAdmin/internal/web/models"
 | 
						"github.com/TeaOSLab/EdgeAdmin/internal/web/models"
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
 | 
				
			||||||
	"github.com/iwind/TeaGo/maps"
 | 
						"github.com/iwind/TeaGo/maps"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -53,5 +54,20 @@ func (this *PolicyAction) RunGet(params struct {
 | 
				
			|||||||
		"groups":      internalGroups,
 | 
							"groups":      internalGroups,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 正在使用此策略的服务
 | 
				
			||||||
 | 
						listServersResp, err := this.RPC().ServerRPC().FindAllEnabledServersWithHTTPFirewallPolicyId(this.AdminContext(), &pb.FindAllEnabledServersWithHTTPFirewallPolicyIdRequest{FirewallPolicyId: params.FirewallPolicyId})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							this.ErrorPage(err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						serverMaps := []maps.Map{}
 | 
				
			||||||
 | 
						for _, server := range listServersResp.Servers {
 | 
				
			||||||
 | 
							serverMaps = append(serverMaps, maps.Map{
 | 
				
			||||||
 | 
								"id":   server.Id,
 | 
				
			||||||
 | 
								"name": server.Name,
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						this.Data["servers"] = serverMaps
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	this.Show()
 | 
						this.Show()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -39,7 +39,7 @@ Vue.component("http-firewall-rules-box", {
 | 
				
			|||||||
		<input type="hidden" name="rulesJSON" :value="JSON.stringify(rules)"/>
 | 
							<input type="hidden" name="rulesJSON" :value="JSON.stringify(rules)"/>
 | 
				
			||||||
		<div v-if="rules.length > 0">
 | 
							<div v-if="rules.length > 0">
 | 
				
			||||||
			<div v-for="(rule, index) in rules" class="ui label tiny" style="margin-bottom: 0.5em">
 | 
								<div v-for="(rule, index) in rules" class="ui label tiny" style="margin-bottom: 0.5em">
 | 
				
			||||||
				<span>{{rule.param}} <var>{{rule.operator}}</var> {{rule.value}}</span>
 | 
									<span>{{rule.param}} <var v-if="rule.value.length > 0">{{rule.operator}}</var> {{rule.value}}</span>
 | 
				
			||||||
				<a href="" title="修改" @click.prevent="updateRule(index, rule)"><i class="icon pencil small"></i></a>
 | 
									<a href="" title="修改" @click.prevent="updateRule(index, rule)"><i class="icon pencil small"></i></a>
 | 
				
			||||||
				<a href="" title="删除" @click.prevent="removeRule(index)"><i class="icon remove"></i></a>
 | 
									<a href="" title="删除" @click.prevent="removeRule(index)"><i class="icon remove"></i></a>
 | 
				
			||||||
			</div>
 | 
								</div>
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										86
									
								
								web/public/js/components/server/http-firewall-rules.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								web/public/js/components/server/http-firewall-rules.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,86 @@
 | 
				
			|||||||
 | 
					// 通用Header长度
 | 
				
			||||||
 | 
					let defaultGeneralHeaders = ["Cache-Control", "Connection", "Date", "Pragma", "Trailer", "Transfer-Encoding", "Upgrade", "Via", "Warning"]
 | 
				
			||||||
 | 
					Vue.component("http-cond-general-header-length", {
 | 
				
			||||||
 | 
						props: ["v-checkpoint"],
 | 
				
			||||||
 | 
						data: function () {
 | 
				
			||||||
 | 
							let headers = null
 | 
				
			||||||
 | 
							let length = null
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (window.parent.UPDATING_RULE != null) {
 | 
				
			||||||
 | 
								let options = window.parent.UPDATING_RULE.checkpointOptions
 | 
				
			||||||
 | 
								if (options.headers != null && Array.$isArray(options.headers)) {
 | 
				
			||||||
 | 
									headers = options.headers
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if (options.length != null) {
 | 
				
			||||||
 | 
									length = options.length
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (headers == null) {
 | 
				
			||||||
 | 
								headers = defaultGeneralHeaders
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (length == null) {
 | 
				
			||||||
 | 
								length = 128
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							let that = this
 | 
				
			||||||
 | 
							setTimeout(function () {
 | 
				
			||||||
 | 
								that.change()
 | 
				
			||||||
 | 
							}, 100)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return {
 | 
				
			||||||
 | 
								headers: headers,
 | 
				
			||||||
 | 
								length: length
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						watch: {
 | 
				
			||||||
 | 
							length: function (v) {
 | 
				
			||||||
 | 
								let len = parseInt(v)
 | 
				
			||||||
 | 
								if (isNaN(len)) {
 | 
				
			||||||
 | 
									len = 0
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if (len < 0) {
 | 
				
			||||||
 | 
									len = 0
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								this.length = len
 | 
				
			||||||
 | 
								this.change()
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						methods: {
 | 
				
			||||||
 | 
							change: function () {
 | 
				
			||||||
 | 
								this.vCheckpoint.options = [
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										code: "headers",
 | 
				
			||||||
 | 
										value: this.headers
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										code: "length",
 | 
				
			||||||
 | 
										value: this.length
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								]
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						template: `<div>
 | 
				
			||||||
 | 
						<table class="ui table">
 | 
				
			||||||
 | 
							<tr>
 | 
				
			||||||
 | 
								<td class="title">通用Header列表</td>
 | 
				
			||||||
 | 
								<td>
 | 
				
			||||||
 | 
									<values-box :values="headers" :placeholder="'Header'" @change="change"></values-box>
 | 
				
			||||||
 | 
									<p class="comment">需要检查的Header列表。</p>
 | 
				
			||||||
 | 
								</td>
 | 
				
			||||||
 | 
							</tr>
 | 
				
			||||||
 | 
							<tr>
 | 
				
			||||||
 | 
								<td>Header值超出长度</td>
 | 
				
			||||||
 | 
								<td>
 | 
				
			||||||
 | 
									<div class="ui input right labeled">
 | 
				
			||||||
 | 
										<input type="text" name="" style="width: 5em" v-model="length" maxlength="6"/>
 | 
				
			||||||
 | 
										<span class="ui label">字节</span>
 | 
				
			||||||
 | 
									</div>
 | 
				
			||||||
 | 
									<p class="comment">超出此长度认为匹配成功,0表示不限制。</p>
 | 
				
			||||||
 | 
								</td>
 | 
				
			||||||
 | 
							</tr>
 | 
				
			||||||
 | 
						</table>
 | 
				
			||||||
 | 
					</div>`
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
@@ -12,7 +12,10 @@
 | 
				
			|||||||
			<td>
 | 
								<td>
 | 
				
			||||||
				<select name="prefix" class="ui dropdown auto-width" @change="changeCheckpoint()" v-model="rule.checkpointPrefix">
 | 
									<select name="prefix" class="ui dropdown auto-width" @change="changeCheckpoint()" v-model="rule.checkpointPrefix">
 | 
				
			||||||
					<option value="">[选择参数]</option>
 | 
										<option value="">[选择参数]</option>
 | 
				
			||||||
					<option v-for="cp in checkpoints" :value="cp.prefix">{{cp.name}} - [ {{cp.prefix}}]</option>
 | 
										<optgroup label="特殊参数"></optgroup>
 | 
				
			||||||
 | 
										<option v-for="cp in checkpoints" v-if="cp.isComposed" :value="cp.prefix">{{cp.name}} - [ {{cp.prefix}}]</option>
 | 
				
			||||||
 | 
										<optgroup label="通用参数"></optgroup>
 | 
				
			||||||
 | 
										<option v-for="cp in checkpoints" v-if="!cp.isComposed" :value="cp.prefix">{{cp.name}} - [ {{cp.prefix}}]</option>
 | 
				
			||||||
				</select>
 | 
									</select>
 | 
				
			||||||
				<p class="comment" v-if="checkpoint != null"><span class="ui label tiny">${<em style="font-style: normal;">{{checkpoint.prefix}}</em>}</span>{{checkpoint.description}}</p>
 | 
									<p class="comment" v-if="checkpoint != null"><span class="ui label tiny">${<em style="font-style: normal;">{{checkpoint.prefix}}</em>}</span>{{checkpoint.description}}</p>
 | 
				
			||||||
			</td>
 | 
								</td>
 | 
				
			||||||
@@ -27,59 +30,71 @@
 | 
				
			|||||||
			</td>
 | 
								</td>
 | 
				
			||||||
		</tr>
 | 
							</tr>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		<!-- 选项 -->
 | 
							<!-- 组合规则的选项 -->
 | 
				
			||||||
		<tbody v-if="checkpoint != null && checkpoint.options != null && checkpoint.options.length > 0">
 | 
							<tbody v-if="checkpoint != null && checkpoint.isComposed">
 | 
				
			||||||
		<tr v-for="option in checkpoint.options">
 | 
								<tr>
 | 
				
			||||||
			<td>{{option.name}}</td>
 | 
									<td>配置选项</td>
 | 
				
			||||||
			<td>
 | 
									<td>
 | 
				
			||||||
				<div class="ui fields inline" v-if="option.type == 'field'">
 | 
										<http-cond-general-header-length v-if="checkpoint.prefix == 'requestGeneralHeaderLength' || checkpoint.prefix == 'responseGeneralHeaderLength'" :v-checkpoint="checkpoint"></http-cond-general-header-length>
 | 
				
			||||||
					<div class="ui field">
 | 
									</td>
 | 
				
			||||||
						<input type="text" name="" :placeholder="option.placeholder" :maxlength="(option.maxLength > 0)?option.maxLength:1024" :size="option.size" v-model="option.value"/>
 | 
								</tr>
 | 
				
			||||||
					</div>
 | 
					 | 
				
			||||||
					<div class="ui field">
 | 
					 | 
				
			||||||
                        {{option.rightLabel}}
 | 
					 | 
				
			||||||
					</div>
 | 
					 | 
				
			||||||
				</div>
 | 
					 | 
				
			||||||
				<div class="ui fields inline" v-if="option.type == 'options'">
 | 
					 | 
				
			||||||
					<div class="ui field">
 | 
					 | 
				
			||||||
						<select class="ui dropdown" :style="'width:' + option.size + 'em'" name="" v-model="option.value">
 | 
					 | 
				
			||||||
							<option v-for="opt in option.options" :value="opt.value">{{opt.name}}</option>
 | 
					 | 
				
			||||||
						</select>
 | 
					 | 
				
			||||||
					</div>
 | 
					 | 
				
			||||||
					<div class="ui field">
 | 
					 | 
				
			||||||
                        {{option.rightLabel}}
 | 
					 | 
				
			||||||
					</div>
 | 
					 | 
				
			||||||
				</div>
 | 
					 | 
				
			||||||
				<p class="comment" v-if="option.comment != null && option.comment.length > 0">{{option.comment}}</p>
 | 
					 | 
				
			||||||
			</td>
 | 
					 | 
				
			||||||
		</tr>
 | 
					 | 
				
			||||||
		</tbody>
 | 
							</tbody>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		<tr>
 | 
							<!-- 选项 -->
 | 
				
			||||||
			<td>操作符</td>
 | 
							<tbody v-if="checkpoint != null && !checkpoint.isComposed && checkpoint.options != null && checkpoint.options.length > 0">
 | 
				
			||||||
			<td>
 | 
								<tr v-for="option in checkpoint.options">
 | 
				
			||||||
				<select class="ui dropdown" name="operator" style="width:10em" v-model="rule.operator" @change="changeOperator()">
 | 
									<td>{{option.name}}</td>
 | 
				
			||||||
					<option v-for="op in operators" :value="op.code">{{op.name}}</option>
 | 
									<td>
 | 
				
			||||||
				</select>
 | 
										<div class="ui fields inline" v-if="option.type == 'field'">
 | 
				
			||||||
				<p class="comment" v-if="operator != null" v-html="operator.description"></p>
 | 
											<div class="ui field">
 | 
				
			||||||
			</td>
 | 
												<input type="text" name="" :placeholder="option.placeholder" :maxlength="(option.maxLength > 0)?option.maxLength:1024" :size="option.size" v-model="option.value"/>
 | 
				
			||||||
		</tr>
 | 
											</div>
 | 
				
			||||||
		<tr v-if="operator.case != 'none'">
 | 
											<div class="ui field">
 | 
				
			||||||
			<td>开启大小写不敏感</td>
 | 
												{{option.rightLabel}}
 | 
				
			||||||
			<td>
 | 
											</div>
 | 
				
			||||||
				<div class="ui checkbox">
 | 
										</div>
 | 
				
			||||||
					<input name="case" type="checkbox" value="1"  v-model="rule.isCaseInsensitive"/>
 | 
										<div class="ui fields inline" v-if="option.type == 'options'">
 | 
				
			||||||
					<label></label>
 | 
											<div class="ui field">
 | 
				
			||||||
				</div>
 | 
												<select class="ui dropdown" :style="'width:' + option.size + 'em'" name="" v-model="option.value">
 | 
				
			||||||
				<p class="comment">开启后忽略英文字母大小写</p>
 | 
													<option v-for="opt in option.options" :value="opt.value">{{opt.name}}</option>
 | 
				
			||||||
			</td>
 | 
												</select>
 | 
				
			||||||
		</tr>
 | 
											</div>
 | 
				
			||||||
		<tr>
 | 
											<div class="ui field">
 | 
				
			||||||
			<td>对比值</td>
 | 
												{{option.rightLabel}}
 | 
				
			||||||
			<td>
 | 
											</div>
 | 
				
			||||||
				<textarea rows="3" maxlength="4096" name="value" v-model="rule.value"></textarea>
 | 
										</div>
 | 
				
			||||||
			</td>
 | 
										<p class="comment" v-if="option.comment != null && option.comment.length > 0">{{option.comment}}</p>
 | 
				
			||||||
		</tr>
 | 
									</td>
 | 
				
			||||||
 | 
								</tr>
 | 
				
			||||||
 | 
							</tbody>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							<tbody v-show="checkpoint != null && !checkpoint.isComposed">
 | 
				
			||||||
 | 
								<tr>
 | 
				
			||||||
 | 
									<td>操作符</td>
 | 
				
			||||||
 | 
									<td>
 | 
				
			||||||
 | 
										<select class="ui dropdown" name="operator" style="width:10em" v-model="rule.operator" @change="changeOperator()">
 | 
				
			||||||
 | 
											<option v-for="op in operators" :value="op.code">{{op.name}}</option>
 | 
				
			||||||
 | 
										</select>
 | 
				
			||||||
 | 
										<p class="comment" v-if="operator != null" v-html="operator.description"></p>
 | 
				
			||||||
 | 
									</td>
 | 
				
			||||||
 | 
								</tr>
 | 
				
			||||||
 | 
								<tr v-if="operator.case != 'none'">
 | 
				
			||||||
 | 
									<td>开启大小写不敏感</td>
 | 
				
			||||||
 | 
									<td>
 | 
				
			||||||
 | 
										<div class="ui checkbox">
 | 
				
			||||||
 | 
											<input name="case" type="checkbox" value="1"  v-model="rule.isCaseInsensitive"/>
 | 
				
			||||||
 | 
											<label></label>
 | 
				
			||||||
 | 
										</div>
 | 
				
			||||||
 | 
										<p class="comment">开启后忽略英文字母大小写</p>
 | 
				
			||||||
 | 
									</td>
 | 
				
			||||||
 | 
								</tr>
 | 
				
			||||||
 | 
								<tr>
 | 
				
			||||||
 | 
									<td>对比值</td>
 | 
				
			||||||
 | 
									<td>
 | 
				
			||||||
 | 
										<textarea rows="3" maxlength="4096" name="value" v-model="rule.value"></textarea>
 | 
				
			||||||
 | 
									</td>
 | 
				
			||||||
 | 
								</tr>
 | 
				
			||||||
 | 
							</tbody>
 | 
				
			||||||
	</table>
 | 
						</table>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	<submit-btn></submit-btn>
 | 
						<submit-btn></submit-btn>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -48,7 +48,7 @@
 | 
				
			|||||||
			</td>
 | 
								</td>
 | 
				
			||||||
			<td class="rules-box">
 | 
								<td class="rules-box">
 | 
				
			||||||
				<div v-for="rule in set.rules" style="margin-top: 0.4em;margin-bottom:0.4em">
 | 
									<div v-for="rule in set.rules" style="margin-top: 0.4em;margin-bottom:0.4em">
 | 
				
			||||||
					<span class="ui label tiny">{{rule.name}}[{{rule.param}}] <var :class="{dash:rule.isCaseInsensitive}" :title="rule.isCaseInsensitive ? '大小写不敏感':''">{{rule.operator}}</var> {{rule.value}}</span>
 | 
										<span class="ui label tiny">{{rule.name}}[{{rule.param}}] <var :class="{dash:rule.isCaseInsensitive}" :title="rule.isCaseInsensitive ? '大小写不敏感':''" v-if="!rule.isComposed">{{rule.operator}}</var> {{rule.value}}</span>
 | 
				
			||||||
				</div>
 | 
									</div>
 | 
				
			||||||
				<span class="ui disabled" v-if="set.rules.length == 0">暂时还没有规则</span>
 | 
									<span class="ui disabled" v-if="set.rules.length == 0">暂时还没有规则</span>
 | 
				
			||||||
			</td>
 | 
								</td>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,4 +29,12 @@
 | 
				
			|||||||
			</td>
 | 
								</td>
 | 
				
			||||||
		</tr>
 | 
							</tr>
 | 
				
			||||||
	</table>
 | 
						</table>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						<h4>使用此策略的服务</h4>
 | 
				
			||||||
 | 
						<p class="comment" v-if="servers.length == 0">暂时还没有代理服务使用此策略。</p>
 | 
				
			||||||
 | 
						<table class="ui table selectable" v-if="servers.length > 0">
 | 
				
			||||||
 | 
							<tr v-for="server in servers">
 | 
				
			||||||
 | 
								<td>{{server.name}}<link-icon :href="'/servers/server?serverId=' + server.id"></link-icon></td>
 | 
				
			||||||
 | 
							</tr>
 | 
				
			||||||
 | 
						</table>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
		Reference in New Issue
	
	Block a user