merge map

pull/26/head
yumaojun 2015-11-15 08:39:43 +08:00
commit 0862ffef98
39 changed files with 2749 additions and 168 deletions

View File

@ -96,7 +96,7 @@ def asset_add(request):
username = request.POST.get('username')
password = request.POST.get('password')
port = request.POST.get('port')
password_encode = CRYPTOR.encrypt(password)
password_encode = password
else:
username = None
port = None

12
jperm/README.md Normal file
View File

@ -0,0 +1,12 @@
# Jperm App
---
### 模块 ansible_api
> 使用说明
+ 依赖rpm安装包 ansible、 sshpass
+ 依赖pip安装包 passlib
+ 关于ansible配置 需要启用配置文件(/etc/ansible/ansible.cfg)的 host_key_checking = False

474
jperm/ansible_api.py Normal file
View File

@ -0,0 +1,474 @@
# -*- coding: utf-8 -*-
from ansible.inventory.group import Group
from ansible.inventory.host import Host
from ansible.inventory import Inventory
from ansible.runner import Runner
from ansible.playbook import PlayBook
from ansible import callbacks
from ansible import utils
from passlib.hash import sha512_crypt
from utils import get_rand_pass
import os.path
API_DIR = os.path.dirname(os.path.abspath(__file__))
ANSIBLE_DIR = os.path.join(API_DIR, 'playbooks')
class AnsibleError(StandardError):
"""
the base AnsibleError which contains error(required),
data(optional) and message(optional).
存储所有Ansible 异常对象
"""
def __init__(self, error, data='', message=''):
super(AnsibleError, self).__init__(message)
self.error = error
self.data = data
self.message = message
class CommandValueError(AnsibleError):
"""
indicate the input value has error or invalid.
the data specifies the error field of input form.
输入不合法 异常对象
"""
def __init__(self, field, message=''):
super(CommandValueError, self).__init__('value:invalid', field, message)
class MyInventory(object):
"""
this is my ansible inventory object.
"""
def __init__(self, resource):
"""
resource的数据格式是一个列表字典比如
{
"group1": {
"hosts": [{"hostname": "10.10.10.10", "port": "22", "username": "test", "password": "mypass"}, ...],
"vars": {"var1": value1, "var2": value2, ...}
}
}
如果你只传入1个列表这默认该列表内的所有主机属于my_group组,比如
[{"hostname": "10.10.10.10", "port": "22", "username": "test", "password": "mypass"}, ...]
"""
self.resource = resource
self.inventory = Inventory()
self.gen_inventory()
def add_group(self, hosts, groupname, groupvars=None):
"""
add hosts to a group
"""
my_group = Group(name=groupname)
# if group variables exists, add them to group
if groupvars:
for key, value in groupvars.iteritems():
my_group.set_variable(key, value)
# add hosts to group
for host in hosts:
# set connection variables
hostname = host.get("hostname")
hostport = host.get("port")
username = host.get("username")
password = host.get("password")
my_host = Host(name=hostname, port=hostport)
my_host.set_variable('ansible_ssh_host', hostname)
my_host.set_variable('ansible_ssh_port', hostport)
my_host.set_variable('ansible_ssh_user', username)
my_host.set_variable('ansible_ssh_pass', password)
# set other variables
for key, value in host.iteritems():
if key not in ["hostname", "port", "username", "password"]:
my_host.set_variable(key, value)
# add to group
my_group.add_host(my_host)
self.inventory.add_group(my_group)
def gen_inventory(self):
"""
add hosts to inventory.
"""
if isinstance(self.resource, list):
self.add_group(self.resource, 'my_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"))
class Command(MyInventory):
"""
this is a command object for parallel execute command.
"""
def __init__(self, *args, **kwargs):
super(Command, self).__init__(*args, **kwargs)
self.results = ''
def run(self, command, module_name="command", timeout=5, forks=10, group='my_group'):
"""
run command from andible ad-hoc.
command : 必须是一个需要执行的命令字符串 比如
'uname -a'
"""
if module_name not in ["raw", "command", "shell"]:
raise CommandValueError("module_name",
"module_name must be of the 'raw, command, shell'")
hoc = Runner(module_name=module_name,
module_args=command,
timeout=timeout,
inventory=self.inventory,
subset=group,
forks=forks
)
self.results = hoc.run()
if self.stdout:
return {"ok": self.stdout}
else:
msg = []
if self.stderr:
msg.append(self.stderr)
if self.dark:
msg.append(self.dark)
return {"failed": msg}
@property
def raw_results(self):
"""
get the ansible raw results.
"""
return self.results
@property
def exec_time(self):
"""
get the command execute time.
"""
result = {}
all = self.results.get("contacted")
for key, value in all.iteritems():
result[key] = {
"start": value.get("start"),
"end" : value.get("end"),
"delta": value.get("delta"),}
return result
@property
def stdout(self):
"""
get the comamnd standard output.
"""
result = {}
all = self.results.get("contacted")
for key, value in all.iteritems():
result[key] = value.get("stdout")
return result
@property
def stderr(self):
"""
get the command standard error.
"""
result = {}
all = self.results.get("contacted")
for key, value in all.iteritems():
result[key] = {
"stderr": value.get("stderr"),
"warnings": value.get("warnings"),}
return result
@property
def dark(self):
"""
get the dark results.
"""
return self.results.get("dark")
class Tasks(Command):
"""
this is a tasks object for include the common 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='my_group'):
"""
run command from andible ad-hoc.
command : 必须是一个需要执行的命令字符串 比如
'uname -a'
"""
hoc = Runner(module_name=module_name,
module_args=module_args,
timeout=timeout,
inventory=self.inventory,
subset=group,
forks=forks
)
self.results = hoc.run()
@property
def msg(self):
"""
get the contacted and dark msg
"""
msg = {}
for result in ["contacted", "dark"]:
all = self.results.get(result)
for key, value in all.iteritems():
if value.get("msg"):
msg[key] = value.get("msg")
return msg
def push_key(self, user, key_path):
"""
push the ssh authorized key to target.
"""
module_args = 'user="%s" key="{{ lookup("file", "%s") }}"' % (user, key_path)
self.__run(module_args, "authorized_key")
return {"status": "failed","msg": self.msg} if self.msg else {"status": "ok"}
def del_key(self, user, key_path):
"""
push the ssh authorized key to target.
"""
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"}
def add_user(self, username, password):
"""
add a host user.
"""
encrypt_pass = sha512_crypt.encrypt(password)
module_args = 'name=%s shell=/bin/bash password=%s' % (username, encrypt_pass)
self.__run(module_args, "user")
return {"status": "failed","msg": self.msg} if self.msg else {"status": "ok"}
def add_multi_user(self, *args):
"""
add multi user
:param args:
user
:return:
"""
results = {}
users = {}
action = results["action_info"] = {}
for user in args:
users[user] = get_rand_pass()
for user, password in users.iteritems():
ret = self.add_user(user, password)
action[user] = ret
results["user_info"] = users
return results
def del_user(self, username):
"""
delete a host user.
"""
module_args = 'name=%s state=absent remove=yes move_home=yes force=yes' % (username)
self.__run(module_args, "user")
return {"status": "failed","msg": self.msg} if self.msg else {"status": "ok"}
def add_init_users(self):
"""
add initail users: SA, DBA, DEV
"""
results = {}
action = results["action_info"] = {}
users = {"SA": get_rand_pass(), "DBA": get_rand_pass(), "DEV": get_rand_pass()}
for user, password in users.iteritems():
ret = self.add_user(user, password)
action[user] = ret
results["user_info"] = users
return results
def del_init_users(self):
"""
delete initail users: SA, DBA, DEV
"""
results = {}
action = results["action_info"] = {}
for user in ["SA", "DBA", "DEV"]:
ret = self.del_user(user)
action[user] = ret
return results
def get_host_info(self):
"""
use the setup module get host informations
:return:
all_ip is list
processor_count is int
system_dist_version is string
system_type is string
disk is dict (device_name: device_size}
system_dist is string
processor_type is string
default_ip is string
hostname is string
product_sn is string
memory_total is int (MB)
default_mac is string
product_name is string
"""
self.__run('', 'setup')
result = {}
all = self.results.get("contacted")
for key, value in all.iteritems():
setup =value.get("ansible_facts")
# get disk informations
disk_all = setup.get("ansible_devices")
disk_need = {}
for disk_name, disk_info in disk_all.iteritems():
if disk_name.startswith('sd') or disk_name.startswith('hd'):
disk_need[disk_name] = disk_info.get("size")
result[key] = {
"all_ip": setup.get("ansible_all_ipv4_addresses"),
"hostname" : setup.get("ansible_hostname" ),
"default_ip": setup.get("ansible_default_ipv4").get("address"),
"default_mac": setup.get("ansible_default_ipv4").get("macaddress"),
"product_name": setup.get("ansible_product_name"),
"processor_type": ' '.join(setup.get("ansible_processor")),
"processor_count": setup.get("ansible_processor_count"),
"memory_total": setup.get("ansible_memtotal_mb"),
"disk": disk_need,
"system_type": setup.get("ansible_system"),
"system_dist": setup.get("ansible_distribution"),
"system_dist_verion": setup.get("ansible_distribution_major_version"),
"product_sn": setup.get("ansible_product_serial")
}
return {"status": "failed", "msg": self.msg} if self.msg else {"status": "ok", "result": result}
class CustomAggregateStats(callbacks.AggregateStats):
"""
Holds stats about per-host activity during playbook runs.
"""
def __init__(self):
super(CustomAggregateStats, self).__init__()
self.results = []
def compute(self, runner_results, setup=False, poll=False,
ignore_errors=False):
"""
Walk through all results and increment stats.
"""
super(CustomAggregateStats, self).compute(runner_results, setup, poll,
ignore_errors)
self.results.append(runner_results)
def summarize(self, host):
"""
Return information about a particular host
"""
summarized_info = super(CustomAggregateStats, self).summarize(host)
# Adding the info I need
summarized_info['result'] = self.results
return summarized_info
class MyPlaybook(MyInventory):
"""
this is my playbook object for execute playbook.
"""
def __init__(self, *args, **kwargs):
super(MyPlaybook, self).__init__(*args, **kwargs)
def run(self, playbook_relational_path, extra_vars=None):
"""
run ansible playbook,
only surport relational path.
"""
stats = callbacks.AggregateStats()
playbook_cb = callbacks.PlaybookCallbacks(verbose=utils.VERBOSITY)
runner_cb = callbacks.PlaybookRunnerCallbacks(stats, verbose=utils.VERBOSITY)
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,
check=False)
self.results = pb.run()
@property
def raw_results(self):
"""
get the raw results after playbook run.
"""
return self.results
class App(MyPlaybook):
"""
this is a app object for inclue the common playbook.
"""
def __init__(self, *args, **kwargs):
super(App, self).__init__(*args, **kwargs)
if __name__ == "__main__":
pass
# resource = {
# "group1": {
# "hosts": [{"hostname": "127.0.0.1", "port": "22", "username": "root", "password": "xxx"},],
# "vars" : {"var1": "value1", "var2": "value2"},
# },
# }
# command = Command(resource)
# print command.run("who", group="group1")
# resource = [{"hostname": "192.168.10.148", "port": "22", "username": "root", "password": "xxx"}]
# task = Tasks(resource)
# print task.get_host_info()
# playbook = MyPlaybook(resource)
# playbook.run('test.yml')
# print playbook.raw_results
# task = Tasks(resource)
# print task.add_user('test', 'mypass')
# print task.del_user('test')
# print task.push_key('root', '/root/.ssh/id_rsa.pub')
# print task.del_key('root', '/root/.ssh/id_rsa.pub')
# task = Tasks(resource)
# print task.add_init_users()
# print task.del_init_users()

View File

@ -1,8 +1,8 @@
import datetime
from django.db import models
from juser.models import User, UserGroup
from jasset.models import Asset, AssetGroup
from juser.models import User, UserGroup
class PermLog(models.Model):
@ -19,3 +19,27 @@ class SysUser(models.Model):
comment = models.CharField(max_length=100, null=True, blank=True, default='')
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)
def __unicode__(self):
return self.name
class PermRule(models.Model):
date_added = models.DateTimeField(auto_now=True)
name = models.CharField(max_length=100)
comment = models.CharField(max_length=100)
asset = models.ManyToManyField(Asset, related_name='perm_rule')
asset_group = models.ManyToManyField(AssetGroup, related_name='perm_rule')
user = models.ManyToManyField(User, related_name='perm_rule')
user_group = models.ManyToManyField(UserGroup, related_name='perm_rule')
role = models.ManyToManyField(PermRole, related_name='perm_rule')
ssh_type = models.BooleanField()
def __unicode__(self):
return self.name

View File

@ -1,6 +1,6 @@
# coding: utf-8
from jasset.models import *
from jumpserver.api import *
import uuid
import re
@ -9,6 +9,8 @@ from jumpserver.tasks import playbook_run
from jumpserver.models import Setting
from jperm.models import PermLog
from jperm.models import PermRole
def get_object_list(model, id_list):
"""根据id列表获取对象列表"""
@ -281,8 +283,62 @@ def push_user(user, asset_groups_id):
return results
def get_role_info(role_id, type="all"):
"""
获取role对应的一些信息
:return: 返回值 均为对象列表
"""
# 获取role对应的授权规则
role_obj = PermRole.objects.get(id=role_id)
rules_obj = role_obj.perm_rule.all()
# 获取role 对应的用户 和 用户组
# 获取role 对应的主机 和主机组
users_obj = []
assets_obj = []
user_groups_obj = []
group_users_obj = []
asset_groups_obj = []
group_assets_obj = []
for rule in rules_obj:
for user in rule.user.all():
users_obj.append(user)
for asset in rule.asset.all():
assets_obj.append(asset)
for user_group in rule.user_group.all():
user_groups_obj.append(user_group)
for user in user_group.user_set.all():
group_users_obj.append(user)
for asset_group in rule.asset_group.all():
asset_groups_obj.append(asset_group)
for asset in asset_group.asset_set.all():
group_assets_obj.append(asset)
calc_users = set(users_obj) | set(group_users_obj)
calc_assets = set(assets_obj) | set(group_assets_obj)
if type == "all":
return {"rules": rules_obj,
"users": list(calc_users),
"user_groups": user_groups_obj,
"assets": list(calc_assets),
"asset_groups": asset_groups_obj,
}
elif type == "rule":
return rules_obj
elif type == "user":
return calc_users
elif type == "user_group":
return user_groups_obj
elif type == "asset":
return calc_assets
elif type == "asset_group":
return asset_groups_obj
else:
return u"不支持的查询"
if __name__ == "__main__":
print get_role_info(1)

View File

@ -0,0 +1,12 @@
---
- hosts: 'add_users_group'
gather_facts: no
tasks:
- name: add SA user
command: uname -a

9
jperm/playbooks/test.yml Normal file
View File

@ -0,0 +1,9 @@
---
- hosts: test
gather_facts: no
tasks:
- name: just for test
command: uname -a

View File

@ -0,0 +1,51 @@
-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----

View File

@ -0,0 +1 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDXDRoQwHevjEVqM2JeVgkADM2aVxEm/yQHCpqYqREe0xGGrSSCykEZGp+O+q5FRZwFEgbZkCykJRrI3+3kEr6zB83N3P2oy/qd0pRTkA0tS50uctQA4aIp9kyOQOKLx8Uttmta0+nLwYKBSSPgJPL1xwC+sVMVvMwsIXyWGzgIWV0KZIrjNYjgEpxU0cQ7pJLXCrw5dM+fMdWvP9MDyMfX5iYZwIaYwnnTY1qO+fNewDbiFSDTo5AzcYnAUsNsRjOqWrNazMEB3o6ZoH8fANlJCJ5Jgeu/IV6UcRAYGYXq924I6AwTVENiDVf3o1lfBvAqTmNfIo25TgZCzewFGl0cuRdKVP6j0qps6N1ZBRVE8NtT4fmg8gP05OGHzz9j8rsPzCpsnQXByYJ927u7ypIm2+xCAhvqElsyJeR5yFs9J9SFa6ix9UzO2hEhO0ypU8ioNU99DbMEhZ4jXwRl63sK5AWUzf3akNGzUDLlttw86SIjV9dt6kOyhKpE8oVVB56DrmHx76uC0Dd75QojDyQQUnLX+pd9OngCCIu+VVWB175+LhDduDRBIrWsFsOciqzCS4LwB5rQFj/6dikfDDKt++M5qOzLeVnnKcMGucH8uHK8JVEB8yZMhsTkha4vxvrh1XsoTxwIqSs9JbUVI2ZjARSO+t8JU4meSV/HL+QeCQ==

View File

@ -0,0 +1,51 @@
-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----

View File

@ -0,0 +1 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC5NOm3k5bZLzjsM1YhHskQUvNsk9tGwYTx7+UQ1o1HBJ00C05f+e6FwfyG0wWjVS+WRLVE95JrqLhOKzOFHmxBuA4eA+rSQewjljkJH35ZYhcuqUSpGTU7mSVgQaE7iSJxTfu0vnydsWYbP9IW04LmX5tg2OC69LL5M0NE+LFm07m7rAZTfXpTLs3p4zCKKIfu7jVXtnCwnd3dc5oJpbumuqci2MPKvl4vTIGBBJz3MUqYFxSvsTvBPDop4oV738mso6wuFQQNvVFvt+BCelBkws3Im3Ij0his6OVROAkzw8MLTty3VSPfVcmHM6IEuD/q2GacQafK+BSTADkpmIjyJEKf5U6vftjwW18/rLMJ/CrbFEYigSmNQMSwkY/uOwSzxAPHrW37WA7fxybR8T7o895ELisUd3EhS8al8W4A0QVmkZ+l09uaHW/BrxJ8TuJSPTTfU++vCPfmDb3HQ5A9KH+yO9k8IHuFY5OFwuRGURsUx0kMV8D4YpbsAjwA0xyGw+20zFHC49bgfZj26/tOV2GIPfW9JXR5GXeFgGR9j3QJc6QXJQXgPhLRDzrhtAlyV/iqOeXHOhyq/73lIRu3FWu4IuVuIoIcUQRQfW67ihifywQxIPjlRo6vgXND4J7ugVPZPwHJZ0mCimtMj3vOQ9E6XOFim3+v4dH8M0GZpQ==

View File

@ -0,0 +1,51 @@
-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----

View File

@ -0,0 +1 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDBlmj6CGfjmP+1pPxaH5otomnU6ShYLs0Oxo19FpzCsWnSstFZMHv7So3zH0l3qvyfqxQzG38T7rkOwu0Ksdp7I6E7Qqov6GxONpsdpOQQisYgdzMdWzpJ2M+fEru/68QCiKCdLs2PUP3T7JwgIf3S0Vqi+qBxGs/aKALL8m2bpjp8Nvo0TVKdEH6LtpYJ/L1gfrMRSIf/Crt9JEjo3GGeN/U94WCU4iBunZL37g/oQ6U+RlylxFiDrrITBYA1cdXGAEY8ts5lvypKGCU7JFHW3YLv6ZlBZud16y8C9J1RjxSTh9RZc6w1p1j4b1hjyNAWSgHLvlCQEo5TKVMMTGx/sR+yVGR1gL8Cr2cPNJoXeDJhKjqlKYCYIdNLFJHx68C+A5ONYrANeHZbCQwsIgZLqD5Zd5nUxC/5z+5y2RU29SuqNktVeGkDpeofn0cQNH2RYZAKdA+EWnMeebr+zgNloXyp9SgR0loPUMk3dXwiWg714DhUoM3HhE2JhJwhyamFKPd13t5mokpLSMzBIae+o84iFDy5MplFASf66k5ZhnQ4/M9QIB6DgyJmo20HN4PvNg8Wbsz06iPbJqYBP4LgaooKQh5QitrvvQg4KZ/mi8jXBsrbeONxcbVlCuFQ3DUZ3MghGx65k/aGDrDk0nuE8p9iDrl8FKf+wgwS4+fMpw==

View File

@ -0,0 +1,51 @@
-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----

View File

@ -0,0 +1 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCcN2e3DZBEWLZcw/20Mo39H8leTUhXshy7JAriAoJoDfiMAy2fqhE3RbvipD3xcKcYWzrX9lEfp6mw1PyStVbcy7NqJ0spMnnNSQpqA0T2K2ySeVzVOfMhUHQOsyraVG7HizvtTHNzFqBOvucxdfEaCYKw+NWDsRCOIn9VjBUjK4fnL2qxeOiWP9ZsiOYSNH0wkhJYPjx0vPxVLbbDnOl4fSU+Do/bIeq0TZ4jY7XP9ctCSxQVztZCvR70AZBei5PpB9kii/CbsiRgprj9r8wz/TrfjiWTt+J0cBjpschDvOpuVXNMqgD+WF0408XJgXsKatmwRl6eQc86TtpKMsvhj+R3cF3Fj2Q8fJFKGmoHHbG3V3Z2lc2KwvjcjDWwy2/tY8bT9uLDQZYLxEGV+Mjbux/qDytMC5vWXKXVm0J7FBrWy8RqhWb+lTAm7nH1gSfAkrlHZRyHz49bMUwkajDFS9QcBmd0kJ/MDIGsiNxg+MFQrJzXkSw8QHhXWRDDNHu4eh5rPbYwPVNobonkBy3Jf0WPB75qumE7JtoHLKcRyk2zWEDwSrVZ9Z8/faaFh9AMVkP++WCg5R+alovn906zcXZei0Nx91q7+nki2RMfP+uZsRWJllCiZz6GfNp6Ry8vHfJ2K58uKCH0OEluoN/14wVM+RaEER+F0Ceo0QyDaQ==

0
jperm/template_filter.py Normal file
View File

View File

@ -2,13 +2,22 @@ from django.conf.urls import patterns, include, url
from jperm.views import *
urlpatterns = patterns('jperm.views',
(r'^user/$', perm_user_list),
(r'^perm_user_edit/$', perm_user_edit),
(r'^group/$', perm_group_list),
(r'^perm_group_edit/$', perm_group_edit),
(r'^rule/$', perm_rule_list),
(r'^perm_rule_add/$', perm_rule_add),
(r'^perm_rule_detail/$', perm_rule_detail),
(r'^perm_rule_edit/$', perm_rule_edit),
(r'^perm_rule_delete/$', perm_rule_delete),
(r'^role/$', perm_role_list),
(r'^role/perm_role_add/$', perm_role_add),
(r'^role/perm_role_delete/$', perm_role_delete),
(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'^log/$', log),
(r'^sys_user_add/$', sys_user_add),
(r'^sys_user_list/$', sys_user_list),
(r'^perm_user_list/$', sys_user_list),
(r'^sys_user_del/$', sys_user_del),
(r'^sys_user_edit/$', sys_user_edit),
)

68
jperm/utils.py Normal file
View File

@ -0,0 +1,68 @@
# -*- coding: utf-8 -*-
import random
import os.path
from Crypto.PublicKey import RSA
from os import chmod, mkdir
from uuid import uuid4
PERM_DIR = os.path.dirname(os.path.abspath(__file__))
KEY_DIR = os.path.join(PERM_DIR, 'role_keys')
def get_rand_pass():
"""
get a reandom password.
"""
lower = [chr(i) for i in range(97,123)]
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):
"""
surport update multi dict
"""
result = {}
for d in args:
result.update(d)
return result
def gen_keys():
"""
在KEY_DIR下创建一个 uuid命名的目录
并且在该目录下 生产一对秘钥
:return: 返回目录名(uuid)
"""
key_basename = "keys-" + uuid4().hex
key_path_dir = os.path.join(KEY_DIR, key_basename)
mkdir(key_path_dir, 0700)
key = RSA.generate(4096)
private_key = os.path.join(key_path_dir, 'id_rsa')
public_key = os.path.join(key_path_dir, 'id_rsa.pub')
with open(private_key, 'w') as content_file:
content_file.write(key.exportKey('PEM'))
with open(public_key, 'w') as content_file:
content_file.write(key.publickey().exportKey('OpenSSH'))
return key_path_dir
if __name__ == "__main__":
print gen_keys()

File diff suppressed because one or more lines are too long

1
jperm/views.py.back Normal file

File diff suppressed because one or more lines are too long

View File

@ -1,21 +1,20 @@
#coding: utf8
[base]
url = http://192.168.244.129
url = http://127.0.0.1
key = 88aaaf7ffe3c6c04
log = debug
[db]
host = 127.0.0.1
port = 3306
user = jumpserver
password = mysql234
password =mysql1234
database = jumpserver
[websocket]
web_socket_host = 192.168.244.129:3000
web_socket_host = 127.0.0.1:3000
[mail]

View File

@ -6,7 +6,7 @@ from django.db import models
class Setting(models.Model):
name = models.CharField(max_length=100)
default_user = models.CharField(max_length=100, null=True, blank=True)
default_port = models.IntegerField(max_length=10, null=True, blank=True)
default_port = models.IntegerField(null=True, blank=True)
default_password = models.CharField(max_length=100, null=True, blank=True)
default_pri_key_path = models.CharField(max_length=100, null=True, blank=True)

View File

@ -18,6 +18,7 @@ config = ConfigParser.ConfigParser()
BASE_DIR = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
config.read(os.path.join(BASE_DIR, 'jumpserver.conf'))
DB_HOST = config.get('db', 'host')
DB_PORT = config.getint('db', 'port')
DB_USER = config.get('db', 'user')
@ -69,6 +70,7 @@ INSTALLED_APPS = (
'jasset',
'jperm',
'jlog',
)
MIDDLEWARE_CLASSES = (

View File

@ -1,4 +1,4 @@
# coding: utf-8
# -*- coding: utf-8 -*-
from ansible.playbook import PlayBook
from ansible import callbacks, utils
@ -45,3 +45,4 @@ def playbook_run(inventory, playbook, default_user=None, default_port=None, defa
results_r['success'].append(hostname)
print "%s >>> Success" % hostname
return results_r

Binary file not shown.

View File

@ -123,3 +123,62 @@ def result2bool(result=''):
return '<b style="color: red">失败</b>'
else:
return '<b style="color: green">成功</b>'
@register.filter(name='rule_member_count')
def rule_member_count(instance, member):
"""
instance is a rule object,
use to get the number of the members
:param instance:
:param member:
:return:
"""
member = getattr(instance, member)
counts = member.all().count()
return str(counts)
@register.filter(name='rule_member_name')
def rule_member_name(instance, member):
"""
instance is a rule object,
use to get the name of the members
:param instance:
:param member:
:return:
"""
member = getattr(instance, member)
names = member.all()
return names
@register.filter(name='user_which_groups')
def user_which_group(user, member):
"""
instance is a user object,
use to get the group of the user
:param instance:
:param member:
:return:
"""
member = getattr(user, member)
names = [members.name for members in member.all()]
return ','.join(names)
@register.filter(name='asset_which_groups')
def asset_which_group(asset, member):
"""
instance is a user object,
use to get the group of the user
:param instance:
:param member:
:return:
"""
member = getattr(asset, member)
names = [members.name for members in member.all()]
return ','.join(names)

View File

@ -3,14 +3,11 @@
from django.db import models
from django.contrib.auth.models import AbstractUser
from jasset.models import Asset, AssetGroup
class UserGroup(models.Model):
name = models.CharField(max_length=80, unique=True)
comment = models.CharField(max_length=160, blank=True, null=True)
asset = models.ManyToManyField(Asset)
asset_group = models.ManyToManyField(AssetGroup)
def __unicode__(self):
return self.name
@ -27,6 +24,11 @@ class User(AbstractUser):
role = models.CharField(max_length=2, choices=USER_ROLE_CHOICES, default='CU')
group = models.ManyToManyField(UserGroup)
ssh_key_pwd = models.CharField(max_length=200)
# is_active = models.BooleanField(default=True)
# last_login = models.DateTimeField(null=True)
# date_joined = models.DateTimeField(null=True)
def __unicode__(self):
return self.username

0
logs/jumpserver.log Normal file
View File

View File

@ -0,0 +1,113 @@
{% 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="userForm" 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="role_name" class="col-sm-2 control-label">规则名称<span class="red-fonts">*</span></label>
<div class="col-sm-8">
<input id="role_name" name="role_name" placeholder="Role Name" type="text" class="form-control" {% if error %}value="{{ role.name }}" {% endif %}>
</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">
<input id="role_comment" name="role_comment" placeholder="Role Comment" type="text" class="form-control" {% if error %}value="{{ role.comment }}" {% endif %}>
</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 %}

View File

@ -0,0 +1,161 @@
{% 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-4">
<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>
</tr>
</thead>
<tbody>
{% for rule in rules %}
<tr class="gradeX">
<td class="text-center"> {{ rule.date_added | date:"Y-m-d H:i:s"}} </td>
<td class="text-center"> {{ rule.name }} </td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<div class="col-lg-4">
<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>
</tr>
</thead>
<tbody>
{% for user in users %}
<tr class="gradeX">
<td class="text-center"> {{ user.name }} </td>
<td class="text-center"> {{ user | user_which_groups:"group" }} </td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<div class="col-lg-4">
<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="agedit" >
<thead>
<tr>
<th class="text-center">主机</th>
<th class="text-center">主机组</th>
</tr>
</thead>
<tbody>
{% for asset in assets %}
<tr class="gradeX">
<td class="text-center"> {{ asset.ip }} </td>
<td class="text-center"> {{ asset | asset_which_groups:"group" }} </td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function(){
$('#show').click(function(){
$('#last').css('display', 'none');
$('#all').css('display', 'block');
})
})
</script>
{% endblock %}

View File

@ -0,0 +1,113 @@
{% 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="userForm" 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="role_name" class="col-sm-2 control-label">规则名称<span class="red-fonts">*</span></label>
<div class="col-sm-8">
<input id="role_name" name="role_name" placeholder="Role Name" type="text" class="form-control" value="{{ role.name }}">
</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">
<input id="role_comment" name="role_comment" placeholder="Role Comment" type="text" class="form-control" value="{{ role.comment }}">
</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 %}

View File

@ -8,7 +8,7 @@
<div class="col-lg-10">
<div class="ibox float-e-margins">
<div class="ibox-title">
<h5> 查看小组</h5>
<h5> 所有系统角色</h5>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
@ -24,7 +24,9 @@
<div class="ibox-content">
<div class="">
<a target="_blank" href="/juser/user_add/" class="btn btn-sm btn-primary "> 添加用户 </a>
<a target="_blank" href="/jperm/role/perm_role_add/" class="btn btn-sm btn-primary "> 添加角色 </a>
<a target="_blank" 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">
<div class="input-group">
<input type="text" class="form-control input-sm" id="search_input" name="search" placeholder="Search">
@ -40,25 +42,22 @@
<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>
<th class="text-center">名称 </th>
<th class="text-center">备注</th>
<th class="text-center">创建时间</th>
<th class="text-center">操作</th>
</tr>
</thead>
<tbody>
{% for user in users.object_list %}
<tr class="gradeX">
<td class="text-center"> {{ user.name }} </td>
<tbody id="edittbody">
{% for role in roles %}
<tr class="gradeX" id={{ role.id }}>
<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">
<a href="/juser/user_list/?gid={{ user.id }}">{{ user.group.all | groups2str }} </a>
</td>
<td class="text-center"> <a href="/jasset/asset_list/?gid={{ user.id }}">{{ user.name }} </a> </td>
<td class="text-center"> <a href="/jasset/group_list/?gid={{ user.id }}">{{ user.name }}</a></td>
<td class="text-center">
<a href="../perm_user_detail/?id={{ user.id }}" class="btn btn-xs btn-primary">详情</a>
<a href="../perm_user_edit/?id={{ user.id }}" class="btn btn-xs btn-danger">编辑</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>
<button onclick="remove_role({{ role.id }})" class="btn btn-xs btn-danger">删除</button>
</td>
</tr>
{% endfor %}
@ -78,4 +77,29 @@
</div>
</div>
<script>
function remove_role(role_id){
if (confirm("确认删除")) {
$.ajax({
type: "POST",
url: "/jperm/role/perm_role_delete/",
data: "id=" + role_id,
success: function(msg){
alert( "成功: " + msg );
var del_row = $('tbody#edittbody>tr#' + role_id);
del_row.remove()
},
error: function (msg) {
alert("失败: " + msg)
}
});
}
}
</script>
{% endblock %}

View File

@ -0,0 +1,162 @@
{% 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="userForm" 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="asset" class="col-sm-2 control-label">资产<span class="red-fonts">*</span></label>
<div class="col-sm-8">
<select name="assets" data-placeholder="请选择资产" class="chosen-select form-control m-b" multiple tabindex="2">
{% for asset in assets %}
<option value="{{ asset.ip }}">{{ asset.ip }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="assetgroup" class="col-sm-2 control-label">资产组<span class="red-fonts">*</span></label>
<div class="col-sm-8">
<select name="asset_groups" data-placeholder="请选择资产组" class="chosen-select form-control m-b" multiple tabindex="2">
{% for asset_group in asset_groups %}
<option value="{{ asset_group.name }}">{{ asset_group.name }}</option>
{% endfor %}
</select>
</div>
</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.name }}">{{ role.name }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="row">
<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 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>
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="comment" class="col-sm-2 control-label">备注</label>
<div class="col-sm-8">
<input id="comment" name="comment" placeholder="Comment" type="text" class="form-control" {% if error %}value="{{ username }}" {% endif %}>
</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 %}

View File

@ -0,0 +1,209 @@
{% 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="userForm" 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="username" 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 %}>
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="user" class="col-sm-2 control-label">用户<span class="red-fonts">*</span></label>
<div class="col-sm-8">
<select name="user" data-placeholder="用户名" class="chosen-select form-control m-b" multiple tabindex="2">
{% for user in users %}
<option value="{{ user.name }}">{{ user.name }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="usergroup" class="col-sm-2 control-label">用户组<span class="red-fonts">*</span></label>
<div class="col-sm-8">
<select name="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 %}
</select>
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="asset" class="col-sm-2 control-label">资产<span class="red-fonts">*</span></label>
<div class="col-sm-8">
<select name="asset" data-placeholder="请选择资产" class="chosen-select form-control m-b" multiple tabindex="2">
{% for asset in assets %}
<option value="{{ asset.ip }}">{{ asset.ip }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="assetgroup" class="col-sm-2 control-label">资产组<span class="red-fonts">*</span></label>
<div class="col-sm-8">
<select name="assetgroup" data-placeholder="请选择资产组" class="chosen-select form-control m-b" multiple tabindex="2">
{% for asset_group in asset_groups %}
<option value="{{ asset_group.name }}">{{ asset_group.name }}</option>
{% endfor %}
</select>
</div>
</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="role" data-placeholder="请选择角色" class="chosen-select form-control m-b" multiple tabindex="2">
{% for role in roles %}
<option value="{{ role.name }}">{{ role.name }}</option>
{% endfor %}
</select>
</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="0" id="use_password" name="use_password">
</label>
</div>
</div>
</div>
<div class="form-group" id="admin_account_password" style="display: none">
<label class="col-sm-1 control-label"> 密码<span class="red-fonts">*</span> </label>
<div class="col-sm-4">
<input type="password" name="password" class="form-control">
</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="form-group" id="admin_account_publicKey" style="display: none">
<label class="col-sm-1 control-label"> 秘钥<span class="red-fonts">*</span> </label>
<div class="col-sm-4">
<input type="password" name="password" class="form-control">
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="comment" class="col-sm-2 control-label">备注</label>
<div class="col-sm-8">
<input id="comment" name="comment" placeholder="Rule Comment" type="text" class="form-control" {% if error %}value="{{ username }}" {% endif %}>
</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 %}

View File

@ -0,0 +1,168 @@
{% 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-4">
<div class="ibox float-e-margins">
<div class="ibox-title">
<span class="label label-primary"><b>{{ rule.name }}</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">
<tr>
<td class="text-navy">ID</td>
<td>{{ rule.id }}</td>
</tr>
<tr>
<td class="text-navy">名称</td>
<td>{{ rule.name }}</td>
</tr>
<tr>
<td class="text-navy">时间</td>
<td>{{ rule.date_added | date:"Y-m-d H:i:s"}}</td>
</tr>
<tr>
<td class="text-navy">角色</td>
<td>{{ roles_name }}</td>
</tr>
<tr>
<td class="text-navy">激活</td>
<td></td>
</tr>
</table>
</div>
</div>
</div>
</div>
</div>
<div class="col-lg-4">
<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>
</tr>
</thead>
<tbody>
{% for user in users %}
<tr class="gradeX">
<td class="text-center"> {{ user.name }} </td>
<td class="text-center"> {{ user | user_which_groups:"group" }} </td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<div class="col-lg-4">
<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="agedit" >
<thead>
<tr>
<th class="text-center">主机</th>
<th class="text-center">主机组</th>
</tr>
</thead>
<tbody>
{% for asset in assets %}
<tr class="gradeX">
<td class="text-center"> {{ asset.ip }} </td>
<td class="text-center"> {{ asset | asset_which_groups:"group" }} </td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function(){
$('#show').click(function(){
$('#last').css('display', 'none');
$('#all').css('display', 'block');
})
})
</script>
{% endblock %}

View File

@ -0,0 +1,209 @@
{% 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="userForm" 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="username" class="col-sm-2 control-label">授权名称<span class="red-fonts">*</span></label>
<div class="col-sm-8">
<input id="rulename" name="rulename" placeholder="RuleName" type="text" class="form-control" value="{{ rule.name }}">
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="user" class="col-sm-2 control-label">用户<span class="red-fonts">*</span></label>
<div class="col-sm-8">
<select name="user" data-placeholder="用户名" class="chosen-select form-control m-b" multiple tabindex="2">
{% for user in users %}
<option value="{{ user.name }}">{{ user.name }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="usergroup" class="col-sm-2 control-label">用户组<span class="red-fonts">*</span></label>
<div class="col-sm-8">
<select name="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 %}
</select>
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="asset" class="col-sm-2 control-label">资产<span class="red-fonts">*</span></label>
<div class="col-sm-8">
<select name="asset" data-placeholder="请选择资产" class="chosen-select form-control m-b" multiple tabindex="2">
{% for asset in assets %}
<option value="{{ asset.ip }}">{{ asset.ip }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="assetgroup" class="col-sm-2 control-label">资产组<span class="red-fonts">*</span></label>
<div class="col-sm-8">
<select name="assetgroup" data-placeholder="请选择资产组" class="chosen-select form-control m-b" multiple tabindex="2">
{% for asset_group in asset_groups %}
<option value="{{ asset_group.name }}">{{ asset_group.name }}</option>
{% endfor %}
</select>
</div>
</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="role" data-placeholder="请选择角色" class="chosen-select form-control m-b" multiple tabindex="2">
{% for role in roles %}
<option value="{{ role.name }}">{{ role.name }}</option>
{% endfor %}
</select>
</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="0" id="use_password" name="use_password">
</label>
</div>
</div>
</div>
<div class="form-group" id="admin_account_password" style="display: none">
<label class="col-sm-1 control-label"> 密码<span class="red-fonts">*</span> </label>
<div class="col-sm-4">
<input type="password" name="password" class="form-control">
</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="form-group" id="admin_account_publicKey" style="display: none">
<label class="col-sm-1 control-label"> 秘钥<span class="red-fonts">*</span> </label>
<div class="col-sm-4">
<input type="password" name="password" class="form-control">
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="comment" class="col-sm-2 control-label">备注</label>
<div class="col-sm-8">
<input id="comment" name="comment" placeholder="Comment" type="text" class="form-control" {% if error %}value="{{ username }}" {% endif %}>
</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 %}

View File

@ -0,0 +1,120 @@
{% 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 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">
<div class="">
<a target="_blank" href="/jperm/perm_rule_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>
<th class="text-center">资产组</th>
<th class="text-center">角色</th>
<th class="text-center">操作</th>
</tr>
</thead>
<tbody id="edittbody">
{% for rule in rules %}
<tr class="gradeX" id={{ rule.id }}>
<td class="text-center"> {{ rule.name }} </td>
<td class="text-center">
<a href="/jasset/asset_list/?gid={{ user.id }}">{{ rule | rule_member_count:"user" }} </a>
</td>
<td class="text-center">
<a href="/jasset/group_list/?gid={{ user.id }}">{{ rule | rule_member_count:"user_group" }}</a>
</td>
<td class="text-center">
<a href="/jasset/group_list/?gid={{ user.id }}">{{ rule | rule_member_count:"asset" }}</a>
</td>
<td class="text-center">
<a href="/jasset/group_list/?gid={{ user.id }}">{{ rule | rule_member_count:"asset_group" }}</a>
</td>
<td class="text-center">
<a href="/jasset/group_list/?gid={{ user.id }}">{{ rule | rule_member_count:"role" }}</a>
</td>
<td class="text-center">
<a href="/jperm/perm_rule_detail/?id={{ rule.id }}" class="btn btn-xs btn-primary">详情</a>
<a href="/jperm/perm_rule_edit/?id={{ rule.id }}" class="btn btn-xs btn-info">编辑</a>
<button onclick="remove_rule({{ rule.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_rule(rule_id){
if (confirm("确认删除")) {
$.ajax({
type: "POST",
url: "/jperm/perm_rule_delete/",
data: "id=" + rule_id,
success: function(msg){
alert( "成功: " + msg );
var del_row = $('tbody#edittbody>tr#' + rule_id);
del_row.remove()
},
error: function (msg) {
alert("失败: " + msg)
}
});
}
}
</script>
{% endblock %}

View File

@ -1,122 +0,0 @@
{% 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 class="ibox-title">
<h5> {{ user.name }}授权修改</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 id="userPerm" method="post" class="form-horizontal" action="../perm_user_edit/?id={{ user.id }}">
{% 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="row">
<div class="form-group">
<label for="" class="col-sm-2 control-label">用户<span class="red-fonts">*</span></label>
<div class="col-sm-4">
<input id="user_group_name" name="user_group_name" type="text" class="form-control" value="{{ user.name }}" readonly>
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="" class="col-sm-2 control-label">资产<span class="red-fonts">*</span></label>
<div class="col-sm-4">
<div>
<select id="assets" name="assets" class="form-control m-b" size="12" multiple>
{% for asset in assets %}
<option value="{{ asset.id }}">{{ asset.ip }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="col-sm-1">
<div class="btn-group" style="margin-top: 42px;">
<button type="button" class="btn btn-white" onclick="move('assets', 'asset_select')"><i class="fa fa-chevron-right"></i></button>
<button type="button" class="btn btn-white" onclick="move('asset_select', 'assets')"><i class="fa fa-chevron-left"></i> </button>
</div>
</div>
<div class="col-sm-3">
<div>
<select id="asset_select" name="asset_select" class="form-control m-b" size="12" multiple>
{% for asset in asset_permed %}
<option value="{{ asset.id }}">{{ asset.ip }}</option>
{% endfor %}
</select>
</div>
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="" class="col-sm-2 control-label">资产组<span class="red-fonts">*</span></label>
<div class="col-sm-4">
<div>
<select id="asset_groups" name="asset_groups" class="form-control m-b" size="12" multiple>
{% for asset_group in asset_groups %}
<option value="{{ asset_group.id }}">{{ asset_group.name }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="col-sm-1">
<div class="btn-group" style="margin-top: 42px;">
<button type="button" class="btn btn-white" onclick="move('asset_groups', 'asset_groups_select')"><i class="fa fa-chevron-right"></i></button>
<button type="button" class="btn btn-white" onclick="move('asset_groups_select', 'asset_groups')"><i class="fa fa-chevron-left"></i> </button>
</div>
</div>
<div class="col-sm-3">
<div>
<select id="asset_groups_select" name="asset_groups_select" class="form-control m-b" size="12" multiple>
{% for asset_group in asset_group_permed %}
<option value="{{ asset_group.id }}">{{ asset_group.name }}</option>
{% endfor %}
</select>
</div>
</div>
</div>
</div>
<div class="row">
<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" onclick="selectAll()">确认保存</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -28,15 +28,11 @@
<a href="#"><i class="fa fa-edit"></i> <span class="nav-label">授权管理</span><span class="fa arrow"></span></a>
<ul class="nav nav-second-level">
<li class="dept_perm_list dept_perm_edit">
<a href="/jperm/user/">用户授权</a>
</li>
<li class="perm_list perm_edit perm_detail">
<a href="/jperm/group/">用户组授权</a>
<a href="/jperm/rule/">授权规则</a>
</li>
<li class="sudo_list sudo_edit sudo_add cmd_list cmd_edit cmd_add sudo_detail">
<a href="/jperm/sys_user_list/">系统用户</a>
<a href="/jperm/role/">系统角色</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>