--ADDED security to apis
	--MARKED DONE to integrated apis
This commit is contained in:
george committed 2026-09-28 12:05:25 +05:30
1 parent f43eaee98f
commit 3be2f2b0ce
3 files changed
+126 -11

No files matched your search

+6
View File
@@ -92,3 +92,9 @@ DASHBOARD
| **RAM Usage** | Server memory pressure | % | | **RAM Usage** | Server memory pressure | % |
| **Disk Usage** | Remaining DB server disk | % | | **Disk Usage** | Remaining DB server disk | % |
| **Disk I/O** | Storage read/write activity | MB/s | | **Disk I/O** | Storage read/write activity | MB/s |
SPOKE (LIMIT)
CONNECTIVE (LIMIT)
PGEDGE (ENTRIPRISE VS OPENSOURCE)
+10
View File
@@ -20,3 +20,13 @@ source /home/george/Desktop/PROJECT26/psqlDB/venv/bin/activate
INSTALL IN DB, IF NOT DONE!!! INSTALL IN DB, IF NOT DONE!!!
CREATE EXTENSION IF NOT EXISTS pg_stat_statements; CREATE EXTENSION IF NOT EXISTS pg_stat_statements;
psutil.cpu_percent()
psutil.virtual_memory()
psutil.disk_usage()
const token = localStorage.getItem("token");
const socket = new WebSocket(
`ws://172.16.10.178:8000/ws/node/replication-health?token=${encodeURIComponent(token)}`
);
+110 -11
View File
@@ -1,7 +1,7 @@
import os import os
import uvicorn import uvicorn
from dotenv import load_dotenv from dotenv import load_dotenv
from fastapi import FastAPI,Depends, Header, HTTPException, status, WebSocket, WebSocketDisconnect from fastapi import FastAPI,Depends, Header, HTTPException, status, WebSocket, WebSocketDisconnect, WebSocketException
import psycopg2 import psycopg2
from jwt import ExpiredSignatureError, InvalidTokenError from jwt import ExpiredSignatureError, InvalidTokenError
import jwt import jwt
@@ -89,8 +89,42 @@ def verify_token(
) )
# JWT TOKEN VERIFICATION FOR WEBSOCKET CONNECTIONS
async def verify_websocket_token(websocket: WebSocket):
token = websocket.query_params.get("token")
if not token:
raise WebSocketException(
code=status.WS_1008_POLICY_VIOLATION,
reason="Authentication token missing"
)
try:
payload = jwt.decode(
token,
SECRET_KEY,
algorithms=[ALGORITHM],
)
return payload
except ExpiredSignatureError:
raise WebSocketException(
code=status.WS_1008_POLICY_VIOLATION,
reason="Token expired"
)
except InvalidTokenError:
raise WebSocketException(
code=status.WS_1008_POLICY_VIOLATION,
reason="Invalid token"
)
@app.get("/") @app.get("/")
@@ -215,9 +249,12 @@ def get_replication_health(data: NodeStatusRequest):
# "user": "postgres", # "user": "postgres",
# "password": "postgres" # "password": "postgres"
# } # }
#DONE
@app.websocket("/ws/node/replication-health") @app.websocket("/ws/node/replication-health")
async def replication_monitor(websocket: WebSocket): async def replication_monitor(websocket: WebSocket):
token_data = await verify_websocket_token(websocket)
# if token_data is None:
# return
await websocket.accept() await websocket.accept()
try: try:
raw_data = await websocket.receive_json() raw_data = await websocket.receive_json()
@@ -344,10 +381,12 @@ def get_database_uptime(
if conn: if conn:
conn.close() conn.close()
# DONE
@app.websocket("/ws/database/status") @app.websocket("/ws/database/status")
async def database_status_monitor(websocket: WebSocket): async def database_status_monitor(websocket: WebSocket):
token_data = await verify_websocket_token(websocket)
# if token_data is None:
# return
await websocket.accept() await websocket.accept()
try: try:
@@ -508,9 +547,12 @@ def get_connection_usage(data: DatabaseRequest):
conn.close() conn.close()
# WEB SOCKETS FOR ACTIVE CONNECTIONS MONITORING # WEB SOCKETS FOR ACTIVE CONNECTIONS MONITORING
# DONE
@app.websocket("/ws/database/active-connections") @app.websocket("/ws/database/active-connections")
async def database_active_connections_monitor(websocket: WebSocket): async def database_active_connections_monitor(websocket: WebSocket):
token_data = await verify_websocket_token(websocket)
# if token_data is None:
# return
await websocket.accept() await websocket.accept()
try: try:
@@ -725,9 +767,12 @@ def get_cache_hit_ratio(data: DatabaseRequest):
conn.close() conn.close()
#TPS AND CACHE HIT RATIO WEB SOCKET #TPS AND CACHE HIT RATIO WEB SOCKET
# DONE
@app.websocket("/ws/database/performance") @app.websocket("/ws/database/performance")
async def database_performance_monitor(websocket: WebSocket): async def database_performance_monitor(websocket: WebSocket):
token_data = await verify_websocket_token(websocket)
# if token_data is None:
# return
await websocket.accept() await websocket.accept()
try: try:
@@ -911,7 +956,9 @@ def get_database_deadlocks(data: DatabaseRequest):
# LOCKS AND DEADLOCKS WEB SOCKET # LOCKS AND DEADLOCKS WEB SOCKET
@app.websocket("/ws/database/locks-deadlocks") @app.websocket("/ws/database/locks-deadlocks")
async def database_locks_deadlocks_monitor(websocket: WebSocket): async def database_locks_deadlocks_monitor(websocket: WebSocket):
token_data = await verify_websocket_token(websocket)
# if token_data is None:
# return
await websocket.accept() await websocket.accept()
try: try:
@@ -1040,6 +1087,7 @@ def get_database_size(data: DatabaseRequest):
# API ENDPOINTS FOR DATABASE SIZE # API ENDPOINTS FOR DATABASE SIZE
#DONE
@app.post("/database/size") @app.post("/database/size")
def database_size( def database_size(
data: DatabaseRequest, data: DatabaseRequest,
@@ -1136,6 +1184,7 @@ def get_largest_tables(
# SHOWS THE LIST OF TABLES IN THE DATABASE SORTED BY SIZE # SHOWS THE LIST OF TABLES IN THE DATABASE SORTED BY SIZE
# DONE
@app.post("/database/largest-tables") @app.post("/database/largest-tables")
def database_largest_tables( def database_largest_tables(
data: DatabaseRequest, data: DatabaseRequest,
@@ -1216,6 +1265,7 @@ def get_index_size(data: DatabaseRequest):
# API ENDPOINT FOR INDEX SIZE REST API # API ENDPOINT FOR INDEX SIZE REST API
# DONE
@app.post("/database/index-size") @app.post("/database/index-size")
def database_index_size( def database_index_size(
data: DatabaseRequest, data: DatabaseRequest,
@@ -1338,9 +1388,12 @@ def get_tuple_reads_writes(data: DatabaseRequest):
conn.close() conn.close()
# TUPLE READS AND WRITES PER SECOND WEB SOCKET # TUPLE READS AND WRITES PER SECOND WEB SOCKET
# DONE
@app.websocket("/ws/database/tuple-activity") @app.websocket("/ws/database/tuple-activity")
async def database_tuple_activity_monitor(websocket: WebSocket): async def database_tuple_activity_monitor(websocket: WebSocket):
token_data = await verify_websocket_token(websocket)
if token_data is None:
return
await websocket.accept() await websocket.accept()
try: try:
@@ -1429,11 +1482,25 @@ def get_dead_tuples(data: DatabaseRequest):
n_live_tup, n_live_tup,
n_dead_tup, n_dead_tup,
last_vacuum, last_vacuum,
last_autovacuum last_autovacuum,
pg_total_relation_size(
quote_ident(schemaname) || '.' ||
quote_ident(relname)
) AS size_bytes,
ROUND(
pg_total_relation_size(
quote_ident(schemaname) || '.' ||
quote_ident(relname)
)::numeric
/ 1024 / 1024,
2
) AS size_mb
FROM pg_stat_user_tables FROM pg_stat_user_tables
WHERE n_dead_tup > 0
ORDER BY n_dead_tup DESC; ORDER BY size_bytes DESC;
""") """)
rows = cursor.fetchall() rows = cursor.fetchall()
@@ -1443,17 +1510,40 @@ def get_dead_tuples(data: DatabaseRequest):
for row in rows for row in rows
) )
total_size_bytes = sum(
row["size_bytes"] or 0
for row in rows
)
total_size_mb = round(
total_size_bytes / 1024 / 1024,
2
)
return { return {
"database_name": data.dbname, "database_name": data.dbname,
"table_count": len(rows),
"total_dead_tuples": total_dead_tuples, "total_dead_tuples": total_dead_tuples,
"total_table_size_bytes": total_size_bytes,
"total_table_size_mb": total_size_mb,
"tables": [ "tables": [
{ {
"schema": row["schemaname"], "schema": row["schemaname"],
"table_name": row["table_name"], "table_name": row["table_name"],
"live_tuples": row["n_live_tup"], "live_tuples": row["n_live_tup"],
"dead_tuples": row["n_dead_tup"], "dead_tuples": row["n_dead_tup"],
"size_bytes": row["size_bytes"],
"size_mb": float(row["size_mb"]),
"last_vacuum": "last_vacuum":
row["last_vacuum"].isoformat() row["last_vacuum"].isoformat()
if row["last_vacuum"] if row["last_vacuum"]
@@ -1472,8 +1562,17 @@ def get_dead_tuples(data: DatabaseRequest):
return { return {
"database_name": data.dbname, "database_name": data.dbname,
"table_count": None,
"total_dead_tuples": None, "total_dead_tuples": None,
"total_table_size_bytes": None,
"total_table_size_mb": None,
"tables": [], "tables": [],
"error": str(e) "error": str(e)
} }