diff --git a/examples/simple/index.js b/examples/simple/index.js index 0a153ed..237d875 100644 --- a/examples/simple/index.js +++ b/examples/simple/index.js @@ -24,6 +24,8 @@ broker.createService({ mappingPolicy: "restrict", }, + checkActionVisibility: true, + // https://www.apollographql.com/docs/apollo-server/v2/api/apollo-server.html serverOptions: {}, }), @@ -78,6 +80,26 @@ broker.createService({ throw new MoleculerClientError("I've said it's a danger action!", 422, "DANGER"); }, }, + + secret: { + visibility: "protected", + graphql: { + query: "secret: String!", + }, + async handler() { + return "! TOP SECRET !"; + }, + }, + + visible: { + visibility: "published", + graphql: { + query: "visible: String!", + }, + async handler() { + return "Not secret"; + }, + }, }, }); diff --git a/index.d.ts b/index.d.ts index 94ce401..0af641c 100644 --- a/index.d.ts +++ b/index.d.ts @@ -41,6 +41,7 @@ declare module "moleculer-apollo-server" { }; dataLoader?: boolean; nullIfError?: boolean; + skipNullKeys?: boolean; params?: { [key: string]: any }; } @@ -94,6 +95,7 @@ declare module "moleculer-apollo-server" { }; routeOptions?: ServiceRouteOptions; serverOptions?: Config; + checkActionVisibility?: boolean; autoUpdateSchema?: boolean; } diff --git a/package-lock.json b/package-lock.json index a39a9bf..bba1944 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5632,13 +5632,19 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001255", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001255.tgz", - "integrity": "sha512-F+A3N9jTZL882f/fg/WWVnKSu6IOo3ueLz4zwaOPbPYHNmM/ZaDUyzyJwS1mZhX7Ex5jqTyW599Gdelh5PDYLQ==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - } + "version": "1.0.30001415", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001415.tgz", + "integrity": "sha512-ER+PfgCJUe8BqunLGWd/1EY4g8AzQcsDAVzdtMGKVtQEmKAwaFfU6vb7EAVIqTMYsqxBorYZi2+22Iouj/y7GQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + } + ] }, "node_modules/caseless": { "version": "0.12.0", @@ -17890,9 +17896,9 @@ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" }, "caniuse-lite": { - "version": "1.0.30001255", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001255.tgz", - "integrity": "sha512-F+A3N9jTZL882f/fg/WWVnKSu6IOo3ueLz4zwaOPbPYHNmM/ZaDUyzyJwS1mZhX7Ex5jqTyW599Gdelh5PDYLQ==" + "version": "1.0.30001415", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001415.tgz", + "integrity": "sha512-ER+PfgCJUe8BqunLGWd/1EY4g8AzQcsDAVzdtMGKVtQEmKAwaFfU6vb7EAVIqTMYsqxBorYZi2+22Iouj/y7GQ==" }, "caseless": { "version": "0.12.0", diff --git a/src/service.js b/src/service.js index 09bbe57..a7b96d3 100644 --- a/src/service.js +++ b/src/service.js @@ -25,6 +25,7 @@ module.exports = function (mixinOptions) { createAction: true, subscriptionEventName: "graphql.publish", autoUpdateSchema: true, + checkActionVisibility: false, }); const serviceSchema = { @@ -450,6 +451,13 @@ module.exports = function (mixinOptions) { Object.values(service.actions).forEach(action => { const { graphql: def } = action; + if ( + mixinOptions.checkActionVisibility && + action.visibility != null && + action.visibility != "published" + ) + return; + if (def && _.isObject(def)) { if (def.query) { if (!resolver["Query"]) resolver.Query = {}; diff --git a/test/integration/greeter.spec.js b/test/integration/greeter.spec.js index 66169ae..4f27821 100644 --- a/test/integration/greeter.spec.js +++ b/test/integration/greeter.spec.js @@ -26,6 +26,8 @@ describe("Integration test for greeter service", () => { mappingPolicy: "restrict", }, + checkActionVisibility: true, + // https://www.apollographql.com/docs/apollo-server/v2/api/apollo-server.html serverOptions: {}, }), @@ -104,6 +106,16 @@ describe("Integration test for greeter service", () => { ); }, }, + + secret: { + visibility: "protected", + graphql: { + query: "secret: String!", + }, + async handler() { + return "! TOP SECRET !"; + }, + }, }, }); @@ -227,4 +239,41 @@ describe("Integration test for greeter service", () => { ], }); }); + + it("should not call the greeter.secret", async () => { + const res = await fetch(`http://localhost:${port}/graphql`, { + method: "post", + body: JSON.stringify({ + operationName: null, + variables: {}, + query: "query { danger }", + }), + headers: { "Content-Type": "application/json" }, + }); + + expect(res.status).toBe(200); + expect(await res.json()).toStrictEqual({ + data: null, + errors: [ + { + extensions: { + code: "INTERNAL_SERVER_ERROR", + exception: { + code: 422, + retryable: false, + type: "DANGER", + }, + }, + locations: [ + { + column: 9, + line: 1, + }, + ], + message: "I've said it's a danger action!", + path: ["danger"], + }, + ], + }); + }); });