Commit 31807b67 authored by liuzheng712's avatar liuzheng712

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

parents 75fbd9e6 6b1b3348
...@@ -37,6 +37,7 @@ nosetests.xml ...@@ -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
......
...@@ -19,8 +19,8 @@ import struct, fcntl, signal, socket, select ...@@ -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): ...@@ -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): ...@@ -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): ...@@ -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): ...@@ -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,21 +466,84 @@ class SshTty(Tty): ...@@ -468,21 +466,84 @@ class SshTty(Tty):
pass pass
def print_prompt(): def print_user_asset_group_info(user):
asset_groups = AssetGroup.objects.all()
for asset_group in asset_groups:
if asset_group.comment:
print '[%-2s] %-10s %s' % (asset_group.id, asset_group.name, asset_group.comment)
else:
print '[%-2s] %-10s' % (asset_group.id, asset_group.name)
print
class Nav(object):
def __init__(self, user):
self.user = user
self.search_result = {}
@staticmethod
def print_nav():
""" """
Print prompt Print prompt
打印提示导航 打印提示导航
""" """
msg = """\033[1;32m### Welcome Use JumpServer To Login. ### \033[0m msg = """\n\033[1;32m### Welcome To Use JumpServer, A Open Source System . ### \033[0m
1) Type \033[32mIP or Part IP, Host Alias or Comments \033[0m To Login. 1) Type \033[32mID\033[0m To Login.
2) Type \033[32mP/p\033[0m To Print The Servers You Available. 2) Type \033[32m/\033[0m + \033[32mIP, Host Name, Host Alias or Comments \033[0mTo Search.
3) Type \033[32mG/g\033[0m To Print The Server Groups You Available. 3) Type \033[32mP/p\033[0m To Print The Servers You Available.
4) Type \033[32mG/g(1-N)\033[0m To Print The Server Group Hosts You Available. 4) Type \033[32mG/g\033[0m To Print The Server Groups You Available.
5) Type \033[32mE/e\033[0m To Execute Command On Several Servers. 5) Type \033[32mG/g\033[0m\033[0m + \033[32mGroup ID\033[0m To Print The Server Group You Available.
6) Type \033[32mQ/q\033[0m To Quit. 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) 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(): ...@@ -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(): ...@@ -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:
......
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
...@@ -10,3 +9,8 @@ psutil==2.2.1 ...@@ -10,3 +9,8 @@ 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
\ No newline at end of file
...@@ -311,8 +311,12 @@ def write_excel(asset_all): ...@@ -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): ...@@ -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
......
...@@ -37,8 +37,8 @@ class AssetGroup(models.Model): ...@@ -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)
......
...@@ -2,9 +2,9 @@ ...@@ -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 ...@@ -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): ...@@ -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): ...@@ -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): ...@@ -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): ...@@ -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): ...@@ -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): ...@@ -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,8 +456,9 @@ def idc_del(request): ...@@ -446,8 +456,9 @@ 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)
if idc:
idc.delete() idc.delete()
return HttpResponseRedirect('/jasset/idc_list/') return HttpResponseRedirect('/jasset/idc_list/')
...@@ -455,7 +466,7 @@ def idc_del(request): ...@@ -455,7 +466,7 @@ def idc_del(request):
@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', '')
......
...@@ -15,11 +15,11 @@ from utils import get_rand_pass ...@@ -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): ...@@ -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): ...@@ -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,12 +115,13 @@ class Command(MyInventory): ...@@ -115,12 +115,13 @@ 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'")
...@@ -129,7 +130,8 @@ class Command(MyInventory): ...@@ -129,7 +130,8 @@ class Command(MyInventory):
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): ...@@ -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): ...@@ -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): ...@@ -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): ...@@ -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__": ...@@ -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)
......
...@@ -32,14 +32,13 @@ class PermRole(models.Model): ...@@ -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
\ No newline at end of file
...@@ -89,7 +89,7 @@ def perm_user_api(perm_info): ...@@ -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')})
......
...@@ -4,7 +4,7 @@ import random ...@@ -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(): ...@@ -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(): ...@@ -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()
......
This diff is collapsed.
...@@ -14,10 +14,8 @@ from django.core.paginator import Paginator, EmptyPage, InvalidPage ...@@ -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'): ...@@ -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): ...@@ -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): ...@@ -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')
...@@ -17,8 +17,8 @@ config = ConfigParser.ConfigParser() ...@@ -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 ...@@ -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')
......
...@@ -226,3 +226,14 @@ def ip_str_to_list(ip_str): ...@@ -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
...@@ -15,7 +15,6 @@ from jumpserver.api import * ...@@ -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): ...@@ -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): ...@@ -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)
......
...@@ -123,21 +123,21 @@ def db_del_user(username): ...@@ -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:
......
看山是山,看水是水
看山不是山,看水不是水
看山是山,看水是水
永远年轻,永远热泪盈眶
- 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 ]
...@@ -14,7 +14,6 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 %}
......
...@@ -31,11 +31,11 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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>
......
...@@ -54,17 +54,17 @@ ...@@ -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 @@ ...@@ -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 {
......
<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>
\ No newline at end of file
...@@ -119,12 +119,12 @@ ...@@ -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 @@ ...@@ -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');
if (confirm("确定删除")) {
$.get( $.get(
$(this).attr('value'), $(this).attr('value'),
{}, {},
function(data){ function (data) {
alert(data);
row.remove() row.remove()
} }
) )
}
}) })
}); });
......
...@@ -75,12 +75,12 @@ ...@@ -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 @@ ...@@ -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) {
......
...@@ -52,17 +52,17 @@ ...@@ -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>
......
...@@ -86,7 +86,7 @@ ...@@ -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 @@ ...@@ -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>
......
...@@ -63,7 +63,7 @@ ...@@ -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 @@ ...@@ -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');
if (confirm('确定删除')) {
$.get( $.get(
$(this).attr('value'), $(this).attr('value'),
{}, {},
function(data){ function (data) {
row.remove(); row.remove();
alert(data)
} }
) )
}
}); });
$('#del_check').click(function(){ $('#del_check').click(function(){
...@@ -111,15 +112,12 @@ ...@@ -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 %}
...@@ -40,6 +40,13 @@ ...@@ -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">
......
...@@ -7,6 +7,14 @@ ...@@ -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">
......
...@@ -67,16 +67,6 @@ ...@@ -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">
......
...@@ -95,51 +95,11 @@ ...@@ -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>
......
...@@ -45,7 +45,7 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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>
......
...@@ -3,10 +3,20 @@ ...@@ -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 @@ ...@@ -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>
......
...@@ -64,7 +64,13 @@ ...@@ -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>
......
...@@ -4,10 +4,10 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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>
......
1.1
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment