Share View Modernized - sebiboga/testlink-upgraded GitHub Wiki

Public Share Link Viewer (shareView) — Modernized

Refs #1508 (enhancement) — lnl.php (type=exec) public share-link flow modernized into a standalone anonymous Dashio viewer.

Legacy behavior

execTest.html:copyDirectLink() (the "Copy" link button on an executed test case row) built a URL lnl.php?type=exec&id=<exec>&apikey=<plan_api_key> for sharing/email. lnl.php authenticated the key (32-char user key via setUpEnvForRemoteAccess, or 64-char object key via setUpEnvForAnonymousAccess) and 302-redirected to the legacy lib/execute/execPrint.php, which rendered the full print document.

Legacy weakness (hardened here): for type=exec with a 64-char key, lnl.php did not validate the caller's key at all — it replaced it with the execution's own testplan.api_key taken from the DB and validated that, so any 64-char string opened the execution anonymously.

Modernized implementation

  • BFF api/share/index.php — session-free, apikey-authenticated JSON.
    • GET ?type=exec&id=N&apikey=AK&… → { status, type, exec_id, meta{…}, share_url }.
    • 32-char key = remote user key (tlUser::getByAPIKey, exactly one user required), else 401.
    • 64-char key = object key bound to the owning testplan / testproject via getEntityByAPIKey; the resolved entity MUST own the requested execution (fail closed), else 401.
    • Length gate 32/64 (else 400), unknown/forged execution id → 404 (probed, no E_WARNING events), missing key → 400, unsupported type → 400.
    • Metadata: test case name + external id (prefix-glue-number) + version, summary, status char + verbatim suffix (client badge map), execution_ts, duration seconds, tester display name/login, build, platform, project + plan names (via nodes_hierarchy — no name columns on testplans/testprojects), execution notes, canonical share_url.
  • Screen gui/templates/share/shareView.html — standalone Dashio page, no login needed. Toolbar (Print → window.print(), Copy share link → clipboard + toast, Close), public-share notice banner, test case header, status pill (passed/failed/blocked/not_run/unknown, Dashio teal/red/orange/grey palette), summary box, metadata grid, execution-notes box, share link box. Print CSS hides chrome; noindex,nofollow; Cache-Control: no-store. Localized 400/401/404/500 error banners.
  • i18n: share.* (35 keys) + footers.shareView in all 10 client bundles (en/ro/de/es/fr/it/pt/ru/zh/ja).
  • Link switch: execTest.html:copyDirectLink() now copies gui/templates/share/shareView.html?type=exec&id=…&apikey=…; $actions->share added in lib/functions/common.php.
  • Kept legacy: lnl.php still serves the other share types (metrics dashboard, file download, plan/test-report documents, testspec, charts), and the legacy link format remains a compat fallback for already-sent emails.

Screenshots

Passed shared execution

shareView-passed

Failed shared execution with notes

shareView-failed

Verification (browser, anonymous context)

Check Result
Passed execution status=p → green PASSED pill + full metadata PASS
Failed execution status=f → red FAILED pill + notes PASS
Wrong 64-char key → 401 localized banner PASS
Forged execution id → 404 localized banner PASS
No/short key → 400 JSON PASS
Copy share link → clipboard + success toast PASS
Print → window.print() with print CSS PASS
No login/session (fresh isolated anon context) PASS
Event Viewer: 0 ERROR/WARNING PASS

Files

  • api/share/index.php — BFF (apikey auth + exec metadata).
  • gui/templates/share/shareView.html — anonymous Dashio viewer screen.
  • gui/templates/execute/execTest.html — copyDirectLink() link switch.
  • lib/functions/common.php — $actions->share entry.
  • gui/templates/i18n/*.json ×10 — share.* + footers.shareView bundles.

Test suite: Share-View-Modernized.md regression suite 1508, 24/24 PASS.

⚠️ **GitHub.com Fallback** ⚠️