mirror of https://github.com/jumpserver/jumpserver
Merge branch 'dev' of git.coding.net:jumpserver/jumpserver into dev
commit
8ac369b925
|
@ -43,7 +43,7 @@ class CommandValueError(AnsibleError):
|
|||
super(CommandValueError, self).__init__('value:invalid', field, message)
|
||||
|
||||
|
||||
class MyInventory(object):
|
||||
class MyInventory(Inventory):
|
||||
"""
|
||||
this is my ansible inventory object.
|
||||
"""
|
||||
|
@ -64,7 +64,7 @@ class MyInventory(object):
|
|||
self.inventory = Inventory(host_list=[])
|
||||
self.gen_inventory()
|
||||
|
||||
def add_group(self, hosts, groupname, groupvars=None):
|
||||
def my_add_group(self, hosts, groupname, groupvars=None):
|
||||
"""
|
||||
add hosts to a group
|
||||
"""
|
||||
|
@ -90,6 +90,7 @@ class MyInventory(object):
|
|||
my_host.set_variable('ansible_ssh_user', username)
|
||||
my_host.set_variable('ansible_ssh_pass', password)
|
||||
my_host.set_variable('ansible_ssh_private_key_file', ssh_key)
|
||||
|
||||
# set other variables
|
||||
for key, value in host.iteritems():
|
||||
if key not in ["hostname", "port", "username", "password"]:
|
||||
|
@ -104,10 +105,10 @@ class MyInventory(object):
|
|||
add hosts to inventory.
|
||||
"""
|
||||
if isinstance(self.resource, list):
|
||||
self.add_group(self.resource, 'default_group')
|
||||
self.my_add_group(self.resource, 'default_group')
|
||||
elif isinstance(self.resource, dict):
|
||||
for groupname, hosts_and_vars in self.resource.iteritems():
|
||||
self.add_group(hosts_and_vars.get("hosts"), groupname, hosts_and_vars.get("vars"))
|
||||
self.my_add_group(hosts_and_vars.get("hosts"), groupname, hosts_and_vars.get("vars"))
|
||||
|
||||
|
||||
class MyRunner(MyInventory):
|
||||
|
@ -168,6 +169,7 @@ class Command(MyInventory):
|
|||
)
|
||||
self.results = hoc.run()
|
||||
|
||||
ret = {}
|
||||
if self.stdout:
|
||||
data['ok'] = self.stdout
|
||||
if self.stderr:
|
||||
|
@ -177,6 +179,7 @@ class Command(MyInventory):
|
|||
|
||||
return data
|
||||
|
||||
|
||||
@property
|
||||
def raw_results(self):
|
||||
"""
|
||||
|
@ -238,7 +241,14 @@ class Tasks(Command):
|
|||
def __init__(self, *args, **kwargs):
|
||||
super(Tasks, self).__init__(*args, **kwargs)
|
||||
|
||||
def __run(self, module_args, module_name="command", timeout=5, forks=10, group='default_group', pattern='*'):
|
||||
def __run(self,
|
||||
module_args,
|
||||
module_name="command",
|
||||
timeout=5,
|
||||
forks=10,
|
||||
group='default_group',
|
||||
pattern='*',
|
||||
):
|
||||
"""
|
||||
run command from andible ad-hoc.
|
||||
command : 必须是一个需要执行的命令字符串, 比如
|
||||
|
@ -251,9 +261,11 @@ class Tasks(Command):
|
|||
subset=group,
|
||||
pattern=pattern,
|
||||
forks=forks,
|
||||
become=False,
|
||||
)
|
||||
|
||||
self.results = hoc.run()
|
||||
return {"msg": self.msg, "result": self.results}
|
||||
|
||||
@property
|
||||
def msg(self):
|
||||
|
@ -304,7 +316,7 @@ class Tasks(Command):
|
|||
module_args = 'user="%s" key="{{ lookup("file", "%s") }}" state="absent"' % (user, key_path)
|
||||
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 add_user(self, username, password):
|
||||
"""
|
||||
|
@ -342,7 +354,8 @@ class Tasks(Command):
|
|||
delete a host user.
|
||||
"""
|
||||
module_args = 'name=%s state=absent remove=yes move_home=yes force=yes' % (username)
|
||||
self.__run(module_args, "user")
|
||||
self.__run(module_args,
|
||||
"user",)
|
||||
|
||||
return {"status": "failed","msg": self.msg} if self.msg else {"status": "ok"}
|
||||
|
||||
|
@ -418,8 +431,31 @@ class Tasks(Command):
|
|||
"product_sn": setup.get("ansible_product_serial")
|
||||
}
|
||||
|
||||
return {"status": "failed", "msg": self.msg} if self.msg else {"status": "ok", "result": result}
|
||||
return {"failed": self.msg, "ok": result}
|
||||
|
||||
def push_sudo_file(self, file_path):
|
||||
"""
|
||||
use template to render pushed sudoers file
|
||||
:return:
|
||||
"""
|
||||
module_args1 = 'test'
|
||||
ret1 = self.__run(module_args1, "script")
|
||||
module_args2 = 'visudo -c | grep "parsed OK" &> /dev/null && echo "ok" || echo "failed"'
|
||||
ret2 = self.__run(module_args2, "shell")
|
||||
ret2_status = [host_value.get("stdout") for host_value in ret2["result"]["contacted"].values()]
|
||||
|
||||
result = {}
|
||||
if not ret1["msg"]:
|
||||
result["step1"] = "ok"
|
||||
else:
|
||||
result["step1"] = "failed"
|
||||
|
||||
if not ret2["msg"] and "failed" not in ret2_status:
|
||||
result["step2"] = "ok"
|
||||
else:
|
||||
result["step2"] = "failed"
|
||||
|
||||
return result
|
||||
|
||||
class CustomAggregateStats(callbacks.AggregateStats):
|
||||
"""
|
||||
|
@ -469,12 +505,12 @@ class MyPlaybook(MyInventory):
|
|||
playbook_path = os.path.join(ANSIBLE_DIR, playbook_relational_path)
|
||||
|
||||
pb = PlayBook(
|
||||
playbook = playbook_path,
|
||||
stats = stats,
|
||||
callbacks = playbook_cb,
|
||||
runner_callbacks = runner_cb,
|
||||
inventory = self.inventory,
|
||||
extra_vars = extra_vars,
|
||||
playbook=playbook_path,
|
||||
stats=stats,
|
||||
callbacks=playbook_cb,
|
||||
runner_callbacks=runner_cb,
|
||||
inventory=self.inventory,
|
||||
extra_vars=extra_vars,
|
||||
check=False)
|
||||
|
||||
self.results = pb.run()
|
||||
|
@ -504,9 +540,14 @@ if __name__ == "__main__":
|
|||
# },
|
||||
# }
|
||||
|
||||
resource = [{"hostname": "127.0.0.1", "port": "22", "username": "yumaojun", "password": "yusky0902"}]
|
||||
command = Command(resource)
|
||||
print command.run("who")
|
||||
resource = [{"hostname": "127.0.0.1", "port": "22", "username": "yumaojun", "password": "yusky0902",
|
||||
# "ansible_become": "yes",
|
||||
# "ansible_become_method": "sudo",
|
||||
# # "ansible_become_user": "root",
|
||||
# "ansible_become_pass": "yusky0902",
|
||||
}]
|
||||
cmd = Command(resource)
|
||||
print cmd.run('ls')
|
||||
|
||||
# resource = [{"hostname": "192.168.10.148", "port": "22", "username": "root", "password": "xxx"}]
|
||||
# task = Tasks(resource)
|
||||
|
|
|
@ -5,12 +5,37 @@ from jasset.models import Asset, AssetGroup
|
|||
from juser.models import User, UserGroup
|
||||
|
||||
|
||||
class PermLog(models.Model):
|
||||
datetime = models.DateTimeField(auto_now_add=True)
|
||||
action = models.CharField(max_length=100, null=True, blank=True, default='')
|
||||
results = models.CharField(max_length=1000, null=True, blank=True, default='')
|
||||
is_success = models.BooleanField(default=False)
|
||||
is_finish = models.BooleanField(default=False)
|
||||
|
||||
|
||||
class SysUser(models.Model):
|
||||
username = models.CharField(max_length=100)
|
||||
password = models.CharField(max_length=100)
|
||||
comment = models.CharField(max_length=100, null=True, blank=True, default='')
|
||||
|
||||
|
||||
class PermSudo(models.Model):
|
||||
name = models.CharField(max_length=100, unique=True)
|
||||
date_added = models.DateTimeField(auto_now=True)
|
||||
commands = models.TextField()
|
||||
comment = models.CharField(max_length=100, null=True, blank=True, default='')
|
||||
|
||||
def __unicode__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class PermRole(models.Model):
|
||||
name = models.CharField(max_length=100, unique=True)
|
||||
comment = models.CharField(max_length=100, null=True, blank=True, default='')
|
||||
password = models.CharField(max_length=100)
|
||||
key_path = models.CharField(max_length=100)
|
||||
date_added = models.DateTimeField(auto_now=True)
|
||||
sudo = models.ManyToManyField(PermSudo, related_name='perm_role')
|
||||
|
||||
def __unicode__(self):
|
||||
return self.name
|
||||
|
@ -28,3 +53,13 @@ class PermRule(models.Model):
|
|||
|
||||
def __unicode__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class PermPush(models.Model):
|
||||
date_added = models.DateTimeField(auto_now=True)
|
||||
asset = models.ManyToManyField(Asset, related_name='perm_push')
|
||||
asset_group = models.ManyToManyField(AssetGroup, related_name='perm_push')
|
||||
role = models.ManyToManyField(PermRole, related_name='perm_push')
|
||||
is_public_key = models.BooleanField(default=False)
|
||||
is_password = models.BooleanField(default=False)
|
||||
|
||||
|
|
|
@ -266,6 +266,40 @@ def get_role_info(role_id, type="all"):
|
|||
return u"不支持的查询"
|
||||
|
||||
|
||||
def get_role_push_host(role):
|
||||
"""
|
||||
get the role push host
|
||||
:return: the asset object
|
||||
"""
|
||||
# 计算该role 所有push记录 总共推送的主机
|
||||
assets = []
|
||||
asset_groups = []
|
||||
for push in role.perm_push.all():
|
||||
assets.extend(push.asset.all())
|
||||
asset_groups.extend(push.asset_group.all())
|
||||
group_assets = []
|
||||
for asset_group in asset_groups:
|
||||
group_assets.extend(asset_group.asset_set.all())
|
||||
cacl_assets = set(assets) | set(group_assets)
|
||||
|
||||
# 计算所有主机 在push记录里面的 使用密码和使用秘钥状况
|
||||
result = []
|
||||
for asset in cacl_assets:
|
||||
all_push = asset.perm_push.all()
|
||||
if True in [push.is_password for push in all_push if role in push.role.all()]:
|
||||
is_password = u"是"
|
||||
else:
|
||||
is_password = u"否"
|
||||
if True in [push.is_public_key for push in all_push if role in push.role.all()]:
|
||||
is_public_key = u"是"
|
||||
else:
|
||||
is_public_key = u"否"
|
||||
result.append({"ip": asset.ip,
|
||||
"group": ','.join([group.name for group in asset.group.all()]),
|
||||
"password": is_password,
|
||||
"pubkey": is_public_key})
|
||||
return result
|
||||
|
||||
if __name__ == "__main__":
|
||||
print get_role_info(1)
|
||||
|
||||
|
|
|
@ -13,4 +13,9 @@ urlpatterns = patterns('jperm.views',
|
|||
(r'^role/perm_role_detail/$', perm_role_detail),
|
||||
(r'^role/perm_role_edit/$', perm_role_edit),
|
||||
(r'^role/perm_role_push/$', perm_role_push),
|
||||
(r'^sudo/$', perm_sudo_list),
|
||||
(r'^sudo/perm_sudo_add/$', perm_sudo_add),
|
||||
(r'^sudo/perm_sudo_delete/$', perm_sudo_delete),
|
||||
(r'^sudo/perm_sudo_edit/$', perm_sudo_edit),
|
||||
|
||||
)
|
||||
|
|
|
@ -8,6 +8,12 @@ from paramiko.rsakey import RSAKey
|
|||
from jumpserver.api import mkdir
|
||||
from uuid import uuid4
|
||||
from jumpserver.api import CRYPTOR
|
||||
from os import makedirs
|
||||
|
||||
from django.template.loader import get_template
|
||||
from django.template import Context
|
||||
from tempfile import NamedTemporaryFile
|
||||
|
||||
|
||||
from jumpserver.settings import KEY_DIR
|
||||
|
||||
|
@ -66,6 +72,47 @@ def gen_keys(key="", key_path_dir=""):
|
|||
return key_path_dir
|
||||
|
||||
|
||||
def gen_sudo(role_custom, role_name, role_chosen):
|
||||
"""
|
||||
生成sudo file, 仅测试了cenos7
|
||||
role_custom: 自定义支持的sudo 命令 格式: 'CMD1, CMD2, CMD3, ...'
|
||||
role_name: role name
|
||||
role_chosen: 选择那些sudo的命令别名:
|
||||
NETWORKING, SOFTWARE, SERVICES, STORAGE,
|
||||
DELEGATING, PROCESSES, LOCATE, DRIVERS
|
||||
:return:
|
||||
"""
|
||||
sudo_file_basename = os.path.join(os.path.dirname(KEY_DIR), 'role_sudo_file')
|
||||
makedirs(sudo_file_basename)
|
||||
sudo_file_path = os.path.join(sudo_file_basename, role_name)
|
||||
|
||||
t = get_template('role_sudo.j2')
|
||||
content = t.render(Context({"role_custom": role_custom,
|
||||
"role_name": role_name,
|
||||
"role_chosen": role_chosen,
|
||||
}))
|
||||
with open(sudo_file_path, 'w') as f:
|
||||
f.write(content)
|
||||
return sudo_file_path
|
||||
|
||||
|
||||
def get_add_sudo_script(sudo_chosen_aliase, sudo_chosen_obj):
|
||||
"""
|
||||
get the sudo file
|
||||
:param kwargs:
|
||||
:return:
|
||||
"""
|
||||
sudo_j2 = get_template('jperm/role_sudo.j2')
|
||||
sudo_content = sudo_j2.render(Context({"sudo_chosen_aliase": sudo_chosen_aliase,
|
||||
"sudo_chosen_obj": sudo_chosen_obj}))
|
||||
sudo_file = NamedTemporaryFile(delete=False)
|
||||
sudo_file.write(sudo_content)
|
||||
sudo_file.close()
|
||||
|
||||
return sudo_file.name
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print gen_keys()
|
||||
|
||||
|
|
261
jperm/views.py
261
jperm/views.py
|
@ -5,15 +5,14 @@ from paramiko import SSHException
|
|||
from jperm.perm_api import *
|
||||
from juser.user_api import gen_ssh_key
|
||||
|
||||
|
||||
from juser.models import User, UserGroup
|
||||
from jasset.models import Asset, AssetGroup
|
||||
from jperm.models import PermRole, PermRule
|
||||
from jperm.models import PermRole, PermRule, PermSudo, PermPush
|
||||
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, get_add_sudo_script
|
||||
from jperm.ansible_api import Tasks
|
||||
from jperm.perm_api import get_role_info
|
||||
from jperm.perm_api import get_role_info, get_role_push_host
|
||||
|
||||
from jumpserver.api import my_render, get_object, CRYPTOR
|
||||
|
||||
|
@ -256,37 +255,36 @@ def perm_role_add(request):
|
|||
# 渲染数据
|
||||
header_title, path1, path2 = "系统角色", "角色管理", "添加角色"
|
||||
|
||||
if request.method == "POST":
|
||||
# 获取参数: name, comment
|
||||
name = request.POST.get("role_name", "")
|
||||
comment = request.POST.get("role_comment", "")
|
||||
password = request.POST.get("role_password", "")
|
||||
key_content = request.POST.get("role_key", "")
|
||||
try:
|
||||
if get_object(PermRole, name=name):
|
||||
raise ServerError('已经存在该用户 %s' % name)
|
||||
if request.method == "GET":
|
||||
default_password = get_rand_pass()
|
||||
sudos = PermSudo.objects.all()
|
||||
return my_render('jperm/perm_role_add.html', locals(), request)
|
||||
|
||||
elif request.method == "POST":
|
||||
# 获取参数: name, comment, sudo
|
||||
name = request.POST.get("role_name")
|
||||
comment = request.POST.get("role_comment")
|
||||
password = request.POST.get("role_password")
|
||||
sudos_name = request.POST.getlist("sudo_name")
|
||||
sudos_obj = [PermSudo.objects.get(name=sudo_name) for sudo_name in sudos_name]
|
||||
encrypt_pass = CRYPTOR.encrypt(password)
|
||||
# 生成随机密码,生成秘钥对
|
||||
|
||||
key_path = gen_keys()
|
||||
role = PermRole(name=name, comment=comment, password=encrypt_pass, key_path=key_path)
|
||||
role.save()
|
||||
role.sudo = sudos_obj
|
||||
role.save()
|
||||
|
||||
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))
|
||||
|
||||
if '' == password and '' == key_content:
|
||||
raise ServerError('账号和密码必填一项')
|
||||
if password:
|
||||
encrypt_pass = CRYPTOR.encrypt(password)
|
||||
else:
|
||||
encrypt_pass = CRYPTOR.encrypt(CRYPTOR.gen_rand_pass(20))
|
||||
# 生成随机密码,生成秘钥对
|
||||
if key_content:
|
||||
try:
|
||||
key_path = gen_keys(key=key_content)
|
||||
except SSHException:
|
||||
raise ServerError('输入的密钥不合法')
|
||||
else:
|
||||
key_path = gen_keys()
|
||||
logger.debug('generate role key: %s' % key_path)
|
||||
role = PermRole(name=name, comment=comment, password=encrypt_pass, key_path=key_path)
|
||||
role.save()
|
||||
msg = u"添加角色: %s" % name
|
||||
return HttpResponseRedirect('/jperm/role/')
|
||||
except ServerError, e:
|
||||
error = e
|
||||
|
||||
return my_render('jperm/perm_role_add.html', locals(), request)
|
||||
|
||||
|
@ -337,6 +335,7 @@ def perm_role_detail(request):
|
|||
asset_groups = role_info.get("asset_groups")
|
||||
users = role_info.get("users")
|
||||
user_groups = role_info.get("user_groups")
|
||||
push_info = get_role_push_host(PermRole.objects.get(id=role_id))
|
||||
|
||||
return my_render('jperm/perm_role_detail.html', locals(), request)
|
||||
|
||||
|
@ -351,13 +350,20 @@ def perm_role_edit(request):
|
|||
|
||||
# 渲染数据
|
||||
role_id = request.GET.get("id")
|
||||
role = get_object(PermRole, id=role_id)
|
||||
role = PermRole.objects.get(id=role_id)
|
||||
role_pass = CRYPTOR.decrypt(role.password)
|
||||
role_sudos = role.sudo.all()
|
||||
if request.method == "GET":
|
||||
return my_render('jperm/perm_role_edit.html', locals(), request)
|
||||
|
||||
|
||||
if request.method == "POST":
|
||||
# 获取 POST 数据
|
||||
role_name = request.POST.get("role_name")
|
||||
role_password = request.POST.get("role_password")
|
||||
role_comment = request.POST.get("role_comment")
|
||||
role_sudo_names = request.POST.getlist("sudo_name")
|
||||
role_sudos = [PermSudo.objects.get(name=sudo_name) for sudo_name in role_sudo_names]
|
||||
key_content = request.POST.get("role_key", "")
|
||||
try:
|
||||
if not role:
|
||||
|
@ -375,7 +381,9 @@ def perm_role_edit(request):
|
|||
logger.debug('Recreate role key: %s' % role.key_path)
|
||||
# 写入数据库
|
||||
role.name = role_name
|
||||
role.password = encrypt_role_pass
|
||||
role.comment = role_comment
|
||||
role.sudo = role_sudos
|
||||
|
||||
role.save()
|
||||
msg = u"更新系统角色: %s" % role.name
|
||||
|
@ -386,6 +394,7 @@ def perm_role_edit(request):
|
|||
return my_render('jperm/perm_role_edit.html', locals(), request)
|
||||
|
||||
|
||||
|
||||
@require_role('admin')
|
||||
def perm_role_push(request):
|
||||
"""
|
||||
|
@ -445,22 +454,184 @@ def perm_role_push(request):
|
|||
key_push = request.POST.get("use_publicKey")
|
||||
task = Tasks(push_resource)
|
||||
ret = {}
|
||||
ret_failed = []
|
||||
ret_failed = {}
|
||||
|
||||
# 因为要先建立用户,所以password 是必选项,
|
||||
# 而push key是在 password也完成的情况下的 可选项
|
||||
ret["password_push"] = task.add_multi_user(**role_pass)
|
||||
if ret["password_push"].get("status") != "success":
|
||||
ret_failed.append(1)
|
||||
# 因为要先建立用户,所以password 是必选项,而push key是在 password也完成的情况下的 可选项
|
||||
# 1. 以password 方式推送角色
|
||||
if password_push:
|
||||
ret["password_push"] = task.add_multi_user(**role_pass)
|
||||
if ret["password_push"].get("status") != "success":
|
||||
ret_failed["step1"] == "failed"
|
||||
|
||||
# 2. 以秘钥 方式推送角色
|
||||
if key_push:
|
||||
ret["password_push"] = task.add_multi_user(**role_pass)
|
||||
if ret["password_push"].get("status") != "success":
|
||||
ret_failed["step2-1"] = "failed"
|
||||
ret["key_push"] = task.push_multi_key(**role_key)
|
||||
if ret["key_push"].get("status") != "success":
|
||||
ret_failed.append(1)
|
||||
ret_failed["step2-2"] = "failed"
|
||||
|
||||
print ret
|
||||
# 3. 推送sudo配置文件
|
||||
sudo_chosen_aliase = {}
|
||||
sudo_alias = []
|
||||
for role in roles_obj:
|
||||
role_alias = [sudo.name for sudo in role.sudo.all()]
|
||||
sudo_alias.extend(role_alias)
|
||||
sudo_chosen_aliase[role.name] = ','.join(role_alias)
|
||||
sudo_chosen_obj = [PermSudo.objects.get(name=sudo_name) for sudo_name in set(sudo_alias)]
|
||||
|
||||
add_sudo_script = get_add_sudo_script(sudo_chosen_aliase, sudo_chosen_obj)
|
||||
ret_sudo = task.push_sudo_file(add_sudo_script)
|
||||
|
||||
if ret_sudo["step1"] != "ok" or ret_sudo["step2"] != "ok":
|
||||
ret_failed["step3"] = "failed"
|
||||
os.remove(add_sudo_script)
|
||||
|
||||
|
||||
# 结果汇总统计
|
||||
if ret_failed:
|
||||
return HttpResponse(u"推送失败")
|
||||
# 推送失败
|
||||
error = u"推送失败, 原因: %s 失败" % ','.join(ret_failed.keys())
|
||||
else:
|
||||
return HttpResponse(u"推送系统角色: %s" % ','.join(role_names))
|
||||
# 推送成功 回写push表
|
||||
msg = u"推送系统角色: %s" % ','.join(role_names)
|
||||
push = PermPush(is_public_key=bool(key_push), is_password=bool(password_push))
|
||||
push.save()
|
||||
push.asset_group = asset_groups_obj
|
||||
push.asset = calc_assets
|
||||
push.role = roles_obj
|
||||
push.save()
|
||||
|
||||
# 渲染 刷新数据
|
||||
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')
|
||||
def perm_sudo_list(request):
|
||||
"""
|
||||
list sudo commands alias
|
||||
:param request:
|
||||
:return:
|
||||
"""
|
||||
# 渲染数据
|
||||
header_title, path1, path2 = "Sudo命令", "别名管理", "查看别名"
|
||||
|
||||
# 获取所有sudo 命令别名
|
||||
sudos_list = PermSudo.objects.all()
|
||||
|
||||
# TODO: 搜索和分页
|
||||
keyword = request.GET.get('search', '')
|
||||
if keyword:
|
||||
sudos_list = sudos_list.filter(Q(name=keyword))
|
||||
|
||||
sudos_list, p, sudos, page_range, current_page, show_first, show_end = pages(sudos_list, request)
|
||||
|
||||
return my_render('jperm/perm_sudo_list.html', locals(), request)
|
||||
|
||||
|
||||
@require_role('admin')
|
||||
def perm_sudo_add(request):
|
||||
"""
|
||||
list sudo commands alias
|
||||
:param request:
|
||||
:return:
|
||||
"""
|
||||
# 渲染数据
|
||||
header_title, path1, path2 = "Sudo命令", "别名管理", "添加别名"
|
||||
|
||||
if request.method == "GET":
|
||||
return my_render('jperm/perm_sudo_add.html', locals(), request)
|
||||
|
||||
elif request.method == "POST":
|
||||
# 获取参数: name, comment
|
||||
name = request.POST.get("sudo_name")
|
||||
comment = request.POST.get("sudo_comment")
|
||||
commands = request.POST.get("sudo_commands")
|
||||
|
||||
sudo = PermSudo(name=name.strip(), comment=comment, commands=commands.strip())
|
||||
sudo.save()
|
||||
|
||||
msg = u"添加Sudo命令别名: %s" % name
|
||||
# 渲染数据
|
||||
header_title, path1, path2 = "Sudo命令", "别名管理", "查看别名"
|
||||
# 获取所有sudo 命令别名
|
||||
sudos_list = PermSudo.objects.all()
|
||||
|
||||
# TODO: 搜索和分页
|
||||
keyword = request.GET.get('search', '')
|
||||
if keyword:
|
||||
roles_list = sudos_list.filter(Q(name=keyword))
|
||||
|
||||
sudos_list, p, sudos, page_range, current_page, show_first, show_end = pages(sudos_list, request)
|
||||
|
||||
return my_render('jperm/perm_sudo_list.html', locals(), request)
|
||||
else:
|
||||
return HttpResponse(u"不支持该操作")
|
||||
|
||||
|
||||
@require_role('admin')
|
||||
def perm_sudo_edit(request):
|
||||
"""
|
||||
list sudo commands alias
|
||||
:param request:
|
||||
:return:
|
||||
"""
|
||||
# 渲染数据
|
||||
header_title, path1, path2 = "Sudo命令", "别名管理", "编辑别名"
|
||||
|
||||
sudo_id = request.GET.get("id")
|
||||
sudo = PermSudo.objects.get(id=sudo_id)
|
||||
if request.method == "GET":
|
||||
return my_render('jperm/perm_sudo_edit.html', locals(), request)
|
||||
|
||||
if request.method == "POST":
|
||||
name = request.POST.get("sudo_name")
|
||||
commands = request.POST.get("sudo_commands")
|
||||
comment = request.POST.get("sudo_comment")
|
||||
sudo.name = name.strip()
|
||||
sudo.commands = commands.strip()
|
||||
sudo.comment = comment
|
||||
sudo.save()
|
||||
|
||||
msg = u"更新命令别名: %s" % name
|
||||
# 渲染数据
|
||||
header_title, path1, path2 = "Sudo命令", "别名管理", "查看别名"
|
||||
# 获取所有sudo 命令别名
|
||||
sudos_list = PermSudo.objects.all()
|
||||
# TODO: 搜索和分页
|
||||
keyword = request.GET.get('search', '')
|
||||
if keyword:
|
||||
sudos_list = sudos_list.filter(Q(name=keyword))
|
||||
sudos_list, p, sudos, page_range, current_page, show_first, show_end = pages(sudos_list, request)
|
||||
return my_render('jperm/perm_sudo_list.html', locals(), request)
|
||||
|
||||
|
||||
@require_role('admin')
|
||||
def perm_sudo_delete(request):
|
||||
"""
|
||||
list sudo commands alias
|
||||
:param request:
|
||||
:return:
|
||||
"""
|
||||
if request.method == "POST":
|
||||
# 获取参数删除的role对象
|
||||
sudo_id = request.POST.get("id")
|
||||
sudo = PermSudo.objects.get(id=sudo_id)
|
||||
# 数据库里删除记录
|
||||
sudo.delete()
|
||||
return HttpResponse(u"删除角色: %s" % sudo.name)
|
||||
else:
|
||||
return HttpResponse(u"不支持该操作")
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -250,3 +250,12 @@ def check_role(asset_id, user):
|
|||
"""
|
||||
return user
|
||||
|
||||
|
||||
@register.filter(name='role_contain_which_sudos')
|
||||
def role_contain_which_sudos(role):
|
||||
"""
|
||||
get role sudo commands
|
||||
"""
|
||||
sudo_names = [sudo.name for sudo in role.sudo.all()]
|
||||
return ','.join(sudo_names)
|
||||
|
||||
|
|
|
@ -55,6 +55,17 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group">
|
||||
<label for="sudo" class="col-sm-2 control-label">角色Sudo命令<span class="red-fonts">*</span></label>
|
||||
<div class="col-sm-8" id="sudo_name">
|
||||
<select name="sudo_name" data-placeholder="请选择Sudo别名" class="chosen-select form-control m-b" multiple tabindex="2">
|
||||
{% for sudo in sudos %}
|
||||
<option >{{ sudo.name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group">
|
||||
<label for="role_comment" class="col-sm-2 control-label">备注</label>
|
||||
<div class="col-sm-8">
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
{% block content %}
|
||||
{% include 'nav_cat_bar.html' %}
|
||||
<div class="wrapper wrapper-content animated fadeInRight">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-4">
|
||||
<div class="ibox float-e-margins">
|
||||
|
@ -51,8 +50,8 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-4">
|
||||
<div class="ibox float-e-margins">
|
||||
<div class="ibox-title">
|
||||
|
@ -97,8 +96,8 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-4">
|
||||
<div class="ibox float-e-margins">
|
||||
<div class="ibox-title">
|
||||
|
@ -143,8 +142,60 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<div class="ibox float-e-margins">
|
||||
<div class="ibox-title">
|
||||
<span class="label label-primary"><b>推送主机</b></span>
|
||||
<div class="ibox-tools">
|
||||
<a class="collapse-link">
|
||||
<i class="fa fa-chevron-up"></i>
|
||||
</a>
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
|
||||
<i class="fa fa-wrench"></i>
|
||||
</a>
|
||||
<ul class="dropdown-menu dropdown-user">
|
||||
<li><a href="#"></a>
|
||||
</li>
|
||||
<li><a href="#"></a>
|
||||
</li>
|
||||
</ul>
|
||||
<a class="close-link">
|
||||
<i class="fa fa-times"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ibox-content">
|
||||
<div>
|
||||
<div class="text-left">
|
||||
<table class="table table-striped" id="ugedit" >
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-center">主机</th>
|
||||
<th class="text-center">主机组</th>
|
||||
<th class="text-center">使用密码</th>
|
||||
<th class="text-center">使用秘钥</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for host in push_info %}
|
||||
<tr class="gradeX">
|
||||
<td class="text-center"> {{ host.ip }} </td>
|
||||
<td class="text-center"> {{ host.group }} </td>
|
||||
<td class="text-center"> {{ host.password }} </td>
|
||||
<td class="text-center"> {{ host.pubkey }} </td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -56,6 +56,17 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group">
|
||||
<label for="sudo" class="col-sm-2 control-label">角色Sudo命令<span class="red-fonts">*</span></label>
|
||||
<div class="col-sm-8" id="sudo_name">
|
||||
<select name="sudo_name" data-placeholder="请选择Sudo别名" class="chosen-select form-control m-b" multiple tabindex="2">
|
||||
{% for sudo in role_sudos %}
|
||||
<option selected >{{ sudo.name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group">
|
||||
<label for="role_comment" class="col-sm-2 control-label">备注</label>
|
||||
<div class="col-sm-8">
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
<th class="text-center">名称 </th>
|
||||
<th class="text-center">备注</th>
|
||||
<th class="text-center">创建时间</th>
|
||||
<th class="text-center">sudo别名</th>
|
||||
<th class="text-center">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
@ -61,6 +62,7 @@
|
|||
<td class="text-center"> {{ role.name }} </td>
|
||||
<td class="text-center"> {{ role.comment }} </td>
|
||||
<td class="text-center"> {{ role.date_added | date:"Y-m-d H:i:s"}} </td>
|
||||
<td class="text-center"> {{ role | role_contain_which_sudos }} </td>
|
||||
<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_edit/?id={{ role.id }}" class="btn btn-xs btn-info">编辑</a>
|
||||
|
@ -98,6 +100,7 @@ function remove_role(role_id){
|
|||
del_row.remove()
|
||||
},
|
||||
error: function (msg) {
|
||||
console.log(msg)
|
||||
alert("失败: " + msg)
|
||||
}
|
||||
});
|
||||
|
|
|
@ -77,6 +77,16 @@
|
|||
</div>
|
||||
</div>
|
||||
</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_password" name="use_password">
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group">
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
<div class="form-group">
|
||||
<label for="rulename" class="col-sm-2 control-label">授权名称<span class="red-fonts">*</span></label>
|
||||
<div class="col-sm-8">
|
||||
<input id="rulename" name="rulename" placeholder="Rule Name" type="text" class="form-control" {% if error %}value="{{ username }}" {% endif %}>
|
||||
<input id="rulename" name="rulename" placeholder="Rule Name" type="text" class="form-control">
|
||||
</div>
|
||||
</div>
|
||||
<div class="hr-line-dashed"></div>
|
||||
|
@ -44,8 +44,9 @@
|
|||
<label for="user" class="col-sm-2 control-label">用户</label>
|
||||
<div class="col-sm-8">
|
||||
<select name="user" id="user" data-placeholder="用户名" class="chosen-select form-control m-b" multiple tabindex="2">
|
||||
|
||||
{% for user in users %}
|
||||
<option value="{{ user.name }}">{{ user.name }}</option>
|
||||
<option>{{ user.name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<span class="help-block m-b-none">用户和用户组必选一个</span>
|
||||
|
@ -55,6 +56,7 @@
|
|||
<label for="usergroup" class="col-sm-2 control-label">用户组</label>
|
||||
<div class="col-sm-8">
|
||||
<select name="usergroup" id="usergroup" data-placeholder="请选择用户组" class="chosen-select form-control m-b" multiple tabindex="2">
|
||||
|
||||
{% for user_group in user_groups %}
|
||||
<option value="{{ user_group.name }}">{{ user_group.name }}</option>
|
||||
{% endfor %}
|
||||
|
@ -86,7 +88,7 @@
|
|||
<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">
|
||||
<div class="col-sm-8" id="role_name">
|
||||
<select name="role" data-placeholder="请选择角色" class="chosen-select form-control m-b" multiple tabindex="2">
|
||||
{% for role in roles %}
|
||||
<option value="{{ role.name }}">{{ role.name }}</option>
|
||||
|
|
|
@ -0,0 +1,120 @@
|
|||
{% extends 'base.html' %}
|
||||
{% block self_head_css_js %}
|
||||
<link href="/static/css/plugins/datapicker/datepicker3.css" rel="stylesheet">
|
||||
<link href="/static/css/plugins/chosen/chosen.css" rel="stylesheet">
|
||||
<script src="/static/js/plugins/chosen/chosen.jquery.js"></script>
|
||||
{% endblock %}
|
||||
{% load mytags %}
|
||||
{% block content %}
|
||||
{% include 'nav_cat_bar.html' %}
|
||||
<div class="wrapper wrapper-content animated fadeInRight">
|
||||
<div class="row">
|
||||
<div class="col-lg-10">
|
||||
<div class="ibox float-e-margins">
|
||||
<div class="ibox-title">
|
||||
<h5>填写基本信息</h5>
|
||||
<div class="ibox-tools">
|
||||
<a class="collapse-link">
|
||||
<i class="fa fa-chevron-up"></i>
|
||||
</a>
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
|
||||
<i class="fa fa-wrench"></i>
|
||||
</a>
|
||||
<a class="close-link">
|
||||
<i class="fa fa-times"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ibox-content">
|
||||
<form method="post" id="sudoForm" class="form-horizontal" action="">
|
||||
{% 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 class="form-group">
|
||||
<label for="sudo_name" class="col-sm-2 control-label">命令别名<span class="red-fonts">*</span></label>
|
||||
<div class="col-sm-8">
|
||||
<input id="sudo_name" name="sudo_name" placeholder="Sudo Command Alias" type="text" class="form-control">
|
||||
</div>
|
||||
</div>
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group">
|
||||
<label for="sudo_commands_label" class="col-sm-2 control-label">系统命令<span class="red-fonts">*</span></label>
|
||||
<div class="col-sm-8">
|
||||
<textarea id="sudo_commands" name="sudo_commands" class="form-control" rows="3"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group">
|
||||
<label for="sudo_comment" class="col-sm-2 control-label">备注</label>
|
||||
<div class="col-sm-8">
|
||||
<input id="sudo_comment" name="sudo_comment" placeholder="Sudo Comment" type="text" class="form-control">
|
||||
</div>
|
||||
</div>
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-4 col-sm-offset-2">
|
||||
<button class="btn btn-white" type="reset">取消</button>
|
||||
<button id="submit_button" class="btn btn-primary" type="submit">确认保存</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% block self_footer_js %}
|
||||
<script>
|
||||
$(document).ready(function(){
|
||||
$("input.role").click(function(){
|
||||
if($("input.role[value=GA]").is( ":checked" )){
|
||||
$("#admin_groups").css("display", 'none');
|
||||
}
|
||||
else {
|
||||
|
||||
$("#admin_groups").css("display", 'block');
|
||||
}
|
||||
});
|
||||
|
||||
$('#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 src="/static/js/cropper/cropper.min.js"></script>
|
||||
<script src="/static/js/datapicker/bootstrap-datepicker.js"></script>
|
||||
{% endblock %}
|
||||
|
|
@ -0,0 +1,120 @@
|
|||
{% extends 'base.html' %}
|
||||
{% block self_head_css_js %}
|
||||
<link href="/static/css/plugins/datapicker/datepicker3.css" rel="stylesheet">
|
||||
<link href="/static/css/plugins/chosen/chosen.css" rel="stylesheet">
|
||||
<script src="/static/js/plugins/chosen/chosen.jquery.js"></script>
|
||||
{% endblock %}
|
||||
{% load mytags %}
|
||||
{% block content %}
|
||||
{% include 'nav_cat_bar.html' %}
|
||||
<div class="wrapper wrapper-content animated fadeInRight">
|
||||
<div class="row">
|
||||
<div class="col-lg-10">
|
||||
<div class="ibox float-e-margins">
|
||||
<div class="ibox-title">
|
||||
<h5>填写基本信息</h5>
|
||||
<div class="ibox-tools">
|
||||
<a class="collapse-link">
|
||||
<i class="fa fa-chevron-up"></i>
|
||||
</a>
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
|
||||
<i class="fa fa-wrench"></i>
|
||||
</a>
|
||||
<a class="close-link">
|
||||
<i class="fa fa-times"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ibox-content">
|
||||
<form method="post" id="sudoForm" class="form-horizontal" action="">
|
||||
{% 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 class="form-group">
|
||||
<label for="sudo_name" class="col-sm-2 control-label">命令别名<span class="red-fonts">*</span></label>
|
||||
<div class="col-sm-8">
|
||||
<input id="sudo_name" name="sudo_name" placeholder="Sudo Command Alias" type="text" class="form-control" value={{ sudo.name }}>
|
||||
</div>
|
||||
</div>
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group">
|
||||
<label for="sudo_commands_label" class="col-sm-2 control-label">系统命令<span class="red-fonts">*</span></label>
|
||||
<div class="col-sm-8">
|
||||
<textarea id="sudo_commands" name="sudo_commands" class="form-control" rows="3">{{ sudo.commands }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group">
|
||||
<label for="sudo_comment" class="col-sm-2 control-label">备注</label>
|
||||
<div class="col-sm-8">
|
||||
<input id="sudo_comment" name="sudo_comment" placeholder="Sudo Comment" type="text" class="form-control" value={{ sudo.commnet }}>
|
||||
</div>
|
||||
</div>
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-4 col-sm-offset-2">
|
||||
<button class="btn btn-white" type="reset">取消</button>
|
||||
<button id="submit_button" class="btn btn-primary" type="submit">确认保存</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% block self_footer_js %}
|
||||
<script>
|
||||
$(document).ready(function(){
|
||||
$("input.role").click(function(){
|
||||
if($("input.role[value=GA]").is( ":checked" )){
|
||||
$("#admin_groups").css("display", 'none');
|
||||
}
|
||||
else {
|
||||
|
||||
$("#admin_groups").css("display", 'block');
|
||||
}
|
||||
});
|
||||
|
||||
$('#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 src="/static/js/cropper/cropper.min.js"></script>
|
||||
<script src="/static/js/datapicker/bootstrap-datepicker.js"></script>
|
||||
{% endblock %}
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load mytags %}
|
||||
{% block content %}
|
||||
{% include 'nav_cat_bar.html' %}
|
||||
|
||||
<div class="wrapper wrapper-content animated fadeInRight">
|
||||
<div class="row">
|
||||
<div class="col-lg-10">
|
||||
<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">
|
||||
<h5> 所有Sudo命令别名</h5>
|
||||
<div class="ibox-tools">
|
||||
<a class="collapse-link">
|
||||
<i class="fa fa-chevron-up"></i>
|
||||
</a>
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
|
||||
<i class="fa fa-wrench"></i>
|
||||
</a>
|
||||
<a class="close-link">
|
||||
<i class="fa fa-times"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ibox-content">
|
||||
<div class="">
|
||||
<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">
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control input-sm" id="search_input" name="search" placeholder="Search">
|
||||
<div class="input-group-btn">
|
||||
<button id='search_btn' type="submit" class="btn btn-sm btn-primary">
|
||||
- 搜索 -
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<table class="table table-striped table-bordered table-hover " id="editable" >
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-center">命令别名 </th>
|
||||
<th class="text-center">系统命令</th>
|
||||
<th class="text-center">创建时间</th>
|
||||
<th class="text-center">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="edittbody">
|
||||
{% for sudo in sudos %}
|
||||
<tr class="gradeX" id={{ sudo.id }}>
|
||||
<td class="text-center"> {{ sudo.name }} </td>
|
||||
<td class="text-center"> {{ sudo.commands }} </td>
|
||||
<td class="text-center"> {{ sudo.date_added | date:"Y-m-d H:i:s"}} </td>
|
||||
<td class="text-center">
|
||||
{# <a href="/jperm/sudo/perm_sudo_detail/?id={{ sudo.id }}" class="btn btn-xs btn-primary">详情</a>#}
|
||||
<a href="/jperm/sudo/perm_sudo_edit/?id={{ sudo.id }}" class="btn btn-xs btn-info">编辑</a>
|
||||
<button onclick="remove_sudo({{ sudo.id }})" class="btn btn-xs btn-danger">删除</button>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<div class="dataTables_info" id="editable_info" role="status" aria-live="polite">
|
||||
Showing {{ users.start_index }} to {{ users.end_index }} of {{ p.count }} entries
|
||||
</div>
|
||||
</div>
|
||||
{% include 'paginator.html' %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<script>
|
||||
function remove_sudo(sudo_id){
|
||||
if (confirm("确认删除")) {
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: "/jperm/sudo/perm_sudo_delete/",
|
||||
data: "id=" + sudo_id,
|
||||
success: function(msg){
|
||||
alert( "成功: " + msg );
|
||||
var del_row = $('tbody#edittbody>tr#' + sudo_id);
|
||||
del_row.remove()
|
||||
},
|
||||
error: function (msg) {
|
||||
alert("失败: " + msg)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
{% endblock %}
|
||||
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
#!/bin/bash
|
||||
|
||||
|
||||
sudo_file=/etc/sudoers
|
||||
|
||||
|
||||
# Add Command Aliases
|
||||
add_cmd_alias() {
|
||||
{% for sudo in sudo_chosen_obj %}
|
||||
if $(grep '^Cmnd_Alias {{ sudo.name }}' ${sudo_file} &> /dev/null); then
|
||||
sed -i 's@^Cmnd_Alias.*{{ sudo.name }}.*@Cmnd_Alias {{ sudo.name }} = {{ sudo.commands }}@g' ${sudo_file}
|
||||
else
|
||||
echo "Cmnd_Alias {{ sudo.name }} = {{ sudo.commands }}" >> ${sudo_file}
|
||||
fi
|
||||
{% endfor %}
|
||||
}
|
||||
|
||||
|
||||
add_role_chosen() {
|
||||
{% for role, alias in sudo_chosen_aliase.items %}
|
||||
if $(grep '^{{ role }}' ${sudo_file} &> /dev/null); then
|
||||
sed -i 's@^{{ role }}.*@{{ role }} ALL = {{ alias }}@g' ${sudo_file}
|
||||
else
|
||||
echo "{{ role }} ALL = {{ alias }}" >> ${sudo_file}
|
||||
fi
|
||||
{% endfor %}
|
||||
}
|
||||
|
||||
|
||||
add_cmd_alias
|
||||
add_role_chosen
|
|
@ -28,9 +28,15 @@
|
|||
<a href="/jperm/rule/">授权规则</a>
|
||||
</li>
|
||||
|
||||
<li class="role">
|
||||
<li class="sudo_list sudo_edit sudo_add cmd_list cmd_edit cmd_add sudo_detail">
|
||||
<a href="/jperm/role/">系统角色</a>
|
||||
</li>
|
||||
<li class="sudo_list sudo_edit sudo_add cmd_list cmd_edit cmd_add sudo_detail">
|
||||
<a href="/jperm/sudo/">Sudo命令</a>
|
||||
</li>
|
||||
<li class="apply_show online"><a href="/jperm/apply_show/online/">权限审批</a></li>
|
||||
<li class="apply_show online"><a href="/jperm/log/">授权记录</a></li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
<li id="jlog">
|
||||
|
|
Loading…
Reference in New Issue