Skip to content

Commit a7fcbc6

Browse files
Fix data stores object parsing (#3895)
* return parsedValue whenever possible * create value prop definition * minor refactors * refactor summaries exports * use Function to evaluate js objects * bump patch versions * fix additional props
1 parent e8e76b6 commit a7fcbc6

File tree

6 files changed

+72
-67
lines changed

6 files changed

+72
-67
lines changed

components/data_stores/actions/add-update-multiple-records/add-update-multiple-records.mjs

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
import app from "../../data_stores.app.mjs";
2-
import xss from "xss";
32

43
export default {
54
key: "data_stores-add-update-multiple-records",
65
name: "Add or update multiple records",
76
description: "Add or update multiple records to your [Pipedream Data Store](https://pipedream.com/data-stores/).",
8-
version: "0.0.4",
7+
version: "0.0.5",
98
type: "action",
109
props: {
1110
app,
@@ -53,13 +52,7 @@ export default {
5352
}
5453
}
5554

56-
// Try to evaluate string as javascript, using xss as extra security
57-
// If some problem occurs, return the original string
58-
try {
59-
return eval(`(${xss(value)})`);
60-
} catch {
61-
return value;
62-
}
55+
return this.app.evaluate(value);
6356
},
6457
/**
6558
* Add all the key-value pairs in the map object to be used in the data store
@@ -68,8 +61,7 @@ export default {
6861
*/
6962
populateHashMapOfData(data, map) {
7063
if (!Array.isArray(data) && typeof(data) === "object") {
71-
Object.keys(data)
72-
.forEach((key) => map[key] = this.convertString(data[key]));
64+
Object.keys(data).forEach((key) => map[key] = this.convertString(data[key]));
7365
return;
7466
}
7567

@@ -87,7 +79,7 @@ export default {
8779
},
8880
async run({ $ }) {
8981
if (typeof this.data === "string") {
90-
this.data = eval(`(${this.data})`);
82+
this.data = this.app.evaluate(this.data);
9183
}
9284
const map = this.getHashMapOfData(this.data);
9385
const keys = Object.keys(map);
@@ -96,7 +88,9 @@ export default {
9688
if (keys.length === 0) {
9789
$.export("$summary", "No data was added to the data store.");
9890
} else {
99-
$.export("$summary", `Successfully added or updated ${keys.length} record(s)`);
91+
// eslint-disable-next-line multiline-ternary
92+
$.export("$summary", `Successfully added or updated ${keys.length} record${keys.length === 1 ? "" : "s"}`);
10093
}
94+
return map;
10195
},
10296
};

components/data_stores/actions/add-update-record/add-update-record.mjs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ export default {
44
key: "data_stores-add-update-record",
55
name: "Add or update a single record",
66
description: "Add or update a single record in your [Pipedream Data Store](https://pipedream.com/data-stores/).",
7-
version: "0.0.7",
7+
version: "0.0.8",
88
type: "action",
99
props: {
1010
app,
@@ -25,24 +25,25 @@ export default {
2525
description: "Enter a key for the record you'd like to create or select an existing key to update.",
2626
},
2727
value: {
28-
label: "Value",
29-
type: "any",
30-
description: "Enter a string, object, or array.",
28+
propDefinition: [
29+
app,
30+
"value",
31+
],
3132
},
3233
},
3334
async run({ $ }) {
3435
const {
3536
key,
3637
value,
3738
} = this;
38-
const record = await this.dataStore.get(key);
39+
const exists = await this.dataStore.has(key);
3940
const parsedValue = this.app.parseValue(value);
4041
await this.dataStore.set(key, parsedValue);
4142
// eslint-disable-next-line multiline-ternary
42-
$.export("$summary", `Successfully ${record ? "updated the record for" : "added a new record with the"} key, \`${key}\`.`);
43+
$.export("$summary", `Successfully ${exists ? "updated the record for" : "added a new record with the"} key, \`${key}\`.`);
4344
return {
4445
key,
45-
value,
46+
value: parsedValue,
4647
};
4748
},
4849
};

components/data_stores/actions/delete-single-record/delete-single-record.mjs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ export default {
44
key: "data_stores-delete-single-record",
55
name: "Delete a single record",
66
description: "Delete a single record in your [Pipedream Data Store](https://pipedream.com/data-stores/).",
7-
version: "0.0.6",
7+
version: "0.0.7",
88
type: "action",
99
props: {
1010
app,
@@ -30,9 +30,10 @@ export default {
3030

3131
if (record) {
3232
await this.dataStore.delete(this.key);
33-
$.export("$summary", "Successfully deleted the record for key, `" + this.key + "`.");
34-
} else {
35-
$.export("$summary", "No record found for key, `" + this.key + "`. No data was deleted.");
33+
$.export("$summary", `Successfully deleted the record for key, \`${this.key}\`.`);
34+
return record;
3635
}
36+
37+
$.export("$summary", `No record found for key, \`${this.key}\`. No data was deleted.`);
3738
},
3839
};

components/data_stores/actions/get-record-or-create/get-record-or-create.mjs

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ export default {
44
key: "data_stores-get-record-or-create",
55
name: "Get record (or create one if not found)",
66
description: "Get a single record in your [Pipedream Data Store](https://pipedream.com/data-stores/) or create one if it doesn't exist.",
7-
version: "0.0.7",
7+
version: "0.0.8",
88
type: "action",
99
props: {
1010
app,
@@ -32,27 +32,28 @@ export default {
3232
},
3333
},
3434
async additionalProps() {
35+
const props = {};
3536
if (this.app.shouldAddRecord(this.addRecordIfNotFound)) {
36-
return this.app.valueProp();
37+
props.value = app.propDefinitions.value;
3738
}
38-
return {};
39+
return props;
3940
},
4041
async run({ $ }) {
4142
const record = await this.dataStore.get(this.key);
4243

4344
if (record) {
44-
$.export("$summary", "Found data for the key, `" + this.key + "`.");
45-
} else {
46-
if (this.app.shouldAddRecord(this.addRecordIfNotFound)) {
47-
const parsedValue = this.app.parseValue(this.value);
48-
await this.dataStore.set(this.key, parsedValue);
49-
$.export("$summary", "Successfully added a new record with the key, `" + this.key + "`.");
50-
return this.dataStore.get(this.key);
51-
} else {
52-
$.export("$summary", "No data found for key, `" + this.key + "`.");
53-
}
45+
$.export("$summary", `Found data for the key, \`${this.key}\`.`);
46+
return record;
5447
}
5548

56-
return record;
49+
if (!this.app.shouldAddRecord(this.addRecordIfNotFound)) {
50+
$.export("$summary", `No data found for key, \`${this.key}\`.`);
51+
return;
52+
}
53+
54+
const parsedValue = this.app.parseValue(this.value);
55+
await this.dataStore.set(this.key, parsedValue);
56+
$.export("$summary", `Successfully added a new record with the key, \`${this.key}\`.`);
57+
return parsedValue;
5758
},
5859
};

components/data_stores/actions/has-key-or-create/has-key-or-create.mjs

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ export default {
44
key: "data_stores-has-key-or-create",
55
name: "Check for existence of key",
66
description: "Check if a key exists in your [Pipedream Data Store](https://pipedream.com/data-stores/) or create one if it doesn't exist.",
7-
version: "0.0.3",
7+
version: "0.0.4",
88
type: "action",
99
props: {
1010
app,
@@ -32,25 +32,26 @@ export default {
3232
},
3333
},
3434
async additionalProps() {
35+
const props = {};
3536
if (this.app.shouldAddRecord(this.addRecordIfNotFound)) {
36-
return this.app.valueProp();
37+
props.value = app.propDefinitions.value;
3738
}
38-
return {};
39+
return props;
3940
},
4041
async run ({ $ }) {
4142
if (await this.dataStore.has(this.key)) {
42-
$.export("$summary", `Key "${this.key}" exists.`);
43+
$.export("$summary", `Key \`${this.key}\` exists.`);
4344
return true;
4445
}
4546

46-
if (this.app.shouldAddRecord(this.addRecordIfNotFound)) {
47-
const parsedValue = this.app.parseValue(this.value);
48-
await this.dataStore.set(this.key, parsedValue);
49-
$.export("$summary", `Key "${this.key}" was not found. Successfully added a new record.`);
50-
return this.dataStore.get(this.key);
47+
if (!this.app.shouldAddRecord(this.addRecordIfNotFound)) {
48+
$.export("$summary", `Key \`${this.key}\` does not exist.`);
49+
return false;
5150
}
5251

53-
$.export("$summary", `Key "${this.key}" does not exist.`);
54-
return false;
52+
const parsedValue = this.app.parseValue(this.value);
53+
await this.dataStore.set(this.key, parsedValue);
54+
$.export("$summary", `Key \`${this.key}\` was not found. Successfully added a new record.`);
55+
return parsedValue;
5556
},
5657
};
Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
import xss from "xss";
2+
3+
/**
4+
* Should support the following data types:
5+
* https://pipedream.com/docs/data-stores/#supported-data-types
6+
*/
7+
18
export default {
29
type: "app",
310
app: "data_stores",
@@ -15,6 +22,11 @@ export default {
1522
return dataStore.keys();
1623
},
1724
},
25+
value: {
26+
label: "Value",
27+
type: "any",
28+
description: "Enter a string, object, or array.",
29+
},
1830
addRecordIfNotFound: {
1931
label: "Create a new record if the key is not found?",
2032
description: "Create a new record if no records are found for the specified key.",
@@ -28,36 +40,31 @@ export default {
2840
},
2941
},
3042
methods: {
43+
// using Function approach instead of eval:
44+
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval#never_use_eval!
45+
evaluate(value) {
46+
try {
47+
return Function(`"use strict"; return (${xss(value)})`)();
48+
} catch (err) {
49+
return value;
50+
}
51+
},
52+
parseJSON(value) {
53+
return JSON.parse(JSON.stringify(this.evaluate(value)));
54+
},
3155
shouldAddRecord(option) {
3256
return option === "Yes";
3357
},
34-
valueProp() {
35-
return {
36-
value: {
37-
label: "Value",
38-
type: "any",
39-
description: "Enter a string, object, or array.",
40-
},
41-
};
42-
},
4358
parseValue(value) {
4459
if (typeof value !== "string") {
4560
return value;
4661
}
4762

4863
try {
49-
return JSON.parse(this.sanitizeJson(value));
64+
return this.parseJSON(value);
5065
} catch (err) {
5166
return value;
5267
}
5368
},
54-
//Because user might enter a JSON as JS object;
55-
//This method converts a JS object string to a JSON string before parsing it
56-
//e.g. {a:"b", 'c':1} => {"a":"b", "c":1}
57-
//We don't use eval here because of security reasons.
58-
//Using eval may cause something undesired run in the script.
59-
sanitizeJson(str) {
60-
return str.replace(/(['"])?([a-z0-9A-Z_]+)(['"])?:/g, "\"$2\": ");
61-
},
6269
},
6370
};

0 commit comments

Comments
 (0)