Skip to content

Commit

Permalink
Generate the list of sensitive operations dynamically from schema (#1478
Browse files Browse the repository at this point in the history
)
  • Loading branch information
CarsonF authored Sep 21, 2023
1 parent a67a092 commit fd45a71
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 14 deletions.
9 changes: 6 additions & 3 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@ import { ThemeProvider } from '@mui/material/styles';
import { LocalizationProvider } from '@mui/x-date-pickers';
import LogRocket from 'logrocket';
import setupLogRocketReact from 'logrocket-react';
import { ApolloProvider } from './api';
import { ApolloProvider, GqlSensitiveOperations } from './api';
import { LuxonCalenderDateUtils } from './common/LuxonCalenderDateUtils';
import { ConfettiProvider } from './components/Confetti';
import { Nest } from './components/Nest';
import { SnackbarProvider } from './components/Snackbar';
import { UploadProvider as FileUploadProvider } from './components/Upload';
import { SensitiveOperations } from './scenes/Authentication';
import { Root } from './scenes/Root';
import { createTheme } from './theme';

Expand All @@ -19,7 +18,11 @@ if (logRocketAppId) {
network: {
requestSanitizer(request) {
// Relies on operation name suffix which do in Apollo HttpLink config
if (SensitiveOperations.some((op) => request.url.endsWith('/' + op))) {
if (
[...GqlSensitiveOperations].some((op) =>
request.url.endsWith(`/${op}`)
)
) {
request.body = undefined;
}
return request;
Expand Down
46 changes: 44 additions & 2 deletions src/api/operationsList/operations.codegen.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,49 @@
import { plugin as basePlugin } from '@graphql-codegen/named-operations-object';
import type { PluginFunction } from '@graphql-codegen/plugin-helpers';
import { concatAST, FieldNode, visit } from 'graphql';

export const plugin: PluginFunction = async (...args) => {
const result = await basePlugin(...args);
return result ? result + ' as const' : result;
let result = await basePlugin(...args);
result = result ? result + ' as const;' : result;

const [schema, documents] = args;

const queries = Object.values(schema.getQueryType()?.getFields() ?? {});
const mutations = Object.values(schema.getMutationType()?.getFields() ?? {});
const sensitiveQueries = new Set(
[...queries, ...mutations]
.filter(
(f) => f.description && /^\s*@sensitive-secrets$/m.test(f.description)
)
.map((f) => f.name)
);
const sensitiveOperationsNames = new Set();
const allAst = concatAST(documents.flatMap((v) => v.document ?? []));
visit(allAst, {
OperationDefinition: (node) => {
if (
!node.name ||
(node.operation !== 'query' && node.operation !== 'mutation')
) {
return;
}
const fields = node.selectionSet.selections
.filter((s): s is FieldNode => s.kind === 'Field')
.map((s) => s.name.value);
for (const field of fields) {
if (sensitiveQueries.has(field)) {
sensitiveOperationsNames.add(node.name.value);
}
}
},
});

result += `
export const GqlSensitiveOperations: ReadonlySet<string> = new Set([
${[...sensitiveOperationsNames].map((n) => ` '${n}'`).join(',\n')}
]);
`;

return result;
};
9 changes: 0 additions & 9 deletions src/scenes/Authentication/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { GQLOperations } from '../../api';

export * from './AuthLayout';
export * from './AuthWaiting';
export * from './ChangePassword';
Expand All @@ -9,10 +7,3 @@ export * from './Logout';
export * from './Register/Register';
export * from './ResetPassword';
export * from './useAuthRequired';

export const SensitiveOperations = [
GQLOperations.Mutation.Login,
GQLOperations.Mutation.ResetPassword,
GQLOperations.Mutation.ChangePassword,
GQLOperations.Mutation.Register,
];

0 comments on commit fd45a71

Please sign in to comment.