Replace all ~1,086 occurrences of Wizamart/wizamart/WIZAMART/WizaMart with Orion/orion/ORION across 184 files. This includes database identifiers, email addresses, domain references, R2 bucket names, DNS prefixes, encryption salt, Celery app name, config defaults, Docker configs, CI configs, documentation, seed data, and templates. Renames homepage-wizamart.html template to homepage-orion.html. Fixes duplicate file_pattern key in api.yaml architecture rule. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
412 lines
13 KiB
Python
412 lines
13 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Show all platform, admin, store, and storefront URLs.
|
|
|
|
Queries the database for platforms, stores, and custom domains,
|
|
then prints all accessible URLs for both development and production.
|
|
|
|
Usage:
|
|
python scripts/show_urls.py # Show all URLs
|
|
python scripts/show_urls.py --dev # Development URLs only
|
|
python scripts/show_urls.py --prod # Production URLs only
|
|
python scripts/show_urls.py --check # Check dev URLs with curl
|
|
"""
|
|
|
|
import argparse
|
|
import subprocess
|
|
import sys
|
|
|
|
from sqlalchemy import text
|
|
|
|
from app.core.config import settings
|
|
from app.core.database import SessionLocal
|
|
|
|
DEV_BASE = "http://localhost:9999"
|
|
SEPARATOR = "─" * 72
|
|
|
|
|
|
def get_platforms(db):
|
|
"""Get all platforms."""
|
|
return db.execute(
|
|
text(
|
|
"SELECT id, code, name, domain, path_prefix, is_active "
|
|
"FROM platforms ORDER BY code"
|
|
)
|
|
).fetchall()
|
|
|
|
|
|
def get_stores(db):
|
|
"""Get all stores with merchant info."""
|
|
return db.execute(
|
|
text(
|
|
"SELECT v.id, v.store_code, v.name, v.subdomain, v.is_active, "
|
|
" c.name AS merchant_name "
|
|
"FROM stores v "
|
|
"LEFT JOIN merchants c ON c.id = v.merchant_id "
|
|
"ORDER BY c.name, v.name"
|
|
)
|
|
).fetchall()
|
|
|
|
|
|
def get_store_domains(db):
|
|
"""Get all custom store domains."""
|
|
return db.execute(
|
|
text(
|
|
"SELECT vd.store_id, vd.domain, vd.is_primary, vd.is_active, "
|
|
" vd.is_verified, v.store_code "
|
|
"FROM store_domains vd "
|
|
"JOIN stores v ON v.id = vd.store_id "
|
|
"ORDER BY vd.store_id, vd.is_primary DESC"
|
|
)
|
|
).fetchall()
|
|
|
|
|
|
def get_store_platform_map(db):
|
|
"""
|
|
Get store-to-platform mapping.
|
|
|
|
Returns dict: store_id -> list of platform codes.
|
|
Uses store_platforms junction table.
|
|
"""
|
|
rows = db.execute(
|
|
text(
|
|
"SELECT sp.store_id, p.code AS platform_code "
|
|
"FROM store_platforms sp "
|
|
"JOIN platforms p ON p.id = sp.platform_id "
|
|
"WHERE sp.is_active = true "
|
|
"ORDER BY sp.store_id, sp.is_primary DESC"
|
|
)
|
|
).fetchall()
|
|
|
|
mapping = {}
|
|
for r in rows:
|
|
mapping.setdefault(r.store_id, []).append(r.platform_code)
|
|
return mapping
|
|
|
|
|
|
def status_badge(is_active):
|
|
return "active" if is_active else "INACTIVE"
|
|
|
|
|
|
def _store_dev_dashboard_url(store_code, platform_code=None):
|
|
"""Build store dashboard URL for dev mode."""
|
|
if platform_code and platform_code != "main":
|
|
return f"{DEV_BASE}/platforms/{platform_code}/store/{store_code}/"
|
|
return f"{DEV_BASE}/store/{store_code}/"
|
|
|
|
|
|
def _store_dev_login_url(store_code, platform_code=None):
|
|
"""Build store login URL for dev mode."""
|
|
if platform_code and platform_code != "main":
|
|
return f"{DEV_BASE}/platforms/{platform_code}/store/{store_code}/login"
|
|
return f"{DEV_BASE}/store/{store_code}/login"
|
|
|
|
|
|
def collect_dev_urls(platforms, stores, store_domains, store_platform_map):
|
|
"""
|
|
Collect all dev URLs with labels and expected status codes.
|
|
|
|
Returns list of (label, url, expected_codes) tuples.
|
|
"""
|
|
urls = []
|
|
|
|
# Admin
|
|
urls.append(("Admin Login", f"{DEV_BASE}/admin/login", [200]))
|
|
urls.append(("Admin Dashboard", f"{DEV_BASE}/admin/", [200, 302]))
|
|
urls.append(("API Docs", f"{DEV_BASE}/docs", [200]))
|
|
urls.append(("Health", f"{DEV_BASE}/health", [200]))
|
|
|
|
# Platforms
|
|
for p in platforms:
|
|
if not p.is_active:
|
|
continue
|
|
if p.code == "main":
|
|
urls.append((f"Platform: {p.name}", f"{DEV_BASE}/", [200]))
|
|
else:
|
|
urls.append((f"Platform: {p.name}", f"{DEV_BASE}/platforms/{p.code}/", [200]))
|
|
|
|
# Store dashboards (redirect to login when unauthenticated)
|
|
for v in stores:
|
|
if not v.is_active:
|
|
continue
|
|
platform_codes = store_platform_map.get(v.id, [])
|
|
if platform_codes:
|
|
for pc in platform_codes:
|
|
url = _store_dev_login_url(v.store_code, pc)
|
|
urls.append((f"Store Login: {v.name} ({pc})", url, [200]))
|
|
else:
|
|
url = _store_dev_login_url(v.store_code)
|
|
urls.append((f"Store Login: {v.name}", url, [200]))
|
|
|
|
# Storefronts
|
|
for v in stores:
|
|
if not v.is_active:
|
|
continue
|
|
urls.append((
|
|
f"Storefront: {v.name}",
|
|
f"{DEV_BASE}/stores/{v.store_code}/storefront/",
|
|
[200, 302],
|
|
))
|
|
|
|
# Store info API (public, no auth needed)
|
|
for v in stores:
|
|
if not v.is_active:
|
|
continue
|
|
urls.append((
|
|
f"Store API: {v.name}",
|
|
f"{DEV_BASE}/api/v1/store/info/{v.store_code}",
|
|
[200],
|
|
))
|
|
|
|
return urls
|
|
|
|
|
|
def print_dev_urls(platforms, stores, store_domains, store_platform_map):
|
|
"""Print all development URLs."""
|
|
print()
|
|
print("DEVELOPMENT URLS")
|
|
print(f"Base: {DEV_BASE}")
|
|
print(SEPARATOR)
|
|
|
|
# Admin
|
|
print()
|
|
print(" ADMIN PANEL")
|
|
print(f" Login: {DEV_BASE}/admin/login")
|
|
print(f" Dashboard: {DEV_BASE}/admin/")
|
|
print(f" API: {DEV_BASE}/api/v1/admin/")
|
|
print(f" API Docs: {DEV_BASE}/docs")
|
|
|
|
# Platforms
|
|
print()
|
|
print(" PLATFORMS")
|
|
for p in platforms:
|
|
tag = f" [{status_badge(p.is_active)}]" if not p.is_active else ""
|
|
if p.code == "main":
|
|
print(f" {p.name}{tag}")
|
|
print(f" Home: {DEV_BASE}/")
|
|
else:
|
|
print(f" {p.name} ({p.code}){tag}")
|
|
print(f" Home: {DEV_BASE}/platforms/{p.code}/")
|
|
|
|
# Stores
|
|
print()
|
|
print(" STORE DASHBOARDS")
|
|
current_merchant = None
|
|
for v in stores:
|
|
if v.merchant_name != current_merchant:
|
|
current_merchant = v.merchant_name
|
|
print(f" [{current_merchant or 'No Merchant'}]")
|
|
|
|
tag = f" [{status_badge(v.is_active)}]" if not v.is_active else ""
|
|
code = v.store_code
|
|
|
|
# Get platform(s) for this store
|
|
platform_codes = store_platform_map.get(v.id, [])
|
|
|
|
print(f" {v.name} ({code}){tag}")
|
|
if platform_codes:
|
|
for pc in platform_codes:
|
|
print(f" Login: {_store_dev_login_url(code, pc)}")
|
|
print(f" Dashboard: {_store_dev_dashboard_url(code, pc)}")
|
|
else:
|
|
print(f" Login: {_store_dev_login_url(code)}")
|
|
print(f" Dashboard: {_store_dev_dashboard_url(code)}")
|
|
print(f" (!) No platform assigned - use /platforms/{{code}}/store/{code}/ for platform context")
|
|
|
|
# Storefronts
|
|
print()
|
|
print(" STOREFRONTS")
|
|
current_merchant = None
|
|
for v in stores:
|
|
if v.merchant_name != current_merchant:
|
|
current_merchant = v.merchant_name
|
|
print(f" [{current_merchant or 'No Merchant'}]")
|
|
|
|
tag = f" [{status_badge(v.is_active)}]" if not v.is_active else ""
|
|
code = v.store_code
|
|
print(f" {v.name} ({code}){tag}")
|
|
print(f" Shop: {DEV_BASE}/stores/{code}/storefront/")
|
|
print(f" API: {DEV_BASE}/api/v1/storefront/{code}/")
|
|
|
|
|
|
def print_prod_urls(platforms, stores, store_domains):
|
|
"""Print all production URLs."""
|
|
platform_domain = settings.platform_domain
|
|
|
|
print()
|
|
print("PRODUCTION URLS")
|
|
print(f"Platform domain: {platform_domain}")
|
|
print(SEPARATOR)
|
|
|
|
# Admin
|
|
print()
|
|
print(" ADMIN PANEL")
|
|
print(f" Login: https://admin.{platform_domain}/admin/login")
|
|
print(f" Dashboard: https://admin.{platform_domain}/admin/")
|
|
print(f" API: https://admin.{platform_domain}/api/v1/admin/")
|
|
|
|
# Platforms
|
|
print()
|
|
print(" PLATFORMS")
|
|
for p in platforms:
|
|
tag = f" [{status_badge(p.is_active)}]" if not p.is_active else ""
|
|
if p.domain:
|
|
print(f" {p.name} ({p.code}){tag}")
|
|
print(f" Home: https://{p.domain}/")
|
|
elif p.code == "main":
|
|
print(f" {p.name}{tag}")
|
|
print(f" Home: https://{platform_domain}/")
|
|
else:
|
|
print(f" {p.name} ({p.code}){tag}")
|
|
print(f" Home: https://{p.code}.{platform_domain}/")
|
|
|
|
# Group domains by store
|
|
domains_by_store = {}
|
|
for vd in store_domains:
|
|
domains_by_store.setdefault(vd.store_id, []).append(vd)
|
|
|
|
# Stores
|
|
print()
|
|
print(" STORE DASHBOARDS")
|
|
current_merchant = None
|
|
for v in stores:
|
|
if v.merchant_name != current_merchant:
|
|
current_merchant = v.merchant_name
|
|
print(f" [{current_merchant or 'No Merchant'}]")
|
|
|
|
tag = f" [{status_badge(v.is_active)}]" if not v.is_active else ""
|
|
print(f" {v.name} ({v.store_code}){tag}")
|
|
print(f" Dashboard: https://{v.subdomain}.{platform_domain}/store/{v.store_code}/")
|
|
|
|
# Storefronts
|
|
print()
|
|
print(" STOREFRONTS")
|
|
current_merchant = None
|
|
for v in stores:
|
|
if v.merchant_name != current_merchant:
|
|
current_merchant = v.merchant_name
|
|
print(f" [{current_merchant or 'No Merchant'}]")
|
|
|
|
tag = f" [{status_badge(v.is_active)}]" if not v.is_active else ""
|
|
print(f" {v.name} ({v.store_code}){tag}")
|
|
|
|
# Subdomain URL
|
|
print(f" Subdomain: https://{v.subdomain}.{platform_domain}/")
|
|
|
|
# Custom domains
|
|
vd_list = domains_by_store.get(v.id, [])
|
|
for vd in vd_list:
|
|
d_flags = []
|
|
if vd.is_primary:
|
|
d_flags.append("primary")
|
|
if not vd.is_active:
|
|
d_flags.append("INACTIVE")
|
|
if not vd.is_verified:
|
|
d_flags.append("unverified")
|
|
suffix = f" ({', '.join(d_flags)})" if d_flags else ""
|
|
print(f" Custom: https://{vd.domain}/{suffix}")
|
|
|
|
|
|
def check_dev_urls(platforms, stores, store_domains, store_platform_map):
|
|
"""Curl all dev URLs and report reachability."""
|
|
urls = collect_dev_urls(platforms, stores, store_domains, store_platform_map)
|
|
|
|
print()
|
|
print("URL HEALTH CHECK")
|
|
print(f"Base: {DEV_BASE}")
|
|
print(SEPARATOR)
|
|
print()
|
|
|
|
passed = 0
|
|
failed = 0
|
|
errors = []
|
|
|
|
for label, url, expected_codes in urls:
|
|
try:
|
|
result = subprocess.run(
|
|
["curl", "-s", "-o", "/dev/null", "-w", "%{http_code}", "-L", "--max-time", "5", url],
|
|
capture_output=True, text=True, timeout=10,
|
|
)
|
|
status = int(result.stdout.strip())
|
|
|
|
if status in expected_codes:
|
|
print(f" PASS {status} {label}")
|
|
print(f" {url}")
|
|
passed += 1
|
|
else:
|
|
expected_str = "/".join(str(c) for c in expected_codes)
|
|
print(f" FAIL {status} {label} (expected {expected_str})")
|
|
print(f" {url}")
|
|
failed += 1
|
|
errors.append((label, url, status, expected_codes))
|
|
except (subprocess.TimeoutExpired, FileNotFoundError, ValueError) as e:
|
|
print(f" ERR --- {label} ({e})")
|
|
print(f" {url}")
|
|
failed += 1
|
|
errors.append((label, url, 0, expected_codes))
|
|
|
|
# Summary
|
|
print()
|
|
print(SEPARATOR)
|
|
total = passed + failed
|
|
print(f" Results: {passed}/{total} passed", end="")
|
|
if failed:
|
|
print(f", {failed} failed")
|
|
else:
|
|
print()
|
|
|
|
if errors:
|
|
print()
|
|
print(" Failed URLs:")
|
|
for label, url, status, expected in errors:
|
|
expected_str = "/".join(str(c) for c in expected)
|
|
print(f" [{status or 'ERR'}] {url} (expected {expected_str})")
|
|
|
|
print()
|
|
return failed == 0
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description="Show all platform URLs")
|
|
parser.add_argument("--dev", action="store_true", help="Development URLs only")
|
|
parser.add_argument("--prod", action="store_true", help="Production URLs only")
|
|
parser.add_argument("--check", action="store_true", help="Check dev URLs with curl")
|
|
args = parser.parse_args()
|
|
|
|
show_dev = args.dev or (not args.dev and not args.prod and not args.check)
|
|
show_prod = args.prod or (not args.dev and not args.prod and not args.check)
|
|
|
|
db = SessionLocal()
|
|
try:
|
|
platforms = get_platforms(db)
|
|
stores = get_stores(db)
|
|
store_domains = get_store_domains(db)
|
|
store_platform_map = get_store_platform_map(db)
|
|
except Exception as e:
|
|
print(f"Error querying database: {e}", file=sys.stderr)
|
|
sys.exit(1)
|
|
finally:
|
|
db.close()
|
|
|
|
print()
|
|
print("=" * 72)
|
|
print(" ORION PLATFORM - ALL URLS")
|
|
print(f" {len(platforms)} platform(s), {len(stores)} store(s), {len(store_domains)} custom domain(s)")
|
|
print("=" * 72)
|
|
|
|
if args.check:
|
|
success = check_dev_urls(platforms, stores, store_domains, store_platform_map)
|
|
sys.exit(0 if success else 1)
|
|
|
|
if show_dev:
|
|
print_dev_urls(platforms, stores, store_domains, store_platform_map)
|
|
|
|
if show_prod:
|
|
print_prod_urls(platforms, stores, store_domains)
|
|
|
|
print()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|