Skip to content
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

[Data masking] Warn when using data masking with no-cache operations #12121

Merged
merged 21 commits into from
Nov 13, 2024

Conversation

jerelmiller
Copy link
Member

Closes #11678

Emits a warning when using no-cache operations with data masking since watchFragment and useFragment rely on the cache to read fragment data. This warning will not be emitted when either dataMasking is disabled or if the operation already contains @unmask for all fragments.

@jerelmiller jerelmiller added the 🎭 data-masking Issues/PRs related to data masking label Nov 13, 2024
@jerelmiller jerelmiller added this to the Data masking milestone Nov 13, 2024
@svc-apollo-docs
Copy link

svc-apollo-docs commented Nov 13, 2024

✅ Docs Preview Ready

No new or changed pages found.

Copy link

changeset-bot bot commented Nov 13, 2024

⚠️ No Changeset found

Latest commit: 8a3fece

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

}

invariant.warn(
'Fragments masked by data masking when using fetch policy "no-cache" cannot be read by `watchFragment` or `useFragment`. Please add `@unmask` to the fragment to read the fragment data.'
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestions welcome on better wording here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe

-...to read the fragment data.+
+...to make the fragment data available for reading without those hooks.

?

It might also be helpful to include the name of the document.

Copy link

pkg-pr-new bot commented Nov 13, 2024

npm i https://pkg.pr.new/@apollo/client@12121

commit: f57d5a9

Copy link
Contributor

github-actions bot commented Nov 13, 2024

size-limit report 📦

Path Size
dist/apollo-client.min.cjs 40.6 KB (+0.14% 🔺)
import { ApolloClient, InMemoryCache, HttpLink } from "dist/main.cjs" 50.99 KB (+0.45% 🔺)
import { ApolloClient, InMemoryCache, HttpLink } from "dist/main.cjs" (production) 47.57 KB (+0.24% 🔺)
import { ApolloClient, InMemoryCache, HttpLink } from "dist/index.js" 36.31 KB (+0.59% 🔺)
import { ApolloClient, InMemoryCache, HttpLink } from "dist/index.js" (production) 33.56 KB (+0.18% 🔺)
import { ApolloProvider } from "dist/react/index.js" 1.26 KB (0%)
import { ApolloProvider } from "dist/react/index.js" (production) 1.25 KB (-0.08% 🔽)
import { useQuery } from "dist/react/index.js" 5.22 KB (+0.02% 🔺)
import { useQuery } from "dist/react/index.js" (production) 4.3 KB (-0.03% 🔽)
import { useLazyQuery } from "dist/react/index.js" 5.71 KB (+0.02% 🔺)
import { useLazyQuery } from "dist/react/index.js" (production) 4.78 KB (0%)
import { useMutation } from "dist/react/index.js" 3.63 KB (-0.03% 🔽)
import { useMutation } from "dist/react/index.js" (production) 2.85 KB (0%)
import { useSubscription } from "dist/react/index.js" 4.43 KB (+0.03% 🔺)
import { useSubscription } from "dist/react/index.js" (production) 3.48 KB (-0.03% 🔽)
import { useSuspenseQuery } from "dist/react/index.js" 5.52 KB (+0.02% 🔺)
import { useSuspenseQuery } from "dist/react/index.js" (production) 4.17 KB (+0.03% 🔺)
import { useBackgroundQuery } from "dist/react/index.js" 5.02 KB (0%)
import { useBackgroundQuery } from "dist/react/index.js" (production) 3.67 KB (+0.03% 🔺)
import { useLoadableQuery } from "dist/react/index.js" 5.1 KB (+0.04% 🔺)
import { useLoadableQuery } from "dist/react/index.js" (production) 3.74 KB (-0.03% 🔽)
import { useReadQuery } from "dist/react/index.js" 3.42 KB (+0.03% 🔺)
import { useReadQuery } from "dist/react/index.js" (production) 3.36 KB (+0.03% 🔺)
import { useFragment } from "dist/react/index.js" 2.34 KB (+0.05% 🔺)
import { useFragment } from "dist/react/index.js" (production) 2.29 KB (+0.05% 🔺)

@@ -517,6 +517,7 @@ export class ApolloClient<TCacheShape> implements DataProxy {
data: this.queryManager.maskOperation({
document: options.query,
data: result.data,
fetchPolicy: options.fetchPolicy,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Subscriptions don't have a queryId so this would mean the warning would be emitted for every subscription event. Are we ok with that? Should we use something else as the query ID to try and only emit this warning once per subscription?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I think a counter on module level and using something like "subscription"+(id++) as queryId would be fine here. Might make sense to rename the queryId option to something like id then.

@jerelmiller jerelmiller linked an issue Nov 13, 2024 that may be closed by this pull request
return BREAK;
}

isUnmasked &&= node.directives.some(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
isUnmasked &&= node.directives.some(
isUnmasked = node.directives.some(

I think we can safely assume that at this point, isUnmasked is always true, right?

Comment on lines 152 to 165
FragmentSpread: (node) => {
if (!node.directives) {
isUnmasked = false;
return BREAK;
}

isUnmasked &&= node.directives.some(
(directive) => directive.name.value === "unmask"
);

if (!isUnmasked) {
return BREAK;
}
},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
FragmentSpread: (node) => {
if (!node.directives) {
isUnmasked = false;
return BREAK;
}
isUnmasked &&= node.directives.some(
(directive) => directive.name.value === "unmask"
);
if (!isUnmasked) {
return BREAK;
}
},
FragmentSpread: (node) => {
isUnmasked = !!node.directives && node.directives.some(
(directive) => directive.name.value === "unmask"
);
if (!isUnmasked) {
return BREAK;
}
},

I think this whole block could be simplified like this.

});
const stream = new ObservableStream(observable);

link.simulateResult({
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be great if the client.subscribe tests would show more than one subscription result.

Copy link
Member

@phryneas phryneas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left a bunch of comments and suggestions, but as a whole: approved :)

@github-actions github-actions bot added the auto-cleanup 🤖 label Nov 13, 2024
@jerelmiller
Copy link
Member Author

Reminder to self: don't forget a changeset

@jerelmiller jerelmiller merged commit 1085a95 into release-3.12 Nov 13, 2024
32 of 36 checks passed
@jerelmiller jerelmiller deleted the jerel/no-cache-warning branch November 13, 2024 17:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
auto-cleanup 🤖 🎭 data-masking Issues/PRs related to data masking
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Data masking] Allow useFragment to work with no-cache queries
3 participants