Skip to content

Commit 768331d

Browse files
os-zhuangclaude
andauthored
fix(rest): resolve public forms from flattened view metadata (#1989)
`findPublicFormView` (the /forms/:slug + /forms/:slug/submit resolver) only matched the *authoring* view shape — `view.form.sharing` and `view.formViews.{key}.sharing`. But `getMetaItems({type:'view'})` returns the *registered* shape: one flattened item per view, `{ name, object, viewKind, config: { data, sections, sharing } }`. The form's `sharing` (allowAnonymous + publicLink) lives under `config`, which the resolver never inspected — so every standard public form silently failed with FORM_NOT_FOUND, making Web-to-Lead / Web-to-Case non-functional despite being fully declared. Add a third candidate source: a `viewKind === 'form'` item whose `config` carries `sharing`. Object name resolves via `config.data.object` / the item's `object`. Verified end-to-end (HotCRM): anonymous GET /api/v1/forms/contact-us → 200 form spec; POST /api/v1/forms/contact-us/submit (no auth) → creates a crm_lead; /forms/support → crm_case; guest reads still 401 (INSERT-only enforced). Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 07f93e3 commit 768331d

1 file changed

Lines changed: 9 additions & 0 deletions

File tree

packages/rest/src/rest-server.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3448,6 +3448,7 @@ export class RestServer {
34483448
for (const view of views ?? []) {
34493449
if (!view || typeof view !== 'object') continue;
34503450
const candidates: Array<{ form: any; key?: string }> = [];
3451+
// Authoring/nested shape (defineView): { form, formViews: { key: {...} } }.
34513452
if (view.form && view.form.sharing) candidates.push({ form: view.form });
34523453
const formViews = view.formViews;
34533454
if (formViews && typeof formViews === 'object') {
@@ -3457,6 +3458,14 @@ export class RestServer {
34573458
}
34583459
}
34593460
}
3461+
// Flattened registered shape (getMetaItems → one item per view:
3462+
// { name, object, viewKind:'form', config:{ data, sections, sharing } }).
3463+
// A form view carries its sharing under `config`; without this branch
3464+
// public-form resolution silently fails for the standard view metadata.
3465+
if (view.viewKind === 'form' && view.config && typeof view.config === 'object'
3466+
&& (view.config as any).sharing) {
3467+
candidates.push({ form: view.config, key: view.name });
3468+
}
34603469
for (const c of candidates) {
34613470
const sharing = c.form?.sharing;
34623471
if (!sharing || sharing.allowAnonymous !== true) continue;

0 commit comments

Comments
 (0)