Aug 27 - Add MySQL optimize and security check

This commit is contained in:
2026-08-27 17:36:28 -04:00
parent ba10ec42e0
commit b7bc0f0335
16 changed files with 1524 additions and 58 deletions
+14 -4
View File
@@ -17,6 +17,16 @@ bp = Blueprint('dashboard', __name__)
logger = logging.getLogger(__name__)
# Columns the dashboard actually reads off an issue row. The cards below need
# counts and buckets, never a hydrated Issue — loading the full entity pulls the
# description TEXT and three JSON photo columns for every open issue in scope,
# on every dashboard load, and registers each one in the identity map.
# A Row exposes the same attribute names, so _handler_split() and sla_status()
# work against these unchanged.
_ISSUE_CARD_COLS = (Issue.id, Issue.severity, Issue.status,
Issue.reported_at, Issue.handler_type)
def _handler_split(issues):
"""Count a list of Issues by handler_type (phase35). Rows default to
'internal' when unset. Returns a dict keyed internal/facility/vendor."""
@@ -102,7 +112,7 @@ def index():
))
# Single query — derive count from the list to avoid hitting the DB twice
open_issues_all = open_issues_q.all()
open_issues_all = open_issues_q.with_entities(*_ISSUE_CARD_COLS).all()
open_issues = len(open_issues_all)
severity_breakdown = {
'critical': sum(1 for i in open_issues_all if i.severity == 'critical'),
@@ -224,7 +234,7 @@ def index():
elif is_customer and not customer_facility_ids:
all_open_issues = []
else:
all_open_issues = sla_q.all()
all_open_issues = sla_q.with_entities(*_ISSUE_CARD_COLS).all()
sla_breached = sum(1 for i in all_open_issues if sla_status(i) == 'breached')
sla_at_risk = sum(1 for i in all_open_issues if sla_status(i) == 'at_risk')
@@ -250,7 +260,7 @@ def index():
Issue.facility_id.in_(customer_facility_ids),
_AreaT.facility_id.in_(customer_facility_ids),
))
opened_today_all = opened_today_q.all()
opened_today_all = opened_today_q.with_entities(*_ISSUE_CARD_COLS).all()
issues_opened_today = len(opened_today_all)
opened_today_handler = _handler_split(opened_today_all)
@@ -331,7 +341,7 @@ def index():
))
elif is_customer:
unassigned_q = unassigned_q.filter(False) # not relevant for customers
unassigned_all = unassigned_q.all()
unassigned_all = unassigned_q.with_entities(*_ISSUE_CARD_COLS).all()
unassigned_open = len(unassigned_all)
unassigned_handler = _handler_split(unassigned_all)
+4 -2
View File
@@ -253,7 +253,8 @@ def index():
q = q.filter(Inspection.status == status_filter)
if contract_filter.isdigit():
_contract_fids = [
f.id for f in Facility.query.filter_by(project_id=int(contract_filter)).all()
fid for (fid,) in db.session.query(Facility.id)
.filter(Facility.project_id == int(contract_filter)).all()
]
q = q.filter(Inspection.facility_id.in_(_contract_fids)) if _contract_fids else q.filter(False)
if facility_filter.isdigit():
@@ -1243,7 +1244,8 @@ def export_list_pdf():
q = q.filter(Inspection.status == status_filter)
if contract_filter.isdigit():
_contract_fids = [
f.id for f in Facility.query.filter_by(project_id=int(contract_filter)).all()
fid for (fid,) in db.session.query(Facility.id)
.filter(Facility.project_id == int(contract_filter)).all()
]
q = q.filter(Inspection.facility_id.in_(_contract_fids)) if _contract_fids else q.filter(False)
if facility_filter.isdigit():
+10 -7
View File
@@ -166,13 +166,14 @@ def export_list_pdf():
date_to_filter = ''
if contract_filter.isdigit():
_contract_fids = [
f.id for f in Facility.query.filter_by(project_id=int(contract_filter)).all()
fid for (fid,) in db.session.query(Facility.id)
.filter(Facility.project_id == int(contract_filter)).all()
]
q = q.filter(db.or_(
Issue.facility_id.in_(_contract_fids),
Area.facility_id.in_(_contract_fids),
)) if _contract_fids else q.filter(False)
if facility_filter:
if facility_filter.isdigit():
fid = int(facility_filter)
q = q.filter(db.or_(Issue.facility_id == fid, Area.facility_id == fid))
if reporter_filter.isdigit():
@@ -201,7 +202,7 @@ def export_list_pdf():
p = db.session.get(Project, int(contract_filter))
if p:
filter_parts.append(f'Contract: {p.name}')
if facility_filter:
if facility_filter.isdigit():
f = db.session.get(Facility, int(facility_filter))
if f:
filter_parts.append(f'Facility: {f.name}')
@@ -303,7 +304,8 @@ def index():
date_to_filter = ''
if contract_filter.isdigit():
_contract_fids = [
f.id for f in Facility.query.filter_by(project_id=int(contract_filter)).all()
fid for (fid,) in db.session.query(Facility.id)
.filter(Facility.project_id == int(contract_filter)).all()
]
q = q.filter(db.or_(
Issue.facility_id.in_(_contract_fids),
@@ -311,7 +313,7 @@ def index():
)) if _contract_fids else q.filter(False)
if reporter_filter.isdigit():
q = q.filter(Issue.reported_by == int(reporter_filter))
if facility_filter:
if facility_filter.isdigit():
fid = int(facility_filter)
q = q.filter(
db.or_(
@@ -338,8 +340,9 @@ def index():
# can render the following badge and inline unfollow button without an
# additional query per row.
followed_ids = {
f.issue_id
for f in IssueFollower.query.filter_by(user_id=current_user.id).all()
iid for (iid,) in
db.session.query(IssueFollower.issue_id)
.filter(IssueFollower.user_id == current_user.id).all()
}
# Facilities for the filter dropdown — scoped for inspectors/customers,
+19 -19
View File
@@ -74,23 +74,29 @@ def index():
if current_user.role in ('admin', 'director', 'project_manager'):
inspector_filter = request.args.get('inspector_id', type=int) or None
# Pre-compute inspection ID sets used by _scope_issue to avoid join conflicts.
inspector_inspection_ids = [] # own inspections (inspector role)
filter_inspection_ids = None # filtered inspector's inspections (admin/dir/PM)
# Scope issues by the relevant inspector's inspections, as a SUBQUERY rather
# than a materialised id list. The previous form pulled every inspection id
# that inspector had ever performed into Python and sent them straight back
# as a literal IN (1, 2, 3, ... N): the round trip is wasted, the statement
# grows without bound with the inspector's history, and a long enough list
# eventually trips max_allowed_packet. A subquery is also still a single
# statement, so the "avoid join conflicts" reason for pre-computing holds.
#
# IN (empty subquery) already matches nothing, so the explicit empty-list
# guards the old code needed are gone rather than merely moved.
inspector_insp_subq = None
if is_inspector:
inspector_inspection_ids = [
row[0] for row in
inspector_insp_subq = (
db.session.query(Inspection.id)
.filter(Inspection.inspector_id == current_user.id)
.all()
]
.scalar_subquery()
)
elif inspector_filter:
filter_inspection_ids = [
row[0] for row in
inspector_insp_subq = (
db.session.query(Inspection.id)
.filter(Inspection.inspector_id == inspector_filter)
.all()
]
.scalar_subquery()
)
def _scope_insp(q):
if is_inspector:
@@ -104,14 +110,8 @@ def index():
return q
def _scope_issue(q):
if is_inspector:
if not inspector_inspection_ids:
return q.filter(False)
return q.filter(Issue.inspection_id.in_(inspector_inspection_ids))
if filter_inspection_ids is not None:
if not filter_inspection_ids:
return q.filter(False)
return q.filter(Issue.inspection_id.in_(filter_inspection_ids))
if inspector_insp_subq is not None:
return q.filter(Issue.inspection_id.in_(inspector_insp_subq))
if customer_facility_ids is not None:
if not customer_facility_ids:
return q.filter(False)