next-data-kit 7.2.0 → 7.3.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/README.md +8 -1
- package/dist/{action-C-MJOe6-.d.cts → action-De2eEXMg.d.cts} +1 -0
- package/dist/{action-C-MJOe6-.d.ts → action-De2eEXMg.d.ts} +1 -0
- package/dist/index.cjs +10 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +10 -3
- package/dist/index.js.map +1 -1
- package/dist/server.cjs +10 -3
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +2 -2
- package/dist/server.d.ts +2 -2
- package/dist/server.js +10 -3
- package/dist/server.js.map +1 -1
- package/dist/types/index.d.cts +2 -2
- package/dist/types/server/action.d.ts +1 -0
- package/dist/types/server/action.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -292,6 +292,7 @@ dataKitServerAction({
|
|
|
292
292
|
maxLimit?: number, // Default: 100
|
|
293
293
|
queryAllowed?: string[], // Whitelist for query fields
|
|
294
294
|
filterAllowed?: string[], // Auto-derived from filterCustom
|
|
295
|
+
sortAllowed?: string[], // Whitelist for sortable fields
|
|
295
296
|
});
|
|
296
297
|
```
|
|
297
298
|
|
|
@@ -320,12 +321,13 @@ dataKitServerAction({
|
|
|
320
321
|
maxLimit?: number,
|
|
321
322
|
queryAllowed?: string[],
|
|
322
323
|
filterAllowed?: string[],
|
|
324
|
+
sortAllowed?: string[],
|
|
323
325
|
});
|
|
324
326
|
```
|
|
325
327
|
|
|
326
328
|
### Security & Filtering
|
|
327
329
|
|
|
328
|
-
**
|
|
330
|
+
**Three security whitelists:**
|
|
329
331
|
|
|
330
332
|
1. **`filterCustom`** - User-facing filters (search, dropdowns, etc.)
|
|
331
333
|
- Client `filters` prop → validated against `filterCustom` keys
|
|
@@ -335,6 +337,10 @@ dataKitServerAction({
|
|
|
335
337
|
- Explicit whitelist required
|
|
336
338
|
- Use for: `{ active: true }`, user-specific queries
|
|
337
339
|
|
|
340
|
+
3. **`sortAllowed`** - Sortable fields whitelist
|
|
341
|
+
- Prevents sorting on arbitrary/sensitive fields
|
|
342
|
+
- Recommended for production security
|
|
343
|
+
|
|
338
344
|
```typescript
|
|
339
345
|
dataKitServerAction({
|
|
340
346
|
model: UserModel,
|
|
@@ -345,6 +351,7 @@ dataKitServerAction({
|
|
|
345
351
|
role: value => ({ role: value }),
|
|
346
352
|
},
|
|
347
353
|
queryAllowed: ['organizationId', 'active'],
|
|
354
|
+
sortAllowed: ['name', 'email', 'createdAt'], // Only allow sorting these fields
|
|
348
355
|
});
|
|
349
356
|
```
|
|
350
357
|
|
package/dist/index.cjs
CHANGED
|
@@ -179,7 +179,7 @@ var mongooseAdapter = (model, options = {}) => {
|
|
|
179
179
|
};
|
|
180
180
|
|
|
181
181
|
// src/server/action.ts
|
|
182
|
-
async function executeDataKit(input, adapter, item, maxLimit, filterAllowed, queryAllowed) {
|
|
182
|
+
async function executeDataKit(input, adapter, item, maxLimit, filterAllowed, queryAllowed, sortAllowed) {
|
|
183
183
|
if (input.query) {
|
|
184
184
|
const safeQuery = {};
|
|
185
185
|
Object.keys(input.query).forEach((key) => {
|
|
@@ -212,6 +212,13 @@ async function executeDataKit(input, adapter, item, maxLimit, filterAllowed, que
|
|
|
212
212
|
});
|
|
213
213
|
input.filter = safeFilter;
|
|
214
214
|
}
|
|
215
|
+
if (input.sorts && sortAllowed) {
|
|
216
|
+
input.sorts.forEach((sort) => {
|
|
217
|
+
if (!sortAllowed.includes(sort.path)) {
|
|
218
|
+
throw new Error(`[Security] Sort field '${sort.path}' is not allowed.`);
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
}
|
|
215
222
|
switch (input.action ?? "FETCH") {
|
|
216
223
|
case "FETCH": {
|
|
217
224
|
if (!input.limit || !input.page) {
|
|
@@ -239,7 +246,7 @@ async function executeDataKit(input, adapter, item, maxLimit, filterAllowed, que
|
|
|
239
246
|
}
|
|
240
247
|
}
|
|
241
248
|
async function dataKitServerAction(props) {
|
|
242
|
-
const { input, item, maxLimit = 100, queryAllowed, filterAllowed: explicitFilterAllowed } = props;
|
|
249
|
+
const { input, item, maxLimit = 100, queryAllowed, filterAllowed: explicitFilterAllowed, sortAllowed } = props;
|
|
243
250
|
const filterCustom = "filterCustom" in props ? props.filterCustom : void 0;
|
|
244
251
|
const filterAllowed = explicitFilterAllowed ?? (filterCustom ? Object.keys(filterCustom) : void 0);
|
|
245
252
|
let finalAdapter;
|
|
@@ -255,7 +262,7 @@ async function dataKitServerAction(props) {
|
|
|
255
262
|
} else {
|
|
256
263
|
throw new Error("Either model or adapter must be provided");
|
|
257
264
|
}
|
|
258
|
-
return executeDataKit(input, finalAdapter, item, maxLimit, filterAllowed, queryAllowed);
|
|
265
|
+
return executeDataKit(input, finalAdapter, item, maxLimit, filterAllowed, queryAllowed, sortAllowed);
|
|
259
266
|
}
|
|
260
267
|
|
|
261
268
|
// src/server/adapters/memory.ts
|