@envelop/operation-field-permissions 3.4.0-alpha-c0cc559.0 → 3.4.0-alpha-e9434aa.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/{index.js → cjs/index.js} +20 -18
- package/cjs/package.json +1 -0
- package/{index.mjs → esm/index.js} +21 -15
- package/package.json +34 -13
- package/{index.d.ts → typings/index.d.ts} +0 -0
- package/README.md +0 -65
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const graphql = require('graphql');
|
|
8
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useOperationFieldPermissions = void 0;
|
|
4
|
+
const core_1 = require("@envelop/core");
|
|
5
|
+
const extended_validation_1 = require("@envelop/extended-validation");
|
|
6
|
+
const graphql_1 = require("graphql");
|
|
9
7
|
const OPERATION_PERMISSIONS_SYMBOL = Symbol('OPERATION_PERMISSIONS_SYMBOL');
|
|
10
8
|
/**
|
|
11
9
|
* Returns a set of type names that allow access to all fields in the type.
|
|
@@ -37,38 +35,43 @@ const OperationScopeRule = (options) => (context, executionArgs) => {
|
|
|
37
35
|
if (!permissionContext.allowAll &&
|
|
38
36
|
!permissionContext.wildcardTypes.has(objectType.name) &&
|
|
39
37
|
!permissionContext.schemaCoordinates.has(schemaCoordinate)) {
|
|
40
|
-
|
|
38
|
+
// TODO: EnvelopError was a bad idea ;)
|
|
39
|
+
// We should use GraphQLError once the object constructor lands in stable GraphQL.js
|
|
40
|
+
// and useMaskedErrors supports it.
|
|
41
|
+
const error = new core_1.EnvelopError(options.formatError(schemaCoordinate));
|
|
42
|
+
error.nodes = [node];
|
|
43
|
+
context.reportError(error);
|
|
41
44
|
}
|
|
42
45
|
};
|
|
43
46
|
return {
|
|
44
47
|
Field(node) {
|
|
45
48
|
const type = context.getType();
|
|
46
49
|
if (type) {
|
|
47
|
-
const namedType =
|
|
48
|
-
if (
|
|
50
|
+
const namedType = (0, graphql_1.getNamedType)(type);
|
|
51
|
+
if ((0, graphql_1.isIntrospectionType)(namedType)) {
|
|
49
52
|
return false;
|
|
50
53
|
}
|
|
51
54
|
}
|
|
52
55
|
const parentType = context.getParentType();
|
|
53
56
|
if (parentType) {
|
|
54
|
-
if (
|
|
57
|
+
if ((0, graphql_1.isIntrospectionType)(parentType)) {
|
|
55
58
|
return false;
|
|
56
59
|
}
|
|
57
60
|
// We handle objects, interface and union permissions differently.
|
|
58
61
|
// When accessing an an object field, we check simply run the check.
|
|
59
|
-
if (
|
|
62
|
+
if ((0, graphql_1.isObjectType)(parentType)) {
|
|
60
63
|
handleField(node, parentType);
|
|
61
64
|
}
|
|
62
65
|
// To allow a union case, every type in the union has to be allowed/
|
|
63
66
|
// If one of the types doesn't permit access we should throw a validation error.
|
|
64
|
-
if (
|
|
67
|
+
if ((0, graphql_1.isUnionType)(parentType)) {
|
|
65
68
|
for (const objectType of parentType.getTypes()) {
|
|
66
69
|
handleField(node, objectType);
|
|
67
70
|
}
|
|
68
71
|
}
|
|
69
72
|
// Same goes for interfaces. Every implementation should allow the access of the given
|
|
70
73
|
// field to pass the validation rule.
|
|
71
|
-
if (
|
|
74
|
+
if ((0, graphql_1.isInterfaceType)(parentType)) {
|
|
72
75
|
for (const objectType of executionArgs.schema.getImplementations(parentType).objects) {
|
|
73
76
|
handleField(node, objectType);
|
|
74
77
|
}
|
|
@@ -83,14 +86,14 @@ const useOperationFieldPermissions = (opts) => {
|
|
|
83
86
|
return {
|
|
84
87
|
onPluginInit({ addPlugin }) {
|
|
85
88
|
var _a;
|
|
86
|
-
addPlugin(
|
|
89
|
+
addPlugin((0, extended_validation_1.useExtendedValidation)({
|
|
87
90
|
rules: [
|
|
88
91
|
OperationScopeRule({
|
|
89
92
|
formatError: (_a = opts.formatError) !== null && _a !== void 0 ? _a : defaultFormatError,
|
|
90
93
|
}),
|
|
91
94
|
],
|
|
92
95
|
}));
|
|
93
|
-
addPlugin(
|
|
96
|
+
addPlugin((0, core_1.useExtendContext)(async (context) => {
|
|
94
97
|
const permissions = await opts.getPermissions(context);
|
|
95
98
|
// Schema coordinates is a set of type-name field-name strings that
|
|
96
99
|
// describe the position of a field in the schema.
|
|
@@ -108,5 +111,4 @@ const useOperationFieldPermissions = (opts) => {
|
|
|
108
111
|
},
|
|
109
112
|
};
|
|
110
113
|
};
|
|
111
|
-
|
|
112
114
|
exports.useOperationFieldPermissions = useOperationFieldPermissions;
|
package/cjs/package.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type":"commonjs"}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useOperationFieldPermissions = void 0;
|
|
4
|
+
const core_1 = require("@envelop/core");
|
|
5
|
+
const extended_validation_1 = require("@envelop/extended-validation");
|
|
6
|
+
const graphql_1 = require("graphql");
|
|
5
7
|
const OPERATION_PERMISSIONS_SYMBOL = Symbol('OPERATION_PERMISSIONS_SYMBOL');
|
|
6
8
|
/**
|
|
7
9
|
* Returns a set of type names that allow access to all fields in the type.
|
|
@@ -33,38 +35,43 @@ const OperationScopeRule = (options) => (context, executionArgs) => {
|
|
|
33
35
|
if (!permissionContext.allowAll &&
|
|
34
36
|
!permissionContext.wildcardTypes.has(objectType.name) &&
|
|
35
37
|
!permissionContext.schemaCoordinates.has(schemaCoordinate)) {
|
|
36
|
-
|
|
38
|
+
// TODO: EnvelopError was a bad idea ;)
|
|
39
|
+
// We should use GraphQLError once the object constructor lands in stable GraphQL.js
|
|
40
|
+
// and useMaskedErrors supports it.
|
|
41
|
+
const error = new core_1.EnvelopError(options.formatError(schemaCoordinate));
|
|
42
|
+
error.nodes = [node];
|
|
43
|
+
context.reportError(error);
|
|
37
44
|
}
|
|
38
45
|
};
|
|
39
46
|
return {
|
|
40
47
|
Field(node) {
|
|
41
48
|
const type = context.getType();
|
|
42
49
|
if (type) {
|
|
43
|
-
const namedType = getNamedType(type);
|
|
44
|
-
if (isIntrospectionType(namedType)) {
|
|
50
|
+
const namedType = (0, graphql_1.getNamedType)(type);
|
|
51
|
+
if ((0, graphql_1.isIntrospectionType)(namedType)) {
|
|
45
52
|
return false;
|
|
46
53
|
}
|
|
47
54
|
}
|
|
48
55
|
const parentType = context.getParentType();
|
|
49
56
|
if (parentType) {
|
|
50
|
-
if (isIntrospectionType(parentType)) {
|
|
57
|
+
if ((0, graphql_1.isIntrospectionType)(parentType)) {
|
|
51
58
|
return false;
|
|
52
59
|
}
|
|
53
60
|
// We handle objects, interface and union permissions differently.
|
|
54
61
|
// When accessing an an object field, we check simply run the check.
|
|
55
|
-
if (isObjectType(parentType)) {
|
|
62
|
+
if ((0, graphql_1.isObjectType)(parentType)) {
|
|
56
63
|
handleField(node, parentType);
|
|
57
64
|
}
|
|
58
65
|
// To allow a union case, every type in the union has to be allowed/
|
|
59
66
|
// If one of the types doesn't permit access we should throw a validation error.
|
|
60
|
-
if (isUnionType(parentType)) {
|
|
67
|
+
if ((0, graphql_1.isUnionType)(parentType)) {
|
|
61
68
|
for (const objectType of parentType.getTypes()) {
|
|
62
69
|
handleField(node, objectType);
|
|
63
70
|
}
|
|
64
71
|
}
|
|
65
72
|
// Same goes for interfaces. Every implementation should allow the access of the given
|
|
66
73
|
// field to pass the validation rule.
|
|
67
|
-
if (isInterfaceType(parentType)) {
|
|
74
|
+
if ((0, graphql_1.isInterfaceType)(parentType)) {
|
|
68
75
|
for (const objectType of executionArgs.schema.getImplementations(parentType).objects) {
|
|
69
76
|
handleField(node, objectType);
|
|
70
77
|
}
|
|
@@ -79,14 +86,14 @@ const useOperationFieldPermissions = (opts) => {
|
|
|
79
86
|
return {
|
|
80
87
|
onPluginInit({ addPlugin }) {
|
|
81
88
|
var _a;
|
|
82
|
-
addPlugin(useExtendedValidation({
|
|
89
|
+
addPlugin((0, extended_validation_1.useExtendedValidation)({
|
|
83
90
|
rules: [
|
|
84
91
|
OperationScopeRule({
|
|
85
92
|
formatError: (_a = opts.formatError) !== null && _a !== void 0 ? _a : defaultFormatError,
|
|
86
93
|
}),
|
|
87
94
|
],
|
|
88
95
|
}));
|
|
89
|
-
addPlugin(useExtendContext(async (context) => {
|
|
96
|
+
addPlugin((0, core_1.useExtendContext)(async (context) => {
|
|
90
97
|
const permissions = await opts.getPermissions(context);
|
|
91
98
|
// Schema coordinates is a set of type-name field-name strings that
|
|
92
99
|
// describe the position of a field in the schema.
|
|
@@ -104,5 +111,4 @@ const useOperationFieldPermissions = (opts) => {
|
|
|
104
111
|
},
|
|
105
112
|
};
|
|
106
113
|
};
|
|
107
|
-
|
|
108
|
-
export { useOperationFieldPermissions };
|
|
114
|
+
exports.useOperationFieldPermissions = useOperationFieldPermissions;
|
package/package.json
CHANGED
|
@@ -1,36 +1,57 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@envelop/operation-field-permissions",
|
|
3
|
-
"version": "3.4.0-alpha-
|
|
3
|
+
"version": "3.4.0-alpha-e9434aa.0",
|
|
4
4
|
"sideEffects": false,
|
|
5
5
|
"peerDependencies": {
|
|
6
|
-
"@envelop/core": "2.4.0-alpha-
|
|
6
|
+
"@envelop/core": "2.4.0-alpha-e9434aa.0",
|
|
7
7
|
"graphql": "^14.0.0 || ^15.0.0 || ^16.0.0"
|
|
8
8
|
},
|
|
9
9
|
"dependencies": {
|
|
10
|
-
"@envelop/extended-validation": "1.7.0-alpha-
|
|
10
|
+
"@envelop/extended-validation": "1.7.0-alpha-e9434aa.0"
|
|
11
11
|
},
|
|
12
12
|
"repository": {
|
|
13
13
|
"type": "git",
|
|
14
|
-
"url": "https://github.com/
|
|
14
|
+
"url": "https://github.com/n1ru4l/envelop.git",
|
|
15
15
|
"directory": "packages/plugins/operation-field-permissions"
|
|
16
16
|
},
|
|
17
17
|
"author": "Laurin Quast <laurinquast@googlemail.com.com>",
|
|
18
18
|
"license": "MIT",
|
|
19
|
-
"main": "index.js",
|
|
20
|
-
"module": "index.
|
|
21
|
-
"typings": "index.d.ts",
|
|
19
|
+
"main": "cjs/index.js",
|
|
20
|
+
"module": "esm/index.js",
|
|
21
|
+
"typings": "typings/index.d.ts",
|
|
22
22
|
"typescript": {
|
|
23
|
-
"definition": "index.d.ts"
|
|
23
|
+
"definition": "typings/index.d.ts"
|
|
24
24
|
},
|
|
25
|
+
"type": "module",
|
|
25
26
|
"exports": {
|
|
26
27
|
".": {
|
|
27
|
-
"require":
|
|
28
|
-
|
|
28
|
+
"require": {
|
|
29
|
+
"types": "./typings/index.d.ts",
|
|
30
|
+
"default": "./cjs/index.js"
|
|
31
|
+
},
|
|
32
|
+
"import": {
|
|
33
|
+
"types": "./typings/index.d.ts",
|
|
34
|
+
"default": "./esm/index.js"
|
|
35
|
+
},
|
|
36
|
+
"default": {
|
|
37
|
+
"types": "./typings/index.d.ts",
|
|
38
|
+
"default": "./esm/index.js"
|
|
39
|
+
}
|
|
29
40
|
},
|
|
30
41
|
"./*": {
|
|
31
|
-
"require":
|
|
32
|
-
|
|
42
|
+
"require": {
|
|
43
|
+
"types": "./typings/*.d.ts",
|
|
44
|
+
"default": "./cjs/*.js"
|
|
45
|
+
},
|
|
46
|
+
"import": {
|
|
47
|
+
"types": "./typings/*.d.ts",
|
|
48
|
+
"default": "./esm/*.js"
|
|
49
|
+
},
|
|
50
|
+
"default": {
|
|
51
|
+
"types": "./typings/*.d.ts",
|
|
52
|
+
"default": "./esm/*.js"
|
|
53
|
+
}
|
|
33
54
|
},
|
|
34
55
|
"./package.json": "./package.json"
|
|
35
56
|
}
|
|
36
|
-
}
|
|
57
|
+
}
|
|
File without changes
|
package/README.md
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
## `@envelop/operation-field-permissions`
|
|
2
|
-
|
|
3
|
-
Disallow executing operations that select certain fields. Useful if you want to restrict the scope of certain public API users to a subset of the public GraphQL schema, without triggering execution (e.g. how [graphql-shield](https://github.com/maticzav/graphql-shield) works).
|
|
4
|
-
|
|
5
|
-
**Note:** This plugin and authorization on a resolver level (or via middleware) are complementary. You should still verify whether a viewer is allowed to access certain data within your resolvers.
|
|
6
|
-
|
|
7
|
-
## Installation
|
|
8
|
-
|
|
9
|
-
```bash
|
|
10
|
-
yarn add @envelop/operation-field-permissions
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
## Usage Example
|
|
14
|
-
|
|
15
|
-
```ts
|
|
16
|
-
import { envelop, useSchema } from '@envelop/core';
|
|
17
|
-
import { useOperationFieldPermissions } from 'envelop/operation-field-permissions';
|
|
18
|
-
|
|
19
|
-
const getEnveloped = envelop({
|
|
20
|
-
plugins: [
|
|
21
|
-
useSchema(schema),
|
|
22
|
-
useOperationFieldPermissions({
|
|
23
|
-
// we can access graphql context here
|
|
24
|
-
getPermissions: async context => new Set(['Query.greetings', ...context.viewer.permissions]),
|
|
25
|
-
}),
|
|
26
|
-
/* ... other envelops */
|
|
27
|
-
],
|
|
28
|
-
});
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
**Schema**
|
|
32
|
-
|
|
33
|
-
```graphql
|
|
34
|
-
type Query {
|
|
35
|
-
greetings: [String!]!
|
|
36
|
-
foo: String
|
|
37
|
-
}
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
**Operation**
|
|
41
|
-
|
|
42
|
-
```graphql
|
|
43
|
-
query {
|
|
44
|
-
foo
|
|
45
|
-
}
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
**Response**
|
|
49
|
-
|
|
50
|
-
```json
|
|
51
|
-
{
|
|
52
|
-
"data": null,
|
|
53
|
-
"errors": [
|
|
54
|
-
{
|
|
55
|
-
"message": "Insufficient permissions for selecting 'Query.foo'.",
|
|
56
|
-
"locations": [
|
|
57
|
-
{
|
|
58
|
-
"line": 2,
|
|
59
|
-
"column": 2
|
|
60
|
-
}
|
|
61
|
-
]
|
|
62
|
-
}
|
|
63
|
-
]
|
|
64
|
-
}
|
|
65
|
-
```
|