fix: correct tojson|safe usage in templates and update validator
- Remove |safe from |tojson in HTML attributes (x-data) - quotes must become " for browsers to parse correctly - Update LANG-002 and LANG-003 architecture rules to document correct |tojson usage patterns: - HTML attributes: |tojson (no |safe) - Script blocks: |tojson|safe - Fix validator to warn when |tojson|safe is used in x-data (breaks HTML attribute parsing) - Improve code quality across services, APIs, and tests 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -84,13 +84,17 @@ def init_log_settings():
|
||||
)
|
||||
|
||||
if existing:
|
||||
print(f"✓ Setting '{setting_data['key']}' already exists (value: {existing.value})")
|
||||
print(
|
||||
f"✓ Setting '{setting_data['key']}' already exists (value: {existing.value})"
|
||||
)
|
||||
updated_count += 1
|
||||
else:
|
||||
setting = AdminSetting(**setting_data)
|
||||
db.add(setting)
|
||||
created_count += 1
|
||||
print(f"✓ Created setting '{setting_data['key']}' = {setting_data['value']}")
|
||||
print(
|
||||
f"✓ Created setting '{setting_data['key']}' = {setting_data['value']}"
|
||||
)
|
||||
|
||||
db.commit()
|
||||
|
||||
|
||||
@@ -30,7 +30,6 @@ Environment Variables:
|
||||
This script is idempotent when run normally.
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import sys
|
||||
from datetime import UTC, datetime
|
||||
from decimal import Decimal
|
||||
@@ -57,7 +56,9 @@ from models.database.company import Company
|
||||
from models.database.customer import Customer, CustomerAddress
|
||||
from models.database.marketplace_import_job import MarketplaceImportJob
|
||||
from models.database.marketplace_product import MarketplaceProduct
|
||||
from models.database.marketplace_product_translation import MarketplaceProductTranslation
|
||||
from models.database.marketplace_product_translation import (
|
||||
MarketplaceProductTranslation,
|
||||
)
|
||||
from models.database.order import Order, OrderItem
|
||||
from models.database.product import Product
|
||||
from models.database.user import User
|
||||
@@ -263,7 +264,9 @@ def reset_all_data(db: Session):
|
||||
sys.exit(0)
|
||||
except EOFError:
|
||||
print_error("No interactive terminal available.")
|
||||
print(" Use FORCE_RESET=true to skip confirmation in non-interactive mode.")
|
||||
print(
|
||||
" Use FORCE_RESET=true to skip confirmation in non-interactive mode."
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
# Delete in correct order (respecting foreign keys)
|
||||
@@ -367,9 +370,7 @@ def create_demo_companies(db: Session, auth_manager: AuthManager) -> list[Compan
|
||||
db.flush()
|
||||
|
||||
companies.append(company)
|
||||
print_success(
|
||||
f"Created company: {company.name} (Owner: {owner_user.email})"
|
||||
)
|
||||
print_success(f"Created company: {company.name} (Owner: {owner_user.email})")
|
||||
|
||||
db.flush()
|
||||
return companies
|
||||
@@ -456,7 +457,9 @@ def create_demo_vendors(
|
||||
if vendor_data.get("custom_domain"):
|
||||
domain = VendorDomain(
|
||||
vendor_id=vendor.id,
|
||||
domain=vendor_data["custom_domain"], # ✅ Field is 'domain', not 'domain_name'
|
||||
domain=vendor_data[
|
||||
"custom_domain"
|
||||
], # ✅ Field is 'domain', not 'domain_name'
|
||||
is_verified=True, # Auto-verified for demo
|
||||
is_primary=True,
|
||||
verification_token=None,
|
||||
@@ -695,7 +698,7 @@ def print_summary(db: Session):
|
||||
print(f" Vendors: {len(company.vendors) if company.vendors else 0}")
|
||||
print(f" Status: {'✓ Active' if company.is_active else '✗ Inactive'}")
|
||||
if company.is_verified:
|
||||
print(f" Verified: ✓")
|
||||
print(" Verified: ✓")
|
||||
|
||||
# Show vendor details
|
||||
vendors = db.query(Vendor).all()
|
||||
|
||||
@@ -18,6 +18,7 @@ from pathlib import Path
|
||||
project_root = Path(__file__).parent.parent
|
||||
sys.path.insert(0, str(project_root))
|
||||
|
||||
|
||||
def test_logging_endpoints():
|
||||
"""Test logging-related API endpoints."""
|
||||
print("\n" + "=" * 70)
|
||||
@@ -34,7 +35,7 @@ def test_logging_endpoints():
|
||||
# Create an exception log
|
||||
try:
|
||||
raise ValueError("Test exception for logging")
|
||||
except Exception as e:
|
||||
except Exception:
|
||||
logging.error("Test exception logging", exc_info=True)
|
||||
|
||||
print(" ✓ Test logs created")
|
||||
@@ -69,9 +70,12 @@ def test_logging_endpoints():
|
||||
print(f" ✓ Database logs count: {count}")
|
||||
|
||||
if count > 0:
|
||||
recent = db.query(ApplicationLog).order_by(
|
||||
ApplicationLog.timestamp.desc()
|
||||
).limit(5).all()
|
||||
recent = (
|
||||
db.query(ApplicationLog)
|
||||
.order_by(ApplicationLog.timestamp.desc())
|
||||
.limit(5)
|
||||
.all()
|
||||
)
|
||||
|
||||
print(" Recent logs:")
|
||||
for log in recent:
|
||||
@@ -90,9 +94,15 @@ def test_logging_endpoints():
|
||||
|
||||
db = SessionLocal()
|
||||
try:
|
||||
log_level = admin_settings_service.get_setting_value(db, "log_level", "INFO")
|
||||
max_size = admin_settings_service.get_setting_value(db, "log_file_max_size_mb", 10)
|
||||
retention = admin_settings_service.get_setting_value(db, "db_log_retention_days", 30)
|
||||
log_level = admin_settings_service.get_setting_value(
|
||||
db, "log_level", "INFO"
|
||||
)
|
||||
max_size = admin_settings_service.get_setting_value(
|
||||
db, "log_file_max_size_mb", 10
|
||||
)
|
||||
retention = admin_settings_service.get_setting_value(
|
||||
db, "db_log_retention_days", 30
|
||||
)
|
||||
|
||||
print(f" ✓ Log Level: {log_level}")
|
||||
print(f" ✓ Max File Size: {max_size} MB")
|
||||
@@ -118,6 +128,7 @@ def test_logging_endpoints():
|
||||
if __name__ == "__main__":
|
||||
# Set up logging first
|
||||
from app.core.logging import setup_logging
|
||||
|
||||
setup_logging()
|
||||
|
||||
success = test_logging_endpoints()
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -56,7 +56,7 @@ class FileResult:
|
||||
def status(self) -> str:
|
||||
if self.errors > 0:
|
||||
return "FAILED"
|
||||
elif self.warnings > 0:
|
||||
if self.warnings > 0:
|
||||
return "PASSED*"
|
||||
return "PASSED"
|
||||
|
||||
@@ -64,7 +64,7 @@ class FileResult:
|
||||
def status_icon(self) -> str:
|
||||
if self.errors > 0:
|
||||
return "❌"
|
||||
elif self.warnings > 0:
|
||||
if self.warnings > 0:
|
||||
return "⚠️"
|
||||
return "✅"
|
||||
|
||||
@@ -220,17 +220,19 @@ class BaseValidator:
|
||||
# Look for the function definition
|
||||
for j in range(i + 1, min(i + 10, len(lines))):
|
||||
next_line = lines[j].strip()
|
||||
if next_line.startswith("def ") or next_line.startswith("async def "):
|
||||
if next_line.startswith("def ") or next_line.startswith(
|
||||
"async def "
|
||||
):
|
||||
# Extract function name
|
||||
match = re.search(r"(?:async\s+)?def\s+(\w+)", next_line)
|
||||
if match:
|
||||
func_name = match.group(1)
|
||||
results.append((i + 1, decorator, func_name))
|
||||
break
|
||||
elif next_line.startswith("@"):
|
||||
if next_line.startswith("@"):
|
||||
# Multiple decorators - continue to next
|
||||
continue
|
||||
elif next_line and not next_line.startswith("#"):
|
||||
if next_line and not next_line.startswith("#"):
|
||||
# Non-decorator, non-comment line - stop looking
|
||||
break
|
||||
i += 1
|
||||
@@ -303,7 +305,7 @@ class BaseValidator:
|
||||
Returns (is_valid, error_message) tuple.
|
||||
"""
|
||||
try:
|
||||
with open(file_path, "r", encoding="utf-8") as f:
|
||||
with open(file_path, encoding="utf-8") as f:
|
||||
json.load(f)
|
||||
return True, ""
|
||||
except json.JSONDecodeError as e:
|
||||
|
||||
Reference in New Issue
Block a user