87 lines
6.1 KiB
Markdown
87 lines
6.1 KiB
Markdown
# Changelog
|
||
|
||
All notable changes to the SIDES project are documented in this file.
|
||
|
||
---
|
||
|
||
## [2026-05-28] — Audit Fix, Configuration & Database Recovery
|
||
|
||
### Security
|
||
|
||
- **F-01** Parameterized SQL queries in `RainfallController::index()` — replaced string-interpolated `CAST('$dateFilter' AS date)` and `AND s.stationid = '{$stationFilter}'` with `?` bindings, eliminating SQL injection vectors
|
||
- **F-02** Parameterized SQL queries in `WaterLevelController::index()` — replaced `WHERE s.stationid = '{$stationFilter}'` and `AND w.datetime = '{$sqlDate}'` with `?` bindings
|
||
- **F-06** Fixed XSS risk in `stationmgmt.blade.php` — replaced `{!! $types ... !!}` with `e()` escaping for translation strings inside badge HTML
|
||
- **F-07** Standardized password policy in `AdminController` — both `storeUser()` and `updatePassword()` now use `Password::defaults()` instead of `min:6`
|
||
- **F-10** Stopped leaking internal exception messages to users — `AdminController` catch blocks now log errors via `Log::error()` and return `__('toast.error')` generic messages; added `toast.error` translation keys for EN and BM
|
||
- **F-23** Added `Referrer-Policy: strict-origin-when-cross-origin` and `Content-Security-Policy` headers to Nginx config; changed existing headers to `always` directive
|
||
- **F-24** Added `url` validation rule for `cctv_link` in both `storeStation()` and `updateStation()`; removed hardcoded `http://` prefix from CCTV link in `cctv.blade.php`
|
||
|
||
### Reliability
|
||
|
||
- **F-09** Added error handling to `FcmService::__construct()` — validates credentials file existence, catches `JsonException` on parse, logs errors, and returns status 500 in `sendToTopic()` when credentials are unavailable
|
||
- **F-11** Added required parameter validation to `WaterLevelController::wlHistory()`, `WaterLevelController::exportHistoricalWl()`, `RainfallController::historicalRainfall()`, and `RainfallController::exportHourlyRainfallExcel()` — all now validate `station`, `startdate`, and `enddate` before use
|
||
- **F-12** Wrapped `AdminController::storeStation()`, `storeUser()`, and `updateUsers()` write operations in `DB::transaction()` for atomicity
|
||
- **F-15** Removed all commented-out dead code blocks from `cctvController.php`, `RainfallController.php`, `AlertController.php`, `AppServiceProvider.php`, `homeapp.blade.php`, `home.blade.php`, `usermgmt.blade.php`, and `threshold.blade.php`
|
||
|
||
### Performance
|
||
|
||
- **F-13** Created migration `2026_05_28_000000_add_performance_indexes.php` adding indexes on:
|
||
- `rainfall(stationid)`, `rainfall(timestamp)`, `rainfall(stationid, timestamp)`
|
||
- `waterlevel(stationid)`, `waterlevel(datetime)`, `waterlevel(stationid, datetime)`
|
||
- `notification(stationid)`, `notification(timestamp)`, `notification(stationtype)`
|
||
- `siren(stationid)`, `siren(active_time)`
|
||
|
||
### Configuration
|
||
|
||
- **F-18** Created `src/.env.example` with all documented environment variables (APP, DB, SESSION, CACHE, QUEUE, MAIL, FIREBASE, FCM, POSTGRES, PGADMIN)
|
||
- Created `src/.env` with populated values: generated `APP_KEY`, set `DB_*` matching docker-compose PostgreSQL service, set `FIREBASE_PROJECT_ID=sides-b4abb`, set `FIREBASE_CREDENTIALS` path
|
||
- Created root `.env` for docker-compose with `POSTGRES_DB`, `POSTGRES_USER`, `POSTGRES_PASSWORD`, `PGADMIN_EMAIL`, `PGADMIN_PASSWORD`
|
||
- Added `src/.gitignore` and root `.gitignore` to exclude `.env` from version control
|
||
|
||
### Deployment
|
||
|
||
- **F-19** Removed redundant `COPY ./src /var/www/html` line from `Dockerfile` — kept only `COPY --chown=www:www ./src /var/www/html`; removed commented-out dead lines (`RUN curl`, `RUN tar`, `COPY fileni`)
|
||
- Fixed `docker-compose.yml` PostgreSQL data directory from `/var/lib/postgres/data` to `/var/lib/postgresql/data` and added `PGDATA` env var
|
||
- Set non-empty `POSTGRES_PASSWORD` and `DB_PASSWORD` (was empty, causing PostgreSQL 18 to refuse initialization)
|
||
- Set non-empty `PGADMIN_PASSWORD` (was empty, causing pgAdmin to crash)
|
||
|
||
### Database Recovery
|
||
|
||
- Restored production data from `backup/sides_20260528` into the live `sides` database:
|
||
- `users`: 4 rows (admin, imam14, ijantck, jpskedah)
|
||
- `station`: 9 rows (KBLG0025–KBLG0033)
|
||
- `rainfall`: 91,829 rows
|
||
- `waterlevel`: 137,956 rows
|
||
- `notification`: 128 rows
|
||
- Made `users.email` column nullable in migration `0001_01_01_000000_create_users_table.php` — existing data has NULL emails for admin and jpskedah
|
||
- Reset all sequence counters to 300,000+ to avoid duplicate key errors from concurrent sensor inserts with explicit IDs
|
||
|
||
### Codebase Assessment
|
||
|
||
- Created `.planning/codebase/` with 7 structured documents:
|
||
- `STACK.md` — PHP 8.2, Laravel 12, PostgreSQL 18, Docker/Nginx infrastructure
|
||
- `INTEGRATIONS.md` — Firebase FCM, PostgreSQL, S3 filesystem, database queue/cache/session
|
||
- `ARCHITECTURE.md` — MVC pattern, raw SQL over Eloquent, Breeze auth, FCM push alerts
|
||
- `STRUCTURE.md` — Directory tree, 12 migrations, 8+ tables, dual layout system
|
||
- `CONVENTIONS.md` — Raw SQL patterns, PSR-12, localization (en/bm), Blade conventions
|
||
- `TESTING.md` — PHPUnit, near-zero coverage (2 example tests only), no CI
|
||
- `CONCERNS.md` — 26 findings: 3 critical SQL injections, unauthenticated API endpoints, missing indexes, no audit logging, deployment security gaps
|
||
|
||
---
|
||
|
||
### Manual-Only Findings (Not Yet Fixed)
|
||
|
||
These require design decisions or architectural changes:
|
||
|
||
| # | Finding | Notes |
|
||
|---|---------|------|
|
||
| F-03 | Unauthenticated API alert endpoint | Requires Laravel Sanctum + rate limiting |
|
||
| F-04 | API endpoints without authentication | Architectural change across subsystems |
|
||
| F-05 | API login without token | Requires Sanctum integration |
|
||
| F-08 | Inverted block/unblock logic | Requires UX redesign of checkbox semantics |
|
||
| F-14 | Duplicated dashboard query | Requires service class extraction |
|
||
| F-20 | PostgreSQL data dir path | Already fixed in this session |
|
||
| F-21 | Docker security (Dozzle shell, Filebrowser root, pgAdmin exposed) | Architecture decisions needed |
|
||
| F-22 | No Docker health checks | Deployment decisions needed |
|
||
| F-25 | No audit logging | Low severity, requires design |
|
||
| F-26 | No API rate limiting | Low severity, requires design | |