merge with dev

pull/26/head
ibuler 2015-12-19 17:26:34 +08:00
parent 1387e29591
commit c103738302
133 changed files with 5006 additions and 11881 deletions

BIN
.DS_Store vendored

Binary file not shown.

10
.gitignore vendored
View File

@ -1,7 +1,8 @@
*.py[cod] *.py[cod]
.idea .idea
test.py test.py
.DS_Store
db.sqlite3
# C extensions # C extensions
*.so *.so
@ -36,8 +37,9 @@ nosetests.xml
.mr.developer.cfg .mr.developer.cfg
.project .project
.pydevproject .pydevproject
node_modules *.log
logs logs/*
keys keys/*
jumpserver.conf jumpserver.conf
nohup.out nohup.out
tmp/*

View File

@ -1,34 +1,68 @@
#欢迎使用Jumpserver #欢迎使用Jumpserver
**Jumpserver**是一款由python编写开源的跳板机(堡垒机)系统,实现了跳板机应有的功能 **Jumpserver** 是一款由python编写开源的跳板机(堡垒机)系统,实现了跳板机应有的功能
###截图:
首页
> **统计管理** 统一管理用户 ![webterminal](https://github.com/ibuler/static/raw/master/jumpserver3/index.jpeg)
>
> **授权** 授权用户登录特定主机
>
> **审计** 审计用户操作
>
> **web管理** 漂亮的web管理界面
## 主要模块 WebTerminal:
#### 用户管理 ####
负责用户管理,添加用户,编辑用户,建立部门,建立用户组等
#### 资产管理 ####
负责资产管理添加资产编辑资产建立IDC建立用户组等
#### 授权管理 ####
负责授权用户登录某些特定主机授权sudo查看授权申请
#### 日志审计 ####
负责用户操作的审计,监控用户操作,统计用户操作记录,中断用户操作
#### 上传下载 ####
负责用户文件上传下载
[官网](http://www.jumpserver.org) ![webterminal](https://github.com/ibuler/static/raw/master/jumpserver3/webTerminal.gif)
Web批量执行命令
![WebExecCommand](https://github.com/ibuler/static/raw/master/jumpserver3/webExec.gif)
录像回放
![录像](https://github.com/ibuler/static/raw/master/jumpserver3/record.gif)
跳转和批量命令
![跳转](https://github.com/ibuler/static/raw/master/jumpserver3/connect.gif)
命令统计
![跳转](https://github.com/ibuler/static/raw/master/jumpserver3/command.png)
### 文档
* [访问wiki](https://github.com/ibuler/jumpserver/wiki)
* [快速安装](https://github.com/ibuler/jumpserver/wiki/快速安装)
* [名词解释](https://github.com/ibuler/jumpserver/wiki/名称解释)
* [快速开始](https://github.com/ibuler/jumpserver/wiki/快速开始)
### 特点
* 完全真开源GPL授权
* Python编写容易再次开发
* 实现了跳板机基本功能,认证、授权、审计
* 集成了Ansible批量命令等
* 支持WebTerminal
* Bootstrap编写界面美观
* 自动收集硬件信息
* 录像回放
* 命令搜索
* 实时监控
* 批量上传下载
### 其它
[Jumpserver官网](http://www.jumpserver.org)
[demo站点](http://demo.jumpserver.org) [demo站点](http://demo.jumpserver.org)
[更新log](http://laoguang.blog.51cto.com/6013350/1635853) ### 团队
* **广宏伟** ibuler
* **王墉** halcyon
* **陈尚委** 假想控
* **喻茂峻** 紫川秀
* **刘正** evanescunt
* **柯连春** 遍地节操
[部署文档](http://laoguang.blog.51cto.com/6013350/1636273)

1020
connect.py Normal file → Executable file

File diff suppressed because it is too large Load Diff

View File

@ -1,141 +0,0 @@
#coding:utf-8
import django
import os
import sys
import random
import datetime
sys.path.append('../')
os.environ['DJANGO_SETTINGS_MODULE'] = 'jumpserver.settings'
#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 jperm.models import CmdGroup
from jlog.models import Log
def install():
IDC.objects.create(name='ALL', comment='ALL')
IDC.objects.create(name='默认', comment='默认')
DEPT.objects.create(name="默认", comment="默认部门")
DEPT.objects.create(name="超管部", comment="超级管理员部门")
dept = DEPT.objects.get(name='超管部')
dept2 = DEPT.objects.get(name='默认')
UserGroup.objects.create(name='ALL', dept=dept, comment='ALL')
UserGroup.objects.create(name='默认', dept=dept, comment='默认')
BisGroup.objects.create(name='ALL', dept=dept, comment='ALL')
BisGroup.objects.create(name='默认', dept=dept, comment='默认')
User(id=5000, username="admin", password=md5_crypt('admin'),
name='admin', email='admin@jumpserver.org', role='SU', is_active=True, dept=dept).save()
User(id=5001, username="group_admin", password=md5_crypt('group_admin'),
name='group_admin', email='group_admin@jumpserver.org', role='DA', is_active=True, dept=dept2).save()
def test_add_idc():
for i in range(1, 20):
name = 'IDC' + str(i)
IDC.objects.create(name=name, comment='')
print 'Add: %s' % name
def test_add_dept():
for i in range(1, 100):
name = 'DEPT' + str(i)
print "Add: %s" % name
DEPT.objects.create(name=name, comment=name)
def test_add_group():
dept_all = DEPT.objects.all()
for i in range(1, 100):
name = 'UserGroup' + str(i)
UserGroup.objects.create(name=name, dept=random.choice(dept_all), comment=name)
print 'Add: %s' % name
def test_add_cmd_group():
for i in range(1, 20):
name = 'CMD' + str(i)
cmd = '/sbin/ping%s, /sbin/ifconfig/' % str(i)
CmdGroup.objects.create(name=name, cmd=cmd, comment=name)
print 'Add: %s' % name
def test_add_user():
for i in range(1, 500):
username = "test" + str(i)
dept_all = DEPT.objects.all()
group_all = UserGroup.objects.all()
group_all_id = [group.id for group in group_all]
db_add_user(username=username,
password=md5_crypt(username),
dept=random.choice(dept_all),
name=username, email='%s@jumpserver.org' % username,
groups=[random.choice(group_all_id) for i in range(1, 4)], role='CU',
ssh_key_pwd=CRYPTOR.encrypt(username),
ldap_pwd=CRYPTOR.encrypt(username),
is_active=True,
date_joined=datetime.datetime.now())
print "Add: %s" % username
def test_add_asset_group():
dept = DEPT.objects.get(name='默认')
for i in range(1, 20):
name = 'AssetGroup' + str(i)
group = BisGroup(name=name, dept=dept, comment=name)
group.save()
print 'Add: %s' % name
def test_add_asset():
idc_all = IDC.objects.all()
test_idc = random.choice(idc_all)
bis_group_all = BisGroup.objects.all()
dept_all = DEPT.objects.all()
for i in range(1, 500):
ip = '192.168.5.' + str(i)
asset = Asset(ip=ip, port=22, login_type='L', idc=test_idc, is_active=True, comment='test')
asset.save()
asset.bis_group = [random.choice(bis_group_all) for i in range(2)]
asset.dept = [random.choice(dept_all) for i in range(2)]
print "Add: %s" % ip
def test_add_log():
li_date = []
today = datetime.date.today()
oneday = datetime.timedelta(days=1)
for i in range(0, 7):
today = today-oneday
li_date.append(today)
user_list = ['马云', '马化腾', '丁磊', '周鸿祎', '雷军', '柳传志', '陈天桥', '李彦宏', '李开复', '罗永浩']
for i in range(1, 1000):
user = random.choice(user_list)
ip = random.randint(1, 20)
start_time = random.choice(li_date)
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, 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()
#test_add_log()

View File

@ -1 +0,0 @@
__author__ = 'Hudie'

View File

@ -1,36 +0,0 @@
# coding: utf8
Jumpserver开发者文档
开发规范:
1. 遵守PE8规范 1) 命名规范 2) 导入模块规范 3) 空行规范 4) 长度规范
2. 缩进统一4个空格
3. 变量命名明了易懂多个单词下划线隔开
4. 注释到位
框架说明:
1. 项目名称 Jumpserver
2. APP:
juser 用户管理
jasset 资产管理(设备管理)
jpermission 授权管理
jlog 日志管理
3. connect.py 用户登录入口程序
4. logs 日志保存目录
5. jumpserver.conf 配置文件
6. docs 文档目录
7. static 静态文件目录
8. templates 模板目录
connect.py逻辑说明
用户登录系统运行该脚本p调用get_user_host函数查看有权限的服务器ip
输入部分IPverify_connect匹配该部分ip,如果是匹配到多个就显示ip
匹配到0了就显示没有权限或者主机
匹配到1个则继续
查询该服务器是否支持ldap 如果是获得ldap用户密码登陆
如果否,查询授权表,查看该服务器授权的角色,并返回对应账号密码,登陆
connect函数是登陆函数采用paramiko 使用channel登陆posix_shell 来完成交互,并记录日志
signal模块来完成窗口改变导致的tty大小随之改变
PyCrypt是对称加密类

View File

@ -1,135 +0,0 @@
#coding:utf-8
import django
import os
import sys
import random
import datetime
sys.path.append('../')
os.environ['DJANGO_SETTINGS_MODULE'] = 'jumpserver.settings'
#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
def install():
IDC.objects.create(name='ALL', comment='ALL')
IDC.objects.create(name='默认', comment='默认')
DEPT.objects.create(name="默认", comment="默认部门")
DEPT.objects.create(name="超管部", comment="超级管理员部门")
dept = DEPT.objects.get(name='超管部')
dept2 = DEPT.objects.get(name='默认')
UserGroup.objects.create(name='ALL', dept=dept, comment='ALL')
UserGroup.objects.create(name='默认', dept=dept, comment='默认')
BisGroup.objects.create(name='ALL', dept=dept, comment='ALL')
BisGroup.objects.create(name='默认', dept=dept, comment='默认')
User(id=5000, username="admin", password=md5_crypt('admin'),
name='admin', email='admin@jumpserver.org', role='SU', is_active=True, dept=dept).save()
User(id=5001, username="group_admin", password=md5_crypt('group_admin'),
name='group_admin', email='group_admin@jumpserver.org', role='DA', is_active=True, dept=dept2).save()
def test_add_idc():
for i in range(1, 20):
name = 'IDC' + str(i)
IDC.objects.create(name=name, comment='')
print 'Add: %s' % name
def test_add_dept():
for i in range(1, 100):
name = 'DEPT' + str(i)
print "Add: %s" % name
DEPT.objects.create(name=name, comment=name)
def test_add_group():
dept_all = DEPT.objects.all()
for i in range(1, 100):
name = 'UserGroup' + str(i)
UserGroup.objects.create(name=name, dept=random.choice(dept_all), comment=name)
print 'Add: %s' % name
def test_add_cmd_group():
for i in range(1, 20):
name = 'CMD' + str(i)
cmd = '/sbin/ping%s, /sbin/ifconfig/' % str(i)
CmdGroup.objects.create(name=name, cmd=cmd, comment=name)
print 'Add: %s' % name
def test_add_user():
for i in range(1, 500):
username = "test" + str(i)
dept_all = DEPT.objects.all()
group_all = UserGroup.objects.all()
group_all_id = [group.id for group in group_all]
db_add_user(username=username,
password=md5_crypt(username),
dept=random.choice(dept_all),
name=username, email='%s@jumpserver.org' % username,
groups=[random.choice(group_all_id) for i in range(1, 4)], role='CU',
ssh_key_pwd=CRYPTOR.encrypt(username),
ldap_pwd=CRYPTOR.encrypt(username),
is_active=True,
date_joined=datetime.datetime.now())
print "Add: %s" % username
def test_add_asset_group():
dept = DEPT.objects.get(name='默认')
for i in range(1, 20):
name = 'AssetGroup' + str(i)
group = BisGroup(name=name, dept=dept, comment=name)
group.save()
print 'Add: %s' % name
def test_add_asset():
idc_all = IDC.objects.all()
test_idc = random.choice(idc_all)
bis_group_all = BisGroup.objects.all()
dept_all = DEPT.objects.all()
for i in range(1, 500):
ip = '192.168.1.' + str(i)
asset = Asset(ip=ip, port=22, login_type='L', idc=test_idc, is_active=True, comment='test')
asset.save()
asset.bis_group = [random.choice(bis_group_all) for i in range(2)]
asset.dept = [random.choice(dept_all) for i in range(2)]
print "Add: %s" % ip
def test_add_log():
li_date = []
today = datetime.date.today()
oneday = datetime.timedelta(days=1)
for i in range(0, 7):
today = today-oneday
li_date.append(today)
user_list = ['马云', '马化腾', '丁磊', '周鸿祎', '雷军', '柳传志', '陈天桥', '李彦宏', '李开复', '罗永浩']
for i in range(1, 1000):
user = random.choice(user_list)
ip = random.randint(1, 20)
start_time = random.choice(li_date)
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,
is_finished=1, log_finished=1, end_time=end_time)
if __name__ == '__main__':
install()

View File

@ -1,9 +0,0 @@
sphinx-me==0.3
django==1.6
python-ldap==2.4.19
pycrypto==2.6.1
paramiko==1.15.2
ecdsa==0.13
MySQL-python==1.2.5
django-uuidfield==0.5.0
psutil==2.2.1

View File

@ -1,13 +0,0 @@
#!/bin/bash
if [ "$USER" == "admin" ] || [ "$USER" == "root" ] || [ "$USER" == "" ];then
echo ""
else
python /opt/jumpserver/connect.py
if [ $USER == 'guanghongwei' ];then
echo
else
exit 3
echo
fi
fi

View File

@ -1,54 +1,111 @@
# coding: utf-8
import datetime import datetime
from django.db import models from django.db import models
from juser.models import User, UserGroup, DEPT from juser.models import User, UserGroup
ASSET_ENV = (
(1, U'生产环境'),
(2, U'测试环境')
)
ASSET_STATUS = (
(1, u"已使用"),
(2, u"未使用"),
(3, u"报废")
)
ASSET_TYPE = (
(1, u"物理机"),
(2, u"虚拟机"),
(3, u"交换机"),
(4, u"路由器"),
(5, u"防火墙"),
(6, u"Docker"),
(7, u"其他")
)
class IDC(models.Model): class AssetGroup(models.Model):
name = models.CharField(max_length=40, unique=True)
comment = models.CharField(max_length=80, blank=True, null=True)
def __unicode__(self):
return self.name
class BisGroup(models.Model):
GROUP_TYPE = ( GROUP_TYPE = (
('P', 'PRIVATE'), ('P', 'PRIVATE'),
('A', 'ASSET'), ('A', 'ASSET'),
) )
name = models.CharField(max_length=80, unique=True) name = models.CharField(max_length=80, unique=True)
dept = models.ForeignKey(DEPT)
comment = models.CharField(max_length=160, blank=True, null=True) comment = models.CharField(max_length=160, blank=True, null=True)
def __unicode__(self): def __unicode__(self):
return self.name return self.name
class IDC(models.Model):
name = models.CharField(max_length=32, verbose_name=u'机房名称')
bandwidth = models.CharField(max_length=32, blank=True, null=True, default='', verbose_name=u'机房带宽')
linkman = models.CharField(max_length=16, blank=True, null=True, default='', verbose_name=u'联系人')
phone = models.CharField(max_length=32, blank=True, null=True, default='', verbose_name=u'联系电话')
address = models.CharField(max_length=128, blank=True, null=True, default='', verbose_name=u"机房地址")
network = models.TextField(blank=True, null=True, default='', verbose_name=u"IP地址段")
date_added = models.DateField(auto_now=True, null=True)
operator = models.CharField(max_length=32, blank=True, default='', null=True, verbose_name=u"运营商")
comment = models.CharField(max_length=128, blank=True, default='', null=True, verbose_name=u"备注")
def __unicode__(self):
return self.name
class Meta:
verbose_name = u"IDC机房"
verbose_name_plural = verbose_name
class Asset(models.Model): class Asset(models.Model):
LOGIN_TYPE_CHOICES = ( """
('L', 'LDAP'), asset modle
('M', 'MAP'), """
) ip = models.CharField(max_length=32, blank=True, null=True, verbose_name=u"主机IP")
ip = models.IPAddressField(unique=True) other_ip = models.CharField(max_length=255, blank=True, null=True, verbose_name=u"其他IP")
port = models.IntegerField(max_length=6) hostname = models.CharField(unique=True, max_length=128, verbose_name=u"主机名")
idc = models.ForeignKey(IDC) port = models.IntegerField(blank=True, null=True, verbose_name=u"端口号")
bis_group = models.ManyToManyField(BisGroup) group = models.ManyToManyField(AssetGroup, blank=True, verbose_name=u"所属主机组")
dept = models.ManyToManyField(DEPT) username = models.CharField(max_length=16, blank=True, null=True, verbose_name=u"管理用户名")
login_type = models.CharField(max_length=1, choices=LOGIN_TYPE_CHOICES, default='L') password = models.CharField(max_length=64, blank=True, null=True, verbose_name=u"密码")
username = models.CharField(max_length=20, blank=True, null=True) use_default_auth = models.BooleanField(default=True, verbose_name=u"使用默认管理账号")
password = models.CharField(max_length=80, blank=True, null=True) idc = models.ForeignKey(IDC, blank=True, null=True, on_delete=models.SET_NULL, verbose_name=u'机房')
date_added = models.DateTimeField(auto_now=True, default=datetime.datetime.now(), null=True) mac = models.CharField(max_length=20, blank=True, null=True, verbose_name=u"MAC地址")
is_active = models.BooleanField(default=True) remote_ip = models.CharField(max_length=16, blank=True, null=True, verbose_name=u'远控卡IP')
comment = models.CharField(max_length=100, blank=True, null=True) brand = models.CharField(max_length=64, blank=True, null=True, verbose_name=u'硬件厂商型号')
cpu = models.CharField(max_length=64, blank=True, null=True, verbose_name=u'CPU')
memory = models.CharField(max_length=128, blank=True, null=True, verbose_name=u'内存')
disk = models.CharField(max_length=128, blank=True, null=True, verbose_name=u'硬盘')
system_type = models.CharField(max_length=32, blank=True, null=True, verbose_name=u"系统类型")
system_version = models.CharField(max_length=8, blank=True, null=True, verbose_name=u"系统版本号")
system_arch = models.CharField(max_length=16, blank=True, null=True, verbose_name=u"系统平台")
cabinet = models.CharField(max_length=32, blank=True, null=True, verbose_name=u'机柜号')
position = models.IntegerField(blank=True, null=True, verbose_name=u'机器位置')
number = models.CharField(max_length=32, blank=True, null=True, verbose_name=u'资产编号')
status = models.IntegerField(choices=ASSET_STATUS, blank=True, null=True, default=1, verbose_name=u"机器状态")
asset_type = models.IntegerField(choices=ASSET_TYPE, blank=True, null=True, verbose_name=u"主机类型")
env = models.IntegerField(choices=ASSET_ENV, blank=True, null=True, verbose_name=u"运行环境")
sn = models.CharField(max_length=128, blank=True, null=True, verbose_name=u"SN编号")
date_added = models.DateTimeField(auto_now=True, null=True)
is_active = models.BooleanField(default=True, verbose_name=u"是否激活")
comment = models.CharField(max_length=128, blank=True, null=True, verbose_name=u"备注")
def __unicode__(self): def __unicode__(self):
return self.ip return self.ip
class AssetRecord(models.Model):
asset = models.ForeignKey(Asset)
username = models.CharField(max_length=30, null=True)
alert_time = models.DateTimeField(auto_now_add=True)
content = models.TextField(null=True, blank=True)
comment = models.TextField(null=True, blank=True)
class AssetAlias(models.Model): class AssetAlias(models.Model):
user = models.ForeignKey(User) user = models.ForeignKey(User)
host = models.ForeignKey(Asset) asset = models.ForeignKey(Asset)
alias = models.CharField(max_length=100, blank=True, null=True) alias = models.CharField(max_length=100, blank=True, null=True)
def __unicode__(self): def __unicode__(self):
return self.comment return self.alias

View File

@ -3,26 +3,22 @@ from django.conf.urls import patterns, include, url
from jasset.views import * from jasset.views import *
urlpatterns = patterns('', urlpatterns = patterns('',
url(r'^host_add/$', host_add), url(r'^asset/add/$', asset_add, name='asset_add'),
url(r"^host_add_multi/$", host_add_batch), url(r"^asset/add_batch/$", asset_add_batch, name='asset_add_batch'),
url(r'^host_list/$', host_list), url(r'^asset/list/$', asset_list, name='asset_list'),
url(r'^search/$', host_search), url(r'^asset/del/$', asset_del, name='asset_del'),
url(r"^host_detail/$", host_detail), url(r"^asset/detail/$", asset_detail, name='asset_detail'),
url(r"^dept_host_ajax/$", dept_host_ajax), url(r'^asset/edit/$', asset_edit, name='asset_edit'),
url(r"^show_all_ajax/$", show_all_ajax), url(r'^asset/edit_batch/$', asset_edit_batch, name='asset_edit_batch'),
url(r'^idc_add/$', idc_add), url(r'^asset/update/$', asset_update, name='asset_update'),
url(r'^idc_list/$', idc_list), url(r'^asset/update_batch/$', asset_update_batch, name='asset_update_batch'),
url(r'^idc_edit/$', idc_edit), url(r'^asset/upload/$', asset_upload, name='asset_upload'),
url(r'^idc_detail/$', idc_detail), url(r'^group/del/$', group_del, name='asset_group_del'),
url(r'^idc_del/$', idc_del), url(r'^group/add/$', group_add, name='asset_group_add'),
url(r'^group_add/$', group_add), url(r'^group/list/$', group_list, name='asset_group_list'),
url(r'^group_edit/$', group_edit), url(r'^group/edit/$', group_edit, name='asset_group_edit'),
url(r'^group_list/$', group_list), url(r'^idc/add/$', idc_add, name='idc_add'),
url(r'^group_detail/$', group_detail), url(r'^idc/list/$', idc_list, name='idc_list'),
url(r'^group_del_host/$', group_del_host), url(r'^idc/edit/$', idc_edit, name='idc_edit'),
url(r'^group_del/$', group_del), url(r'^idc/del/$', idc_del, name='idc_del'),
url(r'^host_del/(\w+)/$', host_del),
url(r'^host_edit/$', view_splitter, {'su': host_edit, 'adm': host_edit_adm}),
url(r'^host_edit/batch/$', host_edit_batch),
url(r'^host_edit_common/batch/$', host_edit_common_batch),
) )

File diff suppressed because it is too large Load Diff

View File

@ -3,14 +3,13 @@ from django.db import models
class Log(models.Model): class Log(models.Model):
user = models.CharField(max_length=20, null=True) user = models.CharField(max_length=20, null=True)
host = models.CharField(max_length=20, null=True) host = models.CharField(max_length=200, null=True)
remote_ip = models.CharField(max_length=100) remote_ip = models.CharField(max_length=100)
dept_name = models.CharField(max_length=20) login_type = models.CharField(max_length=100)
log_path = models.CharField(max_length=100) log_path = models.CharField(max_length=100)
start_time = models.DateTimeField(null=True) start_time = models.DateTimeField(null=True)
pid = models.IntegerField(max_length=10) pid = models.IntegerField()
is_finished = models.BooleanField(default=False) is_finished = models.BooleanField(default=False)
log_finished = models.BooleanField(default=False)
end_time = models.DateTimeField(null=True) end_time = models.DateTimeField(null=True)
def __unicode__(self): def __unicode__(self):
@ -21,3 +20,30 @@ class Alert(models.Model):
msg = models.CharField(max_length=20) msg = models.CharField(max_length=20)
time = models.DateTimeField(null=True) time = models.DateTimeField(null=True)
is_finished = models.BigIntegerField(default=False) is_finished = models.BigIntegerField(default=False)
class TtyLog(models.Model):
log = models.ForeignKey(Log)
datetime = models.DateTimeField(auto_now=True)
cmd = models.CharField(max_length=200)
class ExecLog(models.Model):
user = models.CharField(max_length=100)
host = models.TextField()
cmd = models.TextField()
remote_ip = models.CharField(max_length=100)
result = models.TextField(default='')
datetime = models.DateTimeField(auto_now=True)
class FileLog(models.Model):
user = models.CharField(max_length=100)
host = models.TextField()
filename = models.TextField()
type = models.CharField(max_length=20)
remote_ip = models.CharField(max_length=100)
result = models.TextField(default='')
datetime = models.DateTimeField(auto_now=True)

View File

@ -3,9 +3,9 @@ from django.conf.urls import patterns, include, url
from jlog.views import * from jlog.views import *
urlpatterns = patterns('', urlpatterns = patterns('',
url(r'^$', log_list), url(r'^list/(\w+)/$', log_list, name='log_list'),
url(r'^log_list/(\w+)/$', log_list), url(r'^detail/(\w+)/$', log_detail, name='log_detail'),
url(r'^log_kill/', log_kill), url(r'^history/$', log_history, name='log_history'),
url(r'^history/$', log_history), url(r'^log_kill/', log_kill, name='log_kill'),
url(r'^search/$', log_search), url(r'^record/$', log_record, name='log_record'),
) )

View File

@ -4,78 +4,93 @@ from django.template import RequestContext
from django.shortcuts import render_to_response from django.shortcuts import render_to_response
from jumpserver.api import * from jumpserver.api import *
from jasset.views import httperror from jperm.perm_api import user_have_perm
from django.http import HttpResponseNotFound from django.http import HttpResponseNotFound
from jlog.log_api import renderTemplate
CONF = ConfigParser() from jlog.models import Log, ExecLog, FileLog
CONF.read('%s/jumpserver.conf' % BASE_DIR) from jumpserver.settings import WEB_SOCKET_HOST
def get_user_info(request, offset): @require_role('admin')
""" 获取用户信息及环境 """
env_dic = {'online': 0, 'offline': 1}
env = env_dic[offset]
keyword = request.GET.get('keyword', '')
user_info = get_session_user_info(request)
user_id, username = user_info[0:2]
dept_id, dept_name = user_info[3:5]
ret = [request, keyword, env, username, dept_name]
return ret
def get_user_log(ret_list):
""" 获取不同类型用户日志记录 """
request, keyword, env, username, dept_name = ret_list
post_all = Log.objects.filter(is_finished=env).order_by('-start_time')
post_keyword_all = Log.objects.filter(Q(user__contains=keyword) |
Q(host__contains=keyword)) \
.filter(is_finished=env).order_by('-start_time')
if is_super_user(request):
if keyword:
posts = post_keyword_all
else:
posts = post_all
elif is_group_admin(request):
if keyword:
posts = post_keyword_all.filter(dept_name=dept_name)
else:
posts = post_all.filter(dept_name=dept_name)
elif is_common_user(request):
if keyword:
posts = post_keyword_all.filter(user=username)
else:
posts = post_all.filter(user=username)
return posts
@require_login
def log_list(request, offset): def log_list(request, offset):
""" 显示日志 """ """ 显示日志 """
header_title, path1, path2 = u'查看日志', u'查看日志', u'在线用户' header_title, path1 = u'审计', u'操作审计'
date_seven_day = request.GET.get('start', '')
date_now_str = request.GET.get('end', '')
username_list = request.GET.getlist('username', [])
host_list = request.GET.getlist('host', [])
cmd = request.GET.get('cmd', '')
if offset == 'online':
keyword = request.GET.get('keyword', '') keyword = request.GET.get('keyword', '')
web_socket_host = CONF.get('websocket', 'web_socket_host') posts = Log.objects.filter(is_finished=False).order_by('-start_time')
posts = get_user_log(get_user_info(request, offset)) if keyword:
posts = posts.filter(Q(user__icontains=keyword) | Q(host__icontains=keyword) |
Q(login_type_icontains=keyword))
elif offset == 'exec':
posts = ExecLog.objects.all().order_by('-id')
keyword = request.GET.get('keyword', '')
if keyword:
posts = posts.filter(Q(user__icontains=keyword)|Q(host__icontains=keyword)|Q(cmd__icontains=keyword))
elif offset == 'file':
posts = FileLog.objects.all().order_by('-id')
keyword = request.GET.get('keyword', '')
if keyword:
posts = posts.filter(Q(user__icontains=keyword)|Q(host__icontains=keyword)|Q(filename__icontains=keyword))
else:
posts = Log.objects.filter(is_finished=True).order_by('-start_time')
username_all = set([log.user for log in Log.objects.all()])
ip_all = set([log.host for log in Log.objects.all()])
if date_seven_day and date_now_str:
datetime_start = datetime.datetime.strptime(date_seven_day + ' 00:00:01', '%m/%d/%Y %H:%M:%S')
datetime_end = datetime.datetime.strptime(date_now_str + ' 23:59:59', '%m/%d/%Y %H:%M:%S')
posts = posts.filter(start_time__gte=datetime_start).filter(start_time__lte=datetime_end)
if username_list:
posts = posts.filter(user__in=username_list)
if host_list:
posts = posts.filter(host__in=host_list)
if cmd:
log_id_list = set([log.log_id for log in TtyLog.objects.filter(cmd__contains=cmd)])
posts = posts.filter(id__in=log_id_list)
if not date_seven_day:
date_now = datetime.datetime.now()
date_now_str = date_now.strftime('%m/%d/%Y')
date_seven_day = (date_now + datetime.timedelta(days=-7)).strftime('%m/%d/%Y')
contact_list, p, contacts, page_range, current_page, show_first, show_end = pages(posts, request) contact_list, p, contacts, page_range, current_page, show_first, show_end = pages(posts, request)
web_monitor_uri = 'ws://%s/monitor' % WEB_SOCKET_HOST
web_kill_uri = 'http://%s/kill' % WEB_SOCKET_HOST
session_id = request.session.session_key
return render_to_response('jlog/log_%s.html' % offset, locals(), context_instance=RequestContext(request)) return render_to_response('jlog/log_%s.html' % offset, locals(), context_instance=RequestContext(request))
@require_admin @require_role('admin')
def log_detail(request):
return my_render('jlog/exec_detail.html', locals(), request)
@require_role('admin')
def log_kill(request): def log_kill(request):
""" 杀掉connect进程 """ """ 杀掉connect进程 """
pid = request.GET.get('id', '') pid = request.GET.get('id', '')
log = Log.objects.filter(pid=pid) log = Log.objects.filter(pid=pid)
if log: if log:
log = log[0] log = log[0]
<<<<<<< HEAD
dept_name = log.dept_name dept_name = log.dept_name
deptname = get_session_user_info(request)[4] deptname = get_session_user_info(request)[4]
if is_group_admin(request) and dept_name != deptname: if is_group_admin(request) and dept_name != deptname:
return httperror(request, u'Kill失败, 您无权操作!') return httperror(request, u'Kill失败, 您无权操作!')
=======
>>>>>>> dev
try: try:
os.kill(int(pid), 9) os.kill(int(pid), 9)
except OSError: except OSError:
@ -86,35 +101,56 @@ def log_kill(request):
return HttpResponseNotFound(u'没有此进程!') return HttpResponseNotFound(u'没有此进程!')
@require_login @require_role('admin')
def log_history(request): def log_history(request):
""" 命令历史记录 """ """ 命令历史记录 """
log_id = request.GET.get('id', 0)
log = Log.objects.filter(id=log_id)
if log:
log = log[0]
tty_logs = log.ttylog_set.all()
if tty_logs:
content = ''
for tty_log in tty_logs:
content += '%s: %s\n' % (tty_log.datetime.strftime('%Y-%m-%d %H:%M:%S'), tty_log.cmd)
return HttpResponse(content)
return HttpResponse('无日志记录!')
@require_role('admin')
def log_record(request):
log_id = request.GET.get('id', 0) log_id = request.GET.get('id', 0)
log = Log.objects.filter(id=int(log_id)) log = Log.objects.filter(id=int(log_id))
if log: if log:
log = log[0] log = log[0]
dept_name = log.dept_name log_file = log.log_path + '.log'
deptname = get_session_user_info(request)[4] log_time = log.log_path + '.time'
if is_group_admin(request) and dept_name != deptname: if os.path.isfile(log_file) and os.path.isfile(log_time):
return httperror(request, '查看失败, 您无权查看!') content = renderTemplate(log_file, log_time)
elif is_common_user(request):
return httperror(request, '查看失败, 您无权查看!')
log_his = "%s.his" % log.log_path
if os.path.isfile(log_his):
f = open(log_his)
content = f.read()
return HttpResponse(content) return HttpResponse(content)
else: else:
return httperror(request, '无日志记录, 请查看日志处理脚本是否开启!') return HttpResponse('无日志记录!')
@require_login @require_role('admin')
def log_search(request): def log_detail(request, offset):
""" 日志搜索 """ log_id = request.GET.get('id')
offset = request.GET.get('env', '') if offset == 'exec':
keyword = request.GET.get('keyword', '') log = get_object(ExecLog, id=log_id)
posts = get_user_log(get_user_info(request, offset)) assets_hostname = log.host.split(' ')
contact_list, p, contacts, page_range, current_page, show_first, show_end = pages(posts, request) try:
return render_to_response('jlog/log_search.html', locals(), context_instance=RequestContext(request)) result = eval(str(log.result))
except (SyntaxError, NameError):
result = {}
return my_render('jlog/exec_detail.html', locals(), request)
elif offset == 'file':
log = get_object(FileLog, id=log_id)
assets_hostname = log.host.split(' ')
file_list = log.filename.split(' ')
try:
result = eval(str(log.result))
except (SyntaxError, NameError):
result = {}
return my_render('jlog/file_detail.html', locals(), request)

View File

@ -1,54 +1,60 @@
import datetime import datetime
from uuidfield import UUIDField
from django.db import models from django.db import models
from juser.models import UserGroup, DEPT from jasset.models import Asset, AssetGroup
from jasset.models import Asset, BisGroup from juser.models import User, UserGroup
class Perm(models.Model): class PermLog(models.Model):
user_group = models.ForeignKey(UserGroup) datetime = models.DateTimeField(auto_now_add=True)
asset_group = models.ForeignKey(BisGroup) action = models.CharField(max_length=100, null=True, blank=True, default='')
results = models.CharField(max_length=1000, null=True, blank=True, default='')
def __unicode__(self): is_success = models.BooleanField(default=False)
return '%s_%s' % (self.user_group.name, self.asset_group.name) is_finish = models.BooleanField(default=False)
class CmdGroup(models.Model): class PermSudo(models.Model):
name = models.CharField(max_length=50, unique=True) name = models.CharField(max_length=100, unique=True)
cmd = models.CharField(max_length=999) date_added = models.DateTimeField(auto_now=True)
dept = models.ForeignKey(DEPT) commands = models.TextField()
comment = models.CharField(blank=True, null=True, max_length=50) comment = models.CharField(max_length=100, null=True, blank=True, default='')
def __unicode__(self): def __unicode__(self):
return self.name return self.name
class SudoPerm(models.Model): class PermRole(models.Model):
user_group = models.ForeignKey(UserGroup) name = models.CharField(max_length=100, unique=True)
user_runas = models.CharField(max_length=100) comment = models.CharField(max_length=100, null=True, blank=True, default='')
asset_group = models.ManyToManyField(BisGroup) password = models.CharField(max_length=100)
cmd_group = models.ManyToManyField(CmdGroup) key_path = models.CharField(max_length=100)
comment = models.CharField(max_length=30, null=True, blank=True) date_added = models.DateTimeField(auto_now=True)
sudo = models.ManyToManyField(PermSudo, related_name='perm_role')
def __unicode__(self): def __unicode__(self):
return self.user_group.name return self.name
class Apply(models.Model): class PermRule(models.Model):
uuid = UUIDField(auto=True) date_added = models.DateTimeField(auto_now=True)
applyer = models.CharField(max_length=20) name = models.CharField(max_length=100, unique=True)
admin = models.CharField(max_length=20) comment = models.CharField(max_length=100)
approver = models.CharField(max_length=20) asset = models.ManyToManyField(Asset, related_name='perm_rule')
dept = models.CharField(max_length=20) asset_group = models.ManyToManyField(AssetGroup, related_name='perm_rule')
bisgroup = models.CharField(max_length=500) user = models.ManyToManyField(User, related_name='perm_rule')
asset = models.CharField(max_length=500) user_group = models.ManyToManyField(UserGroup, related_name='perm_rule')
comment = models.TextField(blank=True, null=True) role = models.ManyToManyField(PermRole, related_name='perm_rule')
status = models.IntegerField(max_length=2)
date_add = models.DateTimeField(null=True)
date_end = models.DateTimeField(null=True)
read = models.IntegerField(max_length=2)
def __unicode__(self): def __unicode__(self):
return self.applyer return self.name
class PermPush(models.Model):
asset = models.ForeignKey(Asset, related_name='perm_push')
role = models.ForeignKey(PermRole, related_name='perm_push')
is_public_key = models.BooleanField(default=False)
is_password = models.BooleanField(default=False)
success = models.BooleanField(default=False)
result = models.TextField(default='')
date_added = models.DateTimeField(auto_now=True)

View File

@ -2,32 +2,21 @@ from django.conf.urls import patterns, include, url
from jperm.views import * from jperm.views import *
urlpatterns = patterns('jperm.views', urlpatterns = patterns('jperm.views',
# Examples: url(r'^rule/list/$', perm_rule_list, name='rule_list'),
# url(r'^$', 'jumpserver.views.home', name='home'), url(r'^rule/add/$', perm_rule_add, name='rule_add'),
# url(r'^blog/', include('blog.urls')), url(r'^rule/detail/$', perm_rule_detail, name='rule_detail'),
url(r'^rule/edit/$', perm_rule_edit, name='rule_edit'),
(r'^perm_edit/$', view_splitter, {'su': perm_edit, 'adm': perm_edit_adm}), url(r'^rule/del/$', perm_rule_delete, name='rule_del'),
(r'^dept_perm_edit/$', 'dept_perm_edit'), url(r'^role/list/$', perm_role_list, name='role_list'),
(r'^perm_list/$', view_splitter, {'su': perm_list, 'adm': perm_list_adm}), url(r'^role/add/$', perm_role_add, name='role_add'),
(r'^dept_perm_list/$', 'dept_perm_list'), url(r'^role/del/$', perm_role_delete, name='role_del'),
(r'^perm_user_detail/$', 'perm_user_detail'), url(r'^role/detail/$', perm_role_detail, name='role_detail'),
(r'^perm_detail/$', 'perm_detail'), url(r'^role/edit/$', perm_role_edit, name='role_edit'),
(r'^perm_del/$', 'perm_del'), url(r'^role/push/$', perm_role_push, name='role_push'),
(r'^perm_asset_detail/$', 'perm_asset_detail'), url(r'^role/recycle/$', perm_role_recycle, name='role_recycle'),
(r'^sudo_list/$', view_splitter, {'su': sudo_list, 'adm': sudo_list_adm}), url(r'^role/get/$', perm_role_get, name='role_get'),
(r'^sudo_del/$', 'sudo_del'), url(r'^sudo/list/$', perm_sudo_list, name='sudo_list'),
(r'^sudo_edit/$', view_splitter, {'su': sudo_edit, 'adm': sudo_edit_adm}), url(r'^sudo/add/$', perm_sudo_add, name='sudo_add'),
(r'^sudo_refresh/$', 'sudo_refresh'), url(r'^sudo/del/$', perm_sudo_delete, name='sudo_del'),
(r'^sudo_detail/$', 'sudo_detail'), url(r'^sudo/edit/$', perm_sudo_edit, name='sudo_edit'),
(r'^cmd_add/$', view_splitter, {'su': cmd_add, 'adm': cmd_add_adm}), )
(r'^cmd_list/$', 'cmd_list'),
(r'^cmd_del/$', 'cmd_del'),
(r'^cmd_edit/$', 'cmd_edit'),
(r'^cmd_detail/$', 'cmd_detail'),
(r'^apply/$', 'perm_apply'),
(r'^apply_show/(\w+)/$', 'perm_apply_log'),
(r'^apply_exec/$', 'perm_apply_exec'),
(r'^apply_info/$', 'perm_apply_info'),
(r'^apply_del/$', 'perm_apply_del'),
(r'^apply_search/$', 'perm_apply_search'),
)

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,7 @@
#coding: utf8
[base] [base]
ip = 192.168.20.209 url = http://192.168.244.129
port = 80
key = 88aaaf7ffe3c6c04 key = 88aaaf7ffe3c6c04
log = debug
[db] [db]
host = 127.0.0.1 host = 127.0.0.1
@ -13,22 +10,20 @@ user = jumpserver
password = mysql234 password = mysql234
database = jumpserver database = jumpserver
[ldap]
ldap_enable = 1
host_url = ldap://127.0.0.1:389
base_dn = dc=jumpserver, dc=org
root_dn = cn=admin,dc=jumpserver,dc=org
root_pw = secret234
[websocket] [websocket]
web_socket_host = 192.168.40.140:3000 web_socket_host = 192.168.244.129:3000
[mail] [mail]
mail_enable = 1
email_host = smtp.qq.com email_host = smtp.qq.com
email_port = 25 email_port = 25
<<<<<<< HEAD
email_host_user = 1152704203@qq.com email_host_user = 1152704203@qq.com
email_host_password = Hudie117... email_host_password = Hudie117...
email_use_tls = False email_use_tls = False
=======
email_host_user = ibuler@qq.com
email_host_password = Hudie117...qq
email_use_tls = True
>>>>>>> dev

View File

@ -1,27 +1,31 @@
# coding: utf-8 # coding: utf-8
import os, sys, time, re
from django.http import HttpResponseRedirect
import json
import os
from ConfigParser import ConfigParser
import getpass
from Crypto.Cipher import AES from Crypto.Cipher import AES
import crypt
import pwd
from binascii import b2a_hex, a2b_hex from binascii import b2a_hex, a2b_hex
import ldap
from ldap import modlist
import hashlib import hashlib
import datetime import datetime
import random
import subprocess import subprocess
import uuid
import json
import logging
from settings import *
from django.core.paginator import Paginator, EmptyPage, InvalidPage 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 juser.models import User, UserGroup
from jlog.models import Log, TtyLog
from jasset.models import Asset, AssetGroup
from jperm.models import PermRule, PermRole
from jumpserver.models import Setting
from django.http import HttpResponseRedirect
from django.shortcuts import render_to_response from django.shortcuts import render_to_response
from juser.models import User, UserGroup, DEPT
from jasset.models import Asset, BisGroup, IDC
from jlog.models import Log
from jasset.models import AssetAlias
from django.core.exceptions import ObjectDoesNotExist
from django.core.mail import send_mail from django.core.mail import send_mail
<<<<<<< HEAD
import json import json
@ -105,64 +109,208 @@ if LDAP_ENABLE:
def md5_crypt(string): def md5_crypt(string):
return hashlib.new("md5", string).hexdigest() return hashlib.new("md5", string).hexdigest()
=======
from django.core.urlresolvers import reverse
def set_log(level, filename='jumpserver.log'):
"""
return a log file object
根据提示设置log打印
"""
log_file = os.path.join(LOG_DIR, filename)
if not os.path.isfile(log_file):
os.mknod(log_file)
os.chmod(log_file, 0777)
log_level_total = {'debug': logging.DEBUG, 'info': logging.INFO, 'warning': logging.WARN, 'error': logging.ERROR,
'critical': logging.CRITICAL}
logger_f = logging.getLogger('jumpserver')
logger_f.setLevel(logging.DEBUG)
fh = logging.FileHandler(log_file)
fh.setLevel(log_level_total.get(level, logging.DEBUG))
formatter = logging.Formatter('%(asctime)s - %(filename)s - %(levelname)s - %(message)s')
fh.setFormatter(formatter)
logger_f.addHandler(fh)
return logger_f
def list_drop_str(a_list, a_str):
for i in a_list:
if i == a_str:
a_list.remove(a_str)
return a_list
def get_asset_info(asset):
"""
获取资产的相关管理账号端口等信息
"""
default = get_object(Setting, name='default')
info = {'hostname': asset.hostname, 'ip': asset.ip}
if asset.use_default_auth:
if default:
info['port'] = int(default.field2)
info['username'] = default.field1
try:
info['password'] = CRYPTOR.decrypt(default.field3)
except ServerError:
pass
if os.path.isfile(default.field4):
info['ssh_key'] = default.field4
else:
info['port'] = int(asset.port)
info['username'] = asset.username
info['password'] = CRYPTOR.decrypt(asset.password)
return info
def get_role_key(user, role):
"""
由于role的key的权限是所有人可以读的 ansible执行命令等要求为600所以拷贝一份到特殊目录
:param user:
:param role:
:return: self key path
"""
user_role_key_dir = os.path.join(KEY_DIR, 'user')
user_role_key_path = os.path.join(user_role_key_dir, '%s_%s.pem' % (user.username, role.name))
mkdir(user_role_key_dir, mode=0777)
if not os.path.isfile(user_role_key_path):
with open(os.path.join(role.key_path, 'id_rsa')) as fk:
with open(user_role_key_path, 'w') as fu:
fu.write(fk.read())
logger.debug(u"创建新的系统用户key %s, Owner: %s" % (user_role_key_path, user.username))
chown(user_role_key_path, user.username)
os.chmod(user_role_key_path, 0600)
return user_role_key_path
def chown(path, user, group=''):
if not group:
group = user
try:
uid = pwd.getpwnam(user).pw_uid
gid = pwd.getpwnam(group).pw_gid
os.chown(path, uid, gid)
except KeyError:
pass
>>>>>>> dev
def page_list_return(total, current=1): def page_list_return(total, current=1):
"""
page
分页返回本次分页的最小页数到最大页数列表
"""
min_page = current - 2 if current - 4 > 0 else 1 min_page = current - 2 if current - 4 > 0 else 1
max_page = min_page + 4 if min_page + 4 < total else total max_page = min_page + 4 if min_page + 4 < total else total
return range(min_page, max_page+1) return range(min_page, max_page + 1)
def pages(posts, r): def pages(post_objects, request):
"""分页公用函数""" """
contact_list = posts page public function , return page's object tuple
p = paginator = Paginator(contact_list, 10) 分页公用函数返回分页的对象元组
"""
paginator = Paginator(post_objects, 20)
try: try:
current_page = int(r.GET.get('page', '1')) current_page = int(request.GET.get('page', '1'))
except ValueError: except ValueError:
current_page = 1 current_page = 1
page_range = page_list_return(len(p.page_range), current_page) page_range = page_list_return(len(paginator.page_range), current_page)
try: try:
contacts = paginator.page(current_page) page_objects = paginator.page(current_page)
except (EmptyPage, InvalidPage): except (EmptyPage, InvalidPage):
contacts = paginator.page(paginator.num_pages) page_objects = paginator.page(paginator.num_pages)
if current_page >= 5: if current_page >= 5:
show_first = 1 show_first = 1
else: else:
show_first = 0 show_first = 0
if current_page <= (len(p.page_range) - 3):
if current_page <= (len(paginator.page_range) - 3):
show_end = 1 show_end = 1
else: else:
show_end = 0 show_end = 0
return contact_list, p, contacts, page_range, current_page, show_first, show_end # 所有对象, 分页器, 本页对象, 所有页码, 本页页码,是否显示第一页,是否显示最后一页
return post_objects, paginator, page_objects, page_range, current_page, show_first, show_end
class PyCrypt(object): class PyCrypt(object):
"""This class used to encrypt and decrypt password.""" """
This class used to encrypt and decrypt password.
加密类
"""
def __init__(self, key): def __init__(self, key):
self.key = key self.key = key
self.mode = AES.MODE_CBC self.mode = AES.MODE_CBC
def encrypt(self, text): @staticmethod
cryptor = AES.new(self.key, self.mode, b'0000000000000000') def gen_rand_pass(length, especial=False):
length = 16 """
random password
随机生成密码
"""
salt_key = '1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_'
symbol = '!@$%^&*()_'
salt_list = []
if especial:
for i in range(length - 4):
salt_list.append(random.choice(salt_key))
for i in range(4):
salt_list.append(random.choice(symbol))
else:
for i in range(length):
salt_list.append(random.choice(salt_key))
salt = ''.join(salt_list)
return salt
@staticmethod
def md5_crypt(string):
"""
md5 encrypt method
md5非对称加密方法
"""
return hashlib.new("md5", string).hexdigest()
@staticmethod
def gen_sha512(salt, password):
"""
generate sha512 format password
生成sha512加密密码
"""
return crypt.crypt(password, '$6$%s$' % salt)
def encrypt(self, passwd=None, length=32):
"""
encrypt gen password
对称加密之加密生成密码
"""
if not passwd:
passwd = self.gen_rand_pass()
cryptor = AES.new(self.key, self.mode, b'8122ca7d906ad5e1')
try: try:
count = len(text) count = len(passwd)
except TypeError: except TypeError:
raise ServerError('Encrypt password error, TYpe error.') raise ServerError('Encrypt password error, TYpe error.')
add = (length - (count % length)) add = (length - (count % length))
text += ('\0' * add) passwd += ('\0' * add)
ciphertext = cryptor.encrypt(text) cipher_text = cryptor.encrypt(passwd)
return b2a_hex(ciphertext) return b2a_hex(cipher_text)
def decrypt(self, text): def decrypt(self, text):
cryptor = AES.new(self.key, self.mode, b'0000000000000000') """
decrypt pass base the same key
对称加密之解密同一个加密随机数
"""
cryptor = AES.new(self.key, self.mode, b'8122ca7d906ad5e1')
try: try:
plain_text = cryptor.decrypt(a2b_hex(text)) plain_text = cryptor.decrypt(a2b_hex(text))
except TypeError: except TypeError:
@ -170,95 +318,103 @@ class PyCrypt(object):
return plain_text.rstrip('\0') return plain_text.rstrip('\0')
CRYPTOR = PyCrypt(KEY)
class ServerError(Exception): class ServerError(Exception):
"""
self define exception
自定义异常
"""
pass pass
def get_object(model, **kwargs): def get_object(model, **kwargs):
try: """
the_object = model.objects.get(**kwargs) use this function for query
except ObjectDoesNotExist: 使用改封装函数查询数据库
raise ServerError('Object get %s failed.' % str(kwargs.values())) """
for value in kwargs.values():
if not value:
return None
the_object = model.objects.filter(**kwargs)
if len(the_object) == 1:
the_object = the_object[0]
else:
the_object = None
return the_object return the_object
def require_login(func): def require_role(role='user'):
"""要求登录的装饰器""" """
def _deco(request, *args, **kwargs): decorator for require user role in ["super", "admin", "user"]
if not request.session.get('user_id'): 要求用户是某种角色 ["super", "admin", "user"]的装饰器
return HttpResponseRedirect('/login/') """
def _deco(func):
def __deco(request, *args, **kwargs):
request.session['pre_url'] = request.path
if not request.user.is_authenticated():
return HttpResponseRedirect(reverse('login'))
if role == 'admin':
# if request.session.get('role_id', 0) < 1:
if request.user.role == 'CU':
return HttpResponseRedirect(reverse('index'))
elif role == 'super':
# if request.session.get('role_id', 0) < 2:
if request.user.role in ['CU', 'GA']:
return HttpResponseRedirect(reverse('index'))
return func(request, *args, **kwargs) return func(request, *args, **kwargs)
return __deco
return _deco return _deco
def require_super_user(func): def is_role_request(request, role='user'):
def _deco(request, *args, **kwargs): """
if not request.session.get('user_id'): require this request of user is right
return HttpResponseRedirect('/login/') 要求请求角色正确
"""
if request.session.get('role_id', 0) != 2: role_all = {'user': 'CU', 'admin': 'GA', 'super': 'SU'}
return HttpResponseRedirect('/') if request.user.role == role_all.get(role, 'CU'):
return func(request, *args, **kwargs)
return _deco
def require_admin(func):
def _deco(request, *args, **kwargs):
if not request.session.get('user_id'):
return HttpResponseRedirect('/login/')
if request.session.get('role_id', 0) < 1:
return HttpResponseRedirect('/')
return func(request, *args, **kwargs)
return _deco
def is_super_user(request):
if request.session.get('role_id') == 2:
return True return True
else: else:
return False return False
def is_group_admin(request):
if request.session.get('role_id') == 1:
return True
else:
return False
def is_common_user(request):
if request.session.get('role_id') == 0:
return True
else:
return False
@require_login
def get_session_user_dept(request): def get_session_user_dept(request):
user_id = request.session.get('user_id', 0) """
user = User.objects.filter(id=user_id) get department of the user in session
if user: 获取session中用户的部门
user = user[0] """
dept = user.dept # user_id = request.session.get('user_id', 0)
return user, dept # print '#' * 20
# print user_id
# user = User.objects.filter(id=user_id)
# if user:
# user = user[0]
# return user, None
return request.user, None
@require_login @require_role
def get_session_user_info(request): def get_session_user_info(request):
user_id = request.session.get('user_id', 0) """
user = User.objects.filter(id=user_id) get the user info of the user in session, for example id, username etc.
if user: 获取用户的信息
user = user[0] """
dept = user.dept # user_id = request.session.get('user_id', 0)
return [user.id, user.username, user, dept.id, dept.name, dept] # user = get_object(User, id=user_id)
# if user:
# return [user.id, user.username, user]
return [request.user.id, request.user.username, request.user]
def get_user_dept(request): def get_user_dept(request):
user_id = request.session.get('user_id') """
get the user dept id
获取用户的部门id
"""
user_id = request.user.id
if user_id: if user_id:
user_dept = User.objects.get(id=user_id).dept user_dept = User.objects.get(id=user_id).dept
return user_dept.id return user_dept.id
@ -273,124 +429,23 @@ def api_user(request):
def view_splitter(request, su=None, adm=None): def view_splitter(request, su=None, adm=None):
if is_super_user(request): """
for different user use different view
视图分页器
"""
if is_role_request(request, 'super'):
return su(request) return su(request)
elif is_group_admin(request): elif is_role_request(request, 'admin'):
return adm(request) return adm(request)
else: else:
return HttpResponseRedirect('/login/') return HttpResponseRedirect(reverse('login'))
def user_group_perm_asset_group_api(user_group):
asset_group_list = []
perm_list = user_group.perm_set.all()
for perm in perm_list:
asset_group_list.append(perm.asset_group)
return asset_group_list
def user_perm_group_api(username):
if username:
user = User.objects.get(username=username)
perm_list = []
user_group_all = user.group.all()
for user_group in user_group_all:
perm_list.extend(user_group.perm_set.all())
asset_group_list = []
for perm in perm_list:
asset_group_list.append(perm.asset_group)
return asset_group_list
def user_perm_group_hosts_api(gid):
hostgroup = BisGroup.objects.filter(id=gid)
if hostgroup:
return hostgroup[0].asset_set.all()
else:
return []
def user_perm_asset_api(username):
user = User.objects.filter(username=username)
if user:
user = user[0]
asset_list = []
asset_group_list = user_perm_group_api(user)
for asset_group in asset_group_list:
asset_list.extend(asset_group.asset_set.all())
asset_list = list(set(asset_list))
return asset_list
else:
return []
def asset_perm_api(asset):
if asset:
perm_list = []
asset_group_all = asset.bis_group.all()
for asset_group in asset_group_all:
perm_list.extend(asset_group.perm_set.all())
user_group_list = []
for perm in perm_list:
user_group_list.append(perm.user_group)
user_permed_list = []
for user_group in user_group_list:
user_permed_list.extend(user_group.user_set.all())
user_permed_list = list(set(user_permed_list))
return user_permed_list
def get_user_host(username):
"""Get the hosts of under the user control."""
hosts_attr = {}
asset_all = user_perm_asset_api(username)
user = User.objects.filter(username=username)
if user:
user = user[0]
for asset in asset_all:
alias = AssetAlias.objects.filter(user=user, host=asset)
if alias and alias[0].alias != '':
hosts_attr[asset.ip] = [asset.id, asset.ip, alias[0].alias]
else:
hosts_attr[asset.ip] = [asset.id, asset.ip, asset.comment]
return hosts_attr
else:
raise ServerError('User %s does not exit!' % username)
def get_connect_item(username, ip):
asset = get_object(Asset, ip=ip)
port = int(asset.port)
if not asset.is_active:
raise ServerError('Host %s is not active.' % ip)
user = get_object(User, username=username)
if not user.is_active:
raise ServerError('User %s is not active.' % username)
login_type_dict = {
'L': user.ldap_pwd,
}
if asset.login_type in login_type_dict:
password = CRYPTOR.decrypt(login_type_dict[asset.login_type])
return username, password, ip, port
elif asset.login_type == 'M':
username = asset.username
password = CRYPTOR.decrypt(asset.password)
return username, password, ip, port
else:
raise ServerError('Login type is not in ["L", "M"]')
def validate(request, user_group=None, user=None, asset_group=None, asset=None, edept=None): def validate(request, user_group=None, user=None, asset_group=None, asset=None, edept=None):
"""
validate the user request
判定用户请求是否合法
"""
dept = get_session_user_dept(request)[1] dept = get_session_user_dept(request)[1]
if edept: if edept:
if dept.id != int(edept[0]): if dept.id != int(edept[0]):
@ -480,39 +535,60 @@ def verify(request, user_group=None, user=None, asset_group=None, asset=None, ed
def bash(cmd): def bash(cmd):
"""执行bash命令""" """
run a bash shell command
执行bash命令
"""
return subprocess.call(cmd, shell=True) return subprocess.call(cmd, shell=True)
def is_dir(dir_name, username='root', mode=0755): def mkdir(dir_name, username='', mode=0755):
"""
insure the dir exist and mode ok
目录存在如果不存在就建立并且权限正确
"""
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:
chown(dir_name, username)
def success(request, msg): def http_success(request, msg):
return render_to_response('success.html', locals()) return render_to_response('success.html', locals())
def httperror(request, emg): def http_error(request, emg):
message = emg message = emg
return render_to_response('error.html', locals()) return render_to_response('error.html', locals())
def node_auth(request): def my_render(template, data, request):
username = request.POST.get('username', ' ') return render_to_response(template, data, context_instance=RequestContext(request))
seed = request.POST.get('seed', ' ')
filename = request.POST.get('filename', ' ')
user = User.objects.filter(username=username, password=seed)
auth = 1
if not user:
auth = 0
if not filename.startswith('/opt/jumpserver/logs/connect/'):
auth = 0
if auth:
result = {'auth': {'username': username, 'result': 'success'}}
else:
result = {'auth': {'username': username, 'result': 'failed'}}
return HttpResponse(json.dumps(result, sort_keys=True, indent=2), content_type='application/json')
def get_tmp_dir():
dir_name = os.path.join('/tmp', uuid.uuid4().hex)
mkdir(dir_name, mode=0777)
return dir_name
def defend_attack(func):
def _deco(request, *args, **kwargs):
if int(request.session.get('visit', 1)) > 10:
logger.debug('请求次数: %s' % request.session.get('visit', 1))
return HttpResponse('Forbidden', status=403)
request.session['visit'] = request.session.get('visit', 1) + 1
request.session.set_expiry(300)
return func(request, *args, **kwargs)
return _deco
def get_mac_address():
node = uuid.getnode()
mac = uuid.UUID(int=node).hex[-12:]
return mac
CRYPTOR = PyCrypt(KEY)
logger = set_log(LOG_LEVEL)

View File

@ -1,26 +1,16 @@
from juser.models import User from juser.models import User
from jasset.models import Asset from jasset.models import Asset
from jumpserver.api import * from jumpserver.api import *
from jperm.models import Apply
def name_proc(request): def name_proc(request):
user_id = request.session.get('user_id') user_id = request.user.id
role_id = request.session.get('role_id') role_id = {'SU': 2, 'GA': 1, 'CU': 0}.get(request.user.role, 0)
if role_id == 2: # role_id = 'SU'
user_total_num = User.objects.all().count() user_total_num = User.objects.all().count()
user_active_num = User.objects.filter().count() user_active_num = User.objects.filter().count()
host_total_num = Asset.objects.all().count() host_total_num = Asset.objects.all().count()
host_active_num = Asset.objects.filter(is_active=True).count() host_active_num = Asset.objects.filter(is_active=True).count()
else:
user, dept = get_session_user_dept(request)
user_total_num = dept.user_set.all().count()
user_active_num = dept.user_set.filter(is_active=True).count()
host_total_num = dept.asset_set.all().count()
host_active_num = dept.asset_set.all().filter(is_active=True).count()
username = User.objects.get(id=user_id).name
apply_info = Apply.objects.filter(admin=username, status=0, read=0)
request.session.set_expiry(3600) request.session.set_expiry(3600)
info_dic = {'session_user_id': user_id, info_dic = {'session_user_id': user_id,
@ -29,7 +19,7 @@ def name_proc(request):
'user_active_num': user_active_num, 'user_active_num': user_active_num,
'host_total_num': host_total_num, 'host_total_num': host_total_num,
'host_active_num': host_active_num, 'host_active_num': host_active_num,
'apply_info': apply_info} }
return info_dic return info_dic

View File

@ -11,24 +11,37 @@ https://docs.djangoproject.com/en/1.7/ref/settings/
# Build paths inside the project like this: os.path.join(BASE_DIR, ...) # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
import os import os
import ConfigParser import ConfigParser
import getpass
config = ConfigParser.ConfigParser() config = ConfigParser.ConfigParser()
BASE_DIR = 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')
DB_HOST = config.get('db', 'host') DB_HOST = config.get('db', 'host')
DB_PORT = config.getint('db', 'port') DB_PORT = config.getint('db', 'port')
DB_USER = config.get('db', 'user') DB_USER = config.get('db', 'user')
DB_PASSWORD = config.get('db', 'password') DB_PASSWORD = config.get('db', 'password')
DB_DATABASE = config.get('db', 'database') DB_DATABASE = config.get('db', 'database')
AUTH_USER_MODEL = 'juser.User'
# mail config # mail config
MAIL_ENABLE = config.get('mail', 'mail_enable')
EMAIL_HOST = config.get('mail', 'email_host') EMAIL_HOST = config.get('mail', 'email_host')
EMAIL_PORT = config.get('mail', 'email_port') EMAIL_PORT = config.get('mail', 'email_port')
EMAIL_HOST_USER = config.get('mail', 'email_host_user') EMAIL_HOST_USER = config.get('mail', 'email_host_user')
EMAIL_HOST_PASSWORD = config.get('mail', 'email_host_password') EMAIL_HOST_PASSWORD = config.get('mail', 'email_host_password')
EMAIL_USE_TLS = config.getboolean('mail', 'email_use_tls') EMAIL_USE_TLS = config.getboolean('mail', 'email_use_tls')
EMAIL_TIMEOUT = 5
# ======== Log ==========
LOG_DIR = os.path.join(BASE_DIR, 'logs')
SSH_KEY_DIR = os.path.join(BASE_DIR, 'keys/role_keys')
KEY = config.get('base', 'key')
URL = config.get('base', 'url')
LOG_LEVEL = config.get('base', 'log')
WEB_SOCKET_HOST = config.get('websocket', 'web_socket_host')
# Quick-start development settings - unsuitable for production # Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.7/howto/deployment/checklist/ # See https://docs.djangoproject.com/en/1.7/howto/deployment/checklist/
@ -43,7 +56,6 @@ TEMPLATE_DEBUG = True
ALLOWED_HOSTS = ['0.0.0.0/8'] ALLOWED_HOSTS = ['0.0.0.0/8']
# Application definition # Application definition
INSTALLED_APPS = ( INSTALLED_APPS = (
@ -54,6 +66,8 @@ INSTALLED_APPS = (
'django.contrib.messages', 'django.contrib.messages',
'django.contrib.staticfiles', 'django.contrib.staticfiles',
'django.contrib.humanize', 'django.contrib.humanize',
'django_crontab',
'bootstrapform',
'jumpserver', 'jumpserver',
'juser', 'juser',
'jasset', 'jasset',
@ -64,9 +78,9 @@ INSTALLED_APPS = (
MIDDLEWARE_CLASSES = ( MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware', 'django.middleware.common.CommonMiddleware',
#'django.middleware.csrf.CsrfViewMiddleware', # 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware',
#'django.contrib.auth.middleware.SessionAuthenticationMiddleware', # 'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware', 'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware',
) )
@ -90,6 +104,12 @@ DATABASES = {
} }
} }
# DATABASES = {
# 'default': {
# 'ENGINE': 'django.db.backends.sqlite3',
# 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
# }
# }
TEMPLATE_CONTEXT_PROCESSORS = ( TEMPLATE_CONTEXT_PROCESSORS = (
'django.contrib.auth.context_processors.auth', 'django.contrib.auth.context_processors.auth',
'django.core.context_processors.debug', 'django.core.context_processors.debug',
@ -98,14 +118,14 @@ TEMPLATE_CONTEXT_PROCESSORS = (
'django.core.context_processors.static', 'django.core.context_processors.static',
'django.core.context_processors.tz', 'django.core.context_processors.tz',
'django.contrib.messages.context_processors.messages', 'django.contrib.messages.context_processors.messages',
'jumpserver.context_processors.name_proc' 'jumpserver.context_processors.name_proc',
) )
TEMPLATE_DIRS = ( TEMPLATE_DIRS = (
os.path.join(BASE_DIR, 'templates'), os.path.join(BASE_DIR, 'templates'),
) )
#STATIC_ROOT = os.path.join(BASE_DIR, 'static') # STATIC_ROOT = os.path.join(BASE_DIR, 'static')
STATICFILES_DIRS = ( STATICFILES_DIRS = (
os.path.join(BASE_DIR, "static"), os.path.join(BASE_DIR, "static"),
@ -129,4 +149,8 @@ USE_TZ = False
STATIC_URL = '/static/' STATIC_URL = '/static/'
BOOTSTRAP_COLUMN_COUNT = 10
CRONJOBS = [
('0 1 * * *', 'jasset.asset_api.asset_ansible_update_all')
]

View File

@ -5,97 +5,67 @@ import ast
import time import time
from django import template from django import template
from jperm.models import CmdGroup from jperm.models import PermPush
from jumpserver.api import * from jumpserver.api import *
from jasset.models import AssetAlias from jperm.perm_api import get_group_user_perm
register = template.Library() register = template.Library()
@register.filter(name='stamp2str')
def stamp2str(value):
try:
return time.strftime('%Y/%m/%d %H:%M:%S', time.localtime(value))
except AttributeError:
return '0000/00/00 00:00:00'
@register.filter(name='int2str') @register.filter(name='int2str')
def int2str(value): def int2str(value):
"""
int 转换为 str
"""
return str(value) return str(value)
@register.filter(name='get_role') @register.filter(name='get_role')
def get_role(user_id): def get_role(user_id):
user_role = {'SU': u'超级管理员', 'DA': u'部门管理员', 'CU': u'普通用户'} """
user = User.objects.filter(id=user_id) 根据用户id获取用户权限
"""
user_role = {'SU': u'超级管理员', 'GA': u'组管理员', 'CU': u'普通用户'}
user = get_object(User, id=user_id)
if user: if user:
user = user[0]
return user_role.get(str(user.role), u"普通用户") return user_role.get(str(user.role), u"普通用户")
else: else:
return u"普通用户" return u"普通用户"
@register.filter(name='groups_str') @register.filter(name='groups2str')
def groups_str(user_id): def groups2str(group_list):
groups = [] """
user = User.objects.get(id=user_id) 将用户组列表转换为str
for group in user.group.all(): """
groups.append(group.name)
if len(groups) < 3:
return ' '.join(groups)
else:
return "%s ..." % ' '.join(groups[0:2])
@register.filter(name='group_str2')
def groups_str2(group_list):
if len(group_list) < 3: if len(group_list) < 3:
return ' '.join([group.name for group in group_list]) return ' '.join([group.name for group in group_list])
else: else:
return '%s ...' % ' '.join([group.name for group in group_list[0:2]]) return '%s ...' % ' '.join([group.name for group in group_list[0:2]])
@register.filter(name='group_str2_all') @register.filter(name='user_asset_count')
def group_str2_all(group_list): def user_asset_count(user):
group_lis = [] """
for i in group_list: 返回用户权限主机的数量
if str(i) != 'ALL': """
group_lis.append(i) assets = user.asset.all()
if len(group_lis) < 3: asset_groups = user.asset_group.all()
return ' '.join([group.name for group in group_lis])
else: for asset_group in asset_groups:
return '%s ...' % ' '.join([group.name for group in group_lis[0:2]]) if asset_group:
assets.extend(asset_group.asset_set.all())
return len(assets)
@register.filter(name='group_dept_all') @register.filter(name='user_asset_group_count')
def group_dept_all(group_list): def user_asset_group_count(user):
group_lis = [] """
for i in group_list: 返回用户权限主机组的数量
if str(i) != 'ALL': """
group_lis.append(i) return len(user.asset_group.all())
return ' '.join([group.name for group in group_lis])
@register.filter(name='group_manage_str')
def group_manage_str(username):
user = User.objects.get(username=username)
group = user.user_group.filter(type='M')
if group:
return group[0].name
else:
return ''
@register.filter(name='get_item')
def get_item(dictionary, key):
return dictionary.get(key)
@register.filter(name='get_login_type')
def get_login_type(login):
login_types = {'L': 'LDAP', 'M': 'MAP'}
return login_types[login]
@register.filter(name='bool2str') @register.filter(name='bool2str')
@ -106,166 +76,19 @@ def bool2str(value):
return u'' return u''
# @register.filter(name='user_readonly') @register.filter(name='members_count')
# def user_readonly(user_id): def members_count(group_id):
# user = User.objects.filter(id=user_id) """统计用户组下成员数量"""
# if user: group = get_object(UserGroup, id=group_id)
# user = user[0] if group:
# if user.role == 'CU':
# return False
# return True
#
@register.filter(name='member_count')
def member_count(group_id):
group = UserGroup.objects.get(id=group_id)
return group.user_set.count() return group.user_set.count()
@register.filter(name='group_user_count')
def group_user_count(group_id):
group = UserGroup.objects.get(id=group_id)
return group.user_set.count()
@register.filter(name='dept_user_num')
def dept_user_num(dept_id):
dept = DEPT.objects.filter(id=dept_id)
if dept:
dept = dept[0]
return dept.user_set.count()
else: else:
return 0 return 0
@register.filter(name='dept_group_num')
def dept_group_num(dept_id):
dept = DEPT.objects.filter(id=dept_id)
if dept:
dept = dept[0]
return dept.usergroup_set.all().count()
else:
return 0
@register.filter(name='perm_count')
def perm_count(group_id):
group = UserGroup.objects.get(id=group_id)
return group.perm_set.count()
@register.filter(name='dept_asset_num')
def dept_asset_num(dept_id):
dept = DEPT.objects.filter(id=dept_id)
if dept:
dept = dept[0]
return dept.asset_set.all().count()
return 0
@register.filter(name='ugrp_perm_agrp_count')
def ugrp_perm_agrp_count(user_group_id):
user_group = UserGroup.objects.filter(id=user_group_id)
if user_group:
user_group = user_group[0]
return user_group.perm_set.all().count()
return 0
@register.filter(name='ugrp_sudo_agrp_count')
def ugrp_sudo_agrp_count(user_group_id):
user_group = UserGroup.objects.filter(id=user_group_id)
asset_groups = []
if user_group:
user_group = user_group[0]
for perm in user_group.sudoperm_set.all():
asset_groups.extend(perm.asset_group.all())
return len(set(asset_groups))
return 0
@register.filter(name='ugrp_perm_asset_count')
def ugrp_perm_asset_count(user_group_id):
user_group = UserGroup.objects.filter(id=user_group_id)
assets = []
if user_group:
user_group = user_group[0]
asset_groups = [perm.asset_group for perm in user_group.perm_set.all()]
for asset_group in asset_groups:
assets.extend(asset_group.asset_set.all())
return len(set(assets))
@register.filter(name='ugrp_sudo_asset_count')
def ugrp_sudo_asset_count(user_group_id):
user_group = UserGroup.objects.filter(id=user_group_id)
asset_groups = []
assets = []
if user_group:
user_group = user_group[0]
for perm in user_group.sudoperm_set.all():
asset_groups.extend(perm.asset_group.all())
for asset_group in asset_groups:
assets.extend(asset_group.asset_set.all())
return len(set(assets))
@register.filter(name='get_user_alias')
def get_user_alias(post, user_id):
user = User.objects.get(id=user_id)
host = Asset.objects.get(id=post.id)
alias = AssetAlias.objects.filter(user=user, host=host)
if alias:
return alias[0].alias
else:
return ''
@register.filter(name='group_type_to_str')
def group_type_to_str(type_name):
group_types = {
'P': '用户',
'M': '部门',
'A': '用户组',
}
return group_types.get(type_name)
@register.filter(name='ast_to_list')
def ast_to_list(lis):
ast_lis = ast.literal_eval(lis)
if len(ast_lis) <= 2:
return ','.join([i for i in ast_lis])
else:
restr = ','.join([i for i in ast_lis[0:2]]) + '...'
return restr
@register.filter(name='get_group_count')
def get_group_count(post, dept):
count = post.asset_set.filter(dept=dept).count()
return count
@register.filter(name='get_idc_count')
def get_idc_count(post, dept):
count = post.asset_set.filter(dept=dept).count()
return count
@register.filter(name='ast_to_list_1')
def ast_to_list_1(lis):
return ast.literal_eval(lis)
@register.filter(name='string_length')
def string_length(string, length):
return '%s ...' % string[0:length]
@register.filter(name='to_name') @register.filter(name='to_name')
def to_name(user_id): def to_name(user_id):
"""user id 转位用户名称"""
try: try:
user = User.objects.filter(id=int(user_id)) user = User.objects.filter(id=int(user_id))
if user: if user:
@ -275,89 +98,182 @@ def to_name(user_id):
return '非法用户' return '非法用户'
@register.filter(name='to_dept_name')
def to_dept_name(user_id):
try:
user = User.objects.filter(id=int(user_id))
if user:
user = user[0]
return user.dept.name
except:
return '非法部门'
@register.filter(name='to_role_name') @register.filter(name='to_role_name')
def to_role_name(role_id): def to_role_name(role_id):
role_dict = {'0': '普通用户', '1': '部门管理员', '2': '超级管理员'} """role_id 转变为角色名称"""
role_dict = {'0': '普通用户', '1': '组管理员', '2': '超级管理员'}
return role_dict.get(str(role_id), '未知') return role_dict.get(str(role_id), '未知')
@register.filter(name='to_avatar') @register.filter(name='to_avatar')
def to_avatar(role_id='0'): def to_avatar(role_id='0'):
"""不同角色不同头像"""
role_dict = {'0': 'user', '1': 'admin', '2': 'root'} role_dict = {'0': 'user', '1': 'admin', '2': 'root'}
return role_dict.get(str(role_id), 'user') return role_dict.get(str(role_id), 'user')
@register.filter(name='get_user_asset_group') @register.filter(name='result2bool')
def get_user_asset_group(user): def result2bool(result=''):
return user_perm_group_api(user) """将结果定向为结果"""
result = eval(result)
unreachable = result.get('unreachable', [])
failures = result.get('failures', [])
if unreachable or failures:
@register.filter(name='group_asset_list') return '<b style="color: red">失败</b>'
def group_asset_list(group):
return group.asset_set.all()
@register.filter(name='group_asset_list_count')
def group_asset_list_count(group):
return group.asset_set.all().count()
@register.filter(name='time_delta')
def time_delta(time_before):
delta = datetime.datetime.now() - time_before
days = delta.days
if days:
return "%s 天前" % days
else: else:
hours = delta.seconds/3600 return '<b style="color: green">成功</b>'
if hours:
return "%s 小时前" % hours
@register.filter(name='rule_member_count')
def rule_member_count(instance, member):
"""
instance is a rule object,
use to get the number of the members
:param instance:
:param member:
:return:
"""
member = getattr(instance, member)
counts = member.all().count()
return str(counts)
@register.filter(name='rule_member_name')
def rule_member_name(instance, member):
"""
instance is a rule object,
use to get the name of the members
:param instance:
:param member:
:return:
"""
member = getattr(instance, member)
names = member.all()
return names
@register.filter(name='user_which_groups')
def user_which_group(user, member):
"""
instance is a user object,
use to get the group of the user
:param instance:
:param member:
:return:
"""
member = getattr(user, member)
names = [members.name for members in member.all()]
return ','.join(names)
@register.filter(name='asset_which_groups')
def asset_which_group(asset, member):
"""
instance is a user object,
use to get the group of the user
:param instance:
:param member:
:return:
"""
member = getattr(asset, member)
names = [members.name for members in member.all()]
return ','.join(names)
@register.filter(name='group_str2')
def groups_str2(group_list):
"""
将用户组列表转换为str
"""
if len(group_list) < 3:
return ' '.join([group.name for group in group_list])
else: else:
mins = delta.seconds/60 return '%s ...' % ' '.join([group.name for group in group_list[0:2]])
if mins:
return '%s 分钟前' % mins
@register.filter(name='str_to_list')
def str_to_list(info):
"""
str to list
"""
print ast.literal_eval(info), type(ast.literal_eval(info))
return ast.literal_eval(info)
@register.filter(name='str_to_dic')
def str_to_dic(info):
"""
str to list
"""
if '{' in info:
info_dic = ast.literal_eval(info).iteritems()
else: else:
return '%s 秒前' % delta.seconds info_dic = {}
return info_dic
@register.filter(name='sudo_cmd_list') @register.filter(name='str_to_code')
def sudo_cmd_list(cmd_group_id): def str_to_code(char_str):
cmd_group = CmdGroup.objects.filter(id=cmd_group_id) if char_str:
if cmd_group: return char_str
cmd_group = cmd_group[0]
return cmd_group.cmd.split(',')
@register.filter(name='sudo_cmd_count')
def sudo_cmd_count(user_group_id):
user_group = UserGroup.objects.filter(id=user_group_id)
cmds = []
if user_group:
user_group = user_group[0]
cmd_groups = []
for perm in user_group.sudoperm_set.all():
cmd_groups.extend(perm.cmd_group.all())
for cmd_group in cmd_groups:
cmds.extend(cmd_group.cmd.split(','))
return len(set(cmds))
else: else:
return 0 return u''
@register.filter(name='ip_str_to_list')
def ip_str_to_list(ip_str):
"""
ip str to list
"""
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+'.pem')):
return True
else:
return False
@register.filter(name='check_role')
def check_role(asset_id, user):
"""
ssh key is exist or not
"""
return user
@register.filter(name='role_contain_which_sudos')
def role_contain_which_sudos(role):
"""
get role sudo commands
"""
sudo_names = [sudo.name for sudo in role.sudo.all()]
return ','.join(sudo_names)
@register.filter(name='get_push_info')
def get_push_info(push_id, arg):
push = get_object(PermPush, id=push_id)
if push and arg:
if arg == 'asset':
return [asset.hostname for asset in push.asset.all()]
if arg == 'asset_group':
return [asset_group.name for asset_group in push.asset_group.all()]
if arg == 'role':
return [role.name for role in push.role.all()]
else:
return []
<<<<<<< HEAD
@register.filter(name='sudo_cmd_count') @register.filter(name='sudo_cmd_count')
def sudo_cmd_count(cmd_group_id): def sudo_cmd_count(cmd_group_id):
cmd_group = CmdGroup.objects.filter(id=cmd_group_id) cmd_group = CmdGroup.objects.filter(id=cmd_group_id)
@ -367,22 +283,36 @@ def sudo_cmd_count(cmd_group_id):
return len(set(cmd_group.cmd.split(','))) return len(set(cmd_group.cmd.split(',')))
else: else:
return 0 return 0
=======
@register.filter(name='get_cpu_core')
def get_cpu_core(cpu_info):
cpu_core = cpu_info.split('* ')[1] if cpu_info and '*' in cpu_info else cpu_info
return cpu_core
>>>>>>> dev
@register.filter(name='sudo_cmd_ids') @register.filter(name='get_disk_info')
def sudo_cmd_ids(user_group_id): def get_disk_info(disk_info):
user_group = UserGroup.objects.filter(id=user_group_id) try:
if user_group: disk_size = 0
user_group = user_group[0] if disk_info:
cmd_groups = [] disk_dic = ast.literal_eval(disk_info)
for perm in user_group.sudoperm_set.all(): for disk, size in disk_dic.items():
cmd_groups.extend(perm.cmd_group.all()) disk_size += size
cmd_ids = [str(cmd_group.id) for cmd_group in cmd_groups] disk_size = int(disk_size)
return ','.join(cmd_ids)
else: else:
return '0' disk_size = ''
except Exception:
disk_size = ''
return disk_size
@register.filter(name='cmd_group_split') @register.filter(name='user_perm_asset_num')
def cmd_group_split(cmd_group): def user_perm_asset_num(user_id):
return cmd_group.cmd.split(',') user = get_object(User, id=user_id)
if user:
user_perm_info = get_group_user_perm(user)
return len(user_perm_info.get('asset').keys())
else:
return 0

View File

@ -1,22 +1,20 @@
from django.conf.urls import patterns, include, url from django.conf.urls import patterns, include, url
urlpatterns = patterns('', urlpatterns = patterns('jumpserver.views',
# Examples: # Examples:
(r'^$', 'jumpserver.views.index'), url(r'^$', 'index', name='index'),
(r'^api/user/$', 'jumpserver.api.api_user'), # url(r'^api/user/$', 'api_user'),
(r'^skin_config/$', 'jumpserver.views.skin_config'), url(r'^skin_config/$', 'skin_config', name='skin_config'),
(r'^install/$', 'jumpserver.views.install'), url(r'^login/$', 'Login', name='login'),
(r'^base/$', 'jumpserver.views.base'), url(r'^logout/$', 'Logout', name='logout'),
(r'^login/$', 'jumpserver.views.login'), url(r'^exec_cmd/$', 'exec_cmd', name='exec_cmd'),
(r'^logout/$', 'jumpserver.views.logout'), url(r'^file/upload/$', 'upload', name='file_upload'),
(r'^file/upload/$', 'jumpserver.views.upload'), url(r'^file/download/$', 'download', name='file_download'),
(r'^file/download/$', 'jumpserver.views.download'), url(r'^setting', 'setting', name='setting'),
(r'^error/$', 'jumpserver.views.httperror'), url(r'^terminal/$', 'web_terminal', name='terminal'),
(r'^juser/', include('juser.urls')), url(r'^juser/', include('juser.urls')),
(r'^jasset/', include('jasset.urls')), url(r'^jasset/', include('jasset.urls')),
(r'^jlog/', include('jlog.urls')), url(r'^jlog/', include('jlog.urls')),
(r'^jperm/', include('jperm.urls')), url(r'^jperm/', include('jperm.urls')),
(r'^node_auth/', 'jumpserver.views.node_auth'),
) )

View File

@ -1,83 +1,98 @@
# coding: utf-8 # coding: utf-8
from __future__ import division from __future__ import division
import uuid
import urllib
from django.db.models import Count from django.db.models import Count
from django.shortcuts import render_to_response from django.shortcuts import render_to_response
from django.template import RequestContext from django.template import RequestContext
from django.http import HttpResponseNotFound from django.http import HttpResponseNotFound
from jperm.models import Apply from django.http import HttpResponse
# from jperm.models import Apply
import paramiko import paramiko
from jumpserver.api import * from jumpserver.api import *
import uuid from jumpserver.models import Setting
import urllib from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required
from jlog.models import Log, FileLog
from jperm.perm_api import get_group_user_perm, gen_resource
from jasset.models import Asset, IDC
from jperm.ansible_api import MyRunner
def getDaysByNum(num): def getDaysByNum(num):
"""
输出格式:([datetime.date(2015, 11, 6), datetime.date(2015, 11, 8)], ['11-06', '11-08'])
"""
today = datetime.date.today() today = datetime.date.today()
oneday = datetime.timedelta(days=1) oneday = datetime.timedelta(days=1)
li_date, li_str = [], [] date_li, date_str = [], []
for i in range(0, num): for i in range(0, num):
today = today-oneday today = today-oneday
li_date.append(today) date_li.append(today)
li_str.append(str(today)[5:10]) date_str.append(str(today)[5:10])
li_date.reverse() date_li.reverse()
li_str.reverse() date_str.reverse()
t = (li_date, li_str) return date_li, date_str
return t
def get_data(data, items, option): def get_data(x, y, z):
dic = {} pass
li_date, li_str = getDaysByNum(7)
for item in items:
li = []
name = item[option]
if option == 'user':
option_data = data.filter(user=name)
elif option == 'host':
option_data = data.filter(host=name)
for t in li_date:
year, month, day = t.year, t.month, t.day
times = option_data.filter(start_time__year=year, start_time__month=month, start_time__day=day).count()
li.append(times)
dic[name] = li
return dic
@require_login def get_data_by_day(date_li, item):
def index_cu(request): data_li = []
user_id = request.session.get('user_id') for d in date_li:
user = User.objects.filter(id=user_id) logs = Log.objects.filter(start_time__year=d.year,
if user: start_time__month=d.month,
user = user[0] start_time__day=d.day)
login_types = {'L': 'LDAP', 'M': 'MAP'} if item == 'user':
user_id = request.session.get('user_id') data_li.append(set([log.user for log in logs]))
username = User.objects.get(id=user_id).username elif item == 'asset':
posts = user_perm_asset_api(username) data_li.append(set([log.host for log in logs]))
host_count = len(posts) elif item == 'login':
new_posts = [] data_li.append(logs)
post_five = []
for post in posts:
if len(post_five) < 5:
post_five.append(post)
else: else:
new_posts.append(post_five) pass
post_five = [] return data_li
new_posts.append(post_five)
return render_to_response('index_cu.html', locals(), context_instance=RequestContext(request))
@require_login def get_count_by_day(date_li, item):
data_li = get_data_by_day(date_li, item)
data_count_li = []
for data in data_li:
data_count_li.append(len(data))
return data_count_li
def get_count_by_date(date_li, item):
data_li = get_data_by_day(date_li, item)
data_count_tmp = []
for data in data_li:
data_count_tmp.extend(list(data))
return len(set(data_count_tmp))
@require_role(role='user')
def index_cu(request):
username = request.user.username
return HttpResponseRedirect(reverse('user_detail'))
@require_role(role='user')
def index(request): def index(request):
li_date, li_str = getDaysByNum(7) li_date, li_str = getDaysByNum(7)
today = datetime.datetime.now().day today = datetime.datetime.now().day
from_week = datetime.datetime.now() - datetime.timedelta(days=7) from_week = datetime.datetime.now() - datetime.timedelta(days=7)
if is_common_user(request): if is_role_request(request, 'user'):
return index_cu(request) return index_cu(request)
elif is_super_user(request): elif is_role_request(request, 'super'):
# dashboard 显示汇总
users = User.objects.all() users = User.objects.all()
hosts = Asset.objects.all() hosts = Asset.objects.all()
online = Log.objects.filter(is_finished=0) online = Log.objects.filter(is_finished=0)
@ -85,68 +100,52 @@ def index(request):
online_user = online.values('user').distinct() online_user = online.values('user').distinct()
active_users = User.objects.filter(is_active=1) active_users = User.objects.filter(is_active=1)
active_hosts = Asset.objects.filter(is_active=1) active_hosts = Asset.objects.filter(is_active=1)
# 一个月历史汇总
date_li, date_str = getDaysByNum(30)
date_month = repr(date_str)
active_user_per_month = str(get_count_by_day(date_li, 'user'))
active_asset_per_month = str(get_count_by_day(date_li, 'asset'))
active_login_per_month = str(get_count_by_day(date_li, 'login'))
# 活跃用户资产图
active_user_month = get_count_by_date(date_li, 'user')
disabled_user_count = len(users.filter(is_active=False))
inactive_user_month = len(users) - active_user_month
active_asset_month = get_count_by_date(date_li, 'asset')
disabled_asset_count = len(hosts.filter(is_active=False)) if hosts.filter(is_active=False) else 0
inactive_asset_month = len(hosts) - active_asset_month if len(hosts) > active_asset_month else 0
# 一周top10用户和主机
week_data = Log.objects.filter(start_time__range=[from_week, datetime.datetime.now()]) week_data = Log.objects.filter(start_time__range=[from_week, datetime.datetime.now()])
elif is_group_admin(request):
user = get_session_user_info(request)[2]
dept_name, dept = get_session_user_info(request)[4:]
users = User.objects.filter(dept=dept)
hosts = Asset.objects.filter(dept=dept)
online = Log.objects.filter(dept_name=dept_name, is_finished=0)
online_host = online.values('host').distinct()
online_user = online.values('user').distinct()
active_users = users.filter(is_active=1)
active_hosts = hosts.filter(is_active=1)
week_data = Log.objects.filter(dept_name=dept_name, start_time__range=[from_week, datetime.datetime.now()])
# percent of dashboard
if users.count() == 0:
percent_user, percent_online_user = '0%', '0%'
else:
percent_user = format(active_users.count() / users.count(), '.0%')
percent_online_user = format(online_user.count() / users.count(), '.0%')
if hosts.count() == 0:
percent_host, percent_online_host = '0%', '0%'
else:
percent_host = format(active_hosts.count() / hosts.count(), '.0%')
percent_online_host = format(online_host.count() / hosts.count(), '.0%')
user_top_ten = week_data.values('user').annotate(times=Count('user')).order_by('-times')[:10] user_top_ten = week_data.values('user').annotate(times=Count('user')).order_by('-times')[:10]
host_top_ten = week_data.values('host').annotate(times=Count('host')).order_by('-times')[:10] host_top_ten = week_data.values('host').annotate(times=Count('host')).order_by('-times')[:10]
user_dic, host_dic = get_data(week_data, user_top_ten, 'user'), get_data(week_data, host_top_ten, 'host')
# a week data for user_info in user_top_ten:
username = user_info.get('user')
last = Log.objects.filter(user=username).latest('start_time')
user_info['last'] = last
for host_info in host_top_ten:
host = host_info.get('host')
last = Log.objects.filter(host=host).latest('start_time')
host_info['last'] = last
# 一周top5
week_users = week_data.values('user').distinct().count() week_users = week_data.values('user').distinct().count()
week_hosts = week_data.count() week_hosts = week_data.count()
user_top_five = week_data.values('user').annotate(times=Count('user')).order_by('-times')[:5] user_top_five = week_data.values('user').annotate(times=Count('user')).order_by('-times')[:5]
color = ['label-success', 'label-info', 'label-primary', 'label-default', 'label-warnning'] color = ['label-success', 'label-info', 'label-primary', 'label-default', 'label-warnning']
# 最后10次权限申请
# perm apply latest 10 # perm apply latest 10
perm_apply_10 = Apply.objects.order_by('-date_add')[:10] # perm_apply_10 = Apply.objects.order_by('-date_add')[:10]
# latest 10 login # 最后10次登陆
login_10 = Log.objects.order_by('-start_time')[:10] login_10 = Log.objects.order_by('-start_time')[:10]
login_more_10 = Log.objects.order_by('-start_time')[10:21] login_more_10 = Log.objects.order_by('-start_time')[10:21]
# a week top 10
for user_info in user_top_ten:
username = user_info.get('user')
last = Log.objects.filter(user=username).latest('start_time')
user_info['last'] = last
top = {'user': '活跃用户数', 'host': '活跃主机数', 'times': '登录次数'}
top_dic = {}
for key, value in top.items():
li = []
for t in li_date:
year, month, day = t.year, t.month, t.day
if key != 'times':
times = week_data.filter(start_time__year=year, start_time__month=month, start_time__day=day).values(key).distinct().count()
else:
times = week_data.filter(start_time__year=year, start_time__month=month, start_time__day=day).count()
li.append(times)
top_dic[value] = li
return render_to_response('index.html', locals(), context_instance=RequestContext(request)) return render_to_response('index.html', locals(), context_instance=RequestContext(request))
@ -154,34 +153,6 @@ def skin_config(request):
return render_to_response('skin_config.html') return render_to_response('skin_config.html')
def pages(posts, r):
"""分页公用函数"""
contact_list = posts
p = paginator = Paginator(contact_list, 10)
try:
current_page = int(r.GET.get('page', '1'))
except ValueError:
current_page = 1
page_range = page_list_return(len(p.page_range), current_page)
try:
contacts = paginator.page(current_page)
except (EmptyPage, InvalidPage):
contacts = paginator.page(paginator.num_pages)
if current_page >= 5:
show_first = 1
else:
show_first = 0
if current_page <= (len(p.page_range) - 3):
show_end = 1
else:
show_end = 0
return contact_list, p, contacts, page_range, current_page, show_first, show_end
def is_latest(): def is_latest():
node = uuid.getnode() node = uuid.getnode()
jsn = uuid.UUID(int=node).hex[-12:] jsn = uuid.UUID(int=node).hex[-12:]
@ -193,137 +164,195 @@ def is_latest():
pass pass
def login(request): @defend_attack
def Login(request):
"""登录界面""" """登录界面"""
if request.session.get('username'): error = ''
return HttpResponseRedirect('/') if request.user.is_authenticated():
return HttpResponseRedirect(reverse('index'))
if request.method == 'GET': if request.method == 'GET':
return render_to_response('login.html') return render_to_response('login.html')
else: else:
username = request.POST.get('username') username = request.POST.get('username')
password = request.POST.get('password') password = request.POST.get('password')
user_filter = User.objects.filter(username=username) if username and password:
if user_filter: user = authenticate(username=username, password=password)
user = user_filter[0] if user is not None:
if md5_crypt(password) == user.password: if user.is_active:
request.session['user_id'] = user.id login(request, user)
user_filter.update(last_login=datetime.datetime.now()) # c = {}
# c.update(csrf(request))
# request.session['csrf_token'] = str(c.get('csrf_token'))
# user_filter = User.objects.filter(username=username)
# if user_filter:
# user = user_filter[0]
# if PyCrypt.md5_crypt(password) == user.password:
# request.session['user_id'] = user.id
# user_filter.update(last_login=datetime.datetime.now())
if user.role == 'SU': if user.role == 'SU':
request.session['role_id'] = 2 request.session['role_id'] = 2
elif user.role == 'DA': elif user.role == 'GA':
request.session['role_id'] = 1 request.session['role_id'] = 1
else: else:
request.session['role_id'] = 0 request.session['role_id'] = 0
response = HttpResponseRedirect('/', ) 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', md5_crypt(password), expires=604800) # response.set_cookie('seed', PyCrypt.md5_crypt(password), expires=604800)
return response # return response
else: else:
error = '密码错误,请重新输入。' error = '用户未激活'
else: else:
error = '用户不存在。' error = '用户名或密码错误'
else:
error = '用户名或密码错误'
return render_to_response('login.html', {'error': error}) return render_to_response('login.html', {'error': error})
def logout(request): @require_role('user')
request.session.delete() def Logout(request):
return HttpResponseRedirect('/login/') logout(request)
return HttpResponseRedirect(reverse('index'))
def filter_ajax_api(request): @require_role('admin')
attr = request.GET.get('attr', 'user') def setting(request):
value = request.GET.get('value', '') header_title, path1 = '项目设置', '设置'
if attr == 'user': setting_default = get_object(Setting, name='default')
contact_list = User.objects.filter(name__icontains=value)
elif attr == "user_group":
contact_list = UserGroup.objects.filter(name__icontains=value)
elif attr == "asset":
contact_list = Asset.objects.filter(ip__icontains=value)
elif attr == "asset":
contact_list = BisGroup.objects.filter(name__icontains=value)
return render_to_response('filter_ajax_api.html', locals()) if request.method == "POST":
setting_raw = request.POST.get('setting', '')
if setting_raw == 'default':
username = request.POST.get('username', '')
port = request.POST.get('port', '')
password = request.POST.get('password', '')
private_key = request.POST.get('key', '')
if '' in [username, port]:
return HttpResponse('所填内容不能为空, 且密码和私钥填一个')
else:
private_key_dir = os.path.join(BASE_DIR, 'keys', 'default')
private_key_path = os.path.join(private_key_dir, 'admin_user.pem')
mkdir(private_key_dir)
if private_key:
with open(private_key_path, 'w') as f:
f.write(private_key)
os.chmod(private_key_path, 0600)
if setting_default:
if password:
password_encode = CRYPTOR.encrypt(password)
else:
password_encode = password
Setting.objects.filter(name='default').update(field1=username, field2=port,
field3=password_encode,
field4=private_key_path)
else:
password_encode = CRYPTOR.encrypt(password)
setting_r = Setting(name='default', field1=username, field2=port,
field3=password_encode,
field4=private_key_path).save()
msg = "设置成功"
return my_render('setting.html', locals(), request)
def install(request): @login_required(login_url='/login')
from juser.models import DEPT, User def upload(request):
if User.objects.filter(id=5000): user = request.user
return httperror(request, 'Jumpserver已初始化不能重复安装') assets = get_group_user_perm(user).get('asset').keys()
asset_select = []
if request.method == 'POST':
remote_ip = request.META.get('REMOTE_ADDR')
asset_ids = request.POST.getlist('asset_ids', '')
upload_files = request.FILES.getlist('file[]', None)
date_now = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
upload_dir = get_tmp_dir()
# file_dict = {}
for asset_id in asset_ids:
asset_select.append(get_object(Asset, id=asset_id))
dept = DEPT(id=1, name="超管部", comment="超级管理部门") if not set(asset_select).issubset(set(assets)):
dept.save() illegal_asset = set(asset_select).issubset(set(assets))
dept2 = DEPT(id=2, name="默认", comment="默认部门") return HttpResponse('没有权限的服务器 %s' % ','.join([asset.hostname for asset in illegal_asset]))
dept2.save()
IDC(id=1, name="默认", comment="默认IDC").save()
BisGroup(id=1, name="ALL", dept=dept, comment="所有主机组").save()
User(id=5000, username="admin", password=md5_crypt('admin'), for upload_file in upload_files:
name='admin', email='admin@jumpserver.org', role='SU', is_active=True, dept=dept).save() file_path = '%s/%s' % (upload_dir, upload_file.name)
return success(request, u'Jumpserver初始化成功') with open(file_path, 'w') as f:
for chunk in upload_file.chunks():
f.write(chunk)
res = gen_resource({'user': user, 'asset': asset_select})
runner = MyRunner(res)
runner.run('copy', module_args='src=%s dest=%s directory_mode'
% (upload_dir, upload_dir), pattern='*')
ret = runner.results
logger.debug(ret)
FileLog(user=request.user.username, host=' '.join([asset.hostname for asset in asset_select]),
filename=' '.join([f.name for f in upload_files]), type='upload', remote_ip=remote_ip,
result=ret).save()
if ret.get('failed'):
error = u'上传目录: %s <br> 上传失败: [ %s ] <br>上传成功 [ %s ]' % (upload_dir,
', '.join(ret.get('failed').keys()),
', '.join(ret.get('ok').keys()))
return HttpResponse(error, status=500)
msg = u'上传目录: %s <br> 传送成功 [ %s ]' % (upload_dir, ', '.join(ret.get('ok').keys()))
return HttpResponse(msg)
return my_render('upload.html', locals(), request)
@login_required(login_url='/login')
def download(request): def download(request):
user = request.user
assets = get_group_user_perm(user).get('asset').keys()
asset_select = []
if request.method == 'POST':
remote_ip = request.META.get('REMOTE_ADDR')
asset_ids = request.POST.getlist('asset_ids', '')
file_path = request.POST.get('file_path')
date_now = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
upload_dir = get_tmp_dir()
for asset_id in asset_ids:
asset_select.append(get_object(Asset, id=asset_id))
if not set(asset_select).issubset(set(assets)):
illegal_asset = set(asset_select).issubset(set(assets))
return HttpResponse(u'没有权限的服务器 %s' % ','.join([asset.hostname for asset in illegal_asset]))
res = gen_resource({'user': user, 'asset': asset_select})
runner = MyRunner(res)
runner.run('fetch', module_args='src=%s dest=%s' % (file_path, upload_dir), pattern='*')
FileLog(user=request.user.username, host=' '.join([asset.hostname for asset in asset_select]),
filename=file_path, type='download', remote_ip=remote_ip, result=runner.results).save()
logger.debug(runner.results)
os.chdir('/tmp')
tmp_dir_name = os.path.basename(upload_dir)
tar_file = '%s.tar.gz' % upload_dir
bash('tar czf %s %s' % (tar_file, tmp_dir_name))
f = open(tar_file)
data = f.read()
f.close()
response = HttpResponse(data, content_type='application/octet-stream')
response['Content-Disposition'] = 'attachment; filename=%s' % os.path.basename(tar_file)
return response
return render_to_response('download.html', locals(), context_instance=RequestContext(request)) return render_to_response('download.html', locals(), context_instance=RequestContext(request))
def transfer(sftp, filenames): @login_required(login_url='/login')
# pool = Pool(processes=5) def exec_cmd(request):
for filename, file_path in filenames.items(): role = request.GET.get('role')
print filename, file_path check_assets = request.GET.get('check_assets', '')
sftp.put(file_path, '/tmp/%s' % filename) web_terminal_uri = 'ws://%s/exec?role=%s' % (WEB_SOCKET_HOST, role)
# pool.apply_async(transfer, (sftp, file_path, '/tmp/%s' % filename)) return my_render('exec_cmd.html', locals(), request)
sftp.close()
# pool.close()
# pool.join()
def upload(request): @require_role('user')
user, dept = get_session_user_dept(request) def web_terminal(request):
if request.method == 'POST': asset_id = request.GET.get('id')
hosts = request.POST.get('hosts') role_name = request.GET.get('role')
upload_files = request.FILES.getlist('file[]', None) web_terminal_uri = 'ws://%s/terminal?id=%s&role=%s' % (WEB_SOCKET_HOST, asset_id, role_name)
upload_dir = "/tmp/%s" % user.username return render_to_response('jlog/web_terminal.html', locals())
is_dir(upload_dir)
date_now = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
hosts_list = hosts.split(',')
user_hosts = get_user_host(user.username).keys()
unperm_hosts = []
filenames = {}
for ip in hosts_list:
if ip not in user_hosts:
unperm_hosts.append(ip)
if not hosts:
return HttpResponseNotFound(u'地址不能为空')
if unperm_hosts:
print hosts_list
return HttpResponseNotFound(u'%s 没有权限.' % ', '.join(unperm_hosts))
for upload_file in upload_files:
file_path = '%s/%s.%s' % (upload_dir, upload_file.name, date_now)
filenames[upload_file.name] = file_path
f = open(file_path, 'w')
for chunk in upload_file.chunks():
f.write(chunk)
f.close()
sftps = []
for host in hosts_list:
username, password, host, port = get_connect_item(user.username, host)
try:
t = paramiko.Transport((host, port))
t.connect(username=username, password=password)
sftp = paramiko.SFTPClient.from_transport(t)
sftps.append(sftp)
except paramiko.AuthenticationException:
return HttpResponseNotFound(u'%s 连接失败.' % host)
# pool = Pool(processes=5)
for sftp in sftps:
transfer(sftp, filenames)
# pool.close()
# pool.join()
return HttpResponse('传送成功')
return render_to_response('upload.html', locals(), context_instance=RequestContext(request))

View File

@ -1,41 +1,54 @@
# coding: utf-8
from django.db import models from django.db import models
from django.contrib.auth.models import AbstractUser
import time
class DEPT(models.Model): # from jasset.models import Asset, AssetGroup
name = models.CharField(max_length=80, unique=True)
comment = models.CharField(max_length=160, blank=True, null=True)
def __unicode__(self):
return self.name
class UserGroup(models.Model): class UserGroup(models.Model):
name = models.CharField(max_length=80, unique=True) name = models.CharField(max_length=80, unique=True)
dept = models.ForeignKey(DEPT)
comment = models.CharField(max_length=160, blank=True, null=True) comment = models.CharField(max_length=160, blank=True, null=True)
def __unicode__(self): def __unicode__(self):
return self.name return self.name
class User(models.Model): class User(AbstractUser):
USER_ROLE_CHOICES = ( USER_ROLE_CHOICES = (
('SU', 'SuperUser'), ('SU', 'SuperUser'),
('DA', 'DeptAdmin'), ('GA', 'GroupAdmin'),
('CU', 'CommonUser'), ('CU', 'CommonUser'),
) )
username = models.CharField(max_length=80, unique=True)
password = models.CharField(max_length=100)
name = models.CharField(max_length=80) name = models.CharField(max_length=80)
email = models.EmailField(max_length=75) uuid = models.CharField(max_length=100)
role = models.CharField(max_length=2, choices=USER_ROLE_CHOICES, default='CU') role = models.CharField(max_length=2, choices=USER_ROLE_CHOICES, default='CU')
dept = models.ForeignKey(DEPT)
group = models.ManyToManyField(UserGroup) group = models.ManyToManyField(UserGroup)
ldap_pwd = models.CharField(max_length=100) ssh_key_pwd = models.CharField(max_length=200)
ssh_key_pwd = models.CharField(max_length=100) # is_active = models.BooleanField(default=True)
is_active = models.BooleanField(default=True) # last_login = models.DateTimeField(null=True)
last_login = models.DateTimeField(null=True) # date_joined = models.DateTimeField(null=True)
date_joined = models.DateTimeField(null=True)
def __unicode__(self): def __unicode__(self):
return self.username return self.username
class AdminGroup(models.Model):
"""
under the user control group
用户可以管理的用户组或组的管理员是该用户
"""
user = models.ForeignKey(User)
group = models.ForeignKey(UserGroup)
def __unicode__(self):
return '%s: %s' % (self.user.username, self.group.name)
class Document(models.Model):
def upload_to(self, filename):
return 'upload/'+str(self.user.id)+time.strftime('/%Y/%m/%d/', time.localtime())+filename
docfile = models.FileField(upload_to=upload_to)
user = models.ForeignKey(User)

View File

@ -1,3 +0,0 @@
from django.test import TestCase
# Create your tests here.

View File

@ -6,28 +6,20 @@ urlpatterns = patterns('juser.views',
# Examples: # Examples:
# url(r'^$', 'jumpserver.views.home', name='home'), # url(r'^$', 'jumpserver.views.home', name='home'),
# url(r'^blog/', include('blog.urls')), # url(r'^blog/', include('blog.urls')),
url(r'^group/add/$', 'group_add', name='user_group_add'),
(r'^dept_list/$', view_splitter, {'su': dept_list, 'adm': dept_list_adm}), url(r'^group/list/$', 'group_list', name='user_group_list'),
(r'^dept_add/$', 'dept_add'), url(r'^group/del/$', 'group_del', name='user_group_del'),
(r'^dept_del/$', 'dept_del'), url(r'^group/edit/$', 'group_edit', name='user_group_edit'),
(r'^dept_detail/$', 'dept_detail'), url(r'^user/add/$', 'user_add', name='user_add'),
(r'^dept_del_ajax/$', 'dept_del_ajax'), url(r'^user/del/$', 'user_del', name='user_del'),
(r'^dept_edit/$', 'dept_edit'), url(r'^user/list/$', 'user_list', name='user_list'),
(r'^dept_user_ajax/$', 'dept_user_ajax'), url(r'^user/edit/$', 'user_edit', name='user_edit'),
(r'^group_add/$', view_splitter, {'su': group_add, 'adm': group_add_adm}), url(r'^user/detail/$', 'user_detail', name='user_detail'),
(r'^group_list/$', view_splitter, {'su': group_list, 'adm': group_list_adm}), url(r'^user/profile/$', 'profile', name='user_profile'),
(r'^group_detail/$', 'group_detail'), url(r'^user/update/$', 'change_info', name='user_update'),
(r'^group_del/$', view_splitter, {'su': group_del, 'adm': group_del_adm}), url(r'^mail/retry/$', 'send_mail_retry', name='mail_retry'),
(r'^group_del_ajax/$', 'group_del_ajax'), url(r'^password/reset/$', 'reset_password', name='password_reset'),
(r'^group_edit/$', view_splitter, {'su': group_edit, 'adm': group_edit_adm}), url(r'^password/forget/$', 'forget_password', name='password_forget'),
(r'^user_add/$', view_splitter, {'su': user_add, 'adm': user_add_adm}), url(r'^key/gen/$', 'regen_ssh_key', name='key_gen'),
(r'^user_list/$', view_splitter, {'su': user_list, 'adm': user_list_adm}), url(r'^key/down/$', 'down_key', name='key_down'),
(r'^user_detail/$', 'user_detail'), )
(r'^user_del/$', 'user_del'),
(r'^user_del_ajax/$', 'user_del_ajax'),
(r'^user_edit/$', view_splitter, {'su': user_edit, 'adm': user_edit_adm}),
(r'^profile/$', 'profile'),
(r'^chg_info/$', 'chg_info'),
(r'^chg_role/$', 'chg_role'),
(r'^down_key/$', 'down_key'),
)

File diff suppressed because it is too large Load Diff

0
manage.py Normal file → Executable file
View File

20
service.sh Normal file → Executable file
View File

@ -7,7 +7,7 @@
# Date: 2015-04-12 # Date: 2015-04-12
# Version: 2.0.0 # Version: 2.0.0
# Site: http://www.jumpserver.org # Site: http://www.jumpserver.org
# Author: jumpserver group # Author: Jumpserver Team
. /etc/init.d/functions . /etc/init.d/functions
export PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/opt/node/bin export PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/opt/node/bin
@ -26,17 +26,16 @@ start() {
success "$jump_start" success "$jump_start"
else else
daemon python $base_dir/manage.py runserver 0.0.0.0:80 &>> /tmp/jumpserver.log 2>&1 & daemon python $base_dir/manage.py runserver 0.0.0.0:80 &>> /tmp/jumpserver.log 2>&1 &
daemon python $base_dir/log_handler.py &> /dev/null 2>&1 & daemon python $base_dir/run_websocket.py &> /dev/null 2>&1 &
cd $base_dir/websocket/;daemon node index.js &> /dev/null 2>&1 &
sleep 2 sleep 2
echo -n "$jump_start" echo -n "$jump_start"
nums=0 nums=0
for i in manage.py log_handler.py index.js;do for i in manage.py run_websocket.py;do
ps aux | grep "$i" | grep -v 'grep' &> /dev/null && let nums+=1 ps aux | grep "$i" | grep -v 'grep' &> /dev/null && let nums+=1 || echo "$i not running"
done done
if [ "x$nums" == "x3" ];then if [ "x$nums" == "x2" ];then
success "$jump_start" success "$jump_start"
touch "$lockfile" touch "$lockfile"
echo echo
@ -44,7 +43,6 @@ start() {
failure "$jump_start" failure "$jump_start"
echo echo
fi fi
fi fi
@ -56,7 +54,7 @@ stop() {
echo -n $"Stopping ${PROC_NAME} service:" echo -n $"Stopping ${PROC_NAME} service:"
if [ -e $lockfile ];then if [ -e $lockfile ];then
ps aux | grep -E 'manage.py|log_handler.py|index.js' | grep -v grep | awk '{print $2}' | xargs kill -9 &> /dev/null ps aux | grep -E 'manage.py|run_websocket.py' | grep -v grep | awk '{print $2}' | xargs kill -9 &> /dev/null
ret=$? ret=$?
if [ $ret -eq 0 ]; then if [ $ret -eq 0 ]; then
@ -104,9 +102,3 @@ esac

BIN
static/.DS_Store vendored

Binary file not shown.

View File

@ -2822,7 +2822,9 @@ body.body-small .footer.fixed {
.table > thead > tr > td, .table > thead > tr > td,
.table > tbody > tr > td, .table > tbody > tr > td,
.table > tfoot > tr > td { .table > tfoot > tr > td {
border-top: 1px solid #e7eaec; /*border-top: 1px solid #e7eaec;*/
border-bottom: 1px solid #e7eaec;
border-top: none;
line-height: 1.42857; line-height: 1.42857;
padding: 8px; padding: 8px;
vertical-align: top; vertical-align: top;
@ -3516,8 +3518,8 @@ body.modal-open {
z-index: 100; z-index: 100;
} }
.lockscreen.middle-box { .lockscreen.middle-box {
width: 200px; width: 400px;
margin-left: -100px; margin-left: -200px;
margin-top: -190px; margin-top: -190px;
} }
.loginscreen.middle-box { .loginscreen.middle-box {
@ -4562,3 +4564,10 @@ body.skin-3 {
.red-fonts { .red-fonts {
color: #ed5565; color: #ed5565;
} }
.form-group.required .control-label:after {
content: " *";
color: red;
}
.n-invalid {border: 1px solid #f00;}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 105 KiB

After

Width:  |  Height:  |  Size: 106 KiB

View File

@ -16,6 +16,22 @@ function check_all(form) {
} }
} }
function checkAll(id, name){
var checklist = document.getElementsByName(name);
if(document.getElementById(id).checked)
{
for(var i=0;i<checklist.length;i++)
{
checklist[i].checked = 1;
}
}else{
for(var j=0;j<checklist.length;j++)
{
checklist[j].checked = 0;
}
}
}
//提取指定行的数据JSON格式 //提取指定行的数据JSON格式
function GetRowData(row){ function GetRowData(row){
var rowData = {}; var rowData = {};
@ -89,22 +105,31 @@ function move_left(from, to, from_o, to_o) {
//} //}
// //
function selectAll(){ //function selectAllOption(){
var checklist = document.getElementsByName ("selected"); // var checklist = document.getElementsByName ("selected");
if(document.getElementById("select_all").checked) // if(document.getElementById("select_all").checked)
{ // {
for(var i=0;i<checklist.length;i++) // for(var i=0;i<checklist.length;i++)
{ // {
checklist[i].checked = 1; // checklist[i].checked = 1;
} // }
}else{ // }else{
for(var j=0;j<checklist.length;j++) // for(var j=0;j<checklist.length;j++)
{ // {
checklist[j].checked = 0; // checklist[j].checked = 0;
} // }
} // }
//
// }
function selectAll(){
// 选择该页面所有option
$('option').each(function(){
$(this).attr('selected', true)
})
}
}
// //
//function move_all(from, to){ //function move_all(from, to){
@ -119,3 +144,11 @@ function selectAll(){
// }) // })
//} //}
function getIDall() {
var check_array = [];
$(".gradeX input:checked").each(function () {
var id = $(this).attr("value");
check_array.push(id);
});
return check_array.join(",");
}

View File

@ -662,7 +662,7 @@
this.element.setAttribute("enctype", "multipart/form-data"); this.element.setAttribute("enctype", "multipart/form-data");
} }
if (this.element.classList.contains("dropzone") && !this.element.querySelector(".dz-message")) { if (this.element.classList.contains("dropzone") && !this.element.querySelector(".dz-message")) {
this.element.appendChild(Dropzone.createElement("<div class=\"dz-default dz-message\"><span>" + this.options.dictDefaultMessage + "</span></div>")); this.element.appendChild(Dropzone.createElement("<div class=\"dz-default dz-message\" style=\"z-index:1;\"><span>" + this.options.dictDefaultMessage + "</span></div>"));
} }
if (this.clickableElements.length) { if (this.clickableElements.length) {
setupHiddenFileInput = (function(_this) { setupHiddenFileInput = (function(_this) {

View File

@ -180,7 +180,7 @@ function merge() {
} }
/** /**
* Take an array and turn into a hash with even number arguments as keys and odd numbers as * Take an array and turn into a hash with even number arguments as role_keys and odd numbers as
* values. Allows creating constants for commonly used style properties, attributes etc. * values. Allows creating constants for commonly used style properties, attributes etc.
* Avoid it in performance critical situations like looping * Avoid it in performance critical situations like looping
*/ */
@ -448,7 +448,7 @@ dateFormat = function (format, timestamp, capitalize) {
lang = defaultOptions.lang, lang = defaultOptions.lang,
langWeekdays = lang.weekdays, langWeekdays = lang.weekdays,
// List all format keys. Custom formats can be added from the outside. // List all format role_keys. Custom formats can be added from the outside.
replacements = extend({ replacements = extend({
// Day // Day
@ -14895,7 +14895,7 @@ var AreaSeries = extendClass(Series, {
pointMap[points[i].x] = points[i]; pointMap[points[i].x] = points[i];
} }
// Sort the keys (#1651) // Sort the role_keys (#1651)
for (x in stack) { for (x in stack) {
if (stack[x].total !== null) { // nulled after switching between grouping and not (#1651, #2336) if (stack[x].total !== null) { // nulled after switching between grouping and not (#1651, #2336)
keys.push(+x); keys.push(+x);

File diff suppressed because one or more lines are too long

View File

@ -358,7 +358,7 @@
getRelated(settings.get('rel')); getRelated(settings.get('rel'));
if (!open) { if (!open) {
open = active = true; // Prevents the page-change action from queuing up if the visitor holds down the left or right keys. open = active = true; // Prevents the page-change action from queuing up if the visitor holds down the left or right role_keys.
setClass(settings.get('className')); setClass(settings.get('className'));

14
static/js/layer/extend/layer.ext.js Normal file → Executable file

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 210 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 701 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 221 B

82
static/js/layer/skin/layer.css Normal file → Executable file

File diff suppressed because one or more lines are too long

41
static/js/layer/skin/layer.ext.css Normal file → Executable file
View File

@ -1,45 +1,8 @@
/** /*!
@Name: layer @Name: layer
@Date: 2012.12.13 @Date: 2012.12.13
@Author: @Author:
@blog: sentsin.com @blog: sentsin.com
**/ */.layui-layer-imgbar,.layui-layer-imgtit a,.layui-layer-tab .layui-layer-title span{text-overflow:ellipsis;white-space:nowrap}.layui-layer-iconext{background:url(default/icon-ext.png) no-repeat}html #layui_layer_skinlayerextcss{display:none;position:absolute;width:1989px}.layui-layer-prompt .layui-layer-input{display:block;width:220px;height:30px;margin:0 auto;line-height:30px;padding:0 5px;border:1px solid #ccc;box-shadow:1px 1px 5px rgba(0,0,0,.1) inset;color:#333}.layui-layer-prompt textarea.layui-layer-input{width:300px;height:100px;line-height:20px}.layui-layer-tab{box-shadow:1px 1px 50px rgba(0,0,0,.4)}.layui-layer-tab .layui-layer-title{padding-left:0;border-bottom:1px solid #ccc;background-color:#eee;overflow:visible}.layui-layer-tab .layui-layer-title span{position:relative;float:left;min-width:80px;max-width:260px;padding:0 20px;text-align:center;cursor:default;overflow:hidden}.layui-layer-tab .layui-layer-title span.layui-layer-tabnow{height:43px;border-left:1px solid #ccc;border-right:1px solid #ccc;background-color:#fff;z-index:10}.layui-layer-tab .layui-layer-title span:first-child{border-left:none}.layui-layer-tabmain{line-height:24px;clear:both}.layui-layer-tabmain .layui-layer-tabli{display:none}.layui-layer-tabmain .layui-layer-tabli.xubox_tab_layer{display:block}.xubox_tabclose{position:absolute;right:10px;top:5px;cursor:pointer}.layui-layer-photos{-webkit-animation-duration:1s;animation-duration:1s;background:url(default/xubox_loading1.gif) center center no-repeat #000}.layui-layer-photos .layui-layer-content{overflow:hidden;text-align:center}.layui-layer-photos .layui-layer-phimg img{position:relative;width:100%;display:inline-block;*display:inline;*zoom:1;vertical-align:top}.layui-layer-imgbar,.layui-layer-imguide{display:none}.layui-layer-imgnext,.layui-layer-imgprev{position:absolute;top:50%;width:27px;_width:44px;height:44px;margin-top:-22px;outline:0;blr:expression(this.onFocus=this.blur())}.layui-layer-imgprev{left:10px;background-position:-5px -5px;_background-position:-70px -5px}.layui-layer-imgprev:hover{background-position:-33px -5px;_background-position:-120px -5px}.layui-layer-imgnext{right:10px;_right:8px;background-position:-5px -50px;_background-position:-70px -50px}.layui-layer-imgnext:hover{background-position:-33px -50px;_background-position:-120px -50px}.layui-layer-imgbar{position:absolute;left:0;bottom:0;width:100%;height:32px;line-height:32px;background-color:rgba(0,0,0,.8);background-color:#000\9;filter:Alpha(opacity=80);color:#fff;overflow:hidden;font-size:0}.layui-layer-imgtit *{display:inline-block;*display:inline;*zoom:1;vertical-align:top;font-size:12px}.layui-layer-imgtit a{max-width:65%;overflow:hidden;color:#fff}.layui-layer-imgtit a:hover{color:#fff;text-decoration:underline}.layui-layer-imgtit em{padding-left:10px;font-style:normal}
.xubox_iconext{background:url(default/icon_ext.png) no-repeat;}
/* prompt模式 */
.xubox_layer .xubox_form{width:240px; height:30px; line-height:30px; padding: 0 5px; border: 1px solid #ccc; background: url(default/textbg.png) #fff repeat-x; color:#333;}
.xubox_layer .xubox_formArea{width:300px; height:100px; line-height:20px;}
/* tab模式 */
.xubox_layer .xubox_tab{position:relative; background-color:#fff; box-shadow:1px 1px 50px rgba(0,0,0,.4)}
.xubox_layer .xubox_tabmove{position:absolute; width:600px; height:30px; top:0; left:0;}
.xubox_layer .xubox_tabtit{ display:block; height:34px; border-bottom:1px solid #ccc; background-color:#eee;}
.xubox_layer .xubox_tabtit span{position:relative; float:left; width:120px; height:34px; line-height:34px; text-align:center; cursor:default;}
.xubox_layer .xubox_tabtit span.xubox_tabnow{left:-1px; _top:1px; height:35px; border-left:1px solid #ccc; border-right:1px solid #ccc; background-color:#fff; z-index:10;}
.xubox_layer .xubox_tab_main{line-height:24px; clear:both;}
.xubox_layer .xubox_tab_main .xubox_tabli{display:none;}
.xubox_layer .xubox_tab_main .xubox_tabli.xubox_tab_layer{display:block;}
.xubox_layer .xubox_tabclose{position:absolute; right:10px; top:5px; cursor:pointer;}
/* photo模式 */
.xubox_bigimg, .xubox_intro{height:300px}
.xubox_bigimg{position:relative; display:block; width:600px; text-align:center; background:url(default/xubox_loading1.gif) center center no-repeat #000; overflow:hidden; }
.xubox_bigimg img{position:relative; display:inline-block; visibility: hidden;}
.xubox_intro{position:absolute; right:-315px; top:0; width:300px; background-color:#fff; overflow-x:hidden; overflow-y:auto;}
.xubox_imgsee{display:none;}
.xubox_prev, .xubox_next{position:absolute; top:50%; width:27px; _width:44px; height:44px; margin-top:-22px; outline:none;blr:expression(this.onFocus=this.blur());}
.xubox_prev{left:10px; background-position:-5px -5px; _background-position:-70px -5px;}
.xubox_prev:hover{background-position:-33px -5px; _background-position:-120px -5px;}
.xubox_next{right:10px; _right:8px; background-position:-5px -50px; _background-position:-70px -50px;}
.xubox_next:hover{background-position:-33px -50px; _background-position:-120px -50px;}
.xubox_imgbar{position:absolute; left:0; bottom:0; width:100%; height:32px; line-height:32px; background-color:rgba(0,0,0,.8); background-color:#000\9; filter:Alpha(opacity=80); color:#fff; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; font-size:0;}
.xubox_imgtit{/*position:absolute; left:20px;*/}
.xubox_imgtit *{display:inline-block; *display:inline; *zoom:1; vertical-align:top; font-size:12px;}
.xubox_imgtit a{max-width:65%; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; color:#fff;}
.xubox_imgtit a:hover{color:#fff; text-decoration:underline;}
.xubox_imgtit em{padding-left:10px;}

View File

@ -2,7 +2,6 @@
<html> <html>
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
@ -11,8 +10,7 @@
<link rel="shortcut icon" href="/static/img/facio.ico" type="image/x-icon"> <link rel="shortcut icon" href="/static/img/facio.ico" type="image/x-icon">
{% include 'link_css.html' %} {% include 'link_css.html' %}
{% include 'head_script.html' %} {% include 'head_script.html' %}
{% block self_head_css_js %} {% endblock %}
</head> </head>
<body> <body>
@ -30,4 +28,5 @@
</body> </body>
{% include 'foot_script.html' %} {% include 'foot_script.html' %}
{% block self_footer_js %} {% endblock %}
</html> </html>

View File

@ -1,11 +1,16 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% load mytags %} {% load mytags %}
{% block self_head_css_js %}
<link href="/static/css/plugins/datepicker/datepicker3.css" rel="stylesheet">
<link href="/static/css/plugins/chosen/chosen.css" rel="stylesheet">
<script src="/static/js/plugins/chosen/chosen.jquery.js"></script>
{% endblock %}
{% block content %} {% block content %}
{% include 'nav_cat_bar.html' %} {% include 'nav_cat_bar.html' %}
<div class="wrapper wrapper-content animated fadeIn"> <div class="wrapper wrapper-content animated fadeIn">
<div class="row"> <div class="row">
<div class="col-lg-12"> <div class="col-sm-12">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div class="ibox-title"> <div class="ibox-title">
<h5>下载文件</h5> <h5>下载文件</h5>
@ -16,24 +21,62 @@
<a class="dropdown-toggle" data-toggle="dropdown" href="#"> <a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i> <i class="fa fa-wrench"></i>
</a> </a>
<ul class="dropdown-menu dropdown-user">
<li><a href="#">Config option 1</a>
</li>
<li><a href="#">Config option 2</a>
</li>
</ul>
<a class="close-link"> <a class="close-link">
<i class="fa fa-times"></i> <i class="fa fa-times"></i>
</a> </a>
</div> </div>
</div> </div>
<div class="ibox-content"> <div class="ibox-content">
<h2>下载文件可联系管理员在服务器安装lrzsz使用sz命令下载。 </h2> <form id="downForm" class="form-horizontal" method="post">
{% if error %}
<div class="alert alert-warning text-center">{{ error }}</div>
{% endif %}
{% if msg %}
<div class="alert alert-success text-center">{{ msg }}</div>
{% endif %}
<div class="form-group">
<label for="file_path" class="col-sm-2 control-label">文件路径<span class="red-fonts">*</span></label>
<div class="col-sm-8">
<input id="file_path" name="file_path" placeholder="File Path" type="text" class="form-control">
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="user" class="col-sm-2 control-label">选择主机<span class="red-fonts">*</span></label>
<div class="col-sm-8">
<select name="asset_ids" id="asset_ids" data-placeholder="请输入" class="chosen-select form-control m-b" multiple tabindex="2">
{% for asset in assets %}
<option value="{{ asset.id }}">{{ asset.hostname }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="form-group">
<div class="col-sm-4 col-sm-offset-2">
<button class="btn btn-white" type="reset">取消</button>
<button id="submit_button" class="btn btn-primary" type="submit">下载</button>
</div>
</div>
</form>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
{% endblock %}
{% block self_footer_js %}
<script>
var config = {
'.chosen-select' : {},
'.chosen-select-deselect' : {allow_single_deselect:true},
'.chosen-select-no-single' : {disable_search_threshold:10},
'.chosen-select-no-results': {no_results_text:'Oops, nothing found!'},
'.chosen-select-width' : {width:"95%"}
};
for (var selector in config) {
$(selector).chosen(config[selector]);
}
</script>
{% endblock %} {% endblock %}

View File

@ -19,22 +19,23 @@
<script src="/static/js/base.js"></script> <script src="/static/js/base.js"></script>
<!-- pop windows layer--> <!-- pop windows layer-->
<script src="/static/js/layer/layer.min.js"></script> <script src="/static/js/layer/layer.js"></script>
<!-- highcharts --> <!-- highcharts -->
<script src="/static/js/highcharts/highcharts.js"></script> <script src="/static/js/highcharts/highcharts.js"></script>
<script src="/static/js/dropzone/dropzone.js"></script> <script src="/static/js/dropzone/dropzone.js"></script>
<!-- active menu --> <!-- active menu -->
<script> <script>
var str = document.location.pathname.split("/")[1]; var url_array = document.location.pathname.split("/");
var str1 = document.location.pathname.split("/")[2]; s1 = url_array[1];
$("#"+str).addClass('active'); s2 = url_array[2];
if($("."+str1).length>0) { if (s1 == ''){
$("."+str1).addClass('active'); $('#index').addClass('active')
} } else {
$("#"+s1).addClass('active');
if(str.length==0){ $('#'+s1+' .'+s2).addClass('active');
$("#index").addClass('active'); console.log(s1)
} }
</script> </script>

View File

@ -1,8 +1,8 @@
<div class="footer fixed"> <div class="footer fixed">
<div class="pull-right"> <div class="pull-right">
Version <strong>2.0.0</strong> GPL. Version <strong>0.3.0</strong> GPL.
</div> </div>
<div> <div>
<strong>Copyright</strong> Jumpserver.org Organization &copy; 2014-2015 <strong>Copyright</strong> Jumpserver.org Team &copy; 2014-2015
</div> </div>
</div> </div>

View File

@ -8,4 +8,5 @@
<!-- validator js --> <!-- validator js -->
<script src="/static/js/validator/jquery.validator.js"></script> <script src="/static/js/validator/jquery.validator.js"></script>
<script src="/static/js/validator/zh_CN.js"></script> <script src="/static/js/validator/zh_CN.js"></script>
<script src="/static/js/datapicker/bootstrap-datepicker.js"></script>

View File

@ -6,63 +6,60 @@
<div class="wrapper wrapper-content"> <div class="wrapper wrapper-content">
<div class="row"> <div class="row">
<div class="col-lg-3"> <div class="col-sm-3">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div class="ibox-title"> <div class="ibox-title">
<span class="label label-success pull-right">Users</span> <span class="label label-success pull-right">Users</span>
<h5>用户总数</h5> <h5>用户总数</h5>
</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="{% url '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>
</div> </div>
<div class="col-lg-3"> <div class="col-sm-3">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div class="ibox-title"> <div class="ibox-title">
<span class="label label-info pull-right">Hosts</span> <span class="label label-info pull-right">Hosts</span>
<h5>主机总数</h5> <h5>主机总数</h5>
</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="{% url 'asset_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>
</div> </div>
<div class="col-lg-3"> <div class="col-sm-3">
<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"></span></a></h1> <h1 class="no-margins"><a href="{% url 'log_list' 'online' %}"> <span id="online_users">{{ online_user | length }}</span></a></h1>
<div class="stat-percent font-bold text-navy">{{ percent_online_user }} <i class="fa fa-level-up"></i></div> {# <div class="stat-percent font-bold text-navy">{{ percent_online_user }} <i class="fa fa-level-up"></i></div>#}
<small>Online user</small> <small>Online user</small>
</div> </div>
</div> </div>
</div> </div>
<div class="col-lg-3"> <div class="col-sm-3">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div class="ibox-title"> <div class="ibox-title">
<span class="label label-danger pull-right">Connected</span> <span class="label label-danger pull-right">Connected</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_hosts"></span></a></h1> <h1 class="no-margins"><a href="{% url '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>
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<div class="col-lg-3 border-bottom white-bg dashboard-header" style="margin-left:15px;height: 346px"> <div class="col-sm-2 border-bottom white-bg dashboard-header" style="margin-left:15px;height: 346px">
<h2>活跃用户TOP5</h2> <h2>活跃用户TOP5</h2>
<small>过去一周共有<span class="text-info">{{ week_users }}</span>位用户登录<span class="text-success">{{ week_hosts }}</span>次服务器.</small> <small>过去一周共有<span class="text-info">{{ week_users }}</span>位用户登录<span class="text-success">{{ week_hosts }}</span>次服务器.</small>
<ul class="list-group clear-list m-t"> <ul class="list-group clear-list m-t">
@ -76,15 +73,83 @@
{% endfor %} {% endfor %}
</ul> </ul>
</div> </div>
<div class="col-lg-9" id="top10" style="margin-left: -15px;height: 345px"></div> <div class="col-sm-7" id="top10" style="margin-left: -15px;height: 346px;padding: 15px 0 15px 0;"></div>
<div class="col-sm-3 white-bg" id="top1" style="margin-left: -15px;height: 346px">
<div class="statistic-box">
<h4>
活跃用户资产占比
</h4>
<p>
以下图形分别描述一个月活跃用户和资产占所有用户主机的百分比
</p>
<div class="row text-center">
<div class="col-sm-6">
<div id="activeUser" style="width: 140px; height: 140px;">
</div>
<h5>用户</h5>
</div>
<div class="col-sm-6">
<div id="activeAsset" style="width: 140px; height: 140px;"></div>
<h5>主机</h5>
</div>
</div>
<div class="m-t">
<small></small>
</div>
</div>
</div>
</div> </div>
<br/> <br/>
<div class="row"> <div class="row">
<div class="col-lg-4"> <div class="col-sm-4">
{# <div class="ibox float-e-margins">#}
{# <div class="ibox-title">#}
{# <h5>权限申请</h5>#}
{# <div class="ibox-tools">#}
{# <a class="collapse-link">#}
{# <i class="fa fa-chevron-up"></i>#}
{# </a>#}
{# <a class="dropdown-toggle" data-toggle="dropdown" href="#">#}
{# <i class="fa fa-wrench"></i>#}
{# </a>#}
{# <ul class="dropdown-menu dropdown-user"></ul>#}
{# <a class="close-link">#}
{# <i class="fa fa-times"></i>#}
{# </a>#}
{# </div>#}
{# </div>#}
{# <div class="ibox-content ibox-heading">#}
{# <h3><i class="fa fa-envelope-o"></i> 权限申请记录 </h3>#}
{# <small><i class="fa fa-map-marker"></i> 最近十条权限申请记录信息.</small>#}
{# </div>#}
{# <div class="ibox-content">#}
{# <div class="feed-activity-list">#}
{# {% if perm_apply_10 %}#}
{# {% for perm in perm_apply_10 %}#}
{# <div class="feed-element">#}
{# <div>#}
{# {% ifequal perm.status 0 %}#}
{# <small class="pull-right text-navy">{{ perm.date_add|naturaltime }}</small>#}
{# {% else %}#}
{# <small class="pull-right">{{ perm.date_add|naturaltime }}</small>#}
{# {% endifequal %}#}
{# <strong>{{ perm.applyer }}</strong>#}
{# <small class="text-muted">{{ perm.date_add }}</small>#}
{# </div>#}
{# </div>#}
{# {% endfor %}#}
{# {% else %}#}
{# <p class="text-center">(暂无)</p>#}
{# {% endif %}#}
{# </div>#}
{# </div>#}
{# </div>#}
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div class="ibox-title"> <div class="ibox-title">
<h5>权限申请</h5> <h5>一周Top10资产</h5>
<div class="ibox-tools"> <div class="ibox-tools">
<a class="collapse-link"> <a class="collapse-link">
<i class="fa fa-chevron-up"></i> <i class="fa fa-chevron-up"></i>
@ -99,24 +164,25 @@
</div> </div>
</div> </div>
<div class="ibox-content ibox-heading"> <div class="ibox-content ibox-heading">
<h3><i class="fa fa-envelope-o"></i> 权限申请记录 </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 class="ibox-content inspinia-timeline">
{% if host_top_ten %}
{% for data in host_top_ten %}
<div class="timeline-item">
<div class="row">
<div class="col-xs-5 date">
<i class="fa fa-info-circle"></i>
<strong>{{ data.host }}</strong>
<br/>
<small class="text-navy">{{ data.times }}次</small>
</div>
<div class="col-xs-7 content no-top-border">
<p class="m-b-xs">最近一次登录用户</p>
<p>{{ data.last.user }}</p>
<p>于{{ data.last.start_time |date:"Y-m-d H:i:s" }}</p>
</div> </div>
<div class="ibox-content">
<div class="feed-activity-list">
{% if perm_apply_10 %}
{% for perm in perm_apply_10 %}
<div class="feed-element">
<div>
{% ifequal perm.status 0 %}
<small class="pull-right text-navy">{{ perm.date_add|naturaltime }}</small>
{% else %}
<small class="pull-right">{{ perm.date_add|naturaltime }}</small>
{% endifequal %}
<strong>{{ perm.applyer }}</strong>
<div>申请 {{ perm.bisgroup|ast_to_list }} 主机组权限</div>
<div>申请 {{ perm.asset|ast_to_list }} 主机权限</div>
<small class="text-muted">{{ perm.date_add }}</small>
</div> </div>
</div> </div>
{% endfor %} {% endfor %}
@ -126,8 +192,7 @@
</div> </div>
</div> </div>
</div> </div>
</div> <div class="col-sm-4">
<div class="col-lg-4">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div class="ibox-title"> <div class="ibox-title">
<h5>最近十次登录</h5> <h5>最近十次登录</h5>
@ -137,7 +202,7 @@
</div> </div>
<div class="ibox-content ibox-heading"> <div class="ibox-content ibox-heading">
<h3><i class="fa fa-paper-plane-o"></i> 登录记录 </h3> <h3><i class="fa fa-paper-plane-o"></i> 登录记录 </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"> <div class="ibox-content">
<div> <div>
@ -193,7 +258,7 @@
</div> </div>
</div> </div>
<div class="col-lg-4"> <div class="col-sm-4">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div class="ibox-title"> <div class="ibox-title">
<h5>一周Top10用户</h5> <h5>一周Top10用户</h5>
@ -212,7 +277,7 @@
</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-user"></i> 一周Top10用户 </h3>
<small><i class="fa fa-map-marker"></i> 一周Top10用户登录次数及最近一次登录记录. </small> <small><i class="fa fa-map-marker"></i> 用户登录次数及最近一次登录记录. </small>
</div> </div>
<div class="ibox-content inspinia-timeline"> <div class="ibox-content inspinia-timeline">
{% if user_top_ten %} {% if user_top_ten %}
@ -226,7 +291,7 @@
<small class="text-navy">{{ data.times }}次</small> <small class="text-navy">{{ data.times }}次</small>
</div> </div>
<div class="col-xs-7 content no-top-border"> <div class="col-xs-7 content no-top-border">
<p class="m-b-xs">最近一次登录</p> <p class="m-b-xs">最近一次登录主机</p>
<p>{{ data.last.host }}</p> <p>{{ data.last.host }}</p>
<p>于{{ data.last.start_time |date:"Y-m-d H:i:s" }}</p> <p>于{{ data.last.start_time |date:"Y-m-d H:i:s" }}</p>
</div> </div>
@ -239,170 +304,258 @@
</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>
{% endblock %}
{% block self_footer_js %}
<script src="/static/js/echarts/echarts.js"></script>
<script> <script>
$(document).ready(function(){ $(document).ready(function(){
$('#show').click(function(){ $('#show').click(function(){
$('#show').css('display', 'none'); $('#show').css('display', 'none');
$('#more').css('display', 'block'); $('#more').css('display', 'block');
}) })
})
var cate = {{ li_str|safe }};
$(function () {
$('#top10').highcharts({
// chart: {
// type: 'column'
// },
title: {
text: '一周数据总览',
x: -20 //center
},
subtitle: {
text: 'Source: JumpServer',
x: -20
},
rangeSelector: {
allButtonsEnabled: true,
selected: 2
},
xAxis: {
type: 'datetime',
categories: cate
},
yAxis:{
min: 0,
title: {
text: ''
},
plotLines: [{
value: 0,
width: 1,
color: '#808080'
}]
},
tooltip: {
valueSuffix: '次'
},
navigation: {
buttonOptions: {
align: 'right'
}
},
series: [
{% for k,v in top_dic.items %}
{
name: '{{ k }}',
data: {{ v }}
},
{% endfor %}
]
});
$('#usertop10').highcharts({
title: {
text: '一周用户登录TOP10',
x: -20 //center
},
subtitle: {
text: 'Source: JumpServer',
x: -20
},
xAxis: {
type: 'datetime',
categories: cate
},
yAxis:{
min: 0,
title: {
text: '登录次数'
},
plotLines: [{
value: 0,
width: 1,
color: '#808080'
}]
},
tooltip: {
valueSuffix: '次'
},
series: [
{% for k,v in user_dic.items %}
{
name: '{{ k }}',
data: {{ v }}
},
{% endfor %}
]
});
$('#hosttop10').highcharts({
title: {
text: '一周主机登录TOP10',
x: -20 //center
},
subtitle: {
text: 'Source: JumpServer',
x: -20
},
xAxis: {
type: 'datetime',
categories: cate
},
yAxis:{
min: 0,
title: {
text: '登录次数'
},
plotLines: [{
value: 0,
width: 1,
color: '#808080'
}]
},
tooltip: {
valueSuffix: '次'
},
series: [
{% for k,v in host_dic.items %}
{
name: '{{ k }}',
data: {{ v }}
},
{% endfor %}
]
});
function magic_number(value, id) {
var num = $("#"+id);
num.animate({count: value}, {
duration: 500,
step: function() {
num.text(String(parseInt(this.count)));
}
});
};
function update() {
$.getJSON('api/user/', function(data) {
var users = data.users;
var hosts = data.hosts;
magic_number(users, 'online_users');
magic_number(hosts, 'online_hosts')
});
};
setInterval(update, 5000); //5秒钟执行一次
update();
}); });
require.config({
paths: {
'echarts': '/static/js/echarts/chart',
'echarts/chart/line': '/static/js/echarts/chart/line',
'echarts/chart/pie': '/static/js/echarts/chart/pie'
}
});
require(
[
'echarts',
'echarts/chart/line'
],
function (ec) {
var top10Chart = ec.init(document.getElementById('top10'));
var option = {
title : {
text: '月数据总览',
subtext: '一个月内历史汇总',
x: 'center'
},
tooltip : {
trigger: 'axis'
},
backgroundColor: '#fff',
legend: {
data:['登陆次数', '活跃用户','活跃资产'],
y: 'bottom'
},
toolbox: {
show : false,
feature : {
{# mark : {show: true},#}
{# dataView : {show: true, readOnly: false},#}
magicType : {show: true, type: ['line', 'bar']}
}
},
calculable : true,
xAxis : [
{
type : 'category',
boundaryGap : false,
data : {{ date_month | safe}}
}
],
yAxis : [
{
type : 'value'
}
],
series : [
{
name:'登陆次数',
type:'line',
smooth:true,
itemStyle: {normal: {areaStyle: {type: 'default'}}},
data: {{ active_login_per_month | safe }}
},
{
name:'活跃用户',
type:'line',
smooth:true,
itemStyle: {normal: {areaStyle: {type: 'default'}}},
data: {{ active_user_per_month | safe }}
},
{
name:'活跃资产',
type:'line',
smooth:true,
itemStyle: {normal: {areaStyle: {type: 'default'}}},
data: {{ active_asset_per_month | safe }}
}
]
};
top10Chart.setOption(option);
}
);
require(
[
'echarts',
'echarts/chart/pie'
],
function (ec) {
var auChart = ec.init(document.getElementById('activeUser'));
var option = {
tooltip : {
trigger: 'item',
formatter: "{b} <br> {c} ({d}%)"
},
legend: {
show: false,
orient : 'vertical',
x : 'left',
data:['月活跃用户','禁用用户','月未登陆用户']
},
toolbox: {
show : false,
feature : {
mark : {show: true},
dataView : {show: true, readOnly: false},
magicType : {
show: true,
type: ['pie', 'funnel'],
option: {
funnel: {
x: '25%',
width: '50%',
funnelAlign: 'center',
max: 1548
}
}
},
restore : {show: true},
saveAsImage : {show: true}
}
},
calculable : true,
series : [
{
name:'访问来源',
type:'pie',
radius : ['50%', '70%'],
itemStyle : {
normal : {
label : {
show : false
},
labelLine : {
show : false
}
},
emphasis : {
label : {
show : true,
position : 'center',
textStyle : {
fontSize : '5',
fontWeight : 'bold'
}
}
}
},
data:[
{value:{{ active_user_month }}, name:'月活跃用户'},
{value:{{ disabled_user_count }}, name:'禁用用户'},
{value:{{ inactive_user_month }}, name:'月未登陆用户'}
]
}
]
};
auChart.setOption(option);
}
);
require(
[
'echarts',
'echarts/chart/pie'
],
function (ec) {
var aaChart = ec.init(document.getElementById('activeAsset'));
var option = {
tooltip : {
trigger: 'item',
formatter: "{b} <br> {c} ({d}%)"
},
legend: {
show: false,
orient : 'vertical',
x : 'left',
data:['月被登陆主机','禁用主机','月未登陆主机']
},
toolbox: {
show : false,
feature : {
mark : {show: true},
dataView : {show: true, readOnly: false},
magicType : {
show: true,
type: ['pie', 'funnel'],
option: {
funnel: {
x: '25%',
width: '50%',
funnelAlign: 'center',
max: 1548
}
}
},
restore : {show: true},
saveAsImage : {show: true}
}
},
calculable : true,
series : [
{
name:'访问来源',
type:'pie',
radius : ['50%', '70%'],
itemStyle : {
normal : {
label : {
show : false
},
labelLine : {
show : false
}
},
emphasis : {
label : {
show : true,
position : 'center',
textStyle : {
fontSize : '5',
fontWeight : 'bold'
}
}
}
},
data:[
{value:{{ active_asset_month }}, name:'月被登陆主机'},
{value:{{ disabled_asset_count }}, name:'禁用主机'},
{value:{{ inactive_asset_month }}, name:'月未登陆主机'}
]
}
]
};
aaChart.setOption(option);
}
);
</script> </script>
{% endblock %} {% endblock %}

View File

@ -5,7 +5,8 @@
<div class="wrapper wrapper-content" xmlns="http://www.w3.org/1999/html"> <div class="wrapper wrapper-content" xmlns="http://www.w3.org/1999/html">
<div class="row"> <div class="row">
<div class="col-lg-8"> <div class="col-sm-8">
<div class="col-sm-12">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div class="ibox-title"> <div class="ibox-title">
<h5> 使用说明 </h5> <h5> 使用说明 </h5>
@ -16,12 +17,6 @@
<a class="dropdown-toggle" data-toggle="dropdown" href="#"> <a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i> <i class="fa fa-wrench"></i>
</a> </a>
<ul class="dropdown-menu dropdown-user">
<li><a href="#">未启用 1</a>
</li>
<li><a href="#">未启用 2</a>
</li>
</ul>
<a class="close-link"> <a class="close-link">
<i class="fa fa-times"></i> <i class="fa fa-times"></i>
</a> </a>
@ -30,55 +25,70 @@
<div class="ibox-content" style="line-height: 26px"> <div class="ibox-content" style="line-height: 26px">
<span style="font-size: large"></span>迎使用<span class="text-navy"><b>Jumpserver</b></span>跳板机系统, <span style="font-size: large"></span>迎使用<span class="text-navy"><b>Jumpserver</b></span>跳板机系统,
首先需要 <b><a href="/juser/down_key/?id={{ user.id }}">下载</a></b> 登录跳板机的SSH密钥文件然后导入到工具或者ssh命令指定密钥文件(确保密钥文件权限600),输入收到的密钥密码,登录跳板机。 首先需要 <b><a href="{% url 'key_down' %}?id={{ user.id }}">下载</a></b> 登录跳板机的SSH密钥文件然后导入到工具或者ssh命令指定密钥文件(确保密钥文件权限600),输入收到的密钥密码,登录跳板机。
登录后根据提示进行操作。跳板机web界面支持修改密码、个人信息和上传下载文件等功能可以向管理员申请权限。 登录后根据提示进行操作。跳板机web界面支持修改密码、个人信息和上传下载文件等功能可以向管理员申请权限。
</div> </div>
</div> </div>
</div>
<div class="col-sm-12">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div class="ibox-title"> <div class="ibox-title">
<h5> 已授权主机 </h5> <h5>登录记录</h5>
<div class="ibox-tools"> <div class="ibox-tools">
<div class="label label-primary float-left"><b>总共:{{ host_count }}</b></div> <span class="label label-warning-light">最近登录</span>
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
</a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i>
</a>
<ul class="dropdown-menu dropdown-user">
<li><a href="#">未启用 1</a>
</li>
<li><a href="#">未启用 2</a>
</li>
</ul>
<a class="close-link">
<i class="fa fa-times"></i>
</a>
</div> </div>
</div> </div>
<div class="ibox-content"> <div class="ibox-content">
<table class="table table-striped"> <div id="last">
{% for host_five in new_posts %} <div class="feed-activity-list" >
<tr> {% for log in logs_last %}
{% for host in host_five %} <div class="feed-element">
<td>{{ host.ip }}</td> <a href="profile.html" class="pull-left">
<img alt="image" class="img-circle" src="/static/img/{{ session_role_id | to_avatar }}.png">
</a>
<div class="media-body ">
{# <small class="pull-right">{{ log.start_time|time_delta }}</small>#}
<small class="pull-right">{{ log.start_time }}</small>
<strong>{{ log.user }}</strong> 登录了 <span class="text-navy">{{ log.host }}. </span><br>
<small class="text-muted">{{ log.start_time|date:"Y-m-d H:i:s" }}</small>
</div>
</div>
{% endfor %} {% endfor %}
</tr> {% if not logs_last %}
(暂无)
{% endif %}
</div>
{% if logs_num > 10 %}
<button id="show" class="btn btn-primary btn-block m-t"><i class="fa fa-arrow-down"></i> Show All</button>
{% endif %}
</div>
<div id="all" style="display: none">
<div class="feed-activity-list" >
{% for log in logs_all %}
<div class="feed-element">
<a href="profile.html" class="pull-left">
<img alt="image" class="img-circle" src="/static/img/{{ session_role_id | to_avatar }}.png">
</a>
<div class="media-body ">
<small class="pull-right">{{ log.start_time }}</small>
{# <small class="pull-right">{{ log.start_time|time_delta }}</small>#}
<strong>{{ log.user }}</strong> 登录了 <span class="text-navy">{{ log.host }}. </span><br>
<small class="text-muted">{{ log.start_time|date:"Y-m-d H:i:s" }}</small>
</div>
</div>
{% endfor %} {% endfor %}
</table> </div>
{% ifequal host_count 0 %} </div>
(空) </div>
{% endifequal %}
</div> </div>
</div> </div>
</div> </div>
<div class="col-lg-4"> <div class="col-sm-4">
<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"><b>{{ user.name }}</b></span> <span class="label label-primary"><b>{{ user.username }}</b></span>
<div class="ibox-tools"> <div class="ibox-tools">
<a class="collapse-link"> <a class="collapse-link">
<i class="fa fa-chevron-up"></i> <i class="fa fa-chevron-up"></i>
@ -114,12 +124,8 @@
<td>{{ user.name }}</td> <td>{{ user.name }}</td>
</tr> </tr>
<tr> <tr>
<td class="text-navy">角色</td> <td class="text-navy">系统用户</td>
<td>{{ user.id | get_role }}</td> <td>{{ user.role }}</td>
</tr>
<tr>
<td class="text-navy">部门</td>
<td>{{ user.dept.name }}</td>
</tr> </tr>
<tr> <tr>
<td class="text-navy">Email</td> <td class="text-navy">Email</td>

View File

@ -1,3 +0,0 @@
{% for host in hosts %}
<option value="{{ host.id }}">{{ host.ip }}</option>
{% endfor %}

View File

@ -19,7 +19,7 @@
<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-sm-10">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div id="ibox-content" class="ibox-title"> <div id="ibox-content" class="ibox-title">
<h5> 填写主机组基本信息 </h5> <h5> 填写主机组基本信息 </h5>
@ -31,10 +31,6 @@
<i class="fa fa-wrench"></i> <i class="fa fa-wrench"></i>
</a> </a>
<ul class="dropdown-menu dropdown-user"> <ul class="dropdown-menu dropdown-user">
<li><a href="#">未启用 1</a>
</li>
<li><a href="#">未启用 2</a>
</li>
</ul> </ul>
<a class="close-link"> <a class="close-link">
<i class="fa fa-times"></i> <i class="fa fa-times"></i>
@ -43,14 +39,14 @@
</div> </div>
<select id="assets_total" name="assets" class="form-control m-b" size="12" multiple style="display: none"> <select id="assets_total" name="assets" class="form-control m-b" size="12" multiple style="display: none">
{% for asset in posts %} {% for asset in asset_all %}
<option value="{{ asset.id }}">{{ asset.ip }}</option> <option value="{{ asset.id }}">{{ asset.hostname }} - {{ asset.ip }}</option>
{% endfor %} {% endfor %}
</select> </select>
<select id="asset_select_total" name="j_hosts" class="form-control m-b" size="12" multiple style="display: none"> <select id="asset_select_total" name="j_hosts" class="form-control m-b" size="12" multiple style="display: none">
{% for asset in eposts %} {% for asset in asset_select %}
<option value="{{ asset.id }}">{{ asset.ip }}</option> <option value="{{ asset.id }}">{{ asset.hostname }} - {{ asset.ip }}</option>
{% endfor %} {% endfor %}
</select> </select>
@ -63,32 +59,9 @@
{% endif %} {% endif %}
<form id="assetForm" method="post" class="form-horizontal"> <form id="assetForm" method="post" class="form-horizontal">
<div class="form-group"><label class="col-sm-2 control-label"> 主机组名<span class="red-fonts">*</span></label> <div class="form-group"><label class="col-sm-2 control-label"> 主机组名<span class="red-fonts">*</span></label>
<div class="col-sm-8" name="group_id" value="{{ post.id }}"><input type="text" value="{{ group.name }}" placeholder="网站" name="j_group" class="form-control"></div> <div class="col-sm-8" name="group_id" value="{{ post.id }}"><input type="text" value="{{ group.name }}" placeholder="Name" name="name" class="form-control"></div>
</div> </div>
{% ifequal session_role_id 2 %}
<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>
<div class="col-sm-8">
<select id="j_dept" name="j_dept" class="form-control m-b" onchange="change_dept(this.value)">
{% for d in edept %}
<option value="{{ d.id }}">{{ d.name }}</option>
{% endfor %}
</select>
</div>
</div>
{% endifequal %}
{% 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" style="">*</span></label>
<input type="text" name="j_dept" value="{{ edept.id }}" style="display: none">
<div class="col-sm-8"><input type="text" value="{{ edept.name }}" class="form-control" readonly="readonly"></div>
</div>
{% endifequal %}
<div class="hr-line-dashed"></div> <div class="hr-line-dashed"></div>
<div class="form-group"> <div class="form-group">
<label for="group_name" class="col-sm-2 control-label">过滤</label> <label for="group_name" class="col-sm-2 control-label">过滤</label>
@ -104,12 +77,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 post in posts %} {% for asset in asset_all %}
<option value="{{ post.id }}">{{ post.ip }}</option> <option value="{{ asset.id }}">{{ asset.hostname|default_if_none:"" }} - {{ asset.ip|default_if_none:"" }}</option>
{% endfor %} {% endfor %}
</select> </select>
</div> </div>
@ -124,14 +97,14 @@
<div class="col-sm-3"> <div class="col-sm-3">
<div> <div>
<select id="asset_select" name="j_hosts" class="form-control m-b" size="12" multiple></select> <select id="asset_select" name="asset_select" class="form-control m-b" size="12" multiple></select>
</div> </div>
</div> </div>
</div> </div>
<div class="hr-line-dashed"></div> <div class="hr-line-dashed"></div>
<div class="form-group"><label class="col-sm-2 control-label"> 备注 </label> <div class="form-group"><label class="col-sm-2 control-label"> 备注 </label>
<div class="col-sm-8"><input type="text" value="{{ j_comment }}" placeholder=包括web组所有主机 name="j_comment" class="form-control"></div> <div class="col-sm-8"><input type="text" value="" placeholder="comment" name="comment" class="form-control"></div>
</div> </div>
<div class="hr-line-dashed"></div> <div class="hr-line-dashed"></div>
@ -162,12 +135,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) {
@ -182,16 +155,6 @@
}) })
} }
// $('#search').keyup(function() {
// var $rows = $('#hosts option');
// var val = $.trim($(this).val()).replace(/ +/g, ' ').toLowerCase();
//
// $rows.show().filter(function() {
// var text = $(this).text().replace(/\s+/g, ' ').toLowerCase();
// return !~text.indexOf(val);
// }).hide();
// });
function change_dept(dept_id){ function change_dept(dept_id){
$.get('/jasset/dept_host_ajax/', $.get('/jasset/dept_host_ajax/',
{'id': dept_id}, {'id': dept_id},

View File

@ -1,203 +0,0 @@
{% extends 'base.html' %}
{% load mytags %}
{% block content %}
{% include 'nav_cat_bar.html' %}
<div class="wrapper wrapper-content animated fadeInRight">
<div class="row">
<div class="col-lg-12">
<div class="ibox float-e-margins" id="all">
<div class="ibox-title">
<h5> 主机组<span class="text-info">{{ group.name }}</span>详细信息列表</h5>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
</a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i>
</a>
<ul class="dropdown-menu dropdown-user">
<li><a href="#">未启用 1</a>
</li>
<li><a href="#">未启用 2</a>
</li>
</ul>
<a class="close-link">
<i class="fa fa-times"></i>
</a>
</div>
</div>
<div class="ibox-content">
<div class="">
<a target="_blank" href="/jasset/host_add" class="btn btn-sm btn-primary"> 添加主机 </a>
<b class="pull-right">提示: 此页面删除只从本主机组中剔除主机 </b>
</div>
<form id="contents_form" name="contents_form">
<table class="table table-striped table-bordered table-hover " id="editable" name="editable">
<thead>
<tr>
<th class="text-center"><input id="checkall" type="checkbox" class="i-checks" name="checkall" value="checkall" data-editable='false' onclick="check_all('contents_form')"></th>
<th class="text-center" name="j_ip"> IP地址 </th>
<th class="text-center"> 端口号 </th>
<th class="text-center" name="j_type"> 登录方式 </th>
<th class="text-center" name="j_idc"> 所属IDC </th>
<th class="text-center" id="group_id" value="{{ group.id }}"> 所属业务组 </th>
<th class="text-center"> 是否激活 </th>
<th class="text-center" name="j_time"> 添加时间 </th>
<th class="text-center" name="j_comment"> 备注 </th>
<th class="text-center"> 操作 </th>
</tr>
</thead>
<tbody>
{% for post in contacts.object_list %}
<tr class="gradeX">
<td class="text-center" name="j_id" value="{{ post.id }}" data-editable='false'><input name="id" value="{{ post.id }}" type="checkbox" class="i-checks"></td>
<td class="text-center" name="j_ip"> {{ post.ip }} </td>
<td class="text-center" name="j_port"> {{ post.port }} </td>
<td class="text-center" name="j_type"> {{ post.login_type|get_login_type }} </td>
<td class="text-center" name="j_idc"> {{ post.idc.name }} </td>
<td class="text-center" name="j_group">{{ post.bis_group.all | group_str2 }}</td>
<td class="text-center" name="j_active"> {{ post.is_active|bool2str }} </td>
<td class="text-center"> {{ post.date_added|date:"Y-m-d H:i:s" }} </td>
<td class="text-center" name="j_comment"> {{ post.comment }} </td>
<td class="text-center" data-editable='false'>
<a href="/jasset/host_detail/?id={{ post.id }}" class="iframe btn btn-xs btn-primary">详情</a>
<a href="/jasset/host_edit/?id={{ post.id }}" class="btn btn-xs btn-info">编辑</a>
<a href="/jasset/group_del_host/?id={{ post.id }}&gid={{ group.id }}" class="btn btn-xs btn-danger">删除</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="row">
<div class="col-sm-6">
<input type="button" id="del_button" class="btn btn-danger btn-sm" name="del_button" value="删除" onclick="del('contents_form')" />
<input type="button" id="alter_button" class="btn btn-warning btn-sm" name="alter_button" value="修改" onclick="alter('contents_form')" />
</div>
<div class="col-sm-6">
<div class="dataTables_paginate paging_simple_numbers" id="editable_paginate">
<ul class="pagination" style="margin-top: 0; float: right">
{% if keyword %}
{% if contacts.has_previous %}
<li class="paginate_button previous" aria-controls="editable" tabindex="0" id="editable_previous">
<a href="?keyword={{ keyword }}&page={{ contacts.previous_page_number }}">Previous</a>
</li>
{% else %}
<li class="paginate_button previous disabled" aria-controls="editable" tabindex="0" id="editable_previous">
<a href="#">Previous</a>
</li>
{% endif %}
{% ifequal show_first 1 %}
<li class="paginate_button" aria-controls="editable" tabindex="0"><a href="?keyword={{ keyword }}&page=1&id={{ group.id }}" title="第1页">1...</a></li>
{% endifequal %}
{% for page in page_range %}
{% ifequal current_page page %}
<li class="paginate_button active" aria-controls="editable" tabindex="0"><a href="?keyword={{ keyword }}&page={{ page }}&id={{ group.id }}" title="第{{ page }}页">{{ page }}</a></li>
{% else %}
<li class="paginate_button" aria-controls="editable" tabindex="0"><a href="?keyword={{ keyword }}&page={{ page }}&id={{ group.id }}" title="第{{ page }}页">{{ page }}</a></li>
{% endifequal %}
{% endfor %}
{% ifequal show_end 1 %}
<li class="paginate_button" aria-controls="editable" tabindex="0"><a href="?keyword={{ keyword }}&page={{ p.num_pages }}&id={{ group.id }}" title="第{{ page }}页">...{{ p.num_pages }}</a></li>
{% endifequal %}
{% if contacts.has_next %}
<li class="paginate_button next" aria-controls="editable" tabindex="0" id="editable_next">
<a href="?keyword={{ keyword }}&page={{ contacts.next_page_number }}&id={{ group.id }}">Next</a>
</li>
{% else %}
<li class="paginate_button next disabled" aria-controls="editable" tabindex="0" id="editable_next">
<a href="#">Next</a>
</li>
{% endif %}
{% else %}
{% if contacts.has_previous %}
<li class="paginate_button previous" aria-controls="editable" tabindex="0" id="editable_previous">
<a href="?page={{ contacts.previous_page_number }}&id={{ group.id }}">Previous</a>
</li>
{% else %}
<li class="paginate_button previous disabled" aria-controls="editable" tabindex="0" id="editable_previous">
<a href="#">Previous</a>
</li>
{% endif %}
{% ifequal show_first 1 %}
<li class="paginate_button" aria-controls="editable" tabindex="0"><a href="?page=1&id={{ group.id }}" title="第1页">1...</a></li>
{% endifequal %}
{% for page in page_range %}
{% ifequal current_page page %}
<li class="paginate_button active" aria-controls="editable" tabindex="0"><a href="?page={{ page }}&id={{ group.id }}" title="第{{ page }}页">{{ page }}</a></li>
{% else %}
<li class="paginate_button" aria-controls="editable" tabindex="0"><a href="?page={{ page }}&id={{ group.id }}" title="第{{ page }}页">{{ page }}</a></li>
{% endifequal %}
{% endfor %}
{% ifequal show_end 1 %}
<li class="paginate_button" aria-controls="editable" tabindex="0"><a href="?page={{ p.num_pages }}&id={{ group.id }}" title="第{{ page }}页">...{{ p.num_pages }}</a></li>
{% endifequal %}
{% if contacts.has_next %}
<li class="paginate_button next" aria-controls="editable" tabindex="0" id="editable_next">
<a href="?page={{ contacts.next_page_number }}&id={{ group.id }}">Next</a>
</li>
{% else %}
<li class="paginate_button next disabled" aria-controls="editable" tabindex="0" id="editable_next">
<a href="#">Next</a>
</li>
{% endif %}
{% endif %}
</ul>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function(){
$('#editable').editableTableWidget();
});
function alter(form) {
selectData = GetTableDataBox();
if (selectData[1] != 0) {
$.ajax({
type: "post",
url: "/jasset/host_edit/batch/",
data: {"editable": selectData[0], "len_table": selectData[1]},
success: function (data) {
alert("修改成功");
window.open("/jasset/host_list/", "_self");
}
});
}
}
function del(form) {
var checkboxes = document.getElementById(form);
var id_list = {};
var group_id = $('#group_id').attr("value");
var j = 0;
for (var i = 0; i < checkboxes.elements.length; i++) {
if (checkboxes.elements[i].type == "checkbox" && checkboxes.elements[i].checked == true && checkboxes.elements[i].value != "checkall") {
id_list[j] = checkboxes.elements[i].value;
j++;
}
}
if (confirm("确定从主机组中删除")) {
$.ajax({
type: "POST",
url: "/jasset/group_del_host/?id=group",
data: {"id_list": id_list, "len_list": j, "group_id": group_id},
success: function (data) {
window.open(window.location.href, "_self");
}
});
}
}
</script>
{% endblock %}

View File

@ -19,7 +19,7 @@
<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-sm-10">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div id="ibox-content" class="ibox-title"> <div id="ibox-content" class="ibox-title">
<h5> 填写主机组基本信息 </h5> <h5> 填写主机组基本信息 </h5>
@ -31,10 +31,6 @@
<i class="fa fa-wrench"></i> <i class="fa fa-wrench"></i>
</a> </a>
<ul class="dropdown-menu dropdown-user"> <ul class="dropdown-menu dropdown-user">
<li><a href="#">未启用 1</a>
</li>
<li><a href="#">未启用 2</a>
</li>
</ul> </ul>
<a class="close-link"> <a class="close-link">
<i class="fa fa-times"></i> <i class="fa fa-times"></i>
@ -43,14 +39,14 @@
</div> </div>
<select id="assets_total" name="assets" class="form-control m-b" size="12" multiple style="display: none"> <select id="assets_total" name="assets" class="form-control m-b" size="12" multiple style="display: none">
{% for asset in posts %} {% for asset in asset_all %}
<option value="{{ asset.id }}">{{ asset.ip }}</option> <option value="{{ asset.id }}">{{ asset.hostname }} - {{ asset.ip }}</option>
{% endfor %} {% endfor %}
</select> </select>
<select id="asset_select_total" name="j_hosts" class="form-control m-b" size="12" multiple style="display: none"> <select id="asset_select_total" name="j_hosts" class="form-control m-b" size="12" multiple style="display: none">
{% for asset in eposts %} {% for asset in asset_select %}
<option value="{{ asset.id }}">{{ asset.ip }}</option> <option value="{{ asset.id }}">{{ asset.hostname }} - {{ asset.ip }}</option>
{% endfor %} {% endfor %}
</select> </select>
@ -63,14 +59,7 @@
{% endif %} {% endif %}
<form id="assetForm" method="post" class="form-horizontal"> <form id="assetForm" method="post" class="form-horizontal">
<div class="form-group"><label class="col-sm-2 control-label"> 主机组名<span class="red-fonts">*</span></label> <div class="form-group"><label class="col-sm-2 control-label"> 主机组名<span class="red-fonts">*</span></label>
<div class="col-sm-8" name="group_id" value="{{ post.id }}"><input type="text" value="{{ group.name }}" placeholder="网站" name="j_group" class="form-control"></div> <div class="col-sm-8" name="group_id" value="{{ group.id }}"><input type="text" value="{{ group.name }}" placeholder="Name" name="name" class="form-control"></div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="j_dept" class="col-lg-2 control-label">所属部门<span class="red-fonts" style="">*</span></label>
<input type="text" name="j_dept" value="{{ group.dept.id }}" style="display: none">
<div class="col-sm-8"><input type="text" value="{{ group.dept.name }}" class="form-control" readonly="readonly"></div>
</div> </div>
<div class="hr-line-dashed"></div> <div class="hr-line-dashed"></div>
@ -92,8 +81,8 @@
<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 post in posts %} {% for asset in asset_no_select %}
<option value="{{ post.id }}">{{ post.ip }}</option> <option value="{{ asset.id }}">{{ asset.hostname|default_if_none:"" }} - {{ asset.ip|default_if_none:"" }}</option>
{% endfor %} {% endfor %}
</select> </select>
</div> </div>
@ -108,9 +97,9 @@
<div class="col-sm-3"> <div class="col-sm-3">
<div> <div>
<select id="asset_select" name="j_hosts" 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 eposts %} {% 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:"" }}</option>
{% endfor %} {% endfor %}
</select> </select>
</div> </div>
@ -119,7 +108,7 @@
<div class="hr-line-dashed"></div> <div class="hr-line-dashed"></div>
<div class="form-group"><label class="col-sm-2 control-label"> 备注 </label> <div class="form-group"><label class="col-sm-2 control-label"> 备注 </label>
<div class="col-sm-8"><input type="text" value="{{ group.comment }}" placeholder=包括web组所有主机 name="j_comment" class="form-control"></div> <div class="col-sm-8"><input type="text" value="{{ group.comment }}" name="comment" class="form-control"></div>
</div> </div>
<div class="hr-line-dashed"></div> <div class="hr-line-dashed"></div>

View File

@ -5,7 +5,7 @@
<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-sm-10">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div class="ibox-title"> <div class="ibox-title">
<h5> 主机组详细信息列表</h5> <h5> 主机组详细信息列表</h5>
@ -16,12 +16,6 @@
<a class="dropdown-toggle" data-toggle="dropdown" href="#"> <a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i> <i class="fa fa-wrench"></i>
</a> </a>
<ul class="dropdown-menu dropdown-user">
<li><a href="#">未启用 1</a>
</li>
<li><a href="#">未启用 2</a>
</li>
</ul>
<a class="close-link"> <a class="close-link">
<i class="fa fa-times"></i> <i class="fa fa-times"></i>
</a> </a>
@ -29,14 +23,15 @@
</div> </div>
<div class="ibox-content"> <div class="ibox-content">
<div class=""> <div class="">
<a target="_blank" href="/jasset/group_add" class="btn btn-sm btn-primary "> 添加主机组 </a> <a href="{% url 'asset_group_add' %}" class="btn btn-sm btn-primary "> 添加主机组 </a>
<a class="btn btn-sm btn-danger" id="del_check"> 删除所选 </a>
<form id="search_form" method="get" action="" class="pull-right mail-search"> <form id="search_form" method="get" action="" class="pull-right mail-search">
<div class="input-group"> <div class="input-group">
<input type="text" class="form-control input-sm" id="search_input" name="keyword" placeholder="Search"> <input type="text" class="form-control input-sm" id="search_input" name="keyword" placeholder="Search">
<input type="text" style="display: none"> <input type="text" style="display: none">
<div class="input-group-btn"> <div class="input-group-btn">
<button id='search_btn' type="submit" class="btn btn-sm btn-primary"> <button id='search_btn' type="submit" class="btn btn-sm btn-primary">
Search - 搜索 -
</button> </button>
</div> </div>
</div> </div>
@ -47,30 +42,27 @@
<table class="table table-striped table-bordered table-hover " id="editable" > <table class="table table-striped table-bordered table-hover " id="editable" >
<thead> <thead>
<tr> <tr>
<th class="text-center"><input id="checkall" type="checkbox" class="i-checks" name="checkall" value="checkall" data-editable='false' onclick="check_all('contents_form')"></th> <th class="text-center">
<input id="checkall" type="checkbox" class="i-checks" name="checkall" value="checkall" data-editable='false' onclick="check_all('contents_form')">
</th>
<th class="text-center"> 主机组名 </th> <th class="text-center"> 主机组名 </th>
<th class="text-center"> 所属部门 </th>
<th class="text-center"> 主机数量 </th> <th class="text-center"> 主机数量 </th>
<th class="text-center"> 备注 </th> <th class="text-center"> 备注 </th>
<th class="text-center"> 操作 </th> <th class="text-center"> 操作 </th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for post in contacts.object_list %} {% for asset_group in asset_groups.object_list %}
<tr class="gradeX"> <tr class="gradeX">
<td class="text-center" name="j_id" value="{{ post.id }}" data-editable='false'><input name="id" value="{{ post.id }}" type="checkbox" class="i-checks"></td> <td class="text-center" name="id" value="{{ asset_group.id }}" data-editable='false'>
<td class="text-center"> {{ post.name }} </td> <input name="id" value="{{ asset_group.id }}" type="checkbox" class="i-checks">
<td class="text-center"> {{ post.dept.name }} </td> </td>
{% ifequal session_role_id 2 %} <td class="text-center"><a href="{% url 'asset_list' %}?group_id={{ asset_group.id }}">{{ asset_group.name }} </a> </td>
<td class="text-center"> <a href="/jasset/group_detail/?id={{ post.id }}">{{ post.asset_set.count }}</a> </td> <td class="text-center"> <a href="{% url 'asset_list' %}?group_id={{ asset_group.id }}">{{ asset_group.asset_set.count }}</a> </td>
{% else %} <td class="text-center"> {{ asset_group.comment }} </td>
<td class="text-center"> <a href="/jasset/group_detail/?id={{ post.id }}">{{ post|get_group_count:dept }}</a> </td>
{% endifequal %}
<td class="text-center"> {{ post.comment }} </td>
<td class="text-center"> <td class="text-center">
<a href="/jasset/group_detail/?id={{ post.id }}" class="btn btn-xs btn-info">详情</a> <a href="{% url 'asset_group_edit' %}?id={{ asset_group.id }}" class="btn btn-xs btn-info">编辑</a>
<a href="/jasset/group_edit/?id={{ post.id }}" class="btn btn-xs btn-info">编辑</a> <a value="{% url 'asset_group_del' %}?id={{ asset_group.id }}" class="btn btn-xs btn-danger group_del">删除</a>
<a href="/jasset/group_del/?id={{ post.id }}" class="btn btn-xs btn-danger">删除</a>
</td> </td>
</tr> </tr>
{% endfor %} {% endfor %}
@ -78,8 +70,9 @@
</table> </table>
<div class="row"> <div class="row">
<div class="col-sm-6"> <div class="col-sm-6">
<input type="button" id="del_button" class="btn btn-danger btn-sm" name="del_button" value="删除" onclick="del('contents_form')" /> <div class="dataTables_info" id="editable_info" role="status" aria-live="polite">
<!--<input type="button" id="alter_button" class="btn btn-warning btn-sm" name="alter_button" value="修改" onclick="alter('contents_form')" />--> Showing {{ asset_groups.start_index }} to {{ asset_groups.end_index }} of {{ p.count }} entries
</div>
</div> </div>
{% include 'paginator.html' %} {% include 'paginator.html' %}
</div> </div>
@ -89,29 +82,41 @@
</div> </div>
</div> </div>
</div> </div>
{% endblock %}
{% block self_footer_js %}
<script> <script>
function del(form) { $(document).ready(function(){
var checkboxes = document.getElementById(form); $('.group_del').click(function(){
var id_list = {}; var row = $(this).closest('tr');
var j = 0; if (confirm('确定删除')) {
for (var i = 0; i < checkboxes.elements.length; i++) { $.get(
if (checkboxes.elements[i].type == "checkbox" && checkboxes.elements[i].checked == true && checkboxes.elements[i].value != "checkall") { $(this).attr('value'),
id_list[j] = checkboxes.elements[i].value; {},
j++; function (data) {
row.remove();
} }
} )
if (confirm("确定删除")) {
$.ajax({
type: "POST",
url: "/jasset/group_del/?id=multi",
data: {"id_list": id_list, "len_list": j},
success: function (data) {
window.open("/jasset/group_list/", "_self");
} }
}); });
$('#del_check').click(function(){
var check_array = [];
if (confirm('确定删除')){
$('tr.gradeX input:checked').each(function(){
check_array.push($(this).attr('value'))
});
$.get(
'{% url "asset_group_del" %}',
{id: check_array.join(',')},
function(data){
$('tr.gradeX input:checked').closest('tr').remove();
} }
)
} }
})
});
</script> </script>
{% endblock %} {% endblock %}

View File

@ -1,207 +0,0 @@
{% extends 'base.html' %}
{% load mytags %}
{% block content %}
{% include 'nav_cat_bar.html' %}
<div class="wrapper wrapper-content animated fadeInRight">
<div class="row">
<div class="col-lg-10">
<div class="ibox float-e-margins">
<div id="ibox-content" class="ibox-title">
<h5> 填写主机基本信息 </h5>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
</a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i>
</a>
<ul class="dropdown-menu dropdown-user">
<li><a href="#">未启用 1</a>
</li>
<li><a href="#">未启用 2</a>
</li>
</ul>
<a class="close-link">
<i class="fa fa-times"></i>
</a>
</div>
</div>
<div class="ibox-content">
<div class="panel blank-panel">
<div class="panel-options">
<ul class="nav nav-tabs">
<li class="active"><a href="/jasset/host_add/" class="text-center"><i class="fa fa-laptop"></i> 单台添加 </a></li>
<li><a href="/jasset/host_add_multi" class="text-center"><i class="fa fa-bar-chart-o"></i> 批量添加 </a></li>
</ul>
</div>
<div class="panel-body">
<div class="tab-content">
<div id="tab-1" class="ibox float-e-margins tab-pane active">
{% if emg %}
<div class="alert alert-warning text-center">{{ emg }}</div>
{% endif %}
{% if smg %}
<div class="alert alert-success text-center">{{ smg }}</div>
{% endif %}
<form id="assetForm" method="post" class="form-horizontal">
<div class="form-group"><label class="col-sm-2 control-label"> IP地址<span class="red-fonts">*</span> </label>
<div class="col-sm-8"><input type="text" name="j_ip" placeholder="192.168.1.1" class="form-control"></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"><input type="text" placeholder="22" name="j_port" class="form-control"></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">
<div class="radio i-checks"><label> <input type="radio" id="L" checked="" value="L" name="j_type" onclick="show(this)"> <i> LDAP </i></label></div>
<div class="radio i-checks"><label> <input type="radio" id="M" value="M" name="j_type" onclick="show(this)"> <i> MAP </i></label></div>
</div>
<div name="a1" id=a1 style="display:none;">
<div class="form-group"><label class="col-sm-2 col-sm-offset-1 control-label"> 普通用户名 </label>
<div class="col-sm-6"><input type="text" name="j_user" placeholder="lilei" class="form-control"></div>
</div>
<div class="form-group"><label class="col-sm-2 col-sm-offset-1 control-label"> 普通用户密码 </label>
<div class="col-sm-6"><input type="password" name="j_password" placeholder="Password" class="form-control"></div>
</div>
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="j_idc" class="col-lg-2 control-label"> 所属IDC<span class="red-fonts">*</span> </label>
<div class="col-sm-8">
<select id="j_idc" name="j_idc" class="form-control m-b">
{% for i in eidc %}
<option value="{{i.id}}"> {{ i }} </option>
{% endfor %}
</select>
</div>
</div>
{% ifequal session_role_id 2 %}
<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>
<div class="col-sm-8">
<select id="j_dept" name="j_dept" class="form-control m-b" multiple size="10">
{% for d in edept %}
<option type="checkbox" value="{{ d.id }}">{{ d.name }} {% if d.comment %} --- {{ d.comment }} {% endif %}</option>
{% endfor %}
</select>
</div>
</div>
{% endifequal %}
{% ifequal session_role_id 1 %}
<div class="hr-line-dashed"></div>
<div class="form-group"><label class="col-sm-2 control-label"> 所属部门 <span class="red-fonts">*</span></label>
<input type="text" name="j_dept" value="{{ dept.id }}" style="display: none">
<div class="col-sm-8"><input type="text" value="{{ dept.name }}" class="form-control" readonly="readonly"></div>
</div>
{% endifequal %}
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="j_group" class="col-lg-2 control-label">所属主机组</label>
<div class="col-sm-8">
<select id="j_group" name="j_group" class="form-control m-b" multiple size="10">
{% for g in egroup %}
<option type="checkbox" value="{{ g.id }}">{{ g.name }} {% if g.comment %} --- {{ g.comment }} {% endif %}</option>
{% endfor %}
</select>
</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">
<div class="radio i-checks"><label> <input type="radio" checked="" value="1" name="j_active"> <i> 激活 </i></label></div>
<div class="radio i-checks"><label> <input type="radio" value="0" name="j_active"> <i> 禁用 </i></label></div>
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group"><label class="col-sm-2 control-label"> 备注 </label>
<div class="col-sm-8"><input type="text" placeholder="hadoop01" name="j_comment" class="form-control"></div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<div class="col-sm-4 col-sm-offset-5">
<button class="btn btn-white" type="submit"> 重置 </button>
<button class="btn btn-primary" type="submit"> 提交 </button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
var showFlag={};
function show(o){
showFlag[o.name]=o.value;
if(showFlag.j_type=="M"){
document.getElementById("a1").style.display="";
}
else{
document.getElementById("a1").style.display="none";
}};
$('#assetForm').validator({
timely: 2,
theme: "yellow_right_effect",
rules: {
check_ip: [/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])(\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])){3}$/, 'ip地址不正确'],
check_port: [/^\d{1,5}$/, '端口号不正确'],
type_m: function(element){
return $("#M").is(":checked");
}
},
fields: {
"j_ip": {
rule: "required;check_ip",
tip: "输入IP",
ok: "",
msg: {required: "必须填写!"}
},
"j_port": {
rule: "required;check_port",
tip: "输入端口号",
ok: "",
msg: {required: "必须填写!"}
},
"j_idc": {
rule: "required",
tip: "选择IDC",
ok: "",
msg: {checked: "必须填写!"}
},
"j_dept": {
rule: "required",
tip: "选择部门",
ok: "",
msg: {checked: "至少选择一个部门"}
}
},
valid: function(form) {
form.submit();
}
});
</script>
{% endblock %}

View File

@ -1,68 +0,0 @@
{% extends 'base.html' %}
{% block content %}
{% include 'nav_cat_bar.html' %}
<div class="wrapper wrapper-content animated fadeInRight">
<div class="row">
<div class="col-lg-10">
<div class="ibox float-e-margins">
<div id="ibox-content" class="ibox-title">
<h5> 填写主机基本信息 </h5>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
</a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i>
</a>
<ul class="dropdown-menu dropdown-user">
<li><a href="#">未启用 1</a>
</li>
<li><a href="#">未启用 2</a>
</li>
</ul>
<a class="close-link">
<i class="fa fa-times"></i>
</a>
</div>
</div>
<div class="ibox-content">
<div class="panel blank-panel">
<div class="panel-options">
<ul class="nav nav-tabs">
<li><a href="/jasset/host_add/" class="text-center"><i class="fa fa-laptop"></i> 单台添加 </a></li>
<li class="active"><a href="/jasset/host_add_multi/" class="text-center"><i class="fa fa-bar-chart-o"></i> 批量添加 </a></li>
</ul>
</div>
<div class="panel-body">
<div id="tab-2" class="ibox float-e-margins tab-pane active">
{% if emg %}
<div class="alert alert-warning text-center">{{ emg }}</div>
{% endif %}
{% if smg %}
<div class="alert alert-success text-center">{{ smg }}</div>
{% endif %}
<p>请严格按照文本框内主机信息格式填写, 多台主机回车换行, 具体格式如下: </p>
<p class="text-info">IP地址 端口号 登录方式 IDC名 所属主机组 所属部门 激活/禁用 备注 </p>
<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 北京联通 [网站,数据库] 运维部 激活 网站服务器" class="form-control" style="width:700px;height:500px">192.168.1.1 22 LDAP 北京联通 ['网站','数据库'] ['运维部','测试部'] 激活 网站服务器</textarea></div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<div class="col-sm-4 col-sm-offset-4">
<button class="btn btn-white" type="submit"> 重置 </button>
<button class="btn btn-primary" type="submit"> 提交 </button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -1,221 +0,0 @@
{% extends 'base.html' %}
{% load mytags %}
{% block content %}
{% include 'nav_cat_bar.html' %}
<div class="wrapper wrapper-content animated fadeInRight">
<div class="row">
<div class="col-lg-4">
<div class="ibox float-e-margins">
<div class="ibox-title">
<span class="text text-primary"><b>{{ post.ip }}</b></span>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
</a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i>
</a>
<ul class="dropdown-menu dropdown-user">
</ul>
<a class="close-link">
<i class="fa fa-times"></i>
</a>
</div>
</div>
<div class="ibox-content ibox-heading">
<h3>主机详细信息</h3>
<small><i class="fa fa-map-marker"></i> 此主机详细信息.</small>
</div>
<div class="ibox-content">
<div>
<div class="text-left">
<table class="table">
<tr>
<td class="text-navy">IP</td>
<td>{{ post.ip }}</td>
</tr>
<tr>
<td class="text-navy">端口</td>
<td>{{ post.port }}</td>
</tr>
<tr>
<td class="text-navy">登录方式</td>
<td>{{ post.login_type|get_login_type }}</td>
</tr>
<tr>
<td class="text-navy">IDC</td>
<td>{{ post.idc.name }} </td>
</tr>
<tr>
<td class="text-navy">部门</td>
<td>
<table class="table">
{% for dept in post.dept.all %}
<tr>
<td>{{ dept.name }}</td>
</tr>
{% endfor %}
</table>
</td>
</tr>
<tr>
<td class="text-navy">主机组</td>
<td>
<table class="table">
{% for group in post.bis_group.all %}
<tr>
<td>{{ group.name }}</td>
</tr>
{% endfor %}
</table>
</td>
</tr>
<tr>
<td class="text-navy">激活</td>
<td>{{ post.is_active|bool2str }}</td>
</tr>
<tr>
<td class="text-navy">添加日期</td>
<td>{{ post.date_added|date:"Y-m-d H:i:s" }}</td>
</tr>
<tr>
<td class="text-navy">备注</td>
<td>{{ post.comment }}</td>
</tr>
</table>
</div>
</div>
</div>
</div>
</div>
<div class="col-lg-4">
<div class="ibox float-e-margins">
<div class="ibox-title">
<h5>拥有权限的用户</h5>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
</a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i>
</a>
<ul class="dropdown-menu dropdown-user">
</ul>
<a class="close-link">
<i class="fa fa-times"></i>
</a>
</div>
</div>
<div class="ibox-content ibox-heading">
<h3>主机所有授权的用户</h3>
<small><i class="fa fa-map-marker"></i> 包含了此主机所有授权的用户.</small>
</div>
<div class="ibox-content">
<div>
<div class="text-left">
<table class="table">
{% if user_permed_list %}
{% for user in user_permed_list %}
<tr>
<td class="text-navy">{{ user.name }}</td>
<td>{{ user.dept.name }}</td>
<td><a href="/juser/user_detail/?id={{ user.id }}">详情</a></td>
</tr>
{% endfor %}
{% else %}
<p class="text-center">(暂无)</p>
{% endif %}
</table>
</div>
</div>
</div>
</div>
</div>
<div class="col-lg-4">
<div class="ibox float-e-margins">
<div class="ibox-title">
<h5>最近一周登录记录</h5>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
</a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i>
</a>
<ul class="dropdown-menu dropdown-user">
</ul>
<a class="close-link">
<i class="fa fa-times"></i>
</a>
</div>
</div>
<div class="ibox-content ibox-heading">
<h3>最近一周登录记录</h3>
<small><i class="fa fa-map-marker"></i> 此主机最近一周用户登录信息.</small>
</div>
<div class="ibox-content inspinia-timeline">
{% if log %}
{% for l in log %}
<div class="timeline-item">
<div class="row">
<div class="col-xs-5 date">
<i class="fa fa-info-circle"></i>
<small class="text-navy">{{ l.user }}</small>
<br/>
<strong>{{l.dept_name}}</strong>
</div>
<div class="col-xs-7 content no-top-border">
<p class="m-b-xs"><strong>详细信息</strong></p>
<p>来源IP: {{ l.remote_ip }}</p>
<p>开始: {{ l.start_time |date:"Y-m-d H:i:s" }}</p>
<p>结束: {{ l.end_time |date:"Y-m-d H:i:s" }}</p>
</div>
</div>
</div>
{% endfor %}
<button id="show" class="btn btn-primary btn-block m-t"><i class="fa fa-arrow-down"></i> 所有 </button>
<div id='more' style="display: none">
<br/>
{% for l in log_more %}
<div class="timeline-item">
<div class="row">
<div class="col-xs-5 date">
<i class="fa fa-info-circle"></i>
<small class="text-navy">{{ l.user }}</small>
<br/>
<strong>{{l.dept_name}}</strong>
</div>
<div class="col-xs-7 content no-top-border">
<p class="m-b-xs"><strong>详细信息</strong></p>
<p>来源IP: {{ l.remote_ip }}</p>
<p>开始: {{ l.start_time |date:"Y-m-d H:i:s" }}</p>
<p>结束: {{ l.end_time |date:"Y-m-d H:i:s" }}</p>
</div>
</div>
</div>
{% endfor %}
{% else %}
<p class="text-center">(暂无)</p>
{% endif %}
</div>
</div>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function(){
$('#show').click(function(){
$('#show').css('display', 'none');
$('#more').css('display', 'block');
})
})
</script>
{% endblock %}

View File

@ -1,228 +0,0 @@
{% extends 'base.html' %}
{% load mytags %}
{% block content %}
{% include 'nav_cat_bar.html' %}
<div class="wrapper wrapper-content animated fadeInRight">
<div class="row">
<div class="col-lg-10">
<div class="ibox float-e-margins">
<div id="ibox-content" class="ibox-title">
<h5> 填写主机基本信息 </h5>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
</a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i>
</a>
<ul class="dropdown-menu dropdown-user">
<li><a href="#">未启用 1</a>
</li>
<li><a href="#">未启用 2</a>
</li>
</ul>
<a class="close-link">
<i class="fa fa-times"></i>
</a>
</div>
</div>
<div class="ibox-content">
{% if emg %}
<div class="alert alert-warning text-center">{{ emg }}</div>
{% endif %}
{% if smg %}
<div class="alert alert-success text-center">{{ smg }}</div>
{% endif %}
<form id="assetForm" method="post" class="form-horizontal" autocomplete="off">
<div class="form-group"><label class="col-sm-2 control-label"> IP地址<span class="red-fonts">*</span> </label>
<div class="col-sm-8"><input type="text" name="j_ip" value="{{ post.ip }}" placeholder="192.168.1.1" class="form-control"></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"><input type="text" placeholder="22" name="j_port" value="{{ post.port }}" class="form-control"></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">
{% for t, type in login_types.items %}
{% ifequal t post.login_type %}
<div class="radio i-checks"><label> <input type="radio" checked="" value="{{ t }}" name="j_type" onclick="show(this)"> <i> {{ type }} </i></label></div>
{% else %}
<div class="radio i-checks"><label> <input type="radio" value="{{ t }}" name="j_type" onclick="show(this)"> <i> {{ type }} </i></label></div>
{% endifequal %}
{% endfor %}
</div>
{% ifequal post.login_type 'M' %}
<div name="type" id="type">
<div class="form-group"><label class="col-sm-2 col-sm-offset-1 control-label"> 普通用户名 </label>
<div class="col-sm-6"><input type="text" name="j_user" value="{{ post.username }}" class="form-control"></div>
</div>
<div class="form-group"><label class="col-sm-2 col-sm-offset-1 control-label"> 普通用户密码 </label>
<div class="col-sm-6"><input type="password" name="j_password" value="{{ post.password }}" class="form-control"></div>
</div>
</div>
{% endifequal %}
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="j_idc" class="col-lg-2 control-label"> 所属IDC<span class="red-fonts">*</span> </label>
<div class="col-sm-8">
<select id="j_idc" name="j_idc" class="form-control m-b">
{% for i in eidc %}
{% ifequal i.id post.idc_id %}
<option value="{{i.id}}" selected> {{ i }} </option>
{% else %}
<option value="{{i.id}}"> {{ i }} </option>
{% endifequal %}
{% endfor %}
</select>
</div>
</div>
{% ifequal session_role_id 2 %}
<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>
<div class="col-sm-8">
<select id="j_dept" name="j_dept" class="form-control m-b" multiple size="10">
{% for d in edept %}
{% if d in e_dept %}
<option type="checkbox" selected value="{{ d.id }}">{{ d.name }} {% if d.comment %} --- {{ d.comment }} {% endif %}</option>
{% else %}
<option type="checkbox" value="{{ d.id }}">{{ d.name }} {% if d.comment %} --- {{ d.comment }} {% endif %}</option>
{% endif %}
{% endfor %}
</select>
</div>
</div>
{% endifequal %}
{% ifequal session_role_id 1 %}
<div class="hr-line-dashed"></div>
<div class="form-group"><label class="col-sm-2 control-label"> 所属部门<span class="red-fonts">*</span> </label>
<input type="text" name="j_dept" value="{{ dept.id }}" style="display: none">
<div class="col-sm-8"><input type="text" value="{{ dept.name }}" class="form-control" readonly="readonly"></div>
</div>
{% endifequal %}
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="j_group" class="col-lg-2 control-label"> 所属主机组</label>
<div class="col-sm-8">
<select id="j_group" name="j_group" class="form-control m-b" multiple size="10">
{% for g in egroup %}
{% if g in e_group %}
<option type="checkbox" value="{{ g.id }}" selected>{{ g.name }} {% if g.comment %} --- {{ g.comment }} {% endif %}</option>
{% else %}
<option type="checkbox" value="{{ g.id }}" >{{ g.name }} {% if g.comment %} --- {{ g.comment }} {% endif %}</option>
{% endif %}
{% endfor %}
</select>
</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">
{% for a,active in actives.items %}
{% ifequal a post.is_active %}
<div class="radio i-checks"><label> <input type="radio" checked value="{{ a }}" name="j_active"> <i> {{ active }} </i></label></div>
{% else %}
<div class="radio i-checks"><label> <input type="radio" value="{{ a }}" name="j_active"> <i> {{ active }} </i></label></div>
{% endifequal %}
{% endfor %}
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group"><label class="col-sm-2 control-label"> 备注 </label>
<div class="col-sm-8"><input type="text" placeholder="hadoop01" value="{{ post.comment }}" name="j_comment" class="form-control"></div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<div class="col-sm-4 col-sm-offset-5">
<button class="btn btn-white" type="submit"> 重置 </button>
<button class="btn btn-primary" type="submit" style="display: i"> 提交 </button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
<script>
var showFlag={};
function show(o){
showFlag[o.name]=o.value;
if(showFlag.j_type=="M"){
document.getElementById("type").style.display="";
}
else{
document.getElementById("type").style.display="none";
}};
$('#assetForm').validator({
timely: 2,
theme: "yellow_right_effect",
rules: {
check_ip: [/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])(\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])){3}$/, 'ip地址不正确'],
check_port: [/^\d{1,5}$/, '端口号不正确'],
type_m: function(element){
return $("#M").is(":checked");
}
},
fields: {
"j_ip": {
rule: "required;check_ip",
tip: "输入IP",
ok: "",
msg: {required: "必须填写!"}
},
"j_port": {
rule: "required;check_port",
tip: "输入端口号",
ok: "",
msg: {required: "必须填写!"}
},
"j_idc": {
rule: "required",
tip: "选择IDC",
ok: "",
msg: {checked: "必须填写!"}
},
"j_dept": {
rule: "required",
tip: "选择部门",
ok: "",
msg: {checked: "至少选择一个部门"}
},
"j_user": {
rule: "required(type_m)",
tip: "普通用户名",
ok: "",
msg: {required: "请填写用户名"}
},
"j_password": {
rule: "required(type_m);length[6~100]",
tip: "密码6-16位",
ok: "",
msg: {required: "6-16位"}
}
},
valid: function(form) {
form.submit();
}
});
</script>
{% endblock %}

View File

@ -1,192 +0,0 @@
{% extends 'base.html' %}
{% load mytags %}
{% block content %}
{% include 'nav_cat_bar.html' %}
<div class="wrapper wrapper-content animated fadeInRight">
<div class="row">
<div class="col-lg-12">
<div class="ibox float-e-margins" id="all">
<div class="ibox-title">
<h5> 主机详细信息列表</h5>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
</a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i>
</a>
<ul class="dropdown-menu dropdown-user">
<li><a href="#">未启用 1</a>
</li>
<li><a href="#">未启用 2</a>
</li>
</ul>
<a class="close-link">
<i class="fa fa-times"></i>
</a>
</div>
</div>
<div class="ibox-content">
<div>
<a target="_blank" href="/jasset/host_add" class="btn btn-sm btn-primary "> 添加 </a>
<form id="search_form" method="get" action="" class="pull-right mail-search">
<div class="input-group">
<input type="text" class="form-control input-sm" id="search_input" name="keyword" placeholder="Search">
<input type="text" style="display: none">
<div class="input-group-btn">
<button id='search_btn' type="button" class="btn btn-sm btn-primary" onclick="host_search()">
Search
</button>
</div>
</div>
</form>
</div>
<form id="contents_form" name="contents_form">
<table class="table table-striped table-bordered table-hover " id="editable" name="editable">
<thead>
<tr>
<th class="text-center"><input id="checkall" type="checkbox" class="i-checks" name="checkall" value="checkall" data-editable='false' onclick="check_all('contents_form')"></th>
<th class="text-center" name="j_ip"> IP地址 </th>
<th class="text-center"> 端口号 </th>
<th class="text-center" name="j_type"> 登录方式 </th>
<th class="text-center" name="j_idc"> 所属IDC </th>
<th class="text-center"> 所属部门 </th>
<th class="text-center"> 所属主机组 </th>
<th class="text-center"> 是否激活 </th>
<th class="text-center" name="j_comment"> 备注 </th>
<th class="text-center"> 操作 </th>
</tr>
</thead>
<tbody>
{% for post in contacts.object_list %}
<tr class="gradeX">
<td class="text-center" name="j_id" value="{{ post.id }}" data-editable='false'><input name="id" value="{{ post.id }}" type="checkbox" class="i-checks"></td>
<td class="text-center" name="j_ip"> {{ post.ip }} </td>
<td class="text-center" name="j_port"> {{ post.port }} </td>
<td class="text-center" name="j_type"> {{ post.login_type|get_login_type }} </td>
<td class="text-center" name="j_idc"> {{ post.idc.name }} </td>
<td class="text-center" name="j_dept">{{ post.dept.all | group_str2 }}</td>
<!--<td class="text-center" id="j_dept_{{post.id}}" name="j_dept" onclick="show_all('dept', '{{post.id}}')">{{ post.dept.all | group_str2 }}</td>-->
<td class="text-center" name="j_group">{{ post.bis_group.all | group_str2_all }}</td>
<!--<td class="text-center" id="j_group_{{post.id}}" name="j_group" onclick="show_all('group', '{{post.id}}')">{{ post.bis_group.all | group_str2_all }}</td>-->
<td class="text-center" name="j_active"> {{ post.is_active|bool2str }} </td>
<td class="text-center" name="j_comment"> {{ post.comment }} </td>
<td class="text-center" data-editable='false'>
<a href="/jasset/host_detail/?id={{ post.id }}" class="btn btn-xs btn-primary">详情</a>
{% ifnotequal session_role_id 0 %}
<a href="/jasset/host_edit/?id={{ post.id }}" class="btn btn-xs btn-info">编辑</a>
<a href="/jasset/host_del/{{ post.id }}" class="btn btn-xs btn-danger">删除</a>
{% endifnotequal %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="row">
<div class="col-sm-6">
<input type="button" id="del_button" class="btn btn-danger btn-sm" name="del_button" value="删除" onclick="del('contents_form')" />
<input type="button" id="alter_button" class="btn btn-warning btn-sm" name="alter_button" value="修改" onclick="alter('contents_form')" />
</div>
{% include 'paginator.html' %}
</div>
</form>
</div>
</div>
</div>
</div>
</div>
<script>
$('table td').on('change', function(env, id){
var url = "/jasset/show_all_ajax/?env=" + env + "&id=" + id;
console.log(url);
$.ajax({
type: "GET",
url: url,
// data: $("#search_form").serialize(),
success: function (data) {
$("#j_dept_"+id).html(data);
}
});
})
$(document).ready(function(){
$('#editable').editableTableWidget({editor: $('<textarea>')});
});
function alter(form) {
selectData = GetTableDataBox();
console.log(selectData[0])
if (selectData[1] != 0) {
$.ajax({
type: "post",
url: "/jasset/host_edit/batch/",
data: {"editable": selectData[0], "len_table": selectData[1]},
success: function (data) {
alert("修改成功");
window.open("/jasset/host_list/", "_self");
error: window.open("/jasset/host_list/", "_self");
}
});
}
}
function del(form) {
var checkboxes = document.getElementById(form);
var id_list = {};
var j = 0;
for (var i = 0; i < checkboxes.elements.length; i++) {
if (checkboxes.elements[i].type == "checkbox" && checkboxes.elements[i].checked == true && checkboxes.elements[i].value != "checkall") {
id_list[j] = checkboxes.elements[i].value;
j++;
}
}
if (confirm("确定删除")) {
$.ajax({
type: "POST",
url: "/jasset/host_del/multi/",
data: {"id_list": id_list, "len_list": j},
success: function (data) {
window.open("/jasset/host_list/", "_self");
}
});
}
}
function host_search(){
$.ajax({
type: "GET",
url: "/jasset/search/",
data: $("#search_form").serialize(),
success: function (data) {
$("#contents_form").html(data);
}
});
}
$("#search_input").keydown(function(e){
if(e.keyCode==13){
host_search()
}
})
function show_all(env, id) {
var url = "/jasset/show_all_ajax/?env=" + env + "&id=" + id;
console.log(url);
$.ajax({
type: "GET",
url: url,
// data: $("#search_form").serialize(),
success: function (data) {
$("#j_group_" + id).html(data);
}
});
}
</script>
{% endblock %}

View File

@ -1,172 +0,0 @@
{% extends 'base.html' %}
{% load mytags %}
{% block content %}
{% include 'nav_cat_bar.html' %}
<div class="wrapper wrapper-content animated fadeInRight">
<div class="row">
<div class="col-lg-12">
<div class="ibox float-e-margins" id="all">
<div class="ibox-title">
<h5> 主机详细信息列表</h5>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
</a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i>
</a>
<ul class="dropdown-menu dropdown-user">
<li><a href="#">未启用 1</a>
</li>
<li><a href="#">未启用 2</a>
</li>
</ul>
<a class="close-link">
<i class="fa fa-times"></i>
</a>
</div>
</div>
<div class="ibox-content">
<div>
<span>点击别名栏修改主机别名, 可在跳板机上使用别名直接登录.</span>
<form id="search_form" method="get" action="" class="pull-right mail-search">
<div class="input-group">
<input type="text" class="form-control input-sm" id="search_input" name="keyword" placeholder="Search">
<input type="text" style="display: none">
<div class="input-group-btn">
<button id='search_btn' type="button" class="btn btn-sm btn-primary" onclick="host_search()">
Search
</button>
</div>
</div>
</form>
</div>
<form id="contents_form" name="contents_form">
<table class="table table-striped table-bordered table-hover " id="editable" name="editable">
<thead>
<tr>
<th class="text-center"><input id="checkall" type="checkbox" class="i-checks" name="checkall" value="checkall" data-editable='false' onclick="check_all('contents_form')"></th>
<th class="text-center" name="j_ip"> IP地址 </th>
<th class="text-center"> 端口号 </th>
<th class="text-center" name="j_type"> 登录方式 </th>
<th class="text-center" name="j_idc"> 所属IDC </th>
<th class="text-center"> 所属部门 </th>
<th class="text-center"> 所属主机组 </th>
<th class="text-center"> 别名 </th>
<th class="text-center" name="j_comment"> 备注 </th>
<th class="text-center"> 操作 </th>
</tr>
</thead>
<tbody>
{% for post in contacts.object_list %}
<tr class="gradeX">
<td class="text-center" name="j_id" value="{{ post.id }}" data-editable='false'><input name="id" value="{{ post.id }}" type="checkbox" class="i-checks"></td>
<td class="text-center" data-editable='false' name="j_ip"> {{ post.ip }} </td>
<td class="text-center" data-editable='false' name="j_port"> {{ post.port }} </td>
<td class="text-center" data-editable='false' name="j_type"> {{ post.login_type|get_login_type }} </td>
<td class="text-center" data-editable='false' name="j_idc"> {{ post.idc.name }} </td>
<td class="text-center" data-editable='false' name="j_dept">{{ post.dept.all | group_str2 }}</td>
<td class="text-center" data-editable='false' name="j_group">{{ post.bis_group.all | group_str2_all }}</td>
<td class="text-center" name="j_alias"> {{ post|get_user_alias:user_id }} </td>
<td class="text-center" data-editable='false' name="j_comment"> {{ post.comment }} </td>
<td class="text-center" data-editable='false'>
<a href="/jasset/host_detail/?id={{ post.id }}" class="iframe btn btn-xs btn-primary">详情</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="row">
<div class="col-sm-6">
<input type="button" id="alter_button" class="btn btn-warning btn-sm" name="alter_button" value="修改" onclick="alter('contents_form')" />
</div>
{% include 'paginator.html' %}
</div>
</form>
</div>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function(){
$('#editable').editableTableWidget();
});
$(".iframe").on('click', function(){
var url= $(this).attr("value");
$.layer({
type: 2,
title: 'JumpServer主机详情',
maxmin: true,
shift: 'top',
border: [2, 0.3, '#1AB394'],
shade: [0.5, '#000000'],
shadeClose: true,
area : ['800px' , '600px'],
iframe: {src: url}
});
});
function alter(form) {
selectData = GetTableDataBox();
if (selectData[1] != 0) {
$.ajax({
type: "post",
url: "/jasset/host_edit_common/batch/",
data: {"editable": selectData[0], "len_table": selectData[1]},
success: function (data) {
alert("修改成功");
window.open("/jasset/host_list/", "_self");
}
});
}
}
function del(form) {
var checkboxes = document.getElementById(form);
var id_list = {};
var j = 0;
for (var i = 0; i < checkboxes.elements.length; i++) {
if (checkboxes.elements[i].type == "checkbox" && checkboxes.elements[i].checked == true && checkboxes.elements[i].value != "checkall") {
id_list[j] = checkboxes.elements[i].value;
j++;
}
}
if (confirm("确定删除")) {
$.ajax({
type: "POST",
url: "/jasset/host_del/multi/",
data: {"id_list": id_list, "len_list": j},
success: function (data) {
window.open("/jasset/host_list/", "_self");
}
});
}
}
function host_search(){
$.ajax({
type: "GET",
url: "/jasset/search/",
data: $("#search_form").serialize(),
success: function (data) {
$("#contents_form").html(data);
}
});
}
$("#search_input").keydown(function(e){
if(e.keyCode==13){
host_search()
}
})
</script>
{% endblock %}

View File

@ -1,177 +0,0 @@
{% extends 'base.html' %}
{% load mytags %}
{% block content %}
{% include 'nav_cat_bar.html' %}
<div class="wrapper wrapper-content animated fadeInRight">
<div class="row">
<div class="col-lg-12">
<div class="ibox float-e-margins" id="all">
<div class="ibox-title">
<h5> 主机详细信息列表</h5>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
</a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i>
</a>
<ul class="dropdown-menu dropdown-user">
<li><a href="#">未启用 1</a>
</li>
<li><a href="#">未启用 2</a>
</li>
</ul>
<a class="close-link">
<i class="fa fa-times"></i>
</a>
</div>
</div>
<div class="ibox-content">
<div>
<a target="_blank" href="/jasset/host_add" class="btn btn-sm btn-primary "> 添加 </a>
<!--<form id="search_form" method="get" action="" class="pull-right mail-search">-->
<!--<div class="input-group">-->
<!--<input type="text" class="form-control input-sm" id="search_input" name="keyword" placeholder="Search">-->
<!--<input type="text" style="display: none">-->
<!--<div class="input-group-btn">-->
<!--<button id='search_btn' type="button" class="btn btn-sm btn-primary" onclick="host_search()">-->
<!--Search-->
<!--</button>-->
<!--</div>-->
<!--</div>-->
<!--</form>-->
</div>
<form id="contents_form" name="contents_form">
<table class="table table-striped table-bordered table-hover " id="editable" name="editable">
<thead>
<tr>
<th class="text-center"><input id="checkall" type="checkbox" class="i-checks" name="checkall" value="checkall" data-editable='false' onclick="check_all('contents_form')"></th>
<th class="text-center" name="j_ip"> IP地址 </th>
<th class="text-center"> 端口号 </th>
<th class="text-center" name="j_type"> 登录方式 </th>
<th class="text-center" name="j_idc"> 所属IDC </th>
<th class="text-center"> 所属部门 </th>
<th class="text-center"> 所属主机组 </th>
<th class="text-center"> 是否激活 </th>
<th class="text-center" name="j_comment"> 备注 </th>
<th class="text-center"> 操作 </th>
</tr>
</thead>
<tbody>
{% for post in posts %}
<tr class="gradeX">
<td class="text-center" name="j_id" value="{{ post.id }}" data-editable='false'><input name="id" value="{{ post.id }}" type="checkbox" class="i-checks"></td>
<td class="text-center" name="j_ip"> {{ post.ip }} </td>
<td class="text-center" name="j_port"> {{ post.port }} </td>
<td class="text-center" name="j_type"> {{ post.login_type|get_login_type }} </td>
<td class="text-center" name="j_idc"> {{ post.idc.name }} </td>
<td class="text-center" name="j_dept">{{ post.dept.all | group_str2 }}</td>
<td class="text-center" name="j_group">{{ post.bis_group.all | group_str2_all }}</td>
<td class="text-center" name="j_active"> {{ post.is_active|bool2str }} </td>
<td class="text-center" name="j_comment"> {{ post.comment }} </td>
<td class="text-center" data-editable='false'>
<a value="/jasset/{{ post.ip }}/" class="iframe btn btn-xs btn-primary">详情</a>
{% ifnotequal session_role_id 0 %}
<a href="/jasset/host_edit/?id={{ post.id }}" class="btn btn-xs btn-info">编辑</a>
<a href="/jasset/host_del/{{ post.id }}" class="btn btn-xs btn-danger">删除</a>
{% endifnotequal %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="row">
<div class="col-sm-6">
<input type="button" id="del_button" class="btn btn-danger btn-sm" name="del_button" value="删除" onclick="del('contents_form')" />
<input type="button" id="alter_button" class="btn btn-warning btn-sm" name="alter_button" value="修改" onclick="alter('contents_form')" />
</div>
<!--{% include 'paginator.html' %}-->
</div>
</form>
</div>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function(){
$('#editable').editableTableWidget();
});
$(".iframe").on('click', function(){
var url= $(this).attr("value");
$.layer({
type: 2,
title: 'JumpServer主机详情',
maxmin: true,
shift: 'top',
border: [2, 0.3, '#1AB394'],
shade: [0.5, '#000000'],
shadeClose: true,
area : ['800px' , '600px'],
iframe: {src: url}
});
});
function alter(form) {
selectData = GetTableDataBox();
if (selectData[1] != 0) {
$.ajax({
type: "post",
url: "/jasset/host_edit/batch/",
data: {"editable": selectData[0], "len_table": selectData[1]},
success: function (data) {
alert("修改成功");
window.open("/jasset/host_list/", "_self");
}
});
}
}
function del(form) {
var checkboxes = document.getElementById(form);
var id_list = {};
var j = 0;
for (var i = 0; i < checkboxes.elements.length; i++) {
if (checkboxes.elements[i].type == "checkbox" && checkboxes.elements[i].checked == true && checkboxes.elements[i].value != "checkall") {
id_list[j] = checkboxes.elements[i].value;
j++;
}
}
if (confirm("确定删除")) {
$.ajax({
type: "POST",
url: "/jasset/host_del/multi/",
data: {"id_list": id_list, "len_list": j},
success: function (data) {
window.open("/jasset/host_list/", "_self");
}
});
}
}
function host_search(){
$.ajax({
type: "GET",
url: "/jasset/search/",
data: $("#search_form").serialize(),
success: function (data) {
$("#contents_form").html(data);
}
});
}
$("#search_input").keydown(function(e){
if(e.keyCode==13){
host_search()
}
})
</script>
{% endblock %}

View File

@ -1,169 +0,0 @@
{% load mytags %}
<table class="table table-striped table-bordered table-hover " id="editable" name="editable">
<thead>
<tr>
<th class="text-center"><input id="checkall" type="checkbox" class="i-checks" name="checkall" value="checkall" data-editable='false' onclick="check_all('contents_form')"></th>
<th class="text-center" name="j_ip"> IP地址 </th>
<th class="text-center"> 端口号 </th>
<th class="text-center" name="j_type"> 登录方式 </th>
<th class="text-center" name="j_idc"> 所属IDC </th>
<th class="text-center"> 所属业务组 </th>
{% ifnotequal session_role_id 0 %}
<th class="text-center"> 是否激活 </th>
{% else %}
<th class="text-center"> 别名 </th>
{% endifnotequal %}
<th class="text-center" name="j_time"> 添加时间 </th>
<th class="text-center" name="j_comment"> 备注 </th>
<th class="text-center"> 操作 </th>
</tr>
</thead>
<tbody>
{% for post in contacts.object_list %}
<tr class="gradeX">
<td class="text-center" name="j_id" value="{{ post.id }}" data-editable='false'><input name="id" value="{{ post.id }}" type="checkbox" class="i-checks"></td>
<td class="text-center" name="j_ip"> {{ post.ip }} </td>
<td class="text-center" name="j_port"> {{ post.port }} </td>
<td class="text-center" name="j_type"> {{ post.login_type|get_login_type }} </td>
<td class="text-center" name="j_idc"> {{ post.idc.name }} </td>
<td class="text-center" name="j_group">{{ post.bis_group.all | group_str2 }}</td>
{% ifnotequal session_role_id 0 %}
<td class="text-center" name="j_alias"> {{ post.is_active|bool2str }} </td>
{% else %}
<td class="text-center" name="j_active"> {{ post|get_user_alias:user_id }} </td>
{% endifnotequal %}
<td class="text-center"> {{ post.date_added|date:"Y-m-d H:i:s" }} </td>
<td class="text-center" name="j_comment"> {{ post.comment }} </td>
<td class="text-center" data-editable='false'>
<a value="/jasset/{{ post.ip }}/" class="iframe btn btn-xs btn-primary">详情</a>
{% ifnotequal session_role_id 0 %}
<a href="/jasset/host_edit/?id={{ post.id }}" class="btn btn-xs btn-info">编辑</a>
<a href="/jasset/host_del/{{ post.id }}" class="btn btn-xs btn-danger">删除</a>
{% endifnotequal %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="row">
<div class="col-sm-6">
<input type="button" id="del_button" class="btn btn-danger btn-sm" name="del_button" value="删除" onclick="del('contents_form')" />
<input type="button" id="alter_button" class="btn btn-warning btn-sm" name="alter_button" value="修改" onclick="alter('contents_form')" />
</div>
<div class="col-sm-6">
<div class="dataTables_paginate paging_simple_numbers" id="editable_paginate">
<ul class="pagination" style="margin-top: 0; float: right">
{% if contacts.has_previous %}
<li class="paginate_button previous" aria-controls="editable" tabindex="0" id="editable_previous">
<a href="?page={{ contacts.previous_page_number }}">Previous</a>
</li>
{% else %}
<li class="paginate_button previous disabled" aria-controls="editable" tabindex="0" id="editable_previous">
<a href="#">Previous</a>
</li>
{% endif %}
{% ifequal show_first 1 %}
<li class="paginate_button" aria-controls="editable" tabindex="0"><a href="?page=1" title="第1页">1...</a></li>
{% endifequal %}
{% for page in page_range %}
{% ifequal current_page page %}
<li class="paginate_button active" aria-controls="editable" tabindex="0"><a href="?keyword={{ keyword }}&page={{ page }}" title="第{{ page }}页">{{ page }}</a></li>
{% else %}
<li class="paginate_button" aria-controls="editable" tabindex="0"><a href="?keyword={{ keyword }}&page={{ page }}" title="第{{ page }}页">{{ page }}</a></li>
{% endifequal %}
{% endfor %}
{% ifequal show_end 1 %}
<li class="paginate_button" aria-controls="editable" tabindex="0"><a href="?page={{ p.num_pages }}" title="第{{ page }}页">...{{ p.num_pages }}</a></li>
{% endifequal %}
{% if contacts.has_next %}
<li class="paginate_button next" aria-controls="editable" tabindex="0" id="editable_next">
<a href="?page={{ contacts.next_page_number }}">Next</a>
</li>
{% else %}
<li class="paginate_button next disabled" aria-controls="editable" tabindex="0" id="editable_next">
<a href="#">Next</a>
</li>
{% endif %}
</ul>
</div>
</div>
</div>
<script>
$(document).ready(function(){
$('#editable').editableTableWidget();
});
$(".iframe").on('click', function(){
var url= $(this).attr("value");
$.layer({
type: 2,
title: 'JumpServer主机详情',
maxmin: true,
shift: 'top',
border: [2, 0.3, '#1AB394'],
shade: [0.5, '#000000'],
shadeClose: true,
area : ['800px' , '600px'],
iframe: {src: url}
});
});
function alter(form) {
selectData = GetTableDataBox();
if (selectData[1] != 0) {
$.ajax({
type: "post",
url: "/jasset/host_edit/batch/",
data: {"editable": selectData[0], "len_table": selectData[1]},
success: function (data) {
alert("修改成功");
window.open("/jasset/host_list/", "_self");
}
});
}
}
function del(form) {
var checkboxes = document.getElementById(form);
var id_list = {};
var j = 0;
for (var i = 0; i < checkboxes.elements.length; i++) {
if (checkboxes.elements[i].type == "checkbox" && checkboxes.elements[i].checked == true && checkboxes.elements[i].value != "checkall") {
id_list[j] = checkboxes.elements[i].value;
j++;
}
}
if (confirm("确定删除")) {
$.ajax({
type: "POST",
url: "/jasset/host_del/multi/",
data: {"id_list": id_list, "len_list": j},
success: function (data) {
window.open("/jasset/host_list/", "_self");
}
});
}
}
function host_search(){
$.ajax({
type: "GET",
url: "/jasset/search/",
data: $("#search_form").serialize(),
success: function (data) {
$("#contents_form").html(data);
}
});
}
$("#search_input").keydown(function(e){
if(e.keyCode==13){
host_search()
}
})
</script>

View File

@ -1,9 +1,10 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% block content %} {% block content %}
{% load bootstrap %}
{% 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-sm-10">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div id="ibox-content" class="ibox-title"> <div id="ibox-content" class="ibox-title">
<h5> 填写IDC基本信息 </h5> <h5> 填写IDC基本信息 </h5>
@ -15,10 +16,6 @@
<i class="fa fa-wrench"></i> <i class="fa fa-wrench"></i>
</a> </a>
<ul class="dropdown-menu dropdown-user"> <ul class="dropdown-menu dropdown-user">
<li><a href="#">未启用 1</a>
</li>
<li><a href="#">未启用 2</a>
</li>
</ul> </ul>
<a class="close-link"> <a class="close-link">
<i class="fa fa-times"></i> <i class="fa fa-times"></i>
@ -34,14 +31,28 @@
<div class="alert alert-success text-center">{{ smg }}</div> <div class="alert alert-success text-center">{{ smg }}</div>
{% endif %} {% endif %}
<form id="assetForm" method="post" class="form-horizontal"> <form id="assetForm" method="post" class="form-horizontal">
<div class="form-group"><label class="col-sm-2 control-label"> IDC名 <span class="red-fonts">*</span></label> {{ idc_form.name|bootstrap_horizontal }}
<div class="col-sm-8"><input type="text" value="{{ idc.name }}" placeholder="北京联通" name="j_idc" class="form-control"></div>
</div>
<div class="hr-line-dashed"></div> <div class="hr-line-dashed"></div>
<div class="form-group"><label class="col-sm-2 control-label"> 备注 </label> {{ idc_form.bandwidth|bootstrap_horizontal }}
<div class="col-sm-8"><input type="text" value="{{ idc.comment }}" placeholder="核心联通机房" name="j_comment" class="form-control"></div>
</div> <div class="hr-line-dashed"></div>
{{ idc_form.operator|bootstrap_horizontal }}
<div class="hr-line-dashed"></div>
{{ idc_form.linkman|bootstrap_horizontal }}
<div class="hr-line-dashed"></div>
{{ idc_form.phone|bootstrap_horizontal }}
<div class="hr-line-dashed"></div>
{{ idc_form.address|bootstrap_horizontal }}
<div class="hr-line-dashed"></div>
{{ idc_form.network|bootstrap_horizontal }}
<div class="hr-line-dashed"></div>
{{ idc_form.comment|bootstrap_horizontal }}
<div class="hr-line-dashed"></div> <div class="hr-line-dashed"></div>
<div class="form-group"> <div class="form-group">
@ -58,7 +69,12 @@
</div> </div>
<script> <script>
$('#assetForm').validator({ var required_fields = ["id_name"];
required_fields.forEach(function(field) {
$('label[for="' + field + '"]').parent().addClass("required");
});
$('#assetForm').validator({
timely: 2, timely: 2,
theme: "yellow_right_effect", theme: "yellow_right_effect",
fields: { fields: {
@ -73,7 +89,7 @@ $('#assetForm').validator({
valid: function(form) { valid: function(form) {
form.submit(); form.submit();
} }
}); });
</script> </script>
{% endblock %} {% endblock %}

View File

@ -1,211 +0,0 @@
{% extends 'base.html' %}
{% load mytags %}
{% block content %}
{% include 'nav_cat_bar.html' %}
<div class="wrapper wrapper-content animated fadeInRight">
<div class="row">
<div class="col-lg-12">
<div class="ibox float-e-margins" id="all">
<div class="ibox-title">
<h5> IDC<span class="text-info"> {{ idc.name }} </span>详细信息列表 </h5>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
</a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i>
</a>
<ul class="dropdown-menu dropdown-user">
<li><a href="#">未启用 1</a>
</li>
<li><a href="#">未启用 2</a>
</li>
</ul>
<a class="close-link">
<i class="fa fa-times"></i>
</a>
</div>
</div>
<div class="ibox-content">
{% if emg %}
<div class="alert alert-warning text-center">{{ emg }}</div>
{% endif %}
{% if smg %}
<div class="alert alert-success text-center">{{ smg }}</div>
{% endif %}
<div class="">
<a target="_blank" href="/jasset/host_add" class="btn btn-sm btn-primary "> 添加主机 </a>
</div>
<form id="contents_form" name="contents_form">
<table class="table table-striped table-bordered table-hover " id="editable" name="editable">
<thead>
<tr>
<th class="text-center"><input id="checkall" type="checkbox" class="i-checks" name="checkall" value="checkall" data-editable='false' onclick="check_all('contents_form')"></th>
<th class="text-center" name="j_ip"> IP地址 </th>
<th class="text-center"> 端口号 </th>
<th class="text-center" name="j_type"> 登录方式 </th>
<th class="text-center" id="j_group_name" value="{{ idc_name }}"> 所属IDC </th>
<th class="text-center"> 所属业务组 </th>
<th class="text-center"> 是否激活 </th>
<th class="text-center" name="j_time"> 添加时间 </th>
<th class="text-center" name="j_comment"> 备注 </th>
<th class="text-center"> 操作 </th>
</tr>
</thead>
<tbody>
{% for post in contacts.object_list %}
<tr class="gradeX">
<td class="text-center" name="j_id" value="{{ post.id }}" data-editable='false'><input name="id" value="{{ post.id }}" type="checkbox" class="i-checks"></td>
<td class="text-center" name="j_ip"> {{ post.ip }} </td>
<td class="text-center" name="j_port"> {{ post.port }} </td>
<td class="text-center" name="j_type"> {{ post.login_type|get_login_type }} </td>
<td class="text-center" name="j_idc"> {{ post.idc.name }} </td>
<td class="text-center" name="j_dept">{{ post.dept.all | group_str2 }}</td>
<td class="text-center" name="j_group">{{ post.bis_group.all | group_str2_all }}</td>
<td class="text-center" name="j_active"> {{ post.is_active|bool2str }} </td>
<td class="text-center" name="j_comment"> {{ post.comment }} </td>
<td class="text-center" data-editable='false'>
<a href="/jasset/host_detail/?id={{ post.id }}" class="btn btn-xs btn-primary">详情</a>
{% ifnotequal session_role_id 0 %}
<a href="/jasset/host_edit/?id={{ post.id }}" class="btn btn-xs btn-info">编辑</a>
<a href="/jasset/host_del/{{ post.id }}" class="btn btn-xs btn-danger">删除</a>
{% endifnotequal %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="row">
<div class="col-sm-6">
<input type="button" id="del_button" class="btn btn-danger btn-sm" name="del_button" value="删除" onclick="del('contents_form')" />
<input type="button" id="alter_button" class="btn btn-warning btn-sm" name="alter_button" value="修改" onclick="alter('contents_form')" />
</div>
<div class="col-sm-6">
<div class="dataTables_paginate paging_simple_numbers" id="editable_paginate">
<ul class="pagination" style="margin-top: 0; float: right">
{% if keyword %}
{% if contacts.has_previous %}
<li class="paginate_button previous" aria-controls="editable" tabindex="0" id="editable_previous">
<a href="?keyword={{ keyword }}&page={{ contacts.previous_page_number }}">Previous</a>
</li>
{% else %}
<li class="paginate_button previous disabled" aria-controls="editable" tabindex="0" id="editable_previous">
<a href="#">Previous</a>
</li>
{% endif %}
{% ifequal show_first 1 %}
<li class="paginate_button" aria-controls="editable" tabindex="0"><a href="?keyword={{ keyword }}&page=1&id={{ idc.id }}" title="第1页">1...</a></li>
{% endifequal %}
{% for page in page_range %}
{% ifequal current_page page %}
<li class="paginate_button active" aria-controls="editable" tabindex="0"><a href="?keyword={{ keyword }}&page={{ page }}&id={{ idc.id }}" title="第{{ page }}页">{{ page }}</a></li>
{% else %}
<li class="paginate_button" aria-controls="editable" tabindex="0"><a href="?keyword={{ keyword }}&page={{ page }}&id={{ idc.id }}" title="第{{ page }}页">{{ page }}</a></li>
{% endifequal %}
{% endfor %}
{% ifequal show_end 1 %}
<li class="paginate_button" aria-controls="editable" tabindex="0"><a href="?keyword={{ keyword }}&page={{ p.num_pages }}&id={{ idc.id }}" title="第{{ page }}页">...{{ p.num_pages }}</a></li>
{% endifequal %}
{% if contacts.has_next %}
<li class="paginate_button next" aria-controls="editable" tabindex="0" id="editable_next">
<a href="?keyword={{ keyword }}&page={{ contacts.next_page_number }}&id={{ idc.id }}">Next</a>
</li>
{% else %}
<li class="paginate_button next disabled" aria-controls="editable" tabindex="0" id="editable_next">
<a href="#">Next</a>
</li>
{% endif %}
{% else %}
{% if contacts.has_previous %}
<li class="paginate_button previous" aria-controls="editable" tabindex="0" id="editable_previous">
<a href="?page={{ contacts.previous_page_number }}&id={{ idc.id }}">Previous</a>
</li>
{% else %}
<li class="paginate_button previous disabled" aria-controls="editable" tabindex="0" id="editable_previous">
<a href="#">Previous</a>
</li>
{% endif %}
{% ifequal show_first 1 %}
<li class="paginate_button" aria-controls="editable" tabindex="0"><a href="?page=1&id={{ idc.id }}" title="第1页">1...</a></li>
{% endifequal %}
{% for page in page_range %}
{% ifequal current_page page %}
<li class="paginate_button active" aria-controls="editable" tabindex="0"><a href="?page={{ page }}&id={{ idc.id }}" title="第{{ page }}页">{{ page }}</a></li>
{% else %}
<li class="paginate_button" aria-controls="editable" tabindex="0"><a href="?page={{ page }}&id={{ idc.id }}" title="第{{ page }}页">{{ page }}</a></li>
{% endifequal %}
{% endfor %}
{% ifequal show_end 1 %}
<li class="paginate_button" aria-controls="editable" tabindex="0"><a href="?page={{ p.num_pages }}&id={{ idc.id }}" title="第{{ page }}页">...{{ p.num_pages }}</a></li>
{% endifequal %}
{% if contacts.has_next %}
<li class="paginate_button next" aria-controls="editable" tabindex="0" id="editable_next">
<a href="?page={{ contacts.next_page_number }}&id={{ idc.id }}">Next</a>
</li>
{% else %}
<li class="paginate_button next disabled" aria-controls="editable" tabindex="0" id="editable_next">
<a href="#">Next</a>
</li>
{% endif %}
{% endif %}
</ul>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function(){
$('#editable').editableTableWidget();
});
function alter(form) {
selectData = GetTableDataBox();
if (selectData[1] != 0) {
$.ajax({
type: "post",
url: "/jasset/host_edit/batch/",
data: {"editable": selectData[0], "len_table": selectData[1]},
success: function (data) {
alert("修改成功");
window.open("/jasset/host_list/", "_self");
}
});
}
}
function del(form) {
var checkboxes = document.getElementById(form);
var id_list = {};
var group_name = $('#j_group_name').attr("value");
console.log(group_name);
var j = 0;
for (var i = 0; i < checkboxes.elements.length; i++) {
if (checkboxes.elements[i].type == "checkbox" && checkboxes.elements[i].checked == true && checkboxes.elements[i].value != "checkall") {
id_list[j] = checkboxes.elements[i].value;
j++;
}
}
if (confirm("确定从该IDC中删除")) {
$.ajax({
type: "POST",
url: "/jasset/host_del/multi/",
data: {"id_list": id_list, "len_list": j, "group_name": group_name},
success: function (data) {
window.open(window.location.href, "_self");
}
});
}
}
</script>
{% endblock %}

View File

@ -1,9 +1,10 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% block content %} {% block content %}
{% load bootstrap %}
{% 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-sm-10">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div id="ibox-content" class="ibox-title"> <div id="ibox-content" class="ibox-title">
<h5> 填写IDC基本信息 </h5> <h5> 填写IDC基本信息 </h5>
@ -34,44 +35,28 @@
<div class="alert alert-success text-center">{{ smg }}</div> <div class="alert alert-success text-center">{{ smg }}</div>
{% endif %} {% endif %}
<form id="assetForm" method="post" class="form-horizontal"> <form id="assetForm" method="post" class="form-horizontal">
<div class="form-group"><label class="col-sm-2 control-label"> IDC名 <span class="red-fonts">*</span></label> {{ idc_form.name|bootstrap_horizontal }}
<div class="col-sm-8">
<input name="id" type="text" value="{{ idc.id }}" style="display: none;">
<input type="text" value="{{ idc.name }}" placeholder="北京联通" name="j_idc" class="form-control">
</div>
</div>
<div class="hr-line-dashed"></div> <div class="hr-line-dashed"></div>
<div class="form-group"><label class="col-sm-2 control-label"> 备注 </label> {{ idc_form.bandwidth|bootstrap_horizontal }}
<div class="col-sm-8"><input type="text" value="{{ idc.comment }}" placeholder="核心联通机房" name="j_comment" class="form-control"></div>
</div>
<div class="hr-line-dashed"></div> <div class="hr-line-dashed"></div>
<div class="form-group"> {{ idc_form.operator|bootstrap_horizontal }}
<label for="groups" class="col-lg-2 control-label">主机</label>
<div class="col-sm-3"> <div class="hr-line-dashed"></div>
<select id="groups" name="idc_default" size="12" class="form-control m-b" multiple> {{ idc_form.linkman|bootstrap_horizontal }}
{% for post in posts %}
<option value="{{ post.id }}">{{ post.ip }}</option> <div class="hr-line-dashed"></div>
{% endfor %} {{ idc_form.phone|bootstrap_horizontal }}
</select>
</div> <div class="hr-line-dashed"></div>
<div class="col-sm-1"> {{ idc_form.address|bootstrap_horizontal }}
<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> <div class="hr-line-dashed"></div>
<button type="button" class="btn btn-white" onclick="move_left('groups_selected', 'groups')"><i class="fa fa-chevron-left"></i> </button> {{ idc_form.network|bootstrap_horizontal }}
</div>
</div> <div class="hr-line-dashed"></div>
<div class="col-sm-3"> {{ idc_form.comment|bootstrap_horizontal }}
<div>
<select id="groups_selected" name="j_hosts" class="form-control m-b" size="12" multiple>
{% for post in eposts %}
<option value="{{ post.id }}">{{ post.ip }}</option>
{% endfor %}
</select>
</div>
</div>
</div>
<div class="hr-line-dashed"></div> <div class="hr-line-dashed"></div>
<div class="form-group"> <div class="form-group">
@ -88,7 +73,12 @@
</div> </div>
<script> <script>
$('#assetForm').validator({ var required_fields = ["id_name"];
required_fields.forEach(function(field) {
$('label[for="' + field + '"]').parent().addClass("required");
});
$('#assetForm').validator({
timely: 2, timely: 2,
theme: "yellow_right_effect", theme: "yellow_right_effect",
fields: { fields: {
@ -103,7 +93,7 @@ $('#assetForm').validator({
valid: function(form) { valid: function(form) {
form.submit(); form.submit();
} }
}); });
</script> </script>
{% endblock %} {% endblock %}

View File

@ -5,7 +5,7 @@
<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-sm-10">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div class="ibox-title"> <div class="ibox-title">
<h5> IDC详细信息列表</h5> <h5> IDC详细信息列表</h5>
@ -17,10 +17,6 @@
<i class="fa fa-wrench"></i> <i class="fa fa-wrench"></i>
</a> </a>
<ul class="dropdown-menu dropdown-user"> <ul class="dropdown-menu dropdown-user">
<li><a href="#">未启用 1</a>
</li>
<li><a href="#">未启用 2</a>
</li>
</ul> </ul>
<a class="close-link"> <a class="close-link">
<i class="fa fa-times"></i> <i class="fa fa-times"></i>
@ -29,9 +25,8 @@
</div> </div>
<div class="ibox-content"> <div class="ibox-content">
<div class=""> <div class="">
{% ifequal session_role_id 2 %} <a href="{% url 'idc_add' %}" class="btn btn-sm btn-primary "> 添加机房 </a>
<a target="_blank" href="/jasset/idc_add" class="btn btn-sm btn-primary "> 添加IDC </a> <input type="button" id="del_check" class="btn btn-danger btn-sm" name="del_button" value="删除所选"/>
{% endifequal %}
<form id="search_form" method="get" action="" class="pull-right mail-search"> <form id="search_form" method="get" action="" class="pull-right mail-search">
<div class="input-group"> <div class="input-group">
<input type="text" class="form-control input-sm" id="search_input" name="keyword" placeholder="Search"> <input type="text" class="form-control input-sm" id="search_input" name="keyword" placeholder="Search">
@ -54,6 +49,8 @@
{% endifequal %} {% endifequal %}
<th class="text-center"> 机房名 </th> <th class="text-center"> 机房名 </th>
<th class="text-center"> 主机数量 </th> <th class="text-center"> 主机数量 </th>
<th class="text-center"> 联系人 </th>
<th class="text-center"> 电话 </th>
<th class="text-center"> 备注 </th> <th class="text-center"> 备注 </th>
<th class="text-center"> 操作 </th> <th class="text-center"> 操作 </th>
</tr> </tr>
@ -61,22 +58,16 @@
<tbody> <tbody>
{% for post in contacts.object_list %} {% for post in contacts.object_list %}
<tr class="gradeX"> <tr class="gradeX">
{% ifequal session_role_id 2 %}
<td class="text-center" name="j_id" value="{{ post.id }}" data-editable='false'><input name="id" value="{{ post.id }}" type="checkbox" class="i-checks"></td> <td class="text-center" name="j_id" value="{{ post.id }}" data-editable='false'><input name="id" value="{{ post.id }}" type="checkbox" class="i-checks"></td>
{% endifequal %} <td class="text-center"> <a href="{% url 'asset_list' %}?idc_id={{ post.id }}">{{ post.name }}</a> </td>
<td class="text-center"> {{ post.name }} </td> <td class="text-center"> <a href="{% url 'asset_list' %}?idc_id={{ post.id }}">{{ post.asset_set.count }}</a> </td>
{% ifequal session_role_id 2 %} <td class="text-center"> {{ post.linkman }} </td>
<td class="text-center"> <a href="/jasset/idc_detail/?id={{ post.id }}">{{ post.asset_set.count }}</a> </td> <td class="text-center"> {{ post.phone }} </td>
{% else %}
<td class="text-center"> <a href="/jasset/idc_detail/?id={{ post.id }}">{{ post|get_idc_count:dept }}</a> </td>
{% endifequal %}
<td class="text-center"> {{ post.comment }} </td> <td class="text-center"> {{ post.comment }} </td>
<td class="text-center"> <td class="text-center">
<a href="/jasset/idc_detail/?id={{ post.id }}" class="iframe btn btn-xs btn-primary">详情</a>
{% ifequal session_role_id 2 %} <a href="{% url 'idc_edit' %}?id={{ post.id }}" class="btn btn-xs btn-info">编辑</a>
<a href="/jasset/idc_edit/?id={{ post.id }}" class="btn btn-xs btn-info">编辑</a> <a value="{% url 'idc_del' %}?id={{ post.id }}" class="btn btn-xs btn-danger idc_del">删除</a>
<a href="/jasset/idc_del/?id={{ post.id }}" class="btn btn-xs btn-danger">删除</a>
{% endifequal %}
</td> </td>
</tr> </tr>
{% endfor %} {% endfor %}
@ -84,10 +75,9 @@
</table> </table>
<div class="row"> <div class="row">
<div class="col-sm-6"> <div class="col-sm-6">
{% ifequal session_role_id 2 %} <div class="dataTables_info" id="editable_info" role="status" aria-live="polite">
<input type="button" id="del_button" class="btn btn-danger btn-sm" name="del_button" value="删除" onclick="del('contents_form')" /> Showing {{ contacts.start_index }} to {{ contacts.end_index }} of {{ p.count }} entries
<!--<input type="button" id="alter_button" class="btn btn-warning btn-sm" name="alter_button" value="修改" onclick="alter('contents_form')" />--> </div>
{% endifequal %}
</div> </div>
{% include 'paginator.html' %} {% include 'paginator.html' %}
</div> </div>
@ -97,29 +87,41 @@
</div> </div>
</div> </div>
</div> </div>
{% endblock %}
{% block self_footer_js %}
<script> <script>
function del(form) { $(document).ready(function(){
var checkboxes = document.getElementById(form); $('.idc_del').click(function(){
var id_list = {}; var row = $(this).closest('tr');
var j = 0; if (confirm('确定删除?')) {
for (var i = 0; i < checkboxes.elements.length; i++) { $.get(
if (checkboxes.elements[i].type == "checkbox" && checkboxes.elements[i].checked == true && checkboxes.elements[i].value != "checkall") { $(this).attr('value'),
id_list[j] = checkboxes.elements[i].value; {},
j++; function (data) {
row.remove();
} }
} );
if (confirm("确定删除")) { return false
$.ajax({
type: "POST",
url: "/jasset/idc_del/?id=multi",
data: {"id_list": id_list, "len_list": j},
success: function (data) {
window.open("/jasset/idc_list/", "_self");
} }
}); });
}
}
</script>
$('#del_check').click(function(){
var check_array = [];
if (confirm('确定删除?')){
$('tr.gradeX input:checked').each(function(){
check_array.push($(this).attr('value'))
});
$.get(
'{% url "idc_del" %}',
{id: check_array.join(',')},
function(data){
$('tr.gradeX input:checked').closest('tr').remove();
}
);
return false;
}
})
});
</script>
{% endblock %} {% endblock %}

View File

@ -1,10 +0,0 @@
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>资产管理</title>
</head>
<body>
<h1>welocome!</h1>
</body>
</html>

View File

@ -1,106 +0,0 @@
{% load mytags %}
<html>
<head>
{% include 'link_css.html' %}
{% include 'head_script.html' %}
<style type="text/css">
body
{
background: #FFFFFF;
}
</style>
</head>
<body>
<div class="row">
<div class="contact-box">
<h3 class="text-center">{{ offset }}主机详情</h3>
<table class="table table-striped table-bordered table-hover " id="editable" >
<thead>
<tr>
<th> IP地址 </th>
<th> 端口号 </th>
<th> 登录方式 </th>
<th> 所属IDC </th>
<th> 所属业务组 </th>
<th> 添加时间 </th>
<th> 备注 </th>
</tr>
</thead>
<tbody>
<tr class="gradeX">
<td> <a id="ip" class="iframe" href="/jasset/{{ post.ip }}/">{{ post.ip }}</a></td>
<td> {{ post.port }} </td>
<td> {{ post.login_type|get_login_type }} </td>
<td class="text-center"> {{ post.idc.name }} </td>
<td class="text-center">{% for group in post.bis_group.all %} {{ group }} {% endfor %}</td>
<td class="text-center"> {{ post.date_added|date:"Y-m-d H:i:s" }} </td>
<td class="text-center"> {{ post.comment }} </td>
</tr>
</tbody>
</table>
<h3 class="text-center">{{ offset }}主机用户权限详情</h3>
<table class="table table-striped table-bordered table-hover " id="editable" >
<thead>
<tr>
<th> 用户名 </th>
</tr>
</thead>
<tbody>
<tr class="gradeX">
<td>
{% for user in user_permed_list %}
<a class="btn"> {{ user.name }} </a>
{% endfor %}
</td>
</tr>
</tbody>
</table>
<!--<a> 是否 激活: {{ post.is_active }}</a>-->
<h3 class="text-center">最近一周登录详情</h3>
<table class="table table-striped table-bordered table-hover ">
<thead>
<tr>
<th class="text-center"> 用户名 </th>
<th class="text-center"> 登录时间 </th>
<th class="text-center"> 退出时间 </th>
<th class="text-center"> 详情 </th>
</tr>
</thead>
<tbody>
{% for l in log %}
<tr class="gradeX">
<td class="text-center" id="username"> {{ l.user }} </td>
<td class="text-center" id="start_time">{{ l.start_time|date:"Y-m-d H:i:s" }}</td>
<td class="text-center" id="end_time"> {{ l.end_time|date:"Y-m-d H:i:s" }} </td>
<td class="text-center">
<a class="log_command text-success" href="/jlog/history/?id={{ l.id }}">命令统计</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</body>
<script src="/static/js/bootstrap-dialog.js"></script>
<script>
$('.log_command').on('click',function(){
var url = $(this).attr('href');
var username = $('#username')[0].innerText;
var ip = $('#ip')[0].innerText;
var start_time = $('#start_time')[0].innerText;
var end_time = $('#end_time')[0].innerText;
var div_username = ' 登录用户名: '+'<span class="text-info">'+username+'' + '</span>';
var div_ip = ' 登录主机: '+'<span class="text-info">' + ip + '</span>';
var div_time = ' 开始时间: ' + '<span class="text-info">'+start_time +'</span>' + ' 结束时间: ' +'<span class="text-info">' + end_time + '</span>'
var title = div_username + div_ip + div_time
$.ajax({url:url,success:function(data){
BootstrapDialog.show({title: title, message:data});
}});
return false;
})
</script>
</html>

View File

@ -1,12 +1,18 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% block self_head_css_js %}
<link href="/static/css/plugins/datepicker/datepicker3.css" rel="stylesheet">
<link href="/static/css/plugins/chosen/chosen.css" rel="stylesheet">
<script src="/static/js/plugins/chosen/chosen.jquery.js"></script>
{% endblock %}
{% block content %} {% block content %}
{% include 'nav_cat_bar.html' %} {% include 'nav_cat_bar.html' %}
<style> <style>
.bootstrap-dialog-body { .bootstrap-dialog-body {
background-color: rgba(0, 0, 0, 0); background-color: rgba(0, 0, 0, 0);
} }
.bootstrap-dialog-message { .bootstrap-dialog-message {
background-color: rgba(0, 0, 0, 0); color: #00FF00;
} }
.modal-content { .modal-content {
background-color: rgba(0, 0, 0, 0.6); background-color: rgba(0, 0, 0, 0.6);
@ -21,14 +27,12 @@
.modal-header { .modal-header {
background-color: #FFFFFF; background-color: #FFFFFF;
} }
.bootstrap-dialog-message {
color: #00FF00;
}
</style> </style>
<div class="wrapper wrapper-content animated fadeInRight"> <div class="wrapper wrapper-content animated fadeInRight">
<div class="row"> <div class="row">
<div class="col-lg-12"> <div class="col-sm-12">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div id="ibox-content" class="ibox-title"> <div id="ibox-content" class="ibox-title">
<h5> 用户日志详细信息列表 </h5> <h5> 用户日志详细信息列表 </h5>
@ -39,12 +43,6 @@
<a class="dropdown-toggle" data-toggle="dropdown" href="#"> <a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i> <i class="fa fa-wrench"></i>
</a> </a>
<ul class="dropdown-menu dropdown-user">
<li><a href="#">未启用 1</a>
</li>
<li><a href="#">未启用 2</a>
</li>
</ul>
<a class="close-link"> <a class="close-link">
<i class="fa fa-times"></i> <i class="fa fa-times"></i>
</a> </a>
@ -54,52 +52,78 @@
<div class="ibox-content"> <div class="ibox-content">
<div class="panel-options"> <div class="panel-options">
<ul class="nav nav-tabs"> <ul class="nav nav-tabs">
<li><a href="/jlog/log_list/online/" class="text-center"><i class="fa fa-laptop"></i> 在线 </a></li> <li><a href="{% url 'log_list' 'online' %}" class="text-center"><i class="fa fa-laptop"></i> 在线 </a></li>
<li class="active"><a href="/jlog/log_list/offline/" class="text-center"><i class="fa fa-bar-chart-o"></i> 历史记录 </a></li> <li class="active"><a href="{% url 'log_list' 'offline' %}" class="text-center"><i class="fa fa-bar-chart-o"></i> 登录历史</a></li>
<li style="float: right"> <li><a href="{% url 'log_list' 'exec' %}" class="text-center"><i class="fa fa-bar-chart-o"></i> 命令记录 </a></li>
<form id="search_form" method="get" action="" class="pull-right mail-search"> <li><a href="{% url 'log_list' 'file' %}" class="text-center"><i class="fa fa-bar-chart-o"></i> 上传下载 </a></li>
<div class="input-group">
<input type="text" class="form-control input-sm" id="search_input" name="keyword" placeholder="Search">
<input type="text" style="display: none">
<div class="input-group-btn">
<button id='search_btn' type="button" class="btn btn-sm btn-primary" onclick="log_search()">
Search
</button>
</div>
</div>
</form>
</li>
</ul> </ul>
</div> </div>
<br/> <form class="form-inline" action="" method="get">
<div class="form-group" id="date_5">
<div class="input-daterange input-group" id="datepicker">
<input type="text" class="input-sm form-control" style="width: 100px;" name="start" value="{{ date_seven_day }}">
<span class="input-group-addon">to</span>
<input type="text" class="input-sm form-control" style="width: 100px;" name="end" value="{{ date_now_str }}">
</div>
</div>
<div class="form-group">
<div class="input-group">
<select name="username" data-placeholder="用户名" class="chosen-select" multiple style="width:200px;" tabindex="2">
{% for username in username_all %}
<option value="{{ username }}"{% if username in username_list %}selected{% endif %}>{{ username }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="form-group">
<div class="input-group">
<select name="host" data-placeholder="主机" class="chosen-select" multiple style="width:200px;" tabindex="4">
{% for ip in ip_all %}
<option value="{{ ip }}" {% if ip in host_list %}selected{% endif %}>{{ ip }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="form-group">
<input id="cmd" name="cmd" placeholder="命令" type="text" class="form-control" value="{{ cmd }}" style="width: 200px;">
</div>
<button id='search_btn' type="submit" class="btn btn-sm btn-primary">
- 搜索 -
</button>
</form>
<div class="tab-content"> <div class="tab-content">
<table class="table table-striped table-bordered table-hover "> <table class="table table-striped table-bordered table-hover ">
<thead> <thead>
<tr> <tr>
<th class="text-center"> ID </th>
<th class="text-center"> 用户名 </th> <th class="text-center"> 用户名 </th>
<th class="text-center"> 所属部门 </th>
<th class="text-center"> 登录主机 </th> <th class="text-center"> 登录主机 </th>
<th class="text-center"> 来源IP </th> <th class="text-center"> 来源IP </th>
<th class="text-center"> 登陆方式 </th>
{% ifnotequal session_role_id 0 %} {% ifnotequal session_role_id 0 %}
<th class="text-center"> 命令统计 </th> <th class="text-center"> 命令 </th>
{% endifnotequal %} {% endifnotequal %}
<th class="text-center"> 录像 </th>
<th class="text-center"> 登录时间 </th> <th class="text-center"> 登录时间 </th>
<th class="text-center"> 结束时间 </th> <th class="text-center"> 时长</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for post in contacts.object_list %} {% for post in contacts.object_list %}
<tr class="gradeX"> <tr class="gradeX">
<td class="text-center" id="username"> {{ post.user }} </td> <td class="text-center"> {{ post.id }} </td>
<td class="text-center" id="dept"> {{ post.dept_name }} </td> <td class="text-center username"> {{ post.user }} </td>
<td class="text-center" id="ip"> {{ post.host }} </td> <td class="text-center ip"> {{ post.host }} </td>
<td class="text-center" id="remote_ip"> {{ post.remote_ip }} </td> <td class="text-center remote_ip"> {{ post.remote_ip }} </td>
<td class="text-center"> {{ post.login_type }} </td>
{% ifnotequal session_role_id 0 %} {% ifnotequal session_role_id 0 %}
<td class="text-center"><a href="/jlog/history/?id={{ post.id }}" class="log_command"> 命令统计 </td> <td class="text-center"><a href="{% url 'log_history' %}?id={{ post.id }}" class="log_command"> 统计 </a></td>
{% endifnotequal %} {% endifnotequal %}
<td class="text-center" id="start_time"> {{ post.start_time|date:"Y-m-d H:i:s"}} </td> <td class="text-center"><a value="{% url 'log_record' %}?id={{ post.id }}" class="log_record"> 回放 </a></td>
<td class="text-center" id="end_time"> {{ post.end_time|date:"Y-m-d H:i:s" }} </td> <td class="text-center start_time"> {{ post.start_time|date:"Y-m-d H:i:s"}} </td>
<td class="text-center end_time"> {{ post.end_time|timeuntil:post.start_time }} </td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
@ -116,28 +140,46 @@
</div> </div>
</div> </div>
{#<script src="http://{{ web_socket_host }}/socket.io/socket.io.js"></script>#}
<script> <script>
$('.log_command').on('click',function(){ $('.log_record').click(function(){
var url = $(this).attr('href'); var url = $(this).attr('value');
var username = $('#username')[0].innerText; //window.open(url, '播放', 'height=500, width=910, top=89px, left=99px,toolbar=no,menubar=no,scrollbars=auto,resizeable=no,location=no,status=no');
var ip = $('#ip')[0].innerText; var username = $(this).closest('tr').find('.username')[0].innerHTML;
var start_time = $('#start_time')[0].innerText; var ip = $(this).closest('tr').find('.ip')[0].innerHTML;
var end_time = $('#end_time')[0].innerText; var start_time = $(this).closest('tr').find('.start_time')[0].innerHTML;
var end_time = $(this).closest('tr').find('.end_time')[0].innerHTML;
var div_username = ' 用户名: '+'<span class="text-info">'+username+'' + '</span>'; var div_username = ' 用户名: '+'<span class="text-info">'+username+'' + '</span>';
var div_ip = ' 主机: '+'<span class="text-info">' + ip + '</span>'; var div_ip = ' 主机: '+'<span class="text-info">' + ip + '</span>';
var div_time = ' 开始时间: ' + '<span class="text-info">'+start_time +'</span>' + ' 结束时间: ' +'<span class="text-info">' + end_time + '</span' var div_time = ' 时间: ' + '<span class="text-info">'+start_time +'</span>' +' - <span class="text-info">' + end_time + '</span>';
var title = 'JumpServer录像回放 '+ div_username + div_ip + div_time;
layer.open({
type: 2,
title: title,
maxmin: true,
shade: false,
area: ['800px', '520px'],
content: url
});
return false;
});
$('.log_command').on('click',function(){
var url = $(this).attr('href');
var username = $(this).closest('tr').find('.username')[0].innerHTML;
var ip = $(this).closest('tr').find('.ip')[0].innerHTML;
var start_time = $(this).closest('tr').find('.start_time')[0].innerHTML;
var end_time = $(this).closest('tr').find('.end_time')[0].innerHTML;
var div_username = ' 用户名: '+'<span class="text-info">'+username+'' + '</span>';
var div_ip = ' 主机: '+'<span class="text-info">' + ip + '</span>';
var div_time = ' 开始时间: ' + '<span class="text-info">'+start_time +'</span>' + ' 结束时间: ' +'<span class="text-info">' + end_time + '</span>';
var title = 'JumpServer命令统计 '+ div_username + div_ip + div_time; var title = 'JumpServer命令统计 '+ div_username + div_ip + div_time;
$.ajax({url:url,success:function(data){ $.ajax({url:url,
success:function(data){
var tag = $('<div style="height: 500px;overflow: auto;background-color: rgba(0, 0, 0, 0);"></div>').html(data.replace(/\n/g,"<br />")); var tag = $('<div style="height: 500px;overflow: auto;background-color: rgba(0, 0, 0, 0);"></div>').html(data.replace(/\n/g,"<br />"));
BootstrapDialog.show({title: title, message:tag[0]}); BootstrapDialog.show({title: title, message:tag[0]});
}}); }});
return false; return false;
}); });
globalConfig = {
SOCKET_HOST: "{{ web_socket_host }}"
};
function log_search(){ function log_search(){
$.ajax({ $.ajax({
@ -150,11 +192,33 @@
}); });
} }
$("#search_input").keydown(function(e){ {# $("#search_input").keydown(function(e){#}
if(e.keyCode==13){ {# if(e.keyCode==13){#}
log_search() {# log_search()#}
{# }#}
{# });#}
$('#date_5 .input-daterange').datepicker({
dateFormat: 'mm/dd/yy',
keyboardNavigation: false,
forceParse: false,
autoclose: true
});
var config = {
'.chosen-select' : {},
'.chosen-select-deselect' : {allow_single_deselect:true},
'.chosen-select-no-single' : {disable_search_threshold:10},
'.chosen-select-no-results': {no_results_text:'Oops, nothing found!'},
'.chosen-select-width' : {width:"95%"}
};
for (var selector in config) {
$(selector).chosen(config[selector]);
} }
})
</script> </script>
{% endblock %} {% endblock %}
{% block self_footer_js %}
<script src="/static/js/cropper/cropper.min.js"></script>
<script src="/static/js/datapicker/bootstrap-datepicker.js"></script>
{% endblock %}

View File

@ -1,18 +1,32 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% block content %} {% block self_head_css_js %}
{% include 'nav_cat_bar.html' %} <style>
<style> .terminal {
border: #000 solid 5px;
font-family: "Monaco", "DejaVu Sans Mono", "Liberation Mono", monospace;
font-size: 11px;
color: #f0f0f0;
background: rgba(0, 0, 0, 0.6);
width: 600px;
box-shadow: rgba(0, 0, 0, 0.6) 2px 2px 20px;
}
.reverse-video {
color: #000;
background: #f0f0f0;
}
.bootstrap-dialog-body { .bootstrap-dialog-body {
background-color: rgba(0, 0, 0, 0); background-color: rgba(0, 0, 0, 0);
} }
.bootstrap-dialog-message { .bootstrap-dialog-message {
background-color: rgba(0, 0, 0, 0); color: #00FF00;
} }
.pre-class { .pre-class {
background-color: rgba(0, 0, 0, 1); background-color: rgba(0, 0, 0, 1);
} }
.modal-content { .modal-content {
background-color: rgba(0, 0, 0, 0.6); background-color: #000;
} }
.modal-dialog { .modal-dialog {
background-color: rgba(0, 0, 0, 0); background-color: rgba(0, 0, 0, 0);
@ -24,11 +38,16 @@
.modal-header { .modal-header {
background-color: #FFFFFF; background-color: #FFFFFF;
} }
</style> </style>
<script src="/static/js/term.js"></script>
{% endblock %}
{% block content %}
{% 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-12"> <div class="col-sm-12">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div id="ibox-content" class="ibox-title"> <div id="ibox-content" class="ibox-title">
<h5> 用户日志详细信息列表 </h5> <h5> 用户日志详细信息列表 </h5>
@ -39,12 +58,6 @@
<a class="dropdown-toggle" data-toggle="dropdown" href="#"> <a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i> <i class="fa fa-wrench"></i>
</a> </a>
<ul class="dropdown-menu dropdown-user">
<li><a href="#">未启用 1</a>
</li>
<li><a href="#">未启用 2</a>
</li>
</ul>
<a class="close-link"> <a class="close-link">
<i class="fa fa-times"></i> <i class="fa fa-times"></i>
</a> </a>
@ -54,52 +67,51 @@
<div class="ibox-content"> <div class="ibox-content">
<div class="panel-options"> <div class="panel-options">
<ul class="nav nav-tabs"> <ul class="nav nav-tabs">
<li class="active"><a href="/jlog/log_list/online/" class="text-center"><i class="fa fa-laptop"></i> 在线 </a></li> <li class="active"><a href="{% url 'log_list' 'online' %}" class="text-center"><i class="fa fa-laptop"></i> 在线 </a></li>
<li><a href="/jlog/log_list/offline/" class="text-center"><i class="fa fa-bar-chart-o"></i> 历史记录 </a></li> <li><a href="{% url 'log_list' 'offline' %}" class="text-center"><i class="fa fa-bar-chart-o"></i> 登录历史</a></li>
<li style="float: right"> <li><a href="{% url 'log_list' 'exec' %}" class="text-center"><i class="fa fa-bar-chart-o"></i> 命令记录 </a></li>
<li><a href="{% url 'log_list' 'file' %}" class="text-center"><i class="fa fa-bar-chart-o"></i> 上传下载 </a></li>
<div class="" style="float: right">
<form id="search_form" method="get" action="" class="pull-right mail-search"> <form id="search_form" method="get" action="" class="pull-right mail-search">
<div class="input-group"> <div class="input-group">
<input type="text" class="form-control input-sm" id="search_input" name="keyword" placeholder="Search"> <input type="text" class="form-control input-sm" id="keyword" name="keyword" value="{{ keyword }}" placeholder="Search">
<input type="text" style="display: none">
<div class="input-group-btn"> <div class="input-group-btn">
<button id='search_btn' type="button" class="btn btn-sm btn-primary" onclick="log_search()"> <button id='search_btn' type="submit" class="btn btn-sm btn-primary">
Search -搜索-
</button> </button>
</div> </div>
</div> </div>
</form> </form>
</li> </div>
</ul> </ul>
</div> </div>
<br/>
<div class="tab-content"> <div class="tab-content">
<table class="table table-striped table-bordered table-hover "> <table class="table table-striped table-bordered table-hover ">
<thead> <thead>
<tr> <tr>
<th class="text-center"> ID </th>
<th class="text-center"> 用户名 </th> <th class="text-center"> 用户名 </th>
<th class="text-center"> 所属部门 </th>
<th class="text-center"> 登录主机 </th> <th class="text-center"> 登录主机 </th>
<th class="text-center"> 来源IP </th> <th class="text-center"> 来源IP </th>
{% ifnotequal session_role_id 0 %} <th class="text-center"> 登录方式 </th>
<th class="text-center"> 命令 </th>
<th class="text-center"> 实时监控 </th> <th class="text-center"> 实时监控 </th>
<th class="text-center"> 阻断 </th> <th class="text-center"> 阻断 </th>
{% endifnotequal %}
<th class="text-center"> 登录时间 </th> <th class="text-center"> 登录时间 </th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for post in contacts.object_list %} {% for post in contacts.object_list %}
<tr class="gradeX"> <tr class="gradeX">
<td class="text-center">{{ post.id }}</td>
<td id="username" class="text-center"> {{ post.user }} </td> <td id="username" class="text-center"> {{ post.user }} </td>
<td id="deptname" class="text-center"> {{ post.dept_name }} </td>
<td id="ip" class="text-center"> {{ post.host }} </td> <td id="ip" class="text-center"> {{ post.host }} </td>
<td id="remote_ip" class="text-center"> {{ post.remote_ip }} </td> <td id="remote_ip" class="text-center"> {{ post.remote_ip }} </td>
{% ifnotequal session_role_id 0 %} <td class="text-center"> {{ post.login_type }} </td>
<td class="text-center"><a class="monitor" filename="{{ post.log_path }}"> 监控 </a></td> <td class="text-center"><a href="{% url 'log_history' %}?id={{ post.id }}" class="log_command"> 统计 </a></td>
<td class="text-center"><input type="button" id="cut" class="btn btn-danger btn-xs" name="cut" value="阻断" onclick='cut("{{ post.pid }}")' /></td> <td class="text-center"><a class="monitor" file_path="{{ post.log_path }}"> 监控 </a></td>
{% endifnotequal %} <td class="text-center"><input type="button" id="cut" class="btn btn-danger btn-xs" name="cut" value="阻断" onclick='cut("{{ post.pid }}", "{{ post.login_type }}")' /></td>
<td class="text-center"> {{ post.start_time|date:"Y-m-d H:i:s" }} </td> <td class="text-center" id="start_time"> {{ post.start_time|date:"Y-m-d H:i:s" }} </td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
@ -116,115 +128,92 @@
</div> </div>
<script src="http://{{ web_socket_host }}/socket.io/socket.io.js"></script> {#<script src="http://{{ web_socket_host }}/socket.io/socket.io.js"></script>#}
<script> <script>
$.fn.webSocket = function(opt){ {# $(document).ready(function(){#}
var st = {}; {# $('.monitor').click(function(){#}
st = $.extend(st,opt); {# window.open('/jlog/monitor/', '监控', 'height=500, width=910, top=89px, left=99px,toolbar=no,menubar=no,scrollbars=auto,resizeable=no,location=no,status=no');#}
var message = {}; {# })#}
var $this = $(this); {# });#}
var genUid = function(){ function init(obj){
return new Date().getTime()+""+Math.floor(Math.random()*899+100); var file_path = obj.attr('file_path');
}; var wsUri = '{{ web_monitor_uri }}';
var init = function(e){ var socket = new WebSocket(wsUri + '?file_path=' + file_path);
var socket = io.connect('ws://'+globalConfig.SOCKET_HOST);
var node = $(e.target);
message.id = genUid();
message.filename = node.attr('filename');
var username = $('#username')[0].innerText;
var ip = $('#ip')[0].innerText;
BootstrapDialog.show({message:function(){
var option, exsit_message;
var escapeString = function (html){
var elem = document.createElement('div');
var txt = document.createTextNode(html);
elem.appendChild(txt);
return elem.innerHTML;
};
var tag = $('<div id="log" style="height: 500px;overflow: auto;background-color: rgba(0, 0, 0, 0);"></div>');
var username = ""; var term = new Terminal({
var seed = ""; cols: 80,
document.cookie.split('; ').forEach(function(obj){ rows: 24,
var info = obj.split('='); screenKeys: false
if(info.length == 2 ){
if(info[0] == 'username'){
username = info[1];
}else if(info[0] == 'seed'){
seed = info[1];
}
}
})
//告诉服务器端有用户登录
socket.emit('login', {userid:message.id, filename:message.filename,username:username,seed:seed});
socket.on('message',function(obj){
option = obj.option;
console.log(option+'so')
exsit_message = obj.content;
console.log(obj.content)
//去除log中的颜色控制字符
var regx = /\x1B\[([0-9]{1,3}((;[0-9]{1,3})*)?)?[m|K]/g;
// tag.append('<p>'+escapeString(obj.content.replace(regx,''))+'</p>');
if (option == 'new') {
// tag.append('<p style="margin: 2px">' + escapeString(obj.content) + '</p>');
tag.append('<p style="margin: 2px">'+escapeString(obj.content.replace(regx,' '))+'</p>');
} else if (option == 'exist') {
tag.append('<pre>' + exsit_message + '</pre>');
}
tag.animate({ scrollTop: tag[0].scrollHeight}, 1);
}); });
tag[0].style.color = "#00FF00";
return tag[0];
var tag = $('<div id="term" style="height:500px; overflow: auto;background-color: rgba(0, 0, 0, 0);border: none"></div>');
term.open();
term.resize(80, 24);
socket.onopen = function(evt){
socket.send('hello');
term.write('~.~ Connect WebSocket Success.~.~ \r\n');
};
window.onbeforeunload = function(){
socket.close()
};
var username = obj.closest('tr').find('#username').text();
var ip = obj.closest('tr').find('#ip').text();
BootstrapDialog.show({message: function(){
//服务器端认证
{# socket.send('login', {userid:message.id, filename:message.filename,username:username,seed:seed});#}
window.setTimeout(function(){
$('.terminal').detach().appendTo('#term');
socket.onmessage = function(evt){
term.write(evt.data);
}}, 1000);
return tag[0];
} , } ,
title:'Jumpserver实时监控 '+' 登录用户名: '+'<span class="text-info">'+username+'</span>'+' 登录主机: '+'<span class="text-info">'+ip, title:'Jumpserver实时监控 '+' 登录用户名: '+'<span class="text-info">'+username+'</span>'+' 登录主机: '+'<span class="text-info">'+ip,
onhide:function(){ onhide:function(){
socket.emit('disconnect'); socket.close();
}}); }});
} }
$this.on("click",function(e){
init(e); $(document).ready(function(){
return false; $('.monitor').click(function(){
init($(this));
}); });
}
$('.log_command').on('click',function(){ $('.log_command').on('click',function(){
var url = $(this).attr('href'); var url = $(this).attr('href');
$.ajax({url:url,success:function(data){ var username = $(this).closest('tr').find('#username').text();
BootstrapDialog.show({title:'命令统计',message:data}); var ip = $(this).closest('tr').find('#ip').text();
var start_time = $(this).closest('tr').find('#start_time').text();
var div_username = ' 用户名: '+'<span class="text-info">'+username+'' + '</span>';
var div_ip = ' 主机: '+'<span class="text-info">' + ip + '</span>';
var div_time = ' 开始时间: ' + '<span class="text-info">'+start_time +'</span>' + '</span>';
var title = 'JumpServer命令统计 '+ div_username + div_ip + div_time;
$.ajax({url:url,
success:function(data){
var tag = $('<div style="height: 500px;overflow: auto;background-color: rgba(0, 0, 0, 0);"></div>').html(data.replace(/\n/g,"<br />"));
BootstrapDialog.show({title: title, message:tag[0]});
}}); }});
return false; return false;
})
globalConfig = {
SOCKET_HOST: "{{ web_socket_host }}"
}
$(".monitor").webSocket()
function log_search(){
$.ajax({
type: "GET",
url: "/jlog/search/?env=online",
data: $("#search_form").serialize(),
success: function (data) {
$(".tab-content").html(data);
}
}); });
});
function cut(num, login_type){
console.log(login_type);
if (login_type=='web'){
var g_url = '{{ web_kill_uri }}' + '?id=' + num;
} else {
var g_url = "{% url 'log_kill' %} }?id=" + num;
} }
$("#search_input").keydown(function(e){
if(e.keyCode==13){
log_search()
}
})
function cut(num){
var g_url = "/jlog/log_kill/?id="+num;
$.ajax({ $.ajax({
type: "GET", type: "GET",
url: g_url, url: g_url+"&sessionid={{ session_id }}",
success: window.open("/jlog/log_list/online/", "_self") success: window.open("{% url 'log_list' 'online' %}", "_self")
// error: window.open(g_url, "_self")
}); });
} }

View File

@ -19,7 +19,7 @@
<td class="text-center" id="dept_name"> {{ post.dept_name }} </td> <td class="text-center" id="dept_name"> {{ post.dept_name }} </td>
<td class="text-center" id="host"> {{ post.host }} </td> <td class="text-center" id="host"> {{ post.host }} </td>
<td class="text-center" id="remote_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"><a href="{% url 'log_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="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> <td class="text-center" id="end_time"> {{ post.end_time|date:"Y-m-d H:i:s" }} </td>
</tr> </tr>

View File

@ -28,7 +28,7 @@
<div class="wrapper wrapper-content animated fadeInRight"> <div class="wrapper wrapper-content animated fadeInRight">
<div class="row"> <div class="row">
<div class="col-lg-12"> <div class="col-sm-12">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div id="ibox-content" class="ibox-title"> <div id="ibox-content" class="ibox-title">
<h5> 用户{{ username }}日志详细信息列表 </h5> <h5> 用户{{ username }}日志详细信息列表 </h5>

View File

@ -1,179 +0,0 @@
{% extends 'base.html' %}
{% load mytags %}
{% block content %}
{% include 'nav_cat_bar.html' %}
<script type="text/javascript">
function search_ip(text, noselect, total){
$("#" + noselect).children().each(
function(){
$(this).remove();
});
$("#" + total).children().each(function(){
if($(this).text().search(text) != -1){
$("#" + noselect).append($(this).clone())
}
})
}
</script>
<div class="wrapper wrapper-content animated fadeInRight">
<div class="row">
<div class="col-lg-10">
<div class="ibox float-e-margins">
<div class="ibox-title">
<h5> 部门授权编辑 </h5>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
</a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i>
</a>
<ul class="dropdown-menu dropdown-user">
<li><a href="#">未启用 1</a>
</li>
<li><a href="#">未启用 2</a>
</li>
</ul>
<a class="close-link">
<i class="fa fa-times"></i>
</a>
</div>
</div>
<select id="assets_total" name="assets" class="form-control m-b" size="12" multiple style="display: none">
{% for asset in assets %}
<option value="{{ asset.id }}">{{ asset.ip }}</option>
{% endfor %}
</select>
<select id="asset_select_total" name="asset_select" class="form-control m-b" size="12" multiple style="display: none">
{% for asset in asset_select %}
<option value="{{ asset.id }}">{{ asset.ip }}</option>
{% endfor %}
</select>
<div class="ibox-content">
<form id="sudoPerm" method="post" class="form-horizontal" action="">
{% if error %}
<div class="alert alert-warning text-center">{{ error }}</div>
{% endif %}
{% if msg %}
<div class="alert alert-success text-center">{{ msg }}</div>
{% endif %}
<div class="row">
<div class="form-group">
<label for="group_name" class="col-sm-2 control-label">部门</label>
<div class="col-sm-8">
<input id="dept_id" name="dept_id" type="text" class="form-control" value="{{ dept.id }}" style="display: none">
<input id="dept_name" name="dept_name" type="text" class="form-control" value="{{ dept.name }}" readonly>
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="group_name" class="col-sm-2 control-label">过滤</label>
<div class="col-sm-4">
<input id="noselect" class="form-control" oninput="search_ip(this.value, 'assets', 'assets_total')">
</div>
<div class="col-sm-1">
</div>
<div id="select" class="col-sm-3">
<input class="form-control" oninput="search_ip(this.value, 'asset_select', 'asset_select_total')">
</div>
</div>
<div class="form-group">
<label for="" class="col-sm-2 control-label">主机<span class="red-fonts">*</span></label>
<div class="col-sm-4">
<div>
<select id="assets" name="assets" class="form-control m-b" size="12" multiple>
{% for asset in assets %}
<option value="{{ asset.id }}">{{ asset.ip }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="col-sm-1">
<div class="btn-group" style="margin-top: 60px;">
<button type="button" class="btn btn-white" onclick="move('assets', 'asset_select', 'assets_total', 'asset_select_total' )"><i class="fa fa-chevron-right"></i></button>
<button type="button" class="btn btn-white" onclick="move('asset_select', 'assets', 'asset_select_total', 'assets_total')"><i class="fa fa-chevron-left"></i> </button>
</div>
</div>
<div class="col-sm-3">
<div>
<select id="asset_select" name="asset_select" class="form-control m-b" size="12" multiple>
{% for asset in asset_select %}
<option value="{{ asset.id }}">{{ asset.ip }}</option>
{% endfor %}
</select>
</div>
</div>
</div>
</div>
<div class="row">
<div class="form-group">
<div class="col-sm-4 col-sm-offset-2">
<button class="btn btn-white" type="reset">取消</button>
<button id="submit_button" class="btn btn-primary" type="submit">确认保存</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
<script>
$('#sudoPerm').validator({
timely: 2,
theme: "yellow_right_effect",
fields: {
"name": {
rule: "required",
tip: "输入授权名",
ok: "",
msg: {required: "必须填写!"}
},
"user_groups_select": {
rule: "required",
tip: "选择用户组",
ok: "",
msg: {checked: "至少选择一个用户组"}
},
"asset_groups_select": {
rule: "required",
tip: "选择主机组",
ok: "",
msg: {checked: "至少选择一个主机组"}
}
},
valid: function(form) {
form.submit();
}
});
$(document).ready(function(){
$("#submit_button").click(function(){
$('#sudoPerm option').each(function(){
$(this).prop('selected', true)
})
});
})
</script>
{% endblock %}

View File

@ -1,104 +0,0 @@
{% extends 'base.html' %}
{% load mytags %}
{% block content %}
{% include 'nav_cat_bar.html' %}
<div class="wrapper wrapper-content animated fadeInRight">
<div class="row">
<div class="col-lg-10">
<div class="ibox float-e-margins">
<div class="ibox-title">
<h5> 查看部门 </h5>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
</a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i>
</a>
<ul class="dropdown-menu dropdown-user">
<li><a href="#">未启用 1</a>
</li>
<li><a href="#">未启用 2</a>
</li>
</ul>
<a class="close-link">
<i class="fa fa-times"></i>
</a>
</div>
</div>
<div class="ibox-content">
<div class="">
<a target="_blank" href="/juser/dept_add/" class="btn btn-sm btn-primary "> 添加部门 </a>
<form id="search_form" method="get" action="" class="pull-right mail-search">
<div class="input-group">
<input type="text" class="form-control input-sm" id="search_input" name="search" placeholder="Search">
<div class="input-group-btn">
<button id='search_btn' type="submit" class="btn btn-sm btn-primary">
Search
</button>
</div>
</div>
</form>
</div>
<table class="table table-striped table-bordered table-hover " id="editable" >
<thead>
<tr>
<th class="text-center">部门名称</th>
<th class="text-center">部门成员数目</th>
<th class="text-center">授权主机数目</th>
<th class="text-center">备注</th>
<th class="text-center">操作</th>
</tr>
</thead>
<tbody>
{% for dept in contacts.object_list %}
<tr class="gradeX">
<td class="text-center"> {{ dept.name }} </td>
<td class="text-center"><a href="/juser/user_list/?did={{ dept.id }}">{{ dept.id | dept_user_num }}</a> </td>
<td class="text-center"><a href="/jasset/host_list/?did={{ dept.id }}">{{ dept.id | dept_asset_num }}</a> </td>
<td class="text-center"> {{ dept.comment }} </td>
<td class="text-center">
{# <a title="[ {{ dept.name }} ] 成员信息" href="../dept_detail/?id={{ dept.id }}" class="iframe btn btn-xs btn-primary">主机</a>#}
<a href="../dept_perm_edit/?id={{ dept.id }}" class="btn btn-xs btn-danger">授权编辑</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="row">
<div class="col-sm-6">
<div class="dataTables_info" id="editable_info" role="status" aria-live="polite">
Showing {{ contacts.start_index }} to {{ contacts.end_index }} of {{ p.count }} entries
</div>
</div>
{% include 'paginator.html' %}
</div>
</div>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function(){
$(".iframe").colorbox({iframe:true, width:"70%", height:"70%"});
var check_array = []
$('#del_btn').click(function(){
$(".gradeX input:checked").each(function() {check_array.push($(this).attr("value")) })
$(".gradeX input:checked").closest("tr").remove()
$.post("/juser/dept_del_ajax/",
{dept_ids: check_array.join(",")},
function(data){
alert(data)
}
)
})
});
</script>
{% endblock %}

View File

@ -1,176 +0,0 @@
{% extends 'base.html' %}
{% load mytags %}
{% block content %}
{% include 'nav_cat_bar.html' %}
<div class="wrapper wrapper-content animated fadeInRight">
<div class="row">
<div class="col-lg-10">
<div class="ibox float-e-margins">
<div class="ibox-title">
<h5> 主机授权添加 </h5>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
</a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i>
</a>
<ul class="dropdown-menu dropdown-user">
<li><a href="#">未启用 1</a>
</li>
<li><a href="#">未启用 2</a>
</li>
</ul>
<a class="close-link">
<i class="fa fa-times"></i>
</a>
</div>
</div>
<div class="ibox-content">
<form id="sudoPerm" method="post" class="form-horizontal" action="">
{% if error %}
<div class="alert alert-warning text-center">{{ error }}</div>
{% endif %}
{% if msg %}
<div class="alert alert-success text-center">{{ msg }}</div>
{% endif %}
<div class="row">
<div class="form-group">
<label for="name" class="col-sm-2 control-label">授权名<span class="red-fonts">*</span></label>
<div class="col-sm-8">
<input id="name" name="name" placeholder="授权名称" type="text" class="form-control">
<span class="help-block m-b-none">取个名字方便辨识</span>
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="" class="col-sm-2 control-label">用户组<span class="red-fonts">*</span></label>
<div class="col-sm-4">
<div>
<select id="user_groups" name="user_groups" class="form-control" size="12" multiple>
{% for user_group in user_groups %}
<option value="{{ user_group.id }}">{{ user_group.name }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="col-sm-1">
<div class="btn-group" style="margin-top: 12px;">
<button type="button" class="btn btn-white" onclick="move('user_groups', 'user_groups_select')"><i class="fa fa-chevron-right"></i></button>
<button type="button" class="btn btn-white" onclick="move('user_groups_select', 'user_groups')"><i class="fa fa-chevron-left"></i> </button>
</div>
</div>
<div class="col-sm-3">
<div>
<select id="user_groups_select" name="user_groups_select" class="form-control m-b" size="12" multiple>
</select>
</div>
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="" class="col-sm-2 control-label">主机组<span class="red-fonts">*</span></label>
<div class="col-sm-4">
<div>
<select id="asset_groups" name="asset_groups" class="form-control m-b" size="12" multiple>
{% for asset_group in asset_groups %}
<option value="{{ asset_group.id }}">{{ asset_group.name }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="col-sm-1">
<div class="btn-group" style="margin-top: 12px;">
<button type="button" class="btn btn-white" onclick="move('asset_groups', 'asset_groups_select')"><i class="fa fa-chevron-right"></i></button>
<button type="button" class="btn btn-white" onclick="move('asset_groups_select', 'asset_groups')"><i class="fa fa-chevron-left"></i> </button>
</div>
</div>
<div class="col-sm-3">
<div>
<select id="asset_groups_select" name="asset_groups_select" class="form-control m-b" size="12" multiple>
</select>
</div>
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="group_name" class="col-sm-2 control-label">备注</label>
<div class="col-sm-8">
<input id="comment" name="comment" placeholder="备注说明" type="text" class="form-control">
</div>
</div>
<div class="hr-line-dashed"></div>
</div>
<div class="row">
<div class="form-group">
<div class="col-sm-4 col-sm-offset-2">
<button class="btn btn-white" type="reset">取消</button>
<button id="submit_button" class="btn btn-primary" type="submit">确认保存</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
<script>
$('#sudoPerm').validator({
timely: 2,
theme: "yellow_right_effect",
fields: {
"name": {
rule: "required",
tip: "输入授权名",
ok: "",
msg: {required: "必须填写!"}
},
"user_groups_select": {
rule: "required",
tip: "选择用户组",
ok: "",
msg: {checked: "至少选择一个用户组"}
},
"asset_groups_select": {
rule: "required",
tip: "选择主机组",
ok: "",
msg: {checked: "至少选择一个主机组"}
}
},
valid: function(form) {
form.submit();
}
});
$(document).ready(function(){
$("#submit_button").click(function(){
$('#user_groups_select option').each(function(){
$(this).prop('selected', true)
})
$('#asset_groups_select option').each(function(){
$(this).prop('selected', true)
})
})
})
</script>
{% endblock %}

View File

@ -1,187 +0,0 @@
{% extends 'base.html' %}
{% block content %}
{% include 'nav_cat_bar.html' %}
<script type="text/javascript">
function search_ip(text, noselect, total){
$("#" + noselect).children().each(
function(){
$(this).remove();
});
$("#" + total).children().each(function(){
if($(this).text().search(text) != -1){
$("#" + noselect).append($(this).clone())
}
})
}
</script>
<div class="wrapper wrapper-content animated fadeInRight">
<div class="row">
<div class="col-lg-10">
<div id="add_asset" class="ibox float-e-margins">
<div id="ibox-content" class="ibox-title">
<h5> 填写要申请主机的基本信息 </h5>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
</a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i>
</a>
<ul class="dropdown-menu dropdown-user">
</ul>
<a class="close-link">
<i class="fa fa-times"></i>
</a>
</div>
</div>
<select id="assets_total" name="assets" class="form-control m-b" size="12" multiple style="display: none">
{% for asset in posts %}
<option value="{{ asset.ip }}">{{ asset.ip }}</option>
{% endfor %}
</select>
<select id="asset_select_total" name="j_hosts" class="form-control m-b" size="12" multiple style="display: none">
{% for asset in eposts %}
<option value="{{ asset.ip }}">{{ asset.ip }}</option>
{% endfor %}
</select>
<div class="ibox-content">
{% if emg %}
<div class="alert alert-warning text-center">{{ emg }}</div>
{% endif %}
{% if smg %}
<div class="alert alert-success text-center">{{ smg }}</div>
{% endif %}
<form id="assetForm" method="post" class="form-horizontal">
{% csrf_token %}
<div class="form-group"><label class="col-sm-2 control-label"> 申请人 <span class="red-fonts">*</span></label>
<div class="col-sm-8"><input type="text" name="applyer" value="{{ name }}" class="form-control" readonly="readonly"></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"><input type="text" name="dept" value="{{ deptname }}" class="form-control" readonly="readonly"></div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group" id="j_da"><label class="col-sm-2 control-label"> 管理员 <span class="red-fonts">*</span></label>
<div class="radio">
<label><input type="radio" value="{{ admin.id }}" name="da"> {{ admin.name }}</label>
{% for da in dept_da %}
<label><input type="radio" value="{{ da.id }}" name="da"> {{ da.name }}</label>
{% endfor %}
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="group" class="col-lg-2 control-label">主机组</label>
<div class="col-sm-8">
<select id="group" name="group" class="form-control m-b" multiple size="10">
{% for g in egroup %}
<option type="checkbox" value="{{ g.name }}">{{ g.name }} {% if g.comment %} --- {{ g.comment }} {% endif %}</option>
{% endfor %}
</select>
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="group_name" class="col-sm-2 control-label">过滤</label>
<div class="col-sm-4">
<input id="noselect" class="form-control" oninput="search_ip(this.value, 'assets', 'assets_total')">
</div>
<div class="col-sm-1">
</div>
<div id="select" class="col-sm-3">
<input class="form-control" oninput="search_ip(this.value, 'asset_select', 'asset_select_total')">
</div>
</div>
<div class="form-group">
<label for="" class="col-sm-2 control-label">主机<span class="red-fonts">*</span></label>
<div class="col-sm-4">
<div>
<select id="assets" name="assets" class="form-control m-b" size="12" multiple>
{% for post in posts %}
<option value="{{ post.ip }}">{{ post.ip }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="col-sm-1">
<div class="btn-group" style="margin-top: 60px;">
<button type="button" class="btn btn-white" onclick="move('assets', 'asset_select', 'assets_total', 'asset_select_total' )"><i class="fa fa-chevron-right"></i></button>
<button type="button" class="btn btn-white" onclick="move_left('asset_select', 'assets', 'asset_select_total', 'assets_total')"><i class="fa fa-chevron-left"></i> </button>
</div>
</div>
<div class="col-sm-3">
<div>
<select id="asset_select" name="hosts" class="form-control m-b" size="12" multiple></select>
</div>
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group"><label class="col-sm-2 control-label"> 申请说明 </label>
<div class="col-sm-8"><textarea type="text" placeholder="" name="comment" class="form-control" rows="5" cols="20"></textarea></div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<div class="col-sm-4 col-sm-offset-5">
<button class="btn btn-primary" id="submit_button" type="submit"> 提交 </button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function(){
$("#submit_button").click(function(){
$('#assetForm option').each(function(){
$(this).prop('selected', true)
})
});
})
$('#assetForm').validator({
timely: 2,
theme: "yellow_right_effect",
fields: {
"j_da": {
rule: "required",
tip: "选择管理员",
ok: "",
msg: {required: "管理员必须选择!"},
data: {'data-ok':"ok"}
}
},
valid: function(form) {
form.submit();
}
});
var $rows = $('#groups option');
$('#search').keyup(function() {
var val = $.trim($(this).val()).replace(/ +/g, ' ').toLowerCase();
$rows.show().filter(function() {
var text = $(this).text().replace(/\s+/g, ' ').toLowerCase();
return !~text.indexOf(val);
}).hide();
});
</script>
{% endblock content %}

View File

@ -1,31 +0,0 @@
{% extends 'base.html' %}
{% block content %}
{% include 'nav_cat_bar.html' %}
<!--<h3 class="text-center">项目发布申请</h3>-->
<div class="wrapper wrapper-content animated fadeInRight">
<div class="row">
<div class="col-lg-10">
<div id="add_asset" class="ibox float-e-margins">
<div class="ibox-content">
<h2 id="jumpTo" class="text-center text-info"></h2>
</div>
</div>
</div>
</div>
</div>
<script>
function countDown(secs,surl){
var jumpTo = document.getElementById('jumpTo');
jumpTo.innerHTML='{{ smg }}......' + secs + '秒';
if(--secs>0){
setTimeout("countDown("+secs+",'"+surl+"')",1000);
}
else{
location.href=surl;
}
}
countDown(10,'/');
</script>
{% endblock content %}

View File

@ -1,55 +0,0 @@
{% load mytags %}
<html>
<head>
<link href="/static/css/bootstrap.min.css" rel="stylesheet">
<script src="/static/js/jquery-2.1.1.js"></script>
<script src="/static/js/bootstrap.min.js"></script>
<!--<link href="/static/css/style.css" rel="stylesheet">
<!--{% include 'head_script.html' %}
<!--<style type="text/css">-->
<!--body-->
<!--{-->
<!--background: #FFFFFF;-->
<!--}-->
<!--</style>-->
</head>
<body>
<div class="container">
<h3 class="text-center"><span class="text-success">{{ post.applyer }}</span>权限申请详情</h3>
<br/>
<div class="row">
<div class="col-xs-5">
<h6 class="text-right">申请人</h6>
<h6 class="text-right">所属部门</h6>
<h6 class="text-right">申请主机组</h6>
<h6 class="text-right">申请主机</h6>
{% for i in post.asset|ast_to_list_1 %}
<h6 class="text-right" style="color: #ffffff">Null</h6>
{% endfor %}
<h6 class="text-right">批准人</h6>
<h6 class="text-right">申请时间</h6>
<h6 class="text-right">批准时间</h6>
<h6 class="text-right">备注</h6>
</div>
<div class="col-xs-2">
<div class="col-sm-offset-6" style="width: 2; height: 70%; background-color: #1AB394; padding-top: 200px"></div>
</div>
<div class="col-xs-5">
<h6 class="text-left">{{ post.applyer }}</h6>
<h6 class="text-left">{{ post.dept }}</h6>
<h6 class="text-left">{% for i in post.bisgroup|ast_to_list_1 %} {{ i }} {% endfor %}</h6>
{% for i in post.asset|ast_to_list_1 %}
<h6 class="text-left">{{ i }}</h6>
{% endfor %}
<h6 class="text-right" style="color: #ffffff">Null</h6>
<h6 class="text-left">{{ post.approver }}1</h6>
<h6 class="text-left">{{ post.date_add|date:"Y-m-d H:i:s"}}</h6>
<h6 class="text-left"> {{ post.date_end|date:"Y-m-d H:i:s" }}1 </h6>
<h6 class="text-left"> {{ post.comment }} </h6>
</div>
</div>
</div>
</body>
</html>

View File

@ -1,40 +0,0 @@
{% load mytags %}
<div class="tab-content">
<table class="table table-striped table-bordered table-hover ">
<thead>
<tr>
<th class="text-center"> 申请人 </th>
<th class="text-center"> 所属部门 </th>
<th class="text-center"> 申请主机组 </th>
<th class="text-center"> 申请主机 </th>
<th class="text-center"> 批准人 </th>
<th class="text-center"> 申请时间 </th>
<th class="text-center"> 备注 </th>
<th class="text-center"> 详情 </th>
</tr>
</thead>
<tbody>
{% for post in contacts.object_list %}
<tr class="gradeX">
<td class="text-center" id="username"> {{ post.applyer }} </td>
<td class="text-center" id="dept"> {{ post.dept }} </td>
<td class="text-center" id="ip"> {{ post.bisgroup|ast_to_list }} </td>
<td class="text-center" id="remote_ip"> {{ post.asset|ast_to_list }} </td>
<td class="text-center" id="approver"> {{ post.approver }} </td>
<td class="text-center" id="start_time"> {{ post.date_add|date:"Y-m-d H:i:s"}} </td>
<td class="text-center" id=""> {{ post.comment }} </td>
<td class="text-center" data-editable='false'>
<a value="/jperm/apply_info/?uuid={{ post.uuid }}" class="iframe btn btn-xs btn-primary">详情</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="row">
<div class="col-sm-6">
</div>
{% include 'paginator.html' %}
</div>
</div>
</div>

View File

@ -1,61 +0,0 @@
{% extends 'base.html' %}
{% load mytags %}
{% block content %}
{% include 'nav_cat_bar.html' %}
<div class="wrapper wrapper-content animated fadeInRight">
<div class="row">
<div class="col-lg-6">
<div class="ibox float-e-margins">
<div class="ibox-title">
<h5>授权主机详情</h5>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
</a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i>
</a>
<ul class="dropdown-menu dropdown-user">
<li><a href="#">未启用 1</a>
</li>
<li><a href="#">未启用 2</a>
</li>
</ul>
<a class="close-link">
<i class="fa fa-times"></i>
</a>
</div>
</div>
<div class="ibox-content">
<table class="table">
<thead>
<tr>
<th>IP</th>
<th>IDC</th>
<th>主机组</th>
</tr>
</thead>
<tbody>
{% for asset in assets_list %}
<tr>
<td>{{ asset.ip }}</td>
<td>{{ asset.idc.name }}</td>
<td>
{% for group in asset.bis_group.all|filter_private %}
{{ group }}
{% endfor %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -1,118 +0,0 @@
{% extends 'base.html' %}
{% load mytags %}
{% block content %}
{% include 'nav_cat_bar.html' %}
<div class="wrapper wrapper-content animated fadeInRight">
<div class="row">
<div class="col-lg-4">
<div class="ibox float-e-margins">
<div class="ibox-title">
<h5>授权主机/组</h5>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
</a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i>
</a>
<ul class="dropdown-menu dropdown-user">
<li><a href="#">Config option 1</a>
</li>
<li><a href="#">Config option 2</a>
</li>
</ul>
<a class="close-link">
<i class="fa fa-times"></i>
</a>
</div>
</div>
<div class="ibox-content ibox-heading">
<h3>用户</h3>
<small><i class="fa fa-map-marker"></i> 组下用户.</small>
</div>
<div class="ibox-content inspinia-timeline">
<div class="timeline-item">
<div class="row">
<div class="col-xs-3 date">
<i class="fa fa-users"></i>
<b>{{ user_group.name }}</b>
<br>
<small class="text-navy">共: {{ group_user_num }} 用户</small>
</div>
<div class="col-xs-7 content no-top-border">
<p class="m-b-xs"><strong>{{ user_group.comment }}</strong></p>
<p>
{% for user in users %}
{{ user.name }}<br>
{% endfor %}
</p>
<p></p>
</div>
</div>
</div>
{% if not user|get_user_asset_group %}
(无)
{% endif %}
</div>
</div>
</div>
<div class="col-lg-4">
<div class="ibox float-e-margins">
<div class="ibox-title">
<h5>授权主机/组</h5>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
</a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i>
</a>
<ul class="dropdown-menu dropdown-user">
<li><a href="#">Config option 1</a>
</li>
<li><a href="#">Config option 2</a>
</li>
</ul>
<a class="close-link">
<i class="fa fa-times"></i>
</a>
</div>
</div>
<div class="ibox-content ibox-heading">
<h3>授权主机/组</h3>
<small><i class="fa fa-map-marker"></i> 这里包含了用户所有的主机组和组下的主机.</small>
</div>
<div class="ibox-content inspinia-timeline">
{% for group in asset_groups %}
<div class="timeline-item">
<div class="row">
<div class="col-xs-3 date">
<i class="fa fa-repeat"></i>
<b>{{ group.name }}</b>
<br>
<small class="text-navy">共: {{ group | group_asset_list_count }}台</small>
</div>
<div class="col-xs-7 content no-top-border">
<p class="m-b-xs"><strong>{{ group.comment }}</strong></p>
<p>
{% for asset in group|group_asset_list %}
{{ asset.ip }}<br>
{% endfor %}
</p>
<p></p>
</div>
</div>
</div>
{% endfor %}
{% if not user|get_user_asset_group %}
(暂无)
{% endif %}
</div>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -1,130 +0,0 @@
{% extends 'base.html' %}
{% load mytags %}
{% block content %}
{% include 'nav_cat_bar.html' %}
<div class="wrapper wrapper-content animated fadeInRight">
<div class="row">
<div class="col-lg-10">
<div class="ibox float-e-margins">
<div class="ibox-title">
<h5> 主机授权修改</h5>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
</a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i>
</a>
<ul class="dropdown-menu dropdown-user">
<li><a href="#">未启用 1</a>
</li>
<li><a href="#">未启用 2</a>
</li>
</ul>
<a class="close-link">
<i class="fa fa-times"></i>
</a>
</div>
</div>
<div class="ibox-content">
<form id="sudoPerm" method="post" class="form-horizontal" action="">
{% if error %}
<div class="alert alert-warning text-center">{{ error }}</div>
{% endif %}
{% if msg %}
<div class="alert alert-success text-center">{{ msg }}</div>
{% endif %}
<div class="row">
<div class="form-group">
<label for="" class="col-sm-2 control-label">小组<span class="red-fonts">*</span></label>
<div class="col-sm-4">
<input id="user_group_id" name="user_group_id"type="text" value="{{ user_group.id }}" style="display: none">
<input id="user_group_name" name="user_group_name" type="text" class="form-control" value="{{ user_group.name }}" readonly>
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="" class="col-sm-2 control-label">主机组<span class="red-fonts">*</span></label>
<div class="col-sm-4">
<div>
<select id="asset_groups" name="asset_groups" class="form-control m-b" size="12" multiple>
{% for asset_group in asset_groups %}
<option value="{{ asset_group.id }}">{{ asset_group.name }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="col-sm-1">
<div class="btn-group" style="margin-top: 42px;">
<button type="button" class="btn btn-white" onclick="move('asset_groups', 'asset_groups_select')"><i class="fa fa-chevron-right"></i></button>
<button type="button" class="btn btn-white" onclick="move('asset_groups_select', 'asset_groups')"><i class="fa fa-chevron-left"></i> </button>
</div>
</div>
<div class="col-sm-3">
<div>
<select id="asset_groups_select" name="asset_groups_select" class="form-control m-b" size="12" multiple>
{% for asset_group in asset_groups_select %}
<option value="{{ asset_group.id }}">{{ asset_group.name }}</option>
{% endfor %}
</select>
</div>
</div>
</div>
</div>
<div class="row">
<div class="form-group">
<div class="col-sm-4 col-sm-offset-2">
<button class="btn btn-white" type="reset">取消</button>
<button id="submit_button" class="btn btn-primary" type="submit">确认保存</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
<script>
$('#sudoPerm').validator({
timely: 2,
theme: "yellow_right_effect",
fields: {
"name": {
rule: "required",
tip: "输入授权名",
ok: "",
msg: {required: "必须填写!"}
}
},
valid: function(form) {
form.submit();
}
});
$(document).ready(function(){
$("#submit_button").click(function(){
$('#user_groups_select option').each(function(){
$(this).prop('selected', true)
})
$('#asset_groups_select option').each(function(){
$(this).prop('selected', true)
})
})
})
</script>
{% endblock %}

View File

@ -1,138 +0,0 @@
{% extends 'base.html' %}
{% load mytags %}
{% block content %}
<script type="text/javascript">
function search_host(text){
$("#asset_group_unperm").children().each(function(){$(this).remove();});
var permArray = [];
$("#asset_group_permed").children().each(function(){
permArray.push($(this).text());
});
$("#asset_groups").children().each(function(){
if ($(this).text().search(text) != -1 && permArray.indexOf($(this).text()) == -1) {
$("#asset_group_unperm").append($(this).clone())
}
});
}
</script>
{% include 'nav_cat_bar.html' %}
<div class="wrapper wrapper-content animated fadeInRight">
<div class="row">
<div class="col-lg-10">
<div class="ibox float-e-margins">
<!-- title -->
<div class="ibox-title">
<h5>授权编辑表单 <small>Edit perm of Group</small></h5>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
</a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i>
</a>
<ul class="dropdown-menu dropdown-user">
<li><a href="#">Config option 1</a>
</li>
<li><a href="#">Config option 2</a>
</li>
</ul>
<a class="close-link">
<i class="fa fa-times"></i>
</a>
</div>
</div>
<!-- end title -->
<div class="ibox-content">
<div class="row">
<div class="col-sm-5 ">
<div class="form-group">
<label></label>
<input type="text" id="group_filter" placeholder="Search" class="form-control" value="" oninput="search_host(this.value)">
</div>
</div>
<div class="col-sm-1 ">
<div class="form-group">
<label></label>
</div>
</div>
<div class="col-sm-5 ">
<div class="form-group">
<label></label>
<input type="text" class="form-control" value="{{ user_group.name }}" readonly>
</div>
</div>
</div>
<form method="post" action="">
<input type="text" name="user_group_name" class="form-control" value="{{ user_group.name }}" style="display: none">
<div class="row">
<div class="col-sm-5"><h4>未授权主机组</h4>
<div>
<select id="asset_groups" name="asset_groups" class="form-control" size="10" multiple style="display: none">
{% for asset_group in asset_groups %}
<option value="{{ asset_group.id }}">{{ asset_group.name }}</option>
{% endfor %}
</select>
<select id="asset_group_unperm" name="asset_group_unperm" class="form-control m-b" size="12" multiple>
{% for asset_group in asset_groups_unperm %}
<option value="{{ asset_group.id }}">{{ asset_group.name }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="col-sm-1">
<div class="btn-group" style="margin-top: 50px;">
<button type="button" class="btn btn-white" onclick="move('asset_group_unperm', 'asset_group_permed')"><i class="fa fa-chevron-right"></i></button>
<button type="button" class="btn btn-white" onclick="move('asset_group_permed', 'asset_group_unperm')"><i class="fa fa-chevron-left"></i> </button>
</div>
</div>
<div class="col-sm-5"><h4>授权主机</h4>
<div>
<select id="asset_group_permed" name="asset_group_permed" class="form-control m-b" size="12" multiple>
{% for asset_group in asset_groups_permed %}
<option value="{{ asset_group.id }}">{{ asset_group.name }}</option>
{% endfor %}
</select>
</div>
</div>
</div>
<div class="row">
<div class="form-group">
<div class="col-sm-4 col-sm-offset-2">
<button class="btn btn-white" type="submit">取消</button>
<button class="btn btn-primary" type="submit" onclick="javascript: (function(){$('#asset_group_permed option').each(function(){$(this).prop('selected', true)})})()">确认保存</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
<script>
var str = document.location.pathname.split("/")[1];
var str1 = document.location.pathname.split("/")[2];
$("#"+str).addClass('active');
$("#"+str1).addClass('active');
</script>
{# <script type="text/javascript">#}
{# $("#asset_group_permed").children().each(function(){#}
{# $("#asset_groups").append($(this).clone());#}
{##}
{# if ($(this).prop("selected") == false) {#}
{# $("#asset_group_unperm").append(this);#}
{# }#}
{##}
{# $("#asset_groups").children().each(function(){$(this).prop("selected", false)});#}
{# });#}
{# </script>#}
{% endblock %}

View File

@ -1,108 +0,0 @@
{% extends 'base.html' %}
{% load mytags %}
{% block content %}
{% include 'nav_cat_bar.html' %}
<div class="wrapper wrapper-content animated fadeInRight">
<div class="row">
<div class="col-lg-10">
<div class="ibox float-e-margins">
<div class="ibox-title">
<h5> 查看小组</h5>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
</a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i>
</a>
<ul class="dropdown-menu dropdown-user">
<li><a href="#">未启用 1</a>
</li>
<li><a href="#">未启用 2</a>
</li>
</ul>
<a class="close-link">
<i class="fa fa-times"></i>
</a>
</div>
</div>
<div class="ibox-content">
<div class="">
<a target="_blank" href="/juser/group_add/" class="btn btn-sm btn-primary "> 添加小组 </a>
<form id="search_form" method="get" action="" class="pull-right mail-search">
<div class="input-group">
<input type="text" class="form-control input-sm" id="search_input" name="search" placeholder="Search">
<div class="input-group-btn">
<button id='search_btn' type="submit" class="btn btn-sm btn-primary">
Search
</button>
</div>
</div>
</form>
</div>
<table class="table table-striped table-bordered table-hover " id="editable" >
<thead>
<tr>
<th class="text-center">组名</th>
<th class="text-center">所属部门</th>
<th class="text-center">成员数目</th>
<th class="text-center">授权主机组数目</th>
<th class="text-center">授权主机数目</th>
<th class="text-center">备注</th>
<th class="text-center">操作</th>
</tr>
</thead>
<tbody>
{% for group in contacts.object_list %}
<tr class="gradeX">
<td class="text-center"> {{ group.name }} </td>
<td class="text-center"> {{ group.dept.name }} </td>
<td class="text-center"> <a href="/juser/user_list/?gid={{ group.id }}">{{ group.id | member_count }} </a> </td>
<td class="text-center"> <a href="/jasset/group_list/?gid={{ group.id }}"> {{ group.id | ugrp_perm_agrp_count }} </a> </td>
<td class="text-center"> <a href="/jasset/host_list/?gid={{ group.id }}">{{ group.id | ugrp_perm_asset_count }} </a> </td>
<td class="text-center"> {{ group.comment }} </td>
<td class="text-center">
<a href="../perm_detail/?id={{ group.id }}" class="btn btn-xs btn-primary">详情</a>
<a href="../perm_edit/?id={{ group.id }}" class="btn btn-xs btn-danger">授权编辑</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="row">
<div class="col-sm-6">
<div class="dataTables_info" id="editable_info" role="status" aria-live="polite">
Showing {{ contacts.start_index }} to {{ contacts.end_index }} of {{ p.count }} entries
</div>
</div>
{% include 'paginator.html' %}
</div>
</div>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function(){
$(".iframe").colorbox({iframe:true, width:"70%", height:"70%"});
var check_array = []
$('#del_btn').click(function(){
$(".gradeX input:checked").each(function() {check_array.push($(this).attr("value")) })
$(".gradeX input:checked").closest("tr").remove()
$.post("/juser/group_del_ajax/",
{group_ids: check_array.join(",")},
function(data){
alert(data)
}
)
})
});
</script>
{% endblock %}

View File

@ -1,132 +0,0 @@
{% load mytags %}
{% ifequal tab 'tab1' %}
<table class="table table-striped table-bordered table-hover " id="editable" >
<thead>
<tr>
<th class="text-center">组名</th>
<th class="text-center">
<span class="text-muted text-xs block">类型</span>
</th>
<th class="text-center">成员数量</th>
<th class="text-center">授权数量</th>
<th class="text-center">操作</th>
</tr>
</thead>
<tbody id="perm_edit">
{% for group in contacts.object_list %}
<tr class="gradeX">
<td class="text-center"> {{ group.name }} </td>
<td class="text-center"> {{ group.type|group_type_to_str }} </td>
<td class="text-center"> {{ group.id|member_count }} </td>
<td class="text-center"> {{ group.id|perm_count }} </td>
<td class="text-center">
<a title="[ {{ group.name }} ] 授权详情" href="../perm_detail/?id={{ group.id }}" class="iframe btn btn-xs btn-primary">详情</a>
<a href="../perm_edit/?id={{ group.id }}" class="btn btn-xs btn-info">编辑</a>
<a href="../perm_del/?id={{ group.id }}" class="btn btn-xs btn-danger">删除</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="row">
<div class="col-sm-6">
<div class="dataTables_info" id="editable_info" role="status" aria-live="polite">
Showing {{ contacts.start_index }} to {{ contacts.end_index }} of {{ p.count }} entries
</div>
</div>
<div class="col-sm-6">
<div class="dataTables_paginate paging_simple_numbers" id="editable_paginate">
<ul class="pagination" style="margin-top: 0; float: right">
{% if contacts.has_previous %}
<li class="paginate_button previous" aria-controls="editable" tabindex="0" id="editable_previous">
<a href="?page={{ contacts.previous_page_number }}">Previous</a>
</li>
{% else %}
<li class="paginate_button previous disabled" aria-controls="editable" tabindex="0" id="editable_previous">
<a href="#">Previous</a>
</li>
{% endif %}
{% for page in p.page_range %}
{% ifequal offset1 page %}
<li class="paginate_button active" aria-controls="editable" tabindex="0"><a href="?page={{ page }}" title="第{{ page }}页">{{ page }}</a></li>
{% else %}
<li class="paginate_button" aria-controls="editable" tabindex="0"><a href="?page={{ page }}" title="第{{ page }}页">{{ page }}</a></li>
{% endifequal %}
{% endfor %}
{% if contacts.has_next %}
<li class="paginate_button next" aria-controls="editable" tabindex="0" id="editable_next">
<a href="?page={{ contacts.next_page_number }}">Next</a>
</li>
{% else %}
<li class="paginate_button next disabled" aria-controls="editable" tabindex="0" id="editable_next">
<a href="#">Next</a>
</li>
{% endif %}
</ul>
</div>
</div>
</div>
{% else %}
<table class="table table-striped table-bordered table-hover " id="editable" >
<thead>
<tr>
<th class="text-center">用户</th>
<th class="text-center">角色</th>
<th class="text-center">属组</th>
<th class="text-center">主机数量</th>
<th class="text-center">操作</th>
</tr>
</thead>
<tbody id="perm_list">
{% for user in contacts2.object_list %}
<tr class="gradeX">
<td class="text-center"> {{ user.name }} </td>
<td class="text-center"> {{ user.id | get_role }} </td>
<td class="text-center"> {{ user.username | groups_str }} </td>
<td class="text-center"> {{ user.id | perm_asset_count }} </td>
<td class="text-center">
<a title="{{ user.name }} ] 授权详情" href="../perm_asset_detail/?id={{ user.id }}" class="iframe btn btn-xs btn-primary">详情</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="row">
<div class="col-sm-6">
<div class="dataTables_info" id="editable_info" role="status" aria-live="polite">
Showing {{ contacts2.start_index }} to {{ contacts2.end_index }} of {{ p2.count }} entries
</div>
</div>
<div class="col-sm-6">
<div class="dataTables_paginate paging_simple_numbers" id="editable_paginate">
<ul class="pagination" style="margin-top: 0; float: right">
{% if contacts2.has_previous %}
<li class="paginate_button previous" aria-controls="editable" tabindex="0" id="editable_previous">
<a href="?page={{ contacts2.previous_page_number }}">Previous</a>
</li>
{% else %}
<li class="paginate_button previous disabled" aria-controls="editable" tabindex="0" id="editable_previous">
<a href="#">Previous</a>
</li>
{% endif %}
{% for page in p2.page_range %}
{% ifequal offset1 page %}
<li class="paginate_button active" aria-controls="editable" tabindex="0"><a href="?page={{ page }}" title="第{{ page }}页">{{ page }}</a></li>
{% else %}
<li class="paginate_button" aria-controls="editable" tabindex="0"><a href="?page={{ page }}" title="第{{ page }}页">{{ page }}</a></li>
{% endifequal %}
{% endfor %}
{% if contacts2.has_next %}
<li class="paginate_button next" aria-controls="editable" tabindex="0" id="editable_next">
<a href="?page={{ contacts2.next_page_number }}">Next</a>
</li>
{% else %}
<li class="paginate_button next disabled" aria-controls="editable" tabindex="0" id="editable_next">
<a href="#">Next</a>
</li>
{% endif %}
</ul>
</div>
</div>
</div>
{% endifequal %}

View File

@ -1,12 +1,14 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% load mytags %}
{% 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-12"> <div class="col-sm-10">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div id="ibox-content" class="ibox-title"> <div class="ibox-title">
<h5> 用户权限申请详细信息列表 </h5> <h5> 查看小组</h5>
<div class="ibox-tools"> <div class="ibox-tools">
<a class="collapse-link"> <a class="collapse-link">
<i class="fa fa-chevron-up"></i> <i class="fa fa-chevron-up"></i>
@ -14,12 +16,6 @@
<a class="dropdown-toggle" data-toggle="dropdown" href="#"> <a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i> <i class="fa fa-wrench"></i>
</a> </a>
<ul class="dropdown-menu dropdown-user">
<li><a href="#">未启用 1</a>
</li>
<li><a href="#">未启用 2</a>
</li>
</ul>
<a class="close-link"> <a class="close-link">
<i class="fa fa-times"></i> <i class="fa fa-times"></i>
</a> </a>
@ -27,59 +23,48 @@
</div> </div>
<div class="ibox-content"> <div class="ibox-content">
<div class="panel-options"> <div class="">
<ul class="nav nav-tabs">
<li><a href="/jperm/apply/online/" class="text-center"><i class="fa fa-laptop"></i> 未审批 </a></li>
<li class="active"><a href="/jperm/apply/offline/" class="text-center"><i class="fa fa-bar-chart-o"></i> 已审批 </a></li>
<li style="float: right">
<form id="search_form" method="get" action="" class="pull-right mail-search"> <form id="search_form" method="get" action="" class="pull-right mail-search">
<div class="input-group"> <div class="input-group">
<input type="text" class="form-control input-sm" id="search_input" name="keyword" placeholder="Search"> <input type="text" class="form-control input-sm" id="search_input" name="search" placeholder="Search">
<input type="text" style="display: none">
<div class="input-group-btn"> <div class="input-group-btn">
<button id='search_btn' type="button" class="btn btn-sm btn-primary" onclick="log_search()"> <button id='search_btn' type="submit" class="btn btn-sm btn-primary">
Search - 搜索 -
</button> </button>
</div> </div>
</div> </div>
</form> </form>
</li>
</ul>
</div> </div>
<br/>
<div class="tab-content"> <table class="table table-striped table-bordered table-hover " id="editable" >
<table class="table table-striped table-bordered table-hover ">
<thead> <thead>
<tr> <tr>
<th class="text-center"> 申请人 </th> <th class="text-center">日期</th>
<th class="text-center"> 所属部门 </th> <th class="text-center">动作</th>
<th class="text-center"> 申请主机组 </th> <th class="text-center">成功</th>
<th class="text-center"> 申请主机 </th> <th class="text-center">完成</th>
<th class="text-center"> 申请时间 </th>
<th class="text-center"> 批准时间 </th>
<th class="text-center"> 备注 </th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for post in contacts.object_list %} {% for log in logs %}
<tr class="gradeX"> <tr class="gradeX">
<td class="text-center" id="username"> {{ post.applyer }} </td> <td class="text-center"> {{ log.datetime | date:"Y-n-d G:i:s" }} </td>
<td class="text-center" id="dept"> {{ post.dept }} </td> <td class="text-center"> {{ log.action }} </td>
<td class="text-center" id="ip"> {{ post.bisgroup }} </td> <td class="text-center">
<td class="text-center" id="remote_ip"> {{ post.asset }} </td> <a class="log_result" value="{{ log.results }}">
<!--{% ifnotequal session_role_id 0 %}--> {{ log.is_success | yesno:"是,否,为止" }}
<!--<td class="text-center"><a href="/jlog/history/?id={{ post.id }}" class="log_command"> 命令统计 </td>--> </a>
<!--{% endifnotequal %}--> </td>
<td class="text-center" id="start_time"> {{ post.date_add|date:"Y-m-d H:i:s"}} </td> <td class="text-center"> {{ log.is_finish | yesno:"是,否,为止" }} </td>
<td class="text-center" id="end_time"> {{ post.date_end|date:"Y-m-d H:i:s" }} </td>
<td class="text-center" id=""> {{ post.comment }} </td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
<div class="row"> <div class="row">
<div class="col-sm-6"> <div class="col-sm-6">
<div class="dataTables_info" id="editable_info" role="status" aria-live="polite">
Showing {{ users.start_index }} to {{ users.end_index }} of {{ p.count }} entries
</div>
</div> </div>
{% include 'paginator.html' %} {% include 'paginator.html' %}
</div> </div>
@ -87,7 +72,17 @@
</div> </div>
</div> </div>
</div> </div>
</div>
</div> </div>
{% endblock %} {% endblock %}
{% block self_footer_js %}
<script>
$('document').ready(function(){
$('.log_result').click(function(){
alert($(this).attr('value'))
})
})
</script>
{% endblock %}

View File

@ -1,127 +0,0 @@
{% extends 'base.html' %}
{% load mytags %}
{% block content %}
{% include 'nav_cat_bar.html' %}
<div class="wrapper wrapper-content animated fadeInRight">
<div class="row">
<div class="col-lg-12">
<div class="ibox float-e-margins">
<div id="ibox-content" class="ibox-title">
<h5> 用户权限申请详细信息列表 </h5>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
</a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i>
</a>
<ul class="dropdown-menu dropdown-user">
<li><a href="#">未启用 1</a>
</li>
<li><a href="#">未启用 2</a>
</li>
</ul>
<a class="close-link">
<i class="fa fa-times"></i>
</a>
</div>
</div>
<div class="ibox-content">
<div class="panel-options">
<ul class="nav nav-tabs">
<li><a href="/jperm/apply_show/online/" class="text-center"><i class="fa fa-laptop"></i> 未审批 </a></li>
<li class="active"><a href="/jperm/apply_show/offline/" class="text-center"><i class="fa fa-bar-chart-o"></i> 已审批 </a></li>
<li style="float: right">
<form id="search_form" method="get" action="" class="pull-right mail-search">
<div class="input-group">
<input type="text" class="form-control input-sm" id="search_input" name="keyword" placeholder="Search">
<input type="text" style="display: none">
<div class="input-group-btn">
<button id='search_btn' type="button" class="btn btn-sm btn-primary" onclick="apply_search()">
Search
</button>
</div>
</div>
</form>
</li>
</ul>
</div>
<br/>
<div class="tab-content">
<table class="table table-striped table-bordered table-hover ">
<thead>
<tr>
<th class="text-center"> 申请人 </th>
<th class="text-center"> 所属部门 </th>
<th class="text-center"> 申请主机组 </th>
<th class="text-center"> 申请主机 </th>
<th class="text-center"> 批准人 </th>
<th class="text-center"> 申请时间 </th>
<th class="text-center"> 备注 </th>
<th class="text-center"> 详情 </th>
</tr>
</thead>
<tbody>
{% for post in contacts.object_list %}
<tr class="gradeX">
<td class="text-center" id="username"> {{ post.applyer }} </td>
<td class="text-center" id="dept"> {{ post.dept }} </td>
<td class="text-center" id="ip"> {{ post.bisgroup|ast_to_list }} </td>
<td class="text-center" id="remote_ip">{{ post.asset|ast_to_list }} </td>
<td class="text-center" id="approver"> {{ post.approver }} </td>
<td class="text-center" id="start_time"> {{ post.date_add|date:"Y-m-d H:i:s"}} </td>
<td class="text-center" id=""> {{ post.comment }} </td>
<td class="text-center" data-editable='false'>
<a value="/jperm/apply_info/?uuid={{ post.uuid }}" class="iframe btn btn-xs btn-primary">详情</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="row">
<div class="col-sm-6">
</div>
{% include 'paginator.html' %}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
$(".iframe").on('click', function(){
var url= $(this).attr("value");
$.layer({
type: 2,
title: '权限申请详情',
maxmin: true,
shift: 'top',
border: [2, 0.3, '#1AB394'],
shade: [0.5, '#000000'],
shadeClose: true,
area : ['800px' , '600px'],
iframe: {src: url}
});
});
function apply_search(){
$.ajax({
type: "GET",
url: "/jperm/apply_search/?env=offline",
data: $("#search_form").serialize(),
success: function (data) {
$(".tab-content").html(data);
}
});
}
$("#search_input").keydown(function(e){
if(e.keyCode==13){
apply_search()
}
})
</script>
{% endblock %}

View File

@ -1,128 +0,0 @@
{% extends 'base.html' %}
{% load mytags %}
{% block content %}
{% include 'nav_cat_bar.html' %}
<div class="wrapper wrapper-content animated fadeInRight">
<div class="row">
<div class="col-lg-12">
<div class="ibox float-e-margins">
<div id="ibox-content" class="ibox-title">
<h5> 用户权限申请详细信息列表 </h5>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
</a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i>
</a>
<ul class="dropdown-menu dropdown-user">
<li><a href="#">未启用 1</a>
</li>
<li><a href="#">未启用 2</a>
</li>
</ul>
<a class="close-link">
<i class="fa fa-times"></i>
</a>
</div>
</div>
<div class="ibox-content">
<div class="panel-options">
<ul class="nav nav-tabs">
<li class="active"><a href="/jperm/apply_show/online/" class="text-center"><i class="fa fa-laptop"></i> 未审批 </a></li>
<li><a href="/jperm/apply_show/offline/" class="text-center"><i class="fa fa-bar-chart-o"></i> 已审批 </a></li>
<li style="float: right">
<form id="search_form" method="get" action="" class="pull-right mail-search">
<div class="input-group">
<input type="text" class="form-control input-sm" id="search_input" name="keyword" placeholder="Search">
<input type="text" style="display: none">
<div class="input-group-btn">
<button id='search_btn' type="button" class="btn btn-sm btn-primary" onclick="apply_search()">
Search
</button>
</div>
</div>
</form>
</li>
</ul>
</div>
<br/>
<div class="tab-content">
<table class="table table-striped table-bordered table-hover ">
<thead>
<tr>
<th class="text-center"> 申请人 </th>
<th class="text-center"> 所属部门 </th>
<th class="text-center"> 申请主机组 </th>
<th class="text-center"> 申请主机 </th>
<th class="text-center"> 申请时间 </th>
<th class="text-center"> 备注 </th>
<th class="text-center"> 操作 </th>
</tr>
</thead>
<tbody>
{% for post in contacts.object_list %}
<tr class="gradeX">
<td class="text-center" id="username"> {{ post.applyer }} </td>
<td class="text-center" id="dept"> {{ post.dept }} </td>
<td class="text-center" id="ip"> {{ post.bisgroup|ast_to_list }}</td>
<td class="text-center" id="remote_ip"> {{ post.asset|ast_to_list }} </td>
<td class="text-center" id="start_time"> {{ post.date_add|date:"Y-m-d H:i:s"}} </td>
<td class="text-center" id=""> {{ post.comment }} </td>
<td class="text-center" data-editable='false'>
<a value="/jperm/apply_info/?uuid={{ post.uuid }}" class="iframe btn btn-xs btn-primary">详情</a>
{% ifnotequal session_role_id 0 %}
<a href="/jperm/apply_exec/?uuid={{ post.uuid }}" class="btn btn-xs btn-info">确认</a>
<a href="/jperm/apply_del/?uuid={{ post.uuid }}" class="btn btn-xs btn-danger">删除</a>
{% endifnotequal %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="row">
<div class="col-sm-6">
</div>
{% include 'paginator.html' %}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
$(".iframe").on('click', function(){
var url= $(this).attr("value");
$.layer({
type: 2,
title: '权限申请详情',
maxmin: true,
shift: 'top',
border: [2, 0.3, '#1AB394'],
shade: [0.5, '#000000'],
shadeClose: true,
area : ['800px' , '600px'],
iframe: {src: url}
});
});
function apply_search(){
$.ajax({
type: "GET",
url: "/jperm/apply_search/?env=online",
data: $("#search_form").serialize(),
success: function (data) {
$(".tab-content").html(data);
}
});
}
$("#search_input").keydown(function(e){
if(e.keyCode==13){
apply_search()
}
})
</script>
{% endblock %}

View File

@ -1,240 +0,0 @@
{% extends 'base.html' %}
{% load mytags %}
{% block content %}
{% include 'nav_cat_bar.html' %}
<div class="wrapper wrapper-content animated fadeInRight">
<div class="row">
<div class="col-lg-10">
<div class="ibox float-e-margins">
<div class="ibox-title">
<h5> 用户授权详情</h5>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
</a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i>
</a>
<ul class="dropdown-menu dropdown-user">
<li><a href="#">未启用 1</a>
</li>
<li><a href="#">未启用 2</a>
</li>
</ul>
<a class="close-link">
<i class="fa fa-times"></i>
</a>
</div>
</div>
<div class="ibox-content">
<div class="panel blank-panel">
<div class="panel-heading">
<div class="panel-options">
<ul class="nav nav-tabs">
<li id="tab1" class="active"><a data-toggle="tab" href="/perm_list/">授权查看</a></li>
<li id="tab2" class=""><a data-toggle="tab" href="/perm_user_detail/">用户授权详情</a></li>
<li style="float: right">
<form method="get" action="" class="pull-right mail-search">
<div class="input-group">
<input type="text" class="form-control input-sm" id="search_input" name="search" placeholder="Search">
<div class="input-group-btn">
<button id='search_btn' type="button" class="btn btn-sm btn-primary">
Search
</button>
</div>
</div>
</form>
</li>
</ul>
</div>
</div>
<div class="panel-body">
<div class="tab-content">
<div id="tab-1" class="tab-pane active">
<table class="table table-striped table-bordered table-hover " id="editable" >
<thead>
<tr>
<th class="text-center">名称</th>
<th class="text-center">用户组</th>
<th class="text-center">主机组</th>
<th class="text-center">备注</th>
<th class="text-center">操作</th>
</tr>
</thead>
<tbody id="perm_edit">
{% for perm in contacts.object_list %}
<tr class="gradeX">
<td class="text-center"> {{ perm.name }} </td>
<td class="text-center">
{% for user_group in perm.user_group.all %}
{{ user_group.name }}
{% endfor %}
</td>
<td class="text-center">
{% for asset_group in perm.asset_group.all %}
{{ asset_group.name }}
{% endfor %}
</td>
<td class="text-center"> {{ perm.comment }} </td>
<td class="text-center">
<a title="[ {{ group.name }} 授权详情 ]" href="../perm_detail/?id={{ perm.id }}" class=" btn btn-xs btn-primary">详情</a>
<a href="../perm_edit/?id={{ perm.id }}" class="btn btn-xs btn-info">编辑</a>
<a href="../perm_del/?id={{ perm.id }}" class="btn btn-xs btn-danger">删除</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="row">
<div class="col-sm-6">
<div class="dataTables_info" id="editable_info" role="status" aria-live="polite">
Showing {{ contacts.start_index }} to {{ contacts.end_index }} of {{ p.count }} entries
</div>
</div>
<div class="col-sm-6">
<div class="dataTables_paginate paging_simple_numbers" id="editable_paginate">
<ul class="pagination" style="margin-top: 0; float: right">
{% if contacts.has_previous %}
<li class="paginate_button previous" aria-controls="editable" tabindex="0" id="editable_previous">
<a href="?page={{ contacts.previous_page_number }}">Previous</a>
</li>
{% else %}
<li class="paginate_button previous disabled" aria-controls="editable" tabindex="0" id="editable_previous">
<a href="#">Previous</a>
</li>
{% endif %}
{% for page in page_range %}
{% ifequal current_page page %}
<li class="paginate_button active" aria-controls="editable" tabindex="0"><a href="?page={{ page }}" title="第{{ page }}页">{{ page }}</a></li>
{% else %}
<li class="paginate_button" aria-controls="editable" tabindex="0"><a href="?page={{ page }}" title="第{{ page }}页">{{ page }}</a></li>
{% endifequal %}
{% endfor %}
{% if contacts.has_next %}
<li class="paginate_button next" aria-controls="editable" tabindex="0" id="editable_next">
<a href="?page={{ contacts.next_page_number }}">Next</a>
</li>
{% else %}
<li class="paginate_button next disabled" aria-controls="editable" tabindex="0" id="editable_next">
<a href="#">Next</a>
</li>
{% endif %}
</ul>
</div>
</div>
</div>
</div>
<div id="tab-2" class="tab-pane">
{# <table class="table table-striped table-bordered table-hover " id="editable" >#}
{# <thead>#}
{# <tr>#}
{# <th class="text-center">用户</th>#}
{# <th class="text-center">角色</th>#}
{# <th class="text-center">属组</th>#}
{# <th class="text-center">主机数量</th>#}
{# <th class="text-center">操作</th>#}
{# </tr>#}
{# </thead>#}
{# <tbody id="perm_list">#}
{# {% for user in contacts2.object_list %}#}
{# <tr class="gradeX">#}
{# <td class="text-center"> {{ user.name }} </td>#}
{# <td class="text-center"> {{ user.id | get_role }} </td>#}
{# <td class="text-center"> {{ user.username | groups_str }} </td>#}
{# <td class="text-center"> {{ user.id | perm_asset_count }} </td>#}
{# <td class="text-center">#}
{# <a title="[ {{ user.name }} ] 授权详情" href="../perm_asset_detail/?id={{ user.id }}" class="btn btn-xs btn-primary">详情</a>#}
{# </td>#}
{# </tr>#}
{# {% endfor %}#}
{# </tbody>#}
{# </table>#}
{# <div class="row">#}
{# <div class="col-sm-6">#}
{# <div class="dataTables_info" id="editable_info" role="status" aria-live="polite">#}
{# Showing {{ contacts2.start_index }} to {{ contacts2.end_index }} of {{ p2.count }} entries#}
{# </div>#}
{# </div>#}
{# <div class="col-sm-6">#}
{# <div class="dataTables_paginate paging_simple_numbers" id="editable_paginate">#}
{# <ul class="pagination" style="margin-top: 0; float: right">#}
{# {% if contacts2.has_previous %}#}
{# <li class="paginate_button previous" aria-controls="editable" tabindex="0" id="editable_previous">#}
{# <a href="?page={{ contacts2.previous_page_number }}">Previous</a>#}
{# </li>#}
{# {% else %}#}
{# <li class="paginate_button previous disabled" aria-controls="editable" tabindex="0" id="editable_previous">#}
{# <a href="#">Previous</a>#}
{# </li>#}
{# {% endif %}#}
{# {% for page in page_range2 %}#}
{# {% ifequal current_page page %}#}
{# <li class="paginate_button active" aria-controls="editable" tabindex="0"><a href="?page={{ page }}" title="第{{ page }}页">{{ page }}</a></li>#}
{# {% else %}#}
{# <li class="paginate_button" aria-controls="editable" tabindex="0"><a href="?page={{ page }}" title="第{{ page }}页">{{ page }}</a></li>#}
{# {% endifequal %}#}
{# {% endfor %}#}
{# {% if contacts2.has_next %}#}
{# <li class="paginate_button next" aria-controls="editable" tabindex="0" id="editable_next">#}
{# <a href="?page={{ contacts2.next_page_number }}">Next</a>#}
{# </li>#}
{# {% else %}#}
{# <li class="paginate_button next disabled" aria-controls="editable" tabindex="0" id="editable_next">#}
{# <a href="#">Next</a>#}
{# </li>#}
{# {% endif %}#}
{# </ul>#}
{# </div>#}
{# </div>#}
{# </div>#}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function(){
$(".iframe").colorbox({iframe:true, width:"70%", height:"70%"});
});
$(document).ready(function(){
$('#search_btn').click(function(){
if ($('#tab2').attr('class') == 'active'){
var tab='tab2'
} else {
var tab='tab1'
}
var search=$('#search_input').val()
$.post('/jperm/perm_list_ajax/',
{'tab': tab, 'search': search},
function(data){
if ($('#tab2').attr('class') == 'active'){
$('#tab-2').html(data)
} else {
$('#tab-1').html(data)
}
})
})
})
</script>
{% endblock %}

View File

@ -1,226 +0,0 @@
{% extends 'base.html' %}
{% load mytags %}
{% block content %}
{% include 'nav_cat_bar.html' %}
<div class="wrapper wrapper-content animated fadeInRight">
<div class="row">
<div class="col-lg-10">
<div class="ibox float-e-margins">
<div class="ibox-title">
<h5> Sudo授权添加</h5>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
</a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i>
</a>
<ul class="dropdown-menu dropdown-user">
<li><a href="#">未启用 1</a>
</li>
<li><a href="#">未启用 2</a>
</li>
</ul>
<a class="close-link">
<i class="fa fa-times"></i>
</a>
</div>
</div>
<div class="panel blank-panel">
<div class="panel-heading">
<div class="panel-options">
<ul class="nav nav-tabs">
<li id="tab1" class=""><a href="/jperm/sudo_list/">查看Sudo授权</a></li>
<li id="tab2" class="active"><a href="/jperm/sudo_add/">Sudo授权添加</a></li>
<li id="tab3" class=""><a href="/jperm/cmd_list/">查看命令组</a></li>
<li id="tab4" class=""><a href="/jperm/cmd_add/">添加命令组</a></li>
</ul>
</div>
</div>
<div class="panel-body">
<div class="tab-content">
<div id="tab-1" class="tab-pane active">
<form id="sudoPerm" method="post" class="form-horizontal" action="">
{% if error %}
<div class="alert alert-warning text-center">{{ error }}</div>
{% endif %}
{% if msg %}
<div class="alert alert-success text-center">{{ msg }}</div>
{% endif %}
<div class="row">
<div class="form-group">
<label for="name" class="col-sm-2 control-label">授权名<span class="red-fonts">*</span></label>
<div class="col-sm-8">
<input id="name" name="name" placeholder="OnlyForEnglish" type="text" class="form-control">
<span class="help-block m-b-none">取个名字方便辨识,只支持英文</span>
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="runas" class="col-sm-2 control-label">RunAsUser<span class="red-fonts">*</span></label>
<div class="col-sm-8">
<input id="runas" name="runas" placeholder="RunAsUser" type="text" class="form-control">
<span class="help-block m-b-none">
允许以哪个用户允许sudo,逗号分隔,默认root
</span>
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="" class="col-sm-2 control-label">用户组<span class="red-fonts">*</span></label>
<div class="col-sm-4">
<div>
<select id="user_groups" name="user_groups" class="form-control" size="5" multiple>
{% for user_group in user_groups %}
<option value="{{ user_group.id }}">{{ user_group.name }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="col-sm-1">
<div class="btn-group" style="margin-top: 12px;">
<button type="button" class="btn btn-white" onclick="move('user_groups', 'user_groups_select')"><i class="fa fa-chevron-right"></i></button>
<button type="button" class="btn btn-white" onclick="move('user_groups_select', 'user_groups')"><i class="fa fa-chevron-left"></i> </button>
</div>
</div>
<div class="col-sm-3">
<div>
<select id="user_groups_select" name="user_groups_select" class="form-control m-b" size="5" multiple>
</select>
</div>
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="" class="col-sm-2 control-label">主机组<span class="red-fonts">*</span></label>
<div class="col-sm-4">
<div>
<select id="asset_groups" name="asset_groups" class="form-control m-b" size="5" multiple>
{% for asset_group in asset_groups %}
<option value="{{ asset_group.id }}">{{ asset_group.name }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="col-sm-1">
<div class="btn-group" style="margin-top: 12px;">
<button type="button" class="btn btn-white" onclick="move('asset_groups', 'asset_groups_select')"><i class="fa fa-chevron-right"></i></button>
<button type="button" class="btn btn-white" onclick="move('asset_groups_select', 'asset_groups')"><i class="fa fa-chevron-left"></i> </button>
</div>
</div>
<div class="col-sm-3">
<div>
<select id="asset_groups_select" name="asset_groups_select" class="form-control m-b" size="5" multiple>
</select>
</div>
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="" class="col-sm-2 control-label">命令组<span class="red-fonts">*</span></label>
<div class="col-sm-4">
<div>
<select id="cmd_groups" name="cmd_groups" class="form-control m-b" size="5" multiple>
{% for cmd_group in cmd_groups %}
<option value="{{ cmd_group.id }}">{{ cmd_group.name }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="col-sm-1">
<div class="btn-group" style="margin-top: 12px;">
<button type="button" class="btn btn-white" onclick="move('cmd_groups', 'cmd_groups_select')"><i class="fa fa-chevron-right"></i></button>
<button type="button" class="btn btn-white" onclick="move('cmd_groups_select', 'cmd_groups')"><i class="fa fa-chevron-left"></i> </button>
</div>
</div>
<div class="col-sm-3">
<div>
<select id="cmd_groups_select" name="cmd_groups_select" class="form-control m-b" size="5" multiple>
</select>
</div>
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="group_name" class="col-sm-2 control-label">备注</label>
<div class="col-sm-8">
<input id="comment" name="comment" placeholder="备注说明" type="text" class="form-control">
</div>
</div>
<div class="hr-line-dashed"></div>
</div>
<div class="row">
<div class="form-group">
<div class="col-sm-4 col-sm-offset-2">
<button class="btn btn-white" type="reset">取消</button>
<button id="submit_button" class="btn btn-primary" type="submit">确认保存</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
$('#sudoPerm').validator({
timely: 2,
theme: "yellow_right_effect",
fields: {
"name": {
rule: "required",
tip: "输入授权名",
ok: "",
msg: {required: "必须填写!"}
},
"runas": {
rule: "required",
tip: "输入sudoas用户",
ok: "",
msg: {required: "必须填写!"}
}
},
valid: function(form) {
form.submit();
}
});
$(document).ready(function(){
$("#submit_button").click(function(){
$('#sudoPerm option').each(function(){
$(this).prop('selected', true)
})
})
})
</script>
{% endblock %}

View File

@ -1,148 +0,0 @@
{% extends 'base.html' %}
{% block content %}
{% include 'nav_cat_bar.html' %}
<div class="wrapper wrapper-content animated fadeInRight">
<div class="row">
<div class="col-lg-10">
<div class="ibox float-e-margins">
<div class="ibox-title">
<h5>填写基本信息</h5>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
</a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i>
</a>
<ul class="dropdown-menu dropdown-user">
<li><a href="#">未启用 1</a>
</li>
<li><a href="#">未启用 2</a>
</li>
</ul>
<a class="close-link">
<i class="fa fa-times"></i>
</a>
</div>
</div>
<div class="ibox-content">
<div class="panel blank-panel">
<div class="panel-heading">
<div class="panel-options">
<ul class="nav nav-tabs">
<li id="tab1" class=""><a href="/jperm/sudo_list/">查看Sudo授权</a></li>
<li id="tab2" class=""><a href="/jperm/cmd_list/">查看命令组</a></li>
<li id="tab3" class="active"><a href="/jperm/cmd_add/">添加命令组</a></li>
</ul>
</div>
</div>
<div class="panel-body">
<div class="tab-content">
<div id="tab-1" class="tab-pane active">
<form id="cmdForm" method="post" class="form-horizontal" action="">
{% if error %}
<div class="alert alert-warning text-center">{{ error }}</div>
{% endif %}
{% if msg %}
<div class="alert alert-success text-center">{{ msg }}</div>
{% endif %}
<div class="form-group">
<label for="group_name" class="col-sm-2 control-label">组名<span class="red-fonts">*</span></label>
<div class="col-sm-8">
<input id="name" name="name" placeholder="Group name" type="text" class="form-control" value="{{ name }}" required="">
<input id="cmd_group_id" name="cmd_group_id" type="text" class="form-control" value="{{ cmd_group_id }}" style="display: none">
</div>
</div>
{% ifequal session_role_id 2 %}
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="dept_id" class="col-sm-2 control-label">部门<span class="red-fonts">*</span></label>
<div class="col-sm-8">
<select id="dept_id" name="dept_id" class="form-control m-b">
{% for dept in dept_all %}
{% ifequal dept_id dept.id %}
<option value="{{ dept.id }}" selected>{{ dept.name }}</option>
{% else %}
<option value="{{ dept.id }}">{{ dept.name }}</option>
{% endifequal %}
{% endfor %}
</select>
</div>
</div>
{% endifequal %}
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="group_type" class="col-sm-2 control-label">命令<span class="red-fonts">*</span></label>
<div class="col-sm-8">
<textarea id='cmd' name='cmd' class="form-control" rows="10" placeholder="/bin/su">{{ cmd }}</textarea>
<span class="help-block m-b-none">
输入命令一行一个,请写绝对路径如: /bin/su所有是ALL排除su是 !/bin/su
</span>
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="group_name" class="col-sm-2 control-label">备注</label>
<div class="col-sm-8">
<input id="comment" name="comment" placeholder="备注说明" type="text" class="form-control" value="{{ comment }}">
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<div class="col-sm-4 col-sm-offset-2">
<button class="btn btn-white" type="reset">取消</button>
<button id="submit_button" class="btn btn-primary" type="submit">确认保存</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
$('#cmdForm').validator({
timely: 2,
theme: "yellow_right_effect",
fields: {
"name": {
rule: "required",
tip: "输入组名",
ok: "",
msg: {required: "必须填写!"}
},
"cmd": {
rule: "required",
tip: "输入组名",
ok: "",
msg: {required: "必须填写!"}
}
},
valid: function(form) {
form.submit();
}
});
$(document).ready(function(){
$("#submit_button").click(function(){
$('#users_selected option').each(function(){
$(this).prop('selected', true)
})
})
})
</script>
{% endblock %}

Some files were not shown because too many files have changed in this diff Show More