update
This commit is contained in:
@@ -42,7 +42,9 @@ frameSocket.on('refresh', function(data){
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
$('#command_modal').on('hide.bs.modal', function (event) {
|
$('#command_modal').on('hide.bs.modal', function (e) {
|
||||||
|
//e.preventDefault(); 있으면 동작 안함.
|
||||||
|
console.log("ff global command_modal hide.bs.modal CATCH")
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: `/global/ajax/command_modal_hide`,
|
url: `/global/ajax/command_modal_hide`,
|
||||||
type: 'POST',
|
type: 'POST',
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
VERSION="4.0.27"
|
VERSION="4.0.28"
|
||||||
@@ -87,7 +87,7 @@ class SupportSubprocess(object):
|
|||||||
logger.error('command : %s', command)
|
logger.error('command : %s', command)
|
||||||
|
|
||||||
|
|
||||||
instance_list = []
|
__instance_list = []
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, command, print_log=False, shell=False, env=None, timeout=None, uid=None, gid=None, stdout_callback=None, call_id=None):
|
def __init__(self, command, print_log=False, shell=False, env=None, timeout=None, uid=None, gid=None, stdout_callback=None, call_id=None):
|
||||||
@@ -107,7 +107,7 @@ class SupportSubprocess(object):
|
|||||||
|
|
||||||
def start(self, join=True):
|
def start(self, join=True):
|
||||||
try:
|
try:
|
||||||
self.thread = threading.Thread(target=self.execute_thread_function, args=())
|
self.thread = threading.Thread(target=self.__execute_thread_function, args=())
|
||||||
self.thread.setDaemon(True)
|
self.thread.setDaemon(True)
|
||||||
self.thread.start()
|
self.thread.start()
|
||||||
if join:
|
if join:
|
||||||
@@ -117,7 +117,7 @@ class SupportSubprocess(object):
|
|||||||
logger.error(traceback.format_exc())
|
logger.error(traceback.format_exc())
|
||||||
|
|
||||||
|
|
||||||
def execute_thread_function(self):
|
def __execute_thread_function(self):
|
||||||
try:
|
try:
|
||||||
if platform.system() == 'Windows':
|
if platform.system() == 'Windows':
|
||||||
tmp = []
|
tmp = []
|
||||||
@@ -137,15 +137,16 @@ class SupportSubprocess(object):
|
|||||||
self.process = subprocess.Popen(self.command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, shell=self.shell, env=self.env, encoding='utf8', bufsize=0)
|
self.process = subprocess.Popen(self.command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, shell=self.shell, env=self.env, encoding='utf8', bufsize=0)
|
||||||
else:
|
else:
|
||||||
self.process = subprocess.Popen(self.command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, shell=self.shell, env=self.env, preexec_fn=demote(self.uid, self.gid), encoding='utf8', bufsize=0)
|
self.process = subprocess.Popen(self.command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, shell=self.shell, env=self.env, preexec_fn=demote(self.uid, self.gid), encoding='utf8', bufsize=0)
|
||||||
SupportSubprocess.instance_list.append(self)
|
SupportSubprocess.__instance_list.append(self)
|
||||||
self.start_communicate()
|
self.__start_communicate()
|
||||||
self.start_send_callback()
|
self.__start_send_callback()
|
||||||
if self.process is not None:
|
if self.process is not None:
|
||||||
self.process.wait()
|
self.process.wait()
|
||||||
logger.info(f"{self.command} END")
|
logger.info(f"{self.command} END")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f'Exception:{str(e)}')
|
logger.error(f'Exception:{str(e)}')
|
||||||
logger.error(traceback.format_exc())
|
logger.error(traceback.format_exc())
|
||||||
|
logger.warning(self.command)
|
||||||
if self.stdout_callback != None:
|
if self.stdout_callback != None:
|
||||||
self.stdout_callback('error', str(e))
|
self.stdout_callback('error', str(e))
|
||||||
self.stdout_callback('error', str(traceback.format_exc()))
|
self.stdout_callback('error', str(traceback.format_exc()))
|
||||||
@@ -154,7 +155,7 @@ class SupportSubprocess(object):
|
|||||||
self.stdout_callback('thread_end', None)
|
self.stdout_callback('thread_end', None)
|
||||||
|
|
||||||
|
|
||||||
def start_communicate(self):
|
def __start_communicate(self):
|
||||||
self.stdout_queue = queue.Queue()
|
self.stdout_queue = queue.Queue()
|
||||||
sout = io.open(self.process.stdout.fileno(), 'rb', closefd=False)
|
sout = io.open(self.process.stdout.fileno(), 'rb', closefd=False)
|
||||||
|
|
||||||
@@ -199,7 +200,7 @@ class SupportSubprocess(object):
|
|||||||
Pump(sout)
|
Pump(sout)
|
||||||
|
|
||||||
|
|
||||||
def start_send_callback(self):
|
def __start_send_callback(self):
|
||||||
def func():
|
def func():
|
||||||
while self.stdout_queue:
|
while self.stdout_queue:
|
||||||
line = self.stdout_queue.get()
|
line = self.stdout_queue.get()
|
||||||
@@ -245,29 +246,29 @@ class SupportSubprocess(object):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def all_process_close(cls):
|
def all_process_close(cls):
|
||||||
for instance in cls.instance_list:
|
for instance in cls.__instance_list:
|
||||||
instance.process_close()
|
instance.process_close()
|
||||||
cls.instance_list = []
|
cls.__instance_list = []
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def remove_instance(cls, remove_instance):
|
def remove_instance(cls, remove_instance):
|
||||||
new = []
|
new = []
|
||||||
for instance in cls.instance_list:
|
for instance in cls.__instance_list:
|
||||||
if remove_instance.timestamp == instance.timestamp:
|
if remove_instance.timestamp == instance.timestamp:
|
||||||
continue
|
continue
|
||||||
new.append(instance)
|
new.append(instance)
|
||||||
cls.instance_list = new
|
cls.__instance_list = new
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def print(cls):
|
def print(cls):
|
||||||
for instance in cls.instance_list:
|
for instance in cls.__instance_list:
|
||||||
logger.info(instance.command)
|
logger.info(instance.command)
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_instance_by_call_id(cls, call_id):
|
def get_instance_by_call_id(cls, call_id):
|
||||||
for instance in cls.instance_list:
|
for instance in cls.__instance_list:
|
||||||
if instance.call_id == call_id:
|
if instance.call_id == call_id:
|
||||||
return instance
|
return instance
|
||||||
|
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
from support import SupportFile
|
from support import SupportSubprocess
|
||||||
|
from tool import ToolModalCommand
|
||||||
|
|
||||||
from .page_command import PageCommand
|
from .page_command import PageCommand
|
||||||
from .setup import *
|
from .setup import *
|
||||||
@@ -36,4 +37,27 @@ class PageCrypt(PluginPageBase):
|
|||||||
class PagePython(PluginPageBase):
|
class PagePython(PluginPageBase):
|
||||||
def __init__(self, P, parent):
|
def __init__(self, P, parent):
|
||||||
super(PagePython, self).__init__(P, parent, name='python')
|
super(PagePython, self).__init__(P, parent, name='python')
|
||||||
|
self.db_default = {
|
||||||
|
f'{self.parent.name}_{self.name}_name': '',
|
||||||
|
}
|
||||||
|
|
||||||
|
def process_command(self, command, arg1, arg2, arg3, req):
|
||||||
|
ret = {'ret':'success'}
|
||||||
|
if command == 'get_freeze':
|
||||||
|
command = ['pip', 'freeze']
|
||||||
|
result = SupportSubprocess.execute_command_return(command)
|
||||||
|
if result['status'] == 'finish':
|
||||||
|
ret['data'] = []
|
||||||
|
for tmp in result['log'].split('\n'):
|
||||||
|
ret['data'].append(tmp.split('=='))
|
||||||
|
else:
|
||||||
|
ret['ret'] = 'danger'
|
||||||
|
ret['msg'] = "실패"
|
||||||
|
elif command == 'upgrade':
|
||||||
|
P.ModelSetting.set(f'{self.parent.name}_{self.name}_name', arg1)
|
||||||
|
cmd = ['pip', 'install', '--upgrade', arg1]
|
||||||
|
ToolModalCommand.start("pip 설치", [cmd])
|
||||||
|
elif command == 'remove':
|
||||||
|
cmd = ['pip', 'uninstall', '-y', arg1]
|
||||||
|
ToolModalCommand.start("pip 삭제", [cmd])
|
||||||
|
return jsonify(ret)
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ class PageCommand(PluginPageBase):
|
|||||||
import io
|
import io
|
||||||
from contextlib import redirect_stdout
|
from contextlib import redirect_stdout
|
||||||
load_log_list = io.StringIO()
|
load_log_list = io.StringIO()
|
||||||
with redirect_stdout(self.load_log_list):
|
with redirect_stdout(load_log_list):
|
||||||
start_communicate_load(load_log_list)
|
start_communicate_load(load_log_list)
|
||||||
if job_id is not None:
|
if job_id is not None:
|
||||||
command_logger = get_logger(f'command_{job_id}')
|
command_logger = get_logger(f'command_{job_id}')
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ __menu = {
|
|||||||
'list': [
|
'list': [
|
||||||
#{'uri': 'setting', 'name': '설정'},
|
#{'uri': 'setting', 'name': '설정'},
|
||||||
{'uri': 'list', 'name': '로딩 플러그인'},
|
{'uri': 'list', 'name': '로딩 플러그인'},
|
||||||
{'uri': 'all', 'name': '플러그인 목록'},
|
#{'uri': 'all', 'name': '플러그인 목록'},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -32,8 +32,8 @@ __menu = {
|
|||||||
{'uri': 'command', 'name': 'Command'},
|
{'uri': 'command', 'name': 'Command'},
|
||||||
{'uri': 'upload', 'name': '업로드'},
|
{'uri': 'upload', 'name': '업로드'},
|
||||||
{'uri': 'python', 'name': 'Python'},
|
{'uri': 'python', 'name': 'Python'},
|
||||||
{'uri': 'db', 'name': 'DB'},
|
#{'uri': 'db', 'name': 'DB'},
|
||||||
{'uri': 'crypt', 'name': '암호화'},
|
#{'uri': 'crypt', 'name': '암호화'},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,76 +1,91 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div>
|
|
||||||
{{ macros.m_button_group([['globalSettingSaveBtn', '설정 저장']])}}
|
|
||||||
{{ macros.m_row_start('5') }}
|
|
||||||
{{ macros.m_row_end() }}
|
|
||||||
<nav>
|
|
||||||
{{ macros.m_tab_head_start() }}
|
|
||||||
{{ macros.m_tab_head2('normal', '일반', true) }}
|
|
||||||
|
|
||||||
{{ macros.m_tab_head_end() }}
|
|
||||||
</nav>
|
|
||||||
<form id='setting' name='setting'>
|
|
||||||
<div class="tab-content" id="nav-tabContent">
|
|
||||||
{{ macros.m_tab_content_start('normal', true) }}
|
|
||||||
{{ macros.setting_checkbox('tool_crypt_use_user_key', '암호화 키 직접 입력', value=arg['tool_crypt_use_user_key'], desc=['On : 본인 키 사용', '주의) 변경 후 일반설정-인증-로그인 암호를 새로 저장해야 합니다.', 'Off : 앱 고정 키 사용']) }}
|
|
||||||
<div id="tool_crypt_use_user_key_div" class="collapse">
|
|
||||||
{{ macros.setting_input_text('tool_crypt_user_key', '암호화 키', value=arg['tool_crypt_user_key'], desc=['16진수(숫자, a~e)로 이루어진 32글자. 미만시 앞을 0으로 채움. 초과시 뒤에 무시']) }}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{ macros.setting_input_text_and_buttons('tool_crypt_encrypt_word', '암호화', [['tool_crypt_encrypt_word_btn', '암호화']], value=arg['tool_crypt_encrypt_word']) }}
|
{{ macros.m_button_group([['all_upgrade_btn', '모두 업그레이드'], ['refresh_btn', '새로고침']])}}
|
||||||
{{ macros.setting_input_text('tool_crypt_encrypt_word_result', '', disabled=True) }}
|
{{ macros.m_row_start('5') }}
|
||||||
|
{{ macros.m_row_end() }}
|
||||||
|
|
||||||
{{ macros.setting_input_text_and_buttons('tool_crypt_decrypt_word', '평문화', [['tool_crypt_decrypt_word_btn', '평문화']], value=arg['tool_crypt_decrypt_word']) }}
|
{{ macros.setting_input_text_and_buttons('pip', 'pip 패키지 설치', [['install_btn', '설치 & 업그레이드']], value=arg['tool_python_name'], desc=None) }}
|
||||||
{{ macros.setting_input_text('tool_crypt_decrypt_word_result', '', disabled=True) }}
|
|
||||||
{{ macros.m_tab_content_end() }}
|
|
||||||
|
<div id="list_div"></div>
|
||||||
</div><!--tab-content-->
|
|
||||||
</form>
|
|
||||||
</div> <!--전체-->
|
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
var package_name = "{{arg['package_name'] }}";
|
|
||||||
var sub = "{{arg['sub'] }}";
|
|
||||||
|
|
||||||
$(document).ready(function(){
|
$(document).ready(function(){
|
||||||
use_collapse("tool_crypt_use_user_key");
|
refresh();
|
||||||
});
|
});
|
||||||
|
|
||||||
$("body").on('change', '#tool_crypt_use_user_key', function(e){
|
function refresh() {
|
||||||
use_collapse('tool_crypt_use_user_key');
|
globalSendCommandPage('get_freeze', null, null, null, null, function(ret){
|
||||||
});
|
make_list(ret.data);
|
||||||
|
|
||||||
$("body").on('click', '#tool_crypt_encrypt_word_btn', function(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
word = document.getElementById("tool_crypt_encrypt_word").value
|
|
||||||
crypt_test('encrypt', word);
|
|
||||||
});
|
|
||||||
|
|
||||||
$("body").on('click', '#tool_crypt_decrypt_word_btn', function(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
word = document.getElementById("tool_crypt_decrypt_word").value
|
|
||||||
crypt_test('decrypt', word);
|
|
||||||
});
|
|
||||||
|
|
||||||
function crypt_test(mode, word) {
|
|
||||||
$.ajax({
|
|
||||||
url: '/' + package_name + '/ajax/'+sub+'/crypt_test',
|
|
||||||
type: "POST",
|
|
||||||
cache: false,
|
|
||||||
data: {mode:mode, word:word},
|
|
||||||
dataType: "json",
|
|
||||||
success: function (ret) {
|
|
||||||
if (ret.ret == 'success') {
|
|
||||||
if (mode == "encrypt")
|
|
||||||
document.getElementById("tool_crypt_encrypt_word_result").value = ret.data;
|
|
||||||
else
|
|
||||||
document.getElementById("tool_crypt_decrypt_word_result").value = ret.data;
|
|
||||||
} else {
|
|
||||||
notify(ret.log, 'warning');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$("body").on('click', '#install_btn', function(e){
|
||||||
|
e.preventDefault();
|
||||||
|
name = $('#pip').val();
|
||||||
|
if (name == '') {
|
||||||
|
notify("package 명을 입력하세요.", 'danger');
|
||||||
|
return
|
||||||
|
}
|
||||||
|
upgrade(name);
|
||||||
|
});
|
||||||
|
|
||||||
|
$("body").on('click', '#upgrade_btn', function(e){
|
||||||
|
e.preventDefault();
|
||||||
|
upgrade($(this).data('name'));
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
function upgrade(name) {
|
||||||
|
globalSendCommandPage('upgrade', name);
|
||||||
|
}
|
||||||
|
|
||||||
|
$("body").on('click', '#remove_btn', function(e){
|
||||||
|
e.preventDefault();
|
||||||
|
remove_confirm($(this).data('name'));
|
||||||
|
});
|
||||||
|
|
||||||
|
function remove(name) {
|
||||||
|
globalSendCommandPage('remove', name);
|
||||||
|
}
|
||||||
|
|
||||||
|
function remove_confirm(name) {
|
||||||
|
$("#confirm_title").html("삭제 확인");
|
||||||
|
$("#confirm_body").html(name + "패키지를<br>삭제 하시겠습니까?");
|
||||||
|
$('#confirm_button').attr('onclick', "remove('"+name+"');");
|
||||||
|
$("#confirm_modal").modal();
|
||||||
|
}
|
||||||
|
|
||||||
|
$("body").on('click', '#refresh_btn', function(e){
|
||||||
|
e.preventDefault();
|
||||||
|
refresh();
|
||||||
|
});
|
||||||
|
|
||||||
|
function make_list(data) {
|
||||||
|
current_data = data;
|
||||||
|
str = '';
|
||||||
|
str = '<table id="result_table" class="table table-sm" ><thead class="thead-dark"><tr> \
|
||||||
|
<th style="width:10%; text-align:center;">ID</th> \
|
||||||
|
<th style="width:30%; text-align:center;">Name</th> \
|
||||||
|
<th style="width:30%; text-align:center;">Version</th> \
|
||||||
|
<th style="width:30%; text-align:center;">Action</th> \
|
||||||
|
</tr></thead><tbody id="list">';
|
||||||
|
if (data.length == 0) str += '<tr><td colspan="6"><h4>Empty</h4></td></tr>';
|
||||||
|
for(i in data) {
|
||||||
|
//console.log(data[i]);
|
||||||
|
str += '<tr class="chover" style="cursor: pointer;">';
|
||||||
|
str += '<td scope="col" style="width:10%; text-align:center;">'+ (parseInt(i)+1) + '</td>';
|
||||||
|
str += '<td scope="col" style="width:30%; text-align:center;">'+ data[i][0] + '</td>';
|
||||||
|
str += '<td scope="col" style="width:30%; text-align:center;">'+ data[i][1] + '</td>';
|
||||||
|
tmp = j_button('upgrade_btn', 'Upgrade', {'name':data[i][0]}, 'primary', true, false);
|
||||||
|
tmp += j_button('remove_btn', '삭제', {'name':data[i][0]}, 'danger', true, false);
|
||||||
|
tmp = j_button_group(tmp);
|
||||||
|
str += '<td scope="col" style="width:30%; text-align:center;">'+ tmp + '</td>';
|
||||||
|
str += '</tr>'
|
||||||
|
}
|
||||||
|
str += '</table>';
|
||||||
|
document.getElementById("list_div").innerHTML = str;
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
Reference in New Issue
Block a user