merge with dev
|
@ -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/*
|
||||||
|
|
78
README.md
|
@ -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)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
__author__ = 'Hudie'
|
|
|
@ -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
|
|
||||||
输入部分IP,verify_connect匹配该部分ip,如果是匹配到多个,就显示ip
|
|
||||||
匹配到0了就显示没有权限或者主机,
|
|
||||||
匹配到1个则继续
|
|
||||||
查询该服务器是否支持ldap 如果是,获得ldap用户密码登陆
|
|
||||||
如果否,查询授权表,查看该服务器授权的角色,并返回对应账号密码,登陆
|
|
||||||
connect函数是登陆函数,采用paramiko 使用channel登陆,posix_shell 来完成交互,并记录日志
|
|
||||||
signal模块来完成窗口改变导致的tty大小随之改变
|
|
||||||
PyCrypt是对称加密类
|
|
135
docs/install.py
|
@ -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()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
|
@ -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
|
|
113
jasset/models.py
|
@ -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
|
||||||
|
|
|
@ -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),
|
|
||||||
)
|
)
|
1334
jasset/views.py
|
@ -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)
|
||||||
|
|
||||||
|
|
||||||
|
|
12
jlog/urls.py
|
@ -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'),
|
||||||
)
|
)
|
180
jlog/views.py
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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'),
|
|
||||||
)
|
|
||||||
|
|
1215
jperm/views.py
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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')
|
||||||
|
]
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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'),
|
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
|
@ -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))
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
from django.test import TestCase
|
|
||||||
|
|
||||||
# Create your tests here.
|
|
|
@ -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'),
|
|
||||||
)
|
|
||||||
|
|
843
juser/views.py
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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;}
|
||||||
|
|
Before Width: | Height: | Size: 105 KiB After Width: | Height: | Size: 106 KiB |
|
@ -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(",");
|
||||||
|
}
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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'));
|
||||||
|
|
||||||
|
|
Before Width: | Height: | Size: 7.5 KiB |
Before Width: | Height: | Size: 210 B |
Before Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 5.7 KiB |
Before Width: | Height: | Size: 701 B |
Before Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 221 B |
|
@ -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;}
|
|
||||||
|
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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 %}
|
|
@ -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>
|
||||||
|
|
|
@ -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 © 2014-2015
|
<strong>Copyright</strong> Jumpserver.org Team © 2014-2015
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
||||||
|
|
|
@ -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 %}
|
|
@ -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>
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
{% for host in hosts %}
|
|
||||||
<option value="{{ host.id }}">{{ host.ip }}</option>
|
|
||||||
{% endfor %}
|
|
|
@ -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},
|
||||||
|
|
|
@ -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 %}
|
|
|
@ -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>
|
||||||
|
|
|
@ -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 %}
|
||||||
|
|
|
@ -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 %}
|
|
|
@ -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 %}
|
|
|
@ -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 %}
|
|
|
@ -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 %}
|
|
|
@ -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 %}
|
|
|
@ -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 %}
|
|
|
@ -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 %}
|
|
|
@ -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>
|
|
|
@ -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 %}
|
|
@ -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 %}
|
|
|
@ -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 %}
|
|
@ -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 %}
|
|
@ -1,10 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head lang="en">
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<title>资产管理</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>welocome!</h1>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -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>
|
|
|
@ -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 %}
|
|
@ -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")
|
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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 %}
|
|
|
@ -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 %}
|
|
|
@ -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 %}
|
|
|
@ -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 %}
|
|
|
@ -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 %}
|
|
|
@ -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>
|
|
|
@ -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>
|
|
|
@ -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 %}
|
|
|
@ -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 %}
|
|
|
@ -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 %}
|
|
|
@ -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 %}
|
|
|
@ -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 %}
|
|
|
@ -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 %}
|
|
|
@ -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 %}
|
|
@ -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 %}
|
|
|
@ -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 %}
|
|
|
@ -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 %}
|
|
|
@ -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 %}
|
|
|
@ -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 %}
|
|