Skip to content

Commit 06d4f36

Browse files
committed
[Components] moaform #14132
Sources - New Submission (Instant)
1 parent 6437ac6 commit 06d4f36

File tree

4 files changed

+122
-99
lines changed

4 files changed

+122
-99
lines changed

components/moaform/moaform.app.mjs

Lines changed: 30 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -8,75 +8,61 @@ export default {
88
type: "string",
99
label: "Form ID",
1010
description: "The ID of the form to monitor for new submissions",
11-
async options() {
12-
const forms = await this.getForms();
13-
return forms.map((form) => ({
14-
label: form.name,
15-
value: form.id,
11+
async options({ page }) {
12+
const { items } = await this.getForms({
13+
params: {
14+
page: page + 1,
15+
},
16+
});
17+
return items.map(({
18+
id: value, title: label,
19+
}) => ({
20+
label,
21+
value,
1622
}));
1723
},
1824
},
19-
fields: {
20-
type: "string[]",
21-
label: "Fields to Capture",
22-
description: "Optional fields to capture from the submission",
23-
optional: true,
24-
},
2525
},
2626
methods: {
27-
authKeys() {
28-
console.log(Object.keys(this.$auth));
29-
},
3027
_baseUrl() {
31-
return "https://api.moaform.com";
28+
return "https://api.moaform.com/v1";
29+
},
30+
_headers() {
31+
return {
32+
Authorization: `Bearer ${this.$auth.api_key}`,
33+
};
3234
},
33-
async _makeRequest(opts = {}) {
34-
const {
35-
$ = this, method = "GET", path = "/", headers, ...otherOpts
36-
} = opts;
35+
_makeRequest({
36+
$ = this, path, ...opts
37+
}) {
3738
return axios($, {
38-
...otherOpts,
39-
method,
4039
url: this._baseUrl() + path,
41-
headers: {
42-
...headers,
43-
Authorization: `Bearer ${this.$auth.api_token}`,
44-
},
40+
headers: this._headers(),
41+
...opts,
4542
});
4643
},
47-
async getForms(opts = {}) {
44+
getForms(opts = {}) {
4845
return this._makeRequest({
4946
...opts,
5047
path: "/forms",
5148
});
5249
},
53-
async createWebhook(opts = {}) {
54-
const {
55-
formId, url, fields,
56-
} = opts;
50+
createWebhook({
51+
formId, ...opts
52+
}) {
5753
return this._makeRequest({
5854
method: "POST",
5955
path: `/forms/${formId}/webhooks`,
60-
data: {
61-
url,
62-
fields,
63-
},
56+
...opts,
6457
});
6558
},
66-
async deleteWebhook(opts = {}) {
67-
const {
68-
formId, webhookId,
69-
} = opts;
59+
deleteWebhook({
60+
formId, webhookId,
61+
}) {
7062
return this._makeRequest({
7163
method: "DELETE",
7264
path: `/forms/${formId}/webhooks/${webhookId}`,
7365
});
7466
},
75-
async getWebhooks(opts = {}) {
76-
const { formId } = opts;
77-
return this._makeRequest({
78-
path: `/forms/${formId}/webhooks`,
79-
});
80-
},
8167
},
8268
};

components/moaform/package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@pipedream/moaform",
3-
"version": "0.0.1",
3+
"version": "0.1.0",
44
"description": "Pipedream Moaform Components",
55
"main": "moaform.app.mjs",
66
"keywords": [
@@ -11,5 +11,8 @@
1111
"author": "Pipedream <[email protected]> (https://pipedream.com/)",
1212
"publishConfig": {
1313
"access": "public"
14+
},
15+
"dependencies": {
16+
"@pipedream/platform": "^3.0.3"
1417
}
1518
}
Lines changed: 70 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,71 @@
1-
import { axios } from "@pipedream/platform";
1+
import crypto from "crypto";
22
import moaform from "../../moaform.app.mjs";
3+
import sampleEmit from "./test-event.mjs";
34

45
export default {
56
key: "moaform-new-submission-instant",
6-
name: "New Submission Instant",
7-
description: "Emit new event every time a new form submission is received. [See the documentation](https://help.moaform.com)",
7+
name: "New Submission (Instant)",
8+
description: "Emit new event every time a new form submission is received.",
89
version: "0.0.1",
910
type: "source",
1011
dedupe: "unique",
1112
props: {
1213
moaform,
14+
http: {
15+
type: "$.interface.http",
16+
customResponse: true,
17+
},
1318
db: "$.service.db",
1419
formId: {
1520
propDefinition: [
1621
moaform,
1722
"formId",
1823
],
1924
},
20-
fields: {
21-
propDefinition: [
22-
moaform,
23-
"fields",
25+
retentionDays: {
26+
type: "integer",
27+
label: "Retention Days",
28+
description: "Resend restriction days",
29+
options: [
30+
1,
31+
3,
32+
5,
33+
7,
34+
10,
35+
15,
36+
30,
2437
],
38+
optional: true,
2539
},
26-
httpSource: {
27-
type: "$.interface.http",
28-
label: "HTTP Source",
29-
description: "HTTP source to set up webhooks",
40+
secret: {
41+
type: "string",
42+
label: "Secret Code",
43+
description: "This code is used to verify that the data received at the specified endpoint has indeed been sent from Moaform and has not been tampered with.",
44+
secret: true,
45+
optional: true,
3046
},
3147
},
32-
hooks: {
33-
async deploy() {
34-
const webhooks = await this.moaform.getWebhooks({
35-
formId: this.formId,
36-
});
37-
38-
for (const webhook of webhooks) {
39-
this.$emit(webhook, {
40-
id: webhook.id,
41-
summary: `Existing webhook: ${webhook.id}`,
42-
ts: Date.now(),
43-
});
44-
}
48+
methods: {
49+
_getWebhookId() {
50+
return this.db.get("webhookId");
51+
},
52+
_setWebhookId(id) {
53+
this.db.set("webhookId", id);
4554
},
55+
},
56+
hooks: {
4657
async activate() {
47-
const {
48-
formId, fields,
49-
} = this;
50-
const url = this.httpSource.url;
51-
const webhook = await this.moaform.createWebhook({
52-
formId,
53-
url,
54-
fields,
58+
const response = await this.moaform.createWebhook({
59+
formId: this.formId,
60+
data: {
61+
endpoint: this.http.endpoint,
62+
enabled: true,
63+
secret: this.secret,
64+
verify_ssl: true,
65+
retention_days: this.retentionDays,
66+
},
5567
});
56-
57-
this.db.set("webhookId", webhook.id);
68+
this._setWebhookId(response.id);
5869
},
5970
async deactivate() {
6071
const webhookId = this.db.get("webhookId");
@@ -64,28 +75,33 @@ export default {
6475
});
6576
},
6677
},
67-
async run(event) {
68-
const {
69-
headers, body,
70-
} = event;
71-
const id = headers["x-moaform-submission-id"];
72-
const formId = body.formId;
73-
const submissionFields = this.fields.length ?
74-
this.fields.reduce((acc, field) => ({
75-
...acc,
76-
[field]: body.fields[field],
77-
}), {})
78-
: body.fields;
78+
async run({
79+
bodyRaw, body, headers,
80+
}) {
81+
82+
if (this.secret) {
83+
const signature = headers["moaform-signature"];
84+
const receivedSig = signature.split("sha256=")[1];
85+
86+
const calculatedSig = crypto
87+
.createHmac("sha256", this.secret)
88+
.update(bodyRaw)
89+
.digest("base64");
7990

80-
const eventToEmit = {
81-
formId,
82-
...submissionFields,
83-
};
91+
if (receivedSig !== calculatedSig) {
92+
return this.http.respond({
93+
status: 401,
94+
body: "Unauthorized",
95+
});
96+
}
97+
}
8498

85-
this.$emit(eventToEmit, {
86-
id,
87-
summary: `New submission received for form ${formId}`,
88-
ts: Date.now(),
99+
const ts = Date.parse(body.submitted_at);
100+
this.$emit(body, {
101+
id: body.event_id,
102+
summary: `New submission received for form ${this.formId}`,
103+
ts: ts,
89104
});
90105
},
106+
sampleEmit,
91107
};
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
export default {
2+
"event_id": "105fa72f-9e6e-4667-8ead-22b0a3ed254a",
3+
"event_type": "response_completed",
4+
"hidden": {},
5+
"response_id": "test#123-45-67890",
6+
"submitted_at": "2024-09-27T21:00:55Z",
7+
"form": {
8+
"id": "MG7eAk",
9+
"title": "form title",
10+
"report_url": "https://www.moaform.com/reports/q945EegynYD8G2xM",
11+
"answer_url": "https://moaform.com/q/not-started-collecting"
12+
},
13+
"answers": [],
14+
"thankyou": {
15+
"id": "cm1l7axyf2t9x0fqrly27vdn7",
16+
"url": "https://answer.moaform.com/answers/MG7eAk/thankyou/Wo2b1Z09wx5"
17+
}
18+
}

0 commit comments

Comments
 (0)