Merge branch 'dev' of https://git.coding.net/jumpserver/jumpserver into NormalUserPageLZ

pull/26/head
liuzheng712 2015-11-20 11:12:10 +08:00
commit 31807b674b
37 changed files with 446 additions and 324 deletions

1
.gitignore vendored
View File

@ -37,6 +37,7 @@ nosetests.xml
.mr.developer.cfg .mr.developer.cfg
.project .project
.pydevproject .pydevproject
*.log
logs/* logs/*
keys/* keys/*
jumpserver.conf jumpserver.conf

View File

@ -19,8 +19,8 @@ import struct, fcntl, signal, socket, select
os.environ['DJANGO_SETTINGS_MODULE'] = 'jumpserver.settings' os.environ['DJANGO_SETTINGS_MODULE'] = 'jumpserver.settings'
if django.get_version() != '1.6': if django.get_version() != '1.6':
django.setup() django.setup()
from jumpserver.api import ServerError, User, Asset, AssetGroup, get_object from jumpserver.api import ServerError, User, Asset, AssetGroup, get_object, mkdir
from jumpserver.api import logger, mkdir, Log, TtyLog from jumpserver.api import logger, Log, TtyLog
from jumpserver.settings import LOG_DIR from jumpserver.settings import LOG_DIR
@ -68,9 +68,6 @@ def check_vim_status(command, ssh):
return False return False
class Tty(object): class Tty(object):
""" """
A virtual tty class A virtual tty class
@ -252,6 +249,7 @@ class Tty(object):
log_file_path = os.path.join(today_connect_log_dir, '%s_%s_%s' % (self.username, self.asset_name, time_start)) log_file_path = os.path.join(today_connect_log_dir, '%s_%s_%s' % (self.username, self.asset_name, time_start))
try: try:
mkdir(os.path.dirname(today_connect_log_dir), mode=0777)
mkdir(today_connect_log_dir, mode=0777) mkdir(today_connect_log_dir, mode=0777)
except OSError: except OSError:
logger.debug('创建目录 %s 失败,请修改%s目录权限' % (today_connect_log_dir, tty_log_dir)) logger.debug('创建目录 %s 失败,请修改%s目录权限' % (today_connect_log_dir, tty_log_dir))
@ -289,7 +287,7 @@ class Tty(object):
# 2. get 映射用户 # 2. get 映射用户
# 3. get 映射用户的账号密码或者key # 3. get 映射用户的账号密码或者key
# self.connect_info = {'user': '', 'asset': '', 'ip': '', 'port': 0, 'role_name': '', 'role_pass': '', 'role_key': ''} # self.connect_info = {'user': '', 'asset': '', 'ip': '', 'port': 0, 'role_name': '', 'role_pass': '', 'role_key': ''}
self.connect_info = {'user': 'a', 'asset': 'b', 'ip': '127.0.0.1', 'port': 22, 'role_name': 'root', 'role_pass': '', 'role_key': '/root/.ssh/id_rsa.bak'} self.connect_info = {'user': 'a', 'asset': 'b', 'ip': '127.0.0.1', 'port': 22, 'role_name': 'root', 'role_pass': 'redhat', 'role_key': ''}
return self.connect_info return self.connect_info
def get_connection(self): def get_connection(self):
@ -452,7 +450,7 @@ class SshTty(Tty):
#print 'ok'+tmp+'ok' #print 'ok'+tmp+'ok'
# SSH_TTY = re.search(r'(?<=/dev/).*', tmp).group().strip() # SSH_TTY = re.search(r'(?<=/dev/).*', tmp).group().strip()
# SSH_TTY = '' # SSH_TTY = ''
channel.send('clear\n') # channel.send('clear\n')
# Make ssh interactive tunnel # Make ssh interactive tunnel
self.posix_shell() self.posix_shell()
@ -468,20 +466,83 @@ class SshTty(Tty):
pass pass
def print_prompt(): def print_user_asset_group_info(user):
""" asset_groups = AssetGroup.objects.all()
Print prompt for asset_group in asset_groups:
打印提示导航 if asset_group.comment:
""" print '[%-2s] %-10s %s' % (asset_group.id, asset_group.name, asset_group.comment)
msg = """\033[1;32m### Welcome Use JumpServer To Login. ### \033[0m else:
1) Type \033[32mIP or Part IP, Host Alias or Comments \033[0m To Login. print '[%-2s] %-10s' % (asset_group.id, asset_group.name)
2) Type \033[32mP/p\033[0m To Print The Servers You Available. print
3) Type \033[32mG/g\033[0m To Print The Server Groups You Available.
4) Type \033[32mG/g(1-N)\033[0m To Print The Server Group Hosts You Available.
5) Type \033[32mE/e\033[0m To Execute Command On Several Servers. class Nav(object):
6) Type \033[32mQ/q\033[0m To Quit. def __init__(self, user):
""" self.user = user
print textwrap.dedent(msg) self.search_result = {}
@staticmethod
def print_nav():
"""
Print prompt
打印提示导航
"""
msg = """\n\033[1;32m### Welcome To Use JumpServer, A Open Source System . ### \033[0m
1) Type \033[32mID\033[0m To Login.
2) Type \033[32m/\033[0m + \033[32mIP, Host Name, Host Alias or Comments \033[0mTo Search.
3) Type \033[32mP/p\033[0m To Print The Servers You Available.
4) Type \033[32mG/g\033[0m To Print The Server Groups You Available.
5) Type \033[32mG/g\033[0m\033[0m + \033[32mGroup ID\033[0m To Print The Server Group You Available.
6) Type \033[32mE/e\033[0m To Execute Command On Several Servers.
7) Type \033[32mQ/q\033[0m To Quit.
"""
msg = """\n\033[1;32m### 欢迎使用Jumpserver开源跳板机 ### \033[0m
1) 输入 \033[32mID\033[0m 直接登录.
2) 输入 \033[32m/\033[0m + \033[32mIP, 主机名, 主机别名 or 备注 \033[0m搜索.
3) 输入 \033[32mP/p\033[0m 显示您有权限的主机.
4) 输入 \033[32mG/g\033[0m 显示您有权限的主机组.
5) 输入 \033[32mG/g\033[0m\033[0m + \033[32m组ID\033[0m 显示该组下主机.
6) 输入 \033[32mE/e\033[0m 批量执行命令.
7) 输入 \033[32mQ/q\033[0m 退出.
"""
print textwrap.dedent(msg)
def search(self, str_r=''):
gid_pattern = re.compile(r'^g\d+$')
user_asset_all = list(Asset.objects.all())
user_asset_search = []
if str_r:
if gid_pattern.match(str_r):
user_asset_search = list(Asset.objects.all())
else:
for asset in user_asset_all:
if str_r in asset.ip or str_r in str(asset.comment):
user_asset_search.append(asset)
else:
user_asset_search = user_asset_all
self.search_result = dict(zip(range(len(user_asset_search)), user_asset_search))
print '\033[32m[%-3s] %-15s %-15s %-5s %-5s %s \033[0m' % ('ID', 'AssetName', 'IP', 'Port', 'Role', 'Comment')
for index, asset in self.search_result.items():
if asset.comment:
print '[%-3s] %-15s %-15s %-5s %-5s %s' % (index, 'asset_name'+str(index), asset.ip, asset.port, 'role', asset.comment)
else:
print '[%-3s] %-15s %-15s %-5s %-5s' % (index, 'asset_name'+str(index), asset.ip, asset.port, 'role')
print
@staticmethod
def print_asset_group():
user_asset_group_all = AssetGroup.objects.all()
print '\033[32m[%-3s] %-15s %s \033[0m' % ('ID', 'GroupName', 'Comment')
for asset_group in user_asset_group_all:
if asset_group.comment:
print '[%-3s] %-15s %s' % (asset_group.id, asset_group.name, asset_group.comment)
else:
print '[%-3s] %-15s' % (asset_group.id, asset_group.name)
print
def main(): def main():
@ -492,29 +553,26 @@ def main():
if not login_user: # 判断用户是否存在 if not login_user: # 判断用户是否存在
color_print(u'没有该用户或许你是以root运行的 No that user.', exits=True) color_print(u'没有该用户或许你是以root运行的 No that user.', exits=True)
print_prompt()
gid_pattern = re.compile(r'^g\d+$') gid_pattern = re.compile(r'^g\d+$')
nav = Nav(login_user)
nav.print_nav()
try: try:
while True: while True:
try: try:
option = raw_input("\033[1;32mOpt or IP>:\033[0m ") option = raw_input("\033[1;32mOpt or ID>:\033[0m ").strip()
except EOFError: except EOFError:
print_prompt() nav.print_nav()
continue continue
except KeyboardInterrupt: except KeyboardInterrupt:
sys.exit(0) sys.exit(0)
if option in ['P', 'p']: if option in ['P', 'p', '\n', '']:
login_user.get_asset_info(printable=True) nav.search()
continue continue
if option.startswith('/') or gid_pattern.match(option):
nav.search(option.lstrip('/'))
elif option in ['G', 'g']: elif option in ['G', 'g']:
login_user.get_asset_group_info(printable=True) nav.print_asset_group()
continue
elif gid_pattern.match(option):
gid = option[1:].strip()
asset_group = get_object(AssetGroup, id=gid)
if asset_group and asset_group.is_permed(user=login_user):
asset_group.get_asset_info(printable=True)
continue continue
elif option in ['E', 'e']: elif option in ['E', 'e']:
# exec_cmd_servers(login_name) # exec_cmd_servers(login_name)
@ -523,7 +581,11 @@ def main():
sys.exit() sys.exit()
else: else:
try: try:
verify_connect(login_user, option) asset = nav.search_result[int(option)]
ssh_tty = SshTty('a', 'b')
ssh_tty.connect()
except (KeyError, ValueError):
color_print('请输入正确ID', 'red')
except ServerError, e: except ServerError, e:
color_print(e, 'red') color_print(e, 'red')
except IndexError: except IndexError:

View File

@ -1,6 +1,5 @@
sphinx-me==0.3 sphinx-me==0.3
django==1.6 django==1.6
python-ldap==2.4.19
pycrypto==2.6.1 pycrypto==2.6.1
paramiko==1.15.2 paramiko==1.15.2
ecdsa==0.13 ecdsa==0.13
@ -9,4 +8,9 @@ django-uuidfield==0.5.0
psutil==2.2.1 psutil==2.2.1
xlsxwriter==0.7.7 xlsxwriter==0.7.7
xlrd==0.9.4 xlrd==0.9.4
django-bootstrap-form django-bootstrap-form
tornado
ansible
pyinotify
passlib
argparse

View File

@ -311,8 +311,12 @@ def write_excel(asset_all):
group_all = '/'.join(group_list) group_all = '/'.join(group_list)
status = asset.get_status_display() status = asset.get_status_display()
idc_name = asset.idc.name if asset.idc else u'' idc_name = asset.idc.name if asset.idc else u''
system_type = asset.system_type if asset.idc else u''
system_version = asset.system_version if asset.idc else u''
system_os = unicode(system_type) + unicode(system_version)
alter_dic = [asset.hostname, asset.ip, idc_name, asset.mac, asset.remote_ip, asset.cpu, asset.memory, alter_dic = [asset.hostname, asset.ip, idc_name, asset.mac, asset.remote_ip, asset.cpu, asset.memory,
asset.disk, (asset.system_type + asset.system_version), asset.cabinet, group_all, status, asset.disk, system_os, asset.cabinet, group_all, status,
asset.comment] asset.comment]
data.append(alter_dic) data.append(alter_dic)
format = workbook.add_format() format = workbook.add_format()
@ -381,13 +385,13 @@ def excel_to_db(excel_file):
row = table.row_values(row_num) row = table.row_values(row_num)
if row: if row:
ip, port, hostname, use_default_auth, username, password, group = row ip, port, hostname, use_default_auth, username, password, group = row
print ip
use_default_auth = 1 if use_default_auth == u'默认' else 0 use_default_auth = 1 if use_default_auth == u'默认' else 0
if get_object(Asset, ip=ip): if get_object(Asset, ip=ip):
continue continue
if ip and port: if ip and port:
asset = Asset(ip=ip, asset = Asset(ip=ip,
port=port, port=port,
hostname=hostname,
use_default_auth=use_default_auth, use_default_auth=use_default_auth,
username=username, username=username,
password=password password=password

View File

@ -37,8 +37,8 @@ class AssetGroup(models.Model):
class IDC(models.Model): class IDC(models.Model):
name = models.CharField(max_length=32, verbose_name=u'机房名称') name = models.CharField(max_length=32, verbose_name=u'机房名称')
bandwidth = models.CharField(max_length=32, blank=True, null=True, verbose_name=u'机房带宽') bandwidth = models.CharField(max_length=32, blank=True, null=True, verbose_name=u'机房带宽')
linkman = models.CharField(max_length=16, null=True, verbose_name=u'联系人') linkman = models.CharField(max_length=16, blank=True, null=True, verbose_name=u'联系人')
phone = models.CharField(max_length=32, verbose_name=u'联系电话') phone = models.CharField(max_length=32, blank=True, null=True, verbose_name=u'联系电话')
address = models.CharField(max_length=128, blank=True, null=True, verbose_name=u"机房地址") address = models.CharField(max_length=128, blank=True, null=True, verbose_name=u"机房地址")
network = models.TextField(blank=True, null=True, verbose_name=u"IP地址段") network = models.TextField(blank=True, null=True, verbose_name=u"IP地址段")
date_added = models.DateField(auto_now=True, null=True) date_added = models.DateField(auto_now=True, null=True)

View File

@ -2,9 +2,9 @@
import ast import ast
from django.db.models import Q from django.db.models import Q
from django.shortcuts import get_object_or_404
from jasset.asset_api import * from jasset.asset_api import *
from jumpserver.api import * from jumpserver.api import *
from jumpserver.models import Setting
from jasset.forms import AssetForm, IdcForm from jasset.forms import AssetForm, IdcForm
from jasset.models import Asset, IDC, AssetGroup, ASSET_TYPE, ASSET_STATUS from jasset.models import Asset, IDC, AssetGroup, ASSET_TYPE, ASSET_STATUS
from ansible_api import Tasks from ansible_api import Tasks
@ -13,7 +13,7 @@ from ansible_api import Tasks
@require_role('admin') @require_role('admin')
def group_add(request): def group_add(request):
""" """
Add asset group Group add view
添加资产组 添加资产组
""" """
header_title, path1, path2 = u'添加资产组', u'资产管理', u'添加资产组' header_title, path1, path2 = u'添加资产组', u'资产管理', u'添加资产组'
@ -47,7 +47,7 @@ def group_add(request):
@require_role('admin') @require_role('admin')
def group_edit(request): def group_edit(request):
""" """
Edit asset group Group edit view
编辑资产组 编辑资产组
""" """
header_title, path1, path2 = u'编辑主机组', u'资产管理', u'编辑主机组' header_title, path1, path2 = u'编辑主机组', u'资产管理', u'编辑主机组'
@ -89,7 +89,10 @@ def group_edit(request):
@require_role('admin') @require_role('admin')
def group_detail(request): def group_detail(request):
""" 主机组详情 """ """
Group detail view
主机组详情
"""
header_title, path1, path2 = u'主机组详情', u'资产管理', u'主机组详情' header_title, path1, path2 = u'主机组详情', u'资产管理', u'主机组详情'
group_id = request.GET.get('id', '') group_id = request.GET.get('id', '')
group = get_object(AssetGroup, id=group_id) group = get_object(AssetGroup, id=group_id)
@ -121,7 +124,7 @@ def group_list(request):
@require_role('admin') @require_role('admin')
def group_del(request): def group_del(request):
""" """
del asset group Group delete view
删除主机组 删除主机组
""" """
group_ids = request.GET.get('id', '') group_ids = request.GET.get('id', '')
@ -160,7 +163,7 @@ def asset_add(request):
asset_save = af_post.save(commit=False) asset_save = af_post.save(commit=False)
if not use_default_auth: if not use_default_auth:
password = request.POST.get('password', '') password = request.POST.get('password', '')
password_encode = CRYPTOR.encrypt(password) password_encode = password
asset_save.password = password_encode asset_save.password = password_encode
asset_save.is_active = True if is_active else False asset_save.is_active = True if is_active else False
asset_save.save() asset_save.save()
@ -293,7 +296,7 @@ def asset_list(request):
s = write_excel(asset_find) s = write_excel(asset_find)
if s[0]: if s[0]:
file_name = s[1] file_name = s[1]
smg = 'excel文件已生成请点击下载!' smg = u'excel文件已生成请点击下载!'
return my_render('jasset/asset_excel_download.html', locals(), request) return my_render('jasset/asset_excel_download.html', locals(), request)
assets_list, p, assets, page_range, current_page, show_first, show_end = pages(asset_find, request) assets_list, p, assets, page_range, current_page, show_first, show_end = pages(asset_find, request)
return my_render('jasset/asset_list.html', locals(), request) return my_render('jasset/asset_list.html', locals(), request)
@ -330,13 +333,20 @@ def asset_update(request):
return HttpResponseRedirect('/jasset/asset_detail/?id=%s' % asset_id) return HttpResponseRedirect('/jasset/asset_detail/?id=%s' % asset_id)
name = request.session.get('username', 'admin') name = request.session.get('username', 'admin')
if asset.use_default_auth: if asset.use_default_auth:
username = 'root' default = Setting.objects.all()
password = '123456' if default:
default = default[0]
username = default.default_user
password = default.default_password
port = default.default_port
else:
return HttpResponse(u'没有设置默认用户名和密码!')
else: else:
username = asset.username username = asset.username
password = asset.password password = asset.password
port = asset.port
resource = [{"hostname": asset.ip, "port": asset.port, resource = [{"hostname": asset.ip, "port": port,
"username": username, "password": password}] "username": username, "password": password}]
ansible_instance = Tasks(resource) ansible_instance = Tasks(resource)
@ -446,16 +456,17 @@ def idc_del(request):
""" """
IDC delete view IDC delete view
""" """
uuid = request.GET.get('uuid', '') uuid = request.GET.get('id', '')
idc = get_object_or_404(IDC, uuid=uuid) idc = get_object(IDC, id=uuid)
idc.delete() if idc:
idc.delete()
return HttpResponseRedirect('/jasset/idc_list/') return HttpResponseRedirect('/jasset/idc_list/')
@require_role('admin') @require_role('admin')
def asset_upload(request): def asset_upload(request):
""" """
Upload file view Upload asset excel file view
""" """
if request.method == 'POST': if request.method == 'POST':
excel_file = request.FILES.get('file_name', '') excel_file = request.FILES.get('file_name', '')

View File

@ -15,11 +15,11 @@ from utils import get_rand_pass
import os.path import os.path
API_DIR = os.path.dirname(os.path.abspath(__file__)) API_DIR = os.path.dirname(os.path.abspath(__file__))
ANSIBLE_DIR = os.path.join(API_DIR, 'playbooks') ANSIBLE_DIR = os.path.join(API_DIR, 'playbooks')
class AnsibleError(StandardError): class AnsibleError(StandardError):
""" """
the base AnsibleError which contains error(required), the base AnsibleError which contains error(required),
@ -61,7 +61,7 @@ class MyInventory(object):
[{"hostname": "10.10.10.10", "port": "22", "username": "test", "password": "mypass"}, ...] [{"hostname": "10.10.10.10", "port": "22", "username": "test", "password": "mypass"}, ...]
""" """
self.resource = resource self.resource = resource
self.inventory = Inventory() self.inventory = Inventory(host_list=[])
self.gen_inventory() self.gen_inventory()
def add_group(self, hosts, groupname, groupvars=None): def add_group(self, hosts, groupname, groupvars=None):
@ -101,7 +101,7 @@ class MyInventory(object):
add hosts to inventory. add hosts to inventory.
""" """
if isinstance(self.resource, list): if isinstance(self.resource, list):
self.add_group(self.resource, 'my_group') self.add_group(self.resource, 'default_group')
elif isinstance(self.resource, dict): elif isinstance(self.resource, dict):
for groupname, hosts_and_vars in self.resource.iteritems(): for groupname, hosts_and_vars in self.resource.iteritems():
self.add_group(hosts_and_vars.get("hosts"), groupname, hosts_and_vars.get("vars")) self.add_group(hosts_and_vars.get("hosts"), groupname, hosts_and_vars.get("vars"))
@ -115,21 +115,23 @@ class Command(MyInventory):
super(Command, self).__init__(*args, **kwargs) super(Command, self).__init__(*args, **kwargs)
self.results = '' self.results = ''
def run(self, command, module_name="command", timeout=5, forks=10, group='my_group'): def run(self, command, module_name="command", timeout=10, forks=10, group='default_group', pattern='*'):
""" """
run command from andible ad-hoc. run command from andible ad-hoc.
command : 必须是一个需要执行的命令字符串 比如 command : 必须是一个需要执行的命令字符串 比如
'uname -a' 'uname -a'
""" """
if module_name not in ["raw", "command", "shell"]: if module_name not in ["raw", "command", "shell"]:
raise CommandValueError("module_name", raise CommandValueError("module_name",
"module_name must be of the 'raw, command, shell'") "module_name must be of the 'raw, command, shell'")
hoc = Runner(module_name=module_name, hoc = Runner(module_name=module_name,
module_args=command, module_args=command,
timeout=timeout, timeout=timeout,
inventory=self.inventory, inventory=self.inventory,
subset=group, subset=group,
forks=forks pattern=pattern,
forks=forks,
) )
self.results = hoc.run() self.results = hoc.run()
@ -203,7 +205,7 @@ class Tasks(Command):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(Tasks, self).__init__(*args, **kwargs) super(Tasks, self).__init__(*args, **kwargs)
def __run(self, module_args, module_name="command", timeout=5, forks=10, group='my_group'): def __run(self, module_args, module_name="command", timeout=5, forks=10, group='default_group', pattern='*'):
""" """
run command from andible ad-hoc. run command from andible ad-hoc.
command : 必须是一个需要执行的命令字符串 比如 command : 必须是一个需要执行的命令字符串 比如
@ -214,7 +216,8 @@ class Tasks(Command):
timeout=timeout, timeout=timeout,
inventory=self.inventory, inventory=self.inventory,
subset=group, subset=group,
forks=forks pattern=pattern,
forks=forks,
) )
self.results = hoc.run() self.results = hoc.run()
@ -425,7 +428,6 @@ class MyPlaybook(MyInventory):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(MyPlaybook, self).__init__(*args, **kwargs) super(MyPlaybook, self).__init__(*args, **kwargs)
def run(self, playbook_relational_path, extra_vars=None): def run(self, playbook_relational_path, extra_vars=None):
""" """
run ansible playbook, run ansible playbook,
@ -464,7 +466,6 @@ class App(MyPlaybook):
if __name__ == "__main__": if __name__ == "__main__":
pass
# resource = { # resource = {
# "group1": { # "group1": {
@ -472,8 +473,10 @@ if __name__ == "__main__":
# "vars" : {"var1": "value1", "var2": "value2"}, # "vars" : {"var1": "value1", "var2": "value2"},
# }, # },
# } # }
# command = Command(resource)
# print command.run("who", group="group1") resource = [{"hostname": "127.0.0.1", "port": "22", "username": "yumaojun", "password": "yusky0902"}]
command = Command(resource)
print command.run("who")
# resource = [{"hostname": "192.168.10.148", "port": "22", "username": "root", "password": "xxx"}] # resource = [{"hostname": "192.168.10.148", "port": "22", "username": "root", "password": "xxx"}]
# task = Tasks(resource) # task = Tasks(resource)

View File

@ -32,14 +32,13 @@ class PermRole(models.Model):
class PermRule(models.Model): class PermRule(models.Model):
date_added = models.DateTimeField(auto_now=True) date_added = models.DateTimeField(auto_now=True)
name = models.CharField(max_length=100) name = models.CharField(max_length=100, unique=True)
comment = models.CharField(max_length=100) comment = models.CharField(max_length=100)
asset = models.ManyToManyField(Asset, related_name='perm_rule') asset = models.ManyToManyField(Asset, related_name='perm_rule')
asset_group = models.ManyToManyField(AssetGroup, related_name='perm_rule') asset_group = models.ManyToManyField(AssetGroup, related_name='perm_rule')
user = models.ManyToManyField(User, related_name='perm_rule') user = models.ManyToManyField(User, related_name='perm_rule')
user_group = models.ManyToManyField(UserGroup, related_name='perm_rule') user_group = models.ManyToManyField(UserGroup, related_name='perm_rule')
role = models.ManyToManyField(PermRole, related_name='perm_rule') role = models.ManyToManyField(PermRole, related_name='perm_rule')
ssh_type = models.BooleanField()
def __unicode__(self): def __unicode__(self):
return self.name return self.name

View File

@ -89,7 +89,7 @@ def perm_user_api(perm_info):
the_new_users = ','.join(new_username) the_new_users = ','.join(new_username)
the_del_users = ','.join(del_username) the_del_users = ','.join(del_username)
playbook = get_playbook(os.path.join(BASE_DIR, 'playbook', 'user_perm.yaml'), playbook = get_playbook(os.path.join(BASE_DIR, 'keys/../playbook', 'user_perm.yaml'),
{'the_new_group': 'new', 'the_del_group': 'del', {'the_new_group': 'new', 'the_del_group': 'del',
'the_new_users': the_new_users, 'the_del_users': the_del_users, 'the_new_users': the_new_users, 'the_del_users': the_del_users,
'KEY_DIR': os.path.join(SSH_KEY_DIR, 'sysuser')}) 'KEY_DIR': os.path.join(SSH_KEY_DIR, 'sysuser')})

View File

@ -4,7 +4,7 @@ import random
import os.path import os.path
from paramiko.rsakey import RSAKey from paramiko.rsakey import RSAKey
from os import chmod, mkdir from jumpserver.api import mkdir
from uuid import uuid4 from uuid import uuid4
from jumpserver.settings import KEY_DIR from jumpserver.settings import KEY_DIR
@ -45,9 +45,8 @@ def gen_keys():
:return: 返回目录名(uuid) :return: 返回目录名(uuid)
""" """
key_basename = "key-" + uuid4().hex key_basename = "key-" + uuid4().hex
key_path_dir = os.path.join(KEY_DIR, key_basename) key_path_dir = os.path.join(KEY_DIR, 'role_key', key_basename)
mkdir(key_path_dir, 0700) mkdir(key_path_dir, 0755)
key = RSAKey.generate(2048) key = RSAKey.generate(2048)
private_key = os.path.join(key_path_dir, 'id_rsa') private_key = os.path.join(key_path_dir, 'id_rsa')
public_key = os.path.join(key_path_dir, 'id_rsa.pub') public_key = os.path.join(key_path_dir, 'id_rsa.pub')
@ -62,8 +61,6 @@ def gen_keys():
return key_path_dir return key_path_dir
if __name__ == "__main__": if __name__ == "__main__":
print gen_keys() print gen_keys()

View File

@ -1,6 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from django.db.models import Q from django.db.models import Q
from jperm.perm_api import * from jperm.perm_api import *
from jperm.models import PermLog as Log from jperm.models import PermLog as Log
@ -11,12 +10,13 @@ from juser.user_api import gen_ssh_key
from juser.models import User, UserGroup from juser.models import User, UserGroup
from jasset.models import Asset, AssetGroup from jasset.models import Asset, AssetGroup
from jperm.models import PermRole, PermRule from jperm.models import PermRole, PermRule
from jumpserver.models import Setting
from jperm.utils import updates_dict, gen_keys, get_rand_pass from jperm.utils import updates_dict, gen_keys, get_rand_pass
from jperm.ansible_api import Tasks from jperm.ansible_api import Tasks
from jperm.perm_api import get_role_info from jperm.perm_api import get_role_info
from jumpserver.api import my_render, get_object from jumpserver.api import my_render, get_object, CRYPTOR
@require_role('admin') @require_role('admin')
@ -62,7 +62,7 @@ def perm_rule_detail(request):
assets = asset_obj assets = asset_obj
return my_render('jperm/perm_rule_detail.html', locals(), request) return my_render('jperm/perm_rule_detail.html', locals(), request)
def perm_rule_add(request): def perm_rule_add(request):
""" """
@ -89,7 +89,8 @@ def perm_rule_add(request):
asset_groups_select = request.POST.getlist('assetgroup', []) asset_groups_select = request.POST.getlist('assetgroup', [])
roles_select = request.POST.getlist('role', []) roles_select = request.POST.getlist('role', [])
rule_name = request.POST.get('rulename') rule_name = request.POST.get('rulename')
rule_comment = request.POST.get('comment') rule_comment = request.POST.get('rule_comment')
rule_ssh_key = request.POST.get("use_publicKey")
# 获取需要授权的主机列表 # 获取需要授权的主机列表
assets_obj = [Asset.objects.get(ip=asset) for asset in assets_select] assets_obj = [Asset.objects.get(ip=asset) for asset in assets_select]
@ -115,7 +116,19 @@ def perm_rule_add(request):
rule.asset_group = asset_groups_obj rule.asset_group = asset_groups_obj
rule.role = roles_obj rule.role = roles_obj
rule.save() rule.save()
return HttpResponse(u"添加授权规则:%s" % rule.name)
msg = u"添加授权规则:%s" % rule.name
# 渲染数据
header_title, path1, path2 = "授权规则", "规则管理", "查看规则"
rules_list = PermRule.objects.all()
# TODO: 搜索和分页
keyword = request.GET.get('search', '')
if keyword:
rules_list = rules_list.filter(Q(name=keyword))
rules_list, p, rules, page_range, current_page, show_first, show_end = pages(rules_list, request)
return my_render('jperm/perm_rule_list.html', locals(), request)
@require_role('admin') @require_role('admin')
@ -131,17 +144,69 @@ def perm_rule_edit(request):
rule = PermRule.objects.get(id=rule_id) rule = PermRule.objects.get(id=rule_id)
if request.method == 'GET' and rule_id: if request.method == 'GET' and rule_id:
# 渲染数据, 获取所有的rule对象 # 渲染数据, 获取所选的rule对象
users = rule.user.all() rule_comment = rule.comment
user_groups = rule.user_group.all() users_select = rule.user.all()
assets = rule.asset.all() user_groups_select = rule.user_group.all()
asset_groups = rule.asset_group.all() assets_select = rule.asset.all()
roles = rule.role.all() asset_groups_select = rule.asset_group.all()
roles_select = rule.role.all()
users = User.objects.all()
user_groups = UserGroup.objects.all()
assets = Asset.objects.all()
asset_groups = AssetGroup.objects.all()
roles = PermRole.objects.all()
return my_render('jperm/perm_rule_edit.html', locals(), request) return my_render('jperm/perm_rule_edit.html', locals(), request)
elif request.method == 'POST' and rule_id: elif request.method == 'POST' and rule_id:
return HttpResponse("uncompleted") # 获取用户选择的 用户,用户组,资产,资产组,用户角色
rule_name = request.POST.get('rule_name')
rule_comment = request.POST.get("rule_comment")
users_select = request.POST.getlist('user', [])
user_groups_select = request.POST.getlist('usergroup', [])
assets_select = request.POST.getlist('asset', [])
asset_groups_select = request.POST.getlist('assetgroup', [])
roles_select = request.POST.getlist('role', [])
# 获取需要授权的主机列表
assets_obj = [Asset.objects.get(ip=asset) for asset in assets_select]
asset_groups_obj = [AssetGroup.objects.get(name=group) for group in asset_groups_select]
group_assets_obj = [asset for asset in [group.asset_set.all() for group in asset_groups_obj]]
calc_assets = set(group_assets_obj) | set(assets_obj)
# 获取需要授权的用户列表
users_obj = [User.objects.get(name=user) for user in users_select]
user_groups_obj = [UserGroup.objects.get(name=group) for group in user_groups_select]
group_users_obj = [user for user in [group.user_set.all() for group in user_groups_obj]]
calc_users = set(group_users_obj) | set(users_obj)
# 获取授予的角色列表
roles_obj = [PermRole.objects.get(name=role) for role in roles_select]
# 仅授权成功的,写回数据库(授权规则,用户,用户组,资产,资产组,用户角色)
rule.user = users_obj
rule.usergroup = user_groups_obj
rule.asset = assets_obj
rule.asset_group = asset_groups_obj
rule.role = roles_obj
rule.name = rule_name
rule.comment = rule.comment
rule.save()
msg = u"更新授权规则:%s" % rule.name
# 渲染数据
header_title, path1, path2 = "授权规则", "规则管理", "查看规则"
rules_list = PermRule.objects.all()
# TODO: 搜索和分页
keyword = request.GET.get('search', '')
if keyword:
rules_list = rules_list.filter(Q(name=keyword))
rules_list, p, rules, page_range, current_page, show_first, show_end = pages(rules_list, request)
return my_render('jperm/perm_rule_list.html', locals(), request)
@require_role('admin') @require_role('admin')
@ -201,12 +266,24 @@ def perm_role_add(request):
name = request.POST.get("role_name") name = request.POST.get("role_name")
comment = request.POST.get("role_comment") comment = request.POST.get("role_comment")
password = request.POST.get("role_password") password = request.POST.get("role_password")
encrypt_pass = CRYPTOR.encrypt(password)
# 生成随机密码,生成秘钥对 # 生成随机密码,生成秘钥对
key_path = gen_keys() key_path = gen_keys()
role = PermRole(name=name, comment=comment, password=password, key_path=key_path) role = PermRole(name=name, comment=comment, password=encrypt_pass, key_path=key_path)
role.save() role.save()
return HttpResponse(u"添加角色: %s" % name)
msg = u"添加角色: %s" % name
# 渲染 刷新数据
header_title, path1, path2 = "系统角色", "角色管理", "查看角色"
roles_list = PermRole.objects.all()
# TODO: 搜索和分页
keyword = request.GET.get('search', '')
if keyword:
roles_list = roles_list.filter(Q(name=keyword))
roles_list, p, roles, page_range, current_page, show_first, show_end = pages(roles_list, request)
return my_render('jperm/perm_role_list.html', locals(), request)
else: else:
return HttpResponse(u"不支持该操作") return HttpResponse(u"不支持该操作")
@ -252,8 +329,12 @@ def perm_role_detail(request):
role_info = get_role_info(role_id) role_info = get_role_info(role_id)
# 渲染数据 # 渲染数据
for key, value in role_info.iteritems(): rules = role_info.get("rules")
key = value assets = role_info.get("assets")
asset_groups = role_info.get("asset_groups")
users = role_info.get("users")
user_groups = role_info.get("user_groups")
return my_render('jperm/perm_role_detail.html', locals(), request) return my_render('jperm/perm_role_detail.html', locals(), request)
@ -265,15 +346,40 @@ def perm_role_edit(request):
# 渲染数据 # 渲染数据
header_title, path1, path2 = "系统角色", "角色管理", "角色编辑" header_title, path1, path2 = "系统角色", "角色管理", "角色编辑"
# 渲染数据
role_id = request.GET.get("id")
role = PermRole.objects.get(id=role_id)
role_pass = CRYPTOR.decrypt(role.password)
if request.method == "GET": if request.method == "GET":
role_id = request.GET.get("id")
# 渲染数据
role = PermRole.objects.get(id=role_id)
return my_render('jperm/perm_role_edit.html', locals(), request) return my_render('jperm/perm_role_edit.html', locals(), request)
if request.method == "POST": if request.method == "POST":
return HttpResponse(u"未实现") # 获取 POST 数据
role_name = request.POST.get("role_name")
role_password = request.POST.get("role_password")
encrypt_role_pass = CRYPTOR.encrypt(role_password)
role_comment = request.POST.get("role_comment")
# 写入数据库
role.name = role_name
role.password = encrypt_role_pass
role.comment = role_comment
role.save()
msg = u"更新系统角色: %s" % role.name
# 渲染 刷新数据
header_title, path1, path2 = "系统角色", "角色管理", "查看角色"
roles_list = PermRole.objects.all()
# TODO: 搜索和分页
keyword = request.GET.get('search', '')
if keyword:
roles_list = roles_list.filter(Q(name=keyword))
roles_list, p, roles, page_range, current_page, show_first, show_end = pages(roles_list, request)
return my_render('jperm/perm_role_list.html', locals(), request)
@require_role('admin') @require_role('admin')
@ -307,10 +413,20 @@ def perm_role_push(request):
calc_assets = set(assets_obj) | set(group_assets_obj) calc_assets = set(assets_obj) | set(group_assets_obj)
# 生成Inventory # 生成Inventory
push_resource = [{"hostname": asset.ip, push_resource = []
"port": asset.port, for asset in calc_assets:
"username": asset.username, if asset.use_default_auth:
"password": asset.password} for asset in calc_assets] username = Setting.default_user
password = Setting.default_password
port = Setting.default_port
else:
username = asset.username
password = asset.password
port = asset.port
push_resource.append({"hostname": asset.ip,
"port": port,
"username": username,
"password": password})
# 获取角色的推送方式,以及推送需要的信息 # 获取角色的推送方式,以及推送需要的信息
roles_obj = [PermRole.objects.get(name=role_name) for role_name in role_names] roles_obj = [PermRole.objects.get(name=role_name) for role_name in role_names]
@ -326,10 +442,13 @@ def perm_role_push(request):
task = Tasks(push_resource) task = Tasks(push_resource)
ret = {} ret = {}
ret_failed = [] ret_failed = []
if password_push:
ret["password_push"] = task.add_multi_user(**role_pass) # 因为要先建立用户所以password 是必选项,
if ret["password_push"].get("status") != "success": # 而push key是在 password也完成的情况下的 可选项
ret_failed.append(1) ret["password_push"] = task.add_multi_user(**role_pass)
if ret["password_push"].get("status") != "success":
ret_failed.append(1)
if key_push: if key_push:
ret["key_push"] = task.push_multi_key(**role_key) ret["key_push"] = task.push_multi_key(**role_key)
if ret["key_push"].get("status") != "success": if ret["key_push"].get("status") != "success":

View File

@ -14,10 +14,8 @@ from django.core.paginator import Paginator, EmptyPage, InvalidPage
from django.http import HttpResponse, Http404 from django.http import HttpResponse, Http404
from django.template import RequestContext from django.template import RequestContext
from juser.models import User, UserGroup from juser.models import User, UserGroup
from jlog.models import Log
from jasset.models import Asset, AssetGroup from jasset.models import Asset, AssetGroup
# from jlog.models import Log
from jlog.models import Log, TtyLog
from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned
from django.http import HttpResponseRedirect from django.http import HttpResponseRedirect
from django.shortcuts import render_to_response from django.shortcuts import render_to_response
from django.core.mail import send_mail from django.core.mail import send_mail
@ -197,9 +195,9 @@ def require_role(role='user'):
def _deco(func): def _deco(func):
def __deco(request, *args, **kwargs): def __deco(request, *args, **kwargs):
request.session['pre_url'] = request.path
if not request.user.is_authenticated(): if not request.user.is_authenticated():
return HttpResponseRedirect('/login/') return HttpResponseRedirect('/login/')
if role == 'admin': if role == 'admin':
# if request.session.get('role_id', 0) < 1: # if request.session.get('role_id', 0) < 1:
if request.user.role == 'CU': if request.user.role == 'CU':
@ -395,8 +393,9 @@ def mkdir(dir_name, username='root', mode=0755):
""" """
if not os.path.isdir(dir_name): if not os.path.isdir(dir_name):
os.makedirs(dir_name) os.makedirs(dir_name)
bash("chown %s:%s '%s'" % (username, username, dir_name))
os.chmod(dir_name, mode) os.chmod(dir_name, mode)
if username:
bash('chown %s:%s %s' % (username, username, dir_name))
def http_success(request, msg): def http_success(request, msg):
@ -414,4 +413,3 @@ def my_render(template, data, request):
CRYPTOR = PyCrypt(KEY) CRYPTOR = PyCrypt(KEY)
logger = set_log(LOG_LEVEL) logger = set_log(LOG_LEVEL)
KEY_DIR = os.path.join(BASE_DIR, 'keys')

View File

@ -17,8 +17,8 @@ config = ConfigParser.ConfigParser()
BASE_DIR = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) BASE_DIR = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
config.read(os.path.join(BASE_DIR, 'jumpserver.conf')) config.read(os.path.join(BASE_DIR, 'jumpserver.conf'))
KEY_DIR = os.path.join(BASE_DIR, 'keys')
KEY_DIR = os.path.join(BASE_DIR, 'role_keys')
DB_HOST = config.get('db', 'host') DB_HOST = config.get('db', 'host')
DB_PORT = config.getint('db', 'port') DB_PORT = config.getint('db', 'port')
@ -37,7 +37,7 @@ EMAIL_TIMEOUT = 5
# ======== Log ========== # ======== Log ==========
LOG_DIR = os.path.join(BASE_DIR, 'logs') LOG_DIR = os.path.join(BASE_DIR, 'logs')
SSH_KEY_DIR = os.path.join(BASE_DIR, 'role_keys') SSH_KEY_DIR = os.path.join(BASE_DIR, 'keys/role_keys')
KEY = config.get('base', 'key') KEY = config.get('base', 'key')
URL = config.get('base', 'url') URL = config.get('base', 'url')
LOG_LEVEL = config.get('base', 'log') LOG_LEVEL = config.get('base', 'log')

View File

@ -226,3 +226,14 @@ def ip_str_to_list(ip_str):
ip str to list ip str to list
""" """
return ip_str.split(',') return ip_str.split(',')
@register.filter(name='key_exist')
def key_exist(username):
"""
ssh key is exist or not
"""
if os.path.isfile(os.path.join(KEY_DIR, 'user', username)):
return True
else:
return False

View File

@ -15,7 +15,6 @@ from jumpserver.api import *
from jumpserver.models import Setting from jumpserver.models import Setting
from django.contrib.auth import authenticate, login, logout from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from settings import BASE_DIR
from jlog.models import Log from jlog.models import Log
@ -236,7 +235,7 @@ def Login(request):
request.session['role_id'] = 1 request.session['role_id'] = 1
else: else:
request.session['role_id'] = 0 request.session['role_id'] = 0
return HttpResponseRedirect(request.GET.get('next', '/'), ) return HttpResponseRedirect(request.session.get('pre_url', '/'))
# response.set_cookie('username', username, expires=604800) # response.set_cookie('username', username, expires=604800)
# response.set_cookie('seed', PyCrypt.md5_crypt(password), expires=604800) # response.set_cookie('seed', PyCrypt.md5_crypt(password), expires=604800)
# return response # return response
@ -269,7 +268,7 @@ def setting(request):
if '' in [username, port] and ('' in password or '' in private_key): if '' in [username, port] and ('' in password or '' in private_key):
return HttpResponse('所填内容不能为空, 且密码和私钥填一个') return HttpResponse('所填内容不能为空, 且密码和私钥填一个')
else: else:
private_key_path = os.path.join(BASE_DIR, 'role_keys', 'default', 'default_private_key.pem') private_key_path = os.path.join(BASE_DIR, 'keys/role_keys', 'default', 'default_private_key.pem')
if private_key: if private_key:
with open(private_key_path, 'w') as f: with open(private_key_path, 'w') as f:
f.write(private_key) f.write(private_key)

View File

@ -123,21 +123,21 @@ def db_del_user(username):
def gen_ssh_key(username, password='', def gen_ssh_key(username, password='',
key_dir=os.path.join(KEY_DIR, 'user'), key_dir=os.path.join(KEY_DIR, 'user'),
authorized_keys=True, home="/home", length=2048): authorized_keys=True, home="/home", length=2048):
""" """
generate a user ssh key in a property dir generate a user ssh key in a property dir
生成一个用户ssh密钥对 生成一个用户ssh密钥对
""" """
logger.debug('生成ssh key 并设置authorized_keys')
private_key_file = os.path.join(key_dir, username) private_key_file = os.path.join(key_dir, username)
mkdir(private_key_file, username) mkdir(key_dir)
if os.path.isfile(private_key_file): if os.path.isfile(private_key_file):
os.unlink(private_key_file) os.unlink(private_key_file)
ret = bash('echo -e "y\n"|ssh-keygen -t rsa -f %s -b %s -P "%s"' % (private_key_file, length, password)) ret = bash('echo -e "y\n"|ssh-keygen -t rsa -f %s -b %s -P "%s"' % (private_key_file, length, password))
if authorized_keys: if authorized_keys:
auth_key_dir = os.path.join(home, username, '.ssh') auth_key_dir = os.path.join(home, username, '.ssh')
mkdir(auth_key_dir, username, mode=0700) mkdir(auth_key_dir, mode=0700)
authorized_key_file = os.path.join(auth_key_dir, 'authorized_keys') authorized_key_file = os.path.join(auth_key_dir, 'authorized_keys')
with open(private_key_file+'.pub') as pub_f: with open(private_key_file+'.pub') as pub_f:
with open(authorized_key_file, 'w') as auth_f: with open(authorized_key_file, 'w') as auth_f:

3
keys/README.md Normal file
View File

@ -0,0 +1,3 @@
看山是山,看水是水
看山不是山,看水不是水
看山是山,看水是水

1
logs/README.md Normal file
View File

@ -0,0 +1 @@
永远年轻,永远热泪盈眶

View File

@ -1,17 +0,0 @@
- hosts: the_del_group
tasks:
- name: del user
user: name={{ item }} state=absent remove=yes
with_items: [ the_del_users ]
- hosts: the_new_group
tasks:
- name: add user
user: name={{ item }} state=present
with_items: [ the_new_users ]
- name: .ssh direcotory
file: name=/home/{{ item }}/.ssh mode=700 owner={{ item }} group={{ item }} state=directory
with_items: [ the_new_users ]
- name: set authorizied_file
copy: src=KEY_DIR/{{ item }}.pub dest=/home/{{ item }}/.ssh/authorizied_keys owner={{ item }} group={{ item }} mode=600
with_items: [ the_new_users ]

View File

@ -14,7 +14,6 @@
</div> </div>
<div class="ibox-content"> <div class="ibox-content">
<h1 class="no-margins"><a href="/juser/user_list/">{{ users.count}}</a></h1> <h1 class="no-margins"><a href="/juser/user_list/">{{ users.count}}</a></h1>
{# <div class="stat-percent font-bold text-success">{{ percent_user }} <i class="fa fa-bolt"></i></div>#}
<small>All user</small> <small>All user</small>
</div> </div>
</div> </div>
@ -27,7 +26,6 @@
</div> </div>
<div class="ibox-content"> <div class="ibox-content">
<h1 class="no-margins"><a href="/jasset/host_list/">{{ hosts.count }}</a></h1> <h1 class="no-margins"><a href="/jasset/host_list/">{{ hosts.count }}</a></h1>
{# <div class="stat-percent font-bold text-info">{{ percent_host }} <i class="fa fa-level-up"></i></div>#}
<small>All host</small> <small>All host</small>
</div> </div>
</div> </div>
@ -37,7 +35,7 @@
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div class="ibox-title"> <div class="ibox-title">
<span class="label label-primary pull-right">Online</span> <span class="label label-primary pull-right">Online</span>
<h5>实时在线用户</h5> <h5>在线用户</h5>
</div> </div>
<div class="ibox-content"> <div class="ibox-content">
<h1 class="no-margins"><a href="/jlog/log_list/online/"> <span id="online_users">{{ online_user | length }}</span></a></h1> <h1 class="no-margins"><a href="/jlog/log_list/online/"> <span id="online_users">{{ online_user | length }}</span></a></h1>
@ -55,7 +53,6 @@
</div> </div>
<div class="ibox-content"> <div class="ibox-content">
<h1 class="no-margins"><a href="/jlog/log_list/online/"> <span id="online_hosts">{{ online_host | length }}</span></a></h1> <h1 class="no-margins"><a href="/jlog/log_list/online/"> <span id="online_hosts">{{ online_host | length }}</span></a></h1>
{# <div class="stat-percent font-bold text-danger">{{ percent_online_host }} <i class="fa fa-level-down"></i></div>#}
<small>Connected host</small> <small>Connected host</small>
</div> </div>
</div> </div>
@ -169,7 +166,7 @@
</div> </div>
</div> </div>
<div class="ibox-content ibox-heading"> <div class="ibox-content ibox-heading">
<h3><i class="fa fa-user"></i> 一周Top10资产 </h3> <h3><i class="fa fa-inbox"></i> 一周Top10资产 </h3>
<small><i class="fa fa-map-marker"></i> 登录次数及最近一次登录记录. </small> <small><i class="fa fa-map-marker"></i> 登录次数及最近一次登录记录. </small>
</div> </div>
<div class="ibox-content inspinia-timeline"> <div class="ibox-content inspinia-timeline">
@ -309,14 +306,7 @@
</div> </div>
</div> </div>
</div> </div>
</div>
<!--</div>-->
<!--<div class="col-xm-6" id="top10" style="width:50%;height:400px;"></div>-->
<!--<div class="col-xm-6" id="usertop10" style="width:50%;height:400px;"></div>-->
<!--<div class="row">-->
<!--<div class="col-lg-6" id="hosttop10" style="width:50%;height:400px; margin-top: 20px"></div>-->
<!--</div>-->
</div>
</div> </div>
{% endblock %} {% endblock %}

View File

@ -31,11 +31,11 @@
<table class="table"> <table class="table">
<tr> <tr>
<td class="text-navy">IP</td> <td class="text-navy">IP</td>
<td>{{ asset.ip }}</td> <td>{{ asset.ip|default_if_none:"" }}</td>
</tr> </tr>
<tr> <tr>
<td class="text-navy">主机名</td> <td class="text-navy">主机名</td>
<td>{{ asset.hostname }}</td> <td>{{ asset.hostname|default_if_none:"" }}</td>
</tr> </tr>
<tr> <tr>
<td class="text-navy">其他IP</td> <td class="text-navy">其他IP</td>
@ -53,11 +53,11 @@
</tr> </tr>
<tr> <tr>
<td class="text-navy">远控IP</td> <td class="text-navy">远控IP</td>
<td>{{ asset.remote_ip }}</td> <td>{{ asset.remote_ip|default_if_none:"" }}</td>
</tr> </tr>
<tr> <tr>
<td class="text-navy">端口</td> <td class="text-navy">端口</td>
<td>{{ asset.port }}</td> <td>{{ asset.port|default_if_none:"" }}</td>
</tr> </tr>
<tr> <tr>
@ -66,7 +66,7 @@
<table class="table"> <table class="table">
{% for asset_group in asset.group.all %} {% for asset_group in asset.group.all %}
<tr> <tr>
<td>{{ asset_group.name }}</td> <td>{{ asset_group.name|default_if_none:"" }}</td>
</tr> </tr>
{% endfor %} {% endfor %}
</table> </table>
@ -79,19 +79,19 @@
</tr> </tr>
<tr> <tr>
<td class="text-navy">机房</td> <td class="text-navy">机房</td>
<td>{{ asset.idc.name }}</td> <td>{{ asset.idc.name|default_if_none:"" }}</td>
</tr> </tr>
<tr> <tr>
<td class="text-navy">硬件厂商型号</td> <td class="text-navy">硬件厂商型号</td>
<td>{{ asset.brand }}</td> <td>{{ asset.brand|default_if_none:"" }}</td>
</tr> </tr>
<tr> <tr>
<td class="text-navy">CPU</td> <td class="text-navy">CPU</td>
<td>{{ asset.cpu }}</td> <td>{{ asset.cpu|default_if_none:"" }}</td>
</tr> </tr>
<tr> <tr>
<td class="text-navy">内存</td> <td class="text-navy">内存</td>
<td>{{ asset.memory }}M</td> <td>{{ asset.memory|default_if_none:"" }}{% if asset.memory %}M{% endif %}</td>
</tr> </tr>
<tr> <tr>
<td class="text-navy">硬盘</td> <td class="text-navy">硬盘</td>
@ -100,7 +100,7 @@
{% if asset.disk %} {% if asset.disk %}
{% for disk, value in asset.disk|str_to_dic %} {% for disk, value in asset.disk|str_to_dic %}
<tr> <tr>
<td><span class="text-navy">{{ disk }}</span> &nbsp&nbsp&nbsp {{ value }}</td> <td><span class="text-navy">{{ disk|default_if_none:"" }}</span> &nbsp&nbsp&nbsp {{ value|default_if_none:"" }}</td>
</tr> </tr>
{% endfor %} {% endfor %}
{% endif %} {% endif %}
@ -109,35 +109,35 @@
</tr> </tr>
<tr> <tr>
<td class="text-navy">资产编号</td> <td class="text-navy">资产编号</td>
<td>{{ asset.number }}</td> <td>{{ asset.number|default_if_none:"" }}</td>
</tr> </tr>
<tr> <tr>
<td class="text-navy">SN</td> <td class="text-navy">SN</td>
<td>{{ asset.sn }}</td> <td>{{ asset.sn|default_if_none:"" }}</td>
</tr> </tr>
<tr> <tr>
<td class="text-navy">主机类型</td> <td class="text-navy">主机类型</td>
<td>{{ asset.get_asset_type_display }}</td> <td>{{ asset.get_asset_type_display|default_if_none:"" }}</td>
</tr> </tr>
<tr> <tr>
<td class="text-navy">系统版本</td> <td class="text-navy">系统版本</td>
<td>{{ asset.system_type }} {{ asset.system_version }}</td> <td>{{ asset.system_type|default_if_none:"" }} {{ asset.system_version|default_if_none:"" }}</td>
</tr> </tr>
<tr> <tr>
<td class="text-navy">运行环境</td> <td class="text-navy">运行环境</td>
<td>{{ asset.get_env_display }}</td> <td>{{ asset.get_env_display|default_if_none:"" }}</td>
</tr> </tr>
<tr> <tr>
<td class="text-navy">机器状态</td> <td class="text-navy">机器状态</td>
<td>{{ asset.get_status_display }}</td> <td>{{ asset.get_status_display|default_if_none:"" }}</td>
</tr> </tr>
<tr> <tr>
<td class="text-navy">机柜号</td> <td class="text-navy">机柜号</td>
<td>{{ asset.cabinet }}</td> <td>{{ asset.cabinet|default_if_none:"" }}</td>
</tr> </tr>
<tr> <tr>
<td class="text-navy">机柜位置</td> <td class="text-navy">机柜位置</td>
<td>{{ asset.position }}</td> <td>{{ asset.position|default_if_none:"" }}</td>
</tr> </tr>
<tr> <tr>
<td class="text-navy">激活</td> <td class="text-navy">激活</td>
@ -149,7 +149,7 @@
</tr> </tr>
<tr> <tr>
<td class="text-navy">备注</td> <td class="text-navy">备注</td>
<td>{{ asset.comment }}</td> <td>{{ asset.comment|default_if_none:"" }}</td>
</tr> </tr>
</table> </table>
</div> </div>

View File

@ -54,17 +54,17 @@
<div class="col-sm-2"> <div class="col-sm-2">
<div class="radio i-checks"> <div class="radio i-checks">
<label> <label>
<input type="radio" checked="" value="no_action" name="use_default_auth"><span> 不修改 </span> <input type="radio" checked="" value="no_action" id="no" name="use_default_auth" class="auth"><span> 不修改 </span>
</label> </label>
</div> </div>
<div class="radio i-checks"> <div class="radio i-checks">
<label> <label>
<input type="radio" name="use_default_auth"><span> 使用默认 </span> <input type="radio" id="default" name="use_default_auth" class="auth"><span> 使用默认 </span>
</label> </label>
</div> </div>
<div class="radio i-checks"> <div class="radio i-checks">
<label> <label>
<input type="radio" id="id_use_default_auth" name="use_default_auth"><span> 用户名密码 </span> <input type="radio" id="pass" name="use_default_auth" class="auth"><span> 用户名密码 </span>
</label> </label>
</div> </div>
</div> </div>
@ -140,8 +140,8 @@
$('#uuid').val(ids) $('#uuid').val(ids)
}); });
$('#id_use_default_auth').click(function(){ $('.auth').click(function(){
if ($(this).is(':checked')){ if ($(this).attr('id') == 'pass'){
$('#admin_account').css('display', 'block') $('#admin_account').css('display', 'block')
} }
else { else {

View File

@ -1,7 +1,6 @@
<div class="col-md-12 column"> <div class="col-md-12 column">
<div class="alert alert-success alert-dismissable"> <div class="alert alert-success alert-dismissable">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button> <button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
<h4> <strong>Nice!</strong> excel文件已生成请点击 <a href="/static/files/excels/{{ file_name }}" target="_blank" class="alert-link">下载</a>
</h4> <strong>Nice!</strong> excel文件已生成请点击 <a href="/static/files/excels/{{ file_name }}" target="_blank" class="alert-link">下载</a>
</div> </div>
</div> </div>

View File

@ -119,12 +119,12 @@
<td class="text-center" name="id" value="{{ asset.id }}" data-editable='false'> <td class="text-center" name="id" value="{{ asset.id }}" data-editable='false'>
<input name="id" value="{{ asset.id }}" type="checkbox" class="i-checks"> <input name="id" value="{{ asset.id }}" type="checkbox" class="i-checks">
</td> </td>
<td class="text-center"> {{ asset.ip }} </td> <td class="text-center"> {{ asset.ip|default_if_none:"" }} </td>
<td class="text-center"> {{ asset.hostname }} </td> <td class="text-center"> {{ asset.hostname|default_if_none:"" }} </td>
<td class="text-center"> {{ asset.idc.name }} </td> <td class="text-center"> {{ asset.idc.name|default_if_none:"" }} </td>
<td class="text-center">{{ asset.group.all|group_str2 }}</td> <td class="text-center">{{ asset.group.all|group_str2 }}</td>
{# <td class="text-center">{{ asset.cpu }}|{{ asset.memory }}|{{ asset.disk }}</td>#} {# <td class="text-center">{{ asset.cpu }}|{{ asset.memory }}|{{ asset.disk }}</td>#}
<td class="text-center">{{ asset.system_type }}{{ asset.system_version }}</td> <td class="text-center">{{ asset.system_type|default_if_none:"" }}{{ asset.system_version|default_if_none:"" }}</td>
<td class="text-center"> {{ asset.use_default_auth|bool2str }} </td> <td class="text-center"> {{ asset.use_default_auth|bool2str }} </td>
<td class="text-center" data-editable='false'> <td class="text-center" data-editable='false'>
<a href="/jasset/asset_detail/?id={{ asset.id }}" class="btn btn-xs btn-primary">详情</a> <a href="/jasset/asset_detail/?id={{ asset.id }}" class="btn btn-xs btn-primary">详情</a>
@ -169,17 +169,17 @@
}); });
$(document).ready(function(){ $(document).ready(function(){
$('#editable').editableTableWidget({editor: $('<textarea>')});
$('.asset_del').click(function(){ $('.asset_del').click(function(){
var row = $(this).closest('tr'); var row = $(this).closest('tr');
$.get( if (confirm("确定删除")) {
$(this).attr('value'), $.get(
{}, $(this).attr('value'),
function(data){ {},
alert(data); function (data) {
row.remove() row.remove()
} }
) )
}
}) })
}); });

View File

@ -75,12 +75,12 @@
<div class="form-group"> <div class="form-group">
<label for="" class="col-sm-2 control-label">主机<span class="red-fonts">*</span></label> <label for="" class="col-sm-2 control-label">主机</label>
<div class="col-sm-4"> <div class="col-sm-4">
<div> <div>
<select id="assets" name="assets" class="form-control m-b" size="12" multiple> <select id="assets" name="assets" class="form-control m-b" size="12" multiple>
{% for asset in asset_all %} {% for asset in asset_all %}
<option value="{{ asset.id }}">{{ asset.ip }}</option> <option value="{{ asset.id }}">{{ asset.hostname|default_if_none:"" }} - {{ asset.ip|default_if_none:"" }} - {{ asset.port|default_if_none:"" }}</option>
{% endfor %} {% endfor %}
</select> </select>
</div> </div>
@ -133,12 +133,12 @@
timely: 2, timely: 2,
theme: "yellow_right_effect", theme: "yellow_right_effect",
fields: { fields: {
"j_group": { "name": {
rule: "required", rule: "required",
tip: "输入业务组名", tip: "输入主机组名",
ok: "", ok: "",
msg: {required: "业务组名必须填写!"}, msg: {required: "主机组名必须填写!"},
data: {'data-ok':"业务组名可以使用"} data: {'data-ok':"主机组名可以使用"}
} }
}, },
valid: function(form) { valid: function(form) {

View File

@ -52,17 +52,17 @@
<tbody> <tbody>
{% for asset in contacts.object_list %} {% for asset in contacts.object_list %}
<tr class="gradeX"> <tr class="gradeX">
<td class="text-center" name="j_id" value="{{ asset.id }}" data-editable='false'><input name="id" value="{{ asset.id }}" type="checkbox" class="i-checks"></td> <td class="text-center" name="j_id" value="{{ asset.id|default_if_none:"" }}" data-editable='false'><input name="id" value="{{ asset.id }}" type="checkbox" class="i-checks"></td>
<td class="text-center" name="j_ip"> {{ asset.ip }} </td> <td class="text-center" name="j_ip"> {{ asset.ip|default_if_none:"" }} </td>
<td class="text-center" name="j_port"> {{ asset.port }} </td> <td class="text-center" name="j_port"> {{ asset.port|default_if_none:"" }} </td>
<td class="text-center" name="j_idc"> {{ asset.idc.name }} </td> <td class="text-center" name="j_idc"> {{ asset.idc.name|default_if_none:"" }} </td>
<td class="text-center" name="j_group">{{ asset.bis_group.all | group_str2 }}</td> <td class="text-center" name="j_group">{{ asset.bis_group.all | group_str2 }}</td>
<td class="text-center" name="j_active"> {{ asset.is_active|bool2str }} </td> <td class="text-center" name="j_active"> {{ asset.is_active|bool2str }} </td>
<td class="text-center"> {{ asset.date_added|date:"Y-m-d H:i:s" }} </td> <td class="text-center"> {{ asset.date_added|date:"Y-m-d H:i:s" }} </td>
<td class="text-center" name="j_comment"> {{ asset.comment }} </td> <td class="text-center" name="j_comment"> {{ asset.comment|default_if_none:"" }} </td>
<td class="text-center" data-editable='false'> <td class="text-center" data-editable='false'>
<a href="/jasset/host_detail/?id={{ asset.id }}" class="iframe btn btn-xs btn-primary">详情</a> <a href="/jasset/asset_detail/?id={{ asset.id }}" class="iframe btn btn-xs btn-primary">详情</a>
<a href="/jasset/host_edit/?id={{ asset.id }}" class="btn btn-xs btn-info">编辑</a> <a href="/jasset/asset_edit/?id={{ asset.id }}" class="btn btn-xs btn-info">编辑</a>
<a href="/jasset/group_del_host/?id={{ asset.id }}&gid={{ group.id }}" class="btn btn-xs btn-danger">删除</a> <a href="/jasset/group_del_host/?id={{ asset.id }}&gid={{ group.id }}" class="btn btn-xs btn-danger">删除</a>
</td> </td>
</tr> </tr>

View File

@ -86,7 +86,7 @@
<div> <div>
<select id="assets" name="assets" class="form-control m-b" size="12" multiple> <select id="assets" name="assets" class="form-control m-b" size="12" multiple>
{% for asset in asset_no_select %} {% for asset in asset_no_select %}
<option value="{{ asset.id }}">{{ asset.ip }}</option> <option value="{{ asset.id }}">{{ asset.hostname|default_if_none:"" }} - {{ asset.ip|default_if_none:"" }} - {{ asset.port|default_if_none:"" }}</option>
{% endfor %} {% endfor %}
</select> </select>
</div> </div>
@ -103,7 +103,7 @@
<div> <div>
<select id="asset_select" name="asset_select" class="form-control m-b" size="12" multiple> <select id="asset_select" name="asset_select" class="form-control m-b" size="12" multiple>
{% for asset in asset_select %} {% for asset in asset_select %}
<option value="{{ asset.id }}">{{ asset.ip }}</option> <option value="{{ asset.id }}">{{ asset.hostname|default_if_none:"" }} - {{ asset.ip|default_if_none:"" }} - {{ asset.port|default_if_none:"" }}</option>
{% endfor %} {% endfor %}
</select> </select>
</div> </div>

View File

@ -63,7 +63,7 @@
<td class="text-center"> <td class="text-center">
<a href="/jasset/group_detail/?id={{ asset_group.id }}" class="btn btn-xs btn-info">详情</a> <a href="/jasset/group_detail/?id={{ asset_group.id }}" class="btn btn-xs btn-info">详情</a>
<a href="/jasset/group_edit/?id={{ asset_group.id }}" class="btn btn-xs btn-info">编辑</a> <a href="/jasset/group_edit/?id={{ asset_group.id }}" class="btn btn-xs btn-info">编辑</a>
<a value="/jasset/group_del/?id={{ asset_group.id }}" id="del" class="btn btn-xs btn-danger">删除</a> <a value="/jasset/group_del/?id={{ asset_group.id }}" class="btn btn-xs btn-danger group_del">删除</a>
</td> </td>
</tr> </tr>
{% endfor %} {% endfor %}
@ -88,16 +88,17 @@
{% block self_footer_js %} {% block self_footer_js %}
<script> <script>
$(document).ready(function(){ $(document).ready(function(){
$('#del').click(function(){ $('.group_del').click(function(){
var row = $(this).closest('tr'); var row = $(this).closest('tr');
$.get( if (confirm('确定删除')) {
$(this).attr('value'), $.get(
{}, $(this).attr('value'),
function(data){ {},
row.remove(); function (data) {
alert(data) row.remove();
} }
) )
}
}); });
$('#del_check').click(function(){ $('#del_check').click(function(){
@ -111,15 +112,12 @@
{id: check_array.join(',')}, {id: check_array.join(',')},
function(data){ function(data){
$('tr.gradeX input:checked').closest('tr').remove(); $('tr.gradeX input:checked').closest('tr').remove();
alert(data);
} }
) )
} }
}) })
}); });
</script> </script>
{% endblock %} {% endblock %}

View File

@ -40,6 +40,13 @@
</div> </div>
</div> </div>
<div class="hr-line-dashed"></div> <div class="hr-line-dashed"></div>
<div class="form-group">
<label for="role_password_label" class="col-sm-2 control-label">角色密码<span class="red-fonts">*</span></label>
<div class="col-sm-8">
<input id="role_password" name="role_password" type="password" class="form-control" value="{{ role_pass }}">
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group"> <div class="form-group">
<label for="role_comment" class="col-sm-2 control-label">备注</label> <label for="role_comment" class="col-sm-2 control-label">备注</label>
<div class="col-sm-8"> <div class="col-sm-8">

View File

@ -7,6 +7,14 @@
<div class="row"> <div class="row">
<div class="col-lg-10"> <div class="col-lg-10">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div>
{% if error %}
<div class="alert alert-warning text-center">{{ error }}</div>
{% endif %}
{% if msg %}
<div class="alert alert-success text-center">{{ msg }}</div>
{% endif %}
</div>
<div class="ibox-title"> <div class="ibox-title">
<h5> 所有系统角色</h5> <h5> 所有系统角色</h5>
<div class="ibox-tools"> <div class="ibox-tools">

View File

@ -67,16 +67,6 @@
</div> </div>
<div class="hr-line-dashed"></div> <div class="hr-line-dashed"></div>
<div class="row"> <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"> <div class="form-group">
<label for="j_group" class="col-sm-2 control-label">使用秘钥</label> <label for="j_group" class="col-sm-2 control-label">使用秘钥</label>
<div class="col-sm-1"> <div class="col-sm-1">

View File

@ -95,51 +95,11 @@
</div> </div>
</div> </div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="j_group" class="col-sm-2 control-label">使用密码</label>
<div class="col-sm-1">
<div class="radio i-checks">
<label>
<input type="checkbox" value="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="hr-line-dashed"></div>
<div class="form-group"> <div class="form-group">
<label for="comment" class="col-sm-2 control-label">备注</label> <label for="comment" class="col-sm-2 control-label">备注</label>
<div class="col-sm-8"> <div class="col-sm-8">
<input id="comment" name="comment" placeholder="Rule Comment" type="text" class="form-control" {% if error %}value="{{ username }}" {% endif %}> <input id="rule_comment" name="rule_comment" placeholder="Rule Comment" type="text" class="form-control" {% if error %}value="{{ username }}" {% endif %}>
</div> </div>
</div> </div>
<div class="hr-line-dashed"></div> <div class="hr-line-dashed"></div>

View File

@ -45,7 +45,7 @@
<div class="col-sm-8"> <div class="col-sm-8">
<select name="user" data-placeholder="用户名" class="chosen-select form-control m-b" multiple tabindex="2"> <select name="user" data-placeholder="用户名" class="chosen-select form-control m-b" multiple tabindex="2">
{% for user in users %} {% for user in users %}
<option value="{{ user.name }}">{{ user.name }}</option> <option value="{{ user.name }}" {% if user in users_select %} selected {% endif %}>{{ user.name }}</option>
{% endfor %} {% endfor %}
</select> </select>
</div> </div>
@ -56,7 +56,7 @@
<div class="col-sm-8"> <div class="col-sm-8">
<select name="usergroup" data-placeholder="请选择用户组" class="chosen-select form-control m-b" multiple tabindex="2"> <select name="usergroup" data-placeholder="请选择用户组" class="chosen-select form-control m-b" multiple tabindex="2">
{% for user_group in user_groups %} {% for user_group in user_groups %}
<option value="{{ user_group.name }}">{{ user_group.name }}</option> <option value="{{ user_group.name }}"{% if user_group in users_groups_select %} selected {% endif %}>{{ user_group.name }}</option>
{% endfor %} {% endfor %}
</select> </select>
</div> </div>
@ -67,7 +67,7 @@
<div class="col-sm-8"> <div class="col-sm-8">
<select name="asset" data-placeholder="请选择资产" class="chosen-select form-control m-b" multiple tabindex="2"> <select name="asset" data-placeholder="请选择资产" class="chosen-select form-control m-b" multiple tabindex="2">
{% for asset in assets %} {% for asset in assets %}
<option value="{{ asset.ip }}">{{ asset.ip }}</option> <option value="{{ asset.ip }}"{% if asset in assets_select %} selected {% endif %}>{{ asset.ip }}</option>
{% endfor %} {% endfor %}
</select> </select>
</div> </div>
@ -78,7 +78,7 @@
<div class="col-sm-8"> <div class="col-sm-8">
<select name="assetgroup" data-placeholder="请选择资产组" class="chosen-select form-control m-b" multiple tabindex="2"> <select name="assetgroup" data-placeholder="请选择资产组" class="chosen-select form-control m-b" multiple tabindex="2">
{% for asset_group in asset_groups %} {% for asset_group in asset_groups %}
<option value="{{ asset_group.name }}">{{ asset_group.name }}</option> <option value="{{ asset_group.name }}"{% if asset_group in asset_groups_select %} selected {% endif %}>{{ asset_group.name }}</option>
{% endfor %} {% endfor %}
</select> </select>
</div> </div>
@ -89,57 +89,17 @@
<div class="col-sm-8"> <div class="col-sm-8">
<select name="role" data-placeholder="请选择角色" class="chosen-select form-control m-b" multiple tabindex="2"> <select name="role" data-placeholder="请选择角色" class="chosen-select form-control m-b" multiple tabindex="2">
{% for role in roles %} {% for role in roles %}
<option value="{{ role.name }}">{{ role.name }}</option> <option value="{{ role.name }}"{% if role in roles_select %} selected {% endif %}>{{ role.name }}</option>
{% endfor %} {% endfor %}
</select> </select>
</div> </div>
</div> </div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="j_group" class="col-sm-2 control-label">使用密码</label>
<div class="col-sm-1">
<div class="radio i-checks">
<label>
<input type="checkbox" value="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="hr-line-dashed"></div>
<div class="form-group"> <div class="form-group">
<label for="comment" class="col-sm-2 control-label">备注</label> <label for="comment" class="col-sm-2 control-label">备注</label>
<div class="col-sm-8"> <div class="col-sm-8">
<input id="comment" name="comment" placeholder="Comment" type="text" class="form-control" {% if error %}value="{{ username }}" {% endif %}> <input id="role_comment" name="role_comment" placeholder="Rule Comment" type="text" class="form-control" value="{{ rule_comment }}">
</div> </div>
</div> </div>
<div class="hr-line-dashed"></div> <div class="hr-line-dashed"></div>

View File

@ -3,10 +3,20 @@
{% block content %} {% block content %}
{% include 'nav_cat_bar.html' %} {% include 'nav_cat_bar.html' %}
<div class="wrapper wrapper-content animated fadeInRight"> <div class="wrapper wrapper-content animated fadeInRight">
<div class="row"> <div class="row">
<div class="col-lg-10"> <div class="col-lg-10">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div>
{% if error %}
<div class="alert alert-warning text-center">{{ error }}</div>
{% endif %}
{% if msg %}
<div class="alert alert-success text-center">{{ msg }}</div>
{% endif %}
</div>
<div class="ibox-title"> <div class="ibox-title">
<h5> 所有规则</h5> <h5> 所有规则</h5>
<div class="ibox-tools"> <div class="ibox-tools">
@ -55,19 +65,19 @@
<tr class="gradeX" id={{ rule.id }}> <tr class="gradeX" id={{ rule.id }}>
<td class="text-center"> {{ rule.name }} </td> <td class="text-center"> {{ rule.name }} </td>
<td class="text-center"> <td class="text-center">
<a href="/jasset/asset_list/?gid={{ user.id }}">{{ rule | rule_member_count:"user" }} </a> {{ rule | rule_member_count:"user" }}
</td> </td>
<td class="text-center"> <td class="text-center">
<a href="/jasset/group_list/?gid={{ user.id }}">{{ rule | rule_member_count:"user_group" }}</a> {{ rule | rule_member_count:"user_group" }}
</td> </td>
<td class="text-center"> <td class="text-center">
<a href="/jasset/group_list/?gid={{ user.id }}">{{ rule | rule_member_count:"asset" }}</a> {{ rule | rule_member_count:"asset" }}
</td> </td>
<td class="text-center"> <td class="text-center">
<a href="/jasset/group_list/?gid={{ user.id }}">{{ rule | rule_member_count:"asset_group" }}</a> {{ rule | rule_member_count:"asset_group" }}
</td> </td>
<td class="text-center"> <td class="text-center">
<a href="/jasset/group_list/?gid={{ user.id }}">{{ rule | rule_member_count:"role" }}</a> {{ rule | rule_member_count:"role" }}
</td> </td>
<td class="text-center"> <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_detail/?id={{ rule.id }}" class="btn btn-xs btn-primary">详情</a>

View File

@ -64,7 +64,13 @@
<td class="text-center" title="{% for user_group in user.group.all %} {{ user_group.name }} {% endfor %}"> {{ user.group.all | groups2str }} </td> <td class="text-center" title="{% for user_group in user.group.all %} {{ user_group.name }} {% endfor %}"> {{ user.group.all | groups2str }} </td>
<td class="text-center"> {{ user.id | get_role }}</td> <td class="text-center"> {{ user.id | get_role }}</td>
<td class="text-center">{{ user.is_active | bool2str }}</td> <td class="text-center">{{ user.is_active | bool2str }}</td>
<td class="text-center"><a href="/juser/down_key/?id={{ user.id }}">下载</a></td> <td class="text-center">
{% if user.username|key_exist %}
<a href="/juser/down_key/?id={{ user.id }}" >下载</a>
{% else %}
<span style="color: #586b7d">下载</span>
{% endif %}
</td>
<td class="text-center"> <td class="text-center">
<a href="../user_detail/?id={{ user.id }}" class="btn btn-xs btn-primary">详情</a> <a href="../user_detail/?id={{ user.id }}" class="btn btn-xs btn-primary">详情</a>
<a href="../user_edit/?id={{ user.id }}" class="btn btn-xs btn-info">编辑</a> <a href="../user_edit/?id={{ user.id }}" class="btn btn-xs btn-info">编辑</a>

View File

@ -4,10 +4,10 @@
<ul class="nav" id="side-menu"> <ul class="nav" id="side-menu">
{% include 'nav_li_profile.html' %} {% include 'nav_li_profile.html' %}
<li id="index"> <li id="index">
<a href="/"><i class="fa fa-th-large"></i> <span class="nav-label">仪表盘</span><span class="label label-info pull-right"></span></a> <a href="/"><i class="fa fa-dashboard"></i> <span class="nav-label">仪表盘</span><span class="label label-info pull-right"></span></a>
</li> </li>
<li id="juser"> <li id="juser">
<a href="#"><i class="fa fa-rebel"></i> <span class="nav-label">用户管理</span><span class="fa arrow"></span></a> <a href="#"><i class="fa fa-group"></i> <span class="nav-label">用户管理</span><span class="fa arrow"></span></a>
<ul class="nav nav-second-level"> <ul class="nav nav-second-level">
<li class="group_list group_edit"><a href="/juser/group_list/">查看用户组</a></li> <li class="group_list group_edit"><a href="/juser/group_list/">查看用户组</a></li>
<li class="group_add"><a href="/juser/group_add/">添加用户组</a></li> <li class="group_add"><a href="/juser/group_add/">添加用户组</a></li>
@ -16,7 +16,7 @@
</ul> </ul>
</li> </li>
<li id="jasset"> <li id="jasset">
<a><i class="fa fa-cube"></i> <span class="nav-label">资产管理</span><span class="fa arrow"></span></a> <a><i class="fa fa-inbox"></i> <span class="nav-label">资产管理</span><span class="fa arrow"></span></a>
<ul class="nav nav-second-level"> <ul class="nav nav-second-level">
<li class="group_add"><a href="/jasset/group_add/">添加资产组</a></li> <li class="group_add"><a href="/jasset/group_add/">添加资产组</a></li>
<li class="group_list group_detail group_edit"><a href="/jasset/group_list/">查看资产组</a></li> <li class="group_list group_detail group_edit"><a href="/jasset/group_list/">查看资产组</a></li>
@ -44,7 +44,7 @@
<a href="/jlog/log_list/online/"><i class="fa fa-files-o"></i> <span class="nav-label">日志审计</span><span class="label label-info pull-right"></span></a> <a href="/jlog/log_list/online/"><i class="fa fa-files-o"></i> <span class="nav-label">日志审计</span><span class="label label-info pull-right"></span></a>
</li> </li>
<li id="setting"> <li id="setting">
<a href="/setting/"><i class="fa fa-files-o"></i> <span class="nav-label">设置</span><span class="label label-info pull-right"></span></a> <a href="/setting/"><i class="fa fa-gears"></i> <span class="nav-label">设置</span><span class="label label-info pull-right"></span></a>
</li> </li>
<li class="special_link"> <li class="special_link">
<a href="http://www.jumpserver.org" target="_blank"><i class="fa fa-database"></i> <span class="nav-label">访问官网</span></a> <a href="http://www.jumpserver.org" target="_blank"><i class="fa fa-database"></i> <span class="nav-label">访问官网</span></a>
@ -76,7 +76,7 @@
<a><i class="fa fa-cube"></i> <span class="nav-label">资产管理</span><span class="fa arrow"></span></a> <a><i class="fa fa-cube"></i> <span class="nav-label">资产管理</span><span class="fa arrow"></span></a>
<ul class="nav nav-second-level"> <ul class="nav nav-second-level">
{# <li class="host_add host_add_multi"><a href="/jasset/host_add/">添加资产</a></li>#} {# <li class="host_add host_add_multi"><a href="/jasset/host_add/">添加资产</a></li>#}
<li class="host_list host_detail host_edit"><a href="/jasset/asset_list/">查看资产<span class="label label-info pull-right">{{ host_active_num }}/{{ host_total_num}}</span></a></li> <li class="asset_list asset_detail asset_edit"><a href="/jasset/asset_list/">查看资产<span class="label label-info pull-right">{{ host_active_num }}/{{ host_total_num}}</span></a></li>
<li class="idc_list idc_detail idc_edit"><a href="/jasset/idc_list/">查看IDC</a></li> <li class="idc_list idc_detail idc_edit"><a href="/jasset/idc_list/">查看IDC</a></li>
<li class="group_add"><a href="/jasset/group_add/">添加主机组</a></li> <li class="group_add"><a href="/jasset/group_add/">添加主机组</a></li>
<li class="group_list group_detail group_edit"><a href="/jasset/group_list/">查看主机组</a></li> <li class="group_list group_detail group_edit"><a href="/jasset/group_list/">查看主机组</a></li>

View File

@ -1 +0,0 @@
1.1