@@ -4,6 +4,263 @@ All notable changes to this project are documented in this file.
44
55---
66
7+ ## [ v2.3.1] — 2026-05-09 (Codebase Cleanup, Bug Fixes, Deprecation Fix & Directory Normalization)
8+
9+ ### Summary
10+ Dead code removal, missing dependency fix, algorithm bug fix, security hardening, 5 pre-existing frontend build-breaking bugs fixed, ` datetime.utcnow() ` deprecation migrated across 29 files, frontend directory names normalized (17 directories renamed from spaces to camelCase), ` watermark_resource.py ` split into 4 focused modules, SQLAlchemy 2.0 ` Query.get() ` migration across 11 files, missing ` @admin_required ` on dashboard endpoint fixed, root temp files cleaned up, 22 more unused imports removed, dead ` NC.py ` deleted, 8 dead frontend files removed, duplicate APIs consolidated, bare ` except: ` fixed, QR_SECRET_KEY security hardened.
11+
12+ ** Files changed:** 70+ files, ~ 2700 lines removed
13+
14+ ---
15+
16+ ### Backend — Fixes
17+
18+ #### 1. Missing ` geoalchemy2 ` Dependency (` requirements.txt ` )
19+ - ` model/Shp_File.py ` imports ` geoalchemy2 ` but it was not in ` requirements.txt `
20+ - Added ` geoalchemy2 ` to prevent ImportError on clean install
21+
22+ #### 2. Incomplete Model Bootstrap (` app.py ` )
23+ - ` _bootstrap_runtime_schema() ` only included 20 of 27 models — 7 tables would not auto-create on first deploy
24+ - Added: ` Permission ` , ` AdmAccountPermissions ` , ` EmbedFileRecord ` , ` ExtractHelper ` , ` SendFileRecord `
25+ - Added graceful import for ` ShpFile ` and ` MysqlShpFile ` (require geoalchemy2/mysql-specific types)
26+
27+ #### 3. Algorithm Bug Fix (` algorithm/get_coor.py ` )
28+ - ** Empty feature crash:** When all points in a feature were deleted, ` get_coor_array() ` would throw an unhandled error. Now safely skips empty arrays.
29+ - ** Multi-geometry detection:** The ` isinstance(coor_nested[:, i][0][0], np.ndarray) ` check failed for nested arrays, causing MultiPolygon/MultiLineString to be processed in the wrong branch. Rewritten to use ` shp_type ` for branching instead of runtime type guessing.
30+ - ** ` __main__ ` block:** Replaced undefined ` select_file() ` / ` gpd ` with ` argparse ` -style CLI.
31+
32+ #### 4. Security — ` allow_unsafe_werkzeug ` (` app.py ` )
33+ - Was always ` True ` regardless of environment. Now only enabled when ` DEBUG=True ` .
34+
35+ #### 5. Hardcoded Credentials (` .env.example ` , ` add_user_script.py ` )
36+ - ` .env.example ` had ` root:root ` database passwords — replaced with placeholders
37+ - ` add_user_script.py ` hardcoded ` root:root ` — now reads from ` .env ` via ` dotenv `
38+
39+ ---
40+
41+ ### Backend — Dead Code Removal
42+
43+ | Deleted File | Reason |
44+ | ---| ---|
45+ | ` common/constants.py ` | ` LOGIN_SECRET = "MY_KEY" ` never imported anywhere |
46+ | ` common/api_tools.py ` | Empty file (8 bytes, whitespace only) |
47+ | ` common/__init__.py ` | Package had no remaining modules |
48+ | ` Adm_Info.py ` (project root) | Duplicate of ` model/Adm_Info.py ` , leftover from early development |
49+
50+ #### Filename Typo Fix
51+ - ` server/appliaction_server.py ` → ` server/application_server.py `
52+
53+ ---
54+
55+ ### Frontend — Build-Breaking Bug Fixes (5 files)
56+
57+ These were pre-existing bugs where imported API functions were redeclared as local ` const ` , causing either build failures or infinite recursion at runtime.
58+
59+ | File | Conflict | Fix |
60+ | ---| ---| ---|
61+ | ` employee_profile.vue ` | ` changePassword ` (import vs local) | Renamed local to ` openChangePasswordDialog ` |
62+ | ` not_approved.vue ` | ` batchReview ` (import vs local) | Aliased import as ` batchReviewApi ` |
63+ | ` raster_watermark_embedding.vue ` | ` crmarkEmbed/Recover/Decode ` (import vs local) | Aliased imports as ` *Api ` |
64+ | ` employee_chat.vue ` | ` searchUsers ` (import vs local) | Aliased import as ` searchUsersApi ` |
65+ | ` AdminNotifications.vue ` | ` sendNotification ` (import vs local) | Aliased import as ` sendNotificationApi ` |
66+
67+ #### Import Source Fix
68+ - ` watermark_embedding.vue ` : ` QuestionFilled ` was imported from ` element-plus ` (not exported) — moved to ` @element-plus/icons-vue `
69+
70+ ---
71+
72+ ### Frontend — Dead Code Removal
73+
74+ | Deleted File | Lines | Reason |
75+ | ---| ---| ---|
76+ | ` api/data_viewing_api.js ` | 23 | Marked ` @deprecated ` , replaced by ` api/data.js ` , zero imports |
77+ | ` views/employee/Data Viewing/data_viewing.vue ` | 1520 | Superseded by ` data_viewing_new.vue ` (used in router) |
78+ | ` views/employee/Data Viewing/data_viewing_style.css ` | 771 | Companion CSS for dead view |
79+ | ` styles/design-tokens.css ` | 56 | Overlapping CSS variables with ` design-system.css ` , zero unique variables used |
80+ | ` stores/admin/nav.js ` | 0 | Empty placeholder |
81+ | ` stores/employee/nav.js ` | 0 | Empty placeholder |
82+ | ` types/data.ts ` | 0 | Empty placeholder (abandoned TS migration) |
83+
84+ #### Config Cleanup
85+ - ` vite.config.js ` : Removed 40-line commented-out proxy block (referenced stale port 5001)
86+ - ` main.js ` : Removed unused ` design-tokens.css ` import
87+
88+ ---
89+
90+ ### Backend — ` datetime.utcnow() ` Deprecation Fix (29 files)
91+
92+ #### What
93+ Replaced all ` datetime.utcnow() ` calls with ` datetime.now(timezone.utc) ` for Python 3.12+ compatibility.
94+
95+ #### How
96+ - Model defaults: ` default=datetime.utcnow ` → ` default=lambda: datetime.now(timezone.utc) `
97+ - Direct calls: ` datetime.utcnow() ` → ` datetime.now(timezone.utc) `
98+ - Added ` timezone ` to all ` from datetime import datetime ` statements
99+ - Fixed duplicate import in ` download_file_resource.py ` (two ` from datetime import ` lines consolidated)
100+
101+ #### Files Changed
102+ - 18 model files (all ` default= ` and ` onupdate= ` parameters)
103+ - 9 resource files (direct calls in business logic)
104+ - 1 utility file (` websocket.py ` — timestamp generation)
105+ - 1 server file (` raster_watermark_server.py ` )
106+
107+ ---
108+
109+ ### Frontend — Directory Name Normalization (17 directories)
110+
111+ #### What
112+ Renamed all view directories containing spaces to camelCase for toolchain compatibility and consistency.
113+
114+ #### Before → After
115+
116+ | Before | After |
117+ | ---| ---|
118+ | ` admin/Adm Dashboard ` | ` admin/AdmDashboard ` |
119+ | ` admin/Approve Application ` | ` admin/ApproveApplication ` |
120+ | ` admin/Employee management ` | ` admin/EmployeeManagement ` |
121+ | ` admin/Log Management ` | ` admin/LogManagement ` |
122+ | ` admin/System Management ` | ` admin/SystemManagement ` |
123+ | ` admin/Watermark Embedding ` | ` admin/WatermarkEmbedding ` |
124+ | ` admin/Watermark Extraction ` | ` admin/WatermarkExtraction ` |
125+ | ` admin/Watermark Generation ` | Deleted (empty directory) |
126+ | ` employee/Data Application ` | ` employee/DataApplication ` |
127+ | ` employee/Data Download ` | ` employee/DataDownload ` |
128+ | ` employee/Data Viewing ` | ` employee/DataViewing ` |
129+ | ` employee/Employee About ` | ` employee/EmployeeAbout ` |
130+ | ` employee/Employee Dashboard ` | ` employee/EmployeeDashboard ` |
131+ | ` employee/Employee Help ` | ` employee/EmployeeHelp ` |
132+ | ` employee/Employee Profile ` | ` employee/EmployeeProfile ` |
133+ | ` employee/My Notifications ` | ` employee/MyNotifications ` |
134+ | ` employee/Operation History ` | ` employee/OperationHistory ` |
135+
136+ - Updated all 22 import paths in ` router/index.js `
137+
138+ ---
139+
140+ ### Backend — watermark_resource.py Split (1234 → 4 files)
141+
142+ #### What
143+ Monolithic ` watermark_resource.py ` (1234 lines, 13 classes) split into focused modules.
144+
145+ | New File | Classes | Lines |
146+ | ---| ---| ---|
147+ | ` watermark_utils.py ` | Shared utilities (QR_SECRET_KEY, safe_extract_zip, build_qr_text, etc.) | ~ 100 |
148+ | ` watermark_generate_resource.py ` | Adm1GetGenerateWatermarkApplications, GenerateWatermarkResource | ~ 110 |
149+ | ` watermark_embed_resource.py ` | Adm2GetEmbeddingWatermarkApplications, EmbeddingWatermarkResource | ~ 178 |
150+ | ` watermark_extract_resource.py ` | VectorExtractResource | ~ 209 |
151+ | ` watermark_upload_resource.py ` | Upload, Records, Preview, Batch classes | ~ 606 |
152+
153+ - Updated ` app.py ` imports to reference new modules
154+ - Deleted old ` watermark_resource.py `
155+
156+ ---
157+
158+ ### Backend — SQLAlchemy 2.0 Deprecation Fix (11 files)
159+
160+ #### What
161+ Replaced all ` Model.query.get(id) ` calls with ` db.session.get(Model, id) ` for SQLAlchemy 2.0 compatibility.
162+
163+ - 46 occurrences across 11 resource files
164+ - Eliminates ` LegacyAPIWarning ` in test output
165+
166+ ---
167+
168+ ### Backend — Missing ` @admin_required ` on AdminDashboard
169+
170+ #### What
171+ ` AdminDashboardResource ` was missing the ` @admin_required ` decorator — employees could access admin dashboard data.
172+
173+ - Added ` @admin_required ` decorator between ` @jwt_required() ` and ` @relaxed_limit `
174+
175+ ---
176+
177+ ### Backend — Unused Import Cleanup (88 imports removed, 29 Python files)
178+
179+ #### What
180+ Automated scan and removal of 88 unused Python imports across 29 backend files.
181+
182+ #### Side Effect Fix
183+ The cleanup script broke 7 files by removing import lines but leaving references intact. All 7 manually fixed:
184+ - ` algorithm/extract.py ` — restored trailing comma in import
185+ - ` algorithm/to_geodataframe.py ` — restored ` from shapely.geometry import (...) `
186+ - ` resource/download_file_resource.py ` — restored ` from utils.user_limiter import normal_limit, relaxed_limit `
187+ - ` utils/metrics.py ` — restored ` from prometheus_client import (...) `
188+ - ` tests/conftest.py ` — restored ` from model import (...) `
189+ - ` resource/watermark_generate_resource.py ` — rewrote header with correct imports
190+ - ` resource/watermark_embed_resource.py ` — rewrote header with correct imports
191+
192+ #### Additional Fixes (post-cleanup)
193+ - ` resource/watermark_extract_resource.py ` — rewrote broken header, fixed ` safe_extract_zip ` / ` decode_qr_from_image ` / ` parse_qr_text ` function calls (were underscore-prefixed)
194+ - ` resource/watermark_upload_resource.py ` — rewrote broken header, fixed ` build_qr_text ` / ` get_qr_version ` function calls
195+ - ` resource/watermark_generate_resource.py ` — fixed ` build_qr_text ` / ` get_qr_version ` function calls
196+ - ` resource/watermark_extract_resource.py ` — ` datetime.now() ` → ` datetime.now(timezone.utc) `
197+
198+ ---
199+
200+ ### Backend — Dead Server File Removal (7 files)
201+
202+ | Deleted File | Reason |
203+ | ---| ---|
204+ | ` server/adm_server.py ` | Zero imports, superseded by ` app.py ` factory |
205+ | ` server/application_server.py ` | Zero imports |
206+ | ` server/emp_server.py ` | Zero imports |
207+ | ` server/nav_server.py ` | Zero imports |
208+ | ` server/raster_data_server.py ` | Zero imports |
209+ | ` server/raster_watermark_server.py ` | Zero imports |
210+ | ` server/shp_data_server.py ` | Zero imports |
211+
212+ ---
213+
214+ ### Backend — Second-Pass Cleanup (22 unused imports, dead code, security)
215+
216+ #### Unused Imports Removed (22 instances, 8 files)
217+ | File | Removed |
218+ | ---| ---|
219+ | ` resource/watermark_embed_resource.py ` | ` datetime ` , ` timezone ` , ` build_qr_text ` , ` get_qr_version ` , ` decode_reversible ` , ` extract_dwt ` , ` recover_dwt ` , ` extract_histogram ` , ` recover_histogram ` , ` compute_nc ` , ` compute_ssim_simple ` , ` compute_ber ` , ` record_watermark ` |
220+ | ` resource/admin_application_resource.py ` | ` timedelta ` |
221+ | ` resource/adm_resource.py ` | ` get_jwt_identity ` |
222+ | ` resource/watermark_extract_resource.py ` | ` Shp ` |
223+ | ` resource/watermark_upload_resource.py ` | ` normal_limit ` |
224+ | ` algorithm/extract.py ` | ` NC ` (from ` algorithm.NC ` ) |
225+ | ` algorithm/raster_reversible_watermark.py ` | ` is_geotiff ` |
226+ | ` tests/test_robustness.py ` | ` ImageFilter ` |
227+
228+ #### Dead Code Deleted
229+ | File | Reason |
230+ | ---| ---|
231+ | ` algorithm/NC.py ` | Duplicate of ` quality_metrics.py ` , zero runtime callers |
232+ | ` src/views/admin/EChartBar/echarts.vue ` | Not in router, zero imports |
233+ | ` src/views/admin/EmployeeManagement/account_list.vue ` | Not in router, zero imports |
234+ | ` src/views/admin/EmployeeManagement/account_add.vue ` | Not in router, zero imports |
235+ | ` src/components/DataCard.vue ` | Zero imports |
236+ | ` src/components/DataView.vue ` | Zero imports |
237+ | ` src/components/common/LoadingSkeleton.vue ` | Zero imports |
238+ | ` src/components/common/EmptyState.vue ` | Zero imports |
239+ | ` src/api/NaviApi.js ` | Zero imports |
240+
241+ #### Security Fixes
242+ - ` resource/application_resource.py:560 ` — Bare ` except: ` → ` except Exception: ` (was catching ` KeyboardInterrupt ` , ` SystemExit ` )
243+ - ` resource/wmark_utils.py ` — ` QR_SECRET_KEY ` fallback now only uses dev key when ` FLASK_DEBUG=1 ` ; logs ` ERROR ` in production instead of silently using insecure key
244+
245+ #### Frontend Cleanup
246+ - ` src/api/watermark.js ` — Removed duplicate ` getShpApplications ` / ` getRasterApplications ` (already defined in ` admin.js ` )
247+ - ` src/views/admin/AdmDashboard/adm_dashboard.vue ` — Removed unused ` onUnmounted ` import
248+
249+ ---
250+
251+ ### Misc Cleanup
252+ - Added ` QR_SECRET_KEY ` placeholder to ` .env.example `
253+ - Deleted root-level temp files: ` temp_qrcode.png ` , ` filelist.txt ` (both in ` .gitignore ` )
254+
255+ ---
256+
257+ ### Verification
258+ - ** Backend:** ` create_app() ` succeeds, 106 routes registered, zero import errors
259+ - ** Tests:** 126 passed, 1 failed (pre-existing numpy 2.0 compat), 2 skipped
260+ - ** Frontend:** ` vite build ` succeeds (36 modules, 62s)
261+
262+ ---
263+
7264## [ v2.3.0] — 2026-05-09 (Security Hardening, Multi-Algorithm Watermark & Monitoring)
8265
9266### Summary
0 commit comments