To enhance the existing Community Alert - Real-Time Emergency Response System with features like
**geolocation**, **push notifications**, **encryption**, an **admin dashboard**, and persistent data
storage in a real database (such as PostgreSQL), we'll need to make a few changes. Below is an extended
version of the application incorporating these features.
We'll break down the enhancements as follows:
1. **Geolocation**: Add the ability for users to send their location when creating an alert. This can be
achieved through the browser's geolocation API.
2. **Push Notifications**: Implement push notifications using Firebase Cloud Messaging (FCM) for web.
3. **Encryption**: Use SSL (HTTPS) and encrypted communication for WebSockets.
4. **Admin Dashboard**: Provide an admin interface where admins can view users, alerts, and manage
the system.
5. **Database Integration (PostgreSQL)**: Replace mock databases with PostgreSQL for persistent
storage.
1. Database Setup (PostgreSQL)
Ensure you have PostgreSQL installed. You'll also need the `psycopg2` package for Python to interact
with PostgreSQL.
```bash
pip install psycopg2-binary flask_sqlalchemy flask_migrate
```
### PostgreSQL Schema:
Here is the schema we will use for our **users** and **alerts**:
```sql
CREATE TABLE users (
id SERIAL PRIMARY KEY,
username VARCHAR(100) UNIQUE NOT NULL,
password TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE alerts (
id SERIAL PRIMARY KEY,
username VARCHAR(100) NOT NULL,
message TEXT NOT NULL,
alert_type VARCHAR(50) NOT NULL,
latitude DOUBLE PRECISION,
longitude DOUBLE PRECISION,
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
2. Enhanced Flask Backend (`backend.py`)
```python
from flask import Flask, jsonify, request, render_template, redirect, url_for
from flask_sqlalchemy import SQLAlchemy
from flask_socketio import SocketIO, emit, join_room, leave_room
from werkzeug.security import generate_password_hash, check_password_hash
from datetime import datetime
import os
import psycopg2
import firebase_admin
from firebase_admin import messaging, credentials
# Initialize Flask app and extensions
app = Flask(__name__)
app.config['SECRET_KEY'] = os.urandom(24)
app.config['SQLALCHEMY_DATABASE_URI'] =
'postgresql://your_db_user:your_db_password@localhost/community_alert_db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
socketio = SocketIO(app, cors_allowed_origins="*")
db = SQLAlchemy(app)
# Firebase Admin SDK Setup for Push Notifications
cred = credentials.Certificate("path/to/your/firebase-admin-sdk.json")
firebase_admin.initialize_app(cred)
# Models for User and Alert
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(100), unique=True, nullable=False)
password = db.Column(db.String(255), nullable=False)
created_at = db.Column(db.DateTime, default=datetime.utcnow)
class Alert(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(100), nullable=False)
message = db.Column(db.Text, nullable=False)
alert_type = db.Column(db.String(50), nullable=False)
latitude = db.Column(db.Float, nullable=True)
longitude = db.Column(db.Float, nullable=True)
timestamp = db.Column(db.DateTime, default=datetime.utcnow)
# Helper functions
def authenticate(username, password):
user = User.query.filter_by(username=username).first()
if user and check_password_hash(user.password, password):
return True
return False
@app.route('/')
def index():
return render_template('index.html')
@app.route('/register', methods=['POST'])
def register_user():
data = request.get_json()
username = data['username']
password = data['password']
if User.query.filter_by(username=username).first():
return jsonify({"message": "User already exists!"}), 400
hashed_password = generate_password_hash(password)
new_user = User(username=username, password=hashed_password)
db.session.add(new_user)
db.session.commit()
return jsonify({"message": "User registered successfully!"}), 201
@app.route('/login', methods=['POST'])
def login_user():
data = request.get_json()
username = data['username']
password = data['password']
if authenticate(username, password):
return jsonify({"message": "Login successful!"}), 200
return jsonify({"message": "Invalid credentials!"}), 401
@app.route('/create_alert', methods=['POST'])
def create_alert():
data = request.get_json()
username = data['username']
alert_message = data['message']
alert_type = data.get('type', 'General')
latitude = data.get('latitude')
longitude = data.get('longitude')
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
alert = Alert(
username=username,
message=alert_message,
alert_type=alert_type,
latitude=latitude,
longitude=longitude
db.session.add(alert)
db.session.commit()
# Send Push Notification via Firebase Cloud Messaging (FCM)
message = messaging.Message(
notification=messaging.Notification(
title="New Emergency Alert",
body=f"{username}: {alert_message} at {alert_type}."
),
topic="community_alerts" # Subscribers to this topic will receive the alert
messaging.send(message)
# Broadcast alert to all connected clients via WebSocket
socketio.emit('new_alert', {
'username': username,
'message': alert_message,
'type': alert_type,
'latitude': latitude,
'longitude': longitude,
'timestamp': timestamp
}, broadcast=True)
return jsonify({"message": "Alert created successfully!"}), 200
# WebSocket event handlers
@socketio.on('connect')
def handle_connect():
print("A user connected.")
@socketio.on('disconnect')
def handle_disconnect():
print("A user disconnected.")
# Admin Dashboard
@app.route('/admin')
def admin_dashboard():
if not request.cookies.get('admin_token'):
return redirect(url_for('login'))
alerts = Alert.query.all()
users = User.query.all()
return render_template('admin_dashboard.html', users=users, alerts=alerts)
# Run the app
if __name__ == "__main__":
socketio.run(app, host='0.0.0.0', port=5000, ssl_context=('cert.pem', 'key.pem')) # SSL enabled
```
3. Frontend Enhancements
In the **frontend**, we need to add geolocation features and integrate Firebase for push notifications.
`templates/index.html`
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Community Alert System</title>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/socket.io.min.js"></script>
<script src="https://www.gstatic.com/firebasejs/9.0.0/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/9.0.0/firebase-messaging.js"></script>
<script>
const firebaseConfig = {
apiKey: "your-api-key",
authDomain: "your-app.firebaseapp.com",
projectId: "your-project-id",
storageBucket: "your-app.appspot.com",
messagingSenderId: "your-sender-id",
appId: "your-app-id"
};
firebase.initializeApp(firebaseConfig);
const messaging = firebase.messaging();
// Request permission for Push Notifications
messaging.requestPermission().then(() => {
return messaging.getToken();
}).then((token) => {
console.log("FCM Token:", token);
}).catch((err) => {
console.error("Error getting FCM token", err);
});
// Geolocation feature for emergency alerts
function getLocation() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(sendAlertWithLocation);
} else {
alert("Geolocation is not supported by this browser.");
function sendAlertWithLocation(position) {
const latitude = position.coords.latitude;
const longitude = position.coords.longitude;
const alertMessage = document.getElementById('alert_message').value;
// Send alert to the server with location
fetch('/create_alert', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
username: "user123",
message: alertMessage,
latitude: latitude,
longitude: longitude
})
}).then(response => response.json())
.then(data => console.log(data.message));
}
// Setup socket connection
var socket = io.connect('https://localhost:5000');
socket.on('new_alert', function(alert) {
console.log(alert);
});
// Add geolocation to the button
document.getElementById("send_alert_btn").addEventListener("click", function() {
getLocation();
});
</script>
</head>
<body>
<h1>Community Alert System</h1>
<div>
<h2>Login</h2>
<input type="text" id="username" placeholder="Username">
<input type="password" id="password" placeholder="Password">
<button onclick="login()">Login</button>
</div>
<div>
<h2>Create Alert</h2>
<textarea id="alert_message" placeholder="Describe emergency..." rows="4"
cols="50"></textarea><br>
<button id="send_alert_btn">Send Alert with Location</button>
</div>
<div id="alerts"></div>
</body>
</html>
```
4. Admin Dashboard
Create a basic admin dashboard where the admin can view and manage users and alerts.
#### `templates/admin_dashboard.html`
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Admin Dashboard</title>
</head>
<body>
<h1>Admin Dashboard</h1>
<h2>Users</h2>
<ul>
{% for user in users %}
<li>{{ user.username }} - Registered at {{ user.created_at }}</li>
{% endfor %}
</ul>
<h2>Alerts</h2>
<ul>
{% for alert in alerts %}
<li>{{ alert.username }} - {{ alert.message }} ({{ alert.timestamp }})</li>
{% endfor %}
</ul>
</body>
</html>
```
5. Setting Up SSL (HTTPS)
To enable encryption for your WebSocket and HTTP routes, use SSL certificates. You can obtain free SSL
certificates via **Let's Encrypt** or generate self-signed certificates for local testing.
In the `socketio.run()` command, specify the paths to your SSL certificates:
```python
socketio.run(app, host='0.0.0.0', port=5000, ssl_context=('cert.pem', 'key.pem'))
```
6. Summary of Enhancements:
- **Geolocation**: Alerts now include geographic coordinates (latitude and longitude).
- **Push Notifications**: Integrated Firebase Cloud Messaging (FCM) to send alerts as push notifications
to all users.
- **WebSocket Encryption**: The app runs on HTTPS with WebSocket encryption, ensuring secure
communication.
- **Admin Dashboard**: Admins can manage users and view all alerts in a centralized dashboard.
- **Persistent Storage**: The app now uses PostgreSQL for user and alert persistence, enabling long-
term data storage.