mirror of https://github.com/jumpserver/jumpserver
上传文件
parent
30fd160079
commit
78f00e5c5f
62
connect.py
62
connect.py
|
@ -17,15 +17,15 @@ import getpass
|
||||||
import fnmatch
|
import fnmatch
|
||||||
import readline
|
import readline
|
||||||
from multiprocessing import Pool
|
from multiprocessing import Pool
|
||||||
from ConfigParser import ConfigParser
|
|
||||||
from django.core.exceptions import ObjectDoesNotExist
|
|
||||||
|
|
||||||
os.environ['DJANGO_SETTINGS_MODULE'] = 'jumpserver.settings'
|
os.environ['DJANGO_SETTINGS_MODULE'] = 'jumpserver.settings'
|
||||||
django.setup()
|
django.setup()
|
||||||
from juser.models import User
|
from juser.models import User
|
||||||
from jasset.models import AssetAlias
|
|
||||||
from jlog.models import Log
|
from jlog.models import Log
|
||||||
from jumpserver.api import *
|
from jumpserver.api import *
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import termios
|
import termios
|
||||||
import tty
|
import tty
|
||||||
|
@ -57,10 +57,6 @@ def color_print_exit(msg, color='red'):
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
|
|
||||||
class ServerError(Exception):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def get_win_size():
|
def get_win_size():
|
||||||
"""This function use to get the size of the windows!"""
|
"""This function use to get the size of the windows!"""
|
||||||
if 'TIOCGWINSZ' in dir(termios):
|
if 'TIOCGWINSZ' in dir(termios):
|
||||||
|
@ -81,14 +77,6 @@ def set_win_size(sig, data):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def get_object(model, **kwargs):
|
|
||||||
try:
|
|
||||||
the_object = model.objects.get(**kwargs)
|
|
||||||
except ObjectDoesNotExist:
|
|
||||||
raise ServerError('Object get %s failed.' % str(kwargs.values()))
|
|
||||||
return the_object
|
|
||||||
|
|
||||||
|
|
||||||
def log_record(username, host):
|
def log_record(username, host):
|
||||||
"""Logging user command and output."""
|
"""Logging user command and output."""
|
||||||
connect_log_dir = os.path.join(LOG_DIR, 'connect')
|
connect_log_dir = os.path.join(LOG_DIR, 'connect')
|
||||||
|
@ -171,20 +159,6 @@ def posix_shell(chan, username, host):
|
||||||
print_prompt()
|
print_prompt()
|
||||||
|
|
||||||
|
|
||||||
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.get(username=username)
|
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
def get_user_hostgroup(username):
|
def get_user_hostgroup(username):
|
||||||
"""Get the hostgroups of under the user control."""
|
"""Get the hostgroups of under the user control."""
|
||||||
groups_attr = {}
|
groups_attr = {}
|
||||||
|
@ -208,36 +182,6 @@ def get_user_hostgroup_host(username, gid):
|
||||||
return hosts_attr
|
return hosts_attr
|
||||||
|
|
||||||
|
|
||||||
def get_connect_item(username, ip):
|
|
||||||
|
|
||||||
asset = get_object(Asset, ip=ip)
|
|
||||||
port = 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 verify_connect(username, part_ip):
|
def verify_connect(username, part_ip):
|
||||||
ip_matched = []
|
ip_matched = []
|
||||||
hosts_attr = get_user_host(username)
|
hosts_attr = get_user_host(username)
|
||||||
|
|
|
@ -11,11 +11,14 @@ import ldap
|
||||||
from ldap import modlist
|
from ldap import modlist
|
||||||
import hashlib
|
import hashlib
|
||||||
import datetime
|
import datetime
|
||||||
|
import subprocess
|
||||||
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 juser.models import User, UserGroup, DEPT
|
from juser.models import User, UserGroup, DEPT
|
||||||
from jasset.models import Asset, BisGroup
|
from jasset.models import Asset, BisGroup
|
||||||
from jlog.models import Log
|
from jlog.models import Log
|
||||||
|
from jasset.models import AssetAlias
|
||||||
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
|
|
||||||
|
|
||||||
BASE_DIR = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
|
BASE_DIR = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
|
||||||
|
@ -144,15 +147,6 @@ def pages(posts, r):
|
||||||
return contact_list, p, contacts, page_range, current_page, show_first, show_end
|
return contact_list, p, contacts, page_range, current_page, show_first, show_end
|
||||||
|
|
||||||
|
|
||||||
def get_session_user_dept(request):
|
|
||||||
user_id = request.session.get('user_id', '')
|
|
||||||
user = User.objects.filter(id=user_id)
|
|
||||||
if user:
|
|
||||||
user = user[0]
|
|
||||||
dept = user.dept
|
|
||||||
return user, dept
|
|
||||||
|
|
||||||
|
|
||||||
class PyCrypt(object):
|
class PyCrypt(object):
|
||||||
"""This class used to encrypt and decrypt password."""
|
"""This class used to encrypt and decrypt password."""
|
||||||
|
|
||||||
|
@ -188,6 +182,14 @@ class ServerError(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def get_object(model, **kwargs):
|
||||||
|
try:
|
||||||
|
the_object = model.objects.get(**kwargs)
|
||||||
|
except ObjectDoesNotExist:
|
||||||
|
raise ServerError('Object get %s failed.' % str(kwargs.values()))
|
||||||
|
return the_object
|
||||||
|
|
||||||
|
|
||||||
def require_login(func):
|
def require_login(func):
|
||||||
"""瑕佹眰鐧诲綍鐨勮楗板櫒"""
|
"""瑕佹眰鐧诲綍鐨勮楗板櫒"""
|
||||||
def _deco(request, *args, **kwargs):
|
def _deco(request, *args, **kwargs):
|
||||||
|
@ -235,6 +237,16 @@ def is_common_user(request):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
@require_login
|
||||||
|
def get_session_user_dept(request):
|
||||||
|
user_id = request.session.get('user_id', 0)
|
||||||
|
user = User.objects.filter(id=user_id)
|
||||||
|
if user:
|
||||||
|
user = user[0]
|
||||||
|
dept = user.dept
|
||||||
|
return user, dept
|
||||||
|
|
||||||
|
|
||||||
def get_user_dept(request):
|
def get_user_dept(request):
|
||||||
user_id = request.session.get('user_id')
|
user_id = request.session.get('user_id')
|
||||||
if user_id:
|
if user_id:
|
||||||
|
@ -310,6 +322,49 @@ def asset_perm_api(asset):
|
||||||
return 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.get(username=username)
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
def get_connect_item(username, ip):
|
||||||
|
asset = get_object(Asset, ip=ip)
|
||||||
|
port = 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):
|
||||||
dept = get_session_user_dept(request)[1]
|
dept = get_session_user_dept(request)[1]
|
||||||
if edept:
|
if edept:
|
||||||
|
@ -362,3 +417,16 @@ def validate(request, user_group=None, user=None, asset_group=None, asset=None,
|
||||||
def get_dept_asset(request):
|
def get_dept_asset(request):
|
||||||
dept_id = get_user_dept(request)
|
dept_id = get_user_dept(request)
|
||||||
dept_asset = DEPT.objects.get(id=dept_id).asset_set.all()
|
dept_asset = DEPT.objects.get(id=dept_id).asset_set.all()
|
||||||
|
|
||||||
|
|
||||||
|
def bash(cmd):
|
||||||
|
"""鎵цbash鍛戒护"""
|
||||||
|
return subprocess.call(cmd, shell=True)
|
||||||
|
|
||||||
|
|
||||||
|
def is_dir(dir_name, username='root', mode=0755):
|
||||||
|
if not os.path.isdir(dir_name):
|
||||||
|
os.makedirs(dir_name)
|
||||||
|
bash("chown %s:%s '%s'" % (username, username, dir_name))
|
||||||
|
os.chmod(dir_name, mode)
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,13 @@
|
||||||
# coding: utf-8
|
# coding: utf-8
|
||||||
|
|
||||||
from __future__ import division
|
from __future__ import division
|
||||||
|
|
||||||
import datetime
|
|
||||||
|
|
||||||
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 jasset.models import IDC
|
from django.http import HttpResponseNotFound
|
||||||
from juser.models import DEPT
|
|
||||||
from jperm.models import Apply
|
from jperm.models import Apply
|
||||||
|
from multiprocessing import Pool
|
||||||
|
import paramiko
|
||||||
from jumpserver.api import *
|
from jumpserver.api import *
|
||||||
|
|
||||||
|
|
||||||
|
@ -289,5 +287,64 @@ def install(request):
|
||||||
return HttpResponse('Ok')
|
return HttpResponse('Ok')
|
||||||
|
|
||||||
|
|
||||||
|
def transfer(sftp, filenames):
|
||||||
|
# pool = Pool(processes=5)
|
||||||
|
for filename, file_path in filenames.items():
|
||||||
|
print filename, file_path
|
||||||
|
sftp.put(file_path, '/tmp/%s' % filename)
|
||||||
|
# pool.apply_async(transfer, (sftp, file_path, '/tmp/%s' % filename))
|
||||||
|
sftp.close()
|
||||||
|
# pool.close()
|
||||||
|
# pool.join()
|
||||||
|
|
||||||
|
|
||||||
def upload(request):
|
def upload(request):
|
||||||
pass
|
user, dept = get_session_user_dept(request)
|
||||||
|
if request.method == 'POST':
|
||||||
|
hosts = request.POST.get('hosts')
|
||||||
|
upload_files = request.FILES.getlist('file[]', None)
|
||||||
|
upload_dir = "/tmp/%s" % user.username
|
||||||
|
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))
|
||||||
|
|
|
@ -26,18 +26,6 @@ def gen_rand_pwd(num):
|
||||||
return salt
|
return salt
|
||||||
|
|
||||||
|
|
||||||
def bash(cmd):
|
|
||||||
"""鎵цbash鍛戒护"""
|
|
||||||
return subprocess.call(cmd, shell=True)
|
|
||||||
|
|
||||||
|
|
||||||
def is_dir(dir_name, username='root', mode=0755):
|
|
||||||
if not os.path.isdir(dir_name):
|
|
||||||
os.makedirs(dir_name)
|
|
||||||
bash("chown %s:%s '%s'" % (username, username, dir_name))
|
|
||||||
os.chmod(dir_name, mode)
|
|
||||||
|
|
||||||
|
|
||||||
class AddError(Exception):
|
class AddError(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -1001,6 +989,9 @@ def chg_info(request):
|
||||||
return render_to_response('juser/chg_info.html', locals(), context_instance=RequestContext(request))
|
return render_to_response('juser/chg_info.html', locals(), context_instance=RequestContext(request))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@require_login
|
@require_login
|
||||||
def down_key(request):
|
def down_key(request):
|
||||||
user_id = ''
|
user_id = ''
|
||||||
|
|
|
@ -1,15 +1,14 @@
|
||||||
{% extends 'base.html' %}
|
{% extends 'base.html' %}
|
||||||
{% load mytags %}
|
{% load mytags %}
|
||||||
{% load humanize %}
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{% include 'nav_cat_bar.html' %}
|
{% include 'nav_cat_bar.html' %}
|
||||||
|
|
||||||
<div class="wrapper wrapper-content">
|
<div class="wrapper wrapper-content animated fadeIn">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-12">
|
<div class="col-lg-12">
|
||||||
<div class="ibox float-e-margins">
|
<div class="ibox float-e-margins">
|
||||||
<div class="ibox-title">
|
<div class="ibox-title">
|
||||||
<h5>Dropzone Area</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>
|
||||||
|
@ -29,12 +28,17 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="ibox-content">
|
<div class="ibox-content">
|
||||||
<form id="my-awesome-dropzone" class="dropzone" action="#">
|
<div class="">
|
||||||
<div class="dropzone-previews"></div>
|
<form id="my-awesome-dropzone" class="dropzone" action="#">
|
||||||
<button type="submit" class="btn btn-primary pull-right">Submit this form!</button>
|
<div class="dropzone-previews">
|
||||||
</form>
|
<input id="hosts" name="hosts" type="text" class="form-control" required="涓嶈兘涓虹┖" placeholder="杈撳叆涓绘満鍦板潃锛岄楀彿闅斿紑锛岀‘淇濅綘鏈夎緭鍏ヤ富鏈哄湴鍧鐨勬潈闄" size="80%">
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-primary pull-right">鍏ㄩ儴涓婁紶</button>
|
||||||
|
<div></div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div class="m text-right"><small>DropzoneJS is an open source library that provides drag'n'drop file uploads with image previews: <a href="https://github.com/enyo/dropzone" target="_blank">https://github.com/enyo/dropzone</a></small> </div>
|
<div class="m text-right"><small>涓婁紶鏂囦欢鍒板悗绔湇鍔″櫒鐨/tmp涓锛璇锋敞鎰忔煡鐪</small> </div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -44,36 +48,53 @@
|
||||||
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(function(){
|
$(document).ready(function(){
|
||||||
|
|
||||||
Dropzone.options.myAwesomeDropzone = {
|
Dropzone.options.myAwesomeDropzone = {
|
||||||
|
|
||||||
autoProcessQueue: false,
|
autoProcessQueue: false,
|
||||||
uploadMultiple: true,
|
uploadMultiple: true,
|
||||||
parallelUploads: 100,
|
parallelUploads: 100,
|
||||||
maxFiles: 100,
|
maxFiles: 100,
|
||||||
url: '/upload/',
|
url: '/upload/',
|
||||||
|
|
||||||
// Dropzone settings
|
// Dropzone settings
|
||||||
init: function() {
|
init: function() {
|
||||||
var myDropzone = this;
|
var myDropzone = this;
|
||||||
this.element.querySelector("button[type=submit]").addEventListener("click", function(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
e.stopPropagation();
|
|
||||||
myDropzone.processQueue();
|
|
||||||
});
|
|
||||||
this.on("sendingmultiple", function() {
|
|
||||||
});
|
|
||||||
this.on("successmultiple", function(files, response) {
|
|
||||||
alert(files)
|
|
||||||
});
|
|
||||||
this.on("errormultiple", function(files, response) {
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
this.element.querySelector("button[type=submit]").addEventListener("click", function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
myDropzone.processQueue();
|
||||||
|
});
|
||||||
|
this.on("sendingmultiple", function() {
|
||||||
|
});
|
||||||
|
this.on("successmultiple", function(files, response) {
|
||||||
|
alert(response)
|
||||||
|
});
|
||||||
|
this.on("errormultiple", function(files, response) {
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#my-awesome-dropzone').validator({
|
||||||
|
timely: 2,
|
||||||
|
theme: "yellow_right_effect",
|
||||||
|
fields: {
|
||||||
|
"hosts": {
|
||||||
|
rule: "required",
|
||||||
|
tip: "杈撳叆涓婁紶鐨凥ost",
|
||||||
|
ok: "",
|
||||||
|
msg: {required: "蹇呴』濉啓!"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
valid: function(form) {
|
||||||
|
form.submit();
|
||||||
|
}
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading鈥
Reference in New Issue