docs: sync latest doc updates to repo
This commit is contained in:
@@ -45,6 +45,33 @@ SIDES (Sabo Integrated Debris Flow Monitoring and Early Warning System) is a web
|
|||||||
+---------+
|
+---------+
|
||||||
```
|
```
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart TD
|
||||||
|
I["Internet"]:::internet --> RP["Reverse Proxy (TLS termination)"]:::proxy
|
||||||
|
RP --> NET["Docker Network (tckdev_net)"]:::network
|
||||||
|
|
||||||
|
subgraph NET["Docker Network"]
|
||||||
|
N["nginx (tckdev-web :80)"]:::server --> P["php-fpm (tckdev-app :9000)"]:::app --> DB["PostgreSQL (tckdev-db :5432)"]:::db
|
||||||
|
PG["pgAdmin (tckdev-pgAdmin :5050)"]:::tool --> DB
|
||||||
|
V["pgdata volume"]:::volume --> DB
|
||||||
|
end
|
||||||
|
|
||||||
|
P --> L["Laravel 12 Application"]:::laravel
|
||||||
|
L --> F["FCM API"]:::api
|
||||||
|
|
||||||
|
classDef internet fill:#2196F3,stroke:#333,stroke-width:2px,color:#fff;
|
||||||
|
classDef proxy fill:#4CAF50,stroke:#333,stroke-width:2px,color:#fff;
|
||||||
|
classDef network fill:#9C27B0,stroke:#333,stroke-width:2px,color:#fff;
|
||||||
|
classDef server fill:#FF9800,stroke:#333,stroke-width:2px,color:#fff;
|
||||||
|
classDef app fill:#00BCD4,stroke:#333,stroke-width:2px,color:#fff;
|
||||||
|
classDef db fill:#673AB7,stroke:#333,stroke-width:2px,color:#fff;
|
||||||
|
classDef tool fill:#FFC107,stroke:#333,stroke-width:2px,color:#000;
|
||||||
|
classDef volume fill:#795548,stroke:#333,stroke-width:2px,color:#fff;
|
||||||
|
classDef laravel fill:#8BC34A,stroke:#333,stroke-width:2px,color:#fff;
|
||||||
|
classDef api fill:#607D8B,stroke:#333,stroke-width:2px,color:#fff;
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
All four services run as Docker containers on a single host:
|
All four services run as Docker containers on a single host:
|
||||||
|
|
||||||
| Container | Image | Purpose |
|
| Container | Image | Purpose |
|
||||||
|
|||||||
@@ -37,6 +37,21 @@ SIDES (Sistem Informasi Data dan Early Warning System) is a Laravel 12 web appli
|
|||||||
volume: pgdata volume: pgadmin_data
|
volume: pgdata volume: pgadmin_data
|
||||||
```
|
```
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart TD
|
||||||
|
UB["User Browser"]:::client -->|:80| N["web (nginx)\nnginx:stable-alpine"]:::server
|
||||||
|
N -->|fastcgi :9000| A["app (php-fpm)\nphp:8.2-fpm\n(bind mount ./src)"]:::app
|
||||||
|
A -->|pgsql :5432| DB["postgres\npostgres:16\nvolume: pgdata"]:::db
|
||||||
|
PG["pgAdmin\ndpage/pgadmin4\nvolume: pgadmin_data"]:::tool --> DB
|
||||||
|
|
||||||
|
classDef client fill:#2196F3,stroke:#333,stroke-width:2px,color:#fff;
|
||||||
|
classDef server fill:#FF9800,stroke:#333,stroke-width:2px,color:#fff;
|
||||||
|
classDef app fill:#00BCD4,stroke:#333,stroke-width:2px,color:#fff;
|
||||||
|
classDef db fill:#673AB7,stroke:#333,stroke-width:2px,color:#fff;
|
||||||
|
classDef tool fill:#FFC107,stroke:#333,stroke-width:2px,color:#000;
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
### Container Summary
|
### Container Summary
|
||||||
|
|
||||||
| Container | Image | Port | Purpose |
|
| Container | Image | Port | Purpose |
|
||||||
@@ -92,6 +107,34 @@ Browser --:80--> nginx
|
|||||||
Blade view / JSON response
|
Blade view / JSON response
|
||||||
```
|
```
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart TD
|
||||||
|
B["Browser"]:::client -->|:80| N["nginx"]:::server
|
||||||
|
|
||||||
|
N -->|static asset?| SA["/var/www/html/public/{file}"]:::static
|
||||||
|
N -->|*.php?| P["fastcgi://app:9000"]:::php
|
||||||
|
|
||||||
|
P --> R["Laravel Router"]:::router
|
||||||
|
|
||||||
|
R --> AM["auth middleware\n(Breeze session auth)"]:::middleware
|
||||||
|
R --> ADM["admin middleware\n(access_level === 1 check)"]:::middleware
|
||||||
|
R --> C["Controller"]:::controller
|
||||||
|
|
||||||
|
C --> Q["DB::table() / DB::select()"]:::query --> DB["PostgreSQL"]:::db
|
||||||
|
DB --> V["Blade view / JSON response"]:::response
|
||||||
|
|
||||||
|
classDef client fill:#2196F3,stroke:#333,stroke-width:2px,color:#fff;
|
||||||
|
classDef server fill:#FF9800,stroke:#333,stroke-width:2px,color:#fff;
|
||||||
|
classDef static fill:#9E9E9E,stroke:#333,stroke-width:2px,color:#fff;
|
||||||
|
classDef php fill:#00BCD4,stroke:#333,stroke-width:2px,color:#fff;
|
||||||
|
classDef router fill:#9C27B0,stroke:#333,stroke-width:2px,color:#fff;
|
||||||
|
classDef middleware fill:#FFC107,stroke:#333,stroke-width:2px,color:#000;
|
||||||
|
classDef controller fill:#4CAF50,stroke:#333,stroke-width:2px,color:#fff;
|
||||||
|
classDef query fill:#795548,stroke:#333,stroke-width:2px,color:#fff;
|
||||||
|
classDef db fill:#673AB7,stroke:#333,stroke-width:2px,color:#fff;
|
||||||
|
classDef response fill:#607D8B,stroke:#333,stroke-width:2px,color:#fff;
|
||||||
|
```
|
||||||
|
|
||||||
1. Browser hits port 80 on the `web` container.
|
1. Browser hits port 80 on the `web` container.
|
||||||
2. nginx serves static files from `/var/www/html/public` directly.
|
2. nginx serves static files from `/var/www/html/public` directly.
|
||||||
3. PHP requests are forwarded via FastCGI to `app:9000`.
|
3. PHP requests are forwarded via FastCGI to `app:9000`.
|
||||||
@@ -114,6 +157,24 @@ IoT Device --:80/api/...--> nginx ---> app:9000
|
|||||||
PostgreSQL
|
PostgreSQL
|
||||||
```
|
```
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart TD
|
||||||
|
D["IoT Device"]:::device -->|:80/api/...| N["nginx"]:::server
|
||||||
|
N --> P["app:9000 (php-fpm)"]:::php
|
||||||
|
P --> R["Laravel API Router\n(no auth middleware on data endpoints)"]:::router
|
||||||
|
R --> C["Controller (Api\\*)"]:::controller
|
||||||
|
C --> Q["DB::table() / DB::select()"]:::query --> DB["PostgreSQL"]:::db
|
||||||
|
|
||||||
|
classDef device fill:#2196F3,stroke:#333,stroke-width:2px,color:#fff;
|
||||||
|
classDef server fill:#FF9800,stroke:#333,stroke-width:2px,color:#fff;
|
||||||
|
classDef php fill:#00BCD4,stroke:#333,stroke-width:2px,color:#fff;
|
||||||
|
classDef router fill:#9C27B0,stroke:#333,stroke-width:2px,color:#fff;
|
||||||
|
classDef controller fill:#4CAF50,stroke:#333,stroke-width:2px,color:#fff;
|
||||||
|
classDef query fill:#795548,stroke:#333,stroke-width:2px,color:#fff;
|
||||||
|
classDef db fill:#673AB7,stroke:#333,stroke-width:2px,color:#fff;
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
API routes under `/api/` have no middleware. The `POST /api/login` endpoint validates credentials against the `users` table using `DB::select()` with bound parameters and `Hash::check()`. There are no API tokens -- authentication is a single request/response returning user data on success.
|
API routes under `/api/` have no middleware. The `POST /api/login` endpoint validates credentials against the `users` table using `DB::select()` with bound parameters and `Hash::check()`. There are no API tokens -- authentication is a single request/response returning user data on success.
|
||||||
|
|
||||||
## Data Model
|
## Data Model
|
||||||
@@ -156,6 +217,77 @@ The application uses six database tables. There are no foreign key constraints;
|
|||||||
+----------------+
|
+----------------+
|
||||||
```
|
```
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
erDiagram
|
||||||
|
station {
|
||||||
|
int stationid
|
||||||
|
string name
|
||||||
|
string district
|
||||||
|
float lng
|
||||||
|
float lat
|
||||||
|
string mainriverbasin
|
||||||
|
string subriverbasin
|
||||||
|
boolean rainfall_flag
|
||||||
|
boolean waterlevel_flag
|
||||||
|
boolean siren_flag
|
||||||
|
string cctv_link
|
||||||
|
}
|
||||||
|
|
||||||
|
rainfall {
|
||||||
|
int id
|
||||||
|
int stationid
|
||||||
|
datetime timestamp
|
||||||
|
float anncum
|
||||||
|
float daily
|
||||||
|
float hourly
|
||||||
|
float currentrf
|
||||||
|
float battery
|
||||||
|
}
|
||||||
|
|
||||||
|
waterlevel {
|
||||||
|
int id
|
||||||
|
int stationid
|
||||||
|
datetime datetime
|
||||||
|
float waterlevel
|
||||||
|
string alert
|
||||||
|
string warning
|
||||||
|
string danger
|
||||||
|
}
|
||||||
|
|
||||||
|
siren {
|
||||||
|
int id
|
||||||
|
int stationid
|
||||||
|
string stationtype
|
||||||
|
datetime active_time
|
||||||
|
string level
|
||||||
|
}
|
||||||
|
|
||||||
|
notification {
|
||||||
|
int id
|
||||||
|
int stationid
|
||||||
|
datetime timestamp
|
||||||
|
string stationtype
|
||||||
|
string level
|
||||||
|
datetime active_time
|
||||||
|
}
|
||||||
|
|
||||||
|
users {
|
||||||
|
int id
|
||||||
|
string name
|
||||||
|
string email
|
||||||
|
string access_level
|
||||||
|
string password
|
||||||
|
int login_attempts
|
||||||
|
boolean is_blocked
|
||||||
|
}
|
||||||
|
|
||||||
|
station ||--o{ rainfall : "has"
|
||||||
|
station ||--o{ waterlevel : "has"
|
||||||
|
station ||--o{ siren : "has"
|
||||||
|
station ||--o{ notification : "has"
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
### Table Descriptions
|
### Table Descriptions
|
||||||
|
|
||||||
| Table | Purpose |
|
| Table | Purpose |
|
||||||
|
|||||||
@@ -61,6 +61,67 @@ persistent storage. Data survives container restarts and rebuilds.
|
|||||||
|--------------|
|
|--------------|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
erDiagram
|
||||||
|
station {
|
||||||
|
int stationid
|
||||||
|
string name
|
||||||
|
string district
|
||||||
|
float lng
|
||||||
|
float lat
|
||||||
|
string mainriverbasin
|
||||||
|
string subriverbasin
|
||||||
|
float rainfall
|
||||||
|
float waterlevel
|
||||||
|
boolean siren
|
||||||
|
string cctv_link
|
||||||
|
}
|
||||||
|
|
||||||
|
rainfall {
|
||||||
|
int id
|
||||||
|
int stationid
|
||||||
|
datetime timestamp
|
||||||
|
float anncum
|
||||||
|
float daily
|
||||||
|
float hourly
|
||||||
|
float currentrf
|
||||||
|
float battery
|
||||||
|
}
|
||||||
|
|
||||||
|
waterlevel {
|
||||||
|
int id
|
||||||
|
int stationid
|
||||||
|
datetime datetime
|
||||||
|
float waterlevel
|
||||||
|
string alert
|
||||||
|
string warning
|
||||||
|
string danger
|
||||||
|
}
|
||||||
|
|
||||||
|
siren {
|
||||||
|
int id
|
||||||
|
int stationid
|
||||||
|
string stationtype
|
||||||
|
datetime active_time
|
||||||
|
string level
|
||||||
|
}
|
||||||
|
|
||||||
|
notification {
|
||||||
|
int id
|
||||||
|
int stationid
|
||||||
|
datetime timestamp
|
||||||
|
string stationtype
|
||||||
|
string level
|
||||||
|
datetime active_time
|
||||||
|
}
|
||||||
|
|
||||||
|
station ||--o{ rainfall : "has"
|
||||||
|
station ||--o{ waterlevel : "has"
|
||||||
|
station ||--o{ siren : "has"
|
||||||
|
station ||--o{ notification : "has"
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
**Note:** There are no database-level foreign keys between `station` and the
|
**Note:** There are no database-level foreign keys between `station` and the
|
||||||
data tables. Relationships are enforced at the application level by matching
|
data tables. Relationships are enforced at the application level by matching
|
||||||
`stationid` values.
|
`stationid` values.
|
||||||
|
|||||||
Reference in New Issue
Block a user