# WebForm-mw — CiviCRM extension Adds an **Engagement Report** tab to Organization contact-view pages that embeds the FCI Co-op Survey staff report (`https://survey.fci.coop/staff/report`) in an iframe. The tab shows the report for the current organization, scoped by the contact id in the URL. The embedded app handles its own auth via a shared staff secret. The extension is otherwise read-only and adds no Civi tables, custom fields, or scheduled jobs. ## Install 1. Copy the entire `webform-mw/` directory to your CiviCRM extensions directory (typically `/sites/default/ext/` or wherever `[civicrm.extensionsDir]` points in your `civicrm.settings.php`). - The directory name on disk must be `webform-mw` (matching `` in `info.xml`). 2. In CiviCRM: `Administer → System Settings → Extensions → Add new → Refresh`, then click **Install** next to "WebForm-mw". 3. Configure (see next section). The tab will be hidden until both settings are present. ## Configuration The extension reads two values, in this order: 1. Constants in `civicrm.settings.php` (preferred): ```php define('WEBFORM_MW_APP_URL', 'https://survey.fci.coop'); define('WEBFORM_MW_STAFF_KEY', '...the STAFF_REPORT_KEY shared with the app...'); ``` 2. Or environment variables (`WEBFORM_MW_APP_URL`, `WEBFORM_MW_STAFF_KEY`) set wherever PHP-FPM / the web server reads its environment from. `WEBFORM_MW_STAFF_KEY` must match the `STAFF_REPORT_KEY` configured on the Next.js app (Amplify environment / SSM Parameter Store). The two are the same shared secret; rotate them together. `WEBFORM_MW_APP_URL` is the public base URL of the WebForm-mw deployment (no trailing slash). Production: `https://survey.fci.coop`. When either value is missing, the tab body shows a help banner with the exact configuration snippet to paste, so anyone installing the extension without prior context can self-serve. ## Behaviour - Tab title: **Engagement Report**. - Visible only on **Organization** contacts (Individuals and Households see no tab). The check happens server-side in the tabset hook. - Tab body is an iframe pointing at `${WEBFORM_MW_APP_URL}/staff/report?org=&exp=&sig=&frame=1`. - `frame=1` tells the embedded app to suppress its site header/footer and emit a `postMessage({type:"webform-mw-height", height})` payload on render and on resize. The tab's small inline script listens for this message and auto-sizes the iframe so there's no nested scrollbar. - The script validates the postMessage `event.origin` against the configured `WEBFORM_MW_APP_URL` origin before resizing. ## Security notes - The shared secret never leaves the server. Each tab render mints a signed token, `HMAC-SHA256(secret, "webform-mw.staff-report.v1::")`, valid for one org for 8 hours. The app rejects tokens for other orgs, expired tokens, and anything valid for longer than 12 hours. - Tokens are only minted after `CRM_Contact_BAO_Contact_Permission::allow()` confirms the current user can view the org, so Civi contact ACLs carry through to the embedded report. - Rotating the secret: change `WEBFORM_MW_STAFF_KEY` and the app's `STAFF_REPORT_KEY` together; outstanding tokens stop working at once. - The extension uses `access CiviCRM` as its access argument — anyone with that permission sees the tab on Organization contacts. Tighten by changing the `` value in `xml/Menu/webform_mw.xml` to a more specific permission (e.g., `view all contacts`) and reinstalling. - The embedded app's CSP (`frame-ancestors`) must include the CiviCRM origin or the iframe will refuse to render. The Next app reads `CIVI_BASE_URL` at build time and adds its origin to the staff route's CSP automatically. Confirm with `curl -I /staff/report` after deploy — you should see `Content-Security-Policy: ... frame-ancestors 'self' https:// ...`. ## Files - `info.xml` — extension manifest. Key `webform-mw`, type `module`. - `webform_mw.php` — `hook_civicrm_tabset` + config readers. - `CRM/WebformMw/Page/Tab.php` — page controller for the tab snippet. - `templates/CRM/WebformMw/Page/Tab.tpl` — iframe + height-listener. - `xml/Menu/webform_mw.xml` — registers the `civicrm/contact/view/engagement-report` URL. ## Versions tested - CiviCRM 5.50+ - PHP 7.4+ / 8.x - Tested against Backdrop-as-host and Drupal-as-host CiviCRM deployments. ## Uninstalling `Administer → Extensions → Disable`, then `Uninstall`. Removes nothing from the database; the extension stores no Civi data of its own.