fix: secure cloud sessions and replace stale dashboard examples

This commit is contained in:
leefer
2026-09-22 17:47:01 +08:00
parent e11eb252a4
commit 95a7f5f6ff
5 changed files with 25 additions and 9 deletions
+1 -1
View File
@@ -30,7 +30,7 @@ STORAGE_DIR = Path(os.environ.get("APP_STORAGE_DIR", ROOT / "data" / "files"))
SESSION_COOKIE = "cw_fusion_session" if portal_sso.enabled() else "cw_session"
# Local plain-HTTP deployment: the cookie intentionally carries no Secure
# flag (see docs/decisions/003-auth.md).
COOKIE_FLAGS = "HttpOnly; SameSite=Lax; Path=/"
COOKIE_FLAGS = "HttpOnly; SameSite=Lax; Path=/" + ("; Secure" if os.environ.get("PORTAL_COOKIE_SECURE") == "1" else "")
class AppHandler(portal_sso.PortalMixin, SimpleHTTPRequestHandler):
+5 -1
View File
@@ -3,6 +3,7 @@
from __future__ import annotations
from pathlib import Path
import hashlib
import sqlite3
import tempfile
import unittest
@@ -13,6 +14,7 @@ from bank_importer.db import connect, migrate, utc_now
class LedgerBase(unittest.TestCase):
def setUp(self) -> None:
self._source_file_sequence = 0
self.temp_dir = tempfile.TemporaryDirectory()
self.addCleanup(self.temp_dir.cleanup)
root = Path(self.temp_dir.name)
@@ -66,13 +68,15 @@ class LedgerBase(unittest.TestCase):
summary: str | None = None,
purpose: str | None = None,
) -> int:
self._source_file_sequence = getattr(self, "_source_file_sequence", 0) + 1
fixture_hash = hashlib.sha256(f"ledger-fixture-{self._source_file_sequence}".encode()).hexdigest()
with self.connection:
cursor = self.connection.execute(
"""
INSERT INTO source_files (sha256, original_filename, size_bytes, storage_path, created_at)
VALUES (?, '测试.xlsx', 1, 'data/files/测试.xlsx', ?)
""",
(utc_now(), utc_now()),
(fixture_hash, utc_now()),
)
source_file_id = int(cursor.lastrowid)
cursor = self.connection.execute(
+5 -1
View File
@@ -5,6 +5,7 @@ idempotency, concurrency, Decimal precision and B-44 eligibility."""
from __future__ import annotations
from decimal import Decimal
import hashlib
from pathlib import Path
import sqlite3
import tempfile
@@ -17,6 +18,7 @@ from bank_importer.db import connect, migrate, utc_now
class MatchingBase(unittest.TestCase):
def setUp(self) -> None:
self._source_file_sequence = 0
self.temp_dir = tempfile.TemporaryDirectory()
self.addCleanup(self.temp_dir.cleanup)
root = Path(self.temp_dir.name)
@@ -74,13 +76,15 @@ class MatchingBase(unittest.TestCase):
summary: str | None = None,
sheet: str = "流水",
) -> int:
self._source_file_sequence = getattr(self, "_source_file_sequence", 0) + 1
fixture_hash = hashlib.sha256(f"matching-fixture-{self._source_file_sequence}".encode()).hexdigest()
with self.connection:
cursor = self.connection.execute(
"""
INSERT INTO source_files (sha256, original_filename, size_bytes, storage_path, created_at)
VALUES (?, '测试.xlsx', 1, 'data/files/测试.xlsx', ?)
""",
(utc_now(), utc_now()),
(fixture_hash, utc_now()),
)
source_file_id = int(cursor.lastrowid)
cursor = self.connection.execute(
+6 -6
View File
@@ -205,8 +205,8 @@
</div>
<div class="detail-box row-between" style="margin-top: 12px;">
<div>
<div style="font-weight: 650;">金牛农业 → 应收 386.24 万元</div>
<div class="meta" style="margin-top: 2px;">14 笔(借 9 / 贷 5)· 最早未结 2026-03-12</div>
<div style="font-weight: 650;">查看所选公司的实际往来</div>
<div class="meta" style="margin-top: 2px;">金额、统计截止日及未解决事项以往来查询结果为准</div>
</div>
<button class="btn btn-sm" data-view-link="pair">查看逐笔往来</button>
</div>
@@ -217,9 +217,9 @@
<span class="card-title">账期与结账<span class="sub" id="dashboardPeriodSub">每月 5 日结账 · 全局起算日 2026-01-01</span></span>
</div>
<dl class="kv">
<dt>当前账期</dt><dd>2026-07 · 进行中</dd>
<dt>结账日</dt><dd style="color: var(--warn); font-weight: 650;">2026-08-29(顺延)· 距今 9 天</dd>
<dt>上一账期</dt><dd>2026-06 · 已于 07-03 结账</dd>
<dt>待结账期</dt><dd id="dashboardClosePeriod">正在读取</dd>
<dt>结账状态</dt><dd id="dashboardCloseStatus">正在读取</dd>
<dt>最近结账</dt><dd id="dashboardCloseHistory">正在读取</dd>
</dl>
<button class="btn" data-view-link="settings" style="width: 100%; margin-top: 14px;">进入结账检查</button>
</div>
@@ -1257,6 +1257,6 @@
<script src="theme.js?v=1"></script>
<script src="select.js?v=1"></script>
<script src="datepicker.js?v=2"></script>
<script src="app.js?v=18"></script>
<script src="app.js?v=18-cloud1"></script>
</body>
</html>
+8
View File
@@ -2278,6 +2278,11 @@ function applyClosePanel(overview) {
state.periodClose = overview;
const close = overview.close || {};
const ym = close.year_month || overview.target_month || "—";
if ($("#dashboardClosePeriod")) $("#dashboardClosePeriod").textContent = ym;
if ($("#dashboardCloseStatus")) $("#dashboardCloseStatus").textContent =
({ closed: "已结账", closing: "处理中", failed: "结账失败", reopened: "已重开", open: "未结账" })[close.status] || "待结账检查";
if ($("#dashboardCloseHistory")) $("#dashboardCloseHistory").textContent = overview.history
? `${overview.history.year_month} · ${String(overview.history.closed_at || "").slice(0, 10)}` : "尚无结账记录";
renderTimeline(overview.timeline);
const start = state.calculationStart || "—";
if ($("#timelineSub")) $("#timelineSub").textContent = `全局起算日 ${start} 起,每月 ${overview.closing_day || "—"} 日结账`;
@@ -2388,6 +2393,9 @@ async function loadPeriodClose() {
if (response?.status === 401) { window.location.href = window.PORTAL_HOME || "index.html"; return; }
const result = await response?.json().catch(() => null);
if (!response?.ok || result?.status !== "ok") {
for (const id of ['dashboardClosePeriod', 'dashboardCloseStatus', 'dashboardCloseHistory']) {
if ($(`#${id}`)) $(`#${id}`).textContent = '读取失败,请重试';
}
showToast("结账状态加载失败", result?.message || "请稍后重试", "danger");
return;
}