mirror of
https://github.com/Sea-Haven-Industries/procurement-ingest.git
synced 2026-10-01 03:03:13 +00:00
Harden WO web UI and fix JS-context XSS in both dashboards
- Use json.dumps for onclick URLs to prevent JS string breakout - Add .lower() to WO render_badge color lookup matching PO pattern - Add pagination to get_comments query - Cap get_work_orders to 500 results matching PO pattern
This commit is contained in:
parent
4ba5c37f47
commit
57bcec5a2e
2 changed files with 17 additions and 10 deletions
|
|
@ -5,6 +5,7 @@ Serves a simple HTML dashboard for viewing purchase orders.
|
|||
Accessed via Lambda Function URL.
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
from decimal import Decimal
|
||||
from html import escape as esc
|
||||
|
|
@ -195,7 +196,7 @@ def render_po_list(purchase_orders):
|
|||
processed = esc((po.get("processed_at") or "")[:16])
|
||||
|
||||
rows += f"""
|
||||
<tr style="border-bottom:1px solid #f1f5f9;cursor:pointer;" onclick="window.location='/po?id={po_number}'">
|
||||
<tr style="border-bottom:1px solid #f1f5f9;cursor:pointer;" onclick="window.location={esc(json.dumps(f'/po?id={po.get("po_number", "")}'), quote=True)}">
|
||||
<td style="padding:12px;font-weight:500;color:#3b82f6;">{po_number}</td>
|
||||
<td style="padding:12px;">{supplier}</td>
|
||||
<td style="padding:12px;font-weight:500;">{site_code}</td>
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ Serves a simple HTML dashboard for viewing work orders and comments.
|
|||
Accessed via Lambda Function URL.
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
from html import escape as esc
|
||||
|
||||
|
|
@ -16,7 +17,7 @@ WORK_ORDERS_TABLE = os.environ.get("WORK_ORDERS_TABLE", "WorkOrders")
|
|||
COMMENTS_TABLE = os.environ.get("COMMENTS_TABLE", "WorkOrderComments")
|
||||
|
||||
|
||||
def get_work_orders():
|
||||
def get_work_orders(limit=500):
|
||||
table = dynamodb.Table(WORK_ORDERS_TABLE)
|
||||
items = []
|
||||
response = table.scan()
|
||||
|
|
@ -25,16 +26,21 @@ def get_work_orders():
|
|||
response = table.scan(ExclusiveStartKey=response["LastEvaluatedKey"])
|
||||
items.extend(response.get("Items", []))
|
||||
items.sort(key=lambda x: x.get("updated_at", ""), reverse=True)
|
||||
return items
|
||||
return items[:limit]
|
||||
|
||||
|
||||
def get_comments(work_order_id):
|
||||
table = dynamodb.Table(COMMENTS_TABLE)
|
||||
response = table.query(
|
||||
KeyConditionExpression="work_order_id = :woid",
|
||||
ExpressionAttributeValues={":woid": work_order_id},
|
||||
)
|
||||
items = response.get("Items", [])
|
||||
items = []
|
||||
kwargs = {
|
||||
"KeyConditionExpression": "work_order_id = :woid",
|
||||
"ExpressionAttributeValues": {":woid": work_order_id},
|
||||
}
|
||||
response = table.query(**kwargs)
|
||||
items.extend(response.get("Items", []))
|
||||
while "LastEvaluatedKey" in response:
|
||||
response = table.query(**kwargs, ExclusiveStartKey=response["LastEvaluatedKey"])
|
||||
items.extend(response.get("Items", []))
|
||||
items.sort(key=lambda x: x.get("created_at", ""), reverse=True)
|
||||
return items
|
||||
|
||||
|
|
@ -42,7 +48,7 @@ def get_comments(work_order_id):
|
|||
def render_badge(value, color_map):
|
||||
if not value:
|
||||
value = "unknown"
|
||||
color = color_map.get(value, "#9ca3af")
|
||||
color = color_map.get(value.lower(), "#9ca3af")
|
||||
label = esc(value.replace("_", " ").title())
|
||||
return f'<span style="background:{color};color:#fff;padding:2px 10px;border-radius:12px;font-size:12px;font-weight:500;">{label}</span>'
|
||||
|
||||
|
|
@ -168,7 +174,7 @@ def render_work_orders_list(work_orders):
|
|||
updated = esc((wo.get("updated_at") or "")[:16])
|
||||
|
||||
rows += f"""
|
||||
<tr style="border-bottom:1px solid #f1f5f9;cursor:pointer;" onclick="window.location='/wo?id={wo_id}'">
|
||||
<tr style="border-bottom:1px solid #f1f5f9;cursor:pointer;" onclick="window.location={esc(json.dumps(f'/wo?id={wo.get("work_order_id", "")}'), quote=True)}">
|
||||
<td style="padding:12px;font-weight:500;color:#3b82f6;">{wo_id}</td>
|
||||
<td style="padding:12px;max-width:250px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;">{desc}</td>
|
||||
<td style="padding:12px;">{site}</td>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue