Commit fef22445 authored by halcyon's avatar halcyon

鉴权

parent 9348a0de
......@@ -43,7 +43,8 @@ LOG_DIR = os.path.join(BASE_DIR, 'logs')
SSH_KEY_DIR = os.path.join(BASE_DIR, 'keys')
SERVER_KEY_DIR = os.path.join(SSH_KEY_DIR, 'server')
KEY = CONF.get('web', 'key')
LOGIN_NAME = getpass.getuser()
#LOGIN_NAME = getpass.getuser()
LOGIN_NAME = 'wy01'
def color_print(msg, color='blue'):
......@@ -103,6 +104,7 @@ def log_record(username, host):
today_connect_log_dir = os.path.join(connect_log_dir, today)
log_filename = '%s_%s_%s.log' % (username, host, time_now)
log_file_path = os.path.join(today_connect_log_dir, log_filename)
dept_name = User.objects.get(username=username).dept
pid = os.getpid()
ip_list = []
remote_ip = os.popen("who |grep `ps aux |gawk '{if ($2==%s) print $1}'` |gawk '{print $5}'|tr -d '()'" % pid).readlines()
......@@ -122,7 +124,7 @@ def log_record(username, host):
except IOError:
raise ServerError('Create logfile failed, Please modify %s permission.' % today_connect_log_dir)
log = Log(user=username, host=host, remote_ip=ip_list, log_path=log_file_path, start_time=datetime.now(), pid=pid)
log = Log(user=username, host=host, remote_ip=ip_list, dept_name=dept_name, log_path=log_file_path, start_time=datetime.now(), pid=pid)
log_file.write('Starttime is %s\n' % datetime.now())
log.save()
return log_file, log
......
......@@ -13,7 +13,6 @@ django.setup()
from juser.views import db_add_user, md5_crypt, CRYPTOR, db_add_group
from jasset.models import Asset, IDC, BisGroup
from juser.models import UserGroup, DEPT, User
from jasset.views import jasset_group_add
from jperm.models import CmdGroup
from jlog.models import Log
......@@ -123,18 +122,18 @@ def test_add_log():
end_time = datetime.datetime.now()
log_path = '/var/log/jumpserver/test.log'
host = '192.168.1.' + str(ip)
Log.objects.create(user=user, host=host, log_path=log_path, pid=168, start_time=start_time,
Log.objects.create(user=user, host=host, remote_ip='8.8.8.8', dept_name='运维部', log_path=log_path, pid=168, start_time=start_time,
is_finished=1, log_finished=1, end_time=end_time)
if __name__ == '__main__':
install()
test_add_dept()
test_add_group()
test_add_user()
test_add_idc()
test_add_asset_group()
test_add_asset()
#install()
#test_add_dept()
#test_add_group()
#test_add_user()
#test_add_idc()
#test_add_asset_group()
#test_add_asset()
test_add_log()
......
This diff is collapsed.
......@@ -5,6 +5,7 @@ class Log(models.Model):
user = models.CharField(max_length=20, null=True)
host = models.CharField(max_length=20, null=True)
remote_ip = models.CharField(max_length=100)
dept_name = models.CharField(max_length=20)
log_path = models.CharField(max_length=100)
start_time = models.DateTimeField(null=True)
pid = models.IntegerField(max_length=10)
......
......@@ -12,6 +12,8 @@ from django.shortcuts import render_to_response
from connect import BASE_DIR
from jlog.models import Log
from jumpserver.views import pages
from juser.models import User, DEPT
from jumpserver.api import get_user_dept, is_super_user, is_group_admin, is_common_user
CONF = ConfigParser.ConfigParser()
CONF.read('%s/jumpserver.conf' % BASE_DIR)
......@@ -21,14 +23,30 @@ def log_list_online(request):
header_title, path1, path2 = u'查看日志', u'查看日志', u'在线用户'
keyword = request.GET.get('keyword')
web_socket_host = CONF.get('websocket', 'web_socket_host')
if keyword:
posts = contact_list = Log.objects.filter(Q(user__contains=keyword) | Q(host__contains=keyword)) \
.filter(is_finished=0).order_by('-start_time')
dept_id = get_user_dept(request)
dept_name = DEPT.objects.get(id=dept_id).name
user_id = request.session.get('user_id')
username = User.objects.get(id=user_id).username
if is_super_user(request):
if keyword:
posts = Log.objects.filter(Q(user__contains=keyword) | Q(host__contains=keyword)) \
.filter(is_finished=0).order_by('-start_time')
else:
posts = Log.objects.filter(is_finished=0).order_by('-start_time')
contact_list, p, contacts, page_range, current_page, show_first, show_end = pages(posts, request)
else:
posts = Log.objects.filter(is_finished=0).order_by('-start_time')
elif is_group_admin(request):
if keyword:
posts = Log.objects.filter(Q(user__contains=keyword) | Q(host__contains=keyword)) \
.filter(is_finished=0).filter(dept_name=dept_name).order_by('-start_time')
else:
posts = Log.objects.filter(is_finished=0).filter(dept_name=dept_name).order_by('-start_time')
contact_list, p, contacts, page_range, current_page, show_first, show_end = pages(posts, request)
elif is_common_user(request):
posts = Log.objects.filter(is_finished=0).filter(user=username).order_by('-start_time')
return render_to_response('jlog/log_online.html', locals(), context_instance=RequestContext(request))
......@@ -36,14 +54,29 @@ def log_list_offline(request):
header_title, path1, path2 = u'查看日志', u'查看日志', u'历史记录'
keyword = request.GET.get('keyword')
web_socket_host = CONF.get('websocket', 'web_socket_host')
if keyword:
posts = contact_list = Log.objects.filter(Q(user__contains=keyword) | Q(host__contains=keyword)) \
.filter(is_finished=1).order_by('-start_time')
dept_id = get_user_dept(request)
dept_name = DEPT.objects.get(id=dept_id).name
user_id = request.session.get('user_id')
username = User.objects.get(id=user_id).username
if is_super_user(request):
if keyword:
posts = Log.objects.filter(Q(user__contains=keyword) | Q(host__contains=keyword)) \
.filter(is_finished=1).order_by('-start_time')
else:
posts = Log.objects.filter(is_finished=1).order_by('-start_time')
contact_list, p, contacts, page_range, current_page, show_first, show_end = pages(posts, request)
else:
posts = Log.objects.filter(is_finished=1).order_by('-start_time')
elif is_group_admin(request):
if keyword:
posts = Log.objects.filter(Q(user__contains=keyword) | Q(host__contains=keyword)) \
.filter(is_finished=1).filter(dept_name=dept_name).order_by('-start_time')
else:
posts = Log.objects.filter(is_finished=1).filter(dept_name=dept_name).order_by('-start_time')
contact_list, p, contacts, page_range, current_page, show_first, show_end = pages(posts, request)
elif is_common_user(request):
posts = Log.objects.filter(is_finished=1).filter(user=username).order_by('-start_time')
return render_to_response('jlog/log_offline.html', locals(), context_instance=RequestContext(request))
......@@ -70,13 +103,23 @@ def log_history(request):
def log_search(request):
keyword = request.GET.get('keyword')
env = request.GET.get('env')
if env == 'online':
posts = contact_list = Log.objects.filter(Q(user__contains=keyword) | Q(host__contains=keyword)) \
.filter(is_finished=0).order_by('-start_time')
contact_list, p, contacts, page_range, current_page, show_first, show_end = pages(posts, request)
elif env == 'offline':
posts = contact_list = Log.objects.filter(Q(user__contains=keyword) | Q(host__contains=keyword)) \
.filter(is_finished=1).order_by('-start_time')
dept_id = get_user_dept(request)
dept_name = DEPT.objects.get(id=dept_id).name
if is_super_user(request):
if env == 'online':
posts = contact_list = Log.objects.filter(Q(user__contains=keyword) | Q(host__contains=keyword)) \
.filter(is_finished=0).order_by('-start_time')
elif env == 'offline':
posts = contact_list = Log.objects.filter(Q(user__contains=keyword) | Q(host__contains=keyword)) \
.filter(is_finished=1).order_by('-start_time')
contact_list, p, contacts, page_range, current_page, show_first, show_end = pages(posts, request)
elif is_group_admin(request):
if env == 'online':
posts = contact_list = Log.objects.filter(Q(user__contains=keyword) | Q(host__contains=keyword)) \
.filter(is_finished=0).filter(dept_name=dept_name).order_by('-start_time')
elif env == 'offline':
posts = contact_list = Log.objects.filter(Q(user__contains=keyword) | Q(host__contains=keyword)) \
.filter(is_finished=1).filter(dept_name=dept_name).order_by('-start_time')
contact_list, p, contacts, page_range, current_page, show_first, show_end = pages(posts, request)
return render_to_response('jlog/log_search.html', locals(), context_instance=RequestContext(request))
......@@ -94,6 +94,13 @@ def is_group_admin(request):
return False
def is_common_user(request):
if request.session.get('role_id') == 0:
return True
else:
return False
def get_user_dept(request):
user_id = request.session.get('user_id')
if user_id:
......
from juser.models import User
from jasset.models import Asset
def name_proc(request):
......@@ -6,8 +7,11 @@ def name_proc(request):
role_id = request.session.get('role_id')
user_total_num = User.objects.all().count()
user_active_num = User.objects.filter(is_active=True).count()
host_total_num = Asset.objects.all().count()
host_active_num = Asset.objects.filter(is_active=True).count()
request.session.set_expiry(3600)
return {'session_user_id': user_id, 'session_role_id': role_id,
'user_total_num': user_total_num, 'user_active_num': user_active_num}
'user_total_num': user_total_num, 'user_active_num': user_active_num,
'host_total_num': host_total_num, 'host_active_num': host_active_num}
......@@ -159,22 +159,6 @@ def string_length(string, length):
return '%s ...' % string[0:length]
@register.filter(name='filter_private')
def filter_private(group):
agroup = []
pattern = re.compile(r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}')
p = BisGroup.objects.get(name='ALL')
for g in group:
if not pattern.match(g.name):
agroup.append(g)
try:
agroup.remove(p)
except ValueError:
pass
return agroup
@register.filter(name='to_name')
def to_name(user_id):
try:
......
This diff is collapsed.
/*!
* FullCalendar v2.2.0 Print Stylesheet
* Docs & License: http://arshaw.com/fullcalendar/
* (c) 2013 Adam Shaw
*/
/*
* Include this stylesheet on your page to get a more printer-friendly calendar.
* When including this stylesheet, use the media='print' attribute of the <link> tag.
* Make sure to include this stylesheet IN ADDITION to the regular fullcalendar.css.
*/
.fc {
max-width: 100% !important;
}
/* Global Event Restyling
--------------------------------------------------------------------------------------------------*/
.fc-event {
background: #fff !important;
color: #000 !important;
page-break-inside: avoid;
}
.fc-event .fc-resizer {
display: none;
}
/* Table & Day-Row Restyling
--------------------------------------------------------------------------------------------------*/
th,
td,
hr,
thead,
tbody,
.fc-row {
border-color: #ccc !important;
background: #fff !important;
}
/* kill the overlaid, absolutely-positioned common components */
.fc-bg,
.fc-bgevent-skeleton,
.fc-highlight-skeleton,
.fc-helper-skeleton {
display: none;
}
/* don't force a min-height on rows (for DayGrid) */
.fc tbody .fc-row {
height: auto !important; /* undo height that JS set in distributeHeight */
min-height: 0 !important; /* undo the min-height from each view's specific stylesheet */
}
.fc tbody .fc-row .fc-content-skeleton {
position: static; /* undo .fc-rigid */
padding-bottom: 0 !important; /* use a more border-friendly method for this... */
}
.fc tbody .fc-row .fc-content-skeleton tbody tr:last-child td { /* only works in newer browsers */
padding-bottom: 1em; /* ...gives space within the skeleton. also ensures min height in a way */
}
.fc tbody .fc-row .fc-content-skeleton table {
/* provides a min-height for the row, but only effective for IE, which exaggerates this value,
making it look more like 3em. for other browers, it will already be this tall */
height: 1em;
}
/* Undo month-view event limiting. Display all events and hide the "more" links
--------------------------------------------------------------------------------------------------*/
.fc-more-cell,
.fc-more {
display: none !important;
}
.fc tr.fc-limited {
display: table-row !important;
}
.fc td.fc-limited {
display: table-cell !important;
}
.fc-popover {
display: none; /* never display the "more.." popover in print mode */
}
/* TimeGrid Restyling
--------------------------------------------------------------------------------------------------*/
/* undo the min-height 100% trick used to fill the container's height */
.fc-time-grid {
min-height: 0 !important;
}
/* don't display the side axis at all ("all-day" and time cells) */
.fc-agenda-view .fc-axis {
display: none;
}
/* don't display the horizontal lines */
.fc-slats,
.fc-time-grid hr { /* this hr is used when height is underused and needs to be filled */
display: none !important; /* important overrides inline declaration */
}
/* let the container that holds the events be naturally positioned and create real height */
.fc-time-grid .fc-content-skeleton {
position: static;
}
/* in case there are no events, we still want some height */
.fc-time-grid .fc-content-skeleton table {
height: 4em;
}
/* kill the horizontal spacing made by the event container. event margins will be done below */
.fc-time-grid .fc-event-container {
margin: 0 !important;
}
/* TimeGrid *Event* Restyling
--------------------------------------------------------------------------------------------------*/
/* naturally position events, vertically stacking them */
.fc-time-grid .fc-event {
position: static !important;
margin: 3px 2px !important;
}
/* for events that continue to a future day, give the bottom border back */
.fc-time-grid .fc-event.fc-not-end {
border-bottom-width: 1px !important;
}
/* indicate the event continues via "..." text */
.fc-time-grid .fc-event.fc-not-end:after {
content: "...";
}
/* for events that are continuations from previous days, give the top border back */
.fc-time-grid .fc-event.fc-not-start {
border-top-width: 1px !important;
}
/* indicate the event is a continuation via "..." text */
.fc-time-grid .fc-event.fc-not-start:before {
content: "...";
}
/* time */
/* undo a previous declaration and let the time text span to a second line */
.fc-time-grid .fc-event .fc-time {
white-space: normal !important;
}
/* hide the the time that is normally displayed... */
.fc-time-grid .fc-event .fc-time span {
display: none;
}
/* ...replace it with a more verbose version (includes AM/PM) stored in an html attribute */
.fc-time-grid .fc-event .fc-time:after {
content: attr(data-full);
}
/* Vertical Scroller & Containers
--------------------------------------------------------------------------------------------------*/
/* kill the scrollbars and allow natural height */
.fc-scroller,
.fc-day-grid-container, /* these divs might be assigned height, which we need to cleared */
.fc-time-grid-container { /* */
overflow: visible !important;
height: auto !important;
}
/* kill the horizontal border/padding used to compensate for scrollbars */
.fc-row {
border: 0 !important;
margin: 0 !important;
}
/* Button Controls
--------------------------------------------------------------------------------------------------*/
.fc-button-group,
.fc button {
display: none; /* don't display any button-related controls */
}
This diff is collapsed.
This diff is collapsed.
......@@ -3,6 +3,8 @@
<script src="/static/js/plugins/slimscroll/jquery.slimscroll.min.js"></script>
<script src="/static/js/bootstrap-dialog.js"></script>
<script src="/static/js/mindmup-editabletable.js"></script>
<script src="/static/js/plugins/fullcalendar/moment.min.js"></script>
<script src="/static/js/plugins/fullcalendar/fullcalendar.min.js"></script>
<!-- Custom and plugin javascript -->
<script src="/static/js/inspinia.js"></script>
......
......@@ -38,7 +38,7 @@
{% ifequal session_role_id 1 %}
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="j_dept" class="col-lg-2 control-label">所属部门<span class="red-fonts">*</span></label>
<label for="j_dept" class="col-lg-2 control-label">所属部门<span class="red-fonts" style="">*</span></label>
<div class="col-sm-8"><input type="text" name="j_dept" value="{{ edept.name }}" class="form-control" readonly="readonly"></div>
</div>
{% endifequal %}
......@@ -54,9 +54,9 @@
</select>
</div>
<div class="col-sm-1">
<div class="btn-group" style="margin-top: 50px;">
<button type="button" class="btn btn-white" onclick="move('groups', 'groups_selected')"><i class="fa fa-chevron-right"></i></button>
<button type="button" class="btn btn-white" onclick="move_left('groups_selected', 'groups')"><i class="fa fa-chevron-left"></i> </button>
<div class="fc-button-group" style="margin-top: 50px;">
<button type="button" class="fc-button fc-state-default" onclick="move('groups', 'groups_selected')"><span class="fc-icon fc-icon-right-single-arrow"></span></button>
<button type="button" class="fc-button fc-state-default" onclick="move_left('groups_selected', 'groups')"><span class="fc-icon fc-icon-left-single-arrow"></span></button>
</div>
</div>
<div class="col-sm-3">
......
......@@ -118,16 +118,6 @@
</div>
</div>
<!--<div class="hr-line-dashed"></div>-->
<!--<div class="form-group">-->
<!--<label for="j_group" class="col-sm-2 control-label"> 所属用户组<span class="red-fonts">*</span> </label>-->
<!--<div class="col-sm-8">-->
<!--{% for g in eusergroup %}-->
<!--<label class="checkbox-inline"><input type="checkbox" id="j_usergroup" value="{{ g }}" name="j_usergroup"> {{ g }} </label>-->
<!--{% endfor %}-->
<!--</div>-->
<!--</div>-->
<div class="hr-line-dashed"></div>
<div class="form-group"><label class="col-sm-2 control-label"> 是否激活<span class="red-fonts">*</span> </label>
<div class="col-sm-8">
......
......@@ -44,7 +44,7 @@
{% endif %}
<h4>按照文本框内主机信息格式填写, 多台主机回车换行</h4>
<form id="assetMulti" method="post" class="form-horizontal">
<div><textarea id="j_multi" name="j_multi" type="text" placeholder="192.168.1.1 22 LDAP 北京联通 [网站,数据库] 1 网站服务器" class="form-control" style="width:700px;height:500px"></textarea></div>
<div><textarea id="j_multi" name="j_multi" type="text" placeholder="192.168.1.1 22 LDAP 北京联通 [网站,数据库] 运维部 1 网站服务器" class="form-control" style="width:700px;height:500px">192.168.1.1 22 LDAP 北京联通 ['网站','数据库'] ['运维部','测试部'] 1 网站服务器</textarea></div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<div class="col-sm-4 col-sm-offset-4">
......
......@@ -77,6 +77,7 @@
<thead>
<tr>
<th class="text-center"> 用户名 </th>
<th class="text-center"> 所属部门 </th>
<th class="text-center"> 登录主机 </th>
<th class="text-center"> 来源IP </th>
<th class="text-center"> 命令统计 </th>
......@@ -89,8 +90,9 @@
{% for post in contacts.object_list %}
<tr class="gradeX">
<td class="text-center" id="username"> {{ post.user }} </td>
<td class="text-center" id="dept"> {{ post.dept_name }} </td>
<td class="text-center" id="ip"> {{ post.host }} </td>
<td class="text-center" id="ip"> {{ post.remote_ip }} </td>
<td class="text-center" id="remote_ip"> {{ post.remote_ip }} </td>
<td class="text-center"><a href="/jlog/history/?id={{ post.id }}" class="log_command"> 命令统计 </td>
<td class="text-center" id="start_time"> {{ post.start_time|date:"Y-m-d H:i:s"}} </td>
<td class="text-center" id="end_time"> {{ post.end_time|date:"Y-m-d H:i:s" }} </td>
......
......@@ -77,6 +77,7 @@
<thead>
<tr>
<th class="text-center"> 用户名 </th>
<th class="text-center"> 所属部门 </th>
<th class="text-center"> 登录主机 </th>
<th class="text-center"> 来源IP </th>
<th class="text-center"> 实时监控 </th>
......@@ -89,6 +90,7 @@
{% for post in contacts.object_list %}
<tr class="gradeX">
<td id="username" class="text-center"> {{ post.user }} </td>
<td id="ip" class="text-center"> {{ post.dept_name }} </td>
<td id="ip" class="text-center"> {{ post.host }} </td>
<td id="ip" class="text-center"> {{ post.remote_ip }} </td>
<td class="text-center"><a class="monitor" filename="{{ post.log_path }}"> 监控 </a></td>
......
......@@ -3,6 +3,7 @@
<thead>
<tr>
<th class="text-center"> 用户名 </th>
<th class="text-center"> 所属部门 </th>
<th class="text-center"> 登录主机 </th>
<th class="text-center"> 来源IP </th>
<th class="text-center"> 命令统计 </th>
......@@ -15,6 +16,7 @@
{% for post in contacts.object_list %}
<tr class="gradeX">
<td class="text-center" id="username"> {{ post.user }} </td>
<td class="text-center" id="ip"> {{ post.dept_name }} </td>
<td class="text-center" id="ip"> {{ post.host }} </td>
<td class="text-center" id="ip"> {{ post.remote_ip }} </td>
<td class="text-center"><a href="/jlog/history/?id={{ post.id }}" class="log_command"> 命令统计 </td>
......
......@@ -6,3 +6,4 @@
<link href="/static/css/colorbox.css" rel="stylesheet">
<link href="/static/css/vaildator/jquery.validator.css" rel="stylesheet">
<link href="/static/css/magnific/magnific-popup.css" rel="stylesheet">
<link href="/static/css/plugins/fullcalendar/fullcalendar.css" rel="stylesheet">
......@@ -27,7 +27,7 @@
<a><i class="fa fa-cube"></i> <span class="nav-label">资产管理</span><span class="fa arrow"></span></a>
<ul class="nav nav-second-level">
<li class="host_add host_add_multi"><a href="/jasset/host_add/">添加资产</a></li>
<li class="host_list"><a href="/jasset/host_list/">查看资产&nbsp&nbsp</span><span class="label label-info pull-right">16/18</span></a></li>
<li class="host_list"><a href="/jasset/host_list/">查看资产&nbsp&nbsp</span><span class="label label-info pull-right">{{ host_active_num }}/{{ host_total_num}}</span></a></li>
<li class="jgroup_add"><a href="/jasset/jgroup_add/">添加主机组</a></li>
<li class="jgroup_list group_detail"><a href="/jasset/jgroup_list/">查看主机组</a></li>
<li class="idc_add"><a href="/jasset/idc_add/">添加IDC</a></li>
......@@ -99,11 +99,11 @@
<li id="jasset">
<a><i class="fa fa-cube"></i> <span class="nav-label">资产管理</span><span class="fa arrow"></span></a>
<ul class="nav nav-second-level">
<li id="host_add"><a href="/jasset/host_add/">添加资产</a></li>
<li id="host_list"><a href="/jasset/host_list/">查看资产&nbsp&nbsp</span><span class="label label-info pull-right">16/18</span></a></li>
<li id="jgroup_add"><a href="/jasset/jgroup_add/">添加主机组</a></li>
<li id="jgroup_list"><a href="/jasset/jgroup_list/">查看主机组</a></li>
<li id="idc_list"><a href="/jasset/idc_list/">查看IDC</a></li>
<li class="host_add host_add_multi"><a href="/jasset/host_add/">添加资产</a></li>
<li class="host_list"><a href="/jasset/host_list/">查看资产&nbsp&nbsp</span><span class="label label-info pull-right">{{ host_active_num }}/{{ host_total_num}}</span></a></li>
<li class="jgroup_add"><a href="/jasset/jgroup_add/">添加主机组</a></li>
<li class="jgroup_list group_detail"><a href="/jasset/jgroup_list/">查看主机组</a></li>
<li class="idc_list idc_detail"><a href="/jasset/idc_list/">查看IDC</a></li>
</ul>
</li>
<li id="jperm">
......@@ -139,4 +139,49 @@
</ul>
</div>
</nav>
{% endifequal %}
{% ifequal session_role_id 0 %}
<nav class="navbar-default navbar-static-side" role="navigation">
<div class="sidebar-collapse">
<ul class="nav" id="side-menu">
{% include 'nav_li_profile.html' %}
<li>
<a href="/"><i class="fa fa-th-large"></i> <span class="nav-label">仪表盘</span><span class="label label-info pull-right"></span></a>
</li>
<li id="juser">
<a href="#"><i class="fa fa-rebel"></i> <span class="nav-label">用户管理</span><span class="fa arrow"></span></a>
<ul class="nav nav-second-level">
<li id="user_list"><a href="/juser/user_list/">查看用户<span class="label {% ifequal user_active_num user_total_num %}label-primary {% else %}label-warning {% endifequal %}pull-right">{{ user_active_num }}/{{ user_total_num }}</span></a></li>
</ul>
</li>
<li id="jasset">
<a><i class="fa fa-cube"></i> <span class="nav-label">资产管理</span><span class="fa arrow"></span></a>
<ul class="nav nav-second-level">
<li class="host_list"><a href="/jasset/host_list/">查看资产&nbsp&nbsp</span><span class="label label-info pull-right">16/18</span></a></li>
<li class="jgroup_list group_detail"><a href="/jasset/jgroup_list/">查看主机组</a></li>
<li class="idc_list idc_detail"><a href="/jasset/idc_list/">查看IDC</a></li>
</ul>
</li>
<li id="jlog">
<a href="#"><i class="fa fa-files-o"></i> <span class="nav-label">日志审计</span><span class="fa arrow"></span></a>
<ul class="nav nav-second-level">
<li id="log_list"><a href="/jlog/log_list/online/">查看日志</a></li>
<li id="log_detail"><a href="/jlog/log_detail/">日志分析</a></li>
</ul>
</li>
<li>
<a href="#"><i class="fa fa-download"></i> <span class="nav-label">上传下载</span><span class="fa arrow"></span></a>
<ul class="nav nav-second-level">
<li><a href="/file/upload/">文件上传</a></li>
<li><a href="/file/download/">文件下载</a></li>
</ul>
</li>
<li class="special_link">
<a href="http://www.jumpserver.org" target="_blank"><i class="fa fa-database"></i> <span class="nav-label">访问官网</span></a>
</li>
</ul>
</div>
</nav>
{% endifequal %}
\ 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