Compare commits

...
40 Commits
Author SHA1 Message Date
AndrewandGitHub 096d5962a3 Merge pull request #1221 from OpenSignLabs/validation 2024-09-19 11:30:35 +05:30
prafull-opensignlabs 9ea36f94a7 fix: enableOTP not working properly in template 2024-09-19 11:28:13 +05:30
AndrewandGitHub 2b66df992f Merge pull request #1220 from OpenSignLabs/validation 2024-09-19 10:27:18 +05:30
prafull-opensignlabs ff3c31975e refactor: remove extra space 2024-09-19 10:26:35 +05:30
AndrewandGitHub beaa5eca69 Merge pull request #1219 from OpenSignLabs/validation 2024-09-18 21:17:16 +05:30
prafull-opensignlabs b98040faac fix: document decline event not trigger on revoke 2024-09-18 21:15:31 +05:30
AndrewandGitHub fbbff0df61 Merge pull request #1218 from OpenSignLabs/validation 2024-09-18 19:57:46 +05:30
prafull-opensignlabs 07d5f393c0 fix: document viewed event not trigger 2024-09-18 19:56:47 +05:30
AndrewandGitHub 8220b15a29 Merge pull request #1217 from OpenSignLabs/validation
refactor: add enableOTP in allowedkeys in update doc
2024-09-18 19:27:42 +05:30
prafull-opensignlabs 7cf638b2be refactor: add enableOTP in allowedkeys in update doc 2024-09-18 19:22:41 +05:30
prafull-opensignlabsandGitHub 30fb8f31e3 Merge pull request #1216 from OpenSignLabs/validation
fix: blank page appear when try to add typed signature
2024-09-18 18:10:37 +05:30
prafull-opensignlabs ec4d875547 fix: blank page appear when try to add typed signature 2024-09-18 18:09:18 +05:30
AndrewandGitHub 43eee63df2 Merge pull request #1215 from OpenSignLabs/validation 2024-09-18 14:36:30 +05:30
prafull-opensignlabs 4caf9f598a refactor: change variable from isDisableOTP to isEnableOTP 2024-09-18 14:32:45 +05:30
AndrewandGitHub 107eaca8f0 Merge pull request #1213 from OpenSignLabs/validation
feat: add disable OTP feature to directly sign document without verification
2024-09-17 18:31:15 +05:30
prafull-opensignlabs cc11848346 feat: add disable OTP feature to directly sign document without verification 2024-09-17 18:27:21 +05:30
ZathielandGitHub c8ecd34bd3 Merge pull request #1148 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/lint-staged-15.2.10
build(deps-dev): bump lint-staged from 15.2.9 to 15.2.10 in /apps/OpenSign
2024-09-13 20:00:31 +02:00
ZathielandGitHub d4a4eb3248 Merge pull request #1182 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSignServer/mongoose-8.6.1
build(deps): bump mongoose from 8.6.0 to 8.6.1 in /apps/OpenSignServer
2024-09-13 20:00:01 +02:00
ZathielandGitHub f782733397 Merge pull request #1186 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSignServer/jasmine-5.3.0
build(deps-dev): bump jasmine from 5.2.0 to 5.3.0 in /apps/OpenSignServer
2024-09-13 19:59:13 +02:00
ZathielandGitHub 7720eddc47 Merge pull request #1183 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSignServer/nodemailer-6.9.15
build(deps): bump nodemailer from 6.9.14 to 6.9.15 in /apps/OpenSignServer
2024-09-13 19:58:58 +02:00
AndrewandGitHub 71170a373a Merge pull request #1205 from OpenSignLabs/validation 2024-09-13 12:58:49 +05:30
prafull-opensignlabs 8f080080a7 refactor: changes in text of modal 2024-09-13 12:57:23 +05:30
AndrewandGitHub 71b2958c14 Merge pull request #1204 from OpenSignLabs/validation 2024-09-13 10:56:58 +05:30
prafull-opensignlabs f69aafcbfa refactor: provide userdetails 2024-09-13 10:52:22 +05:30
AndrewandGitHub 5f6a423697 Merge pull request #1203 from OpenSignLabs/validation 2024-09-12 13:29:39 +05:30
prafull-opensignlabs 5d245927c4 fix: user count is not correct 2024-09-12 13:25:11 +05:30
prafull-opensignlabsandGitHub 17c96fb849 Merge pull request #1201 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSignServer/npm_and_yarn-d7ff1d4c1a
build(deps): bump the npm_and_yarn group in /apps/OpenSignServer with 2 updates
2024-09-12 12:07:50 +05:30
prafull-opensignlabsandGitHub b7c28cdf36 Merge pull request #1202 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/npm_and_yarn-cf87d80143
build(deps): bump the npm_and_yarn group in /apps/OpenSign with 2 updates
2024-09-12 12:07:17 +05:30
dependabot[bot]andGitHub d05aa0d350 build(deps): bump the npm_and_yarn group
Bumps the npm_and_yarn group in /apps/OpenSign with 2 updates: [send](https://github.com/pillarjs/send) and [express](https://github.com/expressjs/express).


Updates `send` from 0.18.0 to 0.19.0
- [Release notes](https://github.com/pillarjs/send/releases)
- [Changelog](https://github.com/pillarjs/send/blob/master/HISTORY.md)
- [Commits](https://github.com/pillarjs/send/compare/0.18.0...0.19.0)

Updates `express` from 4.20.0 to 4.21.0
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/4.21.0/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.20.0...4.21.0)

---
updated-dependencies:
- dependency-name: send
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: express
  dependency-type: indirect
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-12 06:34:33 +00:00
prafull-opensignlabsandGitHub 875dc086bf Merge pull request #1195 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/npm_and_yarn-31414ddb3e
build(deps): bump the npm_and_yarn group in /apps/OpenSign with 4 updates
2024-09-12 12:02:55 +05:30
dependabot[bot]andGitHub 4719ebd52a build(deps): bump the npm_and_yarn group
Bumps the npm_and_yarn group in /apps/OpenSignServer with 2 updates: [express](https://github.com/expressjs/express) and [dset](https://github.com/lukeed/dset).


Updates `express` from 4.20.0 to 4.21.0
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/4.21.0/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.20.0...4.21.0)

Updates `dset` from 3.1.3 to 3.1.4
- [Release notes](https://github.com/lukeed/dset/releases)
- [Commits](https://github.com/lukeed/dset/compare/v3.1.3...v3.1.4)

---
updated-dependencies:
- dependency-name: express
  dependency-type: direct:production
  dependency-group: npm_and_yarn
- dependency-name: dset
  dependency-type: indirect
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-11 23:46:04 +00:00
AndrewandGitHub c8a436a7df Merge pull request #1200 from OpenSignLabs/validation 2024-09-11 20:10:47 +05:30
prafull-opensignlabs 8d6f4dd64e fix: issue user count 2024-09-11 20:10:19 +05:30
AndrewandGitHub 63486927d6 Merge pull request #1199 from OpenSignLabs/validation 2024-09-11 17:54:59 +05:30
prafull-opensignlabs c36a70f8d3 refactor: add user validation 2024-09-11 17:50:39 +05:30
dependabot[bot]andGitHub 6cb30a6597 build(deps): bump the npm_and_yarn group
Bumps the npm_and_yarn group in /apps/OpenSign with 4 updates: [body-parser](https://github.com/expressjs/body-parser), [express](https://github.com/expressjs/express), [path-to-regexp](https://github.com/pillarjs/path-to-regexp) and [serve-static](https://github.com/expressjs/serve-static).


Updates `body-parser` from 1.20.2 to 1.20.3
- [Release notes](https://github.com/expressjs/body-parser/releases)
- [Changelog](https://github.com/expressjs/body-parser/blob/master/HISTORY.md)
- [Commits](https://github.com/expressjs/body-parser/compare/1.20.2...1.20.3)

Updates `express` from 4.19.2 to 4.20.0
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/master/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.19.2...4.20.0)

Updates `express` from 4.19.2 to 4.20.0
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/master/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.19.2...4.20.0)

Updates `path-to-regexp` from 0.1.7 to 0.1.10
- [Release notes](https://github.com/pillarjs/path-to-regexp/releases)
- [Changelog](https://github.com/pillarjs/path-to-regexp/blob/master/History.md)
- [Commits](https://github.com/pillarjs/path-to-regexp/compare/v0.1.7...v0.1.10)

Updates `serve-static` from 1.15.0 to 1.16.0
- [Release notes](https://github.com/expressjs/serve-static/releases)
- [Changelog](https://github.com/expressjs/serve-static/blob/master/HISTORY.md)
- [Commits](https://github.com/expressjs/serve-static/compare/v1.15.0...1.16.0)

---
updated-dependencies:
- dependency-name: body-parser
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: express
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: express
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: path-to-regexp
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: serve-static
  dependency-type: indirect
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-11 04:58:46 +00:00
dependabot[bot]andGitHub bc89b33468 build(deps-dev): bump lint-staged in /apps/OpenSign
Bumps [lint-staged](https://github.com/lint-staged/lint-staged) from 15.2.9 to 15.2.10.
- [Release notes](https://github.com/lint-staged/lint-staged/releases)
- [Changelog](https://github.com/lint-staged/lint-staged/blob/master/CHANGELOG.md)
- [Commits](https://github.com/lint-staged/lint-staged/compare/v15.2.9...v15.2.10)

---
updated-dependencies:
- dependency-name: lint-staged
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-11 04:58:17 +00:00
dependabot[bot]andGitHub ff2f7f6586 build(deps-dev): bump jasmine in /apps/OpenSignServer
Bumps [jasmine](https://github.com/jasmine/jasmine-npm) from 5.2.0 to 5.3.0.
- [Release notes](https://github.com/jasmine/jasmine-npm/releases)
- [Changelog](https://github.com/jasmine/jasmine-npm/blob/main/RELEASE.md)
- [Commits](https://github.com/jasmine/jasmine-npm/compare/v5.2.0...v5.3.0)

---
updated-dependencies:
- dependency-name: jasmine
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-09 00:12:15 +00:00
dependabot[bot]andGitHub 93f33d73d9 build(deps): bump nodemailer in /apps/OpenSignServer
Bumps [nodemailer](https://github.com/nodemailer/nodemailer) from 6.9.14 to 6.9.15.
- [Release notes](https://github.com/nodemailer/nodemailer/releases)
- [Changelog](https://github.com/nodemailer/nodemailer/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nodemailer/nodemailer/compare/v6.9.14...v6.9.15)

---
updated-dependencies:
- dependency-name: nodemailer
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-09 00:11:47 +00:00
dependabot[bot]andGitHub 402c176277 build(deps): bump mongoose from 8.6.0 to 8.6.1 in /apps/OpenSignServer
Bumps [mongoose](https://github.com/Automattic/mongoose) from 8.6.0 to 8.6.1.
- [Release notes](https://github.com/Automattic/mongoose/releases)
- [Changelog](https://github.com/Automattic/mongoose/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Automattic/mongoose/compare/8.6.0...8.6.1)

---
updated-dependencies:
- dependency-name: mongoose
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-09 00:11:41 +00:00
51 changed files with 1663 additions and 1024 deletions
+69 -42
View File
@@ -77,7 +77,7 @@
"eslint": "^8.57.0", "eslint": "^8.57.0",
"eslint-plugin-prettier": "^5.2.1", "eslint-plugin-prettier": "^5.2.1",
"eslint-plugin-react": "^7.34.3", "eslint-plugin-react": "^7.34.3",
"lint-staged": "^15.2.8", "lint-staged": "^15.2.10",
"mini-css-extract-plugin": "^2.9.1", "mini-css-extract-plugin": "^2.9.1",
"postcss": "^8.4.45", "postcss": "^8.4.45",
"prettier": "^3.3.3", "prettier": "^3.3.3",
@@ -7592,9 +7592,9 @@
"integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="
}, },
"node_modules/body-parser": { "node_modules/body-parser": {
"version": "1.20.2", "version": "1.20.3",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz",
"integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==",
"dependencies": { "dependencies": {
"bytes": "3.1.2", "bytes": "3.1.2",
"content-type": "~1.0.5", "content-type": "~1.0.5",
@@ -7604,7 +7604,7 @@
"http-errors": "2.0.0", "http-errors": "2.0.0",
"iconv-lite": "0.4.24", "iconv-lite": "0.4.24",
"on-finished": "2.4.1", "on-finished": "2.4.1",
"qs": "6.11.0", "qs": "6.13.0",
"raw-body": "2.5.2", "raw-body": "2.5.2",
"type-is": "~1.6.18", "type-is": "~1.6.18",
"unpipe": "1.0.0" "unpipe": "1.0.0"
@@ -11040,36 +11040,36 @@
} }
}, },
"node_modules/express": { "node_modules/express": {
"version": "4.19.2", "version": "4.21.0",
"resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", "resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz",
"integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", "integrity": "sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==",
"dependencies": { "dependencies": {
"accepts": "~1.3.8", "accepts": "~1.3.8",
"array-flatten": "1.1.1", "array-flatten": "1.1.1",
"body-parser": "1.20.2", "body-parser": "1.20.3",
"content-disposition": "0.5.4", "content-disposition": "0.5.4",
"content-type": "~1.0.4", "content-type": "~1.0.4",
"cookie": "0.6.0", "cookie": "0.6.0",
"cookie-signature": "1.0.6", "cookie-signature": "1.0.6",
"debug": "2.6.9", "debug": "2.6.9",
"depd": "2.0.0", "depd": "2.0.0",
"encodeurl": "~1.0.2", "encodeurl": "~2.0.0",
"escape-html": "~1.0.3", "escape-html": "~1.0.3",
"etag": "~1.8.1", "etag": "~1.8.1",
"finalhandler": "1.2.0", "finalhandler": "1.3.1",
"fresh": "0.5.2", "fresh": "0.5.2",
"http-errors": "2.0.0", "http-errors": "2.0.0",
"merge-descriptors": "1.0.1", "merge-descriptors": "1.0.3",
"methods": "~1.1.2", "methods": "~1.1.2",
"on-finished": "2.4.1", "on-finished": "2.4.1",
"parseurl": "~1.3.3", "parseurl": "~1.3.3",
"path-to-regexp": "0.1.7", "path-to-regexp": "0.1.10",
"proxy-addr": "~2.0.7", "proxy-addr": "~2.0.7",
"qs": "6.11.0", "qs": "6.13.0",
"range-parser": "~1.2.1", "range-parser": "~1.2.1",
"safe-buffer": "5.2.1", "safe-buffer": "5.2.1",
"send": "0.18.0", "send": "0.19.0",
"serve-static": "1.15.0", "serve-static": "1.16.2",
"setprototypeof": "1.2.0", "setprototypeof": "1.2.0",
"statuses": "2.0.1", "statuses": "2.0.1",
"type-is": "~1.6.18", "type-is": "~1.6.18",
@@ -11099,15 +11099,23 @@
"ms": "2.0.0" "ms": "2.0.0"
} }
}, },
"node_modules/express/node_modules/encodeurl": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
"integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/express/node_modules/ms": { "node_modules/express/node_modules/ms": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
}, },
"node_modules/express/node_modules/path-to-regexp": { "node_modules/express/node_modules/path-to-regexp": {
"version": "0.1.7", "version": "0.1.10",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz",
"integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w=="
}, },
"node_modules/express/node_modules/range-parser": { "node_modules/express/node_modules/range-parser": {
"version": "1.2.1", "version": "1.2.1",
@@ -11374,12 +11382,12 @@
} }
}, },
"node_modules/finalhandler": { "node_modules/finalhandler": {
"version": "1.2.0", "version": "1.3.1",
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz",
"integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==",
"dependencies": { "dependencies": {
"debug": "2.6.9", "debug": "2.6.9",
"encodeurl": "~1.0.2", "encodeurl": "~2.0.0",
"escape-html": "~1.0.3", "escape-html": "~1.0.3",
"on-finished": "2.4.1", "on-finished": "2.4.1",
"parseurl": "~1.3.3", "parseurl": "~1.3.3",
@@ -11398,6 +11406,14 @@
"ms": "2.0.0" "ms": "2.0.0"
} }
}, },
"node_modules/finalhandler/node_modules/encodeurl": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
"integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/finalhandler/node_modules/ms": { "node_modules/finalhandler/node_modules/ms": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
@@ -16287,9 +16303,9 @@
"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="
}, },
"node_modules/lint-staged": { "node_modules/lint-staged": {
"version": "15.2.9", "version": "15.2.10",
"resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.9.tgz", "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.10.tgz",
"integrity": "sha512-BZAt8Lk3sEnxw7tfxM7jeZlPRuT4M68O0/CwZhhaw6eeWu0Lz5eERE3m386InivXB64fp/mDID452h48tvKlRQ==", "integrity": "sha512-5dY5t743e1byO19P9I4b3x8HJwalIznL5E1FWYnU6OWw33KxNBSLAc6Cy7F2PsFEO8FKnLwjwm5hx7aMF0jzZg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"chalk": "~5.3.0", "chalk": "~5.3.0",
@@ -16298,7 +16314,7 @@
"execa": "~8.0.1", "execa": "~8.0.1",
"lilconfig": "~3.1.2", "lilconfig": "~3.1.2",
"listr2": "~8.2.4", "listr2": "~8.2.4",
"micromatch": "~4.0.7", "micromatch": "~4.0.8",
"pidtree": "~0.6.0", "pidtree": "~0.6.0",
"string-argv": "~0.3.2", "string-argv": "~0.3.2",
"yaml": "~2.5.0" "yaml": "~2.5.0"
@@ -16908,9 +16924,12 @@
"dev": true "dev": true
}, },
"node_modules/merge-descriptors": { "node_modules/merge-descriptors": {
"version": "1.0.1", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz",
"integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==",
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
}, },
"node_modules/merge-refs": { "node_modules/merge-refs": {
"version": "1.3.0", "version": "1.3.0",
@@ -19758,11 +19777,11 @@
} }
}, },
"node_modules/qs": { "node_modules/qs": {
"version": "6.11.0", "version": "6.13.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz",
"integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==",
"dependencies": { "dependencies": {
"side-channel": "^1.0.4" "side-channel": "^1.0.6"
}, },
"engines": { "engines": {
"node": ">=0.6" "node": ">=0.6"
@@ -22319,9 +22338,9 @@
} }
}, },
"node_modules/send": { "node_modules/send": {
"version": "0.18.0", "version": "0.19.0",
"resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz",
"integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==",
"dependencies": { "dependencies": {
"debug": "2.6.9", "debug": "2.6.9",
"depd": "2.0.0", "depd": "2.0.0",
@@ -22504,19 +22523,27 @@
} }
}, },
"node_modules/serve-static": { "node_modules/serve-static": {
"version": "1.15.0", "version": "1.16.2",
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz",
"integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==",
"dependencies": { "dependencies": {
"encodeurl": "~1.0.2", "encodeurl": "~2.0.0",
"escape-html": "~1.0.3", "escape-html": "~1.0.3",
"parseurl": "~1.3.3", "parseurl": "~1.3.3",
"send": "0.18.0" "send": "0.19.0"
}, },
"engines": { "engines": {
"node": ">= 0.8.0" "node": ">= 0.8.0"
} }
}, },
"node_modules/serve-static/node_modules/encodeurl": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
"integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/serve/node_modules/ajv": { "node_modules/serve/node_modules/ajv": {
"version": "8.12.0", "version": "8.12.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
+1 -1
View File
@@ -109,7 +109,7 @@
"eslint": "^8.57.0", "eslint": "^8.57.0",
"eslint-plugin-prettier": "^5.2.1", "eslint-plugin-prettier": "^5.2.1",
"eslint-plugin-react": "^7.34.3", "eslint-plugin-react": "^7.34.3",
"lint-staged": "^15.2.8", "lint-staged": "^15.2.10",
"mini-css-extract-plugin": "^2.9.1", "mini-css-extract-plugin": "^2.9.1",
"postcss": "^8.4.45", "postcss": "^8.4.45",
"prettier": "^3.3.3", "prettier": "^3.3.3",
@@ -635,7 +635,17 @@
"quota-mail": "You've reached your limit of 15 signature request emails for this month. Upgrade now to continue sending emails directly.", "quota-mail": "You've reached your limit of 15 signature request emails for this month. Upgrade now to continue sending emails directly.",
"quota-mail-tip":"Tip: You can still sign <1>unlimited documents</1> by manually sharing the signing request links.", "quota-mail-tip":"Tip: You can still sign <1>unlimited documents</1> by manually sharing the signing request links.",
"quota-mail-head":"Quota Reached", "quota-mail-head":"Quota Reached",
"unauthorized-modal":"You don't have permission to perform this action, please contact {{adminName}}<{{adminEmail}}>.", "unauthorized-modal":"You don't have permission to perform this action, please contact {{adminEmail}}.",
"sent-this-month":"Sent this month" "sent-this-month":"Sent this month",
"available-seats":"Available seats",
"buy-users":"Buy more users",
"isenable-otp": "Enable OTP verification",
"isenable-otp-help": {
"p1": "Would you like to enable the verification process using a one-time password (OTP)?",
"p2": "Selecting this option will enable OTP verification. Users will receive a verification code via email, which they must enter to sign the document.",
"p3": "Selecting this option will disable OTP verification, allowing users to sign the document directly without additional steps.",
"p4": "Please choose the option that best suits your document signing requirements."
},
"advanced-options":"Advanced options",
"hide-advanced-options":"Hide Advanced options"
} }
@@ -634,7 +634,18 @@
"quota-mail": "Vous avez atteint votre limite de 15 e-mails de demande de signature pour ce mois. Mettez à niveau maintenant pour continuer à envoyer des e-mails directement.", "quota-mail": "Vous avez atteint votre limite de 15 e-mails de demande de signature pour ce mois. Mettez à niveau maintenant pour continuer à envoyer des e-mails directement.",
"quota-mail-tip-tip":"Astuce : Vous pouvez toujours signer un nombre <1>illimité de documents</1> en partageant manuellement les liens de demande de signature.", "quota-mail-tip-tip":"Astuce : Vous pouvez toujours signer un nombre <1>illimité de documents</1> en partageant manuellement les liens de demande de signature.",
"quota-mail-head":"Quota atteint", "quota-mail-head":"Quota atteint",
"unauthorized-modal":"Vous n'êtes pas autorisé à effectuer cette action, veuillez contacter {{adminName}}<{{adminEmail}}>.", "unauthorized-modal":"Vous n'êtes pas autorisé à effectuer cette action, veuillez contacter {{adminEmail}}.",
"sent-this-month":"envoyé ce mois-ci" "sent-this-month":"envoyé ce mois-ci",
"available-seats":"Disponible sièges",
"buy-users":"Acheter plus d'utilisateurs",
"isenable-otp": "Activer la vérification OTP",
"isenable-otp-help": {
"p1": "Souhaitez-vous activer le processus de vérification à l'aide d'un mot de passe à usage unique (OTP)?",
"p2": "La sélection de cette option activera la vérification OTP. Les utilisateurs recevront un code de vérification par e-mail, qu'ils devront saisir pour signer le document.",
"p3": "La sélection de cette option désactivera la vérification OTP, permettant aux utilisateurs de signer le document directement sans étapes supplémentaires.",
"p4": "Veuillez choisir l'option qui correspond le mieux à vos exigences en matière de signature de documents."
},
"advanced-options":"Options avancées",
"hide-advanced-options": "Masquer les options avancées"
} }
+4 -2
View File
@@ -301,6 +301,9 @@ const AddUser = (props) => {
setAllowedUser(amount.quantity); setAllowedUser(amount.quantity);
setPlanInfo((obj) => ({ ...obj, totalAllowedUser: _resAddon.addon })); setPlanInfo((obj) => ({ ...obj, totalAllowedUser: _resAddon.addon }));
} }
if (props.handleBuyUsers) {
props.handleBuyUsers(amount.quantity, _resAddon.addon);
}
} }
} catch (err) { } catch (err) {
console.log("Err in buy addon", err); console.log("Err in buy addon", err);
@@ -495,8 +498,7 @@ const AddUser = (props) => {
{planInfo.adminId !== extUser?.objectId ? ( {planInfo.adminId !== extUser?.objectId ? (
<div className="mb-3 mt-1 flex justify-center text-center items-center font-medium break-all"> <div className="mb-3 mt-1 flex justify-center text-center items-center font-medium break-all">
{t("unauthorized-modal", { {t("unauthorized-modal", {
adminName: extUser?.CreatedBy?.name, adminEmail: extUser?.TenantId?.EmailAddress
adminEmail: extUser?.CreatedBy?.email
})} })}
</div> </div>
) : ( ) : (
+2 -7
View File
@@ -31,7 +31,6 @@ const BulkSendUi = (props) => {
const [isFreePlan, setIsFreePlan] = useState(false); const [isFreePlan, setIsFreePlan] = useState(false);
const [admin, setAdmin] = useState({ const [admin, setAdmin] = useState({
objectId: "", objectId: "",
name: "",
email: "", email: "",
isAdmin: true isAdmin: true
}); });
@@ -63,8 +62,7 @@ const BulkSendUi = (props) => {
setAdmin((obj) => ({ setAdmin((obj) => ({
...obj, ...obj,
isAdmin: false, isAdmin: false,
name: extUser?.CreatedBy?.name, email: extUser?.TenantId?.EmailAddress
email: extUser?.CreatedBy?.email
})); }));
} }
setAdmin((obj) => ({ ...obj, objectId: subscription?.adminId })); setAdmin((obj) => ({ ...obj, objectId: subscription?.adminId }));
@@ -491,10 +489,7 @@ const BulkSendUi = (props) => {
</form> </form>
) : ( ) : (
<div className="mx-8 mt-4 mb-8 flex justify-center text-center items-center font-medium break-all"> <div className="mx-8 mt-4 mb-8 flex justify-center text-center items-center font-medium break-all">
{t("unauthorized-modal", { {t("unauthorized-modal", { adminEmail: admin?.email })}
adminName: admin?.name,
adminEmail: admin?.email
})}
</div> </div>
)} )}
</> </>
@@ -3,6 +3,8 @@ import { checkIsSubscribed, getFileName } from "../../constant/Utils";
import Upgrade from "../../primitives/Upgrade"; import Upgrade from "../../primitives/Upgrade";
import { isEnableSubscription } from "../../constant/const"; import { isEnableSubscription } from "../../constant/const";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Tooltip } from "react-tooltip";
// import SelectFolder from "../../premitives/SelectFolder"; // import SelectFolder from "../../premitives/SelectFolder";
const EditTemplate = ({ template, onSuccess }) => { const EditTemplate = ({ template, onSuccess }) => {
@@ -14,7 +16,8 @@ const EditTemplate = ({ template, onSuccess }) => {
Description: template?.Description || "", Description: template?.Description || "",
SendinOrder: template?.SendinOrder ? `${template?.SendinOrder}` : "false", SendinOrder: template?.SendinOrder ? `${template?.SendinOrder}` : "false",
AutomaticReminders: template?.AutomaticReminders || false, AutomaticReminders: template?.AutomaticReminders || false,
RemindOnceInEvery: template?.RemindOnceInEvery || 5 RemindOnceInEvery: template?.RemindOnceInEvery || 5,
IsEnableOTP: template?.IsEnableOTP ? `${template?.IsEnableOTP}` : "false"
}); });
const [isSubscribe, setIsSubscribe] = useState(false); const [isSubscribe, setIsSubscribe] = useState(false);
useEffect(() => { useEffect(() => {
@@ -41,7 +44,7 @@ const EditTemplate = ({ template, onSuccess }) => {
e.stopPropagation(); e.stopPropagation();
const isChecked = formData.SendinOrder === "true" ? true : false; const isChecked = formData.SendinOrder === "true" ? true : false;
const AutoReminder = formData?.AutomaticReminders || false; const AutoReminder = formData?.AutomaticReminders || false;
const IsEnableOTP = formData.IsEnableOTP === "true" ? true : false;
let reminderDate = {}; let reminderDate = {};
if (AutoReminder) { if (AutoReminder) {
const RemindOnceInEvery = parseInt(formData?.RemindOnceInEvery); const RemindOnceInEvery = parseInt(formData?.RemindOnceInEvery);
@@ -49,7 +52,12 @@ const EditTemplate = ({ template, onSuccess }) => {
ReminderDate.setDate(ReminderDate.getDate() + RemindOnceInEvery); ReminderDate.setDate(ReminderDate.getDate() + RemindOnceInEvery);
reminderDate = { NextReminderDate: ReminderDate }; reminderDate = { NextReminderDate: ReminderDate };
} }
const data = { ...formData, SendinOrder: isChecked, ...reminderDate }; const data = {
...formData,
SendinOrder: isChecked,
IsEnableOTP: IsEnableOTP,
...reminderDate
};
onSuccess(data); onSuccess(data);
}; };
const handleAutoReminder = () => { const handleAutoReminder = () => {
@@ -184,6 +192,70 @@ const EditTemplate = ({ template, onSuccess }) => {
/> />
</div> </div>
)} )}
{isEnableSubscription && (
<div className="text-xs mt-2">
<label className="block">
<span className={isSubscribe ? "" : " text-gray-300"}>
{t("isenable-otp")}{" "}
<a data-tooltip-id="isenableotp-tooltip" className="ml-1">
<sup>
<i className="fa-light fa-question rounded-full border-[#33bbff] text-[#33bbff] text-[13px] border-[1px] py-[1.5px] px-[4px]"></i>
</sup>
</a>{" "}
{!isSubscribe && isEnableSubscription && <Upgrade />}
</span>
<Tooltip id="isenableotp-tooltip" className="z-50">
<div className="max-w-[200px] md:max-w-[450px]">
<p className="font-bold">{t("isenable-otp")}</p>
<p>{t("isenable-otp-help.p1")}</p>
<p className="p-[5px]">
<ol className="list-disc">
<li>
<span className="font-bold">{t("yes")}: </span>
<span>{t("isenable-otp-help.p2")}</span>
</li>
<li>
<span className="font-bold">{t("no")}: </span>
<span>{t("isenable-otp-help.p3")}</span>
</li>
</ol>
</p>
<p>{t("isenable-otp-help.p4")}</p>
</div>
</Tooltip>
</label>
<div
className={`${
isSubscribe ? "" : "pointer-events-none opacity-50"
} flex items-center gap-2 ml-2 mb-1 `}
>
<input
type="radio"
value={"true"}
className="op-radio op-radio-xs"
name="IsEnableOTP"
checked={formData.IsEnableOTP === "true"}
onChange={handleStrInput}
/>
<div className="text-center">{t("yes")}</div>
</div>
<div
className={`${
isSubscribe ? "" : "pointer-events-none opacity-50"
} flex items-center gap-2 ml-2 mb-1 `}
>
<input
type="radio"
value={"false"}
name="IsEnableOTP"
className="op-radio op-radio-xs"
checked={formData.IsEnableOTP === "false"}
onChange={handleStrInput}
/>
<div className="text-center">{t("no")}</div>
</div>
</div>
)}
<div className="mt-[1rem] flex justify-start"> <div className="mt-[1rem] flex justify-start">
<button type="submit" className="op-btn op-btn-primary"> <button type="submit" className="op-btn op-btn-primary">
{t("submit")} {t("submit")}
@@ -154,7 +154,9 @@ function EmailComponent({
<div className="flex flex-row"> <div className="flex flex-row">
{!isAndroid && ( {!isAndroid && (
<button <button
onClick={(e) => handleToPrint(e, pdfUrl, setIsDownloading)} onClick={(e) =>
handleToPrint(e, pdfUrl, setIsDownloading, pdfDetails)
}
className="op-btn op-btn-neutral op-btn-sm text-[15px]" className="op-btn op-btn-neutral op-btn-sm text-[15px]"
> >
<i className="fa-light fa-print" aria-hidden="true"></i> <i className="fa-light fa-print" aria-hidden="true"></i>
@@ -142,7 +142,7 @@ function Header({
<DropdownMenu.Item <DropdownMenu.Item
className="DropdownMenuItem" className="DropdownMenuItem"
onClick={(e) => onClick={(e) =>
handleToPrint(e, pdfUrl, setIsDownloading) handleToPrint(e, pdfUrl, setIsDownloading, pdfDetails)
} }
> >
<div className="flex flex-row"> <div className="flex flex-row">
@@ -342,7 +342,9 @@ function Header({
alreadySign ? ( alreadySign ? (
<div className="flex flex-row"> <div className="flex flex-row">
<button <button
onClick={(e) => handleToPrint(e, pdfUrl, setIsDownloading)} onClick={(e) =>
handleToPrint(e, pdfUrl, setIsDownloading, pdfDetails)
}
type="button" type="button"
className="op-btn op-btn-neutral op-btn-sm mr-[3px] shadow" className="op-btn op-btn-neutral op-btn-sm mr-[3px] shadow"
> >
@@ -459,7 +461,9 @@ function Header({
</button> </button>
)} )}
<button <button
onClick={(e) => handleToPrint(e, pdfUrl, setIsDownloading)} onClick={(e) =>
handleToPrint(e, pdfUrl, setIsDownloading, pdfDetails)
}
type="button" type="button"
className="op-btn op-btn-neutral op-btn-sm gap-0 font-medium text-[12px] mr-[3px] shadow" className="op-btn op-btn-neutral op-btn-sm gap-0 font-medium text-[12px] mr-[3px] shadow"
> >
+10 -8
View File
@@ -31,8 +31,8 @@ function SignPad({
const [isTab, setIsTab] = useState("draw"); const [isTab, setIsTab] = useState("draw");
const [isSignImg, setIsSignImg] = useState(""); const [isSignImg, setIsSignImg] = useState("");
const [signValue, setSignValue] = useState(""); const [signValue, setSignValue] = useState("");
const [textWidth, setTextWidth] = useState(null); const [textWidth, setTextWidth] = useState(0);
const [textHeight, setTextHeight] = useState(null); const [textHeight, setTextHeight] = useState(0);
const [signatureType, setSignatureType] = useState("draw"); const [signatureType, setSignatureType] = useState("draw");
const fontOptions = [ const fontOptions = [
{ value: "Fasthand" }, { value: "Fasthand" },
@@ -51,7 +51,7 @@ function SignPad({
`Parse/${localStorage.getItem("parseAppId")}/currentUser` `Parse/${localStorage.getItem("parseAppId")}/currentUser`
); );
const jsonSender = JSON.parse(senderUser); const jsonSender = JSON.parse(senderUser);
const currentUserName = jsonSender && jsonSender.name; const currentUserName = jsonSender && jsonSender?.name;
//function for clear signature image //function for clear signature image
const handleClear = () => { const handleClear = () => {
@@ -137,7 +137,7 @@ function SignPad({
(isTab === "draw" && isSignImg) || (isTab === "draw" && isSignImg) ||
(isTab === "image" && image) || (isTab === "image" && image) ||
(isTab === "mysignature" && isDefaultSign) || (isTab === "mysignature" && isDefaultSign) ||
(isTab === "type" && textWidth) (isTab === "type" && signValue)
? false ? false
: image : image
? false ? false
@@ -169,10 +169,10 @@ function SignPad({
} }
} }
const trimmedName = currentUserName && currentUserName.trim(); const trimmedName = currentUserName && currentUserName?.trim();
const firstCharacter = trimmedName?.charAt(0); const firstCharacter = trimmedName?.charAt(0);
const userName = isInitial ? firstCharacter : currentUserName; const userName = isInitial ? firstCharacter : currentUserName;
setSignValue(userName); setSignValue(userName || "");
setFontSelect("Fasthand"); setFontSelect("Fasthand");
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
@@ -200,8 +200,10 @@ function SignPad({
canvasRef.current.fromDataURL(isSignImg); canvasRef.current.fromDataURL(isSignImg);
} }
if (isTab === "type") { if (isTab === "type") {
const trimmedName = signValue ? signValue.trim() : currentUserName.trim(); const trimmedName = signValue
const firstCharacter = trimmedName.charAt(0); ? signValue?.trim()
: currentUserName?.trim();
const firstCharacter = trimmedName?.charAt(0);
const userName = isInitial ? firstCharacter : signValue; const userName = isInitial ? firstCharacter : signValue;
setSignValue(userName); setSignValue(userName);
convertToImg(fontSelect, userName); convertToImg(fontSelect, userName);
+13 -7
View File
@@ -708,7 +708,8 @@ export const createDocument = async (
Signers: signers, Signers: signers,
SendinOrder: Doc?.SendinOrder || false, SendinOrder: Doc?.SendinOrder || false,
AutomaticReminders: Doc?.AutomaticReminders || false, AutomaticReminders: Doc?.AutomaticReminders || false,
RemindOnceInEvery: parseInt(Doc?.RemindOnceInEvery || 5) RemindOnceInEvery: parseInt(Doc?.RemindOnceInEvery || 5),
IsEnableOTP: Doc?.IsEnableOTP || false
}; };
try { try {
@@ -1741,9 +1742,7 @@ export const contactBook = async (objectId) => {
//function for getting document details from contract_Documents class //function for getting document details from contract_Documents class
export const contractDocument = async (documentId) => { export const contractDocument = async (documentId) => {
const data = { const data = { docId: documentId };
docId: documentId
};
const documentDeatils = await axios const documentDeatils = await axios
.post(`${localStorage.getItem("baseUrl")}functions/getDocument`, data, { .post(`${localStorage.getItem("baseUrl")}functions/getDocument`, data, {
headers: { headers: {
@@ -2047,11 +2046,12 @@ export const handleDownloadPdf = async (
) => { ) => {
const pdfName = pdfDetails[0] && pdfDetails[0].Name; const pdfName = pdfDetails[0] && pdfDetails[0].Name;
setIsDownloading("pdf"); setIsDownloading("pdf");
const docId = !pdfDetails?.[0]?.IsEnableOTP ? pdfDetails?.[0]?.objectId : "";
try { try {
// const url = await Parse.Cloud.run("getsignedurl", { url: pdfUrl }); // const url = await Parse.Cloud.run("getsignedurl", { url: pdfUrl });
const axiosRes = await axios.post( const axiosRes = await axios.post(
`${localStorage.getItem("baseUrl")}/functions/getsignedurl`, `${localStorage.getItem("baseUrl")}/functions/getsignedurl`,
{ url: pdfUrl }, { url: pdfUrl, docId: docId },
{ {
headers: { headers: {
"content-type": "Application/json", "content-type": "Application/json",
@@ -2075,16 +2075,22 @@ export const sanitizeFileName = (pdfName) => {
return pdfName.replace(/ /g, "_"); return pdfName.replace(/ /g, "_");
}; };
//function for print digital sign pdf //function for print digital sign pdf
export const handleToPrint = async (event, pdfUrl, setIsDownloading) => { export const handleToPrint = async (
event,
pdfUrl,
setIsDownloading,
pdfDetails
) => {
event.preventDefault(); event.preventDefault();
setIsDownloading("pdf"); setIsDownloading("pdf");
const docId = !pdfDetails?.[0]?.IsEnableOTP ? pdfDetails?.[0]?.objectId : "";
try { try {
// const url = await Parse.Cloud.run("getsignedurl", { url: pdfUrl }); // const url = await Parse.Cloud.run("getsignedurl", { url: pdfUrl });
//`localStorage.getItem("baseUrl")` is also use in public-profile flow for public-sign //`localStorage.getItem("baseUrl")` is also use in public-profile flow for public-sign
//if we give this `appInfo.baseUrl` as a base url then in public-profile it will create base url of it's window.location.origin ex- opensign.me which is not base url //if we give this `appInfo.baseUrl` as a base url then in public-profile it will create base url of it's window.location.origin ex- opensign.me which is not base url
const axiosRes = await axios.post( const axiosRes = await axios.post(
`${localStorage.getItem("baseUrl")}/functions/getsignedurl`, `${localStorage.getItem("baseUrl")}/functions/getsignedurl`,
{ url: pdfUrl }, { url: pdfUrl, docId: docId },
{ {
headers: { headers: {
"content-type": "Application/json", "content-type": "Application/json",
+2 -2
View File
@@ -252,9 +252,9 @@ const HomeLayout = () => {
} }
}; };
const handleLoginBtn = () => { const handleLoginBtn = async () => {
try { try {
Parse?.User?.logOut(); await Parse?.User?.logOut();
} catch (err) { } catch (err) {
console.log("err ", err); console.log("err ", err);
} finally { } finally {
+136 -35
View File
@@ -61,7 +61,8 @@ const Forms = (props) => {
password: "", password: "",
file: "", file: "",
remindOnceInEvery: 5, remindOnceInEvery: 5,
autoreminder: false autoreminder: false,
IsEnableOTP: "false"
}); });
const [fileupload, setFileUpload] = useState(""); const [fileupload, setFileUpload] = useState("");
const [fileload, setfileload] = useState(false); const [fileload, setfileload] = useState(false);
@@ -74,6 +75,7 @@ const Forms = (props) => {
const [isDecrypting, setIsDecrypting] = useState(false); const [isDecrypting, setIsDecrypting] = useState(false);
const [isCorrectPass, setIsCorrectPass] = useState(true); const [isCorrectPass, setIsCorrectPass] = useState(true);
const [isSubscribe, setIsSubscribe] = useState(false); const [isSubscribe, setIsSubscribe] = useState(false);
const [isAdvanceOpt, setIsAdvanceOpt] = useState(false);
const handleStrInput = (e) => { const handleStrInput = (e) => {
setIsCorrectPass(true); setIsCorrectPass(true);
setFormData({ ...formData, [e.target.name]: e.target.value }); setFormData({ ...formData, [e.target.name]: e.target.value });
@@ -137,7 +139,6 @@ const Forms = (props) => {
} catch (err) { } catch (err) {
console.log("err in sending posthog encryptedpdf", err); console.log("err in sending posthog encryptedpdf", err);
} }
// console.log("err ", err);
try { try {
setIsDecrypting(true); setIsDecrypting(true);
const size = files?.[0].size; const size = files?.[0].size;
@@ -402,6 +403,13 @@ const Forms = (props) => {
object.set("SendinOrder", isChecked); object.set("SendinOrder", isChecked);
object.set("AutomaticReminders", formData.autoreminder); object.set("AutomaticReminders", formData.autoreminder);
object.set("RemindOnceInEvery", parseInt(formData.remindOnceInEvery)); object.set("RemindOnceInEvery", parseInt(formData.remindOnceInEvery));
if (isEnableSubscription) {
const IsEnableOTP =
formData?.IsEnableOTP === "false" ? false : true;
object.set("IsEnableOTP", IsEnableOTP);
} else {
object.set("IsEnableOTP", false);
}
} }
object.set("URL", fileupload); object.set("URL", fileupload);
object.set("CreatedBy", Parse.User.createWithoutData(currentUser.id)); object.set("CreatedBy", Parse.User.createWithoutData(currentUser.id));
@@ -428,7 +436,17 @@ const Forms = (props) => {
setFormData({ setFormData({
Name: "", Name: "",
Description: "", Description: "",
Note: "" Note:
props.title === "Sign Yourself"
? "Note to myself"
: "Please review and sign this document",
TimeToCompleteDays: 15,
SendinOrder: "true",
password: "",
file: "",
remindOnceInEvery: 5,
autoreminder: false,
IsEnableOTP: "false"
}); });
setFileUpload(""); setFileUpload("");
setpercentage(0); setpercentage(0);
@@ -477,7 +495,8 @@ const Forms = (props) => {
password: "", password: "",
file: "", file: "",
remindOnceInEvery: 5, remindOnceInEvery: 5,
autoreminder: false autoreminder: false,
IsEnableOTP: "false"
}); });
setFileUpload(""); setFileUpload("");
setpercentage(0); setpercentage(0);
@@ -754,28 +773,7 @@ const Forms = (props) => {
isReset={isReset} isReset={isReset}
/> />
)} )}
{props.title === "Request Signatures" && (
<div className="text-xs mt-2">
<label className="block">
{t("time-to-complete")}
<span className="text-red-500 text-[13px]">*</span>
</label>
<input
type="number"
name="TimeToCompleteDays"
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
value={formData.TimeToCompleteDays}
onChange={(e) => handleStrInput(e)}
onInvalid={(e) =>
e.target.setCustomValidity(t("input-required"))
}
onInput={(e) => e.target.setCustomValidity("")}
required
/>
</div>
)}
{props.title !== "Sign Yourself" && ( {props.title !== "Sign Yourself" && (
<>
<div className="text-xs mt-2"> <div className="text-xs mt-2">
<label className="block"> <label className="block">
{t("send-in-order")} {t("send-in-order")}
@@ -827,17 +825,35 @@ const Forms = (props) => {
<div className="text-center">{t("no")}</div> <div className="text-center">{t("no")}</div>
</div> </div>
</div> </div>
)}
{isAdvanceOpt && (
<div className={` overflow-y-auto z-[500] transition-all`}>
{props.title === "Request Signatures" && (
<div className="text-xs mt-2">
<label className="block">
{t("time-to-complete")}
<span className="text-red-500 text-[13px]">*</span>
</label>
<input
type="number"
name="TimeToCompleteDays"
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
value={formData.TimeToCompleteDays}
onChange={(e) => handleStrInput(e)}
onInvalid={(e) =>
e.target.setCustomValidity(t("input-required"))
}
onInput={(e) => e.target.setCustomValidity("")}
required
/>
</div>
)}
{props.title !== "Sign Yourself" && (
<>
{isEnableSubscription && ( {isEnableSubscription && (
<div className="text-xs mt-2"> <div className="text-xs mt-2">
<span <span className={isSubscribe ? "" : " text-gray-300"}>
className={ {t("auto-reminder")}{" "}
isSubscribe
? "font-semibold"
: "font-semibold text-gray-300"
}
>
{t("auto-reminder")}
{" "}
{!isSubscribe && isEnableSubscription && <Upgrade />} {!isSubscribe && isEnableSubscription && <Upgrade />}
</span> </span>
<label <label
@@ -845,7 +861,7 @@ const Forms = (props) => {
isSubscribe isSubscribe
? "cursor-pointer " ? "cursor-pointer "
: "pointer-events-none opacity-50" : "pointer-events-none opacity-50"
} relative block items-center mb-0`} } relative block items-center mb-0 mt-1.5`}
> >
<input <input
type="checkbox" type="checkbox"
@@ -876,8 +892,93 @@ const Forms = (props) => {
/> />
</div> </div>
)} )}
{isEnableSubscription && (
<div className="text-xs mt-2">
<label className="block">
<span className={isSubscribe ? "" : " text-gray-300"}>
{t("isenable-otp")}{" "}
<a
data-tooltip-id="isenableotp-tooltip"
className="ml-1"
>
<sup>
<i className="fa-light fa-question rounded-full border-[#33bbff] text-[#33bbff] text-[13px] border-[1px] py-[1.5px] px-[4px]"></i>
</sup>
</a>{" "}
{!isSubscribe && isEnableSubscription && (
<Upgrade />
)}
</span>
<Tooltip id="isenableotp-tooltip" className="z-50">
<div className="max-w-[200px] md:max-w-[450px]">
<p className="font-bold">{t("isenable-otp")}</p>
<p>{t("isenable-otp-help.p1")}</p>
<p className="p-[5px]">
<ol className="list-disc">
<li>
<span className="font-bold">
{t("yes")}:{" "}
</span>
<span>{t("isenable-otp-help.p2")}</span>
</li>
<li>
<span className="font-bold">
{t("no")}:{" "}
</span>
<span>{t("isenable-otp-help.p3")}</span>
</li>
</ol>
</p>
<p>{t("isenable-otp-help.p4")}</p>
</div>
</Tooltip>
</label>
<div
className={`${
isSubscribe ? "" : "pointer-events-none opacity-50"
} flex items-center gap-2 ml-2 mb-1 `}
>
<input
type="radio"
value={"true"}
className="op-radio op-radio-xs"
name="IsEnableOTP"
checked={formData.IsEnableOTP === "true"}
onChange={handleStrInput}
/>
<div className="text-center">{t("yes")}</div>
</div>
<div
className={`${
isSubscribe ? "" : "pointer-events-none opacity-50"
} flex items-center gap-2 ml-2 mb-1 `}
>
<input
type="radio"
value={"false"}
name="IsEnableOTP"
className="op-radio op-radio-xs"
checked={formData.IsEnableOTP === "false"}
onChange={handleStrInput}
/>
<div className="text-center">{t("no")}</div>
</div>
</div>
)}
</> </>
)} )}
</div>
)}
{props.title !== "Sign Yourself" && (
<div
onClick={() => setIsAdvanceOpt(!isAdvanceOpt)}
className={`mt-2.5 op-link op-link-primary text-sm`}
>
{isAdvanceOpt
? t("hide-advanced-options")
: t("advanced-options")}
</div>
)}
<div className="flex items-center mt-3 gap-2"> <div className="flex items-center mt-3 gap-2">
<button <button
className={`${ className={`${
+1 -4
View File
@@ -28,7 +28,6 @@ function GenerateToken() {
plan: "", plan: "",
isValid: false, isValid: false,
adminId: "", adminId: "",
adminName: "",
adminEmail: "" adminEmail: ""
}); });
const [isAlert, setIsAlert] = useState({ type: "success", msg: "" }); const [isAlert, setIsAlert] = useState({ type: "success", msg: "" });
@@ -154,8 +153,7 @@ function GenerateToken() {
} else { } else {
setIsSubscribe((obj) => ({ setIsSubscribe((obj) => ({
...obj, ...obj,
adminName: extUser?.CreatedBy?.name, adminEmail: extUser?.TenantId?.EmailAddress
adminEmail: extUser?.CreatedBy?.email
})); }));
setIsModal((obj) => ({ ...obj, unauthorized: !obj.unauthorized })); setIsModal((obj) => ({ ...obj, unauthorized: !obj.unauthorized }));
} }
@@ -447,7 +445,6 @@ function GenerateToken() {
> >
<div className="m-8 flex justify-center text-center items-center font-medium break-all"> <div className="m-8 flex justify-center text-center items-center font-medium break-all">
{t("unauthorized-modal", { {t("unauthorized-modal", {
adminName: isSubscribe?.adminName,
adminEmail: isSubscribe?.adminEmail adminEmail: isSubscribe?.adminEmail
})} })}
</div> </div>
+34 -10
View File
@@ -28,6 +28,28 @@ function GuestLogin() {
const [contactId, setContactId] = useState(contactBookId); const [contactId, setContactId] = useState(contactBookId);
const [sendmail, setSendmail] = useState(); const [sendmail, setSendmail] = useState();
const [contact, setContact] = useState({ name: "", phone: "", email: "" }); const [contact, setContact] = useState({ name: "", phone: "", email: "" });
const navigateToDoc = async (docId, contactId) => {
try {
const docDetails = await Parse.Cloud.run("getDocument", {
docId: docId
});
if (!docDetails.error) {
if (sendmail === "false") {
navigate(
`/load/recipientSignPdf/${docId}/${contactId}?sendmail=${sendmail}`
);
} else {
navigate(`/load/recipientSignPdf/${docId}/${contactId}`);
}
return true;
} else {
return false;
}
} catch (err) {
console.log("err while getting doc", err);
return false;
}
};
useEffect(() => { useEffect(() => {
handleServerUrl(); handleServerUrl();
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
@@ -70,13 +92,14 @@ function GuestLogin() {
"linkcontacttodoc", "linkcontacttodoc",
params params
); );
// console.log("linkContactRes ", linkContactRes);
setContactId(linkContactRes?.contactId); setContactId(linkContactRes?.contactId);
await navigateToDoc(checkSplit[0], linkContactRes?.contactId);
} catch (err) { } catch (err) {
console.log("Err in link ext contact", err); console.log("Err in link ext contact", err);
} }
} else { } else {
setContactId(checkSplit[2]); setContactId(checkSplit[2]);
await navigateToDoc(checkSplit[0], checkSplit[2]);
} }
} }
@@ -114,15 +137,12 @@ function GuestLogin() {
if (OTP) { if (OTP) {
setLoading(true); setLoading(true);
try { try {
let url = `${serverUrl}functions/AuthLoginAsMail/`; let url = `${serverUrl}functions/AuthLoginAsMail`;
const headers = { const headers = {
"Content-Type": "application/json", "Content-Type": "application/json",
"X-Parse-Application-Id": parseId "X-Parse-Application-Id": parseId
}; };
let body = { let body = { email: email, otp: OTP };
email: email,
otp: OTP
};
let user = await axios.post(url, body, { headers: headers }); let user = await axios.post(url, body, { headers: headers });
if (user.data.result === "Invalid Otp") { if (user.data.result === "Invalid Otp") {
alert(t("invalid-otp")); alert(t("invalid-otp"));
@@ -140,7 +160,6 @@ function GuestLogin() {
`Parse/${parseId}/currentUser`, `Parse/${parseId}/currentUser`,
JSON.stringify(_user) JSON.stringify(_user)
); );
// console.log("contractUserDetails ", contractUserDetails);
if (contractUserDetails && contractUserDetails.length > 0) { if (contractUserDetails && contractUserDetails.length > 0) {
localStorage.setItem( localStorage.setItem(
"Extand_Class", "Extand_Class",
@@ -174,10 +193,15 @@ function GuestLogin() {
try { try {
setLoading(true); setLoading(true);
const linkContactRes = await Parse.Cloud.run("linkcontacttodoc", params); const linkContactRes = await Parse.Cloud.run("linkcontacttodoc", params);
// console.log("linkContactRes ", linkContactRes);
setContactId(linkContactRes.contactId); setContactId(linkContactRes.contactId);
const IsEnableOTP = await navigateToDoc(
documentId,
linkContactRes.contactId
);
if (!IsEnableOTP) {
setEnterOtp(true); setEnterOtp(true);
await SendOtp(); await SendOtp();
}
} catch (err) { } catch (err) {
setLoading(false); setLoading(false);
alert(t("something-went-wrong-mssg")); alert(t("something-went-wrong-mssg"));
@@ -208,7 +232,7 @@ function GuestLogin() {
<div className="w-full md:w-[50%] text-base-content"> <div className="w-full md:w-[50%] text-base-content">
<h1 className="text-2xl md:text-[30px]">{t("welcome")}</h1> <h1 className="text-2xl md:text-[30px]">{t("welcome")}</h1>
<legend className="text-[12px] text-[#878787] mt-2 mb-1"> <legend className="text-[12px] text-[#878787] mt-2 mb-1">
{t("guest-email-alert")} {t("get-otp-alert")}
</legend> </legend>
<div className="p-[20px] outline outline-1 outline-slate-300/50 my-2 op-card shadow-md"> <div className="p-[20px] outline outline-1 outline-slate-300/50 my-2 op-card shadow-md">
<input <input
@@ -236,7 +260,7 @@ function GuestLogin() {
> >
<h1 className="text-2xl md:text-[30px]">{t("welcome")}</h1> <h1 className="text-2xl md:text-[30px]">{t("welcome")}</h1>
<legend className="text-[12px] text-[#878787] mt-2"> <legend className="text-[12px] text-[#878787] mt-2">
{t("get-verification-code-2")} {t("guest-email-alert")}
</legend> </legend>
<div className="p-[20px] pt-[15px] outline outline-1 outline-slate-300/50 op-card my-2 shadow-md"> <div className="p-[20px] pt-[15px] outline outline-1 outline-slate-300/50 op-card my-2 shadow-md">
<p className="text-sm">{t("enter-verification-code")}</p> <p className="text-sm">{t("enter-verification-code")}</p>
+131 -110
View File
@@ -142,23 +142,23 @@ function PdfRequestFiles(props) {
let isGuestSignFlow = false; let isGuestSignFlow = false;
let sendmail; let sendmail;
let getDocId = ""; let getDocId = "";
const route = !props.templateId && window.location.pathname; //'/load/recipientSignPdf/TOAVuhXbfw/fPAKdK1qgX' let contactBookId = "";
//window.location.search = ?sendmail=false const route = !props.templateId && window.location.pathname;
const getQuery = const getQuery = !props.templateId && window.location?.search?.split("?"); //['','sendmail=false']
!props.templateId &&
window.location?.search &&
window.location?.search?.split("?"); //['','sendmail=false']
//'sendmail=false'
if (getQuery) { if (getQuery) {
sendmail = getQuery[1].split("=")[1]; //false sendmail = getQuery?.[1]?.split("=")[1]; //false
} }
const checkSplit = route && route?.split("/"); // ['', 'load', 'recipientSignPdf', 'TOAVuhXbfw', 'fPAKdK1qgX']
if (checkSplit && checkSplit.length > 4) { const routeId = route && route?.split("/"); // ['', 'load', 'recipientSignPdf', ':docId', ':contactBookId']
if (routeId && routeId.length > 4) {
// this condition will be occur only in guest flow in which load routeId will be include
isGuestSignFlow = true; isGuestSignFlow = true;
getDocId = checkSplit[3]; getDocId = routeId[3];
contactBookId = routeId[4];
} else { } else {
getDocId = checkSplit[2]; // this condition will be occur only in if user is logged in and load routeId will be exclude
getDocId = routeId[2];
contactBookId = routeId?.[3] || "";
} }
let getDocumentId = getDocId || documentId; let getDocumentId = getDocId || documentId;
useEffect(() => { useEffect(() => {
@@ -372,9 +372,10 @@ function PdfRequestFiles(props) {
`Parse/${localStorage.getItem("parseAppId")}/currentUser` `Parse/${localStorage.getItem("parseAppId")}/currentUser`
); );
const jsonSender = JSON.parse(senderUser); const jsonSender = JSON.parse(senderUser);
// `currUserId` will be contactId or extUserId
let currUserId; let currUserId;
//getting document details //getting document details
const documentData = await contractDocument(documentId || docId); const documentData = await contractDocument(docId);
if (documentData && documentData.length > 0) { if (documentData && documentData.length > 0) {
const url = const url =
documentData[0] && documentData[0] &&
@@ -399,13 +400,13 @@ function PdfRequestFiles(props) {
const expireUpdateDate = new Date(expireDate).getTime(); const expireUpdateDate = new Date(expireDate).getTime();
const currDate = new Date().getTime(); const currDate = new Date().getTime();
const getSigners = documentData[0].Signers; const getSigners = documentData[0].Signers;
const getCurrentSigner = const getCurrentSigner = getSigners?.find(
getSigners &&
getSigners.filter(
(data) => data.UserId.objectId === jsonSender?.objectId (data) => data.UserId.objectId === jsonSender?.objectId
); );
currUserId = getCurrentSigner[0] ? getCurrentSigner[0].objectId : ""; currUserId = getCurrentSigner?.objectId
? getCurrentSigner.objectId
: contactBookId || "";
if (isEnableSubscription) { if (isEnableSubscription) {
await checkIsSubscribed( await checkIsSubscribed(
documentData[0]?.ExtUserPtr?.objectId, documentData[0]?.ExtUserPtr?.objectId,
@@ -428,10 +429,7 @@ function PdfRequestFiles(props) {
setIsCelebration(true); setIsCelebration(true);
setTimeout(() => setIsCelebration(false), 5000); setTimeout(() => setIsCelebration(false), 5000);
} else if (declined) { } else if (declined) {
const currentDecline = { const currentDecline = { currnt: "another", isDeclined: true };
currnt: "another",
isDeclined: true
};
setIsDecline(currentDecline); setIsDecline(currentDecline);
} else if (currDate > expireUpdateDate) { } else if (currDate > expireUpdateDate) {
const expireDateFormat = moment(new Date(expireDate)).format( const expireDateFormat = moment(new Date(expireDate)).format(
@@ -457,36 +455,24 @@ function PdfRequestFiles(props) {
} }
} }
} }
const audittrailData = const audittrailData = documentData?.[0]?.AuditTrail?.filter(
documentData[0].AuditTrail &&
documentData[0].AuditTrail.length > 0 &&
documentData[0].AuditTrail.filter(
(data) => data.Activity === "Signed" (data) => data.Activity === "Signed"
); );
const checkAlreadySign = const checkAlreadySign =
documentData[0].AuditTrail && documentData?.[0]?.AuditTrail?.some(
documentData[0].AuditTrail.length > 0 &&
documentData[0].AuditTrail.filter(
(data) => (data) =>
data.UserPtr?.objectId === currUserId && data?.UserPtr?.objectId === currUserId &&
data.Activity === "Signed" data.Activity === "Signed"
); ) || false;
if ( if (checkAlreadySign) {
checkAlreadySign &&
checkAlreadySign[0] &&
checkAlreadySign.length > 0
) {
setAlreadySign(true); setAlreadySign(true);
} else { } else {
const obj = documentData?.[0]; const obj = documentData?.[0];
setSendInOrder(obj?.SendinOrder || false); setSendInOrder(obj?.SendinOrder || false);
if ( if (
obj && obj &&
obj.Signers && obj?.Signers?.length > 0 &&
obj.Signers.length > 0 && obj?.Placeholders?.length > 0
obj.Placeholders &&
obj.Placeholders.length > 0
) { ) {
const params = { const params = {
event: "viewed", event: "viewed",
@@ -502,7 +488,10 @@ function PdfRequestFiles(props) {
email: x?.Email, email: x?.Email,
phone: x?.Phone phone: x?.Phone
})), })),
viewedBy: jsonSender.email, viewedBy:
documentData?.[0].Signers?.find(
(x) => x.objectId === currUserId
)?.Email || jsonSender?.email,
viewedAt: new Date(), viewedAt: new Date(),
createdAt: documentData?.[0].createdAt createdAt: documentData?.[0].createdAt
} }
@@ -583,17 +572,44 @@ function PdfRequestFiles(props) {
//checking if condition current user already sign or owner does not exist as a signer or document has been declined by someone or document has been expired //checking if condition current user already sign or owner does not exist as a signer or document has been declined by someone or document has been expired
//then stop to display tour message //then stop to display tour message
if ( if (
(checkAlreadySign && checkAlreadySign ||
checkAlreadySign[0] &&
checkAlreadySign.length > 0) ||
!currUserId || !currUserId ||
declined || declined ||
currDate > expireUpdateDate currDate > expireUpdateDate
) { ) {
setRequestSignTour(true); setRequestSignTour(true);
} else {
const isEnableOTP = documentData?.[0]?.IsEnableOTP || false;
if (!isEnableOTP) {
try {
const resContact = await axios.post(
`${localStorage.getItem("baseUrl")}functions/getcontact`,
{
contactId: currUserId
},
{
headers: {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId")
}
}
);
const contact = resContact?.data?.result;
setContractName("_Contactbook");
setSignerUserId(contact?.objectId);
const tourData = contact?.TourStatus && contact?.TourStatus;
if (tourData && tourData.length > 0) {
const checkTourRequest =
tourData?.some((data) => data?.requestSign) || false;
setTourStatus(tourData);
setRequestSignTour(checkTourRequest);
}
} catch (err) {
console.log("err while getting tourstatus", err);
}
} else { } else {
//else condition to check current user exist in contracts_Users class and check tour message status //else condition to check current user exist in contracts_Users class and check tour message status
//if not then check user exist in contracts_Contactbook class and check tour message statu //if not then check user exist in contracts_Contactbook class and check tour message status
const res = await contractUsers(); const res = await contractUsers();
if (res === "Error: Something went wrong!") { if (res === "Error: Something went wrong!") {
setHandleError(t("something-went-wrong-mssg")); setHandleError(t("something-went-wrong-mssg"));
@@ -630,6 +646,7 @@ function PdfRequestFiles(props) {
} }
} }
} }
}
setIsUiLoading(false); setIsUiLoading(false);
} else if ( } else if (
documentData === "Error: Something went wrong!" || documentData === "Error: Something went wrong!" ||
@@ -643,12 +660,12 @@ function PdfRequestFiles(props) {
setIsUiLoading({ isLoad: false }); setIsUiLoading({ isLoad: false });
} }
//function to get default signatur eof current user from `contracts_Signature` class //function to get default signatur eof current user from `contracts_Signature` class
const defaultSignRes = await getDefaultSignature(jsonSender.objectId); const defaultSignRes = await getDefaultSignature(jsonSender?.objectId);
if (defaultSignRes?.status === "success") { if (defaultSignRes?.status === "success") {
setDefaultSignImg(defaultSignRes?.res?.defaultSignature); const sign = defaultSignRes?.res?.defaultSignature || "";
setMyInitial(defaultSignRes?.res?.defaultInitial); const initials = defaultSignRes?.res?.defaultInitial || "";
} else if (defaultSignRes?.status === "error") { setDefaultSignImg(sign);
setHandleError("Error: Something went wrong!"); setMyInitial(initials);
} }
setIsLoading({ isLoad: false }); setIsLoading({ isLoad: false });
} catch (err) { } catch (err) {
@@ -664,20 +681,30 @@ function PdfRequestFiles(props) {
`Parse/${localStorage.getItem("parseAppId")}/currentUser` `Parse/${localStorage.getItem("parseAppId")}/currentUser`
); );
let currentUser = JSON.parse(localuser); let currentUser = JSON.parse(localuser);
let isEmailVerified = currentUser?.emailVerified;
const isEnableOTP = pdfDetails?.[0]?.IsEnableOTP || false;
//if emailVerified data is not present in local user details then fetch again in _User class //if emailVerified data is not present in local user details then fetch again in _User class
if (isEnableOTP) {
try {
if (!currentUser?.emailVerified) { if (!currentUser?.emailVerified) {
const userQuery = new Parse.Query(Parse.User); const userQuery = new Parse.Query(Parse.User);
const getUser = await userQuery.get(currentUser?.objectId, { const getUser = await userQuery.get(currentUser?.objectId, {
sessionToken: currentUser?.sessionToken sessionToken:
currentUser?.sessionToken || localStorage.getItem("accesstoken")
}); });
if (getUser) { if (getUser) {
currentUser = JSON.parse(JSON.stringify(getUser)); currentUser = JSON.parse(JSON.stringify(getUser));
} }
} }
let isEmailVerified = currentUser?.emailVerified; isEmailVerified = currentUser?.emailVerified;
//check if isEmailVerified then go on next step
if (isEmailVerified) {
setIsEmailVerified(isEmailVerified); setIsEmailVerified(isEmailVerified);
} catch (err) {
console.log("err in get email verification ", err);
setHandleError(t("something-went-wrong-mssg"));
}
}
//check if isEmailVerified then go on next step
if (!isEnableOTP || isEmailVerified) {
try { try {
const checkUser = signerPos.filter( const checkUser = signerPos.filter(
(data) => data.signerObjId === signerObjectId (data) => data.signerObjId === signerObjectId
@@ -858,17 +885,9 @@ function PdfRequestFiles(props) {
// console.log("pdfte", pdfBytes); // console.log("pdfte", pdfBytes);
//get ExistUserPtr object id of user class to get tenantDetails //get ExistUserPtr object id of user class to get tenantDetails
const objectId = pdfDetails?.[0]?.ExtUserPtr?.UserId?.objectId; const objectId = pdfDetails?.[0]?.ExtUserPtr?.UserId?.objectId;
//get ExistUserPtr email to get userDetails let activeMailAdapter =
const res = await contractUsers(); pdfDetails?.[0]?.ExtUserPtr?.active_mail_adapter;
let activeMailAdapter = "";
if (res === "Error: Something went wrong!") {
setHandleError(t("something-went-wrong-mssg"));
setIsLoading({ isLoad: false });
} else if (!res || res?.length === 0) {
activeMailAdapter = "";
} else if (res[0] && res.length) {
activeMailAdapter = res[0]?.active_mail_adapter;
}
//function for call to embed signature in pdf and get digital signature pdf //function for call to embed signature in pdf and get digital signature pdf
const resSign = await signPdfFun( const resSign = await signPdfFun(
pdfBytes, pdfBytes,
@@ -880,13 +899,13 @@ function PdfRequestFiles(props) {
widgets widgets
); );
if (resSign && resSign.status === "success") { if (resSign && resSign.status === "success") {
setPdfUrl(res.data); setPdfUrl(resSign.data);
setIsSigned(true); setIsSigned(true);
setSignedSigners([]); setSignedSigners([]);
setUnSignedSigners([]); setUnSignedSigners([]);
getDocumentDetails(true); getDocumentDetails(documentId, true);
const index = pdfDetails?.[0].Signers.findIndex( const index = pdfDetails?.[0]?.Signers.findIndex(
(x) => x.Email === currentUser?.email (x) => x.objectId === signerObjectId
); );
const newIndex = index + 1; const newIndex = index + 1;
const usermail = { const usermail = {
@@ -1054,21 +1073,6 @@ function PdfRequestFiles(props) {
alertMessage: t("something-went-wrong-mssg") alertMessage: t("something-went-wrong-mssg")
}); });
} }
} else {
//else verify users email
try {
const userQuery = new Parse.Query(Parse.User);
const user = await userQuery.get(currentUser?.objectId, {
sessionToken: localStorage.getItem("accesstoken")
});
if (user) {
isEmailVerified = user?.get("emailVerified");
setIsEmailVerified(isEmailVerified);
}
} catch (e) {
console.log("error in save user's emailVerified in user class");
setHandleError(t("something-went-wrong-mssg"));
}
} }
} }
@@ -1216,31 +1220,26 @@ function PdfRequestFiles(props) {
); );
const jsonSender = JSON.parse(senderUser); const jsonSender = JSON.parse(senderUser);
setIsDecline({ isDeclined: false }); setIsDecline({ isDeclined: false });
const data = {
IsDeclined: true,
DeclineReason: reason,
DeclineBy: {
__type: "Pointer",
className: "_User",
objectId: jsonSender?.objectId
}
};
setIsUiLoading(true); setIsUiLoading(true);
const email =
pdfDetails?.[0].Signers?.find((x) => x.objectId === signerObjectId)
?.Email || jsonSender?.email;
const userId =
pdfDetails?.[0].Signers?.find((x) => x.objectId === signerObjectId)
?.UserId?.objectId || jsonSender?.objectId;
const params = {
docId: pdfDetails?.[0].objectId,
reason: reason,
userId: userId
};
await axios await axios
.put( .post(`${localStorage.getItem("baseUrl")}functions/declinedoc`, params, {
`${localStorage.getItem(
"baseUrl"
)}classes/contracts_Document/${documentId}`,
data,
{
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"), "X-Parse-Application-Id": localStorage.getItem("parseAppId"),
"X-Parse-Session-Token": localStorage.getItem("accesstoken") "X-Parse-Session-Token": localStorage.getItem("accesstoken")
} }
} })
)
.then(async (result) => { .then(async (result) => {
const res = result.data; const res = result.data;
if (res) { if (res) {
@@ -1260,7 +1259,8 @@ function PdfRequestFiles(props) {
email: x?.Email, email: x?.Email,
phone: x?.Phone phone: x?.Phone
})), })),
declinedBy: jsonSender.email, declinedBy: email,
declinedReason: reason,
declinedAt: new Date(), declinedAt: new Date(),
createdAt: pdfDetails?.[0].createdAt createdAt: pdfDetails?.[0].createdAt
} }
@@ -1314,6 +1314,25 @@ function PdfRequestFiles(props) {
const closeRequestSignTour = async () => { const closeRequestSignTour = async () => {
setRequestSignTour(true); setRequestSignTour(true);
if (isDontShow) { if (isDontShow) {
const isEnableOTP = pdfDetails?.[0]?.IsEnableOTP || false;
if (!isEnableOTP) {
try {
await axios.post(
`${localStorage.getItem("baseUrl")}functions/updatecontacttour`,
{
contactId: signerObjectId
},
{
headers: {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId")
}
}
);
} catch (e) {
console.log("update tour messages error", e);
}
} else {
let updatedTourStatus = []; let updatedTourStatus = [];
if (tourStatus.length > 0) { if (tourStatus.length > 0) {
updatedTourStatus = [...tourStatus]; updatedTourStatus = [...tourStatus];
@@ -1348,6 +1367,7 @@ function PdfRequestFiles(props) {
console.log("update tour messages error", e); console.log("update tour messages error", e);
} }
} }
}
}; };
const requestSignTourFunction = () => { const requestSignTourFunction = () => {
const tourConfig = [ const tourConfig = [
@@ -1691,11 +1711,7 @@ function PdfRequestFiles(props) {
{/* this modal is used to show decline alert */} {/* this modal is used to show decline alert */}
<PdfDeclineModal <PdfDeclineModal
show={isDecline.isDeclined} show={isDecline.isDeclined}
headMsg={ headMsg={t("document-declined")}
pdfDetails[0]?.IsDeclined
? t("document-declined")
: t("document-decline")
}
bodyMssg={ bodyMssg={
isDecline.currnt === "Sure" isDecline.currnt === "Sure"
? t("decline-alert-1") ? t("decline-alert-1")
@@ -1938,7 +1954,12 @@ function PdfRequestFiles(props) {
<div className="flex mt-4 gap-1 px-[15px]"> <div className="flex mt-4 gap-1 px-[15px]">
<button <button
onClick={(e) => onClick={(e) =>
handleToPrint(e, pdfUrl, setIsDownloading) handleToPrint(
e,
pdfUrl,
setIsDownloading,
pdfDetails
)
} }
type="button" type="button"
className="font-[500] text-[13px] mr-[5px] op-btn op-btn-neutral" className="font-[500] text-[13px] mr-[5px] op-btn op-btn-neutral"
+2 -2
View File
@@ -121,9 +121,9 @@ const PlanSubscriptions = () => {
}; };
const handleLogout = async () => { const handleLogout = async () => {
try { try {
Parse?.User?.logOut(); await Parse?.User?.logOut();
} catch (err) { } catch (err) {
console.log("Err", err); console.log("Err while logging out", err);
} }
let appdata = localStorage.getItem("userSettings"); let appdata = localStorage.getItem("userSettings");
let applogo = localStorage.getItem("appLogo"); let applogo = localStorage.getItem("appLogo");
@@ -779,6 +779,7 @@ const TemplatePlaceholder = () => {
AutomaticReminders: pdfDetails[0]?.AutomaticReminders, AutomaticReminders: pdfDetails[0]?.AutomaticReminders,
RemindOnceInEvery: parseInt(pdfDetails[0]?.RemindOnceInEvery), RemindOnceInEvery: parseInt(pdfDetails[0]?.RemindOnceInEvery),
NextReminderDate: pdfDetails[0]?.NextReminderDate, NextReminderDate: pdfDetails[0]?.NextReminderDate,
IsEnableOTP: pdfDetails[0]?.IsEnableOTP === true ? true : false,
URL: pdfUrl URL: pdfUrl
}; };
const updateTemplate = new Parse.Object("contracts_Template"); const updateTemplate = new Parse.Object("contracts_Template");
+187 -23
View File
@@ -9,7 +9,7 @@ import Tooltip from "../primitives/Tooltip";
import AddUser from "../components/AddUser"; import AddUser from "../components/AddUser";
import SubscribeCard from "../primitives/SubscribeCard"; import SubscribeCard from "../primitives/SubscribeCard";
import { isEnableSubscription } from "../constant/const"; import { isEnableSubscription } from "../constant/const";
import { checkIsSubscribed } from "../constant/Utils"; import { fetchSubscriptionInfo } from "../constant/Utils";
import Title from "../components/Title"; import Title from "../components/Title";
import { validplan } from "../json/plansArr"; import { validplan } from "../json/plansArr";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@@ -19,7 +19,11 @@ const UserList = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const [userList, setUserList] = useState([]); const [userList, setUserList] = useState([]);
const [isLoader, setIsLoader] = useState(false); const [isLoader, setIsLoader] = useState(false);
const [isModal, setIsModal] = useState(false); const [isModal, setIsModal] = useState({
form: false,
addseats: false,
options: false
});
const location = useLocation(); const location = useLocation();
const isDashboard = const isDashboard =
location?.pathname === "/dashboard/35KBoSgoAK" ? true : false; location?.pathname === "/dashboard/35KBoSgoAK" ? true : false;
@@ -27,9 +31,16 @@ const UserList = () => {
const [isAlert, setIsAlert] = useState({ type: "success", msg: "" }); const [isAlert, setIsAlert] = useState({ type: "success", msg: "" });
const [isActiveModal, setIsActiveModal] = useState({}); const [isActiveModal, setIsActiveModal] = useState({});
const [isActLoader, setIsActLoader] = useState({}); const [isActLoader, setIsActLoader] = useState({});
const [isSubscribe, setIsSubscribe] = useState({ plan: "", isValid: false }); const [isSubscribe, setIsSubscribe] = useState({
plan: "",
isValid: false,
priceperUser: 0
});
const [isAdmin, setIsAdmin] = useState(false); const [isAdmin, setIsAdmin] = useState(false);
const [formHeader, setFormHeader] = useState(t("add-user")); const [formHeader, setFormHeader] = useState(t("add-user"));
const [usersCount, setUserCounts] = useState({ allowed: 0, totalAllowed: 0 });
const [amount, setAmount] = useState({ quantity: 1, price: 0 });
const [isBuyLoader, setIsBuyLoader] = useState(false);
const recordperPage = 10; const recordperPage = 10;
const startIndex = (currentPage - 1) * recordperPage; // user per page const startIndex = (currentPage - 1) * recordperPage; // user per page
@@ -81,7 +92,6 @@ const UserList = () => {
pages.push(lastPageIndex); pages.push(lastPageIndex);
} }
} }
return pages; return pages;
}; };
const pageNumbers = getPaginationRange(); const pageNumbers = getPaginationRange();
@@ -96,13 +106,43 @@ const UserList = () => {
async function fetchUserList() { async function fetchUserList() {
try { try {
setIsLoader(true); setIsLoader(true);
const extUser =
localStorage.getItem("Extand_Class") &&
JSON.parse(localStorage.getItem("Extand_Class"))?.[0];
if (isEnableSubscription) { if (isEnableSubscription) {
const subscribe = await checkIsSubscribed(); const subscribe = await fetchSubscriptionInfo();
setIsSubscribe(subscribe); if (subscribe?.plan_code?.includes("team")) {
const isSupAdmin =
subscribe?.adminId && extUser?.objectId === subscribe?.adminId;
setIsSubscribe({
plan: subscribe.plan_code,
isValid: true,
adminId: subscribe.adminId,
priceperUser: subscribe.price,
isSuperAdmin: isSupAdmin
});
setAmount((prev) => ({ ...prev, price: subscribe.price }));
try {
const res = await Parse.Cloud.run("allowedusers");
setUserCounts((obj) => ({
...obj,
allowed: parseInt(res),
totalAllowed: parseInt(subscribe?.totalAllowedUser) || 0
}));
} catch (err) {
console.log("err while get users", err);
}
} else {
setIsSubscribe({
plan: subscribe.plan_code,
isValid: false,
adminId: subscribe.adminId
});
}
} else { } else {
setIsSubscribe({ plan: "teams-yearly", isValid: true }); setIsSubscribe({ plan: "teams-yearly", isValid: true });
} }
const extUser = JSON.parse(localStorage.getItem("Extand_Class"))?.[0];
if (extUser) { if (extUser) {
const admin = const admin =
extUser?.UserRole && extUser?.UserRole &&
@@ -121,14 +161,12 @@ const UserList = () => {
console.log("Err in fetch userlist", err); console.log("Err in fetch userlist", err);
setIsAlert({ type: "danger", msg: t("something-went-wrong-mssg") }); setIsAlert({ type: "danger", msg: t("something-went-wrong-mssg") });
} finally { } finally {
setTimeout(() => { setTimeout(() => setIsAlert({ type: "success", msg: "" }), 1500);
setIsAlert({ type: "success", msg: "" });
}, 1500);
setIsLoader(false); setIsLoader(false);
} }
} }
const handleFormModal = () => { const handleModal = (modalName) => {
setIsModal(!isModal); setIsModal((obj) => ({ ...obj, [modalName]: !obj[modalName] }));
}; };
// Change page // Change page
@@ -146,7 +184,13 @@ const UserList = () => {
}; };
const handleUserData = (userData) => { const handleUserData = (userData) => {
if (userData) {
setUserCounts((obj) => ({
...obj,
allowed: obj?.allowed > 0 ? obj.allowed - 1 : 1
}));
setUserList((prev) => [userData, ...prev]); setUserList((prev) => [userData, ...prev]);
}
}; };
// `formatRow` is used to show data in poper manner like // `formatRow` is used to show data in poper manner like
// if data is of array type then it will join array items with "," // if data is of array type then it will join array items with ","
@@ -162,9 +206,8 @@ const UserList = () => {
return "-"; return "-";
} }
}; };
const handleClose = () => { const handleClose = () => setIsActiveModal({});
setIsActiveModal({});
};
const handleToggleSubmit = async (user) => { const handleToggleSubmit = async (user) => {
const index = userList.findIndex((obj) => obj.objectId === user.objectId); const index = userList.findIndex((obj) => obj.objectId === user.objectId);
if (index !== -1) { if (index !== -1) {
@@ -196,6 +239,49 @@ const UserList = () => {
const handleToggleBtn = (user) => { const handleToggleBtn = (user) => {
setIsActiveModal({ [user.objectId]: true }); setIsActiveModal({ [user.objectId]: true });
}; };
const handleAddOnSubmit = async (e) => {
e.preventDefault();
e.stopPropagation();
setIsBuyLoader(true);
try {
const resAddon = await Parse.Cloud.run("buyaddonusers", {
users: parseInt(amount.quantity)
});
if (resAddon) {
const _resAddon = JSON.parse(JSON.stringify(resAddon));
if (_resAddon.status === "success") {
setUserCounts((obj) => ({
...obj,
allowed: parseInt(obj.allowed) + parseInt(amount.quantity),
totalAllowed: parseInt(_resAddon.addon)
}));
setAmount((obj) => ({ ...obj, quantity: 1 }));
}
}
} catch (err) {
console.log("Err in buy addon", err);
setIsAlert({ type: "danger", msg: t("something-went-wrong-mssg") });
} finally {
setTimeout(() => setIsAlert({ type: "success", msg: "" }), 2000);
setIsBuyLoader(false);
handleModal("addseats");
}
};
const handlePricePerUser = (e) => {
const quantity = e.target.value;
const price = e.target?.value > 0 ? isSubscribe.priceperUser * quantity : 0;
setAmount((prev) => ({ ...prev, quantity: quantity, price: price }));
};
const handleBuyUsers = (allowed, totalAllowed) => {
if (allowed && totalAllowed) {
setUserCounts((obj) => ({
...obj,
allowed: parseInt(obj.allowed) + parseInt(allowed),
totalAllowed: parseInt(totalAllowed)
}));
}
};
return ( return (
<div className="relative"> <div className="relative">
<Title title={isAdmin ? "Users" : "Page not found"} /> <Title title={isAdmin ? "Users" : "Page not found"} />
@@ -205,7 +291,7 @@ const UserList = () => {
</div> </div>
)} )}
{Object.keys(isActLoader)?.length > 0 && ( {Object.keys(isActLoader)?.length > 0 && (
<div className="absolute w-full h-full flex justify-center items-center bg-black bg-opacity-30 z-30 rounded-box"> <div className="absolute w-full h-full flex justify-center items-center bg-black/30 z-30 rounded-box">
<Loader /> <Loader />
</div> </div>
)} )}
@@ -216,19 +302,46 @@ const UserList = () => {
{isAlert.msg && <Alert type={isAlert.type}>{isAlert.msg}</Alert>} {isAlert.msg && <Alert type={isAlert.type}>{isAlert.msg}</Alert>}
<div className="flex flex-row items-center justify-between my-2 mx-3 text-[20px] md:text-[23px]"> <div className="flex flex-row items-center justify-between my-2 mx-3 text-[20px] md:text-[23px]">
<div className="font-light"> <div className="font-light">
{t("report-name.Users")} {t("report-name.Users")}{" "}
<span className="text-xs md:text-[13px] font-normal"> <span className="text-xs md:text-[13px] font-normal">
<Tooltip message={t("users-from-teams")} /> <Tooltip message={t("users-from-teams")} />
</span> </span>
</div> </div>
<div className="flex flex-row gap-2 items-center">
{isEnableSubscription && isSubscribe?.isSuperAdmin && (
<div
className="hidden md:flex op-btn op-btn-sm h-[35px] op-btn-primary op-btn-outline text-xs mb-0.5"
onClick={() => handleModal("addseats")}
>
{t("buy-users")}
</div>
)}
<div <div
className="cursor-pointer" className="cursor-pointer"
onClick={() => handleFormModal()} onClick={() => handleModal("form")}
> >
<i className="fa-light fa-square-plus text-accent text-[40px]"></i> <i className="fa-light fa-square-plus text-accent text-[30px] md:text-[40px]"></i>
</div>
{isEnableSubscription && isSubscribe?.isSuperAdmin && (
<div
className="cursor-pointer relative md:hidden mb-0.5"
onClick={() => handleModal("options")}
>
<i className="fa-light fa-ellipsis-vertical fa-xl"></i>
{isModal?.options && (
<ul className="absolute -right-3 top-auto z-[70] w-max op-menu op-menu-xs shadow bg-base-100 text-base-content rounded-box border">
<li onClick={() => handleModal("addseats")}>
<span className="text-[13px] capitalize font-medium">
{t("buy-users")}
</span>
</li>
</ul>
)}
</div>
)}
</div> </div>
</div> </div>
<div className={` overflow-x-auto w-full`}> <div className="overflow-x-auto w-full">
<table className="op-table border-collapse w-full"> <table className="op-table border-collapse w-full">
<thead className="text-[14px]"> <thead className="text-[14px]">
<tr className="border-y-[1px]"> <tr className="border-y-[1px]">
@@ -313,6 +426,7 @@ const UserList = () => {
</tbody> </tbody>
</table> </table>
</div> </div>
<div className="flex flex-row justify-between items-center text-xs font-medium">
<div className="op-join flex flex-wrap items-center p-2"> <div className="op-join flex flex-wrap items-center p-2">
{userList.length > recordperPage && ( {userList.length > recordperPage && (
<button <button
@@ -343,6 +457,13 @@ const UserList = () => {
</button> </button>
)} )}
</div> </div>
{isEnableSubscription && isSubscribe?.isSuperAdmin && (
<div>
{t("available-seats")}: {usersCount.allowed}/
{usersCount.totalAllowed}
</div>
)}
</div>
{userList?.length <= 0 && ( {userList?.length <= 0 && (
<div <div
className={`${ className={`${
@@ -362,17 +483,60 @@ const UserList = () => {
</div> </div>
)} )}
<ModalUi <ModalUi
isOpen={isModal} isOpen={isModal.form}
title={formHeader} title={formHeader}
handleClose={handleFormModal} handleClose={() => handleModal("form")}
> >
<AddUser <AddUser
setIsAlert={setIsAlert} setIsAlert={setIsAlert}
handleUserData={handleUserData} handleUserData={handleUserData}
closePopup={handleFormModal} handleBuyUsers={handleBuyUsers}
closePopup={() => handleModal("form")}
setFormHeader={setFormHeader} setFormHeader={setFormHeader}
/> />
</ModalUi> </ModalUi>
<ModalUi
isOpen={isModal.addseats}
title="Add Seats"
handleClose={() => handleModal("addseats")}
>
{isBuyLoader && (
<div className="absolute w-full h-full inset-0 flex justify-center items-center bg-base-content/30 z-50">
<Loader />
</div>
)}
<form onSubmit={handleAddOnSubmit} className=" px-3 pb-6 pt-6">
<div className="mb-3 flex justify-between">
<label
htmlFor="quantity"
className="block text-xs text-gray-700 font-semibold"
>
{t("Quantity-of-users")}
<span className="text-[red] text-[13px]"> *</span>
</label>
<input
type="number"
name="quantity"
value={amount.quantity}
onChange={(e) => handlePricePerUser(e)}
className="w-1/4 op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content text-xs"
required
/>
</div>
<div className="mb-3 flex justify-between">
<label className="block text-xs text-gray-700 font-semibold">
{t("Price")} (1 * {isSubscribe.priceperUser})
</label>
<div className="w-1/4 flex justify-center items-center text-sm">
USD {amount.price}
</div>
</div>
<hr className="text-base-content mb-3" />
<button className="op-btn op-btn-primary w-full">
{t("Proceed")}
</button>
</form>
</ModalUi>
</div> </div>
) : ( ) : (
<div className="flex items-center justify-center h-screen w-full bg-base-100 text-base-content rounded-box"> <div className="flex items-center justify-center h-screen w-full bg-base-100 text-base-content rounded-box">
@@ -266,7 +266,8 @@ const ReportTable = (props) => {
Signers: signers, Signers: signers,
SendinOrder: Doc?.SendinOrder || false, SendinOrder: Doc?.SendinOrder || false,
AutomaticReminders: Doc?.AutomaticReminders || false, AutomaticReminders: Doc?.AutomaticReminders || false,
RemindOnceInEvery: Doc?.RemindOnceInEvery || 5 RemindOnceInEvery: Doc?.RemindOnceInEvery || 5,
IsEnableOTP: Doc?.IsEnableOTP || false
}; };
try { try {
const res = await axios.post( const res = await axios.post(
@@ -515,7 +516,6 @@ const ReportTable = (props) => {
.then(async (result) => { .then(async (result) => {
const res = result.data; const res = result.data;
if (res) { if (res) {
setReason("");
setActLoader({}); setActLoader({});
setIsAlert(true); setIsAlert(true);
setAlertMsg({ setAlertMsg({
@@ -527,7 +527,43 @@ const ReportTable = (props) => {
(x) => x.objectId !== item.objectId (x) => x.objectId !== item.objectId
); );
props.setList(upldatedList); props.setList(upldatedList);
const params = {
event: "declined",
body: {
objectId: item.objectId,
file: item?.SignedUrl || item?.URL,
name: item?.Name,
note: item?.Note || "",
description: item?.Description || "",
signers: item?.Signers?.map((x) => ({
name: x?.Name,
email: x?.Email,
phone: x?.Phone
})),
declinedBy: jsonSender?.email,
declinedReason: reason,
declinedAt: new Date(),
createdAt: item?.createdAt
} }
};
try {
await axios.post(
`${localStorage.getItem("baseUrl")}functions/callwebhook`,
params,
{
headers: {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
sessiontoken: localStorage.getItem("accesstoken")
}
}
);
} catch (err) {
console.log("Err ", err);
}
}
setReason("");
}) })
.catch((err) => { .catch((err) => {
console.log("err", err); console.log("err", err);
@@ -41,8 +41,8 @@ function CustomModal(props) {
className="op-btn op-btn-primary mr-2 px-6" className="op-btn op-btn-primary mr-2 px-6"
type="button" type="button"
onClick={() => { onClick={() => {
setReason("");
props.declineDoc(reason); props.declineDoc(reason);
setReason("");
}} }}
> >
{t("yes")} {t("yes")}
@@ -632,7 +632,17 @@
"quota-mail": "You've reached your limit of 15 signature request emails for this month. Upgrade now to continue sending emails directly.", "quota-mail": "You've reached your limit of 15 signature request emails for this month. Upgrade now to continue sending emails directly.",
"quota-mail-tip": "Tip: You can still sign <1>unlimited documents</1> by manually sharing the signing request links.", "quota-mail-tip": "Tip: You can still sign <1>unlimited documents</1> by manually sharing the signing request links.",
"quota-mail-head": "Quota Reached", "quota-mail-head": "Quota Reached",
"unauthorized-modal":"You don't have permission to perform this action, please contact {{adminName}}<{{adminEmail}}>.", "unauthorized-modal": "You don't have permission to perform this action, please contact {{adminEmail}}.",
"sent-this-month":"Sent this month" "sent-this-month": "Sent this month",
"available-seats": "Available seats",
"buy-users": "Buy more users",
"isenable-otp": "Enable OTP verification",
"isenable-otp-help": {
"p1": "Would you like to enable the verification process using a one-time password (OTP)?",
"p2": "Selecting this option will enable OTP verification. Users will receive a verification code via email, which they must enter to sign the document.",
"p3": "Selecting this option will disable OTP verification, allowing users to sign the document directly without additional steps.",
"p4": "Please choose the option that best suits your document signing requirements."
},
"advanced-options": "Advanced options",
"hide-advanced-options": "Hide Advanced options"
} }
@@ -631,8 +631,17 @@
"quota-mail": "Vous avez atteint votre limite de 15 e-mails de demande de signature pour ce mois. Mettez à niveau maintenant pour continuer à envoyer des e-mails directement.", "quota-mail": "Vous avez atteint votre limite de 15 e-mails de demande de signature pour ce mois. Mettez à niveau maintenant pour continuer à envoyer des e-mails directement.",
"quota-mail-tip": "Astuce : Vous pouvez toujours signer un nombre <1>illimité de documents</1> en partageant manuellement les liens de demande de signature.", "quota-mail-tip": "Astuce : Vous pouvez toujours signer un nombre <1>illimité de documents</1> en partageant manuellement les liens de demande de signature.",
"quota-mail-head": "Quota atteint", "quota-mail-head": "Quota atteint",
"unauthorized-modal":"Vous n'êtes pas autorisé à effectuer cette action, veuillez contacter {{adminName}}<{{adminEmail}}>.", "unauthorized-modal": "Vous n'êtes pas autorisé à effectuer cette action, veuillez contacter {{adminEmail}}.",
"sent-this-month":"envoyé ce mois-ci" "sent-this-month": "envoyé ce mois-ci",
"available-seats": "Disponible sièges",
"buy-users": "Acheter plus d'utilisateurs",
"isenable-otp": "Activer la vérification OTP",
"isenable-otp-help": {
"p1": "Souhaitez-vous activer le processus de vérification à l'aide d'un mot de passe à usage unique (OTP)?",
"p2": "La sélection de cette option activera la vérification OTP. Les utilisateurs recevront un code de vérification par e-mail, qu'ils devront saisir pour signer le document.",
"p3": "La sélection de cette option désactivera la vérification OTP, permettant aux utilisateurs de signer le document directement sans étapes supplémentaires.",
"p4": "Veuillez choisir l'option qui correspond le mieux à vos exigences en matière de signature de documents."
},
"advanced-options": "Options avancées",
"hide-advanced-options": "Masquer les options avancées"
} }
+2
View File
@@ -42,6 +42,7 @@ export function replaceMailVaribles(subject, body, variables) {
export const saveFileUsage = async (size, fileUrl, userId) => { export const saveFileUsage = async (size, fileUrl, userId) => {
//checking server url and save file's size //checking server url and save file's size
try { try {
if (userId) {
const tenantQuery = new Parse.Query('partners_Tenant'); const tenantQuery = new Parse.Query('partners_Tenant');
tenantQuery.equalTo('UserId', { tenantQuery.equalTo('UserId', {
__type: 'Pointer', __type: 'Pointer',
@@ -73,6 +74,7 @@ export const saveFileUsage = async (size, fileUrl, userId) => {
} }
saveDataFile(size, fileUrl, tenantPtr); saveDataFile(size, fileUrl, tenantPtr);
} }
}
} catch (err) { } catch (err) {
console.log('err in fetch tenant Id', err); console.log('err in fetch tenant Id', err);
} }
@@ -196,6 +196,9 @@ export default async function createDocumentWithTemplate(request, response) {
if (TimeToCompleteDays) { if (TimeToCompleteDays) {
object.set('TimeToCompleteDays', TimeToCompleteDays); object.set('TimeToCompleteDays', TimeToCompleteDays);
} }
const enableOTP = request.body?.enableOTP === true ? true : false;
const IsEnableOTP = enableOTP || template?.IsEnableOTP || false;
object.set('IsEnableOTP', IsEnableOTP);
object.set('CreatedBy', template.CreatedBy); object.set('CreatedBy', template.CreatedBy);
object.set('ExtUserPtr', { object.set('ExtUserPtr', {
__type: 'Pointer', __type: 'Pointer',
@@ -63,6 +63,7 @@ export default async function createDocumentwithCoordinate(request, response) {
const email_body = request.body.email_body; const email_body = request.body.email_body;
const sendInOrder = request.body.sendInOrder || false; const sendInOrder = request.body.sendInOrder || false;
const TimeToCompleteDays = request.body.timeToCompleteDays || 15; const TimeToCompleteDays = request.body.timeToCompleteDays || 15;
const IsEnableOTP = request.body?.enableOTP === true ? true : false;
// console.log('fileData ', fileData); // console.log('fileData ', fileData);
const protocol = customAPIurl(); const protocol = customAPIurl();
const baseUrl = new URL(process.env.PUBLIC_URL); const baseUrl = new URL(process.env.PUBLIC_URL);
@@ -162,6 +163,7 @@ export default async function createDocumentwithCoordinate(request, response) {
if (TimeToCompleteDays) { if (TimeToCompleteDays) {
object.set('TimeToCompleteDays', TimeToCompleteDays); object.set('TimeToCompleteDays', TimeToCompleteDays);
} }
object.set('IsEnableOTP', IsEnableOTP);
object.set('IsSendMail', send_email); object.set('IsSendMail', send_email);
let contact = []; let contact = [];
if (signers && signers.length > 0) { if (signers && signers.length > 0) {
@@ -9,6 +9,7 @@ export default async function createTemplate(request, response) {
const SendinOrder = request.body.sendInOrder || false; const SendinOrder = request.body.sendInOrder || false;
const fileData = request.files?.[0] ? request.files[0].buffer : null; const fileData = request.files?.[0] ? request.files[0].buffer : null;
const baseUrl = new URL(process.env.PUBLIC_URL); const baseUrl = new URL(process.env.PUBLIC_URL);
const isEnableOTP = request.body?.enableOTP === true ? true : false;
try { try {
const reqToken = request.headers['x-api-token']; const reqToken = request.headers['x-api-token'];
@@ -65,6 +66,7 @@ export default async function createTemplate(request, response) {
object.set('URL', fileUrl); object.set('URL', fileUrl);
object.set('CreatedBy', userPtr); object.set('CreatedBy', userPtr);
object.set('ExtUserPtr', extUserPtr); object.set('ExtUserPtr', extUserPtr);
object.set('IsEnableOTP', isEnableOTP);
if (SendinOrder) { if (SendinOrder) {
object.set('SendinOrder', SendinOrder); object.set('SendinOrder', SendinOrder);
} }
@@ -17,6 +17,8 @@ export default async function createTemplatewithCoordinate(request, response) {
const base64File = request.body.file; const base64File = request.body.file;
const fileData = request.files?.[0] ? request.files[0].buffer : null; const fileData = request.files?.[0] ? request.files[0].buffer : null;
const SendinOrder = request.body.sendInOrder || false; const SendinOrder = request.body.sendInOrder || false;
const isEnableOTP = request.body?.enableOTP === true ? true : false;
// console.log('fileData ', fileData); // console.log('fileData ', fileData);
const protocol = customAPIurl(); const protocol = customAPIurl();
@@ -80,6 +82,7 @@ export default async function createTemplatewithCoordinate(request, response) {
object.set('URL', fileUrl); object.set('URL', fileUrl);
object.set('CreatedBy', userPtr); object.set('CreatedBy', userPtr);
object.set('ExtUserPtr', extUserPtr); object.set('ExtUserPtr', extUserPtr);
object.set('IsEnableOTP', isEnableOTP);
let contact = []; let contact = [];
if (signers && signers.length > 0) { if (signers && signers.length > 0) {
let parseSigners; let parseSigners;
@@ -12,6 +12,8 @@ export default async function draftDocument(request, response) {
const send_email = request.body.send_email || true; const send_email = request.body.send_email || true;
const fileData = request.files?.[0] ? request.files[0].buffer : null; const fileData = request.files?.[0] ? request.files[0].buffer : null;
const SendinOrder = request.body.sendInOrder || false; const SendinOrder = request.body.sendInOrder || false;
const isEnableOTP = request.body?.enableOTP === true ? true : false;
// console.log('fileData ', fileData); // console.log('fileData ', fileData);
const protocol = customAPIurl(); const protocol = customAPIurl();
const baseUrl = new URL(process.env.PUBLIC_URL); const baseUrl = new URL(process.env.PUBLIC_URL);
@@ -83,6 +85,7 @@ export default async function draftDocument(request, response) {
object.set('CreatedBy', userPtr); object.set('CreatedBy', userPtr);
object.set('ExtUserPtr', extUserPtr); object.set('ExtUserPtr', extUserPtr);
object.set('IsSendMail', send_email); object.set('IsSendMail', send_email);
object.set('IsEnableOTP', isEnableOTP);
if (signers && signers.length > 0) { if (signers && signers.length > 0) {
let parseSigners; let parseSigners;
if (base64File) { if (base64File) {
@@ -62,6 +62,7 @@ export default async function getDocument(request, response) {
document?.Signers?.map(y => ({ name: y?.Name, email: y?.Email, phone: y?.Phone })) || document?.Signers?.map(y => ({ name: y?.Name, email: y?.Email, phone: y?.Phone })) ||
[], [],
sendInOrder: document?.SendinOrder || false, sendInOrder: document?.SendinOrder || false,
enableOTP: document?.IsEnableOTP || false,
createdAt: document.createdAt, createdAt: document.createdAt,
updatedAt: document.updatedAt, updatedAt: document.updatedAt,
}); });
@@ -100,6 +100,7 @@ export default async function getDocumentList(request, response) {
x?.Signers?.map(y => ({ name: y?.Name, email: y?.Email, phone: y?.Phone })) || x?.Signers?.map(y => ({ name: y?.Name, email: y?.Email, phone: y?.Phone })) ||
[], [],
sendInOrder: x?.SendinOrder || false, sendInOrder: x?.SendinOrder || false,
enableOTP: x?.IsEnableOTP || false,
createdAt: x.createdAt, createdAt: x.createdAt,
updatedAt: x.updatedAt, updatedAt: x.updatedAt,
})); }));
@@ -61,6 +61,7 @@ export default async function getTemplate(request, response) {
), ),
})) || [], })) || [],
sendInOrder: template?.SendinOrder || false, sendInOrder: template?.SendinOrder || false,
enableOTP: template?.IsEnableOTP || false,
createdAt: template.createdAt, createdAt: template.createdAt,
updatedAt: template.updatedAt, updatedAt: template.updatedAt,
}); });
@@ -88,6 +88,7 @@ export default async function getTemplatetList(request, response) {
), ),
})) || [], })) || [],
sendInOrder: template?.SendinOrder || false, sendInOrder: template?.SendinOrder || false,
enableOTP: template?.IsEnableOTP || false,
createdAt: template.createdAt, createdAt: template.createdAt,
updatedAt: template.updatedAt, updatedAt: template.updatedAt,
})); }));
@@ -10,7 +10,7 @@ export default async function updateDocument(request, response) {
const token = await tokenQuery.first({ useMasterKey: true }); const token = await tokenQuery.first({ useMasterKey: true });
if (token !== undefined) { if (token !== undefined) {
// Valid Token then proceed request // Valid Token then proceed request
const allowedKeys = ['name', 'note', 'description', 'folderId']; const allowedKeys = ['name', 'note', 'description', 'folderId', 'enableOTP'];
const objectKeys = Object.keys(request.body); const objectKeys = Object.keys(request.body);
const isValid = objectKeys.every(key => allowedKeys.includes(key)) && objectKeys.length > 0; const isValid = objectKeys.every(key => allowedKeys.includes(key)) && objectKeys.length > 0;
const parseUser = JSON.parse(JSON.stringify(token)); const parseUser = JSON.parse(JSON.stringify(token));
@@ -48,6 +48,10 @@ export default async function updateDocument(request, response) {
objectId: request?.body?.folderId, objectId: request?.body?.folderId,
}); });
} }
if (request.body?.enableOTP) {
updateQuery.set('IsEnableOTP', request.body?.enableOTP);
}
const updatedRes = await updateQuery.save(null, { useMasterKey: true }); const updatedRes = await updateQuery.save(null, { useMasterKey: true });
if (updatedRes) { if (updatedRes) {
if (request.posthog) { if (request.posthog) {
@@ -10,7 +10,7 @@ export default async function updateTemplate(request, response) {
const token = await tokenQuery.first({ useMasterKey: true }); const token = await tokenQuery.first({ useMasterKey: true });
if (token !== undefined) { if (token !== undefined) {
// Valid Token then proceed request // Valid Token then proceed request
const allowedKeys = ['name', 'note', 'description', 'folderId']; const allowedKeys = ['name', 'note', 'description', 'folderId', 'enableOTP'];
const objectKeys = Object.keys(request.body); const objectKeys = Object.keys(request.body);
const isValid = objectKeys.every(key => allowedKeys.includes(key)) && objectKeys.length > 0; const isValid = objectKeys.every(key => allowedKeys.includes(key)) && objectKeys.length > 0;
const parseUser = JSON.parse(JSON.stringify(token)); const parseUser = JSON.parse(JSON.stringify(token));
@@ -48,6 +48,9 @@ export default async function updateTemplate(request, response) {
objectId: request?.body?.folderId, objectId: request?.body?.folderId,
}); });
} }
if (request.body?.enableOTP) {
updateQuery.set('IsEnableOTP', request.body?.enableOTP);
}
const updatedRes = await updateQuery.save(null, { useMasterKey: true }); const updatedRes = await updateQuery.save(null, { useMasterKey: true });
if (updatedRes) { if (updatedRes) {
if (request.posthog) { if (request.posthog) {
+6
View File
@@ -65,6 +65,9 @@ import ExtUserAftersave from './parsefunction/ExtUserAftersave.js';
import ExtUserAfterdelete from './parsefunction/ExtUserAfterdelete.js'; import ExtUserAfterdelete from './parsefunction/ExtUserAfterdelete.js';
import AllowedCredits from './parsefunction/AllowedCredits.js'; import AllowedCredits from './parsefunction/AllowedCredits.js';
import BuyCredits from './parsefunction/BuyCredits.js'; import BuyCredits from './parsefunction/BuyCredits.js';
import getContact from './parsefunction/getContact.js';
import updateContactTour from './parsefunction/updateContactTour.js';
import declinedocument from './parsefunction/declinedocument.js';
// This afterSave function triggers after an object is added or updated in the specified class, allowing for post-processing logic. // This afterSave function triggers after an object is added or updated in the specified class, allowing for post-processing logic.
Parse.Cloud.afterSave('contracts_Document', DocumentAftersave); Parse.Cloud.afterSave('contracts_Document', DocumentAftersave);
@@ -142,3 +145,6 @@ Parse.Cloud.define('allowedusers', AllowedUsers);
Parse.Cloud.define('buyaddonusers', BuyAddonUsers); Parse.Cloud.define('buyaddonusers', BuyAddonUsers);
Parse.Cloud.define('allowedcredits', AllowedCredits); Parse.Cloud.define('allowedcredits', AllowedCredits);
Parse.Cloud.define('buycredits', BuyCredits); Parse.Cloud.define('buycredits', BuyCredits);
Parse.Cloud.define('getcontact', getContact);
Parse.Cloud.define('updatecontacttour', updateContactTour);
Parse.Cloud.define('declinedoc', declinedocument);
@@ -62,6 +62,7 @@ const createDocumentFromTemplate = async (template, existContact, index) => {
object.set('CreatedBy', template?.CreatedBy); object.set('CreatedBy', template?.CreatedBy);
object.set('ExtUserPtr', template?.ExtUserPtr); object.set('ExtUserPtr', template?.ExtUserPtr);
object.set('OriginIp', template?.OriginIp || ''); object.set('OriginIp', template?.OriginIp || '');
object.set('IsEnableOTP', template?.IsEnableOTP || false);
let signers = template?.Signers || []; let signers = template?.Signers || [];
const signerobj = { const signerobj = {
__type: 'Pointer', __type: 'Pointer',
@@ -7,20 +7,24 @@ export default async function callWebhook(request) {
const contactId = request.params.contactId; const contactId = request.params.contactId;
const serverUrl = cloudServerUrl; //process.env.SERVER_URL; const serverUrl = cloudServerUrl; //process.env.SERVER_URL;
const appId = process.env.APP_ID; const appId = process.env.APP_ID;
try {
const docQuery = new Parse.Query('contracts_Document');
const docRes = await docQuery.get(docId, { useMasterKey: true });
const isEnableOTP = docRes?.get('IsEnableOTP') || false;
let userId;
if (isEnableOTP) {
const userRes = await axios.get(serverUrl + '/users/me', { const userRes = await axios.get(serverUrl + '/users/me', {
headers: { headers: {
'X-Parse-Application-Id': appId, 'X-Parse-Application-Id': appId,
'X-Parse-Session-Token': request.headers['sessiontoken'], 'X-Parse-Session-Token': request.headers['sessiontoken'],
}, },
}); });
userId = userRes.data && userRes.data.objectId;
const userId = userRes.data && userRes.data.objectId; }
if (userId) { if (!isEnableOTP || userId) {
if (event === 'viewed' && contactId) { if (event === 'viewed' && contactId) {
const docQuery = new Parse.Query('contracts_Document'); if (docRes) {
const res = await docQuery.get(docId, { useMasterKey: true }); const _docRes = docRes.toJSON();
if (res) {
const _res = res.toJSON();
const userPtr = { const userPtr = {
__type: 'Pointer', __type: 'Pointer',
className: 'contracts_Contactbook', className: 'contracts_Contactbook',
@@ -29,19 +33,19 @@ export default async function callWebhook(request) {
const date = new Date().toISOString(); const date = new Date().toISOString();
const obj = { const obj = {
UserPtr: userPtr, UserPtr: userPtr,
SignedUrl: _res.SignedUrl, SignedUrl: _docRes.SignedUrl,
Activity: 'Viewed', Activity: 'Viewed',
ipAddress: request.headers['x-real-ip'], ipAddress: request.headers['x-real-ip'],
ViewedOn: date, ViewedOn: date,
}; };
const isUserExist = _res?.AuditTrail?.some( const isUserExist = _docRes?.AuditTrail?.some(
x => x.UserPtr.objectId === contactId && x?.ViewedOn x => x.UserPtr.objectId === contactId && x?.ViewedOn
); );
if (!isUserExist) { if (!isUserExist) {
const updateDoc = new Parse.Object('contracts_Document'); const updateDoc = new Parse.Object('contracts_Document');
updateDoc.id = res.id; updateDoc.id = docRes.id;
if (_res?.AuditTrail && _res?.AuditTrail?.length > 0) { if (_docRes?.AuditTrail && _docRes?.AuditTrail?.length > 0) {
updateDoc.set('AuditTrail', [..._res?.AuditTrail, obj]); updateDoc.set('AuditTrail', [..._docRes?.AuditTrail, obj]);
} else { } else {
updateDoc.set('AuditTrail', [obj]); updateDoc.set('AuditTrail', [obj]);
} }
@@ -49,26 +53,20 @@ export default async function callWebhook(request) {
} }
} }
} }
const docQuery = new Parse.Query('contracts_Document');
const resDoc = await docQuery.get(docId, { useMasterKey: true });
const extendcls = new Parse.Query('contracts_Users'); const extendcls = new Parse.Query('contracts_Users');
extendcls.equalTo('objectId', resDoc.get('ExtUserPtr')?.id); extendcls.equalTo('objectId', docRes.get('ExtUserPtr')?.id);
// extendcls.equalTo('UserId', { __type: 'Pointer', className: '_User', objectId: userId }); // extendcls.equalTo('UserId', { __type: 'Pointer', className: '_User', objectId: userId });
const res = await extendcls.first({ useMasterKey: true }); const resExt = await extendcls.first({ useMasterKey: true });
if (res) { if (resExt) {
const extUser = JSON.parse(JSON.stringify(res)); const extUser = JSON.parse(JSON.stringify(resExt));
if (extUser?.Webhook) { if (extUser?.Webhook) {
const params = { const params = { event: event, ...body };
event: event,
...body,
};
await axios await axios
.post(extUser?.Webhook, params, { .post(extUser?.Webhook, params, {
headers: { 'Content-Type': 'application/json' }, headers: { 'Content-Type': 'application/json' },
}) })
.then(res => { .then(res => {
try { try {
// console.log('res ', res);
const webhook = new Parse.Object('contracts_Webhook'); const webhook = new Parse.Object('contracts_Webhook');
webhook.set('Log', res?.status); webhook.set('Log', res?.status);
webhook.set('UserId', { webhook.set('UserId', {
@@ -102,4 +100,8 @@ export default async function callWebhook(request) {
} else { } else {
return { message: 'User not found!' }; return { message: 'User not found!' };
} }
} catch (err) {
console.log('Err in callwebhook', err);
return { message: 'Something went wrong!' };
}
} }
@@ -199,6 +199,7 @@ export default async function createBatchDocs(request) {
TimeToCompleteDays: x.TimeToCompleteDays || 15, TimeToCompleteDays: x.TimeToCompleteDays || 15,
OriginIp: Ip, OriginIp: Ip,
DocSentAt: { __type: 'Date', iso: isoDate }, DocSentAt: { __type: 'Date', iso: isoDate },
IsEnableOTP: x?.IsEnableOTP || false,
}, },
}; };
}); });
@@ -0,0 +1,38 @@
export default async function declinedocument(request) {
const docId = request.params.docId;
const reason = request.params?.reason || '';
const declineBy = {
__type: 'Pointer',
className: '_User',
objectId: request.params?.userId,
};
try {
const docCls = new Parse.Query('contracts_Document');
const updateDoc = await docCls.get(docId, { useMasterKey: true });
if (updateDoc) {
const isEnableOTP = updateDoc?.get('IsEnableOTP') || false;
if (!isEnableOTP) {
updateDoc.set('IsDeclined', true);
updateDoc.set('DeclineReason', reason);
updateDoc.set('DeclineBy', declineBy);
await updateDoc.save(null, { useMasterKey: true });
return 'document declined';
} else {
if (!request?.user) {
throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'User is not authenticated.');
}
updateDoc.set('IsDeclined', true);
updateDoc.set('DeclineReason', reason);
updateDoc.set('DeclineBy', declineBy);
await updateDoc.save(null, { useMasterKey: true });
return 'document declined';
}
} else {
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Document not found.');
}
} catch (err) {
console.log('err while decling doc', err);
throw err;
}
}
@@ -0,0 +1,11 @@
export default async function getContact(request) {
const contactId = request.params.contactId;
try {
const contactCls = new Parse.Query('contracts_Contactbook');
const contactRes = await contactCls.get(contactId, { useMasterKey: true });
return contactRes;
} catch (err) {
console.log('Err in contracts_Contactbook class ', err);
throw err;
}
}
@@ -6,14 +6,7 @@ export default async function getDocument(request) {
const docId = request.params.docId; const docId = request.params.docId;
try { try {
const userRes = await axios.get(serverUrl + '/users/me', { if (docId) {
headers: {
'X-Parse-Application-Id': process.env.APP_ID,
'X-Parse-Session-Token': request.headers['sessiontoken'],
},
});
const userId = userRes.data && userRes.data.objectId;
if (docId && userId) {
try { try {
const query = new Parse.Query('contracts_Document'); const query = new Parse.Query('contracts_Document');
query.equalTo('objectId', docId); query.equalTo('objectId', docId);
@@ -26,12 +19,33 @@ export default async function getDocument(request) {
query.notEqualTo('IsArchive', true); query.notEqualTo('IsArchive', true);
const res = await query.first({ useMasterKey: true }); const res = await query.first({ useMasterKey: true });
if (res) { if (res) {
const IsEnableOTP = res?.get('IsEnableOTP') || false;
if (!IsEnableOTP) {
return res;
} else {
if (request?.headers?.['sessiontoken']) {
try {
const userRes = await axios.get(serverUrl + '/users/me', {
headers: {
'X-Parse-Application-Id': process.env.APP_ID,
'X-Parse-Session-Token': request.headers['sessiontoken'],
},
});
const userId = userRes.data && userRes.data?.objectId;
const acl = res.getACL(); const acl = res.getACL();
if (acl && acl.getReadAccess(userId)) { if (userId && acl && acl.getReadAccess(userId)) {
return res; return res;
} else { } else {
return { error: "You don't have access of this document!" }; return { error: "You don't have access of this document!" };
} }
} catch (err) {
console.log('err user in not authenticated', err);
return { error: "You don't have access of this document!" };
}
} else {
return { error: "You don't have access of this document!" };
}
}
} else { } else {
return { error: "You don't have access of this document!" }; return { error: "You don't have access of this document!" };
} }
@@ -28,7 +28,33 @@ export default function getPresignedUrl(url) {
export async function getSignedUrl(request) { export async function getSignedUrl(request) {
try { try {
const docId = request.params.docId || '';
const url = request.params.url; const url = request.params.url;
if (docId) {
try {
const query = new Parse.Query('contracts_Document');
query.equalTo('objectId', docId);
query.notEqualTo('IsEnableOTP', true);
query.include('CreatedBy');
query.include('Signers');
query.include('AuditTrail.UserPtr');
query.include('Placeholders');
query.include('DeclineBy');
query.notEqualTo('IsArchive', true);
const res = await query.first({ useMasterKey: true });
if (res) {
if (useLocal !== 'true') {
const presignedUrl = getPresignedUrl(url);
return presignedUrl;
} else {
return url;
}
}
} catch (err) {
console.log('Err in presigned url', err);
throw err;
}
} else {
if (!request?.user) { if (!request?.user) {
throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'User is not authenticated.'); throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'User is not authenticated.');
} else { } else {
@@ -39,6 +65,7 @@ export async function getSignedUrl(request) {
return url; return url;
} }
} }
}
} catch (err) { } catch (err) {
console.log('error in getsignedurl', err); console.log('error in getsignedurl', err);
const code = err.code || 400; const code = err.code || 400;
@@ -50,15 +50,6 @@ export default async function getSubscription(request) {
} }
} else if (contactId) { } else if (contactId) {
try { try {
const userRes = await axios.get(serverUrl + '/users/me', {
headers: {
'X-Parse-Application-Id': appId,
'X-Parse-Session-Token': request.headers['sessiontoken'],
},
});
const userId = userRes.data && userRes.data.objectId;
if (userId) {
const contactCls = new Parse.Query('contracts_Contactbook'); const contactCls = new Parse.Query('contracts_Contactbook');
const contactUser = await contactCls.get(contactId, { useMasterKey: true }); const contactUser = await contactCls.get(contactId, { useMasterKey: true });
if (contactUser) { if (contactUser) {
@@ -70,7 +61,6 @@ export default async function getSubscription(request) {
}); });
subscriptionCls.descending('createdAt'); subscriptionCls.descending('createdAt');
const subcripitions = await subscriptionCls.first({ useMasterKey: true }); const subcripitions = await subscriptionCls.first({ useMasterKey: true });
if (subcripitions) { if (subcripitions) {
const _subcripitions = JSON.parse(JSON.stringify(subcripitions)); const _subcripitions = JSON.parse(JSON.stringify(subcripitions));
if (_subcripitions.PlanCode === 'freeplan') { if (_subcripitions.PlanCode === 'freeplan') {
@@ -90,9 +80,6 @@ export default async function getSubscription(request) {
} else { } else {
return { status: 'error', result: 'User not found!' }; return { status: 'error', result: 'User not found!' };
} }
} else {
return { status: 'error', result: 'Invalid session token!' };
}
} catch (err) { } catch (err) {
console.log('Err in get subscription2', err.message); console.log('Err in get subscription2', err.message);
return { status: 'error', result: err.message }; return { status: 'error', result: err.message };
@@ -12,6 +12,8 @@ async function getUserDetails(request) {
} }
userQuery.include('TenantId'); userQuery.include('TenantId');
userQuery.include('UserId'); userQuery.include('UserId');
userQuery.include('CreatedBy');
userQuery.exclude('CreatedBy.authData');
userQuery.exclude('google_refresh_token'); userQuery.exclude('google_refresh_token');
if (userId) { if (userId) {
userQuery.equalTo('CreatedBy', { __type: 'Pointer', className: '_User', objectId: userId }); userQuery.equalTo('CreatedBy', { __type: 'Pointer', className: '_User', objectId: userId });
@@ -32,6 +32,7 @@ export default async function GenerateCertificate(docDetails) {
const OriginIp = docDetails?.OriginIp || ''; const OriginIp = docDetails?.OriginIp || '';
const company = docDetails?.ExtUserPtr?.Company || ''; const company = docDetails?.ExtUserPtr?.Company || '';
const createdAt = docDetails?.DocSentAt?.iso || docDetails.createdAt; const createdAt = docDetails?.DocSentAt?.iso || docDetails.createdAt;
const IsEnableOTP = docDetails?.IsEnableOTP || false;
const auditTrail = const auditTrail =
docDetails?.Signers?.length > 0 docDetails?.Signers?.length > 0
? docDetails.AuditTrail.map(x => { ? docDetails.AuditTrail.map(x => {
@@ -348,6 +349,7 @@ export default async function GenerateCertificate(docDetails) {
font: timesRomanFont, font: timesRomanFont,
color: textValueColor, color: textValueColor,
}); });
if (IsEnableOTP) {
page.drawText('Security level :', { page.drawText('Security level :', {
x: half + 55, x: half + 55,
y: yPosition4 + 10, y: yPosition4 + 10,
@@ -355,15 +357,14 @@ export default async function GenerateCertificate(docDetails) {
font: timesRomanFont, font: timesRomanFont,
color: textKeyColor, color: textKeyColor,
}); });
page.drawText('Email, OTP Auth', {
page.drawText(`Email, OTP Auth`, {
x: half + 125, x: half + 125,
y: yPosition4 + 10, y: yPosition4 + 10,
size: timeText, size: timeText,
font: timesRomanFont, font: timesRomanFont,
color: textValueColor, color: textValueColor,
}); });
}
page.drawText('Signature :', { page.drawText('Signature :', {
x: 30, x: 30,
y: yPosition5, y: yPosition5,
@@ -29,11 +29,7 @@ async function uploadFile(pdfName, filepath) {
// `updateDoc` is used to update signedUrl, AuditTrail, Iscompleted in document // `updateDoc` is used to update signedUrl, AuditTrail, Iscompleted in document
async function updateDoc(docId, url, userId, ipAddress, data, className, sign) { async function updateDoc(docId, url, userId, ipAddress, data, className, sign) {
try { try {
const UserPtr = { const UserPtr = { __type: 'Pointer', className: className, objectId: userId };
__type: 'Pointer',
className: className,
objectId: userId,
};
const obj = { const obj = {
UserPtr: UserPtr, UserPtr: UserPtr,
SignedUrl: url, SignedUrl: url,
@@ -66,11 +62,7 @@ async function updateDoc(docId, url, userId, ipAddress, data, className, sign) {
} else { } else {
isCompleted = true; isCompleted = true;
} }
const body = { const body = { SignedUrl: url, AuditTrail: updateAuditTrail, IsCompleted: isCompleted };
SignedUrl: url,
AuditTrail: updateAuditTrail,
IsCompleted: isCompleted,
};
const signedRes = await axios.put(serverUrl + '/classes/contracts_Document/' + docId, body, { const signedRes = await axios.put(serverUrl + '/classes/contracts_Document/' + docId, body, {
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
@@ -164,29 +156,16 @@ async function sendCompletedMail(obj) {
'X-Parse-Master-Key': masterKEY, 'X-Parse-Master-Key': masterKEY,
}, },
}); });
// console.log('Res ', res);
} }
// `sendDoctoWebhook` is used to send res data of document on webhook // `sendDoctoWebhook` is used to send res data of document on webhook
async function sendDoctoWebhook(doc, Url, event, signUser, certificateUrl) { async function sendDoctoWebhook(doc, Url, event, signUser, certificateUrl) {
let signers = []; let signers = [];
if (signUser) { if (signUser) {
signers = { signers = { name: signUser?.Name, email: signUser?.Email, phone: signUser?.Phone };
name: signUser?.Name,
email: signUser?.Email,
phone: signUser?.Phone,
};
} else { } else {
signers = doc?.Signers?.map(x => ({ signers = doc?.Signers?.map(x => ({ name: x.Name, email: x.Email, phone: x.Phone })) || [
name: x.Name, { name: doc?.ExtUserPtr?.Name, email: doc?.ExtUserPtr?.Email, phone: doc?.ExtUserPtr?.Phone },
email: x.Email,
phone: x.Phone,
})) || [
{
name: doc?.ExtUserPtr?.Name,
email: doc?.ExtUserPtr?.Email,
phone: doc?.ExtUserPtr?.Phone,
},
]; ];
} }
@@ -213,7 +192,6 @@ async function sendDoctoWebhook(doc, Url, event, signUser, certificateUrl) {
}) })
.then(res => { .then(res => {
try { try {
// console.log('res ', res);
const webhook = new Parse.Object('contracts_Webhook'); const webhook = new Parse.Object('contracts_Webhook');
webhook.set('Log', res?.status); webhook.set('Log', res?.status);
webhook.set('UserId', { webhook.set('UserId', {
@@ -241,7 +219,6 @@ async function sendDoctoWebhook(doc, Url, event, signUser, certificateUrl) {
console.log('err save in contracts_Webhook', err.message); console.log('err save in contracts_Webhook', err.message);
} }
}); });
// console.log('res ', res.data);
} }
} }
@@ -281,15 +258,9 @@ const sendMailsaveCertifcate = async (doc, P12Buffer, url, isCustomMail, mailPro
if (doc.IsSendMail === false) { if (doc.IsSendMail === false) {
console.log("don't send mail"); console.log("don't send mail");
} else { } else {
const mailObj = { const mailObj = { url: url, isCustomMail: isCustomMail, doc: doc, mailProvider: mailProvider };
url: url,
isCustomMail: isCustomMail,
doc: doc,
mailProvider: mailProvider,
};
sendCompletedMail(mailObj); sendCompletedMail(mailObj);
} }
saveFileUsage(CertificateBuffer.length, file.imageUrl, userId); saveFileUsage(CertificateBuffer.length, file.imageUrl, userId);
sendDoctoWebhook(doc, url, 'completed', '', file.imageUrl); sendDoctoWebhook(doc, url, 'completed', '', file.imageUrl);
}; };
@@ -301,11 +272,7 @@ const sendMailsaveCertifcate = async (doc, P12Buffer, url, isCustomMail, mailPro
*/ */
async function PDF(req) { async function PDF(req) {
try { try {
if (!req?.user) { const userIP = req.headers['x-real-ip']; // client IPaddress
throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'User is not authenticated.');
} else {
const password = '';
const authUser = req?.user?.toJSON();
const docId = req.params.docId; const docId = req.params.docId;
const reqUserId = req.params.userId; const reqUserId = req.params.userId;
const isCustomMail = req.params.isCustomCompletionMail || false; const isCustomMail = req.params.isCustomCompletionMail || false;
@@ -319,8 +286,14 @@ async function PDF(req) {
if (!resDoc) { if (!resDoc) {
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Document not found.'); throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Document not found.');
} }
const IsEnableOTP = resDoc?.get('IsEnableOTP') || false;
// if `IsEnableOTP` is false then we don't have to check authentication
if (IsEnableOTP) {
if (!req?.user) {
throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'User is not authenticated.');
}
}
const _resDoc = resDoc?.toJSON(); const _resDoc = resDoc?.toJSON();
let signUser; let signUser;
let className; let className;
// `reqUserId` is send throught pdfrequest signing flow // `reqUserId` is send throught pdfrequest signing flow
@@ -346,18 +319,8 @@ async function PDF(req) {
// const P12Buffer = fs.readFileSync(); // const P12Buffer = fs.readFileSync();
const P12Buffer = Buffer.from(pfxFile, 'base64'); const P12Buffer = Buffer.from(pfxFile, 'base64');
const p12Cert = new P12Signer(P12Buffer, { passphrase: process.env.PASS_PHRASE || null }); const p12Cert = new P12Signer(P12Buffer, { passphrase: process.env.PASS_PHRASE || null });
const UserPtr = { __type: 'Pointer', className: className, objectId: signUser.objectId };
const UserPtr = { const obj = { UserPtr: UserPtr, SignedUrl: '', Activity: 'Signed', ipAddress: userIP };
__type: 'Pointer',
className: className,
objectId: signUser.objectId,
};
const obj = {
UserPtr: UserPtr,
SignedUrl: '',
Activity: 'Signed',
ipAddress: req.headers['x-real-ip'],
};
let updateAuditTrail; let updateAuditTrail;
if (_resDoc.AuditTrail && _resDoc.AuditTrail.length > 0) { if (_resDoc.AuditTrail && _resDoc.AuditTrail.length > 0) {
updateAuditTrail = [..._resDoc.AuditTrail, obj]; updateAuditTrail = [..._resDoc.AuditTrail, obj];
@@ -430,13 +393,13 @@ async function PDF(req) {
req.params.docId, //docId req.params.docId, //docId
data.imageUrl, // url data.imageUrl, // url
signUser.objectId, // userID signUser.objectId, // userID
req.headers['x-real-ip'], // client ipAddress, userIP, // client ipAddress,
_resDoc, // auditTrail, signers, etc data _resDoc, // auditTrail, signers, etc data
className, className, // className based on flow
sign sign // sign base64
); );
sendDoctoWebhook(_resDoc, data.imageUrl, 'signed', signUser); sendDoctoWebhook(_resDoc, data.imageUrl, 'signed', signUser);
saveFileUsage(pdfSize, data.imageUrl, authUser.objectId); saveFileUsage(pdfSize, data.imageUrl, _resDoc?.CreatedBy?.objectId);
if (updatedDoc && updatedDoc.isCompleted) { if (updatedDoc && updatedDoc.isCompleted) {
const doc = { ..._resDoc, AuditTrail: updatedDoc.AuditTrail }; const doc = { ..._resDoc, AuditTrail: updatedDoc.AuditTrail };
sendMailsaveCertifcate( sendMailsaveCertifcate(
@@ -445,7 +408,7 @@ async function PDF(req) {
data.imageUrl, data.imageUrl,
isCustomMail, isCustomMail,
mailProvider, mailProvider,
authUser.objectId _resDoc?.CreatedBy?.objectId
); );
} }
// `fs.unlinkSync` is used to remove exported signed pdf file from exports folder // `fs.unlinkSync` is used to remove exported signed pdf file from exports folder
@@ -464,7 +427,6 @@ async function PDF(req) {
error.code = 400; // Set the error code (e.g., 400 for bad request) error.code = 400; // Set the error code (e.g., 400 for bad request)
throw error; throw error;
} }
}
} catch (err) { } catch (err) {
console.log('Err in signpdf', err); console.log('Err in signpdf', err);
throw err; throw err;
@@ -0,0 +1,33 @@
export default async function updateContactTour(request) {
const contactId = request.params.contactId;
try {
const contactCls = new Parse.Query('contracts_Contactbook');
const contactRes = await contactCls.get(contactId, { useMasterKey: true });
if (contactRes) {
const _contactRes = JSON.parse(JSON.stringify(contactRes));
const tourStatus = _contactRes?.TourStatus?.length > 0 ? _contactRes.TourStatus : [];
let updatedTourStatus = [];
if (tourStatus.length > 0) {
updatedTourStatus = [...tourStatus];
const requestSignIndex = tourStatus.findIndex(
obj => obj['requestSign'] === false || obj['requestSign'] === true
);
if (requestSignIndex !== -1) {
updatedTourStatus[requestSignIndex] = { requestSign: true };
} else {
updatedTourStatus.push({ requestSign: true });
}
} else {
updatedTourStatus = [{ requestSign: true }];
}
contactRes.set('TourStatus', updatedTourStatus);
const updateRes = await contactRes.save(null, { useMasterKey: true });
return updateRes;
} else {
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'contact not found.');
}
} catch (err) {
console.log('Err in contracts_Contactbook class ', err);
throw err;
}
}
@@ -0,0 +1,29 @@
/**
*
* @param {Parse} Parse
*/
exports.up = async Parse => {
const templateSchema = new Parse.Schema('contracts_Template');
templateSchema.addBoolean('IsEnableOTP');
await templateSchema.update();
const className = 'contracts_Document';
const schema = new Parse.Schema(className);
schema.addBoolean('IsEnableOTP');
return schema.update();
};
/**
*
* @param {Parse} Parse
*/
exports.down = async Parse => {
const templateSchema = new Parse.Schema('contracts_Template');
templateSchema.deleteField('IsEnableOTP');
await templateSchema.update();
const className = 'contracts_Document';
const schema = new Parse.Schema(className);
schema.deleteField('IsEnableOTP');
return schema.update();
};
+174 -169
View File
@@ -19,17 +19,17 @@
"axios": "^1.7.7", "axios": "^1.7.7",
"cors": "^2.8.5", "cors": "^2.8.5",
"dotenv": "^16.4.5", "dotenv": "^16.4.5",
"express": "^4.20.0", "express": "^4.21.0",
"form-data": "^4.0.0", "form-data": "^4.0.0",
"generate-api-key": "^1.0.2", "generate-api-key": "^1.0.2",
"googleapis": "^140.0.1", "googleapis": "^140.0.1",
"jsonschema": "^1.4.1", "jsonschema": "^1.4.1",
"mailgun.js": "^10.2.3", "mailgun.js": "^10.2.3",
"mongoose": "^8.6.0", "mongoose": "^8.6.1",
"multer": "^1.4.5-lts.1", "multer": "^1.4.5-lts.1",
"multer-s3": "^3.0.1", "multer-s3": "^3.0.1",
"node-forge": "^1.3.1", "node-forge": "^1.3.1",
"nodemailer": "^6.9.14", "nodemailer": "^6.9.15",
"parse": "^5.3.0", "parse": "^5.3.0",
"parse-dbtool": "^1.2.0", "parse-dbtool": "^1.2.0",
"parse-server": "^7.2.0", "parse-server": "^7.2.0",
@@ -41,7 +41,7 @@
"devDependencies": { "devDependencies": {
"@babel/eslint-parser": "^7.25.1", "@babel/eslint-parser": "^7.25.1",
"eslint": "^9.9.1", "eslint": "^9.9.1",
"jasmine": "^5.2.0", "jasmine": "^5.3.0",
"mongodb-runner": "^5.6.6", "mongodb-runner": "^5.6.6",
"nodemon": "^3.1.4", "nodemon": "^3.1.4",
"nyc": "^17.0.0", "nyc": "^17.0.0",
@@ -1770,11 +1770,12 @@
} }
}, },
"node_modules/@google-cloud/firestore": { "node_modules/@google-cloud/firestore": {
"version": "7.9.0", "version": "7.10.0",
"resolved": "https://registry.npmjs.org/@google-cloud/firestore/-/firestore-7.9.0.tgz", "resolved": "https://registry.npmjs.org/@google-cloud/firestore/-/firestore-7.10.0.tgz",
"integrity": "sha512-c4ALHT3G08rV7Zwv8Z2KG63gZh66iKdhCBeDfCpIkLrjX6EAjTD/szMdj14M+FnQuClZLFfW5bAgoOjfNmLtJg==", "integrity": "sha512-VFNhdHvfnmqcHHs6YhmSNHHxQqaaD64GwiL0c+e1qz85S8SWZPC2XFRf8p9yHRTF40Kow424s1KBU9f0fdQa+Q==",
"optional": true, "optional": true,
"dependencies": { "dependencies": {
"@opentelemetry/api": "^1.3.0",
"fast-deep-equal": "^3.1.1", "fast-deep-equal": "^3.1.1",
"functional-red-black-tree": "^1.0.1", "functional-red-black-tree": "^1.0.1",
"google-gax": "^4.3.3", "google-gax": "^4.3.3",
@@ -1866,9 +1867,9 @@
} }
}, },
"node_modules/@graphql-tools/merge/node_modules/@graphql-tools/utils": { "node_modules/@graphql-tools/merge/node_modules/@graphql-tools/utils": {
"version": "10.5.2", "version": "10.5.4",
"resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-10.5.2.tgz", "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-10.5.4.tgz",
"integrity": "sha512-VZpw7wxwmQGcCGt8epw6fDb8LkoySbTJ/MU565ibKivPqCkH96XK36Et/N0RlRCYGN6QAXn5UIaSbOYYHrnpAA==", "integrity": "sha512-XHnyCWSlg1ccsD8s0y6ugo5GZ5TpkTiFVNPSYms5G0s6Z/xTuSmiLBfeqgkfaCwLmLaQnRCmNDL2JRnqc2R5bQ==",
"dependencies": { "dependencies": {
"@graphql-typed-document-node/core": "^3.1.1", "@graphql-typed-document-node/core": "^3.1.1",
"cross-inspect": "1.0.1", "cross-inspect": "1.0.1",
@@ -1900,9 +1901,9 @@
} }
}, },
"node_modules/@graphql-tools/schema/node_modules/@graphql-tools/utils": { "node_modules/@graphql-tools/schema/node_modules/@graphql-tools/utils": {
"version": "10.5.2", "version": "10.5.4",
"resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-10.5.2.tgz", "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-10.5.4.tgz",
"integrity": "sha512-VZpw7wxwmQGcCGt8epw6fDb8LkoySbTJ/MU565ibKivPqCkH96XK36Et/N0RlRCYGN6QAXn5UIaSbOYYHrnpAA==", "integrity": "sha512-XHnyCWSlg1ccsD8s0y6ugo5GZ5TpkTiFVNPSYms5G0s6Z/xTuSmiLBfeqgkfaCwLmLaQnRCmNDL2JRnqc2R5bQ==",
"dependencies": { "dependencies": {
"@graphql-typed-document-node/core": "^3.1.1", "@graphql-typed-document-node/core": "^3.1.1",
"cross-inspect": "1.0.1", "cross-inspect": "1.0.1",
@@ -1936,9 +1937,9 @@
} }
}, },
"node_modules/@grpc/grpc-js": { "node_modules/@grpc/grpc-js": {
"version": "1.11.1", "version": "1.11.2",
"resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.11.1.tgz", "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.11.2.tgz",
"integrity": "sha512-gyt/WayZrVPH2w/UTLansS7F9Nwld472JxxaETamrM8HNlsa+jSLNyKAZmhxI2Me4c3mQHFiS1wWHDY1g1Kthw==", "integrity": "sha512-DWp92gDD7/Qkj7r8kus6/HCINeo3yPZWZ3paKgDgsbKbSpoxKg1yvN8xe2Q8uE3zOsPe3bX8FQX2+XValq2yTw==",
"optional": true, "optional": true,
"dependencies": { "dependencies": {
"@grpc/proto-loader": "^0.7.13", "@grpc/proto-loader": "^0.7.13",
@@ -2625,6 +2626,15 @@
"node": ">= 8" "node": ">= 8"
} }
}, },
"node_modules/@opentelemetry/api": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz",
"integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==",
"optional": true,
"engines": {
"node": ">=8.0.0"
}
},
"node_modules/@parse/fs-files-adapter": { "node_modules/@parse/fs-files-adapter": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/@parse/fs-files-adapter/-/fs-files-adapter-3.0.0.tgz", "resolved": "https://registry.npmjs.org/@parse/fs-files-adapter/-/fs-files-adapter-3.0.0.tgz",
@@ -3771,11 +3781,11 @@
"integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==" "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w=="
}, },
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "22.2.0", "version": "22.5.5",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.2.0.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.5.tgz",
"integrity": "sha512-bm6EG6/pCpkxDf/0gDNDdtDILMOHgaQBVOJGdwsqClnxA3xL6jtMv76rLBc006RVMWbmaf0xbmom4Z/5o2nRkQ==", "integrity": "sha512-Xjs4y5UPO/CLdzpgR6GirZJx36yScjh73+2NlLlkFRSoQN8B0DpfXPdZGnvVmLRLOsqDpOfTNv7D9trgGhmOIA==",
"dependencies": { "dependencies": {
"undici-types": "~6.13.0" "undici-types": "~6.19.2"
} }
}, },
"node_modules/@types/node-fetch": { "node_modules/@types/node-fetch": {
@@ -3793,9 +3803,9 @@
"integrity": "sha512-4tgJ1Z3elF/tOMpA8JLVuR9spt9Ynsf7+JjqsQ2IqtiPJtcLoHoXcT6qU4E10cPFqyXX5HDm9QwIzZhBSkLxsw==" "integrity": "sha512-4tgJ1Z3elF/tOMpA8JLVuR9spt9Ynsf7+JjqsQ2IqtiPJtcLoHoXcT6qU4E10cPFqyXX5HDm9QwIzZhBSkLxsw=="
}, },
"node_modules/@types/qs": { "node_modules/@types/qs": {
"version": "6.9.15", "version": "6.9.16",
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.16.tgz",
"integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==" "integrity": "sha512-7i+zxXdPD0T4cKDuxCUXJ4wHcsJLwENa6Z3dCu8cfCK743OGy5Nu1RmAGqDPsoTDINVEcdXKRvR/zre+P2Ku1A=="
}, },
"node_modules/@types/range-parser": { "node_modules/@types/range-parser": {
"version": "1.2.7", "version": "1.2.7",
@@ -4157,9 +4167,9 @@
} }
}, },
"node_modules/aws4": { "node_modules/aws4": {
"version": "1.13.1", "version": "1.13.2",
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.1.tgz", "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.2.tgz",
"integrity": "sha512-u5w79Rd7SU4JaIlA/zFqG+gOiuq25q5VLyZ8E+ijJeILuTxVzZgp2CaGw/UTw6pXYN9XMO9yiqj/nEHmhTG5CA==" "integrity": "sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw=="
}, },
"node_modules/axios": { "node_modules/axios": {
"version": "1.7.7", "version": "1.7.7",
@@ -4270,9 +4280,9 @@
"integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA=="
}, },
"node_modules/body-parser": { "node_modules/body-parser": {
"version": "1.20.2", "version": "1.20.3",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz",
"integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==",
"dependencies": { "dependencies": {
"bytes": "3.1.2", "bytes": "3.1.2",
"content-type": "~1.0.5", "content-type": "~1.0.5",
@@ -4282,7 +4292,7 @@
"http-errors": "2.0.0", "http-errors": "2.0.0",
"iconv-lite": "0.4.24", "iconv-lite": "0.4.24",
"on-finished": "2.4.1", "on-finished": "2.4.1",
"qs": "6.11.0", "qs": "6.13.0",
"raw-body": "2.5.2", "raw-body": "2.5.2",
"type-is": "~1.6.18", "type-is": "~1.6.18",
"unpipe": "1.0.0" "unpipe": "1.0.0"
@@ -4305,6 +4315,20 @@
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
}, },
"node_modules/body-parser/node_modules/qs": {
"version": "6.13.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz",
"integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==",
"dependencies": {
"side-channel": "^1.0.6"
},
"engines": {
"node": ">=0.6"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/bowser": { "node_modules/bowser": {
"version": "2.11.0", "version": "2.11.0",
"resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz", "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz",
@@ -5201,9 +5225,9 @@
} }
}, },
"node_modules/dset": { "node_modules/dset": {
"version": "3.1.3", "version": "3.1.4",
"resolved": "https://registry.npmjs.org/dset/-/dset-3.1.3.tgz", "resolved": "https://registry.npmjs.org/dset/-/dset-3.1.4.tgz",
"integrity": "sha512-20TuZZHCEZ2O71q9/+8BwKwZ0QtD9D8ObhrihJPr+vLLYlSuAU3/zL4cSlgbfeoGHTjCSJBa7NGcrF9/Bx/WJQ==", "integrity": "sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==",
"engines": { "engines": {
"node": ">=4" "node": ">=4"
} }
@@ -5746,9 +5770,9 @@
} }
}, },
"node_modules/express": { "node_modules/express": {
"version": "4.20.0", "version": "4.21.0",
"resolved": "https://registry.npmjs.org/express/-/express-4.20.0.tgz", "resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz",
"integrity": "sha512-pLdae7I6QqShF5PnNTCVn4hI91Dx0Grkn2+IAsMTgMIKuQVte2dN9PeGSSAME2FR8anOhVA62QDIUaWVfEXVLw==", "integrity": "sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==",
"dependencies": { "dependencies": {
"accepts": "~1.3.8", "accepts": "~1.3.8",
"array-flatten": "1.1.1", "array-flatten": "1.1.1",
@@ -5762,7 +5786,7 @@
"encodeurl": "~2.0.0", "encodeurl": "~2.0.0",
"escape-html": "~1.0.3", "escape-html": "~1.0.3",
"etag": "~1.8.1", "etag": "~1.8.1",
"finalhandler": "1.2.0", "finalhandler": "1.3.1",
"fresh": "0.5.2", "fresh": "0.5.2",
"http-errors": "2.0.0", "http-errors": "2.0.0",
"merge-descriptors": "1.0.3", "merge-descriptors": "1.0.3",
@@ -5771,11 +5795,11 @@
"parseurl": "~1.3.3", "parseurl": "~1.3.3",
"path-to-regexp": "0.1.10", "path-to-regexp": "0.1.10",
"proxy-addr": "~2.0.7", "proxy-addr": "~2.0.7",
"qs": "6.11.0", "qs": "6.13.0",
"range-parser": "~1.2.1", "range-parser": "~1.2.1",
"safe-buffer": "5.2.1", "safe-buffer": "5.2.1",
"send": "0.19.0", "send": "0.19.0",
"serve-static": "1.16.0", "serve-static": "1.16.2",
"setprototypeof": "1.2.0", "setprototypeof": "1.2.0",
"statuses": "2.0.1", "statuses": "2.0.1",
"type-is": "~1.6.18", "type-is": "~1.6.18",
@@ -5797,43 +5821,6 @@
"express": "^4 || ^5" "express": "^4 || ^5"
} }
}, },
"node_modules/express/node_modules/body-parser": {
"version": "1.20.3",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz",
"integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==",
"dependencies": {
"bytes": "3.1.2",
"content-type": "~1.0.5",
"debug": "2.6.9",
"depd": "2.0.0",
"destroy": "1.2.0",
"http-errors": "2.0.0",
"iconv-lite": "0.4.24",
"on-finished": "2.4.1",
"qs": "6.13.0",
"raw-body": "2.5.2",
"type-is": "~1.6.18",
"unpipe": "1.0.0"
},
"engines": {
"node": ">= 0.8",
"npm": "1.2.8000 || >= 1.4.16"
}
},
"node_modules/express/node_modules/body-parser/node_modules/qs": {
"version": "6.13.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz",
"integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==",
"dependencies": {
"side-channel": "^1.0.6"
},
"engines": {
"node": ">=0.6"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/express/node_modules/debug": { "node_modules/express/node_modules/debug": {
"version": "2.6.9", "version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
@@ -5850,11 +5837,42 @@
"node": ">= 0.8" "node": ">= 0.8"
} }
}, },
"node_modules/express/node_modules/finalhandler": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz",
"integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==",
"dependencies": {
"debug": "2.6.9",
"encodeurl": "~2.0.0",
"escape-html": "~1.0.3",
"on-finished": "2.4.1",
"parseurl": "~1.3.3",
"statuses": "2.0.1",
"unpipe": "~1.0.0"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/express/node_modules/ms": { "node_modules/express/node_modules/ms": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
}, },
"node_modules/express/node_modules/qs": {
"version": "6.13.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz",
"integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==",
"dependencies": {
"side-channel": "^1.0.6"
},
"engines": {
"node": ">=0.6"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/ext": { "node_modules/ext": {
"version": "1.7.0", "version": "1.7.0",
"resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz",
@@ -6125,11 +6143,11 @@
} }
}, },
"node_modules/firebase-admin/node_modules/@types/node": { "node_modules/firebase-admin/node_modules/@types/node": {
"version": "20.14.15", "version": "20.16.5",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.15.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.5.tgz",
"integrity": "sha512-Fz1xDMCF/B00/tYSVMlmK7hVeLh7jE5f3B7X1/hmV0MJBwE27KlS7EvD/Yp+z1lm8mVhwV5w+n8jOZG8AfTlKw==", "integrity": "sha512-VwYCweNo3ERajwy0IUlqqcyZ8/A7Zwa9ZP3MnENWcB11AejO+tLy3pu850goUW2FC/IJMdZUfKpX/yxL1gymCA==",
"dependencies": { "dependencies": {
"undici-types": "~5.26.4" "undici-types": "~6.19.2"
} }
}, },
"node_modules/firebase-admin/node_modules/long": { "node_modules/firebase-admin/node_modules/long": {
@@ -6137,11 +6155,6 @@
"resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz",
"integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q=="
}, },
"node_modules/firebase-admin/node_modules/undici-types": {
"version": "5.26.5",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="
},
"node_modules/flat-cache": { "node_modules/flat-cache": {
"version": "4.0.1", "version": "4.0.1",
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
@@ -6583,9 +6596,9 @@
} }
}, },
"node_modules/google-gax": { "node_modules/google-gax": {
"version": "4.3.9", "version": "4.4.1",
"resolved": "https://registry.npmjs.org/google-gax/-/google-gax-4.3.9.tgz", "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-4.4.1.tgz",
"integrity": "sha512-tcjQr7sXVGMdlvcG25wSv98ap1dtF4Z6mcV0rztGIddOcezw4YMb/uTXg72JPrLep+kXcVjaJjg6oo3KLf4itQ==", "integrity": "sha512-Phyp9fMfA00J3sZbJxbbB4jC55b7DBjE3F6poyL3wKMEBVKA79q6BGuHcTiM28yOzVql0NDbRL8MLLh8Iwk9Dg==",
"optional": true, "optional": true,
"dependencies": { "dependencies": {
"@grpc/grpc-js": "^1.10.9", "@grpc/grpc-js": "^1.10.9",
@@ -7426,22 +7439,22 @@
} }
}, },
"node_modules/jasmine": { "node_modules/jasmine": {
"version": "5.2.0", "version": "5.3.0",
"resolved": "https://registry.npmjs.org/jasmine/-/jasmine-5.2.0.tgz", "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-5.3.0.tgz",
"integrity": "sha512-il+noV96N1BGU9/FMmc8QtAMxC8lPnXUiAvgb0o9MDZATRdxglTQe9wo6UdL049ropQL6MopDYwDlludKR6wJQ==", "integrity": "sha512-Vrv5VWTXVZ/5xcNawlYCmE24pOaZu3KduLr9iAaENoMJ8W8Ryvhfpw2cf3rI4Unc2ajvu2t4tCKjS72TnraBGQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"glob": "^10.2.2", "glob": "^10.2.2",
"jasmine-core": "~5.2.0" "jasmine-core": "~5.3.0"
}, },
"bin": { "bin": {
"jasmine": "bin/jasmine.js" "jasmine": "bin/jasmine.js"
} }
}, },
"node_modules/jasmine-core": { "node_modules/jasmine-core": {
"version": "5.2.0", "version": "5.3.0",
"resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-5.2.0.tgz", "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-5.3.0.tgz",
"integrity": "sha512-tSAtdrvWybZkQmmaIoDgnvHG8ORUNw5kEVlO5CvrXj02Jjr9TZrmjFq7FUiOUzJiOP2wLGYT6PgrQgQF4R1xiw==", "integrity": "sha512-zsOmeBKESky4toybvWEikRiZ0jHoBEu79wNArLfMdSnlLMZx3Xcp6CSm2sUcYyoJC+Uyj8LBJap/MUbVSfJ27g==",
"dev": true "dev": true
}, },
"node_modules/jmespath": { "node_modules/jmespath": {
@@ -7828,9 +7841,9 @@
} }
}, },
"node_modules/loglevel": { "node_modules/loglevel": {
"version": "1.9.1", "version": "1.9.2",
"resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.9.1.tgz", "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.9.2.tgz",
"integrity": "sha512-hP3I3kCrDIMuRwAwHltphhDM1r8i55H33GgqjXbrisuJhF4kRhW1dNuxsRklp4bXl8DSdLaNLuiL4A/LWRfxvg==", "integrity": "sha512-HgMmCqIJSAKqo68l0rS2AanEWfkxaZ5wNiEFb5ggm08lDs9Xl2KxBlX3PTcaD2chBM1gXAYf491/M2Rv8Jwayg==",
"engines": { "engines": {
"node": ">= 0.6.0" "node": ">= 0.6.0"
}, },
@@ -8276,9 +8289,9 @@
} }
}, },
"node_modules/mongoose": { "node_modules/mongoose": {
"version": "8.6.0", "version": "8.6.1",
"resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.6.0.tgz", "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.6.1.tgz",
"integrity": "sha512-p6VSbYKvD4ZIabqo8C0kS5eKX1Xpji+opTAIJ9wyuPJ8Y/FblgXSMnFRXnB40bYZLKPQT089K5KU8+bqIXtFdw==", "integrity": "sha512-dppGcYqvsdg+VcnqXR5b467V4a+iNhmvkfYNpEPi6AjaUxnz6ioEDmrMLOi+sOWjvoHapuwPOigV4f2l7HC6ag==",
"dependencies": { "dependencies": {
"bson": "^6.7.0", "bson": "^6.7.0",
"kareem": "2.6.3", "kareem": "2.6.3",
@@ -8501,9 +8514,9 @@
"integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==" "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ=="
}, },
"node_modules/node-abi": { "node_modules/node-abi": {
"version": "3.65.0", "version": "3.67.0",
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.65.0.tgz", "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.67.0.tgz",
"integrity": "sha512-ThjYBfoDNr08AWx6hGaRbfPwxKV9kVzAzOzlLKbk2CuqXE2xnCh+cbAGnwM3t8Lq4v9rUB7VfondlkBckcJrVA==", "integrity": "sha512-bLn/fU/ALVBE9wj+p4Y21ZJWYFjUXLXPi/IewyLZkx3ApxKDNBWCKdReeKOtD8dWpOdDCeMyLh6ZewzcLsG2Nw==",
"dependencies": { "dependencies": {
"semver": "^7.3.5" "semver": "^7.3.5"
}, },
@@ -8596,9 +8609,9 @@
"integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==" "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g=="
}, },
"node_modules/nodemailer": { "node_modules/nodemailer": {
"version": "6.9.14", "version": "6.9.15",
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.14.tgz", "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.15.tgz",
"integrity": "sha512-Dobp/ebDKBvz91sbtRKhcznLThrKxKt97GI2FAlAyy+fk19j73Uz3sBXolVtmcXjaorivqsbbbjDY+Jkt4/bQA==", "integrity": "sha512-AHf04ySLC6CIfuRtRiEYtGEXgRfa6INgWGluDhnxTZhHSKvrBu7lc1VVchQ0d8nPc4cFaZoPq8vkyNoZr0TpGQ==",
"engines": { "engines": {
"node": ">=6.0.0" "node": ">=6.0.0"
} }
@@ -9397,6 +9410,42 @@
"url": "https://github.com/chalk/ansi-styles?sponsor=1" "url": "https://github.com/chalk/ansi-styles?sponsor=1"
} }
}, },
"node_modules/parse-server/node_modules/body-parser": {
"version": "1.20.2",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz",
"integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==",
"dependencies": {
"bytes": "3.1.2",
"content-type": "~1.0.5",
"debug": "2.6.9",
"depd": "2.0.0",
"destroy": "1.2.0",
"http-errors": "2.0.0",
"iconv-lite": "0.4.24",
"on-finished": "2.4.1",
"qs": "6.11.0",
"raw-body": "2.5.2",
"type-is": "~1.6.18",
"unpipe": "1.0.0"
},
"engines": {
"node": ">= 0.8",
"npm": "1.2.8000 || >= 1.4.16"
}
},
"node_modules/parse-server/node_modules/body-parser/node_modules/debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"dependencies": {
"ms": "2.0.0"
}
},
"node_modules/parse-server/node_modules/body-parser/node_modules/ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
},
"node_modules/parse-server/node_modules/bson": { "node_modules/parse-server/node_modules/bson": {
"version": "5.5.1", "version": "5.5.1",
"resolved": "https://registry.npmjs.org/bson/-/bson-5.5.1.tgz", "resolved": "https://registry.npmjs.org/bson/-/bson-5.5.1.tgz",
@@ -10400,9 +10449,9 @@
} }
}, },
"node_modules/protobufjs": { "node_modules/protobufjs": {
"version": "7.3.2", "version": "7.4.0",
"resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.3.2.tgz", "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.4.0.tgz",
"integrity": "sha512-RXyHaACeqXeqAKGLDl68rQKbmObRsTIn4TYVUUug1KfS47YWCo5MacGITEryugIgZqORCvJWEk4l449POg5Txg==", "integrity": "sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==",
"hasInstallScript": true, "hasInstallScript": true,
"optional": true, "optional": true,
"dependencies": { "dependencies": {
@@ -10458,9 +10507,9 @@
"dev": true "dev": true
}, },
"node_modules/pump": { "node_modules/pump": {
"version": "3.0.0", "version": "3.0.2",
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz",
"integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==",
"dependencies": { "dependencies": {
"end-of-stream": "^1.1.0", "end-of-stream": "^1.1.0",
"once": "^1.3.1" "once": "^1.3.1"
@@ -10932,69 +10981,25 @@
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
}, },
"node_modules/serve-static": { "node_modules/serve-static": {
"version": "1.16.0", "version": "1.16.2",
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.0.tgz", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz",
"integrity": "sha512-pDLK8zwl2eKaYrs8mrPZBJua4hMplRWJ1tIFksVC3FtBEBnl8dxgeHtsaMS8DhS9i4fLObaon6ABoc4/hQGdPA==", "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==",
"dependencies": { "dependencies": {
"encodeurl": "~1.0.2", "encodeurl": "~2.0.0",
"escape-html": "~1.0.3", "escape-html": "~1.0.3",
"parseurl": "~1.3.3", "parseurl": "~1.3.3",
"send": "0.18.0" "send": "0.19.0"
}, },
"engines": { "engines": {
"node": ">= 0.8.0" "node": ">= 0.8.0"
} }
}, },
"node_modules/serve-static/node_modules/debug": { "node_modules/serve-static/node_modules/encodeurl": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"dependencies": {
"ms": "2.0.0"
}
},
"node_modules/serve-static/node_modules/debug/node_modules/ms": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
},
"node_modules/serve-static/node_modules/mime": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
"bin": {
"mime": "cli.js"
},
"engines": { "engines": {
"node": ">=4" "node": ">= 0.8"
}
},
"node_modules/serve-static/node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
},
"node_modules/serve-static/node_modules/send": {
"version": "0.18.0",
"resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
"integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==",
"dependencies": {
"debug": "2.6.9",
"depd": "2.0.0",
"destroy": "1.2.0",
"encodeurl": "~1.0.2",
"escape-html": "~1.0.3",
"etag": "~1.8.1",
"fresh": "0.5.2",
"http-errors": "2.0.0",
"mime": "1.6.0",
"ms": "2.1.3",
"on-finished": "2.4.1",
"range-parser": "~1.2.1",
"statuses": "2.0.1"
},
"engines": {
"node": ">= 0.8.0"
} }
}, },
"node_modules/set-blocking": { "node_modules/set-blocking": {
@@ -11997,9 +12002,9 @@
"dev": true "dev": true
}, },
"node_modules/undici-types": { "node_modules/undici-types": {
"version": "6.13.0", "version": "6.19.8",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.13.0.tgz", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
"integrity": "sha512-xtFJHudx8S2DSoujjMd1WeWvn7KKWFRESZTMeL1RptAYERu29D6jphMjjY+vn96jvN3kVPDNxU/E13VTaXj6jg==" "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw=="
}, },
"node_modules/unpipe": { "node_modules/unpipe": {
"version": "1.0.0", "version": "1.0.0",
+4 -4
View File
@@ -28,17 +28,17 @@
"axios": "^1.7.7", "axios": "^1.7.7",
"cors": "^2.8.5", "cors": "^2.8.5",
"dotenv": "^16.4.5", "dotenv": "^16.4.5",
"express": "^4.20.0", "express": "^4.21.0",
"form-data": "^4.0.0", "form-data": "^4.0.0",
"generate-api-key": "^1.0.2", "generate-api-key": "^1.0.2",
"googleapis": "^140.0.1", "googleapis": "^140.0.1",
"jsonschema": "^1.4.1", "jsonschema": "^1.4.1",
"mailgun.js": "^10.2.3", "mailgun.js": "^10.2.3",
"mongoose": "^8.6.0", "mongoose": "^8.6.1",
"multer": "^1.4.5-lts.1", "multer": "^1.4.5-lts.1",
"multer-s3": "^3.0.1", "multer-s3": "^3.0.1",
"node-forge": "^1.3.1", "node-forge": "^1.3.1",
"nodemailer": "^6.9.14", "nodemailer": "^6.9.15",
"parse": "^5.3.0", "parse": "^5.3.0",
"parse-dbtool": "^1.2.0", "parse-dbtool": "^1.2.0",
"parse-server": "^7.2.0", "parse-server": "^7.2.0",
@@ -51,7 +51,7 @@
"devDependencies": { "devDependencies": {
"@babel/eslint-parser": "^7.25.1", "@babel/eslint-parser": "^7.25.1",
"eslint": "^9.9.1", "eslint": "^9.9.1",
"jasmine": "^5.2.0", "jasmine": "^5.3.0",
"mongodb-runner": "^5.6.6", "mongodb-runner": "^5.6.6",
"nodemon": "^3.1.4", "nodemon": "^3.1.4",
"nyc": "^17.0.0", "nyc": "^17.0.0",