@adminforth/import-export 1.5.0 → 1.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/dist/index.d.ts +1 -0
- package/dist/index.js +43 -4
- package/index.ts +70 -4
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ export default class ImportExport extends AdminForthPlugin {
|
|
|
10
10
|
constructor(options: PluginOptions);
|
|
11
11
|
private isRowValid;
|
|
12
12
|
private tryToAuditLogAction;
|
|
13
|
+
private ensureAnyAllowed;
|
|
13
14
|
modifyResourceConfig(adminforth: IAdminForth, resourceConfig: AdminForthResource): Promise<void>;
|
|
14
15
|
validateConfigAfterDiscover(adminforth: IAdminForth, resourceConfig: AdminForthResource): void;
|
|
15
16
|
instanceUniqueRepresentation(pluginOptions: any): string;
|
package/dist/index.js
CHANGED
|
@@ -7,7 +7,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
7
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
|
-
import { AdminForthPlugin, suggestIfTypo, AdminForthFilterOperators, Filters, AdminForthDataTypes, rejectApiRawFilters } from "adminforth";
|
|
10
|
+
import { AdminForthPlugin, suggestIfTypo, AdminForthFilterOperators, Filters, AdminForthDataTypes, rejectApiRawFilters, interpretResource, ActionCheckSource, AllowedActionsEnum } from "adminforth";
|
|
11
11
|
import pLimit from 'p-limit';
|
|
12
12
|
export default class ImportExport extends AdminForthPlugin {
|
|
13
13
|
constructor(options) {
|
|
@@ -53,6 +53,20 @@ export default class ImportExport extends AdminForthPlugin {
|
|
|
53
53
|
console.error('Failed to log action to AuditLogPlugin:', e);
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
|
+
ensureAnyAllowed(adminUser_1, checks_1) {
|
|
57
|
+
return __awaiter(this, arguments, void 0, function* (adminUser, checks, meta = {}) {
|
|
58
|
+
for (const { source, action } of checks) {
|
|
59
|
+
const { allowedActions } = yield interpretResource(adminUser, this.resourceConfig, meta, source, this.adminforth);
|
|
60
|
+
if (allowedActions[action] === true) {
|
|
61
|
+
return { ok: true };
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return {
|
|
65
|
+
ok: false,
|
|
66
|
+
error: 'Action is not allowed',
|
|
67
|
+
};
|
|
68
|
+
});
|
|
69
|
+
}
|
|
56
70
|
modifyResourceConfig(adminforth, resourceConfig) {
|
|
57
71
|
const _super = Object.create(null, {
|
|
58
72
|
modifyResourceConfig: { get: () => super.modifyResourceConfig }
|
|
@@ -101,6 +115,13 @@ export default class ImportExport extends AdminForthPlugin {
|
|
|
101
115
|
path: `/plugin/${this.pluginInstanceId}/export-csv`,
|
|
102
116
|
handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, headers }) {
|
|
103
117
|
const { filters, sort } = body;
|
|
118
|
+
const access = yield this.ensureAnyAllowed(adminUser, [
|
|
119
|
+
{ source: ActionCheckSource.ListRequest, action: AllowedActionsEnum.list },
|
|
120
|
+
{ source: ActionCheckSource.ShowRequest, action: AllowedActionsEnum.show },
|
|
121
|
+
], { requestBody: body });
|
|
122
|
+
if (!access.ok) {
|
|
123
|
+
return { ok: false, error: access.error };
|
|
124
|
+
}
|
|
104
125
|
const rawFilterError = rejectApiRawFilters(body.filters);
|
|
105
126
|
if (rawFilterError) {
|
|
106
127
|
return rawFilterError;
|
|
@@ -138,7 +159,13 @@ export default class ImportExport extends AdminForthPlugin {
|
|
|
138
159
|
path: `/plugin/${this.pluginInstanceId}/import-csv`,
|
|
139
160
|
handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, query, headers, cookies, requestUrl, response }) {
|
|
140
161
|
const { data } = body;
|
|
141
|
-
|
|
162
|
+
const createEditAccess = yield this.ensureAnyAllowed(adminUser, [
|
|
163
|
+
{ source: ActionCheckSource.CreateRequest, action: AllowedActionsEnum.create },
|
|
164
|
+
{ source: ActionCheckSource.EditRequest, action: AllowedActionsEnum.edit }
|
|
165
|
+
], { requestBody: body });
|
|
166
|
+
if (!createEditAccess.ok) {
|
|
167
|
+
return { ok: false, error: createEditAccess.error };
|
|
168
|
+
}
|
|
142
169
|
const columns = this.getColumnNames(data);
|
|
143
170
|
const { errors, resourceColumns } = this.validateColumns(columns);
|
|
144
171
|
const resource = this.adminforth.config.resources.find(r => r.resourceId === this.resourceConfig.resourceId);
|
|
@@ -148,6 +175,7 @@ export default class ImportExport extends AdminForthPlugin {
|
|
|
148
175
|
const primaryKeyColumn = this.resourceConfig.columns.find(col => col.primaryKey);
|
|
149
176
|
const rows = this.buildRowsFromData(data, columns, resourceColumns, { coerceTypes: true });
|
|
150
177
|
console.log('Prepared rows for import:', rows);
|
|
178
|
+
this.tryToAuditLogAction('import', `Import CSV with ${Object.keys(data).length} columns`, adminUser, headers);
|
|
151
179
|
let importedCount = 0;
|
|
152
180
|
let updatedCount = 0;
|
|
153
181
|
const limit = pLimit(100);
|
|
@@ -200,7 +228,10 @@ export default class ImportExport extends AdminForthPlugin {
|
|
|
200
228
|
path: `/plugin/${this.pluginInstanceId}/import-csv-new-only`,
|
|
201
229
|
handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, query, headers, cookies, requestUrl, response }) {
|
|
202
230
|
const { data } = body;
|
|
203
|
-
this.
|
|
231
|
+
const access = yield this.ensureAnyAllowed(adminUser, [{ source: ActionCheckSource.CreateRequest, action: AllowedActionsEnum.create }], { requestBody: body });
|
|
232
|
+
if (!access.ok) {
|
|
233
|
+
return { ok: false, error: access.error };
|
|
234
|
+
}
|
|
204
235
|
const columns = this.getColumnNames(data);
|
|
205
236
|
const resource = this.adminforth.config.resources.find(r => r.resourceId === this.resourceConfig.resourceId);
|
|
206
237
|
const { errors, resourceColumns } = this.validateColumns(columns);
|
|
@@ -209,6 +240,7 @@ export default class ImportExport extends AdminForthPlugin {
|
|
|
209
240
|
}
|
|
210
241
|
const primaryKeyColumn = this.resourceConfig.columns.find(col => col.primaryKey);
|
|
211
242
|
const rows = this.buildRowsFromData(data, columns, resourceColumns, { coerceTypes: true });
|
|
243
|
+
this.tryToAuditLogAction('import', `Import CSV (new only) with ${Object.keys(data).length} columns`, adminUser, headers);
|
|
212
244
|
let importedCount = 0;
|
|
213
245
|
const limit = pLimit(100);
|
|
214
246
|
yield Promise.all(rows.map((row) => limit(() => __awaiter(this, void 0, void 0, function* () {
|
|
@@ -243,7 +275,14 @@ export default class ImportExport extends AdminForthPlugin {
|
|
|
243
275
|
server.endpoint({
|
|
244
276
|
method: 'POST',
|
|
245
277
|
path: `/plugin/${this.pluginInstanceId}/check-records`,
|
|
246
|
-
handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body }) {
|
|
278
|
+
handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser }) {
|
|
279
|
+
const access = yield this.ensureAnyAllowed(adminUser, [
|
|
280
|
+
{ source: ActionCheckSource.ListRequest, action: AllowedActionsEnum.list },
|
|
281
|
+
{ source: ActionCheckSource.ShowRequest, action: AllowedActionsEnum.show },
|
|
282
|
+
], { requestBody: body });
|
|
283
|
+
if (!access.ok) {
|
|
284
|
+
return { ok: false, error: access.error };
|
|
285
|
+
}
|
|
247
286
|
const { data } = body;
|
|
248
287
|
const primaryKeyColumn = this.resourceConfig.columns.find(col => col.primaryKey);
|
|
249
288
|
const columns = this.getColumnNames(data);
|
package/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AdminForthPlugin, suggestIfTypo, AdminForthFilterOperators, Filters, AdminForthDataTypes, rejectApiRawFilters } from "adminforth";
|
|
1
|
+
import { AdminForthPlugin, suggestIfTypo, AdminForthFilterOperators, Filters, AdminForthDataTypes, rejectApiRawFilters, interpretResource, ActionCheckSource, AllowedActionsEnum } from "adminforth";
|
|
2
2
|
import type { IAdminForth, IHttpServer, AdminForthResourceColumn, AdminForthComponentDeclaration, AdminForthResource, AdminUser } from "adminforth";
|
|
3
3
|
import type { PluginOptions } from './types.js';
|
|
4
4
|
import pLimit from 'p-limit';
|
|
@@ -57,6 +57,31 @@ export default class ImportExport extends AdminForthPlugin {
|
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
+
private async ensureAnyAllowed(
|
|
61
|
+
adminUser: AdminUser,
|
|
62
|
+
checks: { source: ActionCheckSource; action: AllowedActionsEnum }[],
|
|
63
|
+
meta: Record<string, unknown> = {}
|
|
64
|
+
): Promise<{ ok: boolean; error?: string }> {
|
|
65
|
+
for (const { source, action } of checks) {
|
|
66
|
+
const { allowedActions } = await interpretResource(
|
|
67
|
+
adminUser,
|
|
68
|
+
this.resourceConfig,
|
|
69
|
+
meta,
|
|
70
|
+
source,
|
|
71
|
+
this.adminforth
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
if (allowedActions[action] === true) {
|
|
75
|
+
return { ok: true };
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return {
|
|
80
|
+
ok: false,
|
|
81
|
+
error: 'Action is not allowed',
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
60
85
|
async modifyResourceConfig(adminforth: IAdminForth, resourceConfig: AdminForthResource) {
|
|
61
86
|
super.modifyResourceConfig(adminforth, resourceConfig);
|
|
62
87
|
if (!resourceConfig.options.pageInjections) {
|
|
@@ -104,6 +129,17 @@ export default class ImportExport extends AdminForthPlugin {
|
|
|
104
129
|
path: `/plugin/${this.pluginInstanceId}/export-csv`,
|
|
105
130
|
handler: async ({ body, adminUser, headers }) => {
|
|
106
131
|
const { filters, sort } = body;
|
|
132
|
+
const access = await this.ensureAnyAllowed(
|
|
133
|
+
adminUser,
|
|
134
|
+
[
|
|
135
|
+
{ source: ActionCheckSource.ListRequest, action: AllowedActionsEnum.list },
|
|
136
|
+
{ source: ActionCheckSource.ShowRequest, action: AllowedActionsEnum.show },
|
|
137
|
+
],
|
|
138
|
+
{ requestBody: body }
|
|
139
|
+
);
|
|
140
|
+
if (!access.ok) {
|
|
141
|
+
return { ok: false, error: access.error };
|
|
142
|
+
}
|
|
107
143
|
const rawFilterError = rejectApiRawFilters(body.filters);
|
|
108
144
|
if (rawFilterError) {
|
|
109
145
|
return rawFilterError;
|
|
@@ -148,7 +184,17 @@ export default class ImportExport extends AdminForthPlugin {
|
|
|
148
184
|
path: `/plugin/${this.pluginInstanceId}/import-csv`,
|
|
149
185
|
handler: async ({ body, adminUser, query, headers, cookies, requestUrl, response }) => {
|
|
150
186
|
const { data } = body;
|
|
151
|
-
|
|
187
|
+
const createEditAccess = await this.ensureAnyAllowed(
|
|
188
|
+
adminUser,
|
|
189
|
+
[
|
|
190
|
+
{ source: ActionCheckSource.CreateRequest, action: AllowedActionsEnum.create },
|
|
191
|
+
{ source: ActionCheckSource.EditRequest, action: AllowedActionsEnum.edit }
|
|
192
|
+
],
|
|
193
|
+
{ requestBody: body }
|
|
194
|
+
);
|
|
195
|
+
if (!createEditAccess.ok) {
|
|
196
|
+
return { ok: false, error: createEditAccess.error };
|
|
197
|
+
}
|
|
152
198
|
const columns = this.getColumnNames(data);
|
|
153
199
|
const { errors, resourceColumns } = this.validateColumns(columns);
|
|
154
200
|
const resource = this.adminforth.config.resources.find(r => r.resourceId === this.resourceConfig.resourceId);
|
|
@@ -160,6 +206,7 @@ export default class ImportExport extends AdminForthPlugin {
|
|
|
160
206
|
const rows = this.buildRowsFromData(data, columns, resourceColumns, { coerceTypes: true });
|
|
161
207
|
|
|
162
208
|
console.log('Prepared rows for import:', rows);
|
|
209
|
+
this.tryToAuditLogAction('import', `Import CSV with ${Object.keys(data).length} columns`, adminUser, headers);
|
|
163
210
|
|
|
164
211
|
let importedCount = 0;
|
|
165
212
|
let updatedCount = 0;
|
|
@@ -216,7 +263,14 @@ export default class ImportExport extends AdminForthPlugin {
|
|
|
216
263
|
path: `/plugin/${this.pluginInstanceId}/import-csv-new-only`,
|
|
217
264
|
handler: async ({ body, adminUser, query, headers, cookies, requestUrl, response }) => {
|
|
218
265
|
const { data } = body;
|
|
219
|
-
|
|
266
|
+
const access = await this.ensureAnyAllowed(
|
|
267
|
+
adminUser,
|
|
268
|
+
[{ source: ActionCheckSource.CreateRequest, action: AllowedActionsEnum.create }],
|
|
269
|
+
{ requestBody: body }
|
|
270
|
+
);
|
|
271
|
+
if (!access.ok) {
|
|
272
|
+
return { ok: false, error: access.error };
|
|
273
|
+
}
|
|
220
274
|
const columns = this.getColumnNames(data);
|
|
221
275
|
const resource = this.adminforth.config.resources.find(r => r.resourceId === this.resourceConfig.resourceId);
|
|
222
276
|
const { errors, resourceColumns } = this.validateColumns(columns);
|
|
@@ -226,6 +280,7 @@ export default class ImportExport extends AdminForthPlugin {
|
|
|
226
280
|
|
|
227
281
|
const primaryKeyColumn = this.resourceConfig.columns.find(col => col.primaryKey);
|
|
228
282
|
const rows = this.buildRowsFromData(data, columns, resourceColumns, { coerceTypes: true });
|
|
283
|
+
this.tryToAuditLogAction('import', `Import CSV (new only) with ${Object.keys(data).length} columns`, adminUser, headers);
|
|
229
284
|
|
|
230
285
|
let importedCount = 0;
|
|
231
286
|
const limit = pLimit(100);
|
|
@@ -264,7 +319,18 @@ export default class ImportExport extends AdminForthPlugin {
|
|
|
264
319
|
server.endpoint({
|
|
265
320
|
method: 'POST',
|
|
266
321
|
path: `/plugin/${this.pluginInstanceId}/check-records`,
|
|
267
|
-
handler: async ({ body }) => {
|
|
322
|
+
handler: async ({ body, adminUser }) => {
|
|
323
|
+
const access = await this.ensureAnyAllowed(
|
|
324
|
+
adminUser,
|
|
325
|
+
[
|
|
326
|
+
{ source: ActionCheckSource.ListRequest, action: AllowedActionsEnum.list },
|
|
327
|
+
{ source: ActionCheckSource.ShowRequest, action: AllowedActionsEnum.show },
|
|
328
|
+
],
|
|
329
|
+
{ requestBody: body }
|
|
330
|
+
);
|
|
331
|
+
if (!access.ok) {
|
|
332
|
+
return { ok: false, error: access.error };
|
|
333
|
+
}
|
|
268
334
|
const { data } = body as { data: Record<string, unknown[]> };
|
|
269
335
|
const primaryKeyColumn = this.resourceConfig.columns.find(col => col.primaryKey);
|
|
270
336
|
const columns = this.getColumnNames(data);
|