-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Create Site Preview JWT in the API #2554
Conversation
0a35f45
to
d504f9b
Compare
Allows having the Site Preview unauthenticated
d504f9b
to
11eb1ed
Compare
Idea to make this non-breaking: Use an existing environment variable that we know to be available in both site and API. Could be the password of the system user. For v8 we can remove this. Alternatives:
|
@@ -748,6 +748,7 @@ type Query { | |||
pageTreeNodeList(scope: PageTreeNodeScopeInput!, category: String): [PageTreeNode!]! | |||
paginatedPageTreeNodes(scope: PageTreeNodeScopeInput!, category: String, sort: [PageTreeNodeSort!], documentType: String, offset: Int! = 0, limit: Int! = 25): PaginatedPageTreeNodes! | |||
pageTreeNodeSlugAvailable(scope: PageTreeNodeScopeInput!, parentId: ID, slug: String!): SlugAvailability! | |||
sitePreviewJwt(scope: JSONObject!, path: String!, includeInvisible: Boolean!): String! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
imho this should be a mutation, not a query:
- it creates something new (although not stored, so it strictly speaking does not mutate a database or something)
- it should never be cached by anything, that might even result into security issues
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think so too
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could call it createSitePreviewJwt or generateSitePreviewJwt
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently the request is polled (due to expiration time of jwt), this is not possible for mutations. Furthermore, useMutation does not provide refetch, which is used when changing the preview settings.
Caching however is disabled by fetchPolicy: "network-only".
Changing to a mutation requires more handwork to simulate polling and refetching. Do you still think a mutation is necessary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Caching however is disabled
I was thinking about a future cache solution we might add
You ave good arguments, leave the query!
👏 why didn't we do that in the first place? |
@@ -66,6 +66,7 @@ NEXT_PUBLIC_API_URL=$API_URL | |||
# site-pages | |||
SITE_PAGES_PORT=3001 | |||
SITE_PAGES_URL=http://localhost:$SITE_PAGES_PORT | |||
SITE_PREVIEW_SECRET=zPoURKLHPcMnV7E9 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change needs a changeset and this change should also be added to the migration guide for projects that are not on v7 yet
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changeset will be added.
I added another commit to mitigate the effort of handling the breaking change: dea0a1d
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changeset: 5d8c99a
@@ -748,6 +748,7 @@ type Query { | |||
pageTreeNodeList(scope: PageTreeNodeScopeInput!, category: String): [PageTreeNode!]! | |||
paginatedPageTreeNodes(scope: PageTreeNodeScopeInput!, category: String, sort: [PageTreeNodeSort!], documentType: String, offset: Int! = 0, limit: Int! = 25): PaginatedPageTreeNodes! | |||
pageTreeNodeSlugAvailable(scope: PageTreeNodeScopeInput!, parentId: ID, slug: String!): SlugAvailability! | |||
sitePreviewJwt(scope: JSONObject!, path: String!, includeInvisible: Boolean!): String! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think so too
}).toString()}`; | ||
const { data, error, refetch } = useQuery<GQLSitePreviewJwtQuery>( | ||
gql` | ||
query SitePreviewJwt($scope: JSONObject!, $path: String!, $includeInvisible: Boolean!) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One downside to a mutation would be that it can't be queried like this here. But we could create it before even navigating to the site preview.
path: iframePath, | ||
includeInvisible: showOnlyVisible ? false : true, | ||
}, | ||
pollInterval: 1000 * 60 * 60 * 24, // due to expiration time of jwt |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't this cause a location reset when a user stays too long in the site preview?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it does. Do we ignore it? (as this only happens after 24 hours)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it's 24 hours, do we even need polling?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The expiry date of the JWT (which is stored in the site as cookie) is validated with every request. If we don't reload the SitePreview every click would result in an error. The problem occurs when a user leaves the tab opened for more than 24 hours and then continues navigation in the preview.
packages/site/cms-site/src/sitePreview/pagesRouter/legacyPagesRouterSitePreviewApiHandler.ts
Show resolved
Hide resolved
Regarding the breaking change:
|
I don't think this will be necessary. After updating and startup in local dev the following error message will be shown: BREAKING: this update of Comet v7 requires to have set sitePreviewSecret (which has to be the same value like possibly already set for site). Please refer to vivid-planet/comet-starter#371 for more information on how to upgrade. The linked PR then shows exactly what to do. |
but it doesn't show the required deployment changes |
This is true. But it's nothing more than copying one line. We could add this to the description of the PR. |
Wouldn't it be even better if the error message said: An even more crazy thought: What if the library could patch itself (i.e. include the upgrade script). I'm thinking about something like Next patches the typescript file if both Pages and App Router are used: https://github.com/vercel/next.js/blob/canary/packages/next/src/lib/typescript/writeAppTypeDeclarations.ts#L52-L56 |
Script for the breaking change in vivid-planet/comet#2554.
<!-- PLEASE MAKE SURE TO KEEP THE PR SIZE AT A MINIMUM! Smaller PRs are easier to review and tend to get merged faster. Unrelated changes, refactorings, fixes etc. should be made in separate PRs. ---> ## Description Add deployment based on [DigitalOcean's app platform](https://www.digitalocean.com/products/app-platform). The apps are split per domain to be compatible with routing from the app platform. The preview does not work yet, as I'm waiting for vivid-planet/comet#2554. I decided to not commit the symlinks and copy the files instead to keep the required changes minimal. The secrets are [safe](https://docs.digitalocean.com/products/app-platform/how-to/use-environment-variables/) inside the repo as they are encrypted. This does not include a secondary site, but could be added later. <!-- The description should describe the change you're making. It will be used as the commit message for the squashed commit once the PR gets merged. Therefore, make sure to keep the description up-to-date as the PR changes. PLEASE DESCRIBE WHY YOU'RE MAKING THE CHANGE, NOT WHAT YOU'RE CHANGING. Reviewers see what you're changing when reviewing the code. However, they might not understand your motives as to why you're making the change. Your description should include: - The problem you're facing - Your solution to the problem - An example usage of your change ---> <!-- Everything below this is intended to help ease reviewing this PR. Remove all unrelated sections. WHEN MERGING THE PR, REMOVE THIS FROM THE COMMIT MESSAGE. --> ## Screenshots/screencasts <!-- When making a visual change, please provide either screenshots or screencasts. Hint: For before/after views, you can use a table: | Before | After | | -------- | ------- | | Link | Link | --> ## Related tasks and documents <!-- Link to related tasks and documents, for instance, https://vivid-planet.atlassian.net/browse/COM-XXX. MAKE SURE THAT EVERYTHING REQUIRED TO UNDERSTAND YOUR CHANGE IS IN THE PR DESCRIPTION. Reviewers shouldn't need to review tasks, JIRA conversations etc. to understand what you're doing. --> ## Open TODOs/questions (Future PR) - [ ] Remove dependency to dkarnutsch/oauth2-proxy (no really trustworthy image from Docker Hub found and GitHub registry does not work yet on DigitalOcean) - [ ] Replace domains with starter.comet-dxp.com and admin.starter.comet-dxp.com - [ ] Add CI/CD based on GitHub Actions ## Further information <!-- Further information that helps reviewing the PR, for instance: - Alternative solutions you have considered - Dependent PRs - Links to relevant documentation, blog posts etc. -->
Since #2554 the site preview isn't anymore behind an authproxy. As a consequence preview urls do not work anymore, but creating normal hashed urls should be sufficient
Allows having the Site Preview unauthenticated ## Description Before: the JWT with the preview scope and setting was generated in the site. To check if the current user is allowed to preview the given scope the site had to make a request to the API and therefore needed the access token of the current user. With this setup the site has to be behind an authproxy. Now: the JWT is generated by the API and submitted to the site. This way the site can be public. ## BREAKING The API now requires the SITE_PREVIEW_SECRET environment variable. To make it explicit to add it this env now is also mandatory for local development.
Allows having the Site Preview unauthenticated
Description
Before: the JWT with the preview scope and setting was generated in the site. To check if the current user is allowed to preview the given scope the site had to make a request to the API and therefore needed the access token of the current user. With this setup the site has to be behind an authproxy.
Now: the JWT is generated by the API and submitted to the site. This way the site can be public.
BREAKING
The API now requires the SITE_PREVIEW_SECRET environment variable. To make it explicit to add it this env now is also mandatory for local development.
Open TODOs/questions
COM-1087