mirror of https://github.com/jumpserver/jumpserver
角色key问题修复
parent
a7db713b1e
commit
6fe6342ca4
|
@ -6,6 +6,7 @@ import os.path
|
||||||
from paramiko.rsakey import RSAKey
|
from paramiko.rsakey import RSAKey
|
||||||
from jumpserver.api import mkdir
|
from jumpserver.api import mkdir
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
|
from jumpserver.api import CRYPTOR
|
||||||
|
|
||||||
from jumpserver.settings import KEY_DIR
|
from jumpserver.settings import KEY_DIR
|
||||||
|
|
||||||
|
@ -14,18 +15,7 @@ def get_rand_pass():
|
||||||
"""
|
"""
|
||||||
get a reandom password.
|
get a reandom password.
|
||||||
"""
|
"""
|
||||||
lower = [chr(i) for i in range(97,123)]
|
CRYPTOR.gen_rand_pass(20)
|
||||||
upper = [chr(i).upper() for i in range(97,123)]
|
|
||||||
digit = [str(i) for i in range(10)]
|
|
||||||
password_pool = []
|
|
||||||
password_pool.extend(lower)
|
|
||||||
password_pool.extend(upper)
|
|
||||||
password_pool.extend(digit)
|
|
||||||
pass_list = [random.choice(password_pool) for i in range(1,14)]
|
|
||||||
pass_list.insert(random.choice(range(1,14)), '@')
|
|
||||||
pass_list.insert(random.choice(range(1,14)), random.choice(digit))
|
|
||||||
password = ''.join(pass_list)
|
|
||||||
return password
|
|
||||||
|
|
||||||
|
|
||||||
def updates_dict(*args):
|
def updates_dict(*args):
|
||||||
|
@ -38,7 +28,7 @@ def updates_dict(*args):
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def gen_keys():
|
def gen_keys(gen=True):
|
||||||
"""
|
"""
|
||||||
在KEY_DIR下创建一个 uuid命名的目录,
|
在KEY_DIR下创建一个 uuid命名的目录,
|
||||||
并且在该目录下 生产一对秘钥
|
并且在该目录下 生产一对秘钥
|
||||||
|
@ -47,6 +37,8 @@ def gen_keys():
|
||||||
key_basename = "key-" + uuid4().hex
|
key_basename = "key-" + uuid4().hex
|
||||||
key_path_dir = os.path.join(KEY_DIR, 'role_key', key_basename)
|
key_path_dir = os.path.join(KEY_DIR, 'role_key', key_basename)
|
||||||
mkdir(key_path_dir, mode=0755)
|
mkdir(key_path_dir, mode=0755)
|
||||||
|
if not gen:
|
||||||
|
return key_path_dir
|
||||||
key = RSAKey.generate(2048)
|
key = RSAKey.generate(2048)
|
||||||
private_key = os.path.join(key_path_dir, 'id_rsa')
|
private_key = os.path.join(key_path_dir, 'id_rsa')
|
||||||
public_key = os.path.join(key_path_dir, 'id_rsa.pub')
|
public_key = os.path.join(key_path_dir, 'id_rsa.pub')
|
||||||
|
|
|
@ -255,36 +255,41 @@ def perm_role_add(request):
|
||||||
# 渲染数据
|
# 渲染数据
|
||||||
header_title, path1, path2 = "系统角色", "角色管理", "添加角色"
|
header_title, path1, path2 = "系统角色", "角色管理", "添加角色"
|
||||||
|
|
||||||
if request.method == "GET":
|
if request.method == "POST":
|
||||||
default_password = get_rand_pass()
|
|
||||||
return my_render('jperm/perm_role_add.html', locals(), request)
|
|
||||||
|
|
||||||
elif request.method == "POST":
|
|
||||||
# 获取参数: name, comment
|
# 获取参数: name, comment
|
||||||
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_content = request.POST.get("role_key", "")
|
||||||
# 生成随机密码,生成秘钥对
|
try:
|
||||||
|
if get_object(PermRole, name=name):
|
||||||
|
raise ServerError('已经存在该用户 %s' % name)
|
||||||
|
|
||||||
key_path = gen_keys()
|
if '' == password and '' == key_content:
|
||||||
role = PermRole(name=name, comment=comment, password=encrypt_pass, key_path=key_path)
|
raise ServerError('账号和密码必填一项')
|
||||||
role.save()
|
if password:
|
||||||
|
encrypt_pass = CRYPTOR.encrypt(password)
|
||||||
msg = u"添加角色: %s" % name
|
else:
|
||||||
# 渲染 刷新数据
|
encrypt_pass = CRYPTOR.encrypt(CRYPTOR.gen_rand_pass(20))
|
||||||
header_title, path1, path2 = "系统角色", "角色管理", "查看角色"
|
# 生成随机密码,生成秘钥对
|
||||||
roles_list = PermRole.objects.all()
|
if key_content:
|
||||||
# TODO: 搜索和分页
|
key_path = gen_keys(gen=False)
|
||||||
keyword = request.GET.get('search', '')
|
with open(os.path.join(key_path, 'id_rsa'), 'w') as f:
|
||||||
if keyword:
|
f.write(key_content)
|
||||||
roles_list = roles_list.filter(Q(name=keyword))
|
else:
|
||||||
|
key_path = gen_keys()
|
||||||
roles_list, p, roles, page_range, current_page, show_first, show_end = pages(roles_list, request)
|
logger.debug('generate role key: %s' % key_path)
|
||||||
return my_render('jperm/perm_role_list.html', locals(), request)
|
role = PermRole(name=name, comment=comment, password=encrypt_pass, key_path=key_path)
|
||||||
|
role.save()
|
||||||
|
msg = u"添加角色: %s" % name
|
||||||
|
return HttpResponseRedirect('/perm/role/')
|
||||||
|
except ServerError, e:
|
||||||
|
error = e
|
||||||
else:
|
else:
|
||||||
return HttpResponse(u"不支持该操作")
|
return HttpResponse(u"不支持该操作")
|
||||||
|
|
||||||
|
return my_render('jperm/perm_role_add.html', locals(), request)
|
||||||
|
|
||||||
|
|
||||||
@require_role('admin')
|
@require_role('admin')
|
||||||
def perm_role_delete(request):
|
def perm_role_delete(request):
|
||||||
|
@ -346,36 +351,37 @@ 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 = get_object(PermRole, id=role_id)
|
||||||
role_pass = CRYPTOR.decrypt(role.password)
|
|
||||||
if request.method == "GET":
|
|
||||||
return my_render('jperm/perm_role_edit.html', locals(), request)
|
|
||||||
|
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
# 获取 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")
|
||||||
|
key_content = request.POST.get("role_key", "")
|
||||||
|
try:
|
||||||
|
if not role:
|
||||||
|
raise ServerError('角色用户不能存在')
|
||||||
|
|
||||||
# 写入数据库
|
if role_password:
|
||||||
role.name = role_name
|
encrypt_pass = CRYPTOR.encrypt(role_password)
|
||||||
role.password = encrypt_role_pass
|
role.password = encrypt_pass
|
||||||
role.comment = role_comment
|
# 生成随机密码,生成秘钥对
|
||||||
|
if key_content:
|
||||||
|
with open(os.path.join(role.key_path, 'id_rsa'), 'w') as f:
|
||||||
|
f.write(key_content)
|
||||||
|
logger.debug('Recreate role key: %s' % role.key_path)
|
||||||
|
# 写入数据库
|
||||||
|
role.name = role_name
|
||||||
|
role.comment = role_comment
|
||||||
|
|
||||||
role.save()
|
role.save()
|
||||||
msg = u"更新系统角色: %s" % role.name
|
msg = u"更新系统角色: %s" % role.name
|
||||||
|
return HttpResponseRedirect('/jperm/role/')
|
||||||
|
except ServerError, e:
|
||||||
|
error = e
|
||||||
|
|
||||||
# 渲染 刷新数据
|
return my_render('jperm/perm_role_edit.html', locals(), request)
|
||||||
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)
|
|
||||||
|
|
||||||
|
|
||||||
@require_role('admin')
|
@require_role('admin')
|
||||||
|
|
|
@ -48,6 +48,9 @@ def set_log(level):
|
||||||
|
|
||||||
|
|
||||||
def get_asset_info(asset):
|
def get_asset_info(asset):
|
||||||
|
"""
|
||||||
|
获取资产的相关账号端口信息
|
||||||
|
"""
|
||||||
default = get_object(Setting, name='default')
|
default = get_object(Setting, name='default')
|
||||||
info = {'hostname': asset.hostname, 'ip': asset.ip}
|
info = {'hostname': asset.hostname, 'ip': asset.ip}
|
||||||
if asset.use_default_auth:
|
if asset.use_default_auth:
|
||||||
|
@ -68,6 +71,9 @@ def get_asset_info(asset):
|
||||||
|
|
||||||
|
|
||||||
def get_role(user, asset):
|
def get_role(user, asset):
|
||||||
|
"""
|
||||||
|
获取用户在这个资产上的授权角色列表
|
||||||
|
"""
|
||||||
roles = []
|
roles = []
|
||||||
rules = PermRule.objects.filter(user=user, asset=asset)
|
rules = PermRule.objects.filter(user=user, asset=asset)
|
||||||
for rule in rules:
|
for rule in rules:
|
||||||
|
@ -77,20 +83,19 @@ def get_role(user, asset):
|
||||||
|
|
||||||
def get_role_key(user, role):
|
def get_role_key(user, role):
|
||||||
"""
|
"""
|
||||||
由于role的key的权限是所有人可以读的, ansible要求为600,所以拷贝一份到特殊目录
|
由于role的key的权限是所有人可以读的, ansible执行命令等要求为600,所以拷贝一份到特殊目录
|
||||||
:param user:
|
:param user:
|
||||||
:param role:
|
:param role:
|
||||||
:return: self key path
|
:return: self key path
|
||||||
"""
|
"""
|
||||||
user_role_key_dir = os.path.join(KEY_DIR, 'user')
|
user_role_key_dir = os.path.join(KEY_DIR, 'user')
|
||||||
user_role_key_path = os.path.join(user_role_key_dir, '%s_%s.pem' % (user.username, role.name))
|
user_role_key_path = os.path.join(user_role_key_dir, '%s_%s.pem' % (user.username, role.name))
|
||||||
mkdir(user_role_key_dir, mode=777)
|
mkdir(user_role_key_dir, mode=0777)
|
||||||
if not os.path.isfile(user_role_key_path):
|
if not os.path.isfile(user_role_key_path):
|
||||||
with open(os.path.join(role.key_path, 'id_rsa')) as fk:
|
with open(os.path.join(role.key_path, 'id_rsa')) as fk:
|
||||||
with open(user_role_key_path, 'w') as fu:
|
with open(user_role_key_path, 'w') as fu:
|
||||||
fu.write(fk.read())
|
fu.write(fk.read())
|
||||||
|
logger.debug("创建新的用户角色key %s" % user_role_key_path)
|
||||||
print user_role_key_path, user.username
|
|
||||||
chown(user_role_key_path, user.username)
|
chown(user_role_key_path, user.username)
|
||||||
os.chmod(user_role_key_path, 0600)
|
os.chmod(user_role_key_path, 0600)
|
||||||
return user_role_key_path
|
return user_role_key_path
|
||||||
|
|
|
@ -4566,4 +4566,6 @@ body.skin-3 {
|
||||||
.form-group.required .control-label:after {
|
.form-group.required .control-label:after {
|
||||||
content: " *";
|
content: " *";
|
||||||
color: red;
|
color: red;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.n-invalid {border: 1px solid #f00;}
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="ibox-content">
|
<div class="ibox-content">
|
||||||
<form method="post" id="userForm" class="form-horizontal" action="">
|
<form method="post" id="roleForm" class="form-horizontal" action="">
|
||||||
{% if error %}
|
{% if error %}
|
||||||
<div class="alert alert-warning text-center">{{ error }}</div>
|
<div class="alert alert-warning text-center">{{ error }}</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -41,9 +41,18 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="hr-line-dashed"></div>
|
<div class="hr-line-dashed"></div>
|
||||||
<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" class="col-sm-2 control-label">角色密码</label>
|
||||||
<div class="col-sm-8">
|
<div class="col-sm-8">
|
||||||
<input id="role_password" name="role_password" type="password" class="form-control" value="{{ default_password }}">
|
<input id="role_password" name="role_password" placeholder="Role Password" type="password" class="form-control">
|
||||||
|
<span class="help-block m-b-none">如果不添加密码,会自动生成</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="hr-line-dashed"></div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="role_key" class="col-sm-2 control-label">角色密钥</label>
|
||||||
|
<div class="col-sm-8">
|
||||||
|
<textarea class="form-control" name="role_key" placeholder="请复制粘贴私钥" rows="10" style="font-size: 9px;"></textarea>
|
||||||
|
<span class="help-block m-b-none">如果不添加密钥,会自动生成, 密码密钥必填一项</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="hr-line-dashed"></div>
|
<div class="hr-line-dashed"></div>
|
||||||
|
@ -69,52 +78,34 @@
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block self_footer_js %}
|
{% block self_footer_js %}
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(function(){
|
$('#roleForm').validator({
|
||||||
$("input.role").click(function(){
|
timely: 2,
|
||||||
if($("input.role[value=GA]").is( ":checked" )){
|
theme: "yellow_right_effect",
|
||||||
$("#admin_groups").css("display", 'none');
|
rules: {
|
||||||
|
check_name: [/^\w{2,20}$/, '大小写字母数字和下划线,2-20位'],
|
||||||
|
either: function(){
|
||||||
|
return $('#role_password').val() == ''
|
||||||
}
|
}
|
||||||
else {
|
},
|
||||||
|
|
||||||
$("#admin_groups").css("display", 'block');
|
fields: {
|
||||||
|
"role_name": {
|
||||||
|
rule: "required;check_name",
|
||||||
|
tip: "输入角色名称",
|
||||||
|
ok: "",
|
||||||
|
msg: {required: "角色名称必填"}
|
||||||
|
},
|
||||||
|
"role_key": {
|
||||||
|
rule: "required(either)",
|
||||||
|
tip: "输入密钥",
|
||||||
|
ok: "",
|
||||||
|
msg: {required: "密码和密钥必填一个!"}
|
||||||
}
|
}
|
||||||
});
|
},
|
||||||
|
valid: function(form) {
|
||||||
$('#use_password').click(function(){
|
form.submit();
|
||||||
if ($(this).is(':checked')){
|
|
||||||
$('#admin_account_password').css('display', 'block')
|
|
||||||
}
|
}
|
||||||
else {
|
})
|
||||||
|
|
||||||
$('#admin_account_password').css('display', 'none')
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#use_publicKey').click(function(){
|
|
||||||
if ($(this).is(':checked')){
|
|
||||||
|
|
||||||
$('#admin_account_publicKey').css('display', 'block')
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$('#admin_account_publicKey').css('display', 'none')
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
var config = {
|
|
||||||
'.chosen-select' : {},
|
|
||||||
'.chosen-select-deselect' : {allow_single_deselect:true},
|
|
||||||
'.chosen-select-no-single' : {disable_search_threshold:10},
|
|
||||||
'.chosen-select-no-results': {no_results_text:'Oops, nothing found!'},
|
|
||||||
'.chosen-select-width' : {width:"95%"}
|
|
||||||
};
|
|
||||||
|
|
||||||
for (var selector in config) {
|
|
||||||
$(selector).chosen(config[selector]);
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<script src="/static/js/cropper/cropper.min.js"></script>
|
|
||||||
<script src="/static/js/datapicker/bootstrap-datepicker.js"></script>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="ibox-content">
|
<div class="ibox-content">
|
||||||
<form method="post" id="userForm" class="form-horizontal" action="">
|
<form method="post" id="roleForm" class="form-horizontal" action="">
|
||||||
{% if error %}
|
{% if error %}
|
||||||
<div class="alert alert-warning text-center">{{ error }}</div>
|
<div class="alert alert-warning text-center">{{ error }}</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -41,9 +41,18 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="hr-line-dashed"></div>
|
<div class="hr-line-dashed"></div>
|
||||||
<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" class="col-sm-2 control-label">角色密码</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_pass }}">
|
<input id="role_password" name="role_password" type="password" class="form-control">
|
||||||
|
<span class="help-block m-b-none">不修改请留空</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="hr-line-dashed"></div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="role_key" class="col-sm-2 control-label">角色密钥</label>
|
||||||
|
<div class="col-sm-8">
|
||||||
|
<textarea class="form-control" name="role_key" placeholder="请复制粘贴私钥" rows="10" style="font-size: 9px;"></textarea>
|
||||||
|
<span class="help-block m-b-none">不修改请留空</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="hr-line-dashed"></div>
|
<div class="hr-line-dashed"></div>
|
||||||
|
@ -69,49 +78,25 @@
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block self_footer_js %}
|
{% block self_footer_js %}
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(function(){
|
$('#roleForm').validator({
|
||||||
$("input.role").click(function(){
|
timely: 2,
|
||||||
if($("input.role[value=GA]").is( ":checked" )){
|
theme: "yellow_right_effect",
|
||||||
$("#admin_groups").css("display", 'none');
|
rules: {
|
||||||
|
check_name: [/^\w{2,20}$/, '大小写字母数字和下划线,2-20位']
|
||||||
|
},
|
||||||
|
|
||||||
|
fields: {
|
||||||
|
"role_name": {
|
||||||
|
rule: "required;check_name",
|
||||||
|
tip: "输入角色名称",
|
||||||
|
ok: "",
|
||||||
|
msg: {required: "角色名称必填"}
|
||||||
}
|
}
|
||||||
else {
|
},
|
||||||
|
valid: function(form) {
|
||||||
$("#admin_groups").css("display", 'block');
|
form.submit();
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
$('#use_password').click(function(){
|
|
||||||
if ($(this).is(':checked')){
|
|
||||||
$('#admin_account_password').css('display', 'block')
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
|
|
||||||
$('#admin_account_password').css('display', 'none')
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#use_publicKey').click(function(){
|
|
||||||
if ($(this).is(':checked')){
|
|
||||||
|
|
||||||
$('#admin_account_publicKey').css('display', 'block')
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$('#admin_account_publicKey').css('display', 'none')
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
var config = {
|
|
||||||
'.chosen-select' : {},
|
|
||||||
'.chosen-select-deselect' : {allow_single_deselect:true},
|
|
||||||
'.chosen-select-no-single' : {disable_search_threshold:10},
|
|
||||||
'.chosen-select-no-results': {no_results_text:'Oops, nothing found!'},
|
|
||||||
'.chosen-select-width' : {width:"95%"}
|
|
||||||
};
|
|
||||||
|
|
||||||
for (var selector in config) {
|
|
||||||
$(selector).chosen(config[selector]);
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<script src="/static/js/cropper/cropper.min.js"></script>
|
<script src="/static/js/cropper/cropper.min.js"></script>
|
||||||
|
|
|
@ -34,7 +34,6 @@
|
||||||
<div class="">
|
<div class="">
|
||||||
<a href="/jperm/role/perm_role_add/" class="btn btn-sm btn-primary "> 添加角色 </a>
|
<a href="/jperm/role/perm_role_add/" class="btn btn-sm btn-primary "> 添加角色 </a>
|
||||||
<a href="/jperm/role/perm_role_push/" class="btn btn-sm btn-primary "> 推送角色 </a>
|
<a href="/jperm/role/perm_role_push/" class="btn btn-sm btn-primary "> 推送角色 </a>
|
||||||
<a id="del_btn" class="btn btn-sm btn-danger "> 删除所选 </a>
|
|
||||||
<form id="search_form" method="get" action="" class="pull-right mail-search">
|
<form id="search_form" method="get" action="" class="pull-right mail-search">
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input type="text" class="form-control input-sm" id="search_input" name="search" placeholder="Search">
|
<input type="text" class="form-control input-sm" id="search_input" name="search" placeholder="Search">
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<div class="tab-content">
|
<div class="tab-content">
|
||||||
<div id="tab-default" class="tab-pane active">
|
<div id="tab-default" class="tab-pane active">
|
||||||
<form method="post" id="userForm" class="form-horizontal" action="">
|
<form method="post" id="settingForm" class="form-horizontal" action="">
|
||||||
{% if error %}
|
{% if error %}
|
||||||
<div class="alert alert-warning text-center">{{ error }}</div>
|
<div class="alert alert-warning text-center">{{ error }}</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -71,7 +71,7 @@
|
||||||
<label for="key" class="col-sm-2 control-label">默认密钥</label>
|
<label for="key" class="col-sm-2 control-label">默认密钥</label>
|
||||||
<div class="col-sm-8">
|
<div class="col-sm-8">
|
||||||
<textarea class="form-control" name="key" placeholder="请复制粘贴私钥" rows="10" style="font-size: 9px;"></textarea>
|
<textarea class="form-control" name="key" placeholder="请复制粘贴私钥" rows="10" style="font-size: 9px;"></textarea>
|
||||||
<span class="help-block m-b-none">如果不修改密钥,请留空</span>
|
<span class="help-block m-b-none">如果不修改密钥,请留空, 密钥密码必填一项</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="hr-line-dashed"></div>
|
<div class="hr-line-dashed"></div>
|
||||||
|
@ -101,4 +101,43 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
{% block self_footer_js %}
|
||||||
|
<script>
|
||||||
|
$('#settingForm').validator({
|
||||||
|
timely: 2,
|
||||||
|
theme: "yellow_right_effect",
|
||||||
|
rules: {
|
||||||
|
check_name: [/^\w{2,20}$/, '大小写字母数字和下划线,2-20位'],
|
||||||
|
check_port: [/^\d{1,5}$/, '端口号不正确'],
|
||||||
|
either: function(){
|
||||||
|
return $('#password').val() == ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
fields: {
|
||||||
|
"username": {
|
||||||
|
rule: "required;check_name",
|
||||||
|
tip: "输入用户名",
|
||||||
|
ok: "",
|
||||||
|
msg: {required: "用户名称必填"}
|
||||||
|
},
|
||||||
|
"port": {
|
||||||
|
rule: "required;check_port",
|
||||||
|
tip: "输入端口号",
|
||||||
|
ok: "",
|
||||||
|
msg: {required: "端口号必填"}
|
||||||
|
},
|
||||||
|
"key": {
|
||||||
|
rule: "required(either)",
|
||||||
|
tip: "输入密钥",
|
||||||
|
ok: "",
|
||||||
|
msg: {required: "密码和密钥必填一个!"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
valid: function(form) {
|
||||||
|
form.submit();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
Loading…
Reference in New Issue