diff --git a/components/virifi/actions/add-member/add-member.mjs b/components/virifi/actions/add-member/add-member.mjs new file mode 100644 index 0000000000000..21627181ee67f --- /dev/null +++ b/components/virifi/actions/add-member/add-member.mjs @@ -0,0 +1,55 @@ +import app from "../../virifi.app.mjs"; + +export default { + key: "virifi-add-member", + name: "Add Member", + description: "Adds a new member to your organization. [See the documentation](https://virifi.io/open/api-guide).", + version: "0.0.1", + type: "action", + props: { + app, + email: { + type: "string", + label: "Email", + description: "The e-mail address of the new member.", + }, + firstName: { + type: "string", + label: "First Name", + description: "The first name of the new member.", + }, + lastName: { + type: "string", + label: "Last Name", + description: "The last name of the new member.", + optional: true, + }, + }, + methods: { + addMember(args = {}) { + return this.app.post({ + path: "/add-member", + ...args, + }); + }, + }, + async run({ $ }) { + const { + addMember, + email, + firstName, + lastName, + } = this; + + const response = await addMember({ + $, + data: { + email, + firstName, + lastName, + }, + }); + $.export("$summary", "Successfully sent invitation to the new member."); + return response; + }, +}; diff --git a/components/virifi/actions/certify-document/certify-document.mjs b/components/virifi/actions/certify-document/certify-document.mjs new file mode 100644 index 0000000000000..544c3cff44730 --- /dev/null +++ b/components/virifi/actions/certify-document/certify-document.mjs @@ -0,0 +1,90 @@ +import fs from "fs"; +import FormData from "form-data"; +import { ConfigurationError } from "@pipedream/platform"; +import app from "../../virifi.app.mjs"; + +export default { + key: "virifi-certify-document", + name: "Certify Document", + description: "Triggers the process for sending a PDF document for certification. For this operation, the user must provide the PDF document. In addition, the user can optionally specify the authenticators for this document. [See the documentation](https://virifi.io/open/api-guide)", + version: "0.0.1", + type: "action", + props: { + app, + folderName: { + type: "string", + label: "Folder Name", + description: "The name of the folder where the document will be stored.", + }, + digitalTwin: { + propDefinition: [ + app, + "digitalTwin", + ], + }, + totalDoc: { + type: "integer", + label: "Total Doc", + description: "The total number of documents.", + reloadProps: true, + default: 1, + }, + }, + additionalProps() { + const { totalDoc } = this; + + if (totalDoc > 5) { + throw new ConfigurationError("The maximum number of documents is 5."); + } + + return Array.from({ + length: totalDoc, + }).reduce((acc, _, index) => { + return Object.assign(acc, { + [`doc${index}`]: { + type: "string", + label: `File Path Document ${index + 1}`, + description: "The document to be sent for certification. This should be the path to the file saved to the `/tmp` directory (e.g. `/tmp/example.pdf`). [See the documentation](https://pipedream.com/docs/workflows/steps/code/nodejs/working-with-files/#the-tmp-directory).", + }, + }); + }, {}); + }, + methods: { + certifyDocument(args = {}) { + return this.app.post({ + path: "/certify-document", + ...args, + }); + }, + }, + async run({ $ }) { + const { + certifyDocument, + folderName, + digitalTwin, + totalDoc, + ...props + } = this; + + const form = new FormData(); + form.append("folderName", folderName); + form.append("digitalTwin", String(digitalTwin)); + form.append("totalDoc", String(totalDoc)); + + Array.from({ + length: totalDoc, + }).forEach((_, index) => { + const value = fs.createReadStream(props[`doc${index}`]); + form.append(`doc${index}`, value); + }); + + const response = await certifyDocument({ + $, + data: form, + headers: form.getHeaders(), + }); + + $.export("$summary", "Document certified successfully"); + return response; + }, +}; diff --git a/components/virifi/actions/sign-document/sign-document.mjs b/components/virifi/actions/sign-document/sign-document.mjs new file mode 100644 index 0000000000000..a7719b311450f --- /dev/null +++ b/components/virifi/actions/sign-document/sign-document.mjs @@ -0,0 +1,87 @@ +import fs from "fs"; +import FormData from "form-data"; +import app from "../../virifi.app.mjs"; +import constants from "../../common/constants.mjs"; + +export default { + key: "virifi-sign-document", + name: "Sign Document", + description: "Enables the sending process of a PDF document for signing. Upload the PDF document and specify the participants who need to sign the document, if any. [See the documentation](https://virifi.io/open/api-guide)", + version: "0.0.1", + type: "action", + props: { + app, + fileName: { + type: "string", + label: "File Name", + description: "The name of the file to be sent for signing.", + }, + digitalTwin: { + propDefinition: [ + app, + "digitalTwin", + ], + }, + doc: { + type: "string", + label: "Document", + description: "The PDF document to be sent for signing. This should be the path to the file saved to the `/tmp` directory (e.g. `/tmp/example.pdf`). [See the documentation](https://pipedream.com/docs/workflows/steps/code/nodejs/working-with-files/#the-tmp-directory).", + }, + signBy: { + type: "string", + label: "Sign By", + description: "The participants who need to sign the document.", + options: Object.values(constants.SIGN_BY_OPTION), + }, + signUser: { + type: "string[]", + label: "Sign Users", + description: "The participants who need to sign the document where each row should contain at least the email address of the participant in JSON format. Eg. `{\"email\":\"user@company.com\",\"number\":\"1234567890\"}`. The account owner's email address should be listed as the first entry when selecting `signByYourself` or `signAndInviteOthers` in the **Sign By** property.", + }, + signatureType: { + type: "string", + label: "Signature Type", + description: "The type of signature to use.", + options: Object.values(constants.SIGNATURE_TYPE_OPTION), + }, + }, + methods: { + signDocument(args = {}) { + return this.app.post({ + path: "/sign-document", + headers: { + "Content-Type": "multipart/form-data", + }, + ...args, + }); + }, + }, + async run({ $ }) { + const { + signDocument, + doc, + fileName, + digitalTwin, + signBy, + signUser, + signatureType, + } = this; + + const form = new FormData(); + form.append("doc", fs.createReadStream(doc)); + form.append("fileName", fileName); + form.append("digitalTwin", String(digitalTwin)); + form.append("signBy", signBy); + form.append("signUser", JSON.stringify(signUser)); + form.append("signatureType", signatureType); + + const response = await signDocument({ + $, + data: form, + headers: form.getHeaders(), + }); + + $.export("$summary", "Document sent for signing successfully"); + return response; + }, +}; diff --git a/components/virifi/common/constants.mjs b/components/virifi/common/constants.mjs new file mode 100644 index 0000000000000..0d4fb90540b4b --- /dev/null +++ b/components/virifi/common/constants.mjs @@ -0,0 +1,29 @@ +const BASE_URL = "https://virifi.io"; +const VERSION_PATH = "/api/developer"; + +const SIGN_BY_OPTION = { + SIGN_BY_YOURSELF: { + label: "Sing By Yourself", + value: "signByYourself", + }, + SIGN_AND_INVITE_OTHERS: { + label: "Sign And Invite Others", + value: "signAndInviteOthers", + }, + SIGN_OTHER: { + label: "Sign Other", + value: "signOther", + }, +}; + +const SIGNATURE_TYPE_OPTION = { + AES: "AES", + PES: "PES", +}; + +export default { + BASE_URL, + VERSION_PATH, + SIGN_BY_OPTION, + SIGNATURE_TYPE_OPTION, +}; diff --git a/components/virifi/common/utils.mjs b/components/virifi/common/utils.mjs new file mode 100644 index 0000000000000..33ffd024d2494 --- /dev/null +++ b/components/virifi/common/utils.mjs @@ -0,0 +1,47 @@ +import { ConfigurationError } from "@pipedream/platform"; + +function emptyStrToUndefined(value) { + const trimmed = typeof(value) === "string" && value.trim(); + return trimmed === "" + ? undefined + : value; +} + +function parse(value) { + const valueToParse = emptyStrToUndefined(value); + if (typeof(valueToParse) === "object" || valueToParse === undefined) { + return valueToParse; + } + try { + return JSON.parse(valueToParse); + } catch (e) { + throw new ConfigurationError("Make sure the custom expression contains a valid object"); + } +} + +function parseArray(value) { + try { + if (!value) { + return []; + } + + if (Array.isArray(value)) { + return value; + } + + const parsedValue = JSON.parse(value); + + if (!Array.isArray(parsedValue)) { + throw new Error("Not an array"); + } + + return parsedValue; + + } catch (e) { + throw new ConfigurationError("Make sure the custom expression contains a valid array object"); + } +} + +export default { + parseArray: (value) => parseArray(value).map(parse), +}; diff --git a/components/virifi/package.json b/components/virifi/package.json index b4c8bbdcadcb7..55e54153c2d82 100644 --- a/components/virifi/package.json +++ b/components/virifi/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/virifi", - "version": "0.0.1", + "version": "0.1.0", "description": "Pipedream Virifi Components", "main": "virifi.app.mjs", "keywords": [ @@ -11,5 +11,10 @@ "author": "Pipedream (https://pipedream.com/)", "publishConfig": { "access": "public" + }, + "dependencies": { + "@pipedream/platform": "3.0.1", + "form-data": "^4.0.0", + "fs": "^0.0.1-security" } -} \ No newline at end of file +} diff --git a/components/virifi/virifi.app.mjs b/components/virifi/virifi.app.mjs index 2f40b6c2ce6b9..d262de8059412 100644 --- a/components/virifi/virifi.app.mjs +++ b/components/virifi/virifi.app.mjs @@ -1,11 +1,41 @@ +import { axios } from "@pipedream/platform"; +import constants from "./common/constants.mjs"; + export default { type: "app", app: "virifi", - propDefinitions: {}, + propDefinitions: { + digitalTwin: { + type: "boolean", + label: "Digital Twin", + description: "Whether to create a digital twin of the document.", + default: false, + }, + }, methods: { - // this.$auth contains connected account data - authKeys() { - console.log(Object.keys(this.$auth)); + getUrl(path) { + return `${constants.BASE_URL}${constants.VERSION_PATH}${path}`; + }, + getHeaders(headers) { + return { + "Authorization": `Bearer ${this.$auth.api_key}`, + ...headers, + }; + }, + _makeRequest({ + $ = this, path, headers, ...args + } = {}) { + return axios($, { + ...args, + url: this.getUrl(path), + headers: this.getHeaders(headers), + }); + }, + post(args = {}) { + return this._makeRequest({ + method: "POST", + ...args, + }); }, }, -}; \ No newline at end of file +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 29ab5043c849e..2a5295e7c9688 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -10491,7 +10491,14 @@ importers: '@pipedream/platform': 1.5.1 components/virifi: - specifiers: {} + specifiers: + '@pipedream/platform': 3.0.1 + form-data: ^4.0.0 + fs: ^0.0.1-security + dependencies: + '@pipedream/platform': 3.0.1 + form-data: 4.0.0 + fs: 0.0.1-security components/virustotal: specifiers: {}