mirror of https://github.com/jumpserver/jumpserver
push role 更改
parent
52c4395b68
commit
8dd4a9fce1
|
@ -284,10 +284,10 @@ class Tasks(Command):
|
||||||
"""
|
"""
|
||||||
push the ssh authorized key to target.
|
push the ssh authorized key to target.
|
||||||
"""
|
"""
|
||||||
module_args = 'user="%s" key="{{ lookup("file", "%s") }}"' % (user, key_path)
|
module_args = 'user="%s" key="{{ lookup("file", "%s") }}" state=present' % (user, key_path)
|
||||||
self.__run(module_args, "authorized_key")
|
self.__run(module_args, "authorized_key")
|
||||||
|
|
||||||
return {"status": "failed","msg": self.msg} if self.msg else {"status": "ok"}
|
return {"status": "failed", "msg": self.msg} if self.msg else {"status": "ok"}
|
||||||
|
|
||||||
def push_multi_key(self, **user_info):
|
def push_multi_key(self, **user_info):
|
||||||
"""
|
"""
|
||||||
|
@ -318,12 +318,15 @@ class Tasks(Command):
|
||||||
|
|
||||||
return {"status": "failed", "msg": self.msg} if self.msg else {"status": "ok"}
|
return {"status": "failed", "msg": self.msg} if self.msg else {"status": "ok"}
|
||||||
|
|
||||||
def add_user(self, username, password):
|
def add_user(self, username, password=''):
|
||||||
"""
|
"""
|
||||||
add a host user.
|
add a host user.
|
||||||
"""
|
"""
|
||||||
encrypt_pass = sha512_crypt.encrypt(password)
|
if password:
|
||||||
module_args = 'name=%s shell=/bin/bash password=%s' % (username, encrypt_pass)
|
encrypt_pass = sha512_crypt.encrypt(password)
|
||||||
|
module_args = 'name=%s shell=/bin/bash password=%s' % (username, encrypt_pass)
|
||||||
|
else:
|
||||||
|
module_args = 'name=%s shell=/bin/bash' % username
|
||||||
self.__run(module_args, "user")
|
self.__run(module_args, "user")
|
||||||
|
|
||||||
return {"status": "failed", "msg": self.msg} if self.msg else {"status": "ok"}
|
return {"status": "failed", "msg": self.msg} if self.msg else {"status": "ok"}
|
||||||
|
|
|
@ -59,7 +59,9 @@ class PermPush(models.Model):
|
||||||
date_added = models.DateTimeField(auto_now=True)
|
date_added = models.DateTimeField(auto_now=True)
|
||||||
asset = models.ManyToManyField(Asset, related_name='perm_push')
|
asset = models.ManyToManyField(Asset, related_name='perm_push')
|
||||||
asset_group = models.ManyToManyField(AssetGroup, related_name='perm_push')
|
asset_group = models.ManyToManyField(AssetGroup, related_name='perm_push')
|
||||||
role = models.ManyToManyField(PermRole, related_name='perm_push')
|
role = models.ForeignKey(PermRole, related_name='perm_push')
|
||||||
is_public_key = models.BooleanField(default=False)
|
is_public_key = models.BooleanField(default=False)
|
||||||
is_password = models.BooleanField(default=False)
|
is_password = models.BooleanField(default=False)
|
||||||
|
success = models.BooleanField(default=False)
|
||||||
|
result = models.TextField()
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ urlpatterns = patterns('jperm.views',
|
||||||
(r'^role/perm_role_delete/$', perm_role_delete),
|
(r'^role/perm_role_delete/$', perm_role_delete),
|
||||||
(r'^role/perm_role_detail/$', perm_role_detail),
|
(r'^role/perm_role_detail/$', perm_role_detail),
|
||||||
(r'^role/perm_role_edit/$', perm_role_edit),
|
(r'^role/perm_role_edit/$', perm_role_edit),
|
||||||
(r'^role/perm_role_push/$', perm_role_push),
|
(r'^role/push/$', perm_role_push),
|
||||||
(r'^sudo/$', perm_sudo_list),
|
(r'^sudo/$', perm_sudo_list),
|
||||||
(r'^sudo/perm_sudo_add/$', perm_sudo_add),
|
(r'^sudo/perm_sudo_add/$', perm_sudo_add),
|
||||||
(r'^sudo/perm_sudo_delete/$', perm_sudo_delete),
|
(r'^sudo/perm_sudo_delete/$', perm_sudo_delete),
|
||||||
|
|
|
@ -263,6 +263,11 @@ def perm_role_add(request):
|
||||||
try:
|
try:
|
||||||
if get_object(PermRole, name=name):
|
if get_object(PermRole, name=name):
|
||||||
raise ServerError('已经存在该用户 %s' % name)
|
raise ServerError('已经存在该用户 %s' % name)
|
||||||
|
default = get_object(Setting, name='default')
|
||||||
|
if default and name == default.field1:
|
||||||
|
raise ServerError('与默认管理账号同名')
|
||||||
|
if name == 'root':
|
||||||
|
raise ServerError('不能为root')
|
||||||
if password:
|
if password:
|
||||||
encrypt_pass = CRYPTOR.encrypt(password)
|
encrypt_pass = CRYPTOR.encrypt(password)
|
||||||
else:
|
else:
|
||||||
|
@ -398,15 +403,13 @@ def perm_role_push(request):
|
||||||
"""
|
"""
|
||||||
# 渲染数据
|
# 渲染数据
|
||||||
header_title, path1, path2 = "系统角色", "角色管理", "角色推送"
|
header_title, path1, path2 = "系统角色", "角色管理", "角色推送"
|
||||||
|
role_id = request.GET.get('id')
|
||||||
roles = PermRole.objects.all()
|
role = get_object(PermRole, id=role_id)
|
||||||
assets = Asset.objects.all()
|
assets = Asset.objects.all()
|
||||||
asset_groups = AssetGroup.objects.all()
|
asset_groups = AssetGroup.objects.all()
|
||||||
|
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
# 获取推荐角色的名称列表
|
# 获取推荐角色的名称列表
|
||||||
role_ids = request.POST.getlist("roles")
|
|
||||||
|
|
||||||
# 计算出需要推送的资产列表
|
# 计算出需要推送的资产列表
|
||||||
asset_ids = request.POST.getlist("assets")
|
asset_ids = request.POST.getlist("assets")
|
||||||
asset_group_ids = request.POST.getlist("asset_groups")
|
asset_group_ids = request.POST.getlist("asset_groups")
|
||||||
|
@ -434,13 +437,7 @@ def perm_role_push(request):
|
||||||
# "password": password})
|
# "password": password})
|
||||||
push_resource = gen_resource(calc_assets)
|
push_resource = gen_resource(calc_assets)
|
||||||
|
|
||||||
# 获取角色的推送方式,以及推送需要的信息
|
logger.debug('推送role res: %s' % push_resource)
|
||||||
roles_obj = [PermRole.objects.get(id=role_id) for role_id in role_ids]
|
|
||||||
role_pass = {}
|
|
||||||
role_key = {}
|
|
||||||
for role in roles_obj:
|
|
||||||
role_pass[role.name] = role.password
|
|
||||||
role_key[role.name] = os.path.join(role.key_path, 'id_rsa.pub')
|
|
||||||
|
|
||||||
# 调用Ansible API 进行推送
|
# 调用Ansible API 进行推送
|
||||||
password_push = request.POST.get("use_password")
|
password_push = request.POST.get("use_password")
|
||||||
|
@ -452,34 +449,31 @@ def perm_role_push(request):
|
||||||
# 因为要先建立用户,所以password 是必选项,而push key是在 password也完成的情况下的 可选项
|
# 因为要先建立用户,所以password 是必选项,而push key是在 password也完成的情况下的 可选项
|
||||||
# 1. 以password 方式推送角色
|
# 1. 以password 方式推送角色
|
||||||
if password_push:
|
if password_push:
|
||||||
ret["password_push"] = task.add_multi_user(**role_pass)
|
ret["password_push"] = task.add_user(role.name, CRYPTOR.decrypt(role.password))
|
||||||
if ret["password_push"].get("status") != "success":
|
if ret["password_push"].get("status") != "success":
|
||||||
ret_failed["step1"] == "failed"
|
ret_failed["step1"] == "failed"
|
||||||
|
|
||||||
# 2. 以秘钥 方式推送角色
|
# 2. 以秘钥 方式推送角色
|
||||||
if key_push:
|
if key_push:
|
||||||
ret["password_push"] = task.add_multi_user(**role_pass)
|
ret["password_push"] = task.add_user(role.name)
|
||||||
if ret["password_push"].get("status") != "success":
|
if ret["password_push"].get("status") != "ok":
|
||||||
ret_failed["step2-1"] = "failed"
|
ret_failed["step2-1"] = "failed"
|
||||||
ret["key_push"] = task.push_multi_key(**role_key)
|
ret["key_push"] = task.push_key(role.name, os.path.join(role.key_path, 'id_rsa.pub'))
|
||||||
if ret["key_push"].get("status") != "success":
|
if ret["key_push"].get("status") != "ok":
|
||||||
ret_failed["step2-2"] = "failed"
|
ret_failed["step2-2"] = "failed"
|
||||||
|
|
||||||
# 3. 推送sudo配置文件
|
# 3. 推送sudo配置文件
|
||||||
role_chosen_aliase = {} # {'dev': 'NETWORKING, SHUTDOWN', 'sa': 'NETWORKING, SHUTDOWN'}
|
role_chosen_aliase = {} # {'dev': 'NETWORKING, SHUTDOWN'}
|
||||||
sudo_alias = set() # set(sudo1, sudo2, sudo3)
|
sudo_alias = set([sudo for sudo in role.sudo.all()]) # set(sudo1, sudo2, sudo3)
|
||||||
for role in roles_obj:
|
role_chosen_aliase[role.name] = ','.join(sudo.name for sudo in sudo_alias)
|
||||||
sudos = set([sudo for sudo in role.sudo.all()])
|
|
||||||
sudo_alias.update(sudos)
|
|
||||||
role_chosen_aliase[role.name] = ','.join(sudo.name for sudo in sudos)
|
|
||||||
add_sudo_script = get_add_sudo_script(role_chosen_aliase, sudo_alias)
|
add_sudo_script = get_add_sudo_script(role_chosen_aliase, sudo_alias)
|
||||||
ret_sudo = task.push_sudo_file(add_sudo_script)
|
ret['sudo'] = task.push_sudo_file(add_sudo_script)
|
||||||
|
|
||||||
if ret_sudo["step1"] != "ok" or ret_sudo["step2"] != "ok":
|
if ret['sudo']["step1"] != "ok" or ret['sudo']["step2"] != "ok":
|
||||||
ret_failed["step3"] = "failed"
|
ret_failed["step3"] = "failed"
|
||||||
os.remove(add_sudo_script)
|
os.remove(add_sudo_script)
|
||||||
|
|
||||||
print ret
|
logger.debug('推送role结果: %s' % ret)
|
||||||
# 结果汇总统计
|
# 结果汇总统计
|
||||||
if ret_failed:
|
if ret_failed:
|
||||||
# 推送失败
|
# 推送失败
|
||||||
|
@ -491,7 +485,7 @@ def perm_role_push(request):
|
||||||
push.save()
|
push.save()
|
||||||
push.asset_group = asset_groups_obj
|
push.asset_group = asset_groups_obj
|
||||||
push.asset = calc_assets
|
push.asset = calc_assets
|
||||||
push.role = roles_obj
|
push.role = role
|
||||||
push.save()
|
push.save()
|
||||||
|
|
||||||
return my_render('jperm/perm_role_push.html', locals(), request)
|
return my_render('jperm/perm_role_push.html', locals(), request)
|
||||||
|
@ -592,5 +586,7 @@ def perm_sudo_delete(request):
|
||||||
return HttpResponse(u"不支持该操作")
|
return HttpResponse(u"不支持该操作")
|
||||||
|
|
||||||
|
|
||||||
|
def role_push_list(request):
|
||||||
|
push_all = PermPush.objects.all()
|
||||||
|
return my_render('jperm/role_push_list.html', locals(), request)
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ import ast
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from django import template
|
from django import template
|
||||||
# from jperm.models import CmdGroup
|
from jperm.models import PermPush
|
||||||
from jumpserver.api import *
|
from jumpserver.api import *
|
||||||
from jasset.models import AssetAlias
|
from jasset.models import AssetAlias
|
||||||
|
|
||||||
|
@ -259,3 +259,16 @@ def role_contain_which_sudos(role):
|
||||||
sudo_names = [sudo.name for sudo in role.sudo.all()]
|
sudo_names = [sudo.name for sudo in role.sudo.all()]
|
||||||
return ','.join(sudo_names)
|
return ','.join(sudo_names)
|
||||||
|
|
||||||
|
|
||||||
|
@register.filter(name='get_push_info')
|
||||||
|
def get_push_info(push_id, arg):
|
||||||
|
push = get_object(PermPush, id=push_id)
|
||||||
|
if push and arg:
|
||||||
|
if arg == 'asset':
|
||||||
|
return [asset.hostname for asset in push.asset.all()]
|
||||||
|
if arg == 'asset_group':
|
||||||
|
return [asset_group.name for asset_group in push.asset_group.all()]
|
||||||
|
if arg == 'role':
|
||||||
|
return [role.name for role in push.role.all()]
|
||||||
|
else:
|
||||||
|
return []
|
||||||
|
|
|
@ -146,7 +146,7 @@ def user_add(request):
|
||||||
error = ''
|
error = ''
|
||||||
msg = ''
|
msg = ''
|
||||||
header_title, path1, path2 = '添加用户', '用户管理', '添加用户'
|
header_title, path1, path2 = '添加用户', '用户管理', '添加用户'
|
||||||
user_role = {'SU': u'超级管理员', 'GA': u'组管理员', 'CU': u'普通用户'}
|
user_role = {'SU': u'超级管理员', 'CU': u'普通用户'}
|
||||||
group_all = UserGroup.objects.all()
|
group_all = UserGroup.objects.all()
|
||||||
|
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
|
@ -349,7 +349,7 @@ def user_edit(request):
|
||||||
if not user_id:
|
if not user_id:
|
||||||
return HttpResponseRedirect('/')
|
return HttpResponseRedirect('/')
|
||||||
|
|
||||||
user_role = {'SU': u'超级管理员', 'GA': u'组管理员', 'CU': u'普通用户'}
|
user_role = {'SU': u'超级管理员', 'CU': u'普通用户'}
|
||||||
user = get_object(User, id=user_id)
|
user = get_object(User, id=user_id)
|
||||||
group_all = UserGroup.objects.all()
|
group_all = UserGroup.objects.all()
|
||||||
if user:
|
if user:
|
||||||
|
|
|
@ -48,7 +48,6 @@
|
||||||
{{ af.ip|bootstrap_horizontal }}
|
{{ af.ip|bootstrap_horizontal }}
|
||||||
<p class="col-sm-offset-2">Tips: 如果IP地址不填写, IP默认会设置与主机名一致</p>
|
<p class="col-sm-offset-2">Tips: 如果IP地址不填写, IP默认会设置与主机名一致</p>
|
||||||
|
|
||||||
|
|
||||||
<div class="hr-line-dashed"></div>
|
<div class="hr-line-dashed"></div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="j_group" class="col-sm-2 control-label">管理账号<span class="red-fonts"> *</span></label>
|
<label for="j_group" class="col-sm-2 control-label">管理账号<span class="red-fonts"> *</span></label>
|
||||||
|
@ -60,7 +59,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<p class="col-sm-offset-2">Tips: 管理用户为root或用户拥有NOPASSWD:ALL sudo权限的用户</p>
|
||||||
<div class="form-group" id="admin_account" style="display: none">
|
<div class="form-group" id="admin_account" style="display: none">
|
||||||
<div class="hr-line-dashed"></div>
|
<div class="hr-line-dashed"></div>
|
||||||
<label class="col-sm-2 control-label"> 管理用户名<span class="red-fonts">*</span> </label>
|
<label class="col-sm-2 control-label"> 管理用户名<span class="red-fonts">*</span> </label>
|
||||||
|
|
|
@ -29,11 +29,10 @@
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="ibox-content">
|
<div class="ibox-content">
|
||||||
<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-danger "> 推送角色 </a>
|
{# <a href="/jperm/role/perm_role_push/" 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">
|
||||||
|
@ -45,7 +44,6 @@
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<table class="table table-striped table-bordered table-hover " id="editable" >
|
<table class="table table-striped table-bordered table-hover " id="editable" >
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -66,6 +64,7 @@
|
||||||
<td class="text-center">
|
<td class="text-center">
|
||||||
<a href="/jperm/role/perm_role_detail/?id={{ role.id }}" class="btn btn-xs btn-primary">详情</a>
|
<a href="/jperm/role/perm_role_detail/?id={{ role.id }}" class="btn btn-xs btn-primary">详情</a>
|
||||||
<a href="/jperm/role/perm_role_edit/?id={{ role.id }}" class="btn btn-xs btn-info">编辑</a>
|
<a href="/jperm/role/perm_role_edit/?id={{ role.id }}" class="btn btn-xs btn-info">编辑</a>
|
||||||
|
<a href="/jperm/role/push/?id={{ role.id }}" class="btn btn-xs btn-warning">推送</a>
|
||||||
<button onclick="remove_role({{ role.id }})" class="btn btn-xs btn-danger">删除</button>
|
<button onclick="remove_role({{ role.id }})" class="btn btn-xs btn-danger">删除</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
@ -33,6 +33,13 @@
|
||||||
{% if msg %}
|
{% if msg %}
|
||||||
<div class="alert alert-success text-center">{{ msg }}</div>
|
<div class="alert alert-success text-center">{{ msg }}</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="role" class="col-sm-2 control-label">角色</label>
|
||||||
|
<div class="col-sm-8">
|
||||||
|
<input name="id" type="text" class="form-control" disabled value="{{ role.name }}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="hr-line-dashed"></div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="asset" class="col-sm-2 control-label">资产</label>
|
<label for="asset" class="col-sm-2 control-label">资产</label>
|
||||||
<div class="col-sm-8">
|
<div class="col-sm-8">
|
||||||
|
@ -55,17 +62,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="hr-line-dashed"></div>
|
<div class="hr-line-dashed"></div>
|
||||||
<div class="form-group">
|
|
||||||
<label for="role" class="col-sm-2 control-label">角色<span class="red-fonts">*</span></label>
|
|
||||||
<div class="col-sm-8">
|
|
||||||
<select name="roles" data-placeholder="请选择角色" class="chosen-select form-control m-b" multiple tabindex="2">
|
|
||||||
{% for role in roles %}
|
|
||||||
<option value="{{ role.id }}">{{ role.name }}</option>
|
|
||||||
{% endfor %}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="hr-line-dashed"></div>
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="j_group" class="col-sm-2 control-label">使用密钥</label>
|
<label for="j_group" class="col-sm-2 control-label">使用密钥</label>
|
||||||
|
|
|
@ -33,7 +33,6 @@
|
||||||
<div class="ibox-content">
|
<div class="ibox-content">
|
||||||
<div class="">
|
<div class="">
|
||||||
<a href="/jperm/sudo/perm_sudo_add/" class="btn btn-sm btn-primary "> 添加别名 </a>
|
<a href="/jperm/sudo/perm_sudo_add/" 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">
|
||||||
|
|
|
@ -61,7 +61,7 @@
|
||||||
{% ifequal session_role_id 2 %}
|
{% ifequal session_role_id 2 %}
|
||||||
<div class="hr-line-dashed"></div>
|
<div class="hr-line-dashed"></div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="role" class="col-sm-2 control-label">角色<span class="red-fonts">*</span></label>
|
<label for="role" class="col-sm-2 control-label">权限<span class="red-fonts">*</span></label>
|
||||||
<div class="col-sm-8">
|
<div class="col-sm-8">
|
||||||
{% for r, role_name in user_role.items %}
|
{% for r, role_name in user_role.items %}
|
||||||
<div class="col-sm-3">
|
<div class="col-sm-3">
|
||||||
|
|
|
@ -49,7 +49,7 @@
|
||||||
<input name="setting" value="default" style="display: none">
|
<input name="setting" value="default" style="display: none">
|
||||||
<div class="col-sm-8">
|
<div class="col-sm-8">
|
||||||
<input id="username" name="username" placeholder="Username" type="text" value="{{ setting_default.field1 }}" class="form-control">
|
<input id="username" name="username" placeholder="Username" type="text" value="{{ setting_default.field1 }}" class="form-control">
|
||||||
<span class="help-block m-b-none">该用户为root或用户NOPASS:ALL sudo权限的用户</span>
|
<span class="help-block m-b-none"> 管理用户为root或用户拥有NOPASSWD:ALL sudo权限的用户</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="hr-line-dashed"></div>
|
<div class="hr-line-dashed"></div>
|
||||||
|
@ -128,13 +128,13 @@
|
||||||
tip: "输入端口号",
|
tip: "输入端口号",
|
||||||
ok: "",
|
ok: "",
|
||||||
msg: {required: "端口号必填"}
|
msg: {required: "端口号必填"}
|
||||||
},
|
|
||||||
"key": {
|
|
||||||
rule: "required(either)",
|
|
||||||
tip: "输入密钥",
|
|
||||||
ok: "",
|
|
||||||
msg: {required: "密码和密钥必填一个!"}
|
|
||||||
}
|
}
|
||||||
|
{# "key": {#}
|
||||||
|
{# rule: "required(either)",#}
|
||||||
|
{# tip: "输入密钥",#}
|
||||||
|
{# ok: "",#}
|
||||||
|
{# msg: {required: "密码和密钥必填一个!"}#}
|
||||||
|
{# }#}
|
||||||
},
|
},
|
||||||
valid: function(form) {
|
valid: function(form) {
|
||||||
form.submit();
|
form.submit();
|
||||||
|
|
Loading…
Reference in New Issue