@smartive/graphql-magic 17.5.0 → 17.5.1
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/CHANGELOG.md +3 -3
- package/dist/cjs/index.cjs +29 -25
- package/dist/esm/permissions/check.js +23 -20
- package/dist/esm/permissions/check.js.map +1 -1
- package/package.json +4 -4
- package/src/permissions/check.ts +42 -35
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
## [17.5.1](https://github.com/smartive/graphql-magic/compare/v17.5.0...v17.5.1) (2025-05-05)
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
###
|
|
4
|
+
### Bug Fixes
|
|
5
5
|
|
|
6
|
-
* field
|
|
6
|
+
* Check field permissions on non relation fields ([#277](https://github.com/smartive/graphql-magic/issues/277)) ([5b04726](https://github.com/smartive/graphql-magic/commit/5b04726deae8a267b6eca61d3138fb98367b2ea0))
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -1835,37 +1835,41 @@ var checkCanWrite = async (ctx, model, data, action) => {
|
|
|
1835
1835
|
}
|
|
1836
1836
|
const query = ctx.knex.select(1).first();
|
|
1837
1837
|
let linked = false;
|
|
1838
|
-
for (const field of model.fields.filter(
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
if (!foreignId) {
|
|
1842
|
-
continue;
|
|
1843
|
-
}
|
|
1838
|
+
for (const field of model.fields.filter(
|
|
1839
|
+
(field2) => field2.generated || (action === "CREATE" ? field2.creatable : field2.updatable)
|
|
1840
|
+
)) {
|
|
1844
1841
|
const fieldPermissions = field[action === "CREATE" ? "creatable" : "updatable"];
|
|
1845
1842
|
const role2 = getRole(ctx);
|
|
1846
|
-
if (fieldPermissions && typeof fieldPermissions === "object" && !fieldPermissions.roles?.includes(role2)) {
|
|
1843
|
+
if (getColumnName(field) in data && fieldPermissions && typeof fieldPermissions === "object" && !fieldPermissions.roles?.includes(role2)) {
|
|
1847
1844
|
throw new PermissionError(role2, action, `this ${model.name}'s ${field.name}`, "field permission not available");
|
|
1848
1845
|
}
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1846
|
+
if (isRelation(field)) {
|
|
1847
|
+
const foreignKey = field.foreignKey || `${field.name}Id`;
|
|
1848
|
+
const foreignId = data[foreignKey];
|
|
1849
|
+
if (!foreignId) {
|
|
1850
|
+
continue;
|
|
1851
|
+
}
|
|
1852
|
+
linked = true;
|
|
1853
|
+
const fieldPermissionStack = getPermissionStack(ctx, field.type, "LINK");
|
|
1854
|
+
if (fieldPermissionStack === true) {
|
|
1855
|
+
query.whereExists((subQuery) => subQuery.from(`${field.type} as a`).whereRaw(`a.id = ?`, foreignId));
|
|
1856
|
+
continue;
|
|
1857
|
+
}
|
|
1858
|
+
if (fieldPermissionStack === false || !fieldPermissionStack.length) {
|
|
1859
|
+
throw new PermissionError(
|
|
1860
|
+
role2,
|
|
1861
|
+
action,
|
|
1862
|
+
`this ${model.name}'s ${field.name}`,
|
|
1863
|
+
"no applicable permissions on data to link"
|
|
1864
|
+
);
|
|
1865
|
+
}
|
|
1866
|
+
ors(
|
|
1867
|
+
query,
|
|
1868
|
+
fieldPermissionStack.map(
|
|
1869
|
+
(links) => (query2) => query2.whereExists((subQuery) => permissionLinkQuery(ctx, subQuery, links, foreignId))
|
|
1870
|
+
)
|
|
1861
1871
|
);
|
|
1862
1872
|
}
|
|
1863
|
-
ors(
|
|
1864
|
-
query,
|
|
1865
|
-
fieldPermissionStack.map(
|
|
1866
|
-
(links) => (query2) => query2.whereExists((subQuery) => permissionLinkQuery(ctx, subQuery, links, foreignId))
|
|
1867
|
-
)
|
|
1868
|
-
);
|
|
1869
1873
|
}
|
|
1870
1874
|
const role = getRole(ctx);
|
|
1871
1875
|
if (linked) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { NotFoundError, PermissionError } from '../errors';
|
|
2
2
|
import { get, isRelation } from '../models/utils';
|
|
3
|
-
import { AliasGenerator, hash, ors } from '../resolvers/utils';
|
|
3
|
+
import { AliasGenerator, getColumnName, hash, ors } from '../resolvers/utils';
|
|
4
4
|
export const getRole = (ctx) => ctx.user?.role ?? 'UNAUTHENTICATED';
|
|
5
5
|
export const getPermissionStack = (ctx, type, action) => {
|
|
6
6
|
const rolePermissions = ctx.permissions[getRole(ctx)];
|
|
@@ -82,30 +82,33 @@ export const checkCanWrite = async (ctx, model, data, action) => {
|
|
|
82
82
|
}
|
|
83
83
|
const query = ctx.knex.select(1).first();
|
|
84
84
|
let linked = false;
|
|
85
|
-
for (const field of model.fields
|
|
86
|
-
.filter(isRelation)
|
|
87
|
-
.filter((field) => field.generated || (action === 'CREATE' ? field.creatable : field.updatable))) {
|
|
88
|
-
const foreignKey = field.foreignKey || `${field.name}Id`;
|
|
89
|
-
const foreignId = data[foreignKey];
|
|
90
|
-
if (!foreignId) {
|
|
91
|
-
continue;
|
|
92
|
-
}
|
|
85
|
+
for (const field of model.fields.filter((field) => field.generated || (action === 'CREATE' ? field.creatable : field.updatable))) {
|
|
93
86
|
const fieldPermissions = field[action === 'CREATE' ? 'creatable' : 'updatable'];
|
|
94
87
|
const role = getRole(ctx);
|
|
95
|
-
if (
|
|
88
|
+
if (getColumnName(field) in data &&
|
|
89
|
+
fieldPermissions &&
|
|
90
|
+
typeof fieldPermissions === 'object' &&
|
|
91
|
+
!fieldPermissions.roles?.includes(role)) {
|
|
96
92
|
throw new PermissionError(role, action, `this ${model.name}'s ${field.name}`, 'field permission not available');
|
|
97
93
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
94
|
+
if (isRelation(field)) {
|
|
95
|
+
const foreignKey = field.foreignKey || `${field.name}Id`;
|
|
96
|
+
const foreignId = data[foreignKey];
|
|
97
|
+
if (!foreignId) {
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
linked = true;
|
|
101
|
+
const fieldPermissionStack = getPermissionStack(ctx, field.type, 'LINK');
|
|
102
|
+
if (fieldPermissionStack === true) {
|
|
103
|
+
// User can link any entity from this type, just check whether it exists
|
|
104
|
+
query.whereExists((subQuery) => subQuery.from(`${field.type} as a`).whereRaw(`a.id = ?`, foreignId));
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
if (fieldPermissionStack === false || !fieldPermissionStack.length) {
|
|
108
|
+
throw new PermissionError(role, action, `this ${model.name}'s ${field.name}`, 'no applicable permissions on data to link');
|
|
109
|
+
}
|
|
110
|
+
ors(query, fieldPermissionStack.map((links) => (query) => query.whereExists((subQuery) => permissionLinkQuery(ctx, subQuery, links, foreignId))));
|
|
107
111
|
}
|
|
108
|
-
ors(query, fieldPermissionStack.map((links) => (query) => query.whereExists((subQuery) => permissionLinkQuery(ctx, subQuery, links, foreignId))));
|
|
109
112
|
}
|
|
110
113
|
const role = getRole(ctx);
|
|
111
114
|
if (linked) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"check.js","sourceRoot":"","sources":["../../../src/permissions/check.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAE3D,OAAO,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"check.js","sourceRoot":"","sources":["../../../src/permissions/check.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@smartive/graphql-magic",
|
|
3
|
-
"version": "17.5.
|
|
3
|
+
"version": "17.5.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"source": "src/index.ts",
|
|
6
6
|
"type": "module",
|
|
@@ -70,12 +70,12 @@
|
|
|
70
70
|
"@types/jest": "29.5.14",
|
|
71
71
|
"@types/lodash": "4.17.16",
|
|
72
72
|
"@types/luxon": "3.6.2",
|
|
73
|
-
"@types/pg": "8.11.
|
|
73
|
+
"@types/pg": "8.11.14",
|
|
74
74
|
"@types/uuid": "10.0.0",
|
|
75
75
|
"create-ts-index": "1.14.0",
|
|
76
76
|
"del-cli": "6.0.0",
|
|
77
|
-
"esbuild": "0.25.
|
|
78
|
-
"eslint": "9.
|
|
77
|
+
"esbuild": "0.25.3",
|
|
78
|
+
"eslint": "9.26.0",
|
|
79
79
|
"jest": "29.7.0",
|
|
80
80
|
"mock-knex": "0.4.13",
|
|
81
81
|
"prettier": "3.5.3",
|
package/src/permissions/check.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { FullContext } from '../context';
|
|
|
3
3
|
import { NotFoundError, PermissionError } from '../errors';
|
|
4
4
|
import { EntityModel } from '../models/models';
|
|
5
5
|
import { get, isRelation } from '../models/utils';
|
|
6
|
-
import { AliasGenerator, hash, ors } from '../resolvers/utils';
|
|
6
|
+
import { AliasGenerator, getColumnName, hash, ors } from '../resolvers/utils';
|
|
7
7
|
import { PermissionAction, PermissionLink, PermissionStack } from './generate';
|
|
8
8
|
|
|
9
9
|
export const getRole = (ctx: Pick<FullContext, 'user'>) => ctx.user?.role ?? 'UNAUTHENTICATED';
|
|
@@ -146,47 +146,54 @@ export const checkCanWrite = async (
|
|
|
146
146
|
const query = ctx.knex.select(1 as any).first();
|
|
147
147
|
let linked = false;
|
|
148
148
|
|
|
149
|
-
for (const field of model.fields
|
|
150
|
-
.
|
|
151
|
-
|
|
152
|
-
const foreignKey = field.foreignKey || `${field.name}Id`;
|
|
153
|
-
const foreignId = data[foreignKey] as string;
|
|
154
|
-
if (!foreignId) {
|
|
155
|
-
continue;
|
|
156
|
-
}
|
|
157
|
-
|
|
149
|
+
for (const field of model.fields.filter(
|
|
150
|
+
(field) => field.generated || (action === 'CREATE' ? field.creatable : field.updatable),
|
|
151
|
+
)) {
|
|
158
152
|
const fieldPermissions = field[action === 'CREATE' ? 'creatable' : 'updatable'];
|
|
159
153
|
const role = getRole(ctx);
|
|
160
|
-
if (
|
|
154
|
+
if (
|
|
155
|
+
getColumnName(field) in data &&
|
|
156
|
+
fieldPermissions &&
|
|
157
|
+
typeof fieldPermissions === 'object' &&
|
|
158
|
+
!fieldPermissions.roles?.includes(role)
|
|
159
|
+
) {
|
|
161
160
|
throw new PermissionError(role, action, `this ${model.name}'s ${field.name}`, 'field permission not available');
|
|
162
161
|
}
|
|
163
162
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
163
|
+
if (isRelation(field)) {
|
|
164
|
+
const foreignKey = field.foreignKey || `${field.name}Id`;
|
|
165
|
+
const foreignId = data[foreignKey] as string;
|
|
166
|
+
if (!foreignId) {
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
linked = true;
|
|
171
|
+
|
|
172
|
+
const fieldPermissionStack = getPermissionStack(ctx, field.type, 'LINK');
|
|
173
|
+
|
|
174
|
+
if (fieldPermissionStack === true) {
|
|
175
|
+
// User can link any entity from this type, just check whether it exists
|
|
176
|
+
|
|
177
|
+
query.whereExists((subQuery) => subQuery.from(`${field.type} as a`).whereRaw(`a.id = ?`, foreignId));
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (fieldPermissionStack === false || !fieldPermissionStack.length) {
|
|
182
|
+
throw new PermissionError(
|
|
183
|
+
role,
|
|
184
|
+
action,
|
|
185
|
+
`this ${model.name}'s ${field.name}`,
|
|
186
|
+
'no applicable permissions on data to link',
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
ors(
|
|
191
|
+
query,
|
|
192
|
+
fieldPermissionStack.map(
|
|
193
|
+
(links) => (query) => query.whereExists((subQuery) => permissionLinkQuery(ctx, subQuery, links, foreignId)),
|
|
194
|
+
),
|
|
181
195
|
);
|
|
182
196
|
}
|
|
183
|
-
|
|
184
|
-
ors(
|
|
185
|
-
query,
|
|
186
|
-
fieldPermissionStack.map(
|
|
187
|
-
(links) => (query) => query.whereExists((subQuery) => permissionLinkQuery(ctx, subQuery, links, foreignId)),
|
|
188
|
-
),
|
|
189
|
-
);
|
|
190
197
|
}
|
|
191
198
|
|
|
192
199
|
const role = getRole(ctx);
|