feat:
--ADDED security to apis --MARKED DONE to integrated apis
This commit is contained in:
1 parent
f43eaee98f
commit
3be2f2b0ce
3 files changed
+127
-12
No files matched your search
@@ -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)
|
||||||
+11
-1
@@ -19,4 +19,14 @@ 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)}`
|
||||||
|
);
|
||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user