45 Commits

Author SHA1 Message Date
root
e9c2059126 chore: push full state including PG data, vendor, logs, and compiled views 2026-06-03 11:37:08 +08:00
root
9cd5565d1a fix(test): resolve F-12 — add comprehensive test suite with 61 tests covering auth, API, admin, data pages, PDF exports, and service layer
7 test files:
- AuthenticationTest: login/logout/blocked users (7 tests)
- ApiAuthTest: Sanctum token auth, rate limiting, validation (9 tests)
- AdminTest: station CRUD, user CRUD, CSV export, logs (7 tests)
- WebRouteTest: route access control, locale switch, health check (20 tests)
- DataPageTest: all data views load correctly (9 tests)
- PdfExportTest: PDF generation with date range caps (5 tests)
- StationDataServiceTest: shared query service unit tests (3 tests)

Uses separate sides_test database to isolate from production.
Removed Breeze scaffold tests that used RefreshDatabase (wiped DB).

Before running tests, clone the production DB:
  docker compose exec -T postgres bash -c     'dropdb --if-exists -U sides_user sides_test &&      createdb -U sides_user -O sides_user sides_test &&      pg_dump -U sides_user sides | psql -U sides_user -d sides_test'
  docker compose exec -T app php artisan config:clear
  docker compose exec -T app php artisan test
2026-06-03 10:30:31 +08:00
root
398e17f291 fix(perf): resolve F-11 — cap PDF exports to 90-day date range to prevent memory exhaustion
All three PDF exports (rainfall, water level, siren) now default to
last 90 days. Accepts optional ?from=&to= query params, capped at
90-day max range. Shared applyDateRange helper in NotificationController.
2026-06-03 01:03:31 +08:00
root
d6193f0e5b fix(infra): resolve F-10 — add queue worker container for Laravel job processing
Separate sides-queue service using same Dockerfile, runs
php artisan queue:work with auto-restart. Uses database driver
with --sleep=3 --tries=3 --max-time=3600.
2026-06-03 00:39:54 +08:00
root
259ed76815 fix(security): resolve F-09 — wrap FcmService::sendToTopic in try-catch, never throw uncaught exceptions
Replaces raw Exception throw with logged error + 500 return.
Logs FCM API failures with response body for debugging.
2026-06-02 23:06:58 +08:00
root
11a2067014 refactor: resolve F-08 — extract duplicated dashboard query into StationDataService
Single getLatestReadings() method now shared by MapController,
HomeController, and AuthenticatedSessionController via DI.
2026-06-02 23:05:10 +08:00
root
1bb9c49194 fix(security): resolve F-07 — add API authentication (Sanctum) and rate limiting
- Install laravel/sanctum for token-based API auth
- AuthController: issues Bearer token on login, checks is_blocked, adds logout endpoint
- AlertController: added input validation for stationid, level, stationtype
- api routes: auth:sanctum middleware on data/alert endpoints, throttle:30,1 on login, throttle:60,1 on data
- Unauthenticated API requests return JSON 401 instead of redirect
- API login logged to activity_log
2026-06-02 23:01:23 +08:00
root
9de2dfba41 fix(security): resolve F-06 — add HSTS header to nginx config (max-age=1yr, includeSubDomains) 2026-06-02 01:09:15 +08:00
root
5644ef5f51 fix(security): resolve F-05 — add url validation to CCTV link update in CctvController 2026-06-02 01:08:38 +08:00
root
aa054b89f9 fix(style): resolve F-04 — rename cctvController.php to CctvController.php for PSR-4 compliance 2026-06-02 01:08:16 +08:00
root
4c1eb49e95 fix(security): resolve F-03 — fix inverted is_blocked checkbox logic, rename to unblock_account for semantic clarity 2026-06-02 01:07:28 +08:00
root
725ccbbeb6 fix(security): resolve F-02 — remove XSS vector by replacing {!! !!} with Blade conditionals in stationmgmt 2026-06-02 01:06:02 +08:00
root
9e0e749855 fix(content): resolve F-01 — replace Lorem Ipsum with SIDES project descriptions 2026-06-02 01:05:21 +08:00
root
63dd4e72e0 feat(cctv): embed live CCTV feeds as card layout with MJPEG stream preview
- Replaced table layout with responsive card grid (3 columns)
- Each station shows embedded live MJPEG feed with fallback for unavailable streams
- Admin edit button moved to card header
- Open Full Screen link in card footer
- Added cctv.tck.com.my to CSP img-src and connect-src
2026-05-30 23:48:31 +08:00
root
659400bbad initial commit 2026-05-30 23:41:15 +08:00
root
09e45443a8 feat(siren): show last data received timestamp in Active column
Active column now uses COALESCE to show the most recent timestamp
from siren, rainfall, or waterlevel data for each siren station.
2026-05-30 23:22:03 +08:00
root
c5270926c7 feat(audit): add user activity logging with View Logs modal and CSV export on User Management page 2026-05-30 23:18:49 +08:00
root
48654e123d feat(stationmgmt): add CSV import and export buttons for station management 2026-05-30 22:48:57 +08:00
root
f58fc6fb77 fix(controller): resolve F-01 — HomeController now matches MapController dashboard data query 2026-05-30 22:20:20 +08:00
root
e6992a03cf fix(nav): resolve F-08 — fix broken stationmanagement link; F-09 — use @lang for Daily Rainfall labels 2026-05-30 22:19:28 +08:00
root
795dee8cd4 fix(view): resolve F-07 — replace broken '../index.php' link with dashboard route 2026-05-30 22:18:54 +08:00
root
05fdfac76d fix(route): resolve F-06 — fix route name typo 'thrshold' to 'threshold' 2026-05-30 22:18:38 +08:00
root
8f7ed77612 fix(controller): resolve F-05 — fix 'potrait' typo to 'portrait' in SirenController and NotificationController 2026-05-30 22:18:16 +08:00
root
d650655d59 fix(view): resolve F-04 — remove dead cumulative sum bug; F-10 — remove debug example row from threshold table 2026-05-30 22:18:04 +08:00
root
5410e0916d fix(controller): resolve F-01 — create missing HomeController with correct column names (lat/lng) 2026-05-30 22:17:29 +08:00
root
6a4de2ba22 fix(db): add ON CONFLICT DO NOTHING rules for sensor table duplicate inserts 2026-05-28 18:54:20 +08:00
root
bfdf528e76 docs: add CHANGELOG.md documenting all audit fixes, config changes, and DB recovery 2026-05-28 18:49:06 +08:00
root
90550e9530 fix(db): make users.email nullable to match existing data schema 2026-05-28 17:35:14 +08:00
root
549932b297 chore: add root .gitignore to exclude .env from version control 2026-05-28 17:03:20 +08:00
root
02d5c24502 chore: add .gitignore to exclude .env from version control 2026-05-28 16:52:28 +08:00
root
8538c1b8df fix(security): resolve F-24 — add URL validation for CCTV links, remove hardcoded http:// prefix 2026-05-28 16:41:50 +08:00
root
abdb5a9fcc fix(security): resolve F-23 — add Referrer-Policy and CSP headers to Nginx config 2026-05-28 16:40:35 +08:00
root
c873e4d261 fix(deploy): resolve F-19 — remove redundant COPY and dead comments in Dockerfile 2026-05-28 16:40:03 +08:00
root
fd8d392a08 fix(config): resolve F-18 — add .env.example with documented environment variables 2026-05-28 16:39:07 +08:00
root
118f550d31 fix(maintainability): resolve F-15 — remove all commented-out dead code blocks 2026-05-28 16:38:26 +08:00
root
f7f2736245 fix(reliability): resolve F-12 — wrap AdminController write operations in DB::transaction() 2026-05-28 16:36:07 +08:00
root
f9061ade2f fix(reliability): resolve F-11 — add required parameter validation to historical endpoints 2026-05-28 16:34:52 +08:00
root
509afdb4c8 fix(security): resolve F-10 — replace leaked exception messages with generic user-facing errors 2026-05-28 16:33:37 +08:00
root
07f22972ee fix(reliability): resolve F-09 — add error handling for FCM credential loading 2026-05-28 16:31:41 +08:00
root
3c83a809ea fix(security): resolve F-07 — standardize password policy to Password::defaults() 2026-05-28 16:28:41 +08:00
root
c863f6f81b fix(perf): resolve F-13 — add database indexes on joined/filtered columns 2026-05-28 16:27:45 +08:00
root
968c1e626f fix(security): resolve F-06 — escape translated strings in station type badges 2026-05-28 16:27:16 +08:00
root
d95cb57275 fix(security): resolve F-02 — parameterize SQL queries in WaterLevelController index() 2026-05-28 16:26:33 +08:00
root
e9fa6a2912 fix(security): resolve F-01 — parameterize SQL queries in RainfallController index() 2026-05-28 16:26:01 +08:00
root
b63cb6a3e8 Initial commit: existing codebase state 2026-05-28 16:25:22 +08:00