diff --git a/CHANGELOG.md b/CHANGELOG.md index 7026880cd6..def1683596 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ Our versioning strategy is as follows: * `[templates/nextjs-sxa]` Fix styles of title component in metadata mode. ([#1839](https://github.com/Sitecore/jss/pull/1839)) * `[templates/nextjs-sxa]` Fix missing value of field property in Title component. ([#1842](https://github.com/Sitecore/jss/pull/1842)) + ### 🎉 New Features & Improvements * `[sitecore-jss-react]` Introduce ErrorBoundary component. All rendered components are wrapped with it and it will catch client or server side errors from any of its children, display appropriate message and prevent the rest of the application from failing. It accepts and can display custom error component and loading message if it is passed as a prop to parent Placeholder. ([#1786](https://github.com/Sitecore/jss/pull/1786))([#1790](https://github.com/Sitecore/jss/pull/1790))([#1793](https://github.com/Sitecore/jss/pull/1793))([#1794](https://github.com/Sitecore/jss/pull/1794))([#1799](https://github.com/Sitecore/jss/pull/1799))([#1807](https://github.com/Sitecore/jss/pull/1807))([#1829](https://github.com/Sitecore/jss/pull/1829)) @@ -33,7 +34,7 @@ Our versioning strategy is as follows: ### 🛠 Breaking Change -* Editing Integration Support: ([#1776](https://github.com/Sitecore/jss/pull/1776))([#1792](https://github.com/Sitecore/jss/pull/1792))([#1773](https://github.com/Sitecore/jss/pull/1773))([#1797](https://github.com/Sitecore/jss/pull/1797))([#1800](https://github.com/Sitecore/jss/pull/1800))([#1803](https://github.com/Sitecore/jss/pull/1803))([#1806](https://github.com/Sitecore/jss/pull/1806))([#1809](https://github.com/Sitecore/jss/pull/1809))([#1814](https://github.com/Sitecore/jss/pull/1814))([#1816](https://github.com/Sitecore/jss/pull/1816))([#1819](https://github.com/Sitecore/jss/pull/1819))([#1828](https://github.com/Sitecore/jss/pull/1828))([#1835](https://github.com/Sitecore/jss/pull/1835)) +* Editing Integration Support: ([#1776](https://github.com/Sitecore/jss/pull/1776))([#1792](https://github.com/Sitecore/jss/pull/1792))([#1773](https://github.com/Sitecore/jss/pull/1773))([#1797](https://github.com/Sitecore/jss/pull/1797))([#1800](https://github.com/Sitecore/jss/pull/1800))([#1803](https://github.com/Sitecore/jss/pull/1803))([#1806](https://github.com/Sitecore/jss/pull/1806))([#1809](https://github.com/Sitecore/jss/pull/1809))([#1814](https://github.com/Sitecore/jss/pull/1814))([#1816](https://github.com/Sitecore/jss/pull/1816))([#1819](https://github.com/Sitecore/jss/pull/1819))([#1828](https://github.com/Sitecore/jss/pull/1828))([#1835](https://github.com/Sitecore/jss/pull/1835)) ([#1849](https://github.com/Sitecore/jss/pull/1849)) * `[sitecore-jss-react]` Introduces `PlaceholderMetadata` component which supports the hydration of chromes on Pages by rendering the components and placeholders with required metadata. * `[sitecore-jss]` Chromes are hydrated based on the basis of new `editMode` property derived from LayoutData, which is defined as an enum consisting of `metadata` and `chromes`. * `ComponentConsumerProps` is removed. You might need to reuse `WithSitecoreContextProps` type. diff --git a/packages/sitecore-jss-nextjs/src/editing/editing-render-middleware.test.ts b/packages/sitecore-jss-nextjs/src/editing/editing-render-middleware.test.ts index a6aebc8f5d..006ded27c1 100644 --- a/packages/sitecore-jss-nextjs/src/editing/editing-render-middleware.test.ts +++ b/packages/sitecore-jss-nextjs/src/editing/editing-render-middleware.test.ts @@ -24,8 +24,8 @@ import sinonChai from 'sinon-chai'; use(sinonChai); const mockNextJsPreviewCookies = [ - '__prerender_bypass:1122334455', - '__next_preview_data:6677889900', + '__prerender_bypass=1122334455; Path=/; SameSite=Lax', + '__next_preview_data=6677889900; Path=/; SameSite=Lax', ]; type Query = { @@ -339,6 +339,21 @@ describe('EditingRenderMiddleware', () => { expect(isEditingMetadataPreviewData(metadataPreviewData)).to.be.true; expect(isEditingMetadataPreviewData(chromesPreviewData)).to.be.false; }); + + it('should modify the Set-Cookie header', async () => { + const req = mockRequest(EE_BODY, query, 'GET'); + const res = mockResponse(); + + const middleware = new EditingRenderMiddleware(); + const handler = middleware.getHandler(); + + await handler(req, res); + + expect(res.setHeader).to.have.been.calledWith('Set-Cookie', [ + '__prerender_bypass=1122334455; Path=/; SameSite=None; Secure', + '__next_preview_data=6677889900; Path=/; SameSite=None; Secure', + ]); + }); }); describe('chromes handler', () => { diff --git a/packages/sitecore-jss-nextjs/src/editing/editing-render-middleware.ts b/packages/sitecore-jss-nextjs/src/editing/editing-render-middleware.ts index 818089bb2a..7cb9aedccb 100644 --- a/packages/sitecore-jss-nextjs/src/editing/editing-render-middleware.ts +++ b/packages/sitecore-jss-nextjs/src/editing/editing-render-middleware.ts @@ -363,6 +363,32 @@ export class MetadataHandler { } ); + // Cookies with the SameSite=Lax policy set by Next.js setPreviewData function causes CORS issue + // when Next.js preview mode is activated, resulting the page to render in normal mode instead. + // By replacing it with "SameSite=None; Secure", we ensure cookies are correctly sent with + // cross-origin requests, allowing the page to be editable. This change should be reverted + // once vercel addresses this open issue: https://github.com/vercel/next.js/issues/49927 + const setCookieHeader = res.getHeader('Set-Cookie'); + + if (setCookieHeader && Array.isArray(setCookieHeader)) { + const modifiedCookies = setCookieHeader.map((cookie) => { + const cookieIdentifiers: { [key: string]: RegExp } = { + __prerender_bypass: /^__prerender_bypass=/, + __next_preview_data: /^__next_preview_data=/, + }; + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + for (const [_, regex] of Object.entries(cookieIdentifiers)) { + if (cookie.match(regex)) { + return cookie.replace(/SameSite=Lax/, 'SameSite=None; Secure'); + } + } + return cookie; + }); + + res.setHeader('Set-Cookie', modifiedCookies); + } + const route = this.config.resolvePageUrl?.({ itemPath: query.route,