v1.1.21: 6 fixes — _finish_op args, connection leak, pool init, XSS, secure cookie, let

This commit is contained in:
2026-07-29 12:01:00 +04:00
parent 8bc87193d4
commit 515fadbcde
5 changed files with 23 additions and 15 deletions
+1 -1
View File
@@ -18,7 +18,7 @@ from routes.api import bp as api_bp
from routes.api_test import bp as api_test_bp
# Версия — меняется при КАЖДОМ изменении кода. Показывается в топбаре UI.
VERSION = "1.1.20"
VERSION = "1.1.21"
app = Flask(__name__, template_folder="templates", static_folder="static")
app.config["NUBES_API_ENDPOINT"] = os.getenv("NUBES_API_ENDPOINT", "https://lk-api-gateway-test.ngcloud.ru/api/v1/svc")
+1 -1
View File
@@ -36,10 +36,10 @@ def _ensure_schema():
global _initialized
if _initialized:
return
_initialized = True
try:
from db.init_db import init_db
init_db()
_initialized = True
except Exception:
pass
+9 -1
View File
@@ -231,7 +231,7 @@ def api_test():
# фоном ждать завершения
user_email = get_token_info().get("email", "")
app_version = current_app.config.get("VERSION", "")
threading.Thread(target=_finish_op, args=(client, op_uid, instance_uid, svc_id, display_name, op_name, svc_op_id, True, get_client_id(), get_stand(), params, user_email, app_version), daemon=True).start()
threading.Thread(target=_finish_op, args=(client, op_uid, instance_uid, svc_id, display_name, op_name, svc_op_id, True, get_client_id(), get_stand(), False, params, user_email, app_version), daemon=True).start()
return jsonify({"status": "RUNNING", "opUid": op_uid, "instanceUid": instance_uid, "displayName": display_name})
else:
@@ -436,6 +436,14 @@ def api_history():
put_conn(conn)
return jsonify(result)
except Exception as e:
try:
cur.close()
except Exception:
pass
try:
put_conn(conn)
except Exception:
pass
return jsonify({"error": str(e)}), 500
+1 -1
View File
@@ -91,7 +91,7 @@ def index():
user_token = request.form.get("token", "")
active_token = user_token or env_token
resp = make_response()
resp.set_cookie("token", user_token, max_age=60*60*24*365, httponly=True, samesite="Strict") # 1 год
resp.set_cookie("token", user_token, max_age=60*60*24*365, httponly=True, samesite="Strict", secure=True) # 1 год
resp.headers["Location"] = "/" # редирект на GET (убирает POST из истории)
resp.status_code = 302
return resp
+11 -11
View File
@@ -47,7 +47,7 @@ async function selectService(svcId){
const d=await r.json();
svcInstances=d.instances||[];
currentSvcName=d.svc||'';
currentSvcShort=d.svcShort||'';
let currentSvcShort=d.svcShort||'';
// Обновить текст кнопки создания
const btnSpan=document.querySelector('#create-btn-area span');
if(btnSpan) btnSpan.textContent='+ Создать новый инстанс '+(currentSvcName||'сервиса');
@@ -57,9 +57,9 @@ async function selectService(svcId){
const status=i.status||i.explainedStatus||'?';
const sc=status==='running'?'badge-success':'';
html+=`<div class="inst-item" onclick="toggleInstance('${i.instanceUid}')" data-iuid="${i.instanceUid}">
<span style="display:inline-block;width:220px;">${i.displayName}</span>
<span style="display:inline-block;width:160px;color:var(--muted);font-size:11px;">${i.svc||''}</span>
<span class="badge ${sc}" style="font-size:9px;">${status}</span>
<span style="display:inline-block;width:220px;">${_esc(i.displayName)}</span>
<span style="display:inline-block;width:160px;color:var(--muted);font-size:11px;">${_esc(i.svc||'')}</span>
<span class="badge ${sc}" style="font-size:9px;">${_esc(status)}</span>
</div>`;
html+=`<div class="inst-ops" id="ops-${i.instanceUid}"></div>`;
});
@@ -353,7 +353,7 @@ function showStages(stages){
stages.forEach(s=>{
const done=!!s.dtFinish;
const icon=done?(s.isSuccessful?'✅':'❌'):'⏳';
html+=`<div style="font-size:11px;padding:2px 0;">${icon} ${s.stage}${(s.duration||0).toFixed(1)}s</div>`;
html+=`<div style="font-size:11px;padding:2px 0;">${icon} ${_esc(s.stage)}${(s.duration||0).toFixed(1)}s</div>`;
});
const boxes=document.querySelectorAll('.stages-box');
if(boxes.length) boxes[boxes.length-1].innerHTML=html;
@@ -373,9 +373,9 @@ async function refreshInstances(){
const status=i.status||i.explainedStatus||'?';
const sc=status==='running'?'badge-success':'';
html+=`<div class="inst-item" onclick="toggleInstance('${i.instanceUid}')" data-iuid="${i.instanceUid}">
<span style="display:inline-block;width:220px;">${i.displayName}</span>
<span style="display:inline-block;width:160px;color:var(--muted);font-size:11px;">${i.svc||''}</span>
<span class="badge ${sc}" style="font-size:9px;">${status}</span>
<span style="display:inline-block;width:220px;">${_esc(i.displayName)}</span>
<span style="display:inline-block;width:160px;color:var(--muted);font-size:11px;">${_esc(i.svc||'')}</span>
<span class="badge ${sc}" style="font-size:9px;">${_esc(status)}</span>
</div>`;
html+=`<div class="inst-ops" id="ops-${i.instanceUid}"></div>`;
});
@@ -404,9 +404,9 @@ async function loadHistory(){
const cls=r.status==='OK'?'badge-success':'';
html+=`<tr>
<td style="padding:2px 6px;">${time}</td>
<td style="padding:2px 6px;">${r.op_name||'?'}</td>
<td style="padding:2px 6px;">${r.display_name||r.instance_uid||'?'}</td>
<td style="padding:2px 6px;"><span class="badge ${cls}" style="font-size:9px;">${r.status||'?'}</span></td>
<td style="padding:2px 6px;">${_esc(r.op_name||'?')}</td>
<td style="padding:2px 6px;">${_esc(r.display_name||r.instance_uid||'?')}</td>
<td style="padding:2px 6px;"><span class="badge ${cls}" style="font-size:9px;">${_esc(r.status||'?')}</span></td>
<td style="padding:2px 6px;">${r.duration_sec!=null?r.duration_sec.toFixed(1)+'s':'-'}</td>
</tr>`;
});