Compare commits

..

10 Commits

1542 changed files with 3776 additions and 517945 deletions

420
README.md Normal file
View File

@@ -0,0 +1,420 @@
# SIDES — SABO Integrated Debris Flows Monitoring and Early Warning System
SIDES is a flood and debris flow monitoring system built for the Sabo Dam construction project at Sg Kupang, Baling, Kedah, Malaysia. It provides real-time monitoring of rainfall, water level, siren status, and CCTV feeds from field stations, with historical data analysis, notifications, and an admin dashboard for station and user management.
The system is part of the flood and debris flow mitigation initiative by **Jabatan Pengairan dan Saliran (JPS) Kedah** and is live at [https://sides.tck.com.my](https://sides.tck.com.my).
---
## Table of Contents
- [Features](#features)
- [Tech Stack](#tech-stack)
- [Architecture](#architecture)
- [Project Structure](#project-structure)
- [Database Schema](#database-schema)
- [Requirements](#requirements)
- [Deployment (Docker)](#deployment-docker)
- [Environment Variables](#environment-variables)
- [User Accounts](#user-accounts)
- [Third-Party Packages](#third-party-packages)
- [Frontend Libraries (CDN)](#frontend-libraries-cdn)
- [Localization](#localization)
- [Activity Logging](#activity-logging)
- [Android App Integration](#android-app-integration)
- [Backup & Restore](#backup--restore)
---
## Features
### Monitoring Dashboard
- Interactive OpenStreetMap showing all stations with real-time sensor data
- Station markers color-coded by type (rainfall, water level, siren)
### Rainfall Monitoring
- **Current Rainfall** — real-time rainfall readings per station with hourly graphs
- **Daily Rainfall** — date-based rainfall data with hourly interval breakdown
- **Threshold Monitoring** — cumulative rainfall totals with 4-tier alert levels:
- Light (110 mm) — green
- Moderate (1130 mm) — yellow
- Heavy (3160 mm) — orange
- Very Heavy (>60 mm) — red
- **Historical Rainfall** — query by station and date range with CSV export
### Water Level Monitoring
- **Current Water Level** — real-time readings per station with graphs
- **Historical Water Level** — query by station and date range with CSV export
### Siren Monitoring
- Siren status for all siren-equipped stations (Normal / Warning / Danger)
- **Active column** shows the last data received timestamp (from siren, rainfall, or waterlevel data)
- Siren history with PDF export
### Notifications
- Rainfall, water level, and siren notifications with history
- PDF export for notification history
### CCTV
- Live CCTV feed links per station
- Admin-only inline editing of CCTV URLs
### Admin Panel
- **Station Management** — CRUD operations, CSV import/export with sample CSV download
- **User Management** — CRUD operations, password updates
- **Activity Logs** — per-user activity log viewer with CSV export (tracks login, logout, CRUD operations, CSV import/export)
### Other
- Bilingual support (English / Bahasa Malaysia)
- Responsive design with Boxicons UI
- PDF report generation (siren history, notification history)
- HTTPS via Caddy reverse proxy with auto Let's Encrypt
- Android app detection — EWT link hidden when accessed from Android app
---
## Tech Stack
| Layer | Technology |
|----------------|-------------------------------------|
| **Backend** | PHP 8.2, Laravel 12 |
| **Database** | PostgreSQL 18 |
| **Web Server** | Nginx (stable-alpine) |
| **Frontend** | Blade templates, Tailwind CSS, Vite |
| **JS Libraries**| Boxicons, Flatpickr, Chart.js |
| **Maps** | OpenStreetMap + Leaflet.js |
| **Containerization** | Docker, Docker Compose |
| **Reverse Proxy** | Caddy (auto HTTPS) |
| **Asset Building** | Vite 7, Node.js LTS |
---
## Architecture
```
Internet → Caddy (HTTPS/443) → Nginx (8080) → PHP-FPM (9000) → Laravel
PostgreSQL (5432)
Additional services:
- pgAdmin (5050) — database management UI
- Dozzle (777) — container log viewer
- FileBrowser (8900) — file management UI
```
All services run in Docker containers on a Debian LXC (Proxmox), connected via the `sides_net` bridge network.
---
## Project Structure
```
sides/
├── .env # Docker Compose environment (DB creds, TZ)
├── docker-compose.yml # Service definitions (app, postgres, web, pgadmin, dozzle, filebrowser)
├── Dockerfile # PHP 8.2-FPM with pgsql, gd, composer, node
├── docker/
│ ├── nginx/default.conf # Nginx config with CSP headers, fastcgi proxy params
│ └── postgres/ # PostgreSQL data directory
├── backup/ # Database backups (e.g., sides_20260528/)
├── src/ # Laravel application root
│ ├── .env # Laravel config (APP_URL, DB, timezone)
│ ├── app/
│ │ ├── Http/
│ │ │ ├── Controllers/ # RainfallController, WaterLevelController, SirenController, AdminController, etc.
│ │ │ └── Middleware/ # AdminMiddleware, ForceRequestScheme, TrustProxies
│ │ ├── Models/ # Eloquent models (User, Station, ActivityLog, etc.)
│ │ ├── Exports/ # Maatwebsite Excel exports (StationExport, WaterLevelExport, etc.)
│ │ └── Imports/ # Maatwebsite Excel imports (StationImport)
│ ├── database/migrations/ # 15 migrations (users, station, rainfall, waterlevel, siren, notification, activity_log, etc.)
│ ├── resources/
│ │ ├── views/layout/ # Blade templates (dashboard, rainfall, waterlevel, siren, cctv, admin, etc.)
│ │ ├── js/ # Frontend JavaScript (app.js)
│ │ └── css/ # Tailwind styles
│ ├── routes/web.php # Application routes
│ ├── lang/en/ # English translations
│ ├── lang/bm/ # Bahasa Malaysia translations
│ └── public/ # Document root (index.php, build assets, js, css)
├── filebrowser-data/ # FileBrowser config
└── filebrowser-files/ # FileBrowser shared files
```
---
## Database Schema
| Table | Description | Key Columns |
|----------------|----------------------------------------------|-----------------------------------------------------|
| `users` | System users | `id`, `name`, `email` (nullable), `password`, `access_level`, `is_blocked`, `login_attempts` |
| `station` | Monitoring stations | `stationid` (PK, varchar), `name`, `district`, `lat`, `lng`, `rainfall`, `waterlevel`, `siren`, `cctv_link` |
| `rainfall` | Rainfall readings | `id` (PK, int), `stationid` (FK), `timestamp`, `interval`, `rainfall` |
| `waterlevel` | Water level readings | `id` (PK, int), `stationid` (FK), `datetime`, `waterlevel` |
| `siren` | Siren events | `id` (PK), `stationid` (FK), `active_time`, `level` (N/H/L) |
| `notification` | System notifications | `id`, `stationid`, `timestamp`, `title`, `description` |
| `activity_log` | User activity tracking | `id`, `user_id`, `user_name`, `action`, `subject_type`, `subject_id`, `properties` (JSON), `ip_address`, `created_at` |
| `sessions` | User sessions (database driver) | |
| `cache` | Application cache (database driver) | |
**Notes:**
- `station.stationid` is a varchar primary key (e.g., `KBLG0031`), not an auto-increment integer
- `rainfall.id` and `waterlevel.id` use explicit values set by the external IoT data insertion system
- PostgreSQL RULEs are configured for `ON CONFLICT DO NOTHING` on sensor tables to handle duplicate inserts
- DB sequences are reset to 300,000+ to avoid conflicts with existing data
- `activity_log.user_id` has no foreign key constraint — logs are preserved when users are deleted
---
## Requirements
- **OS**: Debian/Ubuntu Linux (deployed on Proxmox LXC)
- **Docker**: 24+ with Docker Compose v2
- **Ports**: 8080 (HTTP), 5432 (PostgreSQL), 5050 (pgAdmin), 777 (Dozzle), 8900 (FileBrowser)
- **External**: Caddy reverse proxy handling TLS termination on port 443
- **Disk**: ~2 GB for application + database (238K rainfall records, 138K water level records)
---
## Deployment (Docker)
### 1. Clone the repository
```bash
git clone <repo-url> /root/sides
cd /root/sides
```
### 2. Configure environment
```bash
# Edit the root .env for Docker services
cp .env.example .env
# Set POSTGRES_DB, POSTGRES_USER, POSTGRES_PASSWORD, TZ
# Edit src/.env for Laravel
# Set APP_URL, DB_HOST=postgres, DB_DATABASE, DB_USERNAME, DB_PASSWORD
```
### 3. Build and start containers
```bash
docker compose build app
docker compose up -d
```
### 4. Install Laravel dependencies
```bash
docker compose exec app composer install -u root
docker compose exec app php artisan key:generate
docker compose exec app php artisan migrate
docker compose exec app php artisan db:seed
```
### 5. Set file permissions
```bash
docker compose exec app chown -R 1000:1000 /var/www/html/storage /var/www/html/bootstrap/cache
```
### 6. (Optional) Restore from backup
```bash
# Copy backup SQL to postgres container
docker compose cp backup/sides_20260528/sides_db.sql postgres:/tmp/
docker compose exec postgres psql -U sides_user -d sides -f /tmp/sides_db.sql
```
### 7. Verify
```bash
curl -I http://localhost:8080
```
---
## Environment Variables
### Root `.env` (Docker Compose)
| Variable | Description | Default |
|------------------------|------------------------------------|------------------------------|
| `TZ` | Container timezone | `Asia/Kuala_Lumpur` |
| `POSTGRES_DB` | Database name | `sides` |
| `POSTGRES_USER` | Database user | `sides_user` |
| `POSTGRES_PASSWORD` | Database password | (generated) |
| `PGADMIN_EMAIL` | pgAdmin login email | `admin@sides.didkedah.gov.my`|
| `PGADMIN_PASSWORD` | pgAdmin login password | `sides2026admin` |
### `src/.env` (Laravel)
| Variable | Description | Default |
|-------------------|------------------------------------|----------------------------------|
| `APP_NAME` | Application name | `SIDES` |
| `APP_ENV` | Environment | `local` |
| `APP_URL` | Public URL | `https://sides.tck.com.my` |
| `APP_TIMEZONE` | Application timezone | `Asia/Kuala_Lumpur` |
| `DB_CONNECTION` | Database driver | `pgsql` |
| `DB_HOST` | Database host (container name) | `postgres` |
| `DB_PORT` | Database port | `5432` |
| `DB_DATABASE` | Database name | `sides` |
| `SESSION_DRIVER` | Session driver | `database` |
---
## User Accounts
All passwords use Laravel's `hashed` cast. The following accounts exist:
| Username | Access Level | Description | Password |
|-------------|-------------|----------------------|---------------|
| `admin` | 1 (Admin) | System administrator | `sides2026` |
| `jpskedah` | 1 (Admin) | JPS Kedah officer | `sides2026` |
| `ijantck` | 1 (Admin) | TCK staff | `sides2026` |
| `imam14` | 1 (Admin) | TCK staff | `sides2026` |
**Security notes:**
- Accounts are blocked after 3 failed login attempts (`is_blocked` flag, `login_attempts` counter)
- Blocked accounts must be manually unblocked in the database: `UPDATE users SET is_blocked = false, login_attempts = 0 WHERE name = 'username';`
- Password resets are done through the admin User Management panel
---
## Third-Party Packages
### Composer (PHP)
| Package | Purpose |
|------------------------------|--------------------------------------------|
| `laravel/framework` ^12.0 | Core Laravel framework |
| `laravel/breeze` ^2.3 | Authentication scaffolding |
| `barryvdh/laravel-dompdf` ^3.1 | PDF generation (siren history, notifications) |
| `maatwebsite/excel` ^3.1 | CSV/Excel import and export |
| `google/auth` ^1.49 | Google Auth library (Firebase push notifications) |
| `laravel/tinker` ^2.10 | Interactive REPL |
### NPM (Build)
| Package | Purpose |
|------------------------------|--------------------------------------------|
| `vite` ^7.0.7 | Asset bundler |
| `tailwindcss` ^3.1.0 | CSS framework |
| `alpinejs` ^3.4.2 | Lightweight JS reactivity |
| `axios` ^1.11.0 | HTTP client |
| `laravel-vite-plugin` ^2.0 | Vite integration for Laravel |
---
## Frontend Libraries (CDN)
Loaded via CDN in Blade templates (see CSP headers in `docker/nginx/default.conf`):
| Library | Source | Purpose |
|------------------|--------------------------|-----------------------------|
| Boxicons | `cdn.jsdelivr.net` | Icon library |
| Flatpickr | `cdn.jsdelivr.net` | Date/time picker |
| Chart.js | `cdn.jsdelivr.net` | Rainfall/water level graphs |
| jQuery | `code.jquery.com` | DOM manipulation |
| Bootstrap 5 | `cdn.jsdelivr.net` | CSS framework (admin panels)|
| Leaflet.js | `unpkg.com` | OpenStreetMap integration |
| Data Tables | `cdn.datatables.net` | Sortable/searchable tables |
---
## Localization
SIDES supports two languages:
- **English** (`en`) — `src/lang/en/messages.php`, `src/lang/en/toast.php`
- **Bahasa Malaysia** (`bm`) — `src/lang/bm/messages.php`, `src/lang/bm/toast.php`
Language switcher available in the navbar via the `/locale/{locale}` route.
---
## Activity Logging
User actions are tracked in the `activity_log` table via the `ActivityLog::record()` helper. Logged actions include:
| Category | Actions |
|------------|----------------------------------------------------------------|
| Auth | `login`, `logout` |
| Stations | `create_station`, `update_station`, `delete_station` |
| Users | `create_user`, `update_user`, `update_password`, `delete_user` |
| CSV | `import_stations_csv`, `export_stations_csv` |
| CCTV | `update_cctv_link` |
| Logs | `export_user_logs` |
Activity logs are accessible from User Management → View Logs (per-user), with CSV export.
---
## Android App Integration
The system detects Android user agents and hides the Early Warning Threshold (EWT) nav link when accessed from the Android companion app. Detection is server-side:
```php
$isAndroid = preg_match('/Android/i', request()->userAgent());
```
---
## Backup & Restore
### Create a backup
```bash
docker compose exec postgres pg_dump -U sides_user sides > backup/sides_$(date +%Y%m%d).sql
```
### Restore from backup
```bash
docker compose cp backup/sides_YYYYMMDD/sides_db.sql postgres:/tmp/
docker compose exec postgres psql -U sides_user -d sides -f /tmp/sides_db.sql
```
### Reset sequences after restore
```bash
docker compose exec postgres psql -U sides_user -d sides -c "
SELECT setval('rainfall_id_seq', 300000);
SELECT setval('waterlevel_id_seq', 300000);
SELECT setval('users_id_seq', (SELECT MAX(id) + 1 FROM users));
SELECT setval('notification_id_seq', (SELECT MAX(id) + 1 FROM notification));
"
```
---
## Service Ports
| Service | Container | Port | URL |
|---------------|---------------|-------|------------------------------------------|
| Nginx (HTTP) | `sides-web` | 8080 | `http://localhost:8080` |
| PostgreSQL | `sides-db` | 5432 | `localhost:5432` |
| pgAdmin | `sides-pgAdmin`| 5050 | `http://localhost:5050` |
| Dozzle (Logs) | — | 777 | `http://localhost:777` |
| FileBrowser | `quantum-prod`| 8900 | `http://localhost:8900` |
| SIDES (public)| — | 443 | `https://sides.tck.com.my` (via Caddy) |
---
## Useful Commands
```bash
# Rebuild and restart
docker compose up -d --build
# View logs
docker compose logs -f app
docker compose logs -f web
# Artisan commands (run as root due to vendor permissions)
docker compose exec -u root app php artisan migrate
docker compose exec -u root app php artisan route:clear
docker compose exec -u root app php artisan view:clear
docker compose exec -u root app php artisan config:clear
docker compose exec -u root app composer dump-autoload
# Copy file to container
docker compose cp src/path/to/file app:/var/www/html/path/to/file
```

53
STATE.md Normal file
View File

@@ -0,0 +1,53 @@
# SIDES Deploy — STATE.md
## Deployment Status
- **App**: Running on Proxmox LXC (Docker Compose)
- **URL**: http://localhost:8080 (or server IP:8080)
- **Timezone**: Asia/Kuala_Lumpur (UTC+8) on all containers
## User Accounts
| Username | Password | Access Level | Notes |
|----------|----------|-------------|-------|
| admin | sides2026 | 1 (Admin) | Full access |
| jpskedah | kedah2026 | 1 (Admin) | Full access (upgraded from level 2) |
| ijantck | sides2026 | 1 (Admin) | Full access |
| imam14 | sides2026 | 1 (Admin) | Full access |
## Bugs Fixed
### Critical
- **RainfallController SQL binding**: Off-by-one (11 params vs 10 `?` placeholders) + Carbon object passed as string binding. Fixed to use formatted strings.
- **WaterLevelController displayDate**: Carbon object passed instead of string. Fixed.
- **Storage permissions**: `storage/` and `bootstrap/cache/` chowned to UID 1000 (`www`). Log file truncated.
- **PHP-FPM 502 Bad Gateway**: Nginx cached stale DNS for `app` container. Fixed by restarting nginx.
- **Asset URL generation**: Added `ForceRequestScheme` middleware + `TrustProxies(at: '*')` so `asset()` uses the client's actual host instead of hardcoded `localhost:8080`.
- **Nginx X-Forwarded headers**: Added to fastcgi params for proper proxy support.
- **JS null guards**: `script.js` — guard `#map` and flatpickr elements. `graph.js` — guard `#hourlyGraph`. `homemap.js` — no guard needed (public homepage always has `#map`).
- **graph.js comma typo**: `input:not([readonly]),,``input:not([readonly]),`
### Browser Cache Issues
- Added `?h=<md5>` cache-busting suffixes to JS/CSS URLs
- Added `Cache-Control: no-cache, no-store, must-revalidate` headers via nginx for `.js`/`.css`
- Added `Cache-Control: no-cache, no-store, must-revalidate` via ForceRequestScheme middleware for HTML
- Added `<meta http-equiv="Cache-Control/Pragma/Expires">` no-cache tags in header blade
### Configuration
- **Timezone**: `TZ=Asia/Kuala_Lumpur` in `.env`, applied to all containers via `docker-compose.yml`
- **APP_TIMEZONE**: `Asia/Kuala_Lumpur` in `src/.env`, used by `config/app.php`
### Data
- PostgreSQL 18: Data dir path fixed to `/var/lib/postgresql/data`, PGDATA set, non-empty password
- Backup data restored from `backup/sides_20260528` (users, stations, rainfall, waterlevel, notification)
- `users.email` made nullable (admin, jpskedah have NULL emails)
- DB sequences reset to 300K+ to avoid duplicate key errors
- PostgreSQL RULEs for `ON CONFLICT DO NOTHING` on sensor tables
- Admin password reset to `sides2026` (hash compatible with Laravel)
## Quick Tasks Completed
| Date | Slug | Description | Status |
|------|------|-------------|--------|
| 2026-05-29 | browser-cache-fix | Added cache-busting hashes, no-cache headers, HTML meta tags | Complete |
| 2026-05-29 | login-passwords | Set known passwords for all 4 users, upgraded jpskedah to admin | Complete |
| 2026-05-29 | timezone-config | Added TZ=Asia/Kuala_Lumpur to all containers via docker-compose | Complete |

View File

@@ -1,12 +1,3 @@
# https://github.com/agungprsty/laravel-postgres-with-docker.git
version: "3.9"
networks:
sides_net:
name: sides_net
external: true
services:
app:
container_name: sides-app
@@ -20,17 +11,21 @@ services:
networks:
- sides_net
restart: unless-stopped
environment:
- TZ=${TZ:-Asia/Kuala_Lumpur}
postgres:
container_name: sides-db
image: postgres:18.1
restart: always
volumes:
- ./docker/postgres/data:/var/lib/postgres/data
- ./docker/postgres/data:/var/lib/postgresql/data
environment:
- POSTGRES_DB=${POSTGRES_DB}
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- PGDATA=/var/lib/postgresql/data
- TZ=${TZ:-Asia/Kuala_Lumpur}
ports:
- "5432:5432"
networks:
@@ -48,37 +43,26 @@ services:
- ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
networks:
- sides_net
environment:
- TZ=${TZ:-Asia/Kuala_Lumpur}
# Database management with pgAdmin
pgadmin:
image: dpage/pgadmin4
container_name: sides-pgAdmin
environment:
- PGADMIN_DEFAULT_EMAIL=${PGADMIN_EMAIL}
- PGADMIN_DEFAULT_PASSWORD=${PGADMIN_PASSWORD}
- TZ=${TZ:-Asia/Kuala_Lumpur}
ports:
- "5050:80"
depends_on:
- postgres
volumes:
- ./backup:/var/lib/pgadmin/storage/tck68000_gmail.com/backup
- pgadmin_data:/var/lib/pgadmin
networks:
- sides_net
restart: unless-stopped
# Database management with Adminer
adminer:
container_name: sides-adminer
image: adminer
restart: always
ports:
- "6060:8080"
depends_on:
- postgres
networks:
- sides_net
# Run with docker compose up -d
dozzle:
image: amir20/dozzle:latest
volumes:
@@ -86,14 +70,9 @@ services:
ports:
- 777:8080
environment:
# Uncomment to enable container actions (stop, start, restart). See https://dozzle.dev/guide/actions
- DOZZLE_ENABLE_ACTIONS=true
#
# Uncomment to allow access to container shells. See https://dozzle.dev/guide/shell
- DOZZLE_ENABLE_SHELL=true
#
# Uncomment to enable authentication. See https://dozzle.dev/guide/authentication
# - DOZZLE_AUTH_PROVIDER=simple
- DOZZLE_ENABLE_ACTIONS=true
- DOZZLE_ENABLE_SHELL=true
- TZ=${TZ:-Asia/Kuala_Lumpur}
filebrowser:
image: gtstef/filebrowser:stable
@@ -102,10 +81,16 @@ services:
- 8900:80
user: "0:0"
restart: unless-stopped
# user: filebrowser
volumes:
- ./filebrowser-data:/home/filebrowser/data
- ./files:/files
- /root/sides:/sides # Add other sources
- ./filebrowser-files:/files
- /root/sides:/sides
environment:
- "FILEBROWSER_CONFIG=data/config.yaml" # using our config file at ./data/config.yaml
- FILEBROWSER_CONFIG=data/config.yaml
networks:
sides_net:
name: sides_net
volumes:
pgadmin_data:

View File

@@ -9,7 +9,7 @@ server {
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://cdn.jsdelivr.net https://unpkg.com https://cdnjs.cloudflare.com; style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://unpkg.com https://fonts.googleapis.com; img-src 'self' data: https://*.tile.openstreetmap.org; font-src 'self' https://fonts.gstatic.com https://cdn.jsdelivr.net; connect-src 'self' https://*.tile.openstreetmap.org;" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://cdn.jsdelivr.net https://unpkg.com https://cdnjs.cloudflare.com https://code.jquery.com; style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://unpkg.com https://fonts.googleapis.com; img-src 'self' data: https://tile.openstreetmap.org https://*.tile.openstreetmap.org; font-src 'self' https://fonts.gstatic.com https://cdn.jsdelivr.net https://unpkg.com; connect-src 'self' https://tile.openstreetmap.org https://*.tile.openstreetmap.org https://cdn.jsdelivr.net https://cdnjs.cloudflare.com https://unpkg.com;" always;
charset utf-8;
@@ -24,6 +24,10 @@ server {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param HTTPS $https if_not_empty;
fastcgi_param X-Forwarded-Proto $scheme;
fastcgi_param X-Forwarded-Host $host;
fastcgi_param X-Forwarded-For $proxy_add_x_forwarded_for;
}
location / {
@@ -31,6 +35,13 @@ server {
gzip_static on;
}
location ~* \.(js|css)$ {
try_files $uri =404;
add_header Cache-Control "no-cache, no-store, must-revalidate";
add_header Pragma "no-cache";
add_header Expires "0";
}
location ~ /\.(?!well-known).* {
deny all;
}

View File

@@ -0,0 +1 @@
18

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

Binary file not shown.

View File

View File

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

Binary file not shown.

View File

View File

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More