Commit 26804b40 authored by ibuler's avatar ibuler

Merge pull request #174 from jumpserver/dev

Release 0.3.1 version, Fix most bugs
parents d7442b48 8ebcd475
This diff is collapsed.
#!/bin/bash
#
trap '' SIGINT
base_dir=$(dirname $0)
export LANG='zh_CN.UTF-8'
python $base_dir/connect.py
exit
This diff is collapsed.
This diff is collapsed.
......@@ -5,9 +5,11 @@ import sys
import os
import django
from django.core.management import execute_from_command_line
import shutil
import shlex
import urllib
import socket
import subprocess
jms_dir = os.path.dirname(os.path.abspath(os.path.dirname(__file__)))
sys.path.append(jms_dir)
......@@ -41,9 +43,6 @@ class Setup(object):
version = urllib.urlopen('http://jumpserver.org/version/?id=%s' % mac)
except:
pass
os.chdir(jms_dir)
os.chmod('logs', 0777)
os.chmod('keys', 0777)
def _input_admin(self):
while True:
......@@ -78,27 +77,34 @@ class Setup(object):
user.delete()
db_add_user(username=self.admin_user, password=self.admin_pass, role='SU', name='admin', groups='',
admin_groups='', email='admin@jumpserver.org', uuid='MayBeYouAreTheFirstUser', is_active=True)
os.system('id %s &> /dev/null || useradd %s' % (self.admin_user, self.admin_user))
cmd = 'id %s 2> /dev/null 1> /dev/null || useradd %s' % (self.admin_user, self.admin_user)
shlex.os.system(cmd)
@staticmethod
def _cp_zzsh():
os.chdir(os.path.join(jms_dir, 'install'))
shutil.copy('zzjumpserver.sh', '/etc/profile.d/')
bash("sed -i 's#/opt/jumpserver#%s#g' /etc/profile.d/zzjumpserver.sh" % jms_dir)
def _chmod_file():
os.chdir(jms_dir)
os.chmod('init.sh', 0755)
os.chmod('connect.py', 0755)
os.chmod('manage.py', 0755)
os.chmod('run_server.py', 0755)
os.chmod('service.sh', 0755)
os.chmod('logs', 0777)
os.chmod('keys', 0777)
@staticmethod
def _run_service():
os.system('sh %s start' % os.path.join(jms_dir, 'service.sh'))
cmd = 'bash %s start' % os.path.join(jms_dir, 'service.sh')
shlex.os.system(cmd)
print
color_print('安装成功,请访问web, 祝你使用愉快。\n请访问 https://github.com/ibuler/jumpserver 查看文档', 'green')
color_print('安装成功,请访问web, 祝你使用愉快。\n请访问 https://github.com/jumpserver/jumpserver/wiki 查看文档', 'green')
def start(self):
print "开始安装Jumpserver, 要求环境为 CentOS 6.5 x86_64"
print "开始安装Jumpserver ..."
self._pull()
self._sync_db()
self._input_admin()
self._create_admin()
self._cp_zzsh()
self._chmod_file()
self._run_service()
......
......@@ -15,3 +15,5 @@ pyinotify==0.9.6
passlib==1.6.5
argparse==1.4.0
django_crontab==0.6.0
django-smtp-ssl==1.0
pyte==0.5.2
\ No newline at end of file
#!/bin/bash
export LANG='zh_CN.UTF-8'
if [ "$USER" != "admin" ] && [ "$USER" != "root" ];then
python /opt/jumpserver/connect.py
if [ $USER == 'guanghongwei' ];then
echo
else
exit 3
echo
fi
fi
......@@ -9,6 +9,8 @@ from jperm.ansible_api import MyRunner
from jperm.perm_api import gen_resource
from jumpserver.templatetags.mytags import get_disk_info
import traceback
def group_add_asset(group, asset_id=None, asset_ip=None):
"""
......@@ -333,9 +335,11 @@ def get_ansible_asset_info(asset_ip, setup_info):
# ip = setup_info.get("ansible_default_ipv4").get("address")
mac = setup_info.get("ansible_default_ipv4").get("macaddress")
brand = setup_info.get("ansible_product_name")
try:
cpu_type = setup_info.get("ansible_processor")[1]
cpu_cores = setup_info.get("ansible_processor_vcpus")
cpu = cpu_type + ' * ' + unicode(cpu_cores)
except IndexError:
cpu_type = ' '.join(setup_info.get("ansible_processor")[0].split(' ')[:6])
memory = setup_info.get("ansible_memtotal_mb")
try:
memory_format = int(round((int(memory) / 1000), 0))
......@@ -343,7 +347,13 @@ def get_ansible_asset_info(asset_ip, setup_info):
memory_format = memory
disk = disk_need
system_type = setup_info.get("ansible_distribution")
if system_type.lower() == "freebsd":
system_version = setup_info.get("ansible_distribution_release")
cpu_cores = setup_info.get("ansible_processor_count")
else:
system_version = setup_info.get("ansible_distribution_version")
cpu_cores = setup_info.get("ansible_processor_vcpus")
cpu = cpu_type + ' * ' + unicode(cpu_cores)
system_arch = setup_info.get("ansible_architecture")
# asset_type = setup_info.get("ansible_system")
sn = setup_info.get("ansible_product_serial")
......@@ -359,10 +369,14 @@ def asset_ansible_update(obj_list, name=''):
for asset in obj_list:
try:
setup_info = ansible_asset_info['contacted'][asset.hostname]['ansible_facts']
except KeyError:
logger.debug("setup_info: %s" % setup_info)
except KeyError, e:
logger.error("获取setup_info失败: %s" % e)
continue
else:
try:
asset_info = get_ansible_asset_info(asset.ip, setup_info)
print asset_info
other_ip, mac, cpu, memory, disk, sn, system_type, system_version, brand, system_arch = asset_info
asset_dic = {"other_ip": other_ip,
"mac": mac,
......@@ -377,6 +391,9 @@ def asset_ansible_update(obj_list, name=''):
}
ansible_record(asset, asset_dic, name)
except Exception as e:
logger.error("save setup info failed! %s" % e)
traceback.print_exc()
def asset_ansible_update_all():
......
......@@ -15,12 +15,11 @@ from struct import unpack
from subprocess import Popen
from sys import platform, prefix, stderr
from tempfile import NamedTemporaryFile
from jumpserver.api import logger
from jinja2 import FileSystemLoader, Template
from jinja2.environment import Environment
from jumpserver.api import BASE_DIR
from jumpserver.api import BASE_DIR, logger
from jlog.models import Log
......@@ -104,3 +103,4 @@ def kill_invalid_connection():
log.end_time = now
log.save()
logger.warn('kill log %s' % log.log_path)
from django.db import models
from juser.models import User
import time
class Log(models.Model):
......@@ -11,6 +13,20 @@ class Log(models.Model):
pid = models.IntegerField()
is_finished = models.BooleanField(default=False)
end_time = models.DateTimeField(null=True)
filename = models.CharField(max_length=40)
'''
add by liuzheng
'''
# userMM = models.ManyToManyField(User)
# logPath = models.TextField()
# filename = models.CharField(max_length=40)
# logPWD = models.TextField() # log zip file's
# nick = models.TextField(null=True) # log's nick name
# log = models.TextField(null=True)
# history = models.TextField(null=True)
# timestamp = models.IntegerField(default=int(time.time()))
# datetimestamp = models.DateTimeField(auto_now_add=True)
def __unicode__(self):
return self.log_path
......@@ -47,3 +63,13 @@ class FileLog(models.Model):
datetime = models.DateTimeField(auto_now=True)
class TermLog(models.Model):
user = models.ManyToManyField(User)
logPath = models.TextField()
filename = models.CharField(max_length=40)
logPWD = models.TextField() # log zip file's
nick = models.TextField(null=True) # log's nick name
log = models.TextField(null=True)
history = models.TextField(null=True)
timestamp = models.IntegerField(default=int(time.time()))
datetimestamp = models.DateTimeField(auto_now_add=True)
This diff is collapsed.
......@@ -26,7 +26,7 @@ class PermSudo(models.Model):
class PermRole(models.Model):
name = models.CharField(max_length=100, unique=True)
comment = models.CharField(max_length=100, null=True, blank=True, default='')
password = models.CharField(max_length=100)
password = models.CharField(max_length=128)
key_path = models.CharField(max_length=100)
date_added = models.DateTimeField(auto_now=True)
sudo = models.ManyToManyField(PermSudo, related_name='perm_role')
......
......@@ -182,8 +182,9 @@ def gen_resource(ob, perm=None):
info = {'hostname': asset.hostname,
'ip': asset.ip,
'port': asset_info.get('port', 22),
'ansible_ssh_private_key_file': role_key,
'username': role.name,
'password': CRYPTOR.decrypt(role.password)
# 'password': CRYPTOR.decrypt(role.password)
}
if os.path.isfile(role_key):
......
......@@ -68,6 +68,12 @@ def gen_keys(key="", key_path_dir=""):
return key_path_dir
def trans_all(str):
if str.strip().lower() == "all":
return str.upper()
else:
return str
if __name__ == "__main__":
print gen_keys()
......
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db.models import Q
from django.http import HttpResponseBadRequest, HttpResponseNotAllowed
......@@ -10,7 +11,7 @@ from jasset.models import Asset, AssetGroup
from jperm.models import PermRole, PermRule, PermSudo, PermPush
from jumpserver.models import Setting
from jperm.utils import gen_keys
from jperm.utils import gen_keys, trans_all
from jperm.ansible_api import MyTask
from jperm.perm_api import get_role_info, get_role_push_host
from jumpserver.api import my_render, get_object, CRYPTOR
......@@ -512,18 +513,18 @@ def perm_role_push(request):
task = MyTask(push_resource)
ret = {}
# 因为要先建立用户,所以password 是必选项,而push key是在 password也完成的情况下的 可选项
# 因为要先建立用户,而push key是在 password也完成的情况下的 可选项
# 1. 以秘钥 方式推送角色
if key_push:
ret["pass_push"] = task.add_user(role.name, CRYPTOR.decrypt(role.password))
ret["pass_push"] = task.add_user(role.name)
ret["key_push"] = task.push_key(role.name, os.path.join(role.key_path, 'id_rsa.pub'))
# 2. 推送账号密码
elif password_push:
ret["pass_push"] = task.add_user(role.name, CRYPTOR.decrypt(role.password))
# 2. 推送账号密码 <为了安全 系统用户统一使用秘钥进行通信, 不再提供密码方式的推送>
# elif password_push:
# ret["pass_push"] = task.add_user(role.name, CRYPTOR.decrypt(role.password))
# 3. 推送sudo配置文件
if password_push or key_push:
if key_push:
sudo_list = set([sudo for sudo in role.sudo.all()]) # set(sudo1, sudo2, sudo3)
if sudo_list:
ret['sudo'] = task.push_sudo_file([role], sudo_list)
......@@ -619,7 +620,9 @@ def perm_sudo_add(request):
raise ServerError(u"sudo name 和 commands是必填项!")
pattern = re.compile(r'[\n,\r]')
commands = ', '.join(list_drop_str(pattern.split(commands), u''))
deal_space_commands = list_drop_str(pattern.split(commands), u'')
deal_all_commands = map(trans_all, deal_space_commands)
commands = ', '.join(deal_all_commands)
logger.debug(u'添加sudo %s: %s' % (name, commands))
if get_object(PermSudo, name=name):
......@@ -656,7 +659,9 @@ def perm_sudo_edit(request):
raise ServerError(u"sudo name 和 commands是必填项!")
pattern = re.compile(r'[\n,\r]')
commands = ', '.join(list_drop_str(pattern.split(commands), u'')).strip()
deal_space_commands = list_drop_str(pattern.split(commands), u'')
deal_all_commands = map(trans_all, deal_space_commands)
commands = ', '.join(deal_all_commands).strip()
logger.debug(u'添加sudo %s: %s' % (name, commands))
sudo.name = name.strip()
......@@ -701,8 +706,14 @@ def perm_role_recycle(request):
recycle_assets.append(asset)
recycle_resource = gen_resource(recycle_assets)
task = MyTask(recycle_resource)
# TODO: 判断返回结果,处理异常
msg = task.del_user(get_object(PermRole, id=role_id).name)
try:
msg_del_user = task.del_user(get_object(PermRole, id=role_id).name)
msg_del_sudo = task.del_user_sudo(get_object(PermRole, id=role_id).name)
logger.info("recycle user msg: %s" % msg_del_user)
logger.info("recycle sudo msg: %s" % msg_del_sudo)
except Exception, e:
logger.warning("Recycle Role failed: %s" % e)
raise ServerError(u"回收已推送的系统用户失败: %s" % e)
for asset_id in asset_ids:
asset = get_object(Asset, id=asset_id)
......
[base]
url = http://192.168.244.129
key = 88aaaf7ffe3c6c04
url = http://127.0.0.1
key = 941enj9neshd1wes
ip = 0.0.0.0
port = 8000
log = debug
[db]
......@@ -10,14 +12,11 @@ user = jumpserver
password = mysql234
database = jumpserver
[websocket]
web_socket_host = 192.168.244.129:3000
[mail]
mail_enable = 1
email_host = smtp.qq.com
email_port = 25
email_host_user = xxxxxxxx@qq.com
email_host_password = xxxxxx
email_use_tls = False
email_host =
email_port = 587
email_host_user =
email_host_password =
email_use_tls = True
email_use_ssl = False
......@@ -484,7 +484,8 @@ def my_render(template, data, request):
def get_tmp_dir():
dir_name = os.path.join('/tmp', uuid.uuid4().hex)
seed = uuid.uuid4().hex[:4]
dir_name = os.path.join('/tmp', '%s-%s' % (datetime.datetime.now().strftime('%Y%m%d-%H%M%S'), seed))
mkdir(dir_name, mode=0777)
return dir_name
......
......@@ -33,6 +33,11 @@ EMAIL_PORT = config.get('mail', 'email_port')
EMAIL_HOST_USER = config.get('mail', 'email_host_user')
EMAIL_HOST_PASSWORD = config.get('mail', 'email_host_password')
EMAIL_USE_TLS = config.getboolean('mail', 'email_use_tls')
try:
EMAIL_USE_SSL = config.getboolean('mail', 'email_use_ssl')
except ConfigParser.NoOptionError:
EMAIL_USE_SSL = False
EMAIL_BACKEND = 'django_smtp_ssl.SSLEmailBackend' if EMAIL_USE_SSL else 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_TIMEOUT = 5
# ======== Log ==========
......@@ -41,7 +46,8 @@ 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')
IP = config.get('base', 'ip')
PORT = config.get('base', 'port')
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.7/howto/deployment/checklist/
......
......@@ -286,7 +286,7 @@ def upload(request):
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='*')
% (upload_dir, '/tmp'), pattern='*')
ret = runner.results
logger.debug(ret)
FileLog(user=request.user.username, host=' '.join([asset.hostname for asset in asset_select]),
......@@ -344,7 +344,7 @@ def download(request):
def exec_cmd(request):
role = request.GET.get('role')
check_assets = request.GET.get('check_assets', '')
web_terminal_uri = '%s/exec?role=%s' % (WEB_SOCKET_HOST, role)
web_terminal_uri = '/ws/exec?role=%s' % (role)
return my_render('exec_cmd.html', locals(), request)
......@@ -354,9 +354,7 @@ def web_terminal(request):
role_name = request.GET.get('role')
asset = get_object(Asset, id=asset_id)
if asset:
print asset
hostname = asset.hostname
web_terminal_uri = '%s/terminal?id=%s&role=%s' % (WEB_SOCKET_HOST, asset_id, role_name)
return render_to_response('jlog/web_terminal.html', locals())
......@@ -87,12 +87,12 @@ def db_update_user(**kwargs):
admin_groups_post = kwargs.pop('admin_groups')
user_id = kwargs.pop('user_id')
user = User.objects.filter(id=user_id)
user_get = User.objects.get(id=user_id)
if user:
pwd = kwargs.pop('password')
user_get = user[0]
password = kwargs.pop('password')
user.update(**kwargs)
if pwd != '':
user_get.set_password(pwd)
if password.strip():
user_get.set_password(password)
user_get.save()
else:
return None
......@@ -137,7 +137,7 @@ def gen_ssh_key(username, password='',
if authorized_keys:
auth_key_dir = os.path.join(home, username, '.ssh')
mkdir(auth_key_dir, username=username , mode=0700)
mkdir(auth_key_dir, username=username, mode=0700)
authorized_key_file = os.path.join(auth_key_dir, 'authorized_keys')
with open(private_key_file+'.pub') as pub_f:
with open(authorized_key_file, 'w') as auth_f:
......@@ -146,14 +146,12 @@ def gen_ssh_key(username, password='',
chown(authorized_key_file, username)
def server_add_user(username, password, ssh_key_pwd='', ssh_key_login_need=True):
def server_add_user(username, ssh_key_pwd=''):
"""
add a system user in jumpserver
在jumpserver服务器上添加一个用户
"""
bash("useradd '%s'; echo '%s'; echo '%s:%s' | chpasswd " %
(username, password, username, password))
if ssh_key_login_need:
bash("useradd -s '%s' '%s'" % (os.path.join(BASE_DIR, 'init.sh'), username))
gen_ssh_key(username, ssh_key_pwd)
......@@ -171,7 +169,7 @@ def user_add_mail(user, kwargs):
您的web登录密码: %s
您的ssh密钥文件密码: %s
密钥下载地址: %s/juser/key/down/?uuid=%s
说明: 请登陆后再下载密钥
说明: 请登陆跳板机后台下载密钥, 然后使用密钥登陆跳板机
""" % (user.name, user.username, user_role.get(user.role, u'普通用户'),
kwargs.get('password'), kwargs.get('ssh_key_pwd'), URL, user.uuid)
send_mail(mail_title, mail_msg, MAIL_FROM, [user.email], fail_silently=False)
......@@ -182,30 +180,20 @@ def server_del_user(username):
delete a user from jumpserver linux system
删除系统上的某用户
"""
bash('userdel -r %s' % username)
bash('userdel -r -f %s' % username)
def get_display_msg(user, password, ssh_key_pwd, ssh_key_login_need, send_mail_need):
def get_display_msg(user, password='', ssh_key_pwd='', send_mail_need=False):
if send_mail_need:
msg = u'添加用户 %s 成功! 用户密码已发送到 %s 邮箱!' % (user.name, user.email)
return msg
if ssh_key_login_need:
msg = u"""
跳板机地址: %s
用户名:%s
密码:%s
密钥密码:%s
密钥下载url: %s/juser/key/down/?uuid=%s
该账号密码可以登陆web和跳板机。
""" % (URL, user.username, password, ssh_key_pwd, URL, user.uuid)
else:
msg = u"""
跳板机地址: %s \n
用户名:%s \n
密码:%s \n
跳板机地址: %s <br />
用户名:%s <br />
密码:%s <br />
密钥密码:%s <br />
密钥下载url: %s/juser/key/down/?uuid=%s <br />
该账号密码可以登陆web和跳板机。
""" % (URL, user.username, password)
""" % (URL, user.username, password, ssh_key_pwd, URL, user.uuid)
return msg
......@@ -153,8 +153,7 @@ def user_add(request):
ssh_key_pwd = PyCrypt.gen_rand_pass(16)
extra = request.POST.getlist('extra', [])
is_active = False if '0' in extra else True
ssh_key_login_need = True
send_mail_need = True if '2' in extra else False
send_mail_need = True if '1' in extra else False
try:
if '' in [username, password, ssh_key_pwd, name, role]:
......@@ -176,7 +175,7 @@ def user_add(request):
ssh_key_pwd=ssh_key_pwd,
is_active=is_active,
date_joined=datetime.datetime.now())
server_add_user(username, password, ssh_key_pwd, ssh_key_login_need)
server_add_user(username=username, ssh_key_pwd=ssh_key_pwd)
user = get_object(User, username=username)
if groups:
user_groups = []
......@@ -193,7 +192,7 @@ def user_add(request):
else:
if MAIL_ENABLE and send_mail_need:
user_add_mail(user, kwargs=locals())
msg = get_display_msg(user, password, ssh_key_pwd, ssh_key_login_need, send_mail_need)
msg = get_display_msg(user, password=password, ssh_key_pwd=ssh_key_pwd, send_mail_need=send_mail_need)
return my_render('juser/user_add.html', locals(), request)
......@@ -361,7 +360,7 @@ def user_edit(request):
admin_groups = request.POST.getlist('admin_groups', [])
extra = request.POST.getlist('extra', [])
is_active = True if '0' in extra else False
email_need = True if '2' in extra else False
email_need = True if '1' in extra else False
user_role = {'SU': u'超级管理员', 'GA': u'部门管理员', 'CU': u'普通用户'}
if user_id:
......@@ -369,11 +368,6 @@ def user_edit(request):
else:
return HttpResponseRedirect(reverse('user_list'))
if password != '':
password_decode = password
else:
password_decode = None
db_update_user(user_id=user_id,
password=password,
name=name,
......@@ -392,7 +386,7 @@ def user_edit(request):
密码:%s (如果密码为None代表密码为原密码)
权限::%s
""" % (user.name, URL, user.username, password_decode, user_role.get(role_post, u''))
""" % (user.name, URL, user.username, password, user_role.get(role_post, u''))
send_mail('您的信息已修改', msg, MAIL_FROM, [email], fail_silently=False)
return HttpResponseRedirect(reverse('user_list'))
......@@ -453,7 +447,6 @@ def down_key(request):
uuid_r = request.GET.get('uuid', '')
else:
uuid_r = request.user.uuid
if uuid_r:
user = get_object(User, uuid=uuid_r)
if user:
......@@ -466,6 +459,8 @@ def down_key(request):
f.close()
response = HttpResponse(data, content_type='application/octet-stream')
response['Content-Disposition'] = 'attachment; filename=%s' % os.path.basename(private_key_file)
if request.user.role == 'CU':
os.unlink(private_key_file)
return response
return HttpResponse('No Key File. Contact Admin.')
This diff is collapsed.
......@@ -4,39 +4,47 @@
# chkconfig: - 85 12
# description: Open source detecting system
# processname: jumpserver
# Date: 2015-04-12
# Version: 2.0.0
# Date: 2016-02-27
# Version: 3.0.1
# Site: http://www.jumpserver.org
# Author: Jumpserver Team
. /etc/init.d/functions
export PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/opt/node/bin
jumpserver_dir=
base_dir=$(dirname $0)
PROC_NAME="jumpsever"
jumpserver_dir=${jumpserver_dir:-$base_dir}
export PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
if [ -f ${jumpserver_dir}/install/functions ];then
. ${jumpserver_dir}/install/functions
elif [ -f /etc/init.d/functions ];then
. /etc/init.d/functions
else
echo "No functions script found in [./functions, ./install/functions, /etc/init.d/functions]"
exit 1
fi
PROC_NAME="jumpserver"
lockfile=/var/lock/subsys/${PROC_NAME}
start() {
jump_start=$"Starting ${PROC_NAME} service:"
if [ -f $lockfile ];then
echo "jumpserver is running..."
echo -n "jumpserver is running..."
success "$jump_start"
echo
else
daemon python $base_dir/manage.py runserver 0.0.0.0:80 &>> /tmp/jumpserver.log 2>&1 &
daemon python $base_dir/run_websocket.py &> /dev/null 2>&1 &
sleep 4
daemon python $jumpserver_dir/manage.py crontab add &>> /var/log/jumpserver.log 2>&1
daemon python $jumpserver_dir/run_server.py &> /dev/null 2>&1 &
sleep 1
echo -n "$jump_start"
nums=0
for i in manage.py run_websocket.py;do
ps aux | grep "$i" | grep -v 'grep' &> /dev/null && let nums+=1 || echo "$i not running"
done
if [ "x$nums" == "x2" ];then
ps axu | grep 'run_server' | grep -v 'grep' &> /dev/null
if [ $? == '0' ];then
success "$jump_start"
if [ ! -e $lockfile ]; then
lockfile_dir=`dirname $lockfile`
mkdir -pv $lockfile_dir
fi
touch "$lockfile"
echo
else
......@@ -44,18 +52,14 @@ start() {
echo
fi
fi
}
stop() {
echo -n $"Stopping ${PROC_NAME} service:"
ps aux | grep -E 'manage.py|run_websocket.py' | grep -v grep | awk '{print $2}' | xargs kill -9 &> /dev/null
daemon python $jumpserver_dir/manage.py crontab remove &>> /var/log/jumpserver.log 2>&1
ps aux | grep -E 'run_server.py' | grep -v grep | awk '{print $2}' | xargs kill -9 &> /dev/null
ret=$?
if [ $ret -eq 0 ]; then
echo_success
echo
......@@ -68,6 +72,20 @@ stop() {
}
status(){
ps axu | grep 'run_server' | grep -v 'grep' &> /dev/null
if [ $? == '0' ];then
echo -n "jumpserver is running..."
success
touch "$lockfile"
echo
else
echo -n "jumpserver is not running."
failure
echo
fi
}
restart(){
......@@ -88,10 +106,10 @@ case "$1" in
restart
;;
status)
status
;;
*)
echo $"Usage: $0 {start|stop|restart}"
echo $"Usage: $0 {start|stop|restart|status}"
exit 2
esac
/*
AngularJS v1.2.5
(c) 2010-2014 Google, Inc. http://angularjs.org
License: MIT
*/
(function(h,e,A){'use strict';function u(w,q,k){return{restrict:"ECA",terminal:!0,priority:400,transclude:"element",link:function(a,c,b,f,n){function y(){l&&(l.$destroy(),l=null);g&&(k.leave(g),g=null)}function v(){var b=w.current&&w.current.locals;if(b&&b.$template){var b=a.$new(),f=w.current;g=n(b,function(d){k.enter(d,null,g||c,function(){!e.isDefined(t)||t&&!a.$eval(t)||q()});y()});l=f.scope=b;l.$emit("$viewContentLoaded");l.$eval(h)}else y()}var l,g,t=b.autoscroll,h=b.onload||"";a.$on("$routeChangeSuccess",
v);v()}}}function z(e,h,k){return{restrict:"ECA",priority:-400,link:function(a,c){var b=k.current,f=b.locals;c.html(f.$template);var n=e(c.contents());b.controller&&(f.$scope=a,f=h(b.controller,f),b.controllerAs&&(a[b.controllerAs]=f),c.data("$ngControllerController",f),c.children().data("$ngControllerController",f));n(a)}}}h=e.module("ngRoute",["ng"]).provider("$route",function(){function h(a,c){return e.extend(new (e.extend(function(){},{prototype:a})),c)}function q(a,e){var b=e.caseInsensitiveMatch,
f={originalPath:a,regexp:a},h=f.keys=[];a=a.replace(/([().])/g,"\\$1").replace(/(\/)?:(\w+)([\?|\*])?/g,function(a,e,b,c){a="?"===c?c:null;c="*"===c?c:null;h.push({name:b,optional:!!a});e=e||"";return""+(a?"":e)+"(?:"+(a?e:"")+(c&&"(.+?)"||"([^/]+)")+(a||"")+")"+(a||"")}).replace(/([\/$\*])/g,"\\$1");f.regexp=RegExp("^"+a+"$",b?"i":"");return f}var k={};this.when=function(a,c){k[a]=e.extend({reloadOnSearch:!0},c,a&&q(a,c));if(a){var b="/"==a[a.length-1]?a.substr(0,a.length-1):a+"/";k[b]=e.extend({redirectTo:a},
q(b,c))}return this};this.otherwise=function(a){this.when(null,a);return this};this.$get=["$rootScope","$location","$routeParams","$q","$injector","$http","$templateCache","$sce",function(a,c,b,f,n,q,v,l){function g(){var d=t(),m=r.current;if(d&&m&&d.$$route===m.$$route&&e.equals(d.pathParams,m.pathParams)&&!d.reloadOnSearch&&!x)m.params=d.params,e.copy(m.params,b),a.$broadcast("$routeUpdate",m);else if(d||m)x=!1,a.$broadcast("$routeChangeStart",d,m),(r.current=d)&&d.redirectTo&&(e.isString(d.redirectTo)?
c.path(u(d.redirectTo,d.params)).search(d.params).replace():c.url(d.redirectTo(d.pathParams,c.path(),c.search())).replace()),f.when(d).then(function(){if(d){var a=e.extend({},d.resolve),c,b;e.forEach(a,function(d,c){a[c]=e.isString(d)?n.get(d):n.invoke(d)});e.isDefined(c=d.template)?e.isFunction(c)&&(c=c(d.params)):e.isDefined(b=d.templateUrl)&&(e.isFunction(b)&&(b=b(d.params)),b=l.getTrustedResourceUrl(b),e.isDefined(b)&&(d.loadedTemplateUrl=b,c=q.get(b,{cache:v}).then(function(a){return a.data})));
e.isDefined(c)&&(a.$template=c);return f.all(a)}}).then(function(c){d==r.current&&(d&&(d.locals=c,e.copy(d.params,b)),a.$broadcast("$routeChangeSuccess",d,m))},function(c){d==r.current&&a.$broadcast("$routeChangeError",d,m,c)})}function t(){var a,b;e.forEach(k,function(f,k){var p;if(p=!b){var s=c.path();p=f.keys;var l={};if(f.regexp)if(s=f.regexp.exec(s)){for(var g=1,q=s.length;g<q;++g){var n=p[g-1],r="string"==typeof s[g]?decodeURIComponent(s[g]):s[g];n&&r&&(l[n.name]=r)}p=l}else p=null;else p=null;
p=a=p}p&&(b=h(f,{params:e.extend({},c.search(),a),pathParams:a}),b.$$route=f)});return b||k[null]&&h(k[null],{params:{},pathParams:{}})}function u(a,c){var b=[];e.forEach((a||"").split(":"),function(a,d){if(0===d)b.push(a);else{var e=a.match(/(\w+)(.*)/),f=e[1];b.push(c[f]);b.push(e[2]||"");delete c[f]}});return b.join("")}var x=!1,r={routes:k,reload:function(){x=!0;a.$evalAsync(g)}};a.$on("$locationChangeSuccess",g);return r}]});h.provider("$routeParams",function(){this.$get=function(){return{}}});
h.directive("ngView",u);h.directive("ngView",z);u.$inject=["$route","$anchorScroll","$animate"];z.$inject=["$compile","$controller","$route"]})(window,window.angular);
This source diff could not be displayed because it is too large. You can view the blob instead.
/**
* Created by liuzheng on 3/25/16.
*/
'use strict';
var NgApp = angular.module('NgApp', ['ngRoute']);
NgApp.config(['$httpProvider', function ($httpProvider) {
$httpProvider.defaults.transformRequest = function (obj) {
var str = [];
for (var p in obj) {
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
}
return str.join("&");
};
$httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
$httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
$httpProvider.defaults.headers.post = {
'Content-Type': 'application/x-www-form-urlencoded'
}
}]);
NgApp.controller('TerminalRecordCtrl', function ($scope, $http) {
$http.post(window.location.href).success(function (data) {
var toggle = true;
var totalTime = 0;
var TICK = 33;
var TIMESTEP = 33;
var time = 33;
var timer;
var pos = 0;
// Thanks http://stackoverflow.com/a/2998822
function zeroPad(num, size) {
var s = "0" + num;
return s.substr(s.length - size);
}
$scope.scrub = function () {
var setPercent = document.getElementById('scrubber').value;
time = (setPercent / 100) * totalTime;
$scope.restart(time);
};
function buildTimeString(millis) {
var hours = zeroPad(Math.floor(millis / (1000 * 60 * 60)), 2);
millis -= hours * (1000 * 60 * 60);
var minutes = zeroPad(Math.floor(millis / (1000 * 60)), 2);
millis -= minutes * (1000 * 60);
var seconds = zeroPad(Math.floor(millis / 1000), 2);
return hours + ':' + minutes + ':' + seconds;
}
function advance() {
document.getElementById('scrubber').value =
Math.ceil((time / totalTime) * 100);
document.getElementById("beforeScrubberText").innerHTML = buildTimeString(time);
for (; pos < timelist.length; pos++) {
if (timelist[pos] * 1000 <= time) {
term.write(data[timelist[pos]]);
} else {
break;
}
}
if (pos >= timelist.length) {
clearInterval(timer);
}
time += TIMESTEP;
}
$scope.pause = function (test) {
if (!toggle && test) {
return;
}
if (toggle) {
clearInterval(timer);
toggle = !toggle;
} else {
timer = setInterval(advance, TICK);
toggle = !toggle;
}
};
$scope.setSpeed = function () {
var speed = document.getElementById('speed').value;
if (speed == 0) {
TIMESTEP = TICK;
} else if (speed < 0) {
TIMESTEP = TICK / -speed;
} else {
TIMESTEP = TICK * speed;
}
};
$scope.restart = function (millis) {
clearInterval(timer);
term.reset();
time = millis;
pos = 0;
toggle = true;
timer = setInterval(advance, TICK);
};
var term = new Terminal({
rows: 24,
cols: 80,
useStyle: true,
screenKeys: true
});
var timelist = [];
for (var i in data) {
totalTime = Math.max(totalTime, i);
timelist.push(i);
}
timelist = timelist.sort(function(a, b){return a-b});
totalTime = totalTime * 1000;
document.getElementById("afterScrubberText").innerHTML = buildTimeString(totalTime);
term.open(document.getElementById('terminal'));
timer = setInterval(advance, TICK);
})
})
\ No newline at end of file
This diff is collapsed.
/**
* Created by liuzheng on 3/3/16.
*/
var rowHeight = 1;
var colWidth = 1;
function WSSHClient() {
}
WSSHClient.prototype._generateEndpoint = function (options) {
console.log(options);
if (window.location.protocol == 'https:') {
var protocol = 'wss://';
} else {
var protocol = 'ws://';
}
var endpoint = protocol + document.URL.match(RegExp('//(.*?)/'))[1] + '/ws/terminal' + document.URL.match(/(\?.*)/);
return endpoint;
};
WSSHClient.prototype.connect = function (options) {
var endpoint = this._generateEndpoint(options);
if (window.WebSocket) {
this._connection = new WebSocket(endpoint);
}
else if (window.MozWebSocket) {
this._connection = MozWebSocket(endpoint);
}
else {
options.onError('WebSocket Not Supported');
return;
}
this._connection.onopen = function () {
options.onConnect();
};
this._connection.onmessage = function (evt) {
try{
options.onData(evt.data);
} catch (e) {
var data = JSON.parse(evt.data.toString());
options.onError(data.error);
}
};
this._connection.onclose = function (evt) {
options.onClose();
};
};
WSSHClient.prototype.send = function (data) {
this._connection.send(JSON.stringify({'data': data}));
};
function openTerminal(options) {
var client = new WSSHClient();
var term = new Terminal({
rows: rowHeight,
cols: colWidth,
useStyle: true,
screenKeys: true
});
term.open();
term.on('data', function (data) {
client.send(data)
});
$('.terminal').detach().appendTo('#term');
term.resize(80, 24);
term.write('Connecting...');
client.connect($.extend(options, {
onError: function (error) {
term.write('Error: ' + error + '\r\n');
},
onConnect: function () {
// Erase our connecting message
term.write('\r');
},
onClose: function () {
term.write('Connection Reset By Peer');
},
onData: function (data) {
term.write(data);
}
}));
rowHeight = 0.0 + 1.00 * $('.terminal').height() / 24;
colWidth = 0.0 + 1.00 * $('.terminal').width() / 80;
return {'term': term, 'client': client};
}
function resize() {
$('.terminal').css('width', window.innerWidth - 25);
console.log(window.innerWidth);
console.log(window.innerWidth - 10);
var rows = Math.floor(window.innerHeight / rowHeight) - 2;
var cols = Math.floor(window.innerWidth / colWidth) - 1;
return {rows: rows, cols: cols};
}
$(document).ready(function () {
var options = {};
$('#ssh').show();
var term_client = openTerminal(options);
console.log(rowHeight);
// by liuzheng712 because it will bring record bug
//window.onresize = function () {
// var geom = resize();
// console.log(geom);
// term_client.term.resize(geom.cols, geom.rows);
// term_client.client.send({'resize': {'rows': geom.rows, 'cols': geom.cols}});
// $('#ssh').show();
//}
});
\ No newline at end of file
......@@ -29,7 +29,7 @@
protocol = 'wss://';
}
var wsUri = protocol + "{{ web_terminal_uri }}"; //请求的websocket url
var wsUri = protocol + document.URL.match(RegExp('//(.*?)/'))[1] + "{{ web_terminal_uri }}"; //请求的websocket url
var ws = new WebSocket(wsUri);
function createSystemMessage(message) {
......@@ -82,7 +82,7 @@
<style type="text/css">
* {
font-family: "Monaco", "DejaVu Sans Mono", "Liberation Mono", monospace;
font-family: "Monaco", "Microsoft Yahei", "DejaVu Sans Mono", "Liberation Mono", monospace;
font-size: 11px;
}
......
......@@ -36,6 +36,5 @@
} else {
$("#"+s1).addClass('active');
$('#'+s1+' .'+s2).addClass('active');
console.log(s1)
}
</script>
<div class="footer fixed">
<div class="pull-right">
Version <strong>0.3.0</strong> GPL.
Version <strong>0.3.1</strong> GPL.
</div>
<div>
<strong>Copyright</strong> Jumpserver.org Team &copy; 2014-2015
......
......@@ -210,7 +210,7 @@
{% if login_10 %}
{% for login in login_10 %}
<div class="feed-element">
<a href="profile.html" class="pull-left">
<a href="#" class="pull-left">
<img alt="image" class="img-circle" src="/static/img/root.png">
</a>
<div class="media-body ">
......@@ -232,7 +232,7 @@
<div class="feed-activity-list">
{% for login in login_more_10 %}
<div class="feed-element">
<a href="profile.html" class="pull-left">
<a href="#" class="pull-left">
<img alt="image" class="img-circle" src="/static/img/root.png">
</a>
<div class="media-body ">
......
......@@ -50,24 +50,23 @@
<div class="hr-line-dashed"></div>
<div class="form-group">
<label for="j_group" class="col-sm-2 control-label">管理账号<span class="red-fonts"> *</span></label>
<label for="j_group" class="col-sm-2 control-label">管理用户<span class="red-fonts"> *</span></label>
<div class="col-sm-2">
<div class="radio i-checks">
<label>
<label style="padding-left: 0">
<input type="checkbox" checked="checked" id="id_use_default_auth" name="use_default_auth"><span> 使用默认 </span>
</label>
</div>
</div>
</div>
<p class="col-sm-offset-2">Tips: 管理账号是服务器存在的root等高权限账号,用来推送新建系统用户</p>
<p class="col-sm-offset-2">Tips: 管理用户是服务器存在的root或拥有sudo的用户,用来推送系统用户</p>
<div class="form-group" id="admin_account" style="display: none">
<div class="hr-line-dashed"></div>
<label class="col-sm-2 control-label"> 管理用户名<span class="red-fonts">*</span> </label>
<label class="col-sm-2 control-label"> <span class="red-fonts"></span> </label>
<div class="col-sm-3">
<input type="text" placeholder="Username" name="username" class="form-control">
</div>
<label class="col-sm-1 control-label"> 密码<span class="red-fonts">*</span> </label>
<label class="col-sm-1 control-label"> <span class="red-fonts"></span> </label>
<div class="col-sm-4">
<input type="password" placeholder="Password" name="password" class="form-control">
</div>
......
......@@ -57,20 +57,19 @@
<label for="j_group" class="col-sm-2 control-label">管理账号 <span class="red-fonts">*</span></label>
<div class="col-sm-2">
<div class="radio i-checks">
<label>
<label style="padding-left: 0">
<input type="checkbox" {% if asset.use_default_auth %} checked="checked" {% endif %} id="id_use_default_auth" name="use_default_auth"><span> 使用默认 </span>
</label>
</div>
</div>
</div>
<div class="form-group" id="admin_account" {% if asset.use_default_auth %} style="display: none" {% endif %}>
<div class="hr-line-dashed"></div>
<label class="col-sm-2 control-label"> 管理用户名 <span class="red-fonts">*</span> </label>
<label class="col-sm-2 control-label"> </label>
<div class="col-sm-3">
<input type="text" value="{{ asset.username }}" name="username" class="form-control">
</div>
<label class="col-sm-1 control-label"> 密码<span class="red-fonts">*</span> </label>
<label class="col-sm-1 control-label"> </label>
<div class="col-sm-4">
<input type="password" value="" name="password" placeholder="不填写即不更改密码." class="form-control">
</div>
......
......@@ -8,6 +8,11 @@
{% include 'nav_cat_bar.html' %}
<style>
iframe {
overflow:hidden;
}
.bootstrap-dialog-body {
background-color: rgba(0, 0, 0, 0);
}
......@@ -157,7 +162,7 @@
title: title,
maxmin: true,
shade: false,
area: ['800px', '520px'],
area: ['620px', '450px'],
content: url
});
return false;
......
......@@ -3,14 +3,16 @@
<style>
.terminal {
border: #000 solid 5px;
font-family: "Monaco", "DejaVu Sans Mono", "Liberation Mono", monospace;
font-family: "Monaco", "Microsoft Yahei", "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;
}
white-space: nowrap;
display: inline-block;
}
.reverse-video {
color: #000;
background: #f0f0f0;
......@@ -109,7 +111,7 @@
<td id="remote_ip" class="text-center"> {{ post.remote_ip }} </td>
<td class="text-center"> {{ post.login_type }} </td>
<td class="text-center"><a href="{% url 'log_history' %}?id={{ post.id }}" class="log_command"> 统计 </a></td>
<td class="text-center"><a class="monitor" file_path="{{ post.log_path }}"> 监控 </a></td>
<td class="text-center"><a class="monitor" monitor-id="{{ post.id }}" file_path="{{ post.log_path }}"> 监控 </a></td>
<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" id="start_time"> {{ post.start_time|date:"Y-m-d H:i:s" }} </td>
</tr>
......@@ -128,36 +130,33 @@
</div>
{#<script src="http://{{ web_socket_host }}/socket.io/socket.io.js"></script>#}
<script>
{# $(document).ready(function(){#}
{# $('.monitor').click(function(){#}
{# window.open('/jlog/monitor/', '监控', 'height=500, width=910, top=89px, left=99px,toolbar=no,menubar=no,scrollbars=auto,resizeable=no,location=no,status=no');#}
{# })#}
{# });#}
function init(obj){
var protocol = "ws://";
if (window.location.protocol == 'https:') {
protocol = 'wss://';
var protocol = 'wss://';
} else {
var protocol = 'ws://';
}
var endpoint = protocol + document.URL.match(RegExp('//(.*?)/'))[1] + '/ws/monitor';
var monitorid = obj.attr('monitor-id');
var file_path = obj.attr('file_path');
var wsUri = protocol + '{{ web_monitor_uri }}';
var socket = new WebSocket(wsUri + '?file_path=' + file_path);
{# var socket = new WebSocket(endpoint + '?id=' + monitorid);#}
var socket = new WebSocket(endpoint + '?file_path=' + file_path);
var term = new Terminal({
cols: 80,
rows: 24,
cols: 98,
rows: 28,
screenKeys: false,
handler: function(){return false}
});
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);
$('.terminal').hide();
term.resize(98, 28);
socket.onopen = function(evt){
socket.send('hello');
{# socket.send('hello');#}
term.write('~.~ Connect WebSocket Success.~.~ \r\n');
};
......@@ -170,9 +169,9 @@
BootstrapDialog.show({message: function(){
//服务器端认证
{# socket.send('login', {userid:message.id, filename:message.filename,username:username,seed:seed});#}
window.setTimeout(function(){
$('.terminal').detach().appendTo('#term');
$('.terminal').show();
socket.onmessage = function(evt){
term.write(evt.data);
}}, 1000);
......@@ -209,19 +208,18 @@
});
function cut(num, login_type){
console.log(login_type);
var protocol = window.location.protocol;
var endpoint = protocol + '//' + document.URL.match(RegExp('//(.*?)/'))[1] + '/kill';
if (login_type=='web'){
var g_url = '{{ web_kill_uri }}' + '?id=' + num;
var g_url = endpoint + '?id=' + num;
console.log(g_url);
} else {
var g_url = "{% url 'log_kill' %} }?id=" + num;
var g_url = "{% url 'log_kill' %}?id=" + num;
}
$.ajax({
type: "GET",
url: g_url+"&sessionid={{ session_id }}",
success: window.open("{% url 'log_list' 'online' %}", "_self")
});
$.get(g_url+"&sessionid={{ session_id }}", function () {
window.open("{% url 'log_list' 'online' %}", "_self")
})
}
</script>
{% endblock %}
\ No newline at end of file
<!DOCTYPE html>
<html ng-app="NgApp" style=" overflow:hidden;">
<head lang="en">
<title>Jumpserver 录像回放</title>
<script type="application/javascript" src='/static/js/jquery-2.1.1.js'></script>
<script type="application/javascript" src='/static/js/angular.min.js'></script>
<script type="application/javascript" src='/static/js/angular-route.min.js'></script>
<script type="application/javascript" src='/static/js/term.js'></script>
</head>
<body>
{% csrf_token %}
<div ng-controller="TerminalRecordCtrl">
<input type="button" value="Play/Pause" ng-click="pause(false);"/>
<input type="button" value="Restart" ng-click="restart(1);"/>
<span id="beforeScrubberText"></span>
<input id="scrubber" type="range" value="0" min=0 max=100
ng-mousedown="pause(true);" ng-mouseup="scrub();"/>
<span id="afterScrubberText"></span>
-5x <input id="speed" type="range" value="0" min=-5 max=5
ng-mouseup="setSpeed();"/> +5x
<div id="terminal"></div>
</div>
<script type="application/javascript" src='/static/js/record.js'></script>
</body>
</html>
\ No newline at end of file
This diff is collapsed.
......@@ -11,12 +11,14 @@
.terminal {
border: #000 solid 5px;
font-family: "Monaco", "DejaVu Sans Mono", "Liberation Mono", monospace;
font-family: "Monaco", "Microsoft Yahei", "DejaVu Sans Mono", "Liberation Mono", monospace;
font-size: 11px;
color: #f0f0f0;
background: #000;
width: 600px;
box-shadow: rgba(0, 0, 0, 0.8) 2px 2px 20px;
white-space: nowrap;
display: inline-block;
}
.reverse-video {
......@@ -36,114 +38,6 @@
</script>
<script type="application/javascript" src="/static/js/term.js">
</script>
<script type="application/javascript">
var rowHeight = 1;
var colWidth = 1;
function WSSHClient() {
}
WSSHClient.prototype.connect = function(options) {
var protocol = "ws://";
if (window.location.protocol == 'https:') {
protocol = 'wss://';
}
var endpoint = protocol + '{{ web_terminal_uri }}';
if (window.WebSocket) {
this._connection = new WebSocket(endpoint);
}
else if (window.MozWebSocket) {
this._connection = MozWebSocket(endpoint);
}
else {
options.onError('WebSocket Not Supported');
return ;
}
this._connection.onopen = function() {
options.onConnect();
};
this._connection.onmessage = function (evt) {
var data = JSON.parse(evt.data.toString());
if (data.error !== undefined) {
options.onError(data.error);
}
else {
options.onData(data.data);
}
};
this._connection.onclose = function(evt) {
options.onClose();
};
};
WSSHClient.prototype.send = function(data) {
this._connection.send(JSON.stringify({'data': data}));
};
function openTerminal(options) {
var client = new WSSHClient();
var term = new Terminal(80, 24, function(key) {
client.send(key);
});
term.open();
$('.terminal').detach().appendTo('#term');
term.resize(80, 24);
term.write('Connecting...');
client.connect($.extend(options, {
onError: function(error) {
term.write('Error: ' + error + '\r\n');
},
onConnect: function() {
// Erase our connecting message
term.write('\r');
},
onClose: function() {
term.write('Connection Reset By Peer');
},
onData: function(data) {
term.write(data);
}
}));
rowHeight = 0.0 + 1.00 * $('.terminal').height() / 24 ;
colWidth = 0.0 + 1.00 * $('.terminal').width() / 80;
return {'term': term, 'client': client};
}
function resize(){
$('.terminal').css('width', window.innerWidth-25);
console.log(window.innerWidth);
console.log(window.innerWidth-10);
var rows = Math.floor(window.innerHeight/rowHeight) - 2;
var cols = Math.floor(window.innerWidth/colWidth) - 1;
return {rows: rows, cols: cols};
}
</script>
<script type='application/javascript'>
$(document).ready(function() {
var options = {
};
$('#ssh').show();
var term_client = openTerminal(options);
console.log(rowHeight);
window.onresize = function(){
var geom = resize();
console.log(geom);
term_client.term.resize(geom.cols, geom.rows);
term_client.client.send({'resize': {'roles': geom.rows, 'cols': geom.cols}});
$('#ssh').show();
}
});
</script>
<script type="application/javascript" src="/static/js/webterminal.js"></script>
</body>
</html>
......@@ -104,6 +104,10 @@ $('#roleForm').validator({
ok: "",
msg: {required: "系统用户名称必填"}
},
"role_password": {
rule: "length[0~64]",
tip: "系统密码"
},
"role_key": {
rule: "check_begin",
ok: "",
......
......@@ -105,12 +105,16 @@ $('#roleForm').validator({
tip: "输入系统用户名称",
ok: "",
msg: {required: "系统用户名称必填"}
},
"role_password": {
rule: "length[0~64]",
tip: "系统密码"
},
"role_key": {
rule: "check_begin",
ok: "",
empty: true
},
}
},
valid: function(form) {
......
......@@ -74,16 +74,6 @@
</div>
</div>
</div>
<div class="form-group">
<label for="j_group" class="col-sm-2 control-label">使用密码</label>
<div class="col-sm-1">
<div class="radio i-checks">
<label>
<input type="checkbox" value="1" id="use_password" name="use_password">
</label>
</div>
</div>
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
......
......@@ -28,7 +28,7 @@
<div class="alert alert-warning text-center">{{ error }}</div>
{% endif %}
{% if msg %}
<div class="alert alert-success text-center">{{ msg }}</div>
<div class="alert alert-success">{{ msg | safe }}</div>
{% endif %}
<div class="form-group">
<label for="username" class="col-sm-2 control-label">用户名<span class="red-fonts">*</span></label>
......@@ -99,14 +99,9 @@
<label><input type="checkbox" value="0" name="extra" >禁用 </label>
</div>
</div>
{# <div class="col-sm-2">#}
{# <div class="checkbox i-checks">#}
{# <label><input type="checkbox" value="1" name="extra">ssh key登录 </label>#}
{# </div>#}
{# </div>#}
<div class="col-sm-2">
<div class="checkbox i-checks">
<label><input type="checkbox" value="2" name="extra">发送邮件 </label>
<label><input type="checkbox" value="1" name="extra" checked>发送邮件 </label>
</div>
</div>
</div>
......
......@@ -116,7 +116,7 @@
</div>
<div class="col-sm-2">
<div class="checkbox i-checks">
<label><input type="checkbox" value="2" name="extra">发送邮件 </label>
<label><input type="checkbox" value="1" name="extra">发送邮件 </label>
</div>
</div>
</div>
......
......@@ -70,7 +70,7 @@
{% if user.username|key_exist %}
<a href="{% url 'key_down' %}?uuid={{ user.uuid }}" >下载</a>
{% else %}
<span style="color: #586b7d">NoKey</span>
<a href="#" onclick="genSSH('{{ user.username }}','{% url 'key_gen' %}?uuid={{ user.uuid }}')">NoKey GenOne?</a>
{% endif %}
</td>
<td class="text-center">
......@@ -150,5 +150,13 @@
});
$('.shiftCheckbox').shiftcheckbox();
});
function genSSH(username, url) {
if (confirm('Are you sure to gen a sshkey for user ' + username)) {
$.get(url, function (data) {
alert(data);
location.reload()
})
}
}
</script>
{% endblock %}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment