Aug 27 - Add MySQL optimize and security check
This commit is contained in:
@@ -0,0 +1,205 @@
|
||||
"""
|
||||
Smoke coverage for the pages whose queries were rewritten during the database
|
||||
optimization pass: the dashboard, the issues list, and the reports overview.
|
||||
|
||||
These routes had no request-level tests, so a query rewrite that produced
|
||||
invalid SQL or a broken scope would only have surfaced in production. Each test
|
||||
here drives the real route through the test client for a role that exercises a
|
||||
DIFFERENT branch of the scoping code:
|
||||
|
||||
admin -- unscoped branch
|
||||
inspector -- InspectorAssignment / get_inspector_scope() branch
|
||||
customer -- CustomerAssignment / get_customer_scope() branch
|
||||
|
||||
The assertions are deliberately about behaviour that must hold (status code,
|
||||
scope isolation), not about markup.
|
||||
"""
|
||||
from datetime import timedelta
|
||||
|
||||
import pytest
|
||||
|
||||
from app import db as _db
|
||||
from app.models.issue import Issue
|
||||
from app.models.project import Project, CustomerAssignment
|
||||
from app.models.inspector_assignment import InspectorAssignment
|
||||
from app.utils.time_utils import now_eastern
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def make_issue(db):
|
||||
def _make(facility=None, area=None, severity='high', status='open',
|
||||
hours_ago=1, **kw):
|
||||
issue = Issue(
|
||||
facility_id=facility.id if facility else None,
|
||||
area_id=area.id if area else None,
|
||||
severity=severity,
|
||||
description=kw.pop('description', 'test issue'),
|
||||
status=status,
|
||||
reported_at=now_eastern() - timedelta(hours=hours_ago),
|
||||
)
|
||||
for k, v in kw.items():
|
||||
setattr(issue, k, v)
|
||||
db.session.add(issue)
|
||||
db.session.commit()
|
||||
return issue
|
||||
return _make
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def project(db):
|
||||
proj = Project(name='Contract A', active=True)
|
||||
db.session.add(proj)
|
||||
db.session.commit()
|
||||
return proj
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def other_project(db):
|
||||
proj = Project(name='Contract B', active=True)
|
||||
db.session.add(proj)
|
||||
db.session.commit()
|
||||
return proj
|
||||
|
||||
|
||||
# ── Dashboard ────────────────────────────────────────────────────────────────
|
||||
|
||||
@pytest.mark.parametrize('role', ['admin', 'director', 'project_manager', 'auditor'])
|
||||
def test_dashboard_renders_for_staff_roles(client, login, make_user,
|
||||
make_facility, make_issue,
|
||||
project, role):
|
||||
"""The card queries (severity / handler / SLA splits) build and run."""
|
||||
facility = make_facility(project=project)
|
||||
make_issue(facility=facility, severity='critical', hours_ago=100)
|
||||
make_issue(facility=facility, severity='low', status='in_progress')
|
||||
make_issue(facility=facility, status='resolved',
|
||||
resolved_at=now_eastern())
|
||||
|
||||
login(make_user(role=role))
|
||||
assert client.get('/').status_code == 200
|
||||
|
||||
|
||||
def test_dashboard_renders_for_scoped_inspector(client, login, make_user, db,
|
||||
make_facility, make_area,
|
||||
make_issue, project):
|
||||
inspector = make_user(role='inspector')
|
||||
db.session.add(InspectorAssignment(user_id=inspector.id,
|
||||
project_id=project.id))
|
||||
db.session.commit()
|
||||
|
||||
facility = make_facility(project=project)
|
||||
area = make_area(facility)
|
||||
make_issue(area=area, severity='high', hours_ago=50) # reached via area
|
||||
make_issue(facility=facility, severity='medium') # reached directly
|
||||
|
||||
login(inspector)
|
||||
assert client.get('/').status_code == 200
|
||||
|
||||
|
||||
def test_dashboard_renders_for_inspector_with_no_assignments(client, login,
|
||||
make_user):
|
||||
"""Strict scoping: no assignments must render an empty dashboard, not 500."""
|
||||
login(make_user(role='inspector'))
|
||||
assert client.get('/').status_code == 200
|
||||
|
||||
|
||||
def test_dashboard_renders_for_customer(client, login, make_user, db,
|
||||
make_facility, make_issue, project):
|
||||
customer = make_user(role='customer')
|
||||
facility = make_facility(project=project)
|
||||
db.session.add(CustomerAssignment(user_id=customer.id,
|
||||
project_id=project.id))
|
||||
db.session.commit()
|
||||
make_issue(facility=facility)
|
||||
|
||||
login(customer)
|
||||
assert client.get('/').status_code == 200
|
||||
|
||||
|
||||
# ── Issues list ──────────────────────────────────────────────────────────────
|
||||
|
||||
def test_issues_list_renders(client, login, make_user, make_facility,
|
||||
make_issue, project):
|
||||
facility = make_facility(project=project)
|
||||
make_issue(facility=facility)
|
||||
login(make_user(role='admin'))
|
||||
assert client.get('/issues/').status_code == 200
|
||||
|
||||
|
||||
@pytest.mark.parametrize('query', [
|
||||
'?facility_id=abc', # non-numeric -- used to raise ValueError -> 500
|
||||
'?facility_id=',
|
||||
'?facility_id=999999', # numeric but nonexistent
|
||||
'?contract_id=abc',
|
||||
'?issue_id=abc',
|
||||
'?severity=high&status=open',
|
||||
'?handler_type=vendor',
|
||||
'?unassigned=1',
|
||||
'?sla=breached',
|
||||
'?date_from=notadate&date_to=alsonot',
|
||||
])
|
||||
def test_issues_list_survives_malformed_filters(client, login, make_user,
|
||||
make_facility, make_issue,
|
||||
project, query):
|
||||
"""A hand-edited or stale query string must never 500 the list."""
|
||||
facility = make_facility(project=project)
|
||||
make_issue(facility=facility)
|
||||
login(make_user(role='admin'))
|
||||
assert client.get('/issues/' + query).status_code == 200
|
||||
|
||||
|
||||
def test_issues_list_scopes_a_customer_to_their_own_facilities(
|
||||
client, login, make_user, db, make_facility, make_issue,
|
||||
project, other_project):
|
||||
"""The scope filter still isolates customers after the query rewrite."""
|
||||
customer = make_user(role='customer')
|
||||
mine = make_facility(project=project, name='Mine')
|
||||
theirs = make_facility(project=other_project, name='Theirs')
|
||||
db.session.add(CustomerAssignment(user_id=customer.id,
|
||||
project_id=project.id))
|
||||
db.session.commit()
|
||||
|
||||
make_issue(facility=mine, description='visible to me')
|
||||
make_issue(facility=theirs, description='other customer only')
|
||||
|
||||
login(customer)
|
||||
body = client.get('/issues/').get_data(as_text=True)
|
||||
assert 'visible to me' in body
|
||||
assert 'other customer only' not in body
|
||||
|
||||
|
||||
# ── Reports overview ─────────────────────────────────────────────────────────
|
||||
|
||||
def test_reports_overview_renders_for_admin(client, login, make_user,
|
||||
make_facility, make_template,
|
||||
make_inspection, project):
|
||||
admin = make_user(role='admin')
|
||||
inspector = make_user(role='inspector')
|
||||
facility = make_facility(project=project)
|
||||
make_inspection(facility, inspector, make_template())
|
||||
|
||||
login(admin)
|
||||
assert client.get('/reports/').status_code == 200
|
||||
|
||||
|
||||
def test_reports_overview_inspector_scope_uses_subquery(
|
||||
client, login, make_user, db, make_facility, make_template,
|
||||
make_inspection, make_issue, project):
|
||||
"""_scope_issue() now filters via a subquery instead of an id list."""
|
||||
inspector = make_user(role='inspector')
|
||||
db.session.add(InspectorAssignment(user_id=inspector.id,
|
||||
project_id=project.id))
|
||||
db.session.commit()
|
||||
|
||||
facility = make_facility(project=project)
|
||||
insp = make_inspection(facility, inspector, make_template())
|
||||
make_issue(facility=facility, inspection_id=insp.id)
|
||||
|
||||
login(inspector)
|
||||
assert client.get('/reports/').status_code == 200
|
||||
|
||||
|
||||
def test_reports_overview_inspector_with_no_inspections(client, login,
|
||||
make_user):
|
||||
"""IN (empty subquery) must match nothing rather than error."""
|
||||
login(make_user(role='inspector'))
|
||||
assert client.get('/reports/').status_code == 200
|
||||
Reference in New Issue
Block a user