Commit 0c3d0a45 authored by ibuler's avatar ibuler

merge

parents 9f053fba eeeca2d8
...@@ -2,4 +2,5 @@ ...@@ -2,4 +2,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
from . import logger
from .app import Coco from .app import Coco
...@@ -2,11 +2,6 @@ ...@@ -2,11 +2,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
import eventlet
from eventlet.debug import hub_prevent_multiple_readers
eventlet.monkey_patch()
hub_prevent_multiple_readers(False)
import datetime import datetime
import os import os
import time import time
...@@ -17,16 +12,15 @@ import signal ...@@ -17,16 +12,15 @@ import signal
from .config import config from .config import config
from .sshd import SSHServer from .sshd import SSHServer
from .httpd import HttpServer from .httpd import HttpServer
from .logger import create_logger
from .tasks import TaskHandler from .tasks import TaskHandler
from .utils import get_logger, ugettext as _, ignore_error from .utils import get_logger, ugettext as _, ignore_error
from .ctx import app_service from .service import app_service
from .recorder import get_replay_recorder from .recorder import get_replay_recorder
from .session import Session from .session import Session
from .models import Connection from .models import Connection
__version__ = '1.4.1' __version__ = '1.4.3'
BASE_DIR = os.path.dirname(os.path.dirname(__file__)) BASE_DIR = os.path.dirname(os.path.dirname(__file__))
logger = get_logger(__file__) logger = get_logger(__file__)
...@@ -61,9 +55,6 @@ class Coco: ...@@ -61,9 +55,6 @@ class Coco:
self._task_handler = TaskHandler() self._task_handler = TaskHandler()
return self._task_handler return self._task_handler
def make_logger(self):
create_logger()
@staticmethod @staticmethod
def load_extra_conf_from_server(): def load_extra_conf_from_server():
configs = app_service.load_config_from_server() configs = app_service.load_config_from_server()
...@@ -73,8 +64,6 @@ class Coco: ...@@ -73,8 +64,6 @@ class Coco:
config.update(configs) config.update(configs)
def bootstrap(self): def bootstrap(self):
self.make_logger()
# app_service.initial()
self.load_extra_conf_from_server() self.load_extra_conf_from_server()
self.keep_heartbeat() self.keep_heartbeat()
self.monitor_sessions() self.monitor_sessions()
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
BACKSPACE_CHAR = {b'\x08': b'\x08\x1b[K', b'\x7f': b'\x08\x1b[K'} BACKSPACE_CHAR = {b'\x08': b'\x08\x1b[K', b'\x7f': b'\x08\x1b[K'}
ENTER_CHAR = [b'\r', b'\n', b'\r\n'] ENTER_CHAR = [b'\r', b'\n', b'\r\n']
ENTER_CHAR_ORDER = [ord(b'\r'), ord(b'\n')] ENTER_CHAR_ORDER = [ord(b'\r'), ord(b'\n')]
CLEAR_LINE_CHAR = b'\x15'
UNSUPPORTED_CHAR = {b'\x15': 'Ctrl-U', b'\x0c': 'Ctrl-L', b'\x05': 'Ctrl-E'} UNSUPPORTED_CHAR = {b'\x15': 'Ctrl-U', b'\x0c': 'Ctrl-L', b'\x05': 'Ctrl-E'}
CLEAR_CHAR = b'\x1b[H\x1b[2J' CLEAR_CHAR = b'\x1b[H\x1b[2J'
BELL_CHAR = b'\x07' BELL_CHAR = b'\x07'
......
...@@ -10,7 +10,7 @@ import telnetlib ...@@ -10,7 +10,7 @@ import telnetlib
import paramiko import paramiko
from paramiko.ssh_exception import SSHException from paramiko.ssh_exception import SSHException
from .ctx import app_service from .service import app_service
from .config import config from .config import config
from .utils import get_logger, get_private_key_fingerprint from .utils import get_logger, get_private_key_fingerprint
...@@ -22,7 +22,8 @@ AUTO_LOGIN = 'auto' ...@@ -22,7 +22,8 @@ AUTO_LOGIN = 'auto'
class SSHConnection: class SSHConnection:
def get_system_user_auth(self, system_user): @staticmethod
def get_system_user_auth(system_user):
""" """
获取系统用户的认证信息,密码或秘钥 获取系统用户的认证信息,密码或秘钥
:return: system user have full info :return: system user have full info
......
...@@ -4,9 +4,6 @@ ...@@ -4,9 +4,6 @@
from werkzeug.local import LocalProxy from werkzeug.local import LocalProxy
from functools import partial from functools import partial
from .config import config
from jms.service import AppService
stack = {} stack = {}
__db_sessions = [] __db_sessions = []
...@@ -18,7 +15,4 @@ def _find(name): ...@@ -18,7 +15,4 @@ def _find(name):
raise ValueError("Not found in stack: {}".format(name)) raise ValueError("Not found in stack: {}".format(name))
app_service = AppService(config)
app_service.initial()
current_app = LocalProxy(partial(_find, 'current_app')) current_app = LocalProxy(partial(_find, 'current_app'))
# app_service = LocalProxy(partial(_find, 'app_service'))
...@@ -2,9 +2,9 @@ ...@@ -2,9 +2,9 @@
# #
from functools import wraps from functools import wraps
from flask import request, abort from flask import request, abort, redirect
from ..ctx import app_service from ..service import app_service
def login_required(func): def login_required(func):
...@@ -23,7 +23,8 @@ def login_required(func): ...@@ -23,7 +23,8 @@ def login_required(func):
user = app_service.check_user_cookie(session_id, csrf_token) user = app_service.check_user_cookie(session_id, csrf_token)
request.current_user = user request.current_user = user
if not hasattr(request, 'current_user') or not request.current_user: if not hasattr(request, 'current_user') or not request.current_user:
return abort(403) url = '/users/login/?next={}'.format(request.path)
return redirect(url)
response = func(*args, **kwargs) response = func(*args, **kwargs)
return response return response
return wrapper return wrapper
...@@ -9,7 +9,7 @@ from flask import Flask, request ...@@ -9,7 +9,7 @@ from flask import Flask, request
from ..models import Connection, WSProxy from ..models import Connection, WSProxy
from ..proxy import ProxyServer from ..proxy import ProxyServer
from ..utils import get_logger from ..utils import get_logger
from ..ctx import app_service from ..service import app_service
from ..config import config from ..config import config
BASE_DIR = os.path.dirname(os.path.dirname(__file__)) BASE_DIR = os.path.dirname(os.path.dirname(__file__))
......
import stat import stat
import threading import threading
import tempfile
from flask import send_file from flask import send_file
import requests import requests
...@@ -231,17 +230,7 @@ class SFTPVolume(BaseVolume): ...@@ -231,17 +230,7 @@ class SFTPVolume(BaseVolume):
return target return target
def upload_as_url(self, url, parent): def upload_as_url(self, url, parent):
added = [] raise PermissionError("Not support upload from url")
parent_path = self._path(parent)
path = self._join(parent_path, self._base_name(url))
remote_path = self._remote_path(path)
r = requests.get(url, stream=True)
with self.sftp.open(remote_path, 'w') as rf:
for chunk in r.iter_content(chunk_size=1024):
if chunk: # filter out keep-alive new chunks
rf.write(chunk)
added.append(self._info(path))
return {'added': added}
def upload(self, files, parent): def upload(self, files, parent):
""" For now, this uses a very naive way of storing files - the entire """ For now, this uses a very naive way of storing files - the entire
......
...@@ -1528,9 +1528,15 @@ a.ui-button:active .ui-icon, ...@@ -1528,9 +1528,15 @@ a.ui-button:active .ui-icon,
.std42-dialog .ui-dialog-titlebar .elfinder-titlebar-minimize:hover .ui-icon { .std42-dialog .ui-dialog-titlebar .elfinder-titlebar-minimize:hover .ui-icon {
background-color: #ff9800; background-color: #ff9800;
} }
.elfinder-dialog-title { .elfinder-dialog-title {
color: #f1f1f1; color: #f1f1f1;
} }
.ui-dialog-buttonpane {
background: #fff;
}
.std42-dialog .ui-dialog-content { .std42-dialog .ui-dialog-content {
background: #fff; background: #fff;
} }
......
...@@ -375,7 +375,7 @@ ...@@ -375,7 +375,7 @@
'pass' : '密码', // added 18.04.2012 'pass' : '密码', // added 18.04.2012
'confirmUnmount' : '确实要卸载 $1?', // from v2.1 added 30.04.2012 'confirmUnmount' : '确实要卸载 $1?', // from v2.1 added 30.04.2012
'dropFilesBrowser': '从浏览器中拖放或粘贴文件', // from v2.1 added 30.05.2012 'dropFilesBrowser': '从浏览器中拖放或粘贴文件', // from v2.1 added 30.05.2012
'dropPasteFiles' : '拖放文件,粘贴网址或剪贴板图像', // from v2.1 added 07.04.2014 'dropPasteFiles' : '拖放文件,或粘贴剪贴板图像', // from v2.1 added 07.04.2014
'encoding' : '编码', // from v2.1 added 19.12.2014 'encoding' : '编码', // from v2.1 added 19.12.2014
'locale' : '语言环境', // from v2.1 added 19.12.2014 'locale' : '语言环境', // from v2.1 added 19.12.2014
'searchTarget' : '目标: $1', // from v2.1 added 22.5.2015 'searchTarget' : '目标: $1', // from v2.1 added 22.5.2015
......
...@@ -50,11 +50,13 @@ def sftp_host_connector_view(host): ...@@ -50,11 +50,13 @@ def sftp_host_connector_view(host):
@app.route('/coco/elfinder/sftp/<host>/') @app.route('/coco/elfinder/sftp/<host>/')
@login_required
def sftp_host_finder(host): def sftp_host_finder(host):
return render_template('elfinder/file_manager.html', host=host) return render_template('elfinder/file_manager.html', host=host)
@app.route('/coco/elfinder/sftp/') @app.route('/coco/elfinder/sftp/')
@login_required
def sftp_finder(): def sftp_finder():
return render_template('elfinder/file_manager.html', host='_') return render_template('elfinder/file_manager.html', host='_')
......
...@@ -9,7 +9,7 @@ from flask import request ...@@ -9,7 +9,7 @@ from flask import request
from ..models import Connection, WSProxy from ..models import Connection, WSProxy
from ..proxy import ProxyServer from ..proxy import ProxyServer
from ..utils import get_logger from ..utils import get_logger
from ..ctx import app_service from ..service import app_service
from .base import BaseNamespace from .base import BaseNamespace
from .utils import get_cached_volume from .utils import get_cached_volume
......
...@@ -12,7 +12,7 @@ from .utils import wrap_with_line_feed as wr, wrap_with_title as title, \ ...@@ -12,7 +12,7 @@ from .utils import wrap_with_line_feed as wr, wrap_with_title as title, \
wrap_with_warning as warning, is_obj_attr_has, is_obj_attr_eq, \ wrap_with_warning as warning, is_obj_attr_has, is_obj_attr_eq, \
sort_assets, ugettext as _, get_logger, net_input, format_with_zh, \ sort_assets, ugettext as _, get_logger, net_input, format_with_zh, \
item_max_length, size_of_str_with_zh, switch_lang item_max_length, size_of_str_with_zh, switch_lang
from .ctx import app_service from .service import app_service
from .proxy import ProxyServer from .proxy import ProxyServer
logger = get_logger(__file__) logger = get_logger(__file__)
......
...@@ -8,7 +8,7 @@ from collections import Iterable ...@@ -8,7 +8,7 @@ from collections import Iterable
from .utils import get_logger from .utils import get_logger
from .config import config from .config import config
from .ctx import app_service from .service import app_service
logger = get_logger(__file__) logger = get_logger(__file__)
......
...@@ -57,9 +57,9 @@ def create_logger(): ...@@ -57,9 +57,9 @@ def create_logger():
# 'engineio': main_setting, # 'engineio': main_setting,
} }
) )
dictConfig(config) dictConfig(config)
logger = logging.getLogger() logger = logging.getLogger()
return logger return logger
create_logger()
...@@ -4,7 +4,10 @@ import weakref ...@@ -4,7 +4,10 @@ import weakref
import uuid import uuid
import socket import socket
from .service import app_service
from .struct import SizedList, SelectEvent from .struct import SizedList, SelectEvent
from .utils import wrap_with_line_feed as wr, wrap_with_warning as warning, \
ugettext as _
from . import char from . import char
from . import utils from . import utils
...@@ -140,6 +143,11 @@ class Client: ...@@ -140,6 +143,11 @@ class Client:
return "<%s from %s:%s>" % (self.user, self.addr[0], self.addr[1]) return "<%s from %s:%s>" % (self.user, self.addr[0], self.addr[1])
class ServerFilter:
def run(self, data):
pass
class BaseServer: class BaseServer:
""" """
Base Server Base Server
...@@ -147,18 +155,23 @@ class BaseServer: ...@@ -147,18 +155,23 @@ class BaseServer:
sub-class: Server, Telnet Server sub-class: Server, Telnet Server
""" """
def __init__(self): def __init__(self, chan=None):
self.chan = None self.chan = chan
self._session_ref = None
self.input_data = SizedList(maxsize=1024) self._pre_input_state = True
self.output_data = SizedList(maxsize=1024)
self._in_input_state = True self._in_input_state = True
self._input_initial = False self._input_initial = False
self._enter_vim_mark = b'\x1b[?25l\x1b[37;1H\x1b[1m'
self._exit_vim_mark = b'\x1b[37;1H\x1b[K\x1b'
self._in_vim_state = False self._in_vim_state = False
self.input_data = SizedList(maxsize=1024)
self.output_data = SizedList(maxsize=1024)
self._input = "" self._input = ""
self._output = "" self._output = ""
self._session_ref = None
self._zmodem_recv_start_mark = b'rz waiting to receive.**\x18B0100' self._zmodem_recv_start_mark = b'rz waiting to receive.**\x18B0100'
self._zmodem_send_start_mark = b'**\x18B00000000000000' self._zmodem_send_start_mark = b'**\x18B00000000000000'
self._zmodem_cancel_mark = b'\x18\x18\x18\x18\x18' self._zmodem_cancel_mark = b'\x18\x18\x18\x18\x18'
...@@ -167,6 +180,15 @@ class BaseServer: ...@@ -167,6 +180,15 @@ class BaseServer:
self._zmodem_state_recv = 'recv' self._zmodem_state_recv = 'recv'
self._zmodem_state = '' self._zmodem_state = ''
self._cmd_parser = utils.TtyIOParser()
self._cmd_filter_rules = self.get_system_user_cmd_filter_rules()
def get_system_user_cmd_filter_rules(self):
rules = app_service.get_system_user_cmd_filter_rules(
self.system_user.id
)
return rules
def set_session(self, session): def set_session(self, session):
self._session_ref = weakref.ref(session) self._session_ref = weakref.ref(session)
...@@ -177,51 +199,86 @@ class BaseServer: ...@@ -177,51 +199,86 @@ class BaseServer:
else: else:
return None return None
def initial_filter(self): def s_initial_filter(self, data):
if not self._input_initial: if not self._input_initial:
self._input_initial = True self._input_initial = True
return data
def parse_cmd_filter(self, data): def s_input_state_filter(self, data):
# 输入了回车键, 开始计算输入的内容 self._pre_input_state = self._in_input_state
if self._have_enter_char(data): if self._in_vim_state:
self._in_input_state = False self._in_input_state = False
self._input = self._parse_input() # 输入了回车键
return data elif self._have_enter_char(data):
# 用户输入了内容,但是如果没在输入状态,也就是用户刚开始输入了,结算上次输出内容 self._in_input_state = False
else:
self._in_input_state = True
return data
def s_parse_input_output_filter(self, data):
# 输入了回车键, 计算输入的命令
if not self._in_input_state: if not self._in_input_state:
self._input = self._parse_input()
# 用户输入了内容,但是上次没在输入状态,也就是用户刚开始输入了,结算上次输出内容
if not self._pre_input_state and self._in_input_state:
self._output = self._parse_output() self._output = self._parse_output()
logger.debug("\n{}\nInput: {}\nOutput: {}\n{}".format( # logger.debug("\n{}\nInput: {}\nOutput: {}\n{}".format(
"#" * 30 + " Command " + "#" * 30, # "#" * 30 + " Command " + "#" * 30,
self._input, self._output, # self._input, self._output,
"#" * 30 + " End " + "#" * 30, # "#" * 30 + " End " + "#" * 30,
)) # ))
if self._input: if self._input:
self.session.put_command(self._input, self._output) self.session.put_command(self._input, self._output)
self.input_data.clean() self.input_data.clean()
self.output_data.clean() self.output_data.clean()
self._in_input_state = True
return data return data
def send(self, data): def s_filter_cmd_filter(self, data):
self.initial_filter() if self._in_input_state:
self.parse_cmd_filter(data) return data
return self.chan.send(data) if not self._input:
return data
for rule in self._cmd_filter_rules:
action, cmd = rule.match(self._input)
if action == rule.ALLOW:
break
elif action == rule.DENY:
data = char.CLEAR_LINE_CHAR + b'\r'
msg = _("Command `{}` is forbidden ........").format(cmd)
msg = wr(warning(msg.encode()), before=1, after=1)
self.output_data.append(msg)
self.session.send_to_clients(msg)
self.session.put_command(self._input, msg.decode())
self.session.put_replay(msg)
self.input_data.clean()
break
return data
def replay_filter(self, data): def r_replay_filter(self, data):
if not self._zmodem_state: if not self._zmodem_state:
self.session.put_replay(data) self.session.put_replay(data)
def input_output_filter(self, data): def r_vim_state_filter(self, data):
if self._zmodem_state:
return data
if self._in_vim_state and data[:11] == self._exit_vim_mark:
self._in_vim_state = False
elif not self._in_vim_state and data[:17] == self._enter_vim_mark:
self._in_vim_state = True
return data
def r_input_output_data_filter(self, data):
if not self._input_initial: if not self._input_initial:
return return data
if self._zmodem_state: if self._zmodem_state:
return return data
if self._in_input_state: if self._in_input_state:
self.input_data.append(data) self.input_data.append(data)
else: else:
self.output_data.append(data) self.output_data.append(data)
return data
def zmodem_state_filter(self, data): def r_zmodem_state_filter(self, data):
if not self._zmodem_state: if not self._zmodem_state:
if data[:50].find(self._zmodem_recv_start_mark) != -1: if data[:50].find(self._zmodem_recv_start_mark) != -1:
logger.debug("Zmodem state => recv") logger.debug("Zmodem state => recv")
...@@ -237,18 +294,29 @@ class BaseServer: ...@@ -237,18 +294,29 @@ class BaseServer:
logger.debug("Zmodem state => cancel") logger.debug("Zmodem state => cancel")
self._zmodem_state = '' self._zmodem_state = ''
def zmodem_cancel_filter(self): def r_zmodem_disable_filter(self, data=''):
if self._zmodem_state: if self._zmodem_state:
pass pass
# self.chan.send(self._zmodem_cancel_mark) # self.chan.send(self._zmodem_cancel_mark)
# self.chan.send("Zmodem disabled") # self.chan.send("Zmodem disabled")
def send(self, data):
self.s_initial_filter(data)
self.s_input_state_filter(data)
try:
self.s_parse_input_output_filter(data)
data = self.s_filter_cmd_filter(data)
except Exception as e:
logger.exception(e)
return self.chan.send(data)
def recv(self, size): def recv(self, size):
data = self.chan.recv(size) data = self.chan.recv(size)
self.zmodem_state_filter(data) self.r_zmodem_state_filter(data)
self.zmodem_cancel_filter() self.r_vim_state_filter(data)
self.replay_filter(data) self.r_zmodem_disable_filter(data)
self.input_output_filter(data) self.r_replay_filter(data)
self.r_input_output_data_filter(data)
return data return data
@staticmethod @staticmethod
...@@ -261,21 +329,20 @@ class BaseServer: ...@@ -261,21 +329,20 @@ class BaseServer:
def _parse_output(self): def _parse_output(self):
if not self.output_data: if not self.output_data:
return '' return ''
parser = utils.TtyIOParser() return self._cmd_parser.parse_output(self.output_data)
return parser.parse_output(self.output_data)
def _parse_input(self): def _parse_input(self):
print("Parse input: {}".format(self.input_data))
if not self.input_data: if not self.input_data:
return return
parser = utils.TtyIOParser() return self._cmd_parser.parse_input(self.input_data)
return parser.parse_input(self.input_data)
def fileno(self): def fileno(self):
return self.chan.fileno() return self.chan.fileno()
def close(self): def close(self):
logger.info("Closed server {}".format(self)) logger.info("Closed server {}".format(self))
self.input_output_filter(b'') self.r_input_output_data_filter(b'')
self.chan.close() self.chan.close()
def __getattr__(self, item): def __getattr__(self, item):
...@@ -290,10 +357,9 @@ class TelnetServer(BaseServer): ...@@ -290,10 +357,9 @@ class TelnetServer(BaseServer):
Telnet server Telnet server
""" """
def __init__(self, sock, asset, system_user): def __init__(self, sock, asset, system_user):
super(TelnetServer, self).__init__()
self.chan = sock
self.asset = asset self.asset = asset
self.system_user = system_user self.system_user = system_user
super(TelnetServer, self).__init__(chan=sock)
class Server(BaseServer): class Server(BaseServer):
...@@ -306,11 +372,10 @@ class Server(BaseServer): ...@@ -306,11 +372,10 @@ class Server(BaseServer):
# Todo: Server name is not very suitable # Todo: Server name is not very suitable
def __init__(self, chan, sock, asset, system_user): def __init__(self, chan, sock, asset, system_user):
super(Server, self).__init__()
self.chan = chan
self.sock = sock self.sock = sock
self.asset = asset self.asset = asset
self.system_user = system_user self.system_user = system_user
super(Server, self).__init__(chan=chan)
def close(self): def close(self):
super().close() super().close()
......
...@@ -8,7 +8,7 @@ import time ...@@ -8,7 +8,7 @@ import time
from .session import Session from .session import Session
from .models import Server, TelnetServer from .models import Server, TelnetServer
from .connection import SSHConnection, TelnetConnection from .connection import SSHConnection, TelnetConnection
from .ctx import app_service from .service import app_service
from .config import config from .config import config
from .utils import wrap_with_line_feed as wr, wrap_with_warning as warning, \ from .utils import wrap_with_line_feed as wr, wrap_with_warning as warning, \
get_logger, net_input, ugettext as _ get_logger, net_input, ugettext as _
...@@ -39,6 +39,7 @@ class ProxyServer: ...@@ -39,6 +39,7 @@ class ProxyServer:
or (not password and not private_key): or (not password and not private_key):
prompt = "{}'s password: ".format(self.system_user.username) prompt = "{}'s password: ".format(self.system_user.username)
password = net_input(self.client, prompt=prompt, sensitive=True) password = net_input(self.client, prompt=prompt, sensitive=True)
private_key = None
self.system_user.password = password self.system_user.password = password
self.system_user.private_key = private_key self.system_user.private_key = private_key
......
...@@ -15,7 +15,7 @@ import jms_storage ...@@ -15,7 +15,7 @@ import jms_storage
from .config import config from .config import config
from .utils import get_logger, Singleton from .utils import get_logger, Singleton
from .struct import MemoryQueue from .struct import MemoryQueue
from .ctx import app_service from .service import app_service
logger = get_logger(__file__) logger = get_logger(__file__)
BUF_SIZE = 1024 BUF_SIZE = 1024
......
...@@ -8,7 +8,7 @@ import time ...@@ -8,7 +8,7 @@ import time
from .utils import get_logger, wrap_with_warning as warn, \ from .utils import get_logger, wrap_with_warning as warn, \
wrap_with_line_feed as wr, ugettext as _, ignore_error wrap_with_line_feed as wr, ugettext as _, ignore_error
from .ctx import app_service from .service import app_service
from .struct import SelectEvent from .struct import SelectEvent
from .recorder import get_recorder from .recorder import get_recorder
...@@ -147,6 +147,10 @@ class Session: ...@@ -147,6 +147,10 @@ class Session:
pass pass
self.stop_evt.set() self.stop_evt.set()
def send_to_clients(self, data):
for watcher in [self.client] + self._watchers + self._sharers:
watcher.send(data)
def bridge(self): def bridge(self):
""" """
Bridge clients with server Bridge clients with server
......
...@@ -9,7 +9,7 @@ from paramiko.sftp import SFTP_PERMISSION_DENIED, SFTP_NO_SUCH_FILE, \ ...@@ -9,7 +9,7 @@ from paramiko.sftp import SFTP_PERMISSION_DENIED, SFTP_NO_SUCH_FILE, \
from coco.utils import get_logger from coco.utils import get_logger
from .config import config from .config import config
from .ctx import app_service from .service import app_service
from .connection import SSHConnection from .connection import SSHConnection
CURRENT_DIR = os.path.dirname(__file__) CURRENT_DIR = os.path.dirname(__file__)
......
...@@ -90,7 +90,7 @@ class SSHServer: ...@@ -90,7 +90,7 @@ class SSHServer:
continue continue
if not server.event.is_set(): if not server.event.is_set():
logger.warning("Client not request a valid request, exiting") logger.warning("Client not request invalid, exiting")
sock.close() sock.close()
return return
else: else:
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
from .ctx import app_service from .service import app_service
from .utils import get_logger from .utils import get_logger
from .session import Session from .session import Session
......
...@@ -2,6 +2,11 @@ ...@@ -2,6 +2,11 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
import eventlet
from eventlet.debug import hub_prevent_multiple_readers
eventlet.monkey_patch()
hub_prevent_multiple_readers(False)
import os import os
import sys import sys
import argparse import argparse
...@@ -16,12 +21,9 @@ except ImportError: ...@@ -16,12 +21,9 @@ except ImportError:
print("Please prepare config file `cp conf_example.py conf.py`") print("Please prepare config file `cp conf_example.py conf.py`")
sys.exit(1) sys.exit(1)
try: dirs = ('logs', 'keys')
os.mkdir("logs") for d in dirs:
os.mkdir("keys") os.makedirs(d, exist_ok=True)
os.mkdir("sessions")
except:
pass
BASE_DIR = os.path.dirname(os.path.abspath(__file__)) BASE_DIR = os.path.dirname(os.path.abspath(__file__))
DAEMON = False DAEMON = False
......
...@@ -7,7 +7,7 @@ msgid "" ...@@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-09-03 10:39+0800\n" "POT-Creation-Date: 2018-10-10 15:22+0800\n"
"PO-Revision-Date: 2018-08-10 10:42+0800\n" "PO-Revision-Date: 2018-08-10 10:42+0800\n"
"Last-Translator: BaiJiangjie <bugatti_it@163.com>\n" "Last-Translator: BaiJiangjie <bugatti_it@163.com>\n"
"Language-Team: Language locale/en/LC\n" "Language-Team: Language locale/en/LC\n"
...@@ -16,7 +16,7 @@ msgstr "" ...@@ -16,7 +16,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
#: coco/app.py:147 #: coco/app.py:141
msgid "Connect idle more than {} minutes, disconnect" msgid "Connect idle more than {} minutes, disconnect"
msgstr "" msgstr ""
...@@ -91,44 +91,44 @@ msgstr "" ...@@ -91,44 +91,44 @@ msgstr ""
msgid "Total: {}" msgid "Total: {}"
msgstr "" msgstr ""
#: coco/interactive.py:159 #: coco/interactive.py:161
msgid "There is no matched node, please re-enter" msgid "There is no matched node, please re-enter"
msgstr "" msgstr ""
#: coco/interactive.py:170 #: coco/interactive.py:172
msgid "ID" msgid "ID"
msgstr "" msgstr ""
#: coco/interactive.py:170 #: coco/interactive.py:172
msgid "Hostname" msgid "Hostname"
msgstr "" msgstr ""
#: coco/interactive.py:170 #: coco/interactive.py:172
msgid "IP" msgid "IP"
msgstr "" msgstr ""
#: coco/interactive.py:170 #: coco/interactive.py:172
msgid "LoginAs" msgid "LoginAs"
msgstr "" msgstr ""
#: coco/interactive.py:184 #: coco/interactive.py:186
msgid "Comment" msgid "Comment"
msgstr "" msgstr ""
#: coco/interactive.py:192 #: coco/interactive.py:194
msgid "Total: {} Match: {}" msgid "Total: {} Match: {}"
msgstr "" msgstr ""
#: coco/interactive.py:235 #: coco/interactive.py:237
msgid "Select a login:: " msgid "Select a login:: "
msgstr "" msgstr ""
#: coco/interactive.py:258 #: coco/interactive.py:260
msgid "" msgid ""
"Terminal does not support login Windows, please use web terminal to access" "Terminal does not support login Windows, please use web terminal to access"
msgstr "" msgstr ""
#: coco/interactive.py:269 #: coco/interactive.py:271
msgid "No system user" msgid "No system user"
msgstr "" msgstr ""
......
# Language locale/en/LC translations for PACKAGE package.
# Copyright (C) 2018 THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# BaiJiangjie <bugatti_it@163.com>, 2018.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-09-03 10:36+0800\n"
"PO-Revision-Date: 2018-08-10 10:42+0800\n"
"Last-Translator: BaiJiangjie <bugatti_it@163.com>\n"
"Language-Team: Language locale/en/LC\n"
"Language: locale/en/LC_MESSAGES/coco\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: coco/app.py:147
msgid "Connect idle more than {} minutes, disconnect"
msgstr ""
#: coco/interactive.py:61
#, python-brace-format
msgid ""
"\n"
"{T}{T}{title} {user}, Welcome to use Jumpserver open source fortress system "
"{end}{R}{R}"
msgstr ""
#: coco/interactive.py:63
#, python-brace-format
msgid ""
"{T}1) Enter {green}ID{end} directly login or enter {green}part IP, Hostname, "
"Comment{end} to search login(if unique).{R}"
msgstr ""
#: coco/interactive.py:64
#, python-brace-format
msgid ""
"{T}2) Enter {green}/{end} + {green}IP, Hostname{end} or {green}Comment {end} "
"search, such as: /ip.{R}"
msgstr ""
#: coco/interactive.py:65
#, python-brace-format
msgid "{T}3) Enter {green}p{end} to display the host you have permission.{R}"
msgstr ""
#: coco/interactive.py:66
#, python-brace-format
msgid ""
"{T}4) Enter {green}g{end} to display the node that you have permission.{R}"
msgstr ""
#: coco/interactive.py:67
#, python-brace-format
msgid ""
"{T}5) Enter {green}g{end} + {green}Group ID{end} to display the host under "
"the node, such as g1.{R}"
msgstr ""
#: coco/interactive.py:68
#, python-brace-format
msgid "{T}6) Enter {green}s{end} Chinese-english switch.{R}"
msgstr ""
#: coco/interactive.py:69
#, python-brace-format
msgid "{T}7) Enter {green}h{end} help.{R}"
msgstr ""
#: coco/interactive.py:70
#, python-brace-format
msgid "{T}0) Enter {green}q{end} exit.{R}"
msgstr ""
#: coco/interactive.py:142
msgid "No"
msgstr ""
#: coco/interactive.py:149
msgid "Name"
msgstr ""
#: coco/interactive.py:149
msgid "Assets"
msgstr ""
#: coco/interactive.py:155
msgid "Total: {}"
msgstr ""
#: coco/interactive.py:159
msgid "There is no matched node, please re-enter"
msgstr ""
#: coco/interactive.py:170
msgid "ID"
msgstr ""
#: coco/interactive.py:170
msgid "Hostname"
msgstr ""
#: coco/interactive.py:170
msgid "IP"
msgstr ""
#: coco/interactive.py:170
msgid "LoginAs"
msgstr ""
#: coco/interactive.py:184
msgid "Comment"
msgstr ""
#: coco/interactive.py:192
msgid "Total: {} Match: {}"
msgstr ""
#: coco/interactive.py:235
msgid "Select a login:: "
msgstr ""
#: coco/interactive.py:258
msgid ""
"Terminal does not support login Windows, please use web terminal to access"
msgstr ""
#: coco/interactive.py:269
msgid "No system user"
msgstr ""
#: coco/session.py:143
msgid "Terminated by administrator"
msgstr ""
...@@ -7,7 +7,7 @@ msgid "" ...@@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-09-03 10:39+0800\n" "POT-Creation-Date: 2018-10-10 15:22+0800\n"
"PO-Revision-Date: 2018-08-10 10:42+0800\n" "PO-Revision-Date: 2018-08-10 10:42+0800\n"
"Last-Translator: BaiJiangjie <bugatti_it@163.com>\n" "Last-Translator: BaiJiangjie <bugatti_it@163.com>\n"
"Language-Team: Language locale/zh\n" "Language-Team: Language locale/zh\n"
...@@ -16,7 +16,7 @@ msgstr "" ...@@ -16,7 +16,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
#: coco/app.py:147 #: coco/app.py:141
msgid "Connect idle more than {} minutes, disconnect" msgid "Connect idle more than {} minutes, disconnect"
msgstr "空闲时间超过 {} 分钟,断开连接" msgstr "空闲时间超过 {} 分钟,断开连接"
...@@ -77,9 +77,9 @@ msgid "{T}7) Enter {green}h{end} help.{R}" ...@@ -77,9 +77,9 @@ msgid "{T}7) Enter {green}h{end} help.{R}"
msgstr "{T}7) 输入 {green}h{end} 帮助.{R}" msgstr "{T}7) 输入 {green}h{end} 帮助.{R}"
#: coco/interactive.py:70 #: coco/interactive.py:70
#, fuzzy, python-brace-format #, python-brace-format
msgid "{T}0) Enter {green}q{end} exit.{R}" msgid "{T}0) Enter {green}q{end} exit.{R}"
msgstr "{T}0) 输入 {green}q{end} 退出.{R}\n" msgstr "{T}0) 输入 {green}q{end} 退出.{R}"
#: coco/interactive.py:142 #: coco/interactive.py:142
msgid "No" msgid "No"
...@@ -97,44 +97,44 @@ msgstr "资产" ...@@ -97,44 +97,44 @@ msgstr "资产"
msgid "Total: {}" msgid "Total: {}"
msgstr "总共: {}" msgstr "总共: {}"
#: coco/interactive.py:159 #: coco/interactive.py:161
msgid "There is no matched node, please re-enter" msgid "There is no matched node, please re-enter"
msgstr "没有匹配分组,请重新输入" msgstr "没有匹配分组,请重新输入"
#: coco/interactive.py:170 #: coco/interactive.py:172
msgid "ID" msgid "ID"
msgstr "" msgstr ""
#: coco/interactive.py:170 #: coco/interactive.py:172
msgid "Hostname" msgid "Hostname"
msgstr "主机名" msgstr "主机名"
#: coco/interactive.py:170 #: coco/interactive.py:172
msgid "IP" msgid "IP"
msgstr "" msgstr ""
#: coco/interactive.py:170 #: coco/interactive.py:172
msgid "LoginAs" msgid "LoginAs"
msgstr "" msgstr "登录用户"
#: coco/interactive.py:184 #: coco/interactive.py:186
msgid "Comment" msgid "Comment"
msgstr "备注" msgstr "备注"
#: coco/interactive.py:192 #: coco/interactive.py:194
msgid "Total: {} Match: {}" msgid "Total: {} Match: {}"
msgstr "总共: {} 匹配: {}" msgstr "总共: {} 匹配: {}"
#: coco/interactive.py:235 #: coco/interactive.py:237
msgid "Select a login:: " msgid "Select a login:: "
msgstr "选择一个登录:" msgstr "选择一个登录:"
#: coco/interactive.py:258 #: coco/interactive.py:260
msgid "" msgid ""
"Terminal does not support login Windows, please use web terminal to access" "Terminal does not support login Windows, please use web terminal to access"
msgstr "终端不支持登录windows, 请使用web terminal访问" msgstr "终端不支持登录windows, 请使用web terminal访问"
#: coco/interactive.py:269 #: coco/interactive.py:271
msgid "No system user" msgid "No system user"
msgstr "没有系统用户" msgstr "没有系统用户"
......
# Language locale/zh translations for PACKAGE package.
# Copyright (C) 2018 THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# BaiJiangjie <bugatti_it@163.com>, 2018.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-09-03 10:36+0800\n"
"PO-Revision-Date: 2018-08-10 10:42+0800\n"
"Last-Translator: BaiJiangjie <bugatti_it@163.com>\n"
"Language-Team: Language locale/zh\n"
"Language: locale/zh_CN/LC_MESSAGES/coco\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: coco/app.py:147
msgid "Connect idle more than {} minutes, disconnect"
msgstr "空闲时间超过 {} 分钟,断开连接"
#: coco/interactive.py:61
#, python-brace-format
msgid ""
"\n"
"{T}{T}{title} {user}, Welcome to use Jumpserver open source fortress system "
"{end}{R}{R}"
msgstr ""
"\n"
"{T}{T}{title} {user}, 欢迎使用Jumpserver开源跳板机系统 {end}{R}{R}"
#: coco/interactive.py:63
#, python-brace-format
msgid ""
"{T}1) Enter {green}ID{end} directly login or enter {green}part IP, Hostname, "
"Comment{end} to search login(if unique).{R}"
msgstr ""
"{T}1) 输入 {green}ID{end} 直接登录 或 输入{green}部分 IP,主机名,备注{end} 进"
"行搜索登录(如果唯一).{R}"
#: coco/interactive.py:64
#, python-brace-format
msgid ""
"{T}2) Enter {green}/{end} + {green}IP, Hostname{end} or {green}Comment {end} "
"search, such as: /ip.{R}"
msgstr ""
"{T}2) 输入 {green}/{end} + {green}IP, 主机名{end} or {green}备注 {end}搜索. "
"如: /ip{R}"
#: coco/interactive.py:65
#, python-brace-format
msgid "{T}3) Enter {green}p{end} to display the host you have permission.{R}"
msgstr "{T}3) 输入 {green}p{end} 显示您有权限的主机.{R}"
#: coco/interactive.py:66
#, python-brace-format
msgid ""
"{T}4) Enter {green}g{end} to display the node that you have permission.{R}"
msgstr "{T}4) 输入 {green}g{end} 显示您有权限的节点.{R}"
#: coco/interactive.py:67
#, python-brace-format
msgid ""
"{T}5) Enter {green}g{end} + {green}Group ID{end} to display the host under "
"the node, such as g1.{R}"
msgstr "{T}5) 输入 {green}g{end} + {green}组ID{end} 显示节点下主机. 如: g1{R}"
#: coco/interactive.py:68
#, python-brace-format
msgid "{T}6) Enter {green}s{end} Chinese-english switch.{R}"
msgstr "{T}6) 输入 {green}s{end} 中/英文切换.{R}"
#: coco/interactive.py:69
#, python-brace-format
msgid "{T}7) Enter {green}h{end} help.{R}"
msgstr "{T}7) 输入 {green}h{end} 帮助.{R}"
#: coco/interactive.py:70
#, fuzzy, python-brace-format
msgid "{T}0) Enter {green}q{end} exit.{R}"
msgstr "{T}0) 输入 {green}q{end} 退出.{R}\n"
#: coco/interactive.py:142
msgid "No"
msgstr "无"
#: coco/interactive.py:149
msgid "Name"
msgstr "名称"
#: coco/interactive.py:149
msgid "Assets"
msgstr "资产"
#: coco/interactive.py:155
msgid "Total: {}"
msgstr "总共: {}"
#: coco/interactive.py:159
msgid "There is no matched node, please re-enter"
msgstr "没有匹配分组,请重新输入"
#: coco/interactive.py:170
msgid "ID"
msgstr ""
#: coco/interactive.py:170
msgid "Hostname"
msgstr "主机名"
#: coco/interactive.py:170
msgid "IP"
msgstr ""
#: coco/interactive.py:170
msgid "LoginAs"
msgstr ""
#: coco/interactive.py:184
msgid "Comment"
msgstr "备注"
#: coco/interactive.py:192
msgid "Total: {} Match: {}"
msgstr "总共: {} 匹配: {}"
#: coco/interactive.py:235
msgid "Select a login:: "
msgstr "选择一个登录:"
#: coco/interactive.py:258
msgid ""
"Terminal does not support login Windows, please use web terminal to access"
msgstr "终端不支持登录windows, 请使用web terminal访问"
#: coco/interactive.py:269
msgid "No system user"
msgstr "没有系统用户"
#: coco/session.py:143
msgid "Terminated by administrator"
msgstr "被管理员中断"
...@@ -19,7 +19,7 @@ itsdangerous==0.24 ...@@ -19,7 +19,7 @@ itsdangerous==0.24
Jinja2==2.10 Jinja2==2.10
jmespath==0.9.3 jmespath==0.9.3
jms-storage==0.0.19 jms-storage==0.0.19
jumpserver-python-sdk==0.0.48 jumpserver-python-sdk==0.0.50
MarkupSafe==1.0 MarkupSafe==1.0
oss2==2.4.0 oss2==2.4.0
paramiko==2.4.1 paramiko==2.4.1
......
...@@ -2,15 +2,15 @@ ...@@ -2,15 +2,15 @@
# #
function init_message() { function init_message() {
xgettext -k_ -o pot/coco.pot --from-code=UTF-8 coco/*.py xgettext -k_ -o /tmp/coco.pot --from-code=UTF-8 coco/*.py
msginit -l locale/zh_CN/LC_MESSAGES/coco -i pot/coco.pot msginit -l locale/zh_CN/LC_MESSAGES/coco -i /tmp/coco.pot
msginit -l locale/en/LC_MESSAGES/coco -i pot/coco.pot msginit -l locale/en/LC_MESSAGES/coco -i /tmp/coco.pot
} }
function make_message() { function make_message() {
xgettext -k_ -o pot/coco.pot --from-code=UTF-8 coco/*.py xgettext -k_ -o /tmp/coco.pot --from-code=UTF-8 coco/*.py
msgmerge -U locale/zh_CN/LC_MESSAGES/coco.po pot/coco.pot msgmerge -U locale/zh_CN/LC_MESSAGES/coco.po /tmp/coco.pot
msgmerge -U locale/en/LC_MESSAGES/coco.po pot/coco.pot msgmerge -U locale/en/LC_MESSAGES/coco.po /tmp/coco.pot
} }
function compile_message() { function compile_message() {
......
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