Commit bddb689e authored by ibuler's avatar ibuler

merge with exec_cmd

parents 79ecbc83 757f7bee
...@@ -15,6 +15,7 @@ from utils import get_rand_pass ...@@ -15,6 +15,7 @@ from utils import get_rand_pass
import os.path import os.path
API_DIR = os.path.dirname(os.path.abspath(__file__)) API_DIR = os.path.dirname(os.path.abspath(__file__))
ANSIBLE_DIR = os.path.join(API_DIR, 'playbooks') ANSIBLE_DIR = os.path.join(API_DIR, 'playbooks')
...@@ -60,7 +61,7 @@ class MyInventory(object): ...@@ -60,7 +61,7 @@ class MyInventory(object):
[{"hostname": "10.10.10.10", "port": "22", "username": "test", "password": "mypass"}, ...] [{"hostname": "10.10.10.10", "port": "22", "username": "test", "password": "mypass"}, ...]
""" """
self.resource = resource self.resource = resource
self.inventory = Inventory() self.inventory = Inventory(host_list=[])
self.gen_inventory() self.gen_inventory()
def add_group(self, hosts, groupname, groupvars=None): def add_group(self, hosts, groupname, groupvars=None):
...@@ -100,7 +101,7 @@ class MyInventory(object): ...@@ -100,7 +101,7 @@ class MyInventory(object):
add hosts to inventory. add hosts to inventory.
""" """
if isinstance(self.resource, list): if isinstance(self.resource, list):
self.add_group(self.resource, 'my_group') self.add_group(self.resource, 'default_group')
elif isinstance(self.resource, dict): elif isinstance(self.resource, dict):
for groupname, hosts_and_vars in self.resource.iteritems(): for groupname, hosts_and_vars in self.resource.iteritems():
self.add_group(hosts_and_vars.get("hosts"), groupname, hosts_and_vars.get("vars")) self.add_group(hosts_and_vars.get("hosts"), groupname, hosts_and_vars.get("vars"))
...@@ -114,21 +115,23 @@ class Command(MyInventory): ...@@ -114,21 +115,23 @@ class Command(MyInventory):
super(Command, self).__init__(*args, **kwargs) super(Command, self).__init__(*args, **kwargs)
self.results = '' self.results = ''
def run(self, command, module_name="command", timeout=5, forks=10, pattern='*'): def run(self, command, module_name="command", timeout=10, forks=10, group='default_group', pattern='*'):
""" """
run command from andible ad-hoc. run command from andible ad-hoc.
command : 必须是一个需要执行的命令字符串, 比如 command : 必须是一个需要执行的命令字符串, 比如
'uname -a' 'uname -a'
""" """
if module_name not in ["raw", "command", "shell"]: if module_name not in ["raw", "command", "shell"]:
raise CommandValueError("module_name", raise CommandValueError("module_name",
"module_name must be of the 'raw, command, shell'") "module_name must be of the 'raw, command, shell'")
hoc = Runner(module_name=module_name, hoc = Runner(module_name=module_name,
module_args=command, module_args=command,
timeout=timeout, timeout=timeout,
inventory=self.inventory, inventory=self.inventory,
subset=group,
pattern=pattern, pattern=pattern,
forks=forks forks=forks,
) )
self.results = hoc.run() self.results = hoc.run()
...@@ -202,7 +205,7 @@ class Tasks(Command): ...@@ -202,7 +205,7 @@ class Tasks(Command):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(Tasks, self).__init__(*args, **kwargs) super(Tasks, self).__init__(*args, **kwargs)
def __run(self, module_args, module_name="command", timeout=5, forks=10, group='my_group'): def __run(self, module_args, module_name="command", timeout=5, forks=10, group='default_group', pattern='*'):
""" """
run command from andible ad-hoc. run command from andible ad-hoc.
command : 必须是一个需要执行的命令字符串, 比如 command : 必须是一个需要执行的命令字符串, 比如
...@@ -213,7 +216,8 @@ class Tasks(Command): ...@@ -213,7 +216,8 @@ class Tasks(Command):
timeout=timeout, timeout=timeout,
inventory=self.inventory, inventory=self.inventory,
subset=group, subset=group,
forks=forks pattern=pattern,
forks=forks,
) )
self.results = hoc.run() self.results = hoc.run()
...@@ -424,7 +428,6 @@ class MyPlaybook(MyInventory): ...@@ -424,7 +428,6 @@ class MyPlaybook(MyInventory):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(MyPlaybook, self).__init__(*args, **kwargs) super(MyPlaybook, self).__init__(*args, **kwargs)
def run(self, playbook_relational_path, extra_vars=None): def run(self, playbook_relational_path, extra_vars=None):
""" """
run ansible playbook, run ansible playbook,
...@@ -463,7 +466,6 @@ class App(MyPlaybook): ...@@ -463,7 +466,6 @@ class App(MyPlaybook):
if __name__ == "__main__": if __name__ == "__main__":
pass
# resource = { # resource = {
# "group1": { # "group1": {
...@@ -471,8 +473,10 @@ if __name__ == "__main__": ...@@ -471,8 +473,10 @@ if __name__ == "__main__":
# "vars" : {"var1": "value1", "var2": "value2"}, # "vars" : {"var1": "value1", "var2": "value2"},
# }, # },
# } # }
# command = Command(resource)
# print command.run("who", group="group1") resource = [{"hostname": "127.0.0.1", "port": "22", "username": "yumaojun", "password": "yusky0902"}]
command = Command(resource)
print command.run("who")
# resource = [{"hostname": "192.168.10.148", "port": "22", "username": "root", "password": "xxx"}] # resource = [{"hostname": "192.168.10.148", "port": "22", "username": "root", "password": "xxx"}]
# task = Tasks(resource) # task = Tasks(resource)
......
...@@ -39,7 +39,6 @@ class PermRule(models.Model): ...@@ -39,7 +39,6 @@ class PermRule(models.Model):
user = models.ManyToManyField(User, related_name='perm_rule') user = models.ManyToManyField(User, related_name='perm_rule')
user_group = models.ManyToManyField(UserGroup, related_name='perm_rule') user_group = models.ManyToManyField(UserGroup, related_name='perm_rule')
role = models.ManyToManyField(PermRole, related_name='perm_rule') role = models.ManyToManyField(PermRole, related_name='perm_rule')
is_secret_key = models.BooleanField()
def __unicode__(self): def __unicode__(self):
return self.name return self.name
\ No newline at end of file
...@@ -89,7 +89,7 @@ def perm_user_api(perm_info): ...@@ -89,7 +89,7 @@ def perm_user_api(perm_info):
the_new_users = ','.join(new_username) the_new_users = ','.join(new_username)
the_del_users = ','.join(del_username) the_del_users = ','.join(del_username)
playbook = get_playbook(os.path.join(BASE_DIR, 'playbook', 'user_perm.yaml'), playbook = get_playbook(os.path.join(BASE_DIR, 'keys/../playbook', 'user_perm.yaml'),
{'the_new_group': 'new', 'the_del_group': 'del', {'the_new_group': 'new', 'the_del_group': 'del',
'the_new_users': the_new_users, 'the_del_users': the_del_users, 'the_new_users': the_new_users, 'the_del_users': the_del_users,
'KEY_DIR': os.path.join(SSH_KEY_DIR, 'sysuser')}) 'KEY_DIR': os.path.join(SSH_KEY_DIR, 'sysuser')})
......
...@@ -10,12 +10,13 @@ from juser.user_api import gen_ssh_key ...@@ -10,12 +10,13 @@ from juser.user_api import gen_ssh_key
from juser.models import User, UserGroup from juser.models import User, UserGroup
from jasset.models import Asset, AssetGroup from jasset.models import Asset, AssetGroup
from jperm.models import PermRole, PermRule from jperm.models import PermRole, PermRule
from jumpserver.models import Setting
from jperm.utils import updates_dict, gen_keys, get_rand_pass from jperm.utils import updates_dict, gen_keys, get_rand_pass
from jperm.ansible_api import Tasks from jperm.ansible_api import Tasks
from jperm.perm_api import get_role_info from jperm.perm_api import get_role_info
from jumpserver.api import my_render, get_object from jumpserver.api import my_render, get_object, CRYPTOR
@require_role('admin') @require_role('admin')
...@@ -61,7 +62,7 @@ def perm_rule_detail(request): ...@@ -61,7 +62,7 @@ def perm_rule_detail(request):
assets = asset_obj assets = asset_obj
return my_render('jperm/perm_rule_detail.html', locals(), request) return my_render('jperm/perm_rule_detail.html', locals(), request)
def perm_rule_add(request): def perm_rule_add(request):
""" """
...@@ -114,10 +115,20 @@ def perm_rule_add(request): ...@@ -114,10 +115,20 @@ def perm_rule_add(request):
rule.asset = assets_obj rule.asset = assets_obj
rule.asset_group = asset_groups_obj rule.asset_group = asset_groups_obj
rule.role = roles_obj rule.role = roles_obj
rule.is_secret_key = bool(rule_ssh_key)
rule.save() rule.save()
return HttpResponse(u"添加授权规则:%s" % rule.name) msg = u"添加授权规则:%s" % rule.name
# 渲染数据
header_title, path1, path2 = "授权规则", "规则管理", "查看规则"
rules_list = PermRule.objects.all()
# TODO: 搜索和分页
keyword = request.GET.get('search', '')
if keyword:
rules_list = rules_list.filter(Q(name=keyword))
rules_list, p, rules, page_range, current_page, show_first, show_end = pages(rules_list, request)
return my_render('jperm/perm_rule_list.html', locals(), request)
@require_role('admin') @require_role('admin')
...@@ -132,15 +143,20 @@ def perm_rule_edit(request): ...@@ -132,15 +143,20 @@ def perm_rule_edit(request):
rule_id = request.GET.get("id") rule_id = request.GET.get("id")
rule = PermRule.objects.get(id=rule_id) rule = PermRule.objects.get(id=rule_id)
if request.method == 'GET' and rule_id: if request.method == 'GET' and rule_id:
# 渲染数据, 获取所的rule对象 # 渲染数据, 获取所的rule对象
rule_comment = rule.comment rule_comment = rule.comment
users = rule.user.all() users_select = rule.user.all()
user_groups = rule.user_group.all() user_groups_select = rule.user_group.all()
assets = rule.asset.all() assets_select = rule.asset.all()
asset_groups = rule.asset_group.all() asset_groups_select = rule.asset_group.all()
roles = rule.role.all() roles_select = rule.role.all()
users = User.objects.all()
user_groups = UserGroup.objects.all()
assets = Asset.objects.all()
asset_groups = AssetGroup.objects.all()
roles = PermRole.objects.all()
return my_render('jperm/perm_rule_edit.html', locals(), request) return my_render('jperm/perm_rule_edit.html', locals(), request)
...@@ -177,12 +193,20 @@ def perm_rule_edit(request): ...@@ -177,12 +193,20 @@ def perm_rule_edit(request):
rule.role = roles_obj rule.role = roles_obj
rule.name = rule_name rule.name = rule_name
rule.comment = rule.comment rule.comment = rule.comment
print rule, rule.name
rule.save() rule.save()
return HttpResponse(u"更新授权规则:%s" % rule.name)
msg = u"更新授权规则:%s" % rule.name
# 渲染数据
header_title, path1, path2 = "授权规则", "规则管理", "查看规则"
rules_list = PermRule.objects.all()
# TODO: 搜索和分页
keyword = request.GET.get('search', '')
if keyword:
rules_list = rules_list.filter(Q(name=keyword))
rules_list, p, rules, page_range, current_page, show_first, show_end = pages(rules_list, request)
return my_render('jperm/perm_rule_list.html', locals(), request)
@require_role('admin') @require_role('admin')
...@@ -242,12 +266,24 @@ def perm_role_add(request): ...@@ -242,12 +266,24 @@ def perm_role_add(request):
name = request.POST.get("role_name") name = request.POST.get("role_name")
comment = request.POST.get("role_comment") comment = request.POST.get("role_comment")
password = request.POST.get("role_password") password = request.POST.get("role_password")
encrypt_pass = CRYPTOR.encrypt(password)
# 生成随机密码,生成秘钥对 # 生成随机密码,生成秘钥对
key_path = gen_keys() key_path = gen_keys()
role = PermRole(name=name, comment=comment, password=password, key_path=key_path) role = PermRole(name=name, comment=comment, password=encrypt_pass, key_path=key_path)
role.save() role.save()
return HttpResponse(u"添加角色: %s" % name)
msg = u"添加角色: %s" % name
# 渲染 刷新数据
header_title, path1, path2 = "系统角色", "角色管理", "查看角色"
roles_list = PermRole.objects.all()
# TODO: 搜索和分页
keyword = request.GET.get('search', '')
if keyword:
roles_list = roles_list.filter(Q(name=keyword))
roles_list, p, roles, page_range, current_page, show_first, show_end = pages(roles_list, request)
return my_render('jperm/perm_role_list.html', locals(), request)
else: else:
return HttpResponse(u"不支持该操作") return HttpResponse(u"不支持该操作")
...@@ -313,6 +349,7 @@ def perm_role_edit(request): ...@@ -313,6 +349,7 @@ def perm_role_edit(request):
# 渲染数据 # 渲染数据
role_id = request.GET.get("id") role_id = request.GET.get("id")
role = PermRole.objects.get(id=role_id) role = PermRole.objects.get(id=role_id)
role_pass = CRYPTOR.decrypt(role.password)
if request.method == "GET": if request.method == "GET":
return my_render('jperm/perm_role_edit.html', locals(), request) return my_render('jperm/perm_role_edit.html', locals(), request)
...@@ -320,15 +357,27 @@ def perm_role_edit(request): ...@@ -320,15 +357,27 @@ def perm_role_edit(request):
# 获取 POST 数据 # 获取 POST 数据
role_name = request.POST.get("role_name") role_name = request.POST.get("role_name")
role_password = request.POST.get("role_password") role_password = request.POST.get("role_password")
encrypt_role_pass = CRYPTOR.encrypt(role_password)
role_comment = request.POST.get("role_comment") role_comment = request.POST.get("role_comment")
# 写入数据库 # 写入数据库
role.name = role_name role.name = role_name
role.password = role_password role.password = encrypt_role_pass
role.comment = role_comment role.comment = role_comment
role.save() role.save()
return HttpResponse(u"更新系统角色: %s" % role.name) msg = u"更新系统角色: %s" % role.name
# 渲染 刷新数据
header_title, path1, path2 = "系统角色", "角色管理", "查看角色"
roles_list = PermRole.objects.all()
# TODO: 搜索和分页
keyword = request.GET.get('search', '')
if keyword:
roles_list = roles_list.filter(Q(name=keyword))
roles_list, p, roles, page_range, current_page, show_first, show_end = pages(roles_list, request)
return my_render('jperm/perm_role_list.html', locals(), request)
...@@ -364,10 +413,20 @@ def perm_role_push(request): ...@@ -364,10 +413,20 @@ def perm_role_push(request):
calc_assets = set(assets_obj) | set(group_assets_obj) calc_assets = set(assets_obj) | set(group_assets_obj)
# 生成Inventory # 生成Inventory
push_resource = [{"hostname": asset.ip, push_resource = []
"port": asset.port, for asset in calc_assets:
"username": asset.username, if asset.use_default_auth:
"password": asset.password} for asset in calc_assets] username = Setting.default_user
password = Setting.default_password
port = Setting.default_port
else:
username = asset.username
password = asset.password
port = asset.port
push_resource.append({"hostname": asset.ip,
"port": port,
"username": username,
"password": password})
# 获取角色的推送方式,以及推送需要的信息 # 获取角色的推送方式,以及推送需要的信息
roles_obj = [PermRole.objects.get(name=role_name) for role_name in role_names] roles_obj = [PermRole.objects.get(name=role_name) for role_name in role_names]
......
...@@ -17,8 +17,8 @@ config = ConfigParser.ConfigParser() ...@@ -17,8 +17,8 @@ config = ConfigParser.ConfigParser()
BASE_DIR = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) BASE_DIR = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
config.read(os.path.join(BASE_DIR, 'jumpserver.conf')) config.read(os.path.join(BASE_DIR, 'jumpserver.conf'))
KEY_DIR = os.path.join(BASE_DIR, 'keys/role_keys')
KEY_DIR = os.path.join(BASE_DIR, 'keys')
DB_HOST = config.get('db', 'host') DB_HOST = config.get('db', 'host')
DB_PORT = config.getint('db', 'port') DB_PORT = config.getint('db', 'port')
...@@ -37,7 +37,7 @@ EMAIL_TIMEOUT = 5 ...@@ -37,7 +37,7 @@ EMAIL_TIMEOUT = 5
# ======== Log ========== # ======== Log ==========
LOG_DIR = os.path.join(BASE_DIR, 'logs') LOG_DIR = os.path.join(BASE_DIR, 'logs')
SSH_KEY_DIR = os.path.join(BASE_DIR, 'role_keys') SSH_KEY_DIR = os.path.join(BASE_DIR, 'keys/role_keys')
KEY = config.get('base', 'key') KEY = config.get('base', 'key')
URL = config.get('base', 'url') URL = config.get('base', 'url')
LOG_LEVEL = config.get('base', 'log') LOG_LEVEL = config.get('base', 'log')
......
...@@ -267,7 +267,7 @@ def setting(request): ...@@ -267,7 +267,7 @@ def setting(request):
if '' in [username, port] and ('' in password or '' in private_key): if '' in [username, port] and ('' in password or '' in private_key):
return HttpResponse('所填内容不能为空, 且密码和私钥填一个') return HttpResponse('所填内容不能为空, 且密码和私钥填一个')
else: else:
private_key_path = os.path.join(BASE_DIR, 'role_keys', 'default', 'default_private_key.pem') private_key_path = os.path.join(BASE_DIR, 'keys/role_keys', 'default', 'default_private_key.pem')
if private_key: if private_key:
with open(private_key_path, 'w') as f: with open(private_key_path, 'w') as f:
f.write(private_key) f.write(private_key)
......
...@@ -43,7 +43,7 @@ ...@@ -43,7 +43,7 @@
<div class="form-group"> <div class="form-group">
<label for="role_password_label" class="col-sm-2 control-label">角色密码<span class="red-fonts">*</span></label> <label for="role_password_label" class="col-sm-2 control-label">角色密码<span class="red-fonts">*</span></label>
<div class="col-sm-8"> <div class="col-sm-8">
<input id="role_password" name="role_password" type="password" class="form-control" value="{{ role.password }}"> <input id="role_password" name="role_password" type="password" class="form-control" value="{{ role_pass }}">
</div> </div>
</div> </div>
<div class="hr-line-dashed"></div> <div class="hr-line-dashed"></div>
......
...@@ -7,6 +7,14 @@ ...@@ -7,6 +7,14 @@
<div class="row"> <div class="row">
<div class="col-lg-10"> <div class="col-lg-10">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div>
{% if error %}
<div class="alert alert-warning text-center">{{ error }}</div>
{% endif %}
{% if msg %}
<div class="alert alert-success text-center">{{ msg }}</div>
{% endif %}
</div>
<div class="ibox-title"> <div class="ibox-title">
<h5> 所有系统角色</h5> <h5> 所有系统角色</h5>
<div class="ibox-tools"> <div class="ibox-tools">
......
...@@ -95,18 +95,6 @@ ...@@ -95,18 +95,6 @@
</div> </div>
</div> </div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="j_group" class="col-sm-2 control-label">使用秘钥</label>
<div class="col-sm-1">
<div class="radio i-checks">
<label>
<input type="checkbox" value="1" id="use_publicKey" name="use_publicKey">
</label>
</div>
</div>
</div>
<div class="hr-line-dashed"></div> <div class="hr-line-dashed"></div>
<div class="form-group"> <div class="form-group">
<label for="comment" class="col-sm-2 control-label">备注</label> <label for="comment" class="col-sm-2 control-label">备注</label>
......
...@@ -45,7 +45,7 @@ ...@@ -45,7 +45,7 @@
<div class="col-sm-8"> <div class="col-sm-8">
<select name="user" data-placeholder="用户名" class="chosen-select form-control m-b" multiple tabindex="2"> <select name="user" data-placeholder="用户名" class="chosen-select form-control m-b" multiple tabindex="2">
{% for user in users %} {% for user in users %}
<option value="{{ user.name }}">{{ user.name }}</option> <option value="{{ user.name }}" {% if user in users_select %} selected {% endif %}>{{ user.name }}</option>
{% endfor %} {% endfor %}
</select> </select>
</div> </div>
...@@ -56,7 +56,7 @@ ...@@ -56,7 +56,7 @@
<div class="col-sm-8"> <div class="col-sm-8">
<select name="usergroup" data-placeholder="请选择用户组" class="chosen-select form-control m-b" multiple tabindex="2"> <select name="usergroup" data-placeholder="请选择用户组" class="chosen-select form-control m-b" multiple tabindex="2">
{% for user_group in user_groups %} {% for user_group in user_groups %}
<option value="{{ user_group.name }}">{{ user_group.name }}</option> <option value="{{ user_group.name }}"{% if user_group in users_groups_select %} selected {% endif %}>{{ user_group.name }}</option>
{% endfor %} {% endfor %}
</select> </select>
</div> </div>
...@@ -67,7 +67,7 @@ ...@@ -67,7 +67,7 @@
<div class="col-sm-8"> <div class="col-sm-8">
<select name="asset" data-placeholder="请选择资产" class="chosen-select form-control m-b" multiple tabindex="2"> <select name="asset" data-placeholder="请选择资产" class="chosen-select form-control m-b" multiple tabindex="2">
{% for asset in assets %} {% for asset in assets %}
<option value="{{ asset.ip }}">{{ asset.ip }}</option> <option value="{{ asset.ip }}"{% if asset in assets_select %} selected {% endif %}>{{ asset.ip }}</option>
{% endfor %} {% endfor %}
</select> </select>
</div> </div>
...@@ -78,7 +78,7 @@ ...@@ -78,7 +78,7 @@
<div class="col-sm-8"> <div class="col-sm-8">
<select name="assetgroup" data-placeholder="请选择资产组" class="chosen-select form-control m-b" multiple tabindex="2"> <select name="assetgroup" data-placeholder="请选择资产组" class="chosen-select form-control m-b" multiple tabindex="2">
{% for asset_group in asset_groups %} {% for asset_group in asset_groups %}
<option value="{{ asset_group.name }}">{{ asset_group.name }}</option> <option value="{{ asset_group.name }}"{% if asset_group in asset_groups_select %} selected {% endif %}>{{ asset_group.name }}</option>
{% endfor %} {% endfor %}
</select> </select>
</div> </div>
...@@ -89,24 +89,12 @@ ...@@ -89,24 +89,12 @@
<div class="col-sm-8"> <div class="col-sm-8">
<select name="role" data-placeholder="请选择角色" class="chosen-select form-control m-b" multiple tabindex="2"> <select name="role" data-placeholder="请选择角色" class="chosen-select form-control m-b" multiple tabindex="2">
{% for role in roles %} {% for role in roles %}
<option value="{{ role.name }}">{{ role.name }}</option> <option value="{{ role.name }}"{% if role in roles_select %} selected {% endif %}>{{ role.name }}</option>
{% endfor %} {% endfor %}
</select> </select>
</div> </div>
</div> </div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="j_group" class="col-sm-2 control-label">使用秘钥</label>
<div class="col-sm-1">
<div class="radio i-checks">
<label>
<input type="checkbox" value="1" id="use_publicKey" name="use_publicKey">
</label>
</div>
</div>
</div>
<div class="hr-line-dashed"></div> <div class="hr-line-dashed"></div>
<div class="form-group"> <div class="form-group">
<label for="comment" class="col-sm-2 control-label">备注</label> <label for="comment" class="col-sm-2 control-label">备注</label>
......
...@@ -3,10 +3,20 @@ ...@@ -3,10 +3,20 @@
{% block content %} {% block content %}
{% include 'nav_cat_bar.html' %} {% include 'nav_cat_bar.html' %}
<div class="wrapper wrapper-content animated fadeInRight"> <div class="wrapper wrapper-content animated fadeInRight">
<div class="row"> <div class="row">
<div class="col-lg-10"> <div class="col-lg-10">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div>
{% if error %}
<div class="alert alert-warning text-center">{{ error }}</div>
{% endif %}
{% if msg %}
<div class="alert alert-success text-center">{{ msg }}</div>
{% endif %}
</div>
<div class="ibox-title"> <div class="ibox-title">
<h5> 所有规则</h5> <h5> 所有规则</h5>
<div class="ibox-tools"> <div class="ibox-tools">
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment