Compare commits

...

39 Commits

Author SHA1 Message Date
standardci
6dfb2be4a2 chore(release): publish new version
- @standardnotes/auth-server@1.73.0
2022-12-28 13:09:57 +00:00
Karol Sójko
d81cbad550 Merge pull request #381 from standardnotes/authenticator_registration
feat(auth): add generating authencator registration options
2022-12-28 14:08:02 +01:00
Karol Sójko
51ad06b303 feat(auth): add generating authencator registration options 2022-12-28 13:56:06 +01:00
standardci
27048ad95c chore(release): publish new version
- @standardnotes/auth-server@1.72.0
2022-12-28 11:42:03 +00:00
Karol Sójko
fa9bf0b448 feat(auth): add authenticator challenges model 2022-12-28 12:40:13 +01:00
standardci
305190b64e chore(release): publish new version
- @standardnotes/auth-server@1.71.1
2022-12-28 11:27:35 +00:00
Karol Sójko
98e3d18335 fix(auth): credential id field type 2022-12-28 12:25:36 +01:00
standardci
72e398956b chore(release): publish new version
- @standardnotes/auth-server@1.71.0
2022-12-28 10:39:38 +00:00
Karol Sójko
1e69a13a97 feat(auth): add authenticators model 2022-12-28 11:37:06 +01:00
standardci
7f9e6e2f44 chore(release): publish new version
- @standardnotes/analytics@2.17.8
 - @standardnotes/api-gateway@1.41.3
 - @standardnotes/auth-server@1.70.9
 - @standardnotes/files-server@1.9.3
 - @standardnotes/revisions-server@1.10.3
 - @standardnotes/scheduler-server@1.16.4
 - @standardnotes/syncing-server@1.28.3
 - @standardnotes/websockets-server@1.5.3
 - @standardnotes/workspace-server@1.19.4
2022-12-28 07:07:42 +00:00
Karol Sójko
d3c6c0d48e chore(upgrade): sentry deps 2022-12-28 08:05:42 +01:00
Karol Sójko
6c83476fd2 chore: workflow disptach name 2022-12-27 15:50:40 +01:00
Karol Sójko
9cdf7e2c51 Revert "feat: add workflow for tagging latest versions as stable"
This reverts commit a2c484e0f3.
2022-12-27 15:37:32 +01:00
Karol Sójko
599119e14e chore: move e2e test suite to self-hosted repo 2022-12-27 15:00:11 +01:00
Karol Sójko
a2c484e0f3 feat: add workflow for tagging latest versions as stable 2022-12-27 14:43:36 +01:00
standardci
97ff4d5ac2 chore(release): publish new version
- @standardnotes/auth-server@1.70.8
2022-12-20 20:24:56 +00:00
Karol Sójko
5255cfbb25 fix(auth): move tracing sessions to session creation instead of cross service token creation 2022-12-20 21:22:24 +01:00
standardci
780358368b chore(release): publish new version
- @standardnotes/auth-server@1.70.7
2022-12-20 19:55:43 +00:00
Karol Sójko
cf0b918913 fix(auth): change severity on tracing session errors - most probably hazardous reads 2022-12-20 20:53:26 +01:00
standardci
4ea690204e chore(release): publish new version
- @standardnotes/auth-server@1.70.6
2022-12-20 18:54:47 +00:00
Karol Sójko
14eb775749 fix(auth): query for session traces 2022-12-20 19:52:32 +01:00
standardci
bf4a3be6d9 chore(release): publish new version
- @standardnotes/auth-server@1.70.5
2022-12-20 18:48:19 +00:00
Karol Sójko
b9e1e47871 fix(auth): add session traces index 2022-12-20 19:46:05 +01:00
standardci
ff532ecb22 chore(release): publish new version
- @standardnotes/scheduler-server@1.16.3
2022-12-20 18:21:59 +00:00
Karol Sójko
eb21872db1 fix(scheduler): new pricing for subscription encouragement email 2022-12-20 19:19:59 +01:00
standardci
8e3df184dc chore(release): publish new version
- @standardnotes/analytics@2.17.7
2022-12-20 14:43:24 +00:00
Karol Sójko
b34bbcac8b fix(analytics): monthly numbers of active users 2022-12-20 15:41:03 +01:00
standardci
226965a1d7 chore(release): publish new version
- @standardnotes/analytics@2.17.6
2022-12-20 14:04:05 +00:00
Karol Sójko
17b2ea126c fix(analytics): filtered counts for user activity check 2022-12-20 15:02:09 +01:00
standardci
59fc4a089c chore(release): publish new version
- @standardnotes/analytics@2.17.5
2022-12-20 13:16:57 +00:00
Karol Sójko
ef26dc8cbb fix(analytics): accessing analytics in report 2022-12-20 14:13:54 +01:00
standardci
8a0fbb28b0 chore(release): publish new version
- @standardnotes/analytics@2.17.4
2022-12-20 12:48:03 +00:00
Karol Sójko
618d8d5b1a tmp(analytics): add console logs for html generation on the report 2022-12-20 13:44:22 +01:00
standardci
3a936dc9c1 chore(release): publish new version
- @standardnotes/analytics@2.17.3
2022-12-20 12:15:31 +00:00
Karol Sójko
031fcd75ee fix(analytics): add debug logs for the report 2022-12-20 13:13:14 +01:00
standardci
c8cd23cb32 chore(release): publish new version
- @standardnotes/analytics@2.17.2
2022-12-20 11:27:58 +00:00
Karol Sójko
a3049938a3 fix(analytics): calculating active users 2022-12-20 12:26:06 +01:00
standardci
b23488e862 chore(release): publish new version
- @standardnotes/workspace-server@1.19.3
2022-12-20 10:32:06 +00:00
Karol Sójko
c8203cf04c fix(workspace): specs 2022-12-20 11:30:09 +01:00
86 changed files with 1592 additions and 270 deletions

View File

@@ -190,9 +190,9 @@ jobs:
uses: convictional/trigger-workflow-and-wait@master
with:
owner: standardnotes
repo: e2e
repo: self-hosted
github_token: ${{ secrets.CI_PAT_TOKEN }}
workflow_file_name: testing-with-stable-client.yml
workflow_file_name: testing-with-updating-client-and-server.yml
wait_interval: 30
client_payload: '{"${{ inputs.e2e_tag_parameter_name }}": "${{ github.sha }}"}'
propagate_failure: true

336
.pnp.cjs generated
View File

@@ -126,7 +126,7 @@ const RAW_RUNTIME_STATE =
["@lerna-lite/cli", "npm:1.6.0"],\
["@lerna-lite/list", "npm:1.6.0"],\
["@lerna-lite/run", "npm:1.6.0"],\
["@sentry/node", "npm:7.27.0"],\
["@sentry/node", "npm:7.28.1"],\
["@types/jest", "npm:29.1.1"],\
["@types/newrelic", "npm:7.0.4"],\
["@types/node", "npm:18.11.9"],\
@@ -1968,6 +1968,15 @@ const RAW_RUNTIME_STATE =
"linkType": "HARD"\
}]\
]],\
["@noble/ed25519", [\
["npm:1.7.1", {\
"packageLocation": "./.yarn/cache/@noble-ed25519-npm-1.7.1-177d9beb01-b1aa4b9264.zip/node_modules/@noble/ed25519/",\
"packageDependencies": [\
["@noble/ed25519", "npm:1.7.1"]\
],\
"linkType": "HARD"\
}]\
]],\
["@nodelib/fs.scandir", [\
["npm:2.1.5", {\
"packageLocation": "./.yarn/cache/@nodelib-fs.scandir-npm-2.1.5-89c67370dd-5f309a3b37.zip/node_modules/@nodelib/fs.scandir/",\
@@ -2324,6 +2333,44 @@ const RAW_RUNTIME_STATE =
"linkType": "HARD"\
}]\
]],\
["@peculiar/asn1-android", [\
["npm:2.3.3", {\
"packageLocation": "./.yarn/cache/@peculiar-asn1-android-npm-2.3.3-28df67d7a3-0c7cad544e.zip/node_modules/@peculiar/asn1-android/",\
"packageDependencies": [\
["@peculiar/asn1-android", "npm:2.3.3"],\
["@peculiar/asn1-schema", "npm:2.3.3"],\
["asn1js", "npm:3.0.5"],\
["tslib", "npm:2.4.1"]\
],\
"linkType": "HARD"\
}]\
]],\
["@peculiar/asn1-schema", [\
["npm:2.3.3", {\
"packageLocation": "./.yarn/cache/@peculiar-asn1-schema-npm-2.3.3-7c2b9469c4-f584f79d5a.zip/node_modules/@peculiar/asn1-schema/",\
"packageDependencies": [\
["@peculiar/asn1-schema", "npm:2.3.3"],\
["asn1js", "npm:3.0.5"],\
["pvtsutils", "npm:1.3.2"],\
["tslib", "npm:2.4.1"]\
],\
"linkType": "HARD"\
}]\
]],\
["@peculiar/asn1-x509", [\
["npm:2.3.4", {\
"packageLocation": "./.yarn/cache/@peculiar-asn1-x509-npm-2.3.4-a579005836-10a8659980.zip/node_modules/@peculiar/asn1-x509/",\
"packageDependencies": [\
["@peculiar/asn1-x509", "npm:2.3.4"],\
["@peculiar/asn1-schema", "npm:2.3.3"],\
["asn1js", "npm:3.0.5"],\
["ipaddr.js", "npm:2.0.1"],\
["pvtsutils", "npm:1.3.2"],\
["tslib", "npm:2.4.1"]\
],\
"linkType": "HARD"\
}]\
]],\
["@pnpm/network.ca-file", [\
["npm:1.0.1", {\
"packageLocation": "./.yarn/cache/@pnpm-network.ca-file-npm-1.0.1-42bfe40bec-ed952a5574.zip/node_modules/@pnpm/network.ca-file/",\
@@ -2447,6 +2494,16 @@ const RAW_RUNTIME_STATE =
["tslib", "npm:1.14.1"]\
],\
"linkType": "HARD"\
}],\
["npm:7.28.1", {\
"packageLocation": "./.yarn/cache/@sentry-core-npm-7.28.1-a468033ea8-f29d747d3e.zip/node_modules/@sentry/core/",\
"packageDependencies": [\
["@sentry/core", "npm:7.28.1"],\
["@sentry/types", "npm:7.28.1"],\
["@sentry/utils", "npm:7.28.1"],\
["tslib", "npm:1.14.1"]\
],\
"linkType": "HARD"\
}]\
]],\
["@sentry/hub", [\
@@ -2476,6 +2533,20 @@ const RAW_RUNTIME_STATE =
["tslib", "npm:1.14.1"]\
],\
"linkType": "HARD"\
}],\
["npm:7.28.1", {\
"packageLocation": "./.yarn/cache/@sentry-node-npm-7.28.1-b0e124fdfc-b4922d1f0a.zip/node_modules/@sentry/node/",\
"packageDependencies": [\
["@sentry/node", "npm:7.28.1"],\
["@sentry/core", "npm:7.28.1"],\
["@sentry/types", "npm:7.28.1"],\
["@sentry/utils", "npm:7.28.1"],\
["cookie", "npm:0.4.2"],\
["https-proxy-agent", "npm:5.0.1"],\
["lru_map", "npm:0.3.3"],\
["tslib", "npm:1.14.1"]\
],\
"linkType": "HARD"\
}]\
]],\
["@sentry/profiling-node", [\
@@ -2506,6 +2577,17 @@ const RAW_RUNTIME_STATE =
["tslib", "npm:1.14.1"]\
],\
"linkType": "HARD"\
}],\
["npm:7.28.1", {\
"packageLocation": "./.yarn/cache/@sentry-tracing-npm-7.28.1-e15d453d8e-be501ca9d7.zip/node_modules/@sentry/tracing/",\
"packageDependencies": [\
["@sentry/tracing", "npm:7.28.1"],\
["@sentry/core", "npm:7.28.1"],\
["@sentry/types", "npm:7.28.1"],\
["@sentry/utils", "npm:7.28.1"],\
["tslib", "npm:1.14.1"]\
],\
"linkType": "HARD"\
}]\
]],\
["@sentry/types", [\
@@ -2515,6 +2597,13 @@ const RAW_RUNTIME_STATE =
["@sentry/types", "npm:7.27.0"]\
],\
"linkType": "HARD"\
}],\
["npm:7.28.1", {\
"packageLocation": "./.yarn/cache/@sentry-types-npm-7.28.1-42d9a8574c-7dc6639cb7.zip/node_modules/@sentry/types/",\
"packageDependencies": [\
["@sentry/types", "npm:7.28.1"]\
],\
"linkType": "HARD"\
}]\
]],\
["@sentry/utils", [\
@@ -2526,6 +2615,34 @@ const RAW_RUNTIME_STATE =
["tslib", "npm:1.14.1"]\
],\
"linkType": "HARD"\
}],\
["npm:7.28.1", {\
"packageLocation": "./.yarn/cache/@sentry-utils-npm-7.28.1-71eaeb767f-a4b5f73db0.zip/node_modules/@sentry/utils/",\
"packageDependencies": [\
["@sentry/utils", "npm:7.28.1"],\
["@sentry/types", "npm:7.28.1"],\
["tslib", "npm:1.14.1"]\
],\
"linkType": "HARD"\
}]\
]],\
["@simplewebauthn/server", [\
["npm:6.2.2", {\
"packageLocation": "./.yarn/cache/@simplewebauthn-server-npm-6.2.2-ca870b05c2-5ffb9b1c15.zip/node_modules/@simplewebauthn/server/",\
"packageDependencies": [\
["@simplewebauthn/server", "npm:6.2.2"],\
["@noble/ed25519", "npm:1.7.1"],\
["@peculiar/asn1-android", "npm:2.3.3"],\
["@peculiar/asn1-schema", "npm:2.3.3"],\
["@peculiar/asn1-x509", "npm:2.3.4"],\
["base64url", "npm:3.0.1"],\
["cbor", "npm:5.2.0"],\
["debug", "virtual:b86a9fb34323a98c6519528ed55faa0d9b44ca8879307c0b29aa384bde47ff59a7d0c9051b31246f14521dfb71ba3c5d6d0b35c29fffc17bf875aa6ad977d9e8#npm:4.3.4"],\
["jsrsasign", "npm:10.6.1"],\
["jwk-to-pem", "npm:2.0.5"],\
["node-fetch", "virtual:25a5f5382d53dbf298bf7a1191760bc2e0a523a619eeb0e667b99a8649e8ad183f9e2e0b45f6fb831b92f4078b61622aa567cf79565f6aa5af9597e3c84864f6#npm:2.6.7"]\
],\
"linkType": "HARD"\
}]\
]],\
["@sinclair/typebox", [\
@@ -2581,7 +2698,7 @@ const RAW_RUNTIME_STATE =
"packageDependencies": [\
["@standardnotes/analytics", "workspace:packages/analytics"],\
["@newrelic/winston-enricher", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:4.0.0"],\
["@sentry/node", "npm:7.27.0"],\
["@sentry/node", "npm:7.28.1"],\
["@standardnotes/common", "workspace:packages/common"],\
["@standardnotes/domain-core", "workspace:packages/domain-core"],\
["@standardnotes/domain-events", "workspace:packages/domain-events"],\
@@ -2633,7 +2750,7 @@ const RAW_RUNTIME_STATE =
"packageDependencies": [\
["@standardnotes/api-gateway", "workspace:packages/api-gateway"],\
["@newrelic/winston-enricher", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:4.0.0"],\
["@sentry/node", "npm:7.27.0"],\
["@sentry/node", "npm:7.28.1"],\
["@standardnotes/common", "workspace:packages/common"],\
["@standardnotes/domain-events", "workspace:packages/domain-events"],\
["@standardnotes/domain-events-infra", "workspace:packages/domain-events-infra"],\
@@ -2689,9 +2806,10 @@ const RAW_RUNTIME_STATE =
"packageDependencies": [\
["@standardnotes/auth-server", "workspace:packages/auth"],\
["@newrelic/winston-enricher", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:4.0.0"],\
["@sentry/node", "npm:7.27.0"],\
["@sentry/node", "npm:7.28.1"],\
["@sentry/profiling-node", "npm:0.0.12"],\
["@sentry/tracing", "npm:7.27.0"],\
["@sentry/tracing", "npm:7.28.1"],\
["@simplewebauthn/server", "npm:6.2.2"],\
["@standardnotes/api", "npm:1.19.0"],\
["@standardnotes/common", "workspace:packages/common"],\
["@standardnotes/domain-core", "workspace:packages/domain-core"],\
@@ -2915,7 +3033,7 @@ const RAW_RUNTIME_STATE =
"packageLocation": "./packages/files/",\
"packageDependencies": [\
["@standardnotes/files-server", "workspace:packages/files"],\
["@sentry/node", "npm:7.27.0"],\
["@sentry/node", "npm:7.28.1"],\
["@standardnotes/common", "workspace:packages/common"],\
["@standardnotes/config", "npm:2.4.3"],\
["@standardnotes/domain-events", "workspace:packages/domain-events"],\
@@ -3050,7 +3168,7 @@ const RAW_RUNTIME_STATE =
"packageDependencies": [\
["@standardnotes/revisions-server", "workspace:packages/revisions"],\
["@newrelic/winston-enricher", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:4.0.0"],\
["@sentry/node", "npm:7.27.0"],\
["@sentry/node", "npm:7.28.1"],\
["@standardnotes/api", "npm:1.19.0"],\
["@standardnotes/common", "workspace:packages/common"],\
["@standardnotes/domain-core", "workspace:packages/domain-core"],\
@@ -3095,7 +3213,7 @@ const RAW_RUNTIME_STATE =
"packageDependencies": [\
["@standardnotes/scheduler-server", "workspace:packages/scheduler"],\
["@newrelic/winston-enricher", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:4.0.0"],\
["@sentry/node", "npm:7.27.0"],\
["@sentry/node", "npm:7.28.1"],\
["@standardnotes/common", "workspace:packages/common"],\
["@standardnotes/domain-core", "workspace:packages/domain-core"],\
["@standardnotes/domain-events", "workspace:packages/domain-events"],\
@@ -3156,7 +3274,7 @@ const RAW_RUNTIME_STATE =
["@lerna-lite/cli", "npm:1.6.0"],\
["@lerna-lite/list", "npm:1.6.0"],\
["@lerna-lite/run", "npm:1.6.0"],\
["@sentry/node", "npm:7.27.0"],\
["@sentry/node", "npm:7.28.1"],\
["@types/jest", "npm:29.1.1"],\
["@types/newrelic", "npm:7.0.4"],\
["@types/node", "npm:18.11.9"],\
@@ -3222,9 +3340,9 @@ const RAW_RUNTIME_STATE =
"packageDependencies": [\
["@standardnotes/syncing-server", "workspace:packages/syncing-server"],\
["@newrelic/winston-enricher", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:4.0.0"],\
["@sentry/node", "npm:7.27.0"],\
["@sentry/node", "npm:7.28.1"],\
["@sentry/profiling-node", "npm:0.0.12"],\
["@sentry/tracing", "npm:7.27.0"],\
["@sentry/tracing", "npm:7.28.1"],\
["@standardnotes/common", "workspace:packages/common"],\
["@standardnotes/domain-core", "workspace:packages/domain-core"],\
["@standardnotes/domain-events", "workspace:packages/domain-events"],\
@@ -3324,7 +3442,7 @@ const RAW_RUNTIME_STATE =
"packageDependencies": [\
["@standardnotes/websockets-server", "workspace:packages/websockets"],\
["@newrelic/winston-enricher", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:4.0.0"],\
["@sentry/node", "npm:7.27.0"],\
["@sentry/node", "npm:7.28.1"],\
["@standardnotes/api", "npm:1.19.0"],\
["@standardnotes/common", "workspace:packages/common"],\
["@standardnotes/domain-events", "workspace:packages/domain-events"],\
@@ -3364,7 +3482,7 @@ const RAW_RUNTIME_STATE =
"packageDependencies": [\
["@standardnotes/workspace-server", "workspace:packages/workspace"],\
["@newrelic/winston-enricher", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:4.0.0"],\
["@sentry/node", "npm:7.27.0"],\
["@sentry/node", "npm:7.28.1"],\
["@standardnotes/api", "npm:1.19.0"],\
["@standardnotes/common", "workspace:packages/common"],\
["@standardnotes/domain-core", "workspace:packages/domain-core"],\
@@ -4818,6 +4936,31 @@ const RAW_RUNTIME_STATE =
"linkType": "HARD"\
}]\
]],\
["asn1.js", [\
["npm:5.4.1", {\
"packageLocation": "./.yarn/cache/asn1.js-npm-5.4.1-37c7edbcb0-5c36f81388.zip/node_modules/asn1.js/",\
"packageDependencies": [\
["asn1.js", "npm:5.4.1"],\
["bn.js", "npm:4.12.0"],\
["inherits", "npm:2.0.4"],\
["minimalistic-assert", "npm:1.0.1"],\
["safer-buffer", "npm:2.1.2"]\
],\
"linkType": "HARD"\
}]\
]],\
["asn1js", [\
["npm:3.0.5", {\
"packageLocation": "./.yarn/cache/asn1js-npm-3.0.5-cf5558af33-d0bc57da97.zip/node_modules/asn1js/",\
"packageDependencies": [\
["asn1js", "npm:3.0.5"],\
["pvtsutils", "npm:1.3.2"],\
["pvutils", "npm:1.1.3"],\
["tslib", "npm:2.4.1"]\
],\
"linkType": "HARD"\
}]\
]],\
["async", [\
["npm:3.2.4", {\
"packageLocation": "./.yarn/cache/async-npm-3.2.4-aba13508f9-9719e38d24.zip/node_modules/async/",\
@@ -5031,6 +5174,15 @@ const RAW_RUNTIME_STATE =
"linkType": "HARD"\
}]\
]],\
["base64url", [\
["npm:3.0.1", {\
"packageLocation": "./.yarn/cache/base64url-npm-3.0.1-4c171c4917-72e1401ffe.zip/node_modules/base64url/",\
"packageDependencies": [\
["base64url", "npm:3.0.1"]\
],\
"linkType": "HARD"\
}]\
]],\
["bcryptjs", [\
["npm:2.4.3", {\
"packageLocation": "./.yarn/cache/bcryptjs-npm-2.4.3-32de4957eb-bf6a43e9c4.zip/node_modules/bcryptjs/",\
@@ -5049,6 +5201,15 @@ const RAW_RUNTIME_STATE =
"linkType": "HARD"\
}]\
]],\
["bignumber.js", [\
["npm:9.1.1", {\
"packageLocation": "./.yarn/cache/bignumber.js-npm-9.1.1-5929e8d8dc-e44d008049.zip/node_modules/bignumber.js/",\
"packageDependencies": [\
["bignumber.js", "npm:9.1.1"]\
],\
"linkType": "HARD"\
}]\
]],\
["binary-extensions", [\
["npm:2.2.0", {\
"packageLocation": "./.yarn/cache/binary-extensions-npm-2.2.0-180c33fec7-16cf7c0cfd.zip/node_modules/binary-extensions/",\
@@ -5070,6 +5231,15 @@ const RAW_RUNTIME_STATE =
"linkType": "HARD"\
}]\
]],\
["bn.js", [\
["npm:4.12.0", {\
"packageLocation": "./.yarn/cache/bn.js-npm-4.12.0-3ec6c884f6-bfb4590775.zip/node_modules/bn.js/",\
"packageDependencies": [\
["bn.js", "npm:4.12.0"]\
],\
"linkType": "HARD"\
}]\
]],\
["body-parser", [\
["npm:1.20.1", {\
"packageLocation": "./.yarn/cache/body-parser-npm-1.20.1-759fd14db9-33f202c9d5.zip/node_modules/body-parser/",\
@@ -5137,6 +5307,15 @@ const RAW_RUNTIME_STATE =
"linkType": "HARD"\
}]\
]],\
["brorand", [\
["npm:1.1.0", {\
"packageLocation": "./.yarn/cache/brorand-npm-1.1.0-ea86634c4b-f736e127fb.zip/node_modules/brorand/",\
"packageDependencies": [\
["brorand", "npm:1.1.0"]\
],\
"linkType": "HARD"\
}]\
]],\
["browserslist", [\
["npm:4.21.1", {\
"packageLocation": "./.yarn/cache/browserslist-npm-4.21.1-930e90b93a-617d624493.zip/node_modules/browserslist/",\
@@ -5372,6 +5551,17 @@ const RAW_RUNTIME_STATE =
"linkType": "HARD"\
}]\
]],\
["cbor", [\
["npm:5.2.0", {\
"packageLocation": "./.yarn/cache/cbor-npm-5.2.0-4f6440587f-d60986b9d0.zip/node_modules/cbor/",\
"packageDependencies": [\
["cbor", "npm:5.2.0"],\
["bignumber.js", "npm:9.1.1"],\
["nofilter", "npm:1.0.4"]\
],\
"linkType": "HARD"\
}]\
]],\
["chalk", [\
["npm:2.4.2", {\
"packageLocation": "./.yarn/cache/chalk-npm-2.4.2-3ea16dd91e-befd2fe888.zip/node_modules/chalk/",\
@@ -6496,6 +6686,22 @@ const RAW_RUNTIME_STATE =
"linkType": "HARD"\
}]\
]],\
["elliptic", [\
["npm:6.5.4", {\
"packageLocation": "./.yarn/cache/elliptic-npm-6.5.4-0ca8204a86-4453b008cf.zip/node_modules/elliptic/",\
"packageDependencies": [\
["elliptic", "npm:6.5.4"],\
["bn.js", "npm:4.12.0"],\
["brorand", "npm:1.1.0"],\
["hash.js", "npm:1.1.7"],\
["hmac-drbg", "npm:1.0.1"],\
["inherits", "npm:2.0.4"],\
["minimalistic-assert", "npm:1.0.1"],\
["minimalistic-crypto-utils", "npm:1.0.1"]\
],\
"linkType": "HARD"\
}]\
]],\
["emittery", [\
["npm:0.10.2", {\
"packageLocation": "./.yarn/cache/emittery-npm-0.10.2-aac10498b5-c55b286714.zip/node_modules/emittery/",\
@@ -8002,6 +8208,17 @@ const RAW_RUNTIME_STATE =
"linkType": "HARD"\
}]\
]],\
["hash.js", [\
["npm:1.1.7", {\
"packageLocation": "./.yarn/cache/hash.js-npm-1.1.7-f1ad187358-e4266370d1.zip/node_modules/hash.js/",\
"packageDependencies": [\
["hash.js", "npm:1.1.7"],\
["inherits", "npm:2.0.4"],\
["minimalistic-assert", "npm:1.0.1"]\
],\
"linkType": "HARD"\
}]\
]],\
["helmet", [\
["npm:6.0.0", {\
"packageLocation": "./.yarn/cache/helmet-npm-6.0.0-2285459f57-73b6ba802d.zip/node_modules/helmet/",\
@@ -8020,6 +8237,18 @@ const RAW_RUNTIME_STATE =
"linkType": "HARD"\
}]\
]],\
["hmac-drbg", [\
["npm:1.0.1", {\
"packageLocation": "./.yarn/cache/hmac-drbg-npm-1.0.1-3499ad31cd-4e88d58ffc.zip/node_modules/hmac-drbg/",\
"packageDependencies": [\
["hmac-drbg", "npm:1.0.1"],\
["hash.js", "npm:1.1.7"],\
["minimalistic-assert", "npm:1.0.1"],\
["minimalistic-crypto-utils", "npm:1.0.1"]\
],\
"linkType": "HARD"\
}]\
]],\
["hosted-git-info", [\
["npm:2.8.9", {\
"packageLocation": "./.yarn/cache/hosted-git-info-npm-2.8.9-62c44fa93f-c24da52f98.zip/node_modules/hosted-git-info/",\
@@ -8400,6 +8629,13 @@ const RAW_RUNTIME_STATE =
["ipaddr.js", "npm:1.9.1"]\
],\
"linkType": "HARD"\
}],\
["npm:2.0.1", {\
"packageLocation": "./.yarn/cache/ipaddr.js-npm-2.0.1-04e97280d7-04ce6c896c.zip/node_modules/ipaddr.js/",\
"packageDependencies": [\
["ipaddr.js", "npm:2.0.1"]\
],\
"linkType": "HARD"\
}]\
]],\
["is-arguments", [\
@@ -9602,6 +9838,15 @@ const RAW_RUNTIME_STATE =
"linkType": "HARD"\
}]\
]],\
["jsrsasign", [\
["npm:10.6.1", {\
"packageLocation": "./.yarn/cache/jsrsasign-npm-10.6.1-a8fa295369-e8e9c1b24f.zip/node_modules/jsrsasign/",\
"packageDependencies": [\
["jsrsasign", "npm:10.6.1"]\
],\
"linkType": "HARD"\
}]\
]],\
["jwa", [\
["npm:1.4.1", {\
"packageLocation": "./.yarn/cache/jwa-npm-1.4.1-4f19d6572c-0cc3e68b68.zip/node_modules/jwa/",\
@@ -9614,6 +9859,18 @@ const RAW_RUNTIME_STATE =
"linkType": "HARD"\
}]\
]],\
["jwk-to-pem", [\
["npm:2.0.5", {\
"packageLocation": "./.yarn/cache/jwk-to-pem-npm-2.0.5-aff7d9f125-fced3a75b0.zip/node_modules/jwk-to-pem/",\
"packageDependencies": [\
["jwk-to-pem", "npm:2.0.5"],\
["asn1.js", "npm:5.4.1"],\
["elliptic", "npm:6.5.4"],\
["safe-buffer", "npm:5.2.1"]\
],\
"linkType": "HARD"\
}]\
]],\
["jws", [\
["npm:3.2.2", {\
"packageLocation": "./.yarn/cache/jws-npm-3.2.2-c1ae59c7af-347ed7c334.zip/node_modules/jws/",\
@@ -10227,6 +10484,24 @@ const RAW_RUNTIME_STATE =
"linkType": "HARD"\
}]\
]],\
["minimalistic-assert", [\
["npm:1.0.1", {\
"packageLocation": "./.yarn/cache/minimalistic-assert-npm-1.0.1-dc8bb23d29-e2310081d8.zip/node_modules/minimalistic-assert/",\
"packageDependencies": [\
["minimalistic-assert", "npm:1.0.1"]\
],\
"linkType": "HARD"\
}]\
]],\
["minimalistic-crypto-utils", [\
["npm:1.0.1", {\
"packageLocation": "./.yarn/cache/minimalistic-crypto-utils-npm-1.0.1-e66b10822e-7d909decd2.zip/node_modules/minimalistic-crypto-utils/",\
"packageDependencies": [\
["minimalistic-crypto-utils", "npm:1.0.1"]\
],\
"linkType": "HARD"\
}]\
]],\
["minimatch", [\
["npm:3.1.2", {\
"packageLocation": "./.yarn/cache/minimatch-npm-3.1.2-9405269906-97f5615ee8.zip/node_modules/minimatch/",\
@@ -10646,6 +10921,15 @@ const RAW_RUNTIME_STATE =
"linkType": "HARD"\
}]\
]],\
["nofilter", [\
["npm:1.0.4", {\
"packageLocation": "./.yarn/cache/nofilter-npm-1.0.4-1cbdc6c03a-9a26874e7d.zip/node_modules/nofilter/",\
"packageDependencies": [\
["nofilter", "npm:1.0.4"]\
],\
"linkType": "HARD"\
}]\
]],\
["nopt", [\
["npm:1.0.10", {\
"packageLocation": "./.yarn/cache/nopt-npm-1.0.10-f3db192976-efa5a9c2c1.zip/node_modules/nopt/",\
@@ -11702,6 +11986,25 @@ const RAW_RUNTIME_STATE =
"linkType": "HARD"\
}]\
]],\
["pvtsutils", [\
["npm:1.3.2", {\
"packageLocation": "./.yarn/cache/pvtsutils-npm-1.3.2-e1483da905-eb22d3df60.zip/node_modules/pvtsutils/",\
"packageDependencies": [\
["pvtsutils", "npm:1.3.2"],\
["tslib", "npm:2.4.1"]\
],\
"linkType": "HARD"\
}]\
]],\
["pvutils", [\
["npm:1.1.3", {\
"packageLocation": "./.yarn/cache/pvutils-npm-1.1.3-da8b07d6cf-0cb4f4878f.zip/node_modules/pvutils/",\
"packageDependencies": [\
["pvutils", "npm:1.1.3"]\
],\
"linkType": "HARD"\
}]\
]],\
["q", [\
["npm:1.5.1", {\
"packageLocation": "./.yarn/cache/q-npm-1.5.1-a28b3cfeaf-276b7e93fc.zip/node_modules/q/",\
@@ -13386,6 +13689,13 @@ const RAW_RUNTIME_STATE =
["tslib", "npm:2.4.0"]\
],\
"linkType": "HARD"\
}],\
["npm:2.4.1", {\
"packageLocation": "./.yarn/cache/tslib-npm-2.4.1-36f0ed04db-a739a21e3f.zip/node_modules/tslib/",\
"packageDependencies": [\
["tslib", "npm:2.4.1"]\
],\
"linkType": "HARD"\
}]\
]],\
["tsutils", [\

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -61,7 +61,7 @@
},
"packageManager": "yarn@4.0.0-rc.25",
"dependencies": {
"@sentry/node": "^7.27.0",
"@sentry/node": "^7.28.1",
"newrelic": "^9.6.0"
}
}

View File

@@ -3,6 +3,44 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [2.17.8](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.17.7...@standardnotes/analytics@2.17.8) (2022-12-28)
**Note:** Version bump only for package @standardnotes/analytics
## [2.17.7](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.17.6...@standardnotes/analytics@2.17.7) (2022-12-20)
### Bug Fixes
* **analytics:** monthly numbers of active users ([b34bbca](https://github.com/standardnotes/server/commit/b34bbcac8b9604283b3a5959ab3218c468ce8a00))
## [2.17.6](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.17.5...@standardnotes/analytics@2.17.6) (2022-12-20)
### Bug Fixes
* **analytics:** filtered counts for user activity check ([17b2ea1](https://github.com/standardnotes/server/commit/17b2ea126c5ad2d7cf07657def63f9977f239a3c))
## [2.17.5](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.17.4...@standardnotes/analytics@2.17.5) (2022-12-20)
### Bug Fixes
* **analytics:** accessing analytics in report ([ef26dc8](https://github.com/standardnotes/server/commit/ef26dc8cbb967e088ae7387ff6dbec1e60dc3ee4))
## [2.17.4](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.17.3...@standardnotes/analytics@2.17.4) (2022-12-20)
**Note:** Version bump only for package @standardnotes/analytics
## [2.17.3](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.17.2...@standardnotes/analytics@2.17.3) (2022-12-20)
### Bug Fixes
* **analytics:** add debug logs for the report ([031fcd7](https://github.com/standardnotes/server/commit/031fcd75eecdcf4c2f17257754a0ba3f24ba6d6e))
## [2.17.2](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.17.1...@standardnotes/analytics@2.17.2) (2022-12-20)
### Bug Fixes
* **analytics:** calculating active users ([a304993](https://github.com/standardnotes/server/commit/a3049938a31e21a5867a314ac62bee6aa4990d57))
## [2.17.1](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.17.0...@standardnotes/analytics@2.17.1) (2022-12-20)
### Bug Fixes

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/analytics",
"version": "2.17.1",
"version": "2.17.8",
"engines": {
"node": ">=18.0.0 <19.0.0"
},
@@ -38,7 +38,7 @@
},
"dependencies": {
"@newrelic/winston-enricher": "^4.0.0",
"@sentry/node": "^7.27.0",
"@sentry/node": "^7.28.1",
"@standardnotes/common": "workspace:*",
"@standardnotes/domain-core": "workspace:^",
"@standardnotes/domain-events": "workspace:*",

View File

@@ -6,21 +6,30 @@ import { StatisticMeasureName } from '../Statistics/StatisticMeasureName'
import { Period } from '../Time/Period'
const countActiveUsers = (measureName: string, data: any): { yesterday: number; last30Days: number } => {
const totalActiveUsersLast30DaysIncludingToday = data.statisticMeasures.find(
const totalActiveUsersLast30DaysIncludingToday = data.statisticsOverTime.find(
(a: { name: string; period: number }) => a.name === measureName && a.period === 27,
)
const totalActiveUsersYesterday =
totalActiveUsersLast30DaysIncludingToday.counts[totalActiveUsersLast30DaysIncludingToday.counts.length - 2]
.totalCount
const filteredStats = totalActiveUsersLast30DaysIncludingToday.counts.filter(
const filteredCounts = totalActiveUsersLast30DaysIncludingToday.counts.filter(
(count: { totalCount: number }) => count.totalCount !== 0,
)
const averageActiveUsersLast30Days = Math.floor(
filteredStats.counts.reduce((previousValue: { totalCount: any }, currentValue: { totalCount: any }) => {
return previousValue.totalCount + currentValue.totalCount
}) / filteredStats.counts.length,
)
if (filteredCounts.length === 0) {
return {
yesterday: 0,
last30Days: 0,
}
}
const last30DaysNumbers = filteredCounts.map((count: { totalCount: number }) => count.totalCount)
const last30DaysCount = last30DaysNumbers.reduce((previousValue: number, currentValue: number) => {
return previousValue + currentValue
})
const averageActiveUsersLast30Days = Math.floor(last30DaysCount / last30DaysNumbers.length)
return {
yesterday: totalActiveUsersYesterday,

View File

@@ -3,6 +3,10 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.41.3](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.41.2...@standardnotes/api-gateway@1.41.3) (2022-12-28)
**Note:** Version bump only for package @standardnotes/api-gateway
## [1.41.2](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.41.1...@standardnotes/api-gateway@1.41.2) (2022-12-20)
**Note:** Version bump only for package @standardnotes/api-gateway

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/api-gateway",
"version": "1.41.2",
"version": "1.41.3",
"engines": {
"node": ">=18.0.0 <19.0.0"
},
@@ -21,7 +21,7 @@
},
"dependencies": {
"@newrelic/winston-enricher": "^4.0.0",
"@sentry/node": "^7.27.0",
"@sentry/node": "^7.28.1",
"@standardnotes/common": "workspace:^",
"@standardnotes/domain-events": "workspace:*",
"@standardnotes/domain-events-infra": "workspace:*",

View File

@@ -13,8 +13,8 @@ ENCRYPTION_SERVER_KEY=change-me-!
PORT=3000
DB_HOST=localhost
DB_REPLICA_HOST=localhost
DB_HOST=127.0.0.1
DB_REPLICA_HOST=127.0.0.1
DB_PORT=3306
DB_USERNAME=auth
DB_PASSWORD=changeme123

View File

@@ -3,6 +3,58 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [1.73.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.72.0...@standardnotes/auth-server@1.73.0) (2022-12-28)
### Features
* **auth:** add generating authencator registration options ([51ad06b](https://github.com/standardnotes/server/commit/51ad06b303d7dc994920818872fdf8bd37fc445c))
# [1.72.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.71.1...@standardnotes/auth-server@1.72.0) (2022-12-28)
### Features
* **auth:** add authenticator challenges model ([fa9bf0b](https://github.com/standardnotes/server/commit/fa9bf0b448acb3f19ab44c4b431ce367dab37b76))
## [1.71.1](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.71.0...@standardnotes/auth-server@1.71.1) (2022-12-28)
### Bug Fixes
* **auth:** credential id field type ([98e3d18](https://github.com/standardnotes/server/commit/98e3d1833530dcd9e3e34a4c4a6b14a2a01afea1))
# [1.71.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.70.9...@standardnotes/auth-server@1.71.0) (2022-12-28)
### Features
* **auth:** add authenticators model ([1e69a13](https://github.com/standardnotes/server/commit/1e69a13a97c4d9022aa96397cce1b349d3cede89))
## [1.70.9](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.70.8...@standardnotes/auth-server@1.70.9) (2022-12-28)
**Note:** Version bump only for package @standardnotes/auth-server
## [1.70.8](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.70.7...@standardnotes/auth-server@1.70.8) (2022-12-20)
### Bug Fixes
* **auth:** move tracing sessions to session creation instead of cross service token creation ([5255cfb](https://github.com/standardnotes/server/commit/5255cfbb257cc9e6ac437fe0c5b28d938e3e599b))
## [1.70.7](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.70.6...@standardnotes/auth-server@1.70.7) (2022-12-20)
### Bug Fixes
* **auth:** change severity on tracing session errors - most probably hazardous reads ([cf0b918](https://github.com/standardnotes/server/commit/cf0b91891370e1c1799ad80c10ee9f6b98087a94))
## [1.70.6](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.70.5...@standardnotes/auth-server@1.70.6) (2022-12-20)
### Bug Fixes
* **auth:** query for session traces ([14eb775](https://github.com/standardnotes/server/commit/14eb775749bfa9972dc3c07049505f3d15f0b556))
## [1.70.5](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.70.4...@standardnotes/auth-server@1.70.5) (2022-12-20)
### Bug Fixes
* **auth:** add session traces index ([b9e1e47](https://github.com/standardnotes/server/commit/b9e1e4787129f00fab8f98cb721141f2e7d75600))
## [1.70.4](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.70.3...@standardnotes/auth-server@1.70.4) (2022-12-20)
### Bug Fixes

View File

@@ -0,0 +1,15 @@
import { MigrationInterface, QueryRunner } from 'typeorm'
export class addSessionTracesCompoundIndex1671561748264 implements MigrationInterface {
name = 'addSessionTracesCompoundIndex1671561748264'
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
'CREATE UNIQUE INDEX `user_uuid_and_creation_date` ON `session_traces` (`user_uuid`, `creation_date`)',
)
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query('DROP INDEX `user_uuid_and_creation_date` ON `session_traces`')
}
}

View File

@@ -0,0 +1,16 @@
import { MigrationInterface, QueryRunner } from 'typeorm'
export class addAuthenticators1672223738686 implements MigrationInterface {
name = 'addAuthenticators1672223738686'
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
'CREATE TABLE `authenticators` (`uuid` varchar(36) NOT NULL, `user_uuid` varchar(36) NOT NULL, `credential_id` varbinary(1024) NOT NULL, `credential_public_key` blob NOT NULL, `counter` bigint NOT NULL, `credential_device_type` varchar(32) NOT NULL, `credential_backed_up` tinyint NOT NULL, `transports` varchar(255) NULL, `created_at` bigint NOT NULL, `updated_at` bigint NOT NULL, UNIQUE INDEX `credential_id` (`credential_id`), PRIMARY KEY (`uuid`)) ENGINE=InnoDB',
)
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query('DROP INDEX `credential_id` ON `authenticators`')
await queryRunner.query('DROP TABLE `authenticators`')
}
}

View File

@@ -0,0 +1,16 @@
import { MigrationInterface, QueryRunner } from 'typeorm'
export class addAuthenticatorChallenges1672227471677 implements MigrationInterface {
name = 'addAuthenticatorChallenges1672227471677'
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
'CREATE TABLE `authenticator_challenges` (`uuid` varchar(36) NOT NULL, `user_uuid` varchar(36) NOT NULL, `challenge` varchar(255) NOT NULL, `created_at` bigint NOT NULL, INDEX `user_uuid_and_challenge` (`user_uuid`, `challenge`), PRIMARY KEY (`uuid`)) ENGINE=InnoDB',
)
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query('DROP INDEX `user_uuid_and_challenge` ON `authenticator_challenges`')
await queryRunner.query('DROP TABLE `authenticator_challenges`')
}
}

View File

@@ -0,0 +1,23 @@
import { MigrationInterface, QueryRunner } from 'typeorm'
export class fixAuthenticatorDataTypes1672232035280 implements MigrationInterface {
name = 'fixAuthenticatorDataTypes1672232035280'
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query('ALTER TABLE `authenticators` DROP COLUMN `created_at`')
await queryRunner.query('ALTER TABLE `authenticators` ADD `created_at` datetime NOT NULL')
await queryRunner.query('ALTER TABLE `authenticators` DROP COLUMN `updated_at`')
await queryRunner.query('ALTER TABLE `authenticators` ADD `updated_at` datetime NOT NULL')
await queryRunner.query('ALTER TABLE `authenticator_challenges` DROP COLUMN `created_at`')
await queryRunner.query('ALTER TABLE `authenticator_challenges` ADD `created_at` datetime NOT NULL')
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query('ALTER TABLE `authenticator_challenges` DROP COLUMN `created_at`')
await queryRunner.query('ALTER TABLE `authenticator_challenges` ADD `created_at` bigint NOT NULL')
await queryRunner.query('ALTER TABLE `authenticators` DROP COLUMN `updated_at`')
await queryRunner.query('ALTER TABLE `authenticators` ADD `updated_at` bigint NOT NULL')
await queryRunner.query('ALTER TABLE `authenticators` DROP COLUMN `created_at`')
await queryRunner.query('ALTER TABLE `authenticators` ADD `created_at` bigint NOT NULL')
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/auth-server",
"version": "1.70.4",
"version": "1.73.0",
"engines": {
"node": ">=18.0.0 <19.0.0"
},
@@ -33,9 +33,10 @@
},
"dependencies": {
"@newrelic/winston-enricher": "^4.0.0",
"@sentry/node": "^7.27.0",
"@sentry/node": "^7.28.1",
"@sentry/profiling-node": "^0.0.12",
"@sentry/tracing": "^7.27.0",
"@sentry/tracing": "^7.28.1",
"@simplewebauthn/server": "^6.2.2",
"@standardnotes/api": "^1.19.0",
"@standardnotes/common": "workspace:*",
"@standardnotes/domain-core": "workspace:^",

View File

@@ -203,6 +203,17 @@ import { TypeORMSessionTrace } from '../Infra/TypeORM/TypeORMSessionTrace'
import { TraceSession } from '../Domain/UseCase/TraceSession/TraceSession'
import { CleanupSessionTraces } from '../Domain/UseCase/CleanupSessionTraces/CleanupSessionTraces'
import { PersistStatistics } from '../Domain/UseCase/PersistStatistics/PersistStatistics'
import { TypeORMAuthenticator } from '../Infra/TypeORM/TypeORMAuthenticator'
import { Authenticator } from '../Domain/Authenticator/Authenticator'
import { AuthenticatorPersistenceMapper } from '../Mapping/AuthenticatorPersistenceMapper'
import { AuthenticatorChallenge } from '../Domain/Authenticator/AuthenticatorChallenge'
import { TypeORMAuthenticatorChallenge } from '../Infra/TypeORM/TypeORMAuthenticatorChallenge'
import { AuthenticatorChallengePersistenceMapper } from '../Mapping/AuthenticatorChallengePersistenceMapper'
import { AuthenticatorRepositoryInterface } from '../Domain/Authenticator/AuthenticatorRepositoryInterface'
import { MySQLAuthenticatorRepository } from '../Infra/MySQL/MySQLAuthenticatorRepository'
import { AuthenticatorChallengeRepositoryInterface } from '../Domain/Authenticator/AuthenticatorChallengeRepositoryInterface'
import { MySQLAuthenticatorChallengeRepository } from '../Infra/MySQL/MySQLAuthenticatorChallengeRepository'
import { GenerateAuthenticatorRegistrationOptions } from '../Domain/UseCase/GenerateAuthenticatorRegistrationOptions/GenerateAuthenticatorRegistrationOptions'
// eslint-disable-next-line @typescript-eslint/no-var-requires
const newrelicFormatter = require('@newrelic/winston-enricher')
@@ -280,6 +291,14 @@ export class ContainerConfigLoader {
container
.bind<MapperInterface<SessionTrace, TypeORMSessionTrace>>(TYPES.SessionTracePersistenceMapper)
.toConstantValue(new SessionTracePersistenceMapper())
container
.bind<MapperInterface<Authenticator, TypeORMAuthenticator>>(TYPES.AuthenticatorPersistenceMapper)
.toConstantValue(new AuthenticatorPersistenceMapper())
container
.bind<MapperInterface<AuthenticatorChallenge, TypeORMAuthenticatorChallenge>>(
TYPES.AuthenticatorChallengePersistenceMapper,
)
.toConstantValue(new AuthenticatorChallengePersistenceMapper())
// Controller
container.bind<AuthController>(TYPES.AuthController).to(AuthController)
@@ -316,6 +335,12 @@ export class ContainerConfigLoader {
container
.bind<Repository<TypeORMSessionTrace>>(TYPES.ORMSessionTraceRepository)
.toConstantValue(AppDataSource.getRepository(TypeORMSessionTrace))
container
.bind<Repository<TypeORMAuthenticator>>(TYPES.ORMAuthenticatorRepository)
.toConstantValue(AppDataSource.getRepository(TypeORMAuthenticator))
container
.bind<Repository<TypeORMAuthenticatorChallenge>>(TYPES.ORMAuthenticatorChallengeRepository)
.toConstantValue(AppDataSource.getRepository(TypeORMAuthenticatorChallenge))
// Repositories
container.bind<SessionRepositoryInterface>(TYPES.SessionRepository).to(MySQLSessionRepository)
@@ -355,6 +380,22 @@ export class ContainerConfigLoader {
container.get(TYPES.SessionTracePersistenceMapper),
),
)
container
.bind<AuthenticatorRepositoryInterface>(TYPES.AuthenticatorRepository)
.toConstantValue(
new MySQLAuthenticatorRepository(
container.get(TYPES.ORMAuthenticatorRepository),
container.get(TYPES.AuthenticatorPersistenceMapper),
),
)
container
.bind<AuthenticatorChallengeRepositoryInterface>(TYPES.AuthenticatorChallengeRepository)
.toConstantValue(
new MySQLAuthenticatorChallengeRepository(
container.get(TYPES.ORMAuthenticatorChallengeRepository),
container.get(TYPES.AuthenticatorChallengePersistenceMapper),
),
)
// Middleware
container.bind<AuthMiddleware>(TYPES.AuthMiddleware).to(AuthMiddleware)
@@ -511,6 +552,14 @@ export class ContainerConfigLoader {
container.get(TYPES.Timer),
),
)
container
.bind<GenerateAuthenticatorRegistrationOptions>(TYPES.GenerateAuthenticatorRegistrationOptions)
.toConstantValue(
new GenerateAuthenticatorRegistrationOptions(
container.get(TYPES.AuthenticatorRepository),
container.get(TYPES.AuthenticatorChallengeRepository),
),
)
container
.bind<CleanupSessionTraces>(TYPES.CleanupSessionTraces)

View File

@@ -10,6 +10,8 @@ import { SharedSubscriptionInvitation } from '../Domain/SharedSubscription/Share
import { OfflineUserSubscription } from '../Domain/Subscription/OfflineUserSubscription'
import { UserSubscription } from '../Domain/Subscription/UserSubscription'
import { User } from '../Domain/User/User'
import { TypeORMAuthenticator } from '../Infra/TypeORM/TypeORMAuthenticator'
import { TypeORMAuthenticatorChallenge } from '../Infra/TypeORM/TypeORMAuthenticatorChallenge'
import { TypeORMSessionTrace } from '../Infra/TypeORM/TypeORMSessionTrace'
import { Env } from './Env'
@@ -58,6 +60,8 @@ export const AppDataSource = new DataSource({
SharedSubscriptionInvitation,
SubscriptionSetting,
TypeORMSessionTrace,
TypeORMAuthenticator,
TypeORMAuthenticatorChallenge,
],
migrations: [env.get('DB_MIGRATIONS_PATH', true) ?? 'dist/migrations/*.js'],
migrationsRun: true,

View File

@@ -5,6 +5,8 @@ const TYPES = {
SQS: Symbol.for('SQS'),
// Mapping
SessionTracePersistenceMapper: Symbol.for('SessionTracePersistenceMapper'),
AuthenticatorChallengePersistenceMapper: Symbol.for('AuthenticatorChallengePersistenceMapper'),
AuthenticatorPersistenceMapper: Symbol.for('AuthenticatorPersistenceMapper'),
// Controller
AuthController: Symbol.for('AuthController'),
SubscriptionInvitesController: Symbol.for('SubscriptionInvitesController'),
@@ -26,6 +28,8 @@ const TYPES = {
SharedSubscriptionInvitationRepository: Symbol.for('SharedSubscriptionInvitationRepository'),
PKCERepository: Symbol.for('PKCERepository'),
SessionTraceRepository: Symbol.for('SessionTraceRepository'),
AuthenticatorRepository: Symbol.for('AuthenticatorRepository'),
AuthenticatorChallengeRepository: Symbol.for('AuthenticatorChallengeRepository'),
// ORM
ORMOfflineSettingRepository: Symbol.for('ORMOfflineSettingRepository'),
ORMOfflineUserSubscriptionRepository: Symbol.for('ORMOfflineUserSubscriptionRepository'),
@@ -38,6 +42,8 @@ const TYPES = {
ORMUserRepository: Symbol.for('ORMUserRepository'),
ORMUserSubscriptionRepository: Symbol.for('ORMUserSubscriptionRepository'),
ORMSessionTraceRepository: Symbol.for('ORMSessionTraceRepository'),
ORMAuthenticatorRepository: Symbol.for('ORMAuthenticatorRepository'),
ORMAuthenticatorChallengeRepository: Symbol.for('ORMAuthenticatorChallengeRepository'),
// Middleware
AuthMiddleware: Symbol.for('AuthMiddleware'),
ApiGatewayAuthMiddleware: Symbol.for('ApiGatewayAuthMiddleware'),
@@ -127,6 +133,7 @@ const TYPES = {
TraceSession: Symbol.for('TraceSession'),
CleanupSessionTraces: Symbol.for('CleanupSessionTraces'),
PersistStatistics: Symbol.for('PersistStatistics'),
GenerateAuthenticatorRegistrationOptions: Symbol.for('GenerateAuthenticatorRegistrationOptions'),
// Handlers
UserRegisteredEventHandler: Symbol.for('UserRegisteredEventHandler'),
AccountDeletionRequestedEventHandler: Symbol.for('AccountDeletionRequestedEventHandler'),

View File

@@ -0,0 +1,21 @@
import { Dates, Uuid } from '@standardnotes/domain-core'
import { Authenticator } from './Authenticator'
describe('Authenticator', () => {
it('should create an entity', () => {
const entityOrError = Authenticator.create({
counter: 1,
credentialBackedUp: true,
credentialDeviceType: 'singleDevice',
credentialId: Buffer.from('credentialId'),
credentialPublicKey: Buffer.from('credentialPublicKey'),
userUuid: Uuid.create('00000000-0000-0000-0000-000000000000').getValue(),
dates: Dates.create(new Date(1), new Date(1)).getValue(),
transports: ['usb'],
})
expect(entityOrError.isFailed()).toBeFalsy()
expect(entityOrError.getValue().id).not.toBeNull()
})
})

View File

@@ -0,0 +1,17 @@
import { Entity, Result, UniqueEntityId } from '@standardnotes/domain-core'
import { AuthenticatorProps } from './AuthenticatorProps'
export class Authenticator extends Entity<AuthenticatorProps> {
get id(): UniqueEntityId {
return this._id
}
private constructor(props: AuthenticatorProps, id?: UniqueEntityId) {
super(props, id)
}
static create(props: AuthenticatorProps, id?: UniqueEntityId): Result<Authenticator> {
return Result.ok<Authenticator>(new Authenticator(props, id))
}
}

View File

@@ -0,0 +1,16 @@
import { Uuid } from '@standardnotes/domain-core'
import { AuthenticatorChallenge } from './AuthenticatorChallenge'
describe('AuthenticatorChallenge', () => {
it('should create an entity', () => {
const entityOrError = AuthenticatorChallenge.create({
userUuid: Uuid.create('00000000-0000-0000-0000-000000000000').getValue(),
createdAt: new Date(1),
challenge: Buffer.from('challenge'),
})
expect(entityOrError.isFailed()).toBeFalsy()
expect(entityOrError.getValue().id).not.toBeNull()
})
})

View File

@@ -0,0 +1,17 @@
import { Entity, Result, UniqueEntityId } from '@standardnotes/domain-core'
import { AuthenticatorChallengeProps } from './AuthenticatorChallengeProps'
export class AuthenticatorChallenge extends Entity<AuthenticatorChallengeProps> {
get id(): UniqueEntityId {
return this._id
}
private constructor(props: AuthenticatorChallengeProps, id?: UniqueEntityId) {
super(props, id)
}
static create(props: AuthenticatorChallengeProps, id?: UniqueEntityId): Result<AuthenticatorChallenge> {
return Result.ok<AuthenticatorChallenge>(new AuthenticatorChallenge(props, id))
}
}

View File

@@ -0,0 +1,7 @@
import { Uuid } from '@standardnotes/domain-core'
export interface AuthenticatorChallengeProps {
userUuid: Uuid
challenge: Buffer
createdAt: Date
}

View File

@@ -0,0 +1,5 @@
import { AuthenticatorChallenge } from './AuthenticatorChallenge'
export interface AuthenticatorChallengeRepositoryInterface {
save(authenticatorChallenge: AuthenticatorChallenge): Promise<void>
}

View File

@@ -0,0 +1,12 @@
import { Dates, Uuid } from '@standardnotes/domain-core'
export interface AuthenticatorProps {
userUuid: Uuid
credentialId: Buffer
credentialPublicKey: Buffer
counter: number
credentialDeviceType: string
credentialBackedUp: boolean
transports?: string[]
dates: Dates
}

View File

@@ -0,0 +1,6 @@
import { Uuid } from '@standardnotes/domain-core'
import { Authenticator } from './Authenticator'
export interface AuthenticatorRepositoryInterface {
findByUserUuid(userUuid: Uuid): Promise<Authenticator[]>
}

View File

@@ -15,6 +15,10 @@ import { SettingServiceInterface } from '../Setting/SettingServiceInterface'
import { LogSessionUserAgentOption } from '@standardnotes/settings'
import { Setting } from '../Setting/Setting'
import { CryptoNode } from '@standardnotes/sncrypto-node'
import { UserSubscriptionRepositoryInterface } from '../Subscription/UserSubscriptionRepositoryInterface'
import { TraceSession } from '../UseCase/TraceSession/TraceSession'
import { UserSubscription } from '../Subscription/UserSubscription'
import { Result } from '@standardnotes/domain-core'
describe('SessionService', () => {
let sessionRepository: SessionRepositoryInterface
@@ -28,6 +32,8 @@ describe('SessionService', () => {
let timer: TimerInterface
let logger: winston.Logger
let cryptoNode: CryptoNode
let traceSession: TraceSession
let userSubscriptionRepository: UserSubscriptionRepositoryInterface
const createService = () =>
new SessionService(
@@ -41,6 +47,8 @@ describe('SessionService', () => {
234,
settingService,
cryptoNode,
traceSession,
userSubscriptionRepository,
)
beforeEach(() => {
@@ -106,6 +114,14 @@ describe('SessionService', () => {
cryptoNode = {} as jest.Mocked<CryptoNode>
cryptoNode.generateRandomKey = jest.fn().mockReturnValue('foo bar')
cryptoNode.base64URLEncode = jest.fn().mockReturnValue('foobar')
traceSession = {} as jest.Mocked<TraceSession>
traceSession.execute = jest.fn()
userSubscriptionRepository = {} as jest.Mocked<UserSubscriptionRepositoryInterface>
userSubscriptionRepository.findOneByUserUuid = jest.fn().mockReturnValue({
planName: 'PRO_PLAN',
} as jest.Mocked<UserSubscription>)
})
it('should mark a revoked session as received', async () => {
@@ -204,6 +220,129 @@ describe('SessionService', () => {
})
})
it('should trace a session', async () => {
const user = {} as jest.Mocked<User>
user.uuid = '123'
user.email = 'test@test.te'
await createService().createNewSessionForUser({
user,
apiVersion: '003',
userAgent: 'Google Chrome',
readonlyAccess: false,
})
expect(traceSession.execute).toHaveBeenCalledWith({
userUuid: '123',
username: 'test@test.te',
subscriptionPlanName: 'PRO_PLAN',
})
})
it('should trace a session without a subscription', async () => {
userSubscriptionRepository.findOneByUserUuid = jest.fn().mockReturnValue(null)
const user = {} as jest.Mocked<User>
user.uuid = '123'
user.email = 'test@test.te'
await createService().createNewSessionForUser({
user,
apiVersion: '003',
userAgent: 'Google Chrome',
readonlyAccess: false,
})
expect(traceSession.execute).toHaveBeenCalledWith({
userUuid: '123',
username: 'test@test.te',
subscriptionPlanName: null,
})
})
it('should create a session if tracing session throws an error', async () => {
traceSession.execute = jest.fn().mockRejectedValue(new Error('foo bar'))
userSubscriptionRepository.findOneByUserUuid = jest.fn().mockReturnValue(null)
const user = {} as jest.Mocked<User>
user.uuid = '123'
user.email = 'test@test.te'
const sessionPayload = await createService().createNewSessionForUser({
user,
apiVersion: '003',
userAgent: 'Google Chrome',
readonlyAccess: false,
})
expect(traceSession.execute).toHaveBeenCalledWith({
userUuid: '123',
username: 'test@test.te',
subscriptionPlanName: null,
})
expect(sessionPayload).toEqual({
access_expiration: 123,
access_token: expect.any(String),
refresh_expiration: 123,
refresh_token: expect.any(String),
readonly_access: false,
})
})
it('should create a session if tracing session throws an error', async () => {
traceSession.execute = jest.fn().mockRejectedValue(new Error('foo bar'))
userSubscriptionRepository.findOneByUserUuid = jest.fn().mockReturnValue(null)
const user = {} as jest.Mocked<User>
user.uuid = '123'
user.email = 'test@test.te'
const sessionPayload = await createService().createNewSessionForUser({
user,
apiVersion: '003',
userAgent: 'Google Chrome',
readonlyAccess: false,
})
expect(traceSession.execute).toHaveBeenCalledWith({
userUuid: '123',
username: 'test@test.te',
subscriptionPlanName: null,
})
expect(sessionPayload).toEqual({
access_expiration: 123,
access_token: expect.any(String),
refresh_expiration: 123,
refresh_token: expect.any(String),
readonly_access: false,
})
})
it('should create a session if tracing session fails', async () => {
traceSession.execute = jest.fn().mockReturnValue(Result.fail('Oops'))
userSubscriptionRepository.findOneByUserUuid = jest.fn().mockReturnValue(null)
const user = {} as jest.Mocked<User>
user.uuid = '123'
user.email = 'test@test.te'
const sessionPayload = await createService().createNewSessionForUser({
user,
apiVersion: '003',
userAgent: 'Google Chrome',
readonlyAccess: false,
})
expect(traceSession.execute).toHaveBeenCalledWith({
userUuid: '123',
username: 'test@test.te',
subscriptionPlanName: null,
})
expect(sessionPayload).toEqual({
access_expiration: 123,
access_token: expect.any(String),
refresh_expiration: 123,
refresh_token: expect.any(String),
readonly_access: false,
})
})
it('should create new ephemeral session for a user', async () => {
const user = {} as jest.Mocked<User>
user.uuid = '123'

View File

@@ -1,10 +1,14 @@
import * as crypto from 'crypto'
import * as winston from 'winston'
import * as dayjs from 'dayjs'
import { UAParser } from 'ua-parser-js'
import { inject, injectable } from 'inversify'
import { v4 as uuidv4 } from 'uuid'
import { TimerInterface } from '@standardnotes/time'
import { Logger } from 'winston'
import { LogSessionUserAgentOption, SettingName } from '@standardnotes/settings'
import { SessionBody } from '@standardnotes/responses'
import { Uuid } from '@standardnotes/common'
import { CryptoNode } from '@standardnotes/sncrypto-node'
import TYPES from '../../Bootstrap/Types'
import { Session } from './Session'
@@ -16,10 +20,8 @@ import { EphemeralSession } from './EphemeralSession'
import { RevokedSession } from './RevokedSession'
import { RevokedSessionRepositoryInterface } from './RevokedSessionRepositoryInterface'
import { SettingServiceInterface } from '../Setting/SettingServiceInterface'
import { LogSessionUserAgentOption, SettingName } from '@standardnotes/settings'
import { SessionBody } from '@standardnotes/responses'
import { Uuid } from '@standardnotes/common'
import { CryptoNode } from '@standardnotes/sncrypto-node'
import { TraceSession } from '../UseCase/TraceSession/TraceSession'
import { UserSubscriptionRepositoryInterface } from '../Subscription/UserSubscriptionRepositoryInterface'
@injectable()
export class SessionService implements SessionServiceInterface {
@@ -31,11 +33,13 @@ export class SessionService implements SessionServiceInterface {
@inject(TYPES.RevokedSessionRepository) private revokedSessionRepository: RevokedSessionRepositoryInterface,
@inject(TYPES.DeviceDetector) private deviceDetector: UAParser,
@inject(TYPES.Timer) private timer: TimerInterface,
@inject(TYPES.Logger) private logger: winston.Logger,
@inject(TYPES.Logger) private logger: Logger,
@inject(TYPES.ACCESS_TOKEN_AGE) private accessTokenAge: number,
@inject(TYPES.REFRESH_TOKEN_AGE) private refreshTokenAge: number,
@inject(TYPES.SettingService) private settingService: SettingServiceInterface,
@inject(TYPES.CryptoNode) private cryptoNode: CryptoNode,
@inject(TYPES.TraceSession) private traceSession: TraceSession,
@inject(TYPES.UserSubscriptionRepository) private userSubscriptionRepository: UserSubscriptionRepositoryInterface,
) {}
async createNewSessionForUser(dto: {
@@ -53,6 +57,20 @@ export class SessionService implements SessionServiceInterface {
await this.sessionRepository.save(session)
try {
const userSubscription = await this.userSubscriptionRepository.findOneByUserUuid(dto.user.uuid)
const traceSessionResult = await this.traceSession.execute({
userUuid: dto.user.uuid,
username: dto.user.email,
subscriptionPlanName: userSubscription ? userSubscription.planName : null,
})
if (traceSessionResult.isFailed()) {
this.logger.error(traceSessionResult.getError())
}
} catch (error) {
this.logger.error(`Could not trace session while creating cross service token.: ${(error as Error).message}`)
}
return sessionPayload
}

View File

@@ -8,10 +8,6 @@ import { Role } from '../../Role/Role'
import { UserRepositoryInterface } from '../../User/UserRepositoryInterface'
import { CreateCrossServiceToken } from './CreateCrossServiceToken'
import { RoleToSubscriptionMapInterface } from '../../Role/RoleToSubscriptionMapInterface'
import { TraceSession } from '../TraceSession/TraceSession'
import { Logger } from 'winston'
import { Result, RoleName, SubscriptionPlanName } from '@standardnotes/domain-core'
describe('CreateCrossServiceToken', () => {
let userProjector: ProjectorInterface<User>
@@ -19,9 +15,6 @@ describe('CreateCrossServiceToken', () => {
let roleProjector: ProjectorInterface<Role>
let tokenEncoder: TokenEncoderInterface<CrossServiceTokenData>
let userRepository: UserRepositoryInterface
let roleToSubscriptionMap: RoleToSubscriptionMapInterface
let traceSession: TraceSession
let logger: Logger
const jwtTTL = 60
let session: Session
@@ -29,17 +22,7 @@ describe('CreateCrossServiceToken', () => {
let role: Role
const createUseCase = () =>
new CreateCrossServiceToken(
userProjector,
sessionProjector,
roleProjector,
tokenEncoder,
userRepository,
jwtTTL,
roleToSubscriptionMap,
traceSession,
logger,
)
new CreateCrossServiceToken(userProjector, sessionProjector, roleProjector, tokenEncoder, userRepository, jwtTTL)
beforeEach(() => {
session = {} as jest.Mocked<Session>
@@ -65,18 +48,6 @@ describe('CreateCrossServiceToken', () => {
userRepository = {} as jest.Mocked<UserRepositoryInterface>
userRepository.findOneByUuid = jest.fn().mockReturnValue(user)
roleToSubscriptionMap = {} as jest.Mocked<RoleToSubscriptionMapInterface>
roleToSubscriptionMap.filterSubscriptionRoles = jest.fn().mockReturnValue([RoleName.NAMES.PlusUser])
roleToSubscriptionMap.getSubscriptionNameForRoleName = jest
.fn()
.mockReturnValue(SubscriptionPlanName.NAMES.PlusPlan)
traceSession = {} as jest.Mocked<TraceSession>
traceSession.execute = jest.fn()
logger = {} as jest.Mocked<Logger>
logger.error = jest.fn()
})
it('should create a cross service token for user', async () => {
@@ -85,11 +56,6 @@ describe('CreateCrossServiceToken', () => {
session,
})
expect(traceSession.execute).toHaveBeenCalledWith({
userUuid: '1-2-3',
username: 'test@test.te',
subscriptionPlanName: 'PLUS_PLAN',
})
expect(tokenEncoder.encodeExpirableToken).toHaveBeenCalledWith(
{
roles: [
@@ -168,126 +134,4 @@ describe('CreateCrossServiceToken', () => {
expect(caughtError).not.toBeNull()
})
it('should trace session without a subscription role', async () => {
roleToSubscriptionMap.filterSubscriptionRoles = jest.fn().mockReturnValue([])
await createUseCase().execute({
user,
session,
})
expect(traceSession.execute).toHaveBeenCalledWith({
userUuid: '1-2-3',
username: 'test@test.te',
subscriptionPlanName: null,
})
expect(tokenEncoder.encodeExpirableToken).toHaveBeenCalledWith(
{
roles: [
{
name: 'role1',
uuid: '1-3-4',
},
],
session: {
test: 'test',
},
user: {
email: 'test@test.te',
uuid: '1-2-3',
},
},
60,
)
})
it('should trace session without a subscription', async () => {
roleToSubscriptionMap.getSubscriptionNameForRoleName = jest.fn().mockReturnValue(undefined)
await createUseCase().execute({
user,
session,
})
expect(traceSession.execute).toHaveBeenCalledWith({
userUuid: '1-2-3',
username: 'test@test.te',
subscriptionPlanName: null,
})
expect(tokenEncoder.encodeExpirableToken).toHaveBeenCalledWith(
{
roles: [
{
name: 'role1',
uuid: '1-3-4',
},
],
session: {
test: 'test',
},
user: {
email: 'test@test.te',
uuid: '1-2-3',
},
},
60,
)
})
it('should create token if tracing session throws an error', async () => {
traceSession.execute = jest.fn().mockRejectedValue(new Error('test'))
await createUseCase().execute({
user,
session,
})
expect(tokenEncoder.encodeExpirableToken).toHaveBeenCalledWith(
{
roles: [
{
name: 'role1',
uuid: '1-3-4',
},
],
session: {
test: 'test',
},
user: {
email: 'test@test.te',
uuid: '1-2-3',
},
},
60,
)
})
it('should create token if tracing session fails', async () => {
traceSession.execute = jest.fn().mockReturnValue(Result.fail('Ooops'))
await createUseCase().execute({
user,
session,
})
expect(tokenEncoder.encodeExpirableToken).toHaveBeenCalledWith(
{
roles: [
{
name: 'role1',
uuid: '1-3-4',
},
],
session: {
test: 'test',
},
user: {
email: 'test@test.te',
uuid: '1-2-3',
},
},
60,
)
})
})

View File

@@ -1,16 +1,13 @@
import { RoleName } from '@standardnotes/common'
import { TokenEncoderInterface, CrossServiceTokenData } from '@standardnotes/security'
import { inject, injectable } from 'inversify'
import { Logger } from 'winston'
import TYPES from '../../../Bootstrap/Types'
import { ProjectorInterface } from '../../../Projection/ProjectorInterface'
import { Role } from '../../Role/Role'
import { RoleToSubscriptionMapInterface } from '../../Role/RoleToSubscriptionMapInterface'
import { Session } from '../../Session/Session'
import { User } from '../../User/User'
import { UserRepositoryInterface } from '../../User/UserRepositoryInterface'
import { TraceSession } from '../TraceSession/TraceSession'
import { UseCaseInterface } from '../UseCaseInterface'
import { CreateCrossServiceTokenDTO } from './CreateCrossServiceTokenDTO'
@@ -25,9 +22,6 @@ export class CreateCrossServiceToken implements UseCaseInterface {
@inject(TYPES.CrossServiceTokenEncoder) private tokenEncoder: TokenEncoderInterface<CrossServiceTokenData>,
@inject(TYPES.UserRepository) private userRepository: UserRepositoryInterface,
@inject(TYPES.AUTH_JWT_TTL) private jwtTTL: number,
@inject(TYPES.RoleToSubscriptionMap) private roleToSubscriptionMap: RoleToSubscriptionMapInterface,
@inject(TYPES.TraceSession) private traceSession: TraceSession,
@inject(TYPES.Logger) private logger: Logger,
) {}
async execute(dto: CreateCrossServiceTokenDTO): Promise<CreateCrossServiceTokenResponse> {
@@ -51,19 +45,6 @@ export class CreateCrossServiceToken implements UseCaseInterface {
authTokenData.session = this.projectSession(dto.session)
}
try {
const traceSessionResult = await this.traceSession.execute({
userUuid: user.uuid,
username: user.email,
subscriptionPlanName: this.getSubscriptionNameFromRoles(roles),
})
if (traceSessionResult.isFailed()) {
this.logger.error(traceSessionResult.getError())
}
} catch (error) {
this.logger.error(`Could not trace session while creating cross service token: ${(error as Error).message}`)
}
return {
token: this.tokenEncoder.encodeExpirableToken(authTokenData, this.jwtTTL),
}
@@ -100,17 +81,4 @@ export class CreateCrossServiceToken implements UseCaseInterface {
private projectRoles(roles: Array<Role>): Array<{ uuid: string; name: RoleName }> {
return roles.map((role) => <{ uuid: string; name: RoleName }>this.roleProjector.projectSimple(role))
}
private getSubscriptionNameFromRoles(roles: Array<Role>): string | null {
const nonSubscriptionRoles = this.roleToSubscriptionMap.filterSubscriptionRoles(roles)
if (nonSubscriptionRoles.length === 0) {
return null
}
const subscriptionName = this.roleToSubscriptionMap.getSubscriptionNameForRoleName(
nonSubscriptionRoles[0].name as RoleName,
)
return subscriptionName === undefined ? null : subscriptionName
}
}

View File

@@ -0,0 +1,89 @@
import { Dates, Result, Uuid } from '@standardnotes/domain-core'
import { Authenticator } from '../../Authenticator/Authenticator'
import { AuthenticatorChallenge } from '../../Authenticator/AuthenticatorChallenge'
import { AuthenticatorChallengeRepositoryInterface } from '../../Authenticator/AuthenticatorChallengeRepositoryInterface'
import { AuthenticatorRepositoryInterface } from '../../Authenticator/AuthenticatorRepositoryInterface'
import { GenerateAuthenticatorRegistrationOptions } from './GenerateAuthenticatorRegistrationOptions'
describe('GenerateAuthenticatorRegistrationOptions', () => {
let authenticatorRepository: AuthenticatorRepositoryInterface
let authenticatorChallengeRepository: AuthenticatorChallengeRepositoryInterface
const createUseCase = () =>
new GenerateAuthenticatorRegistrationOptions(authenticatorRepository, authenticatorChallengeRepository)
beforeEach(() => {
const authenticator = Authenticator.create({
counter: 1,
credentialBackedUp: true,
credentialDeviceType: 'singleDevice',
credentialId: Buffer.from('credentialId'),
credentialPublicKey: Buffer.from('credentialPublicKey'),
userUuid: Uuid.create('00000000-0000-0000-0000-000000000000').getValue(),
dates: Dates.create(new Date(1), new Date(1)).getValue(),
transports: ['usb'],
}).getValue()
authenticatorRepository = {} as jest.Mocked<AuthenticatorRepositoryInterface>
authenticatorRepository.findByUserUuid = jest.fn().mockReturnValue([authenticator])
authenticatorChallengeRepository = {} as jest.Mocked<AuthenticatorChallengeRepositoryInterface>
authenticatorChallengeRepository.save = jest.fn()
})
it('should return error if userUuid is invalid', async () => {
const useCase = createUseCase()
const result = await useCase.execute({
userUuid: 'invalid',
username: 'username',
})
expect(result.isFailed()).toBe(true)
expect(result.getError()).toBe(
'Could not generate authenticator registration options: Given value is not a valid uuid: invalid',
)
})
it('should return error if username is invalid', async () => {
const useCase = createUseCase()
const result = await useCase.execute({
userUuid: '00000000-0000-0000-0000-000000000000',
username: '',
})
expect(result.isFailed()).toBe(true)
expect(result.getError()).toBe('Could not generate authenticator registration options: Username cannot be empty')
})
it('should return error if authenticator challenge is invalid', async () => {
const mock = jest.spyOn(AuthenticatorChallenge, 'create')
mock.mockReturnValue(Result.fail('Oops'))
const useCase = createUseCase()
const result = await useCase.execute({
userUuid: '00000000-0000-0000-0000-000000000000',
username: 'username',
})
expect(result.isFailed()).toBe(true)
expect(result.getError()).toBe('Could not generate authenticator registration options: Oops')
mock.mockRestore()
})
it('should return registration options', async () => {
const useCase = createUseCase()
const result = await useCase.execute({
userUuid: '00000000-0000-0000-0000-000000000000',
username: 'username',
})
expect(result.isFailed()).toBe(false)
expect(authenticatorChallengeRepository.save).toHaveBeenCalled()
})
})

View File

@@ -0,0 +1,61 @@
import { Result, UseCaseInterface, Username, Uuid } from '@standardnotes/domain-core'
import { generateRegistrationOptions } from '@simplewebauthn/server'
import { GenerateAuthenticatorRegistrationOptionsDTO } from './GenerateAuthenticatorRegistrationOptionsDTO'
import { AuthenticatorRepositoryInterface } from '../../Authenticator/AuthenticatorRepositoryInterface'
import { AuthenticatorChallengeRepositoryInterface } from '../../Authenticator/AuthenticatorChallengeRepositoryInterface'
import { AuthenticatorChallenge } from '../../Authenticator/AuthenticatorChallenge'
export class GenerateAuthenticatorRegistrationOptions implements UseCaseInterface<Record<string, unknown>> {
private readonly RP_NAME = 'Standard Notes'
private readonly RP_ID = 'standardnotes.com'
constructor(
private authenticatorRepository: AuthenticatorRepositoryInterface,
private authenticatorChallengeRepository: AuthenticatorChallengeRepositoryInterface,
) {}
async execute(dto: GenerateAuthenticatorRegistrationOptionsDTO): Promise<Result<Record<string, unknown>>> {
const userUuidOrError = Uuid.create(dto.userUuid)
if (userUuidOrError.isFailed()) {
return Result.fail(`Could not generate authenticator registration options: ${userUuidOrError.getError()}`)
}
const userUuid = userUuidOrError.getValue()
const usernameOrError = Username.create(dto.username)
if (usernameOrError.isFailed()) {
return Result.fail(`Could not generate authenticator registration options: ${usernameOrError.getError()}`)
}
const username = usernameOrError.getValue()
const authenticators = await this.authenticatorRepository.findByUserUuid(userUuid)
const options = generateRegistrationOptions({
rpID: this.RP_ID,
rpName: this.RP_NAME,
userID: userUuid.value,
userName: username.value,
attestationType: 'none',
excludeCredentials: authenticators.map((authenticator) => ({
id: authenticator.props.credentialId,
type: 'public-key',
transports: authenticator.props.transports,
})),
})
const authenticatorChallengeOrError = AuthenticatorChallenge.create({
challenge: options.challenge,
userUuid,
createdAt: new Date(),
})
if (authenticatorChallengeOrError.isFailed()) {
return Result.fail(
`Could not generate authenticator registration options: ${authenticatorChallengeOrError.getError()}`,
)
}
const authenticatorChallenge = authenticatorChallengeOrError.getValue()
await this.authenticatorChallengeRepository.save(authenticatorChallenge)
return Result.ok(options)
}
}

View File

@@ -0,0 +1,4 @@
export interface GenerateAuthenticatorRegistrationOptionsDTO {
userUuid: string
username: string
}

View File

@@ -0,0 +1,20 @@
import { MapperInterface } from '@standardnotes/domain-core'
import { Repository } from 'typeorm'
import { AuthenticatorChallenge } from '../../Domain/Authenticator/AuthenticatorChallenge'
import { AuthenticatorChallengeRepositoryInterface } from '../../Domain/Authenticator/AuthenticatorChallengeRepositoryInterface'
import { TypeORMAuthenticatorChallenge } from '../TypeORM/TypeORMAuthenticatorChallenge'
export class MySQLAuthenticatorChallengeRepository implements AuthenticatorChallengeRepositoryInterface {
constructor(
private ormRepository: Repository<TypeORMAuthenticatorChallenge>,
private mapper: MapperInterface<AuthenticatorChallenge, TypeORMAuthenticatorChallenge>,
) {}
async save(authenticatorChallenge: AuthenticatorChallenge): Promise<void> {
const persistence = this.mapper.toProjection(authenticatorChallenge)
await this.ormRepository.save(persistence)
}
}

View File

@@ -0,0 +1,24 @@
import { MapperInterface, Uuid } from '@standardnotes/domain-core'
import { Repository } from 'typeorm'
import { Authenticator } from '../../Domain/Authenticator/Authenticator'
import { AuthenticatorRepositoryInterface } from '../../Domain/Authenticator/AuthenticatorRepositoryInterface'
import { TypeORMAuthenticator } from '../TypeORM/TypeORMAuthenticator'
export class MySQLAuthenticatorRepository implements AuthenticatorRepositoryInterface {
constructor(
private ormRepository: Repository<TypeORMAuthenticator>,
private mapper: MapperInterface<Authenticator, TypeORMAuthenticator>,
) {}
async findByUserUuid(userUuid: Uuid): Promise<Authenticator[]> {
const typeOrm = await this.ormRepository
.createQueryBuilder('authenticator')
.where('authenticator.user_uuid = :userUuid', {
userUuid: userUuid.value,
})
.getMany()
return typeOrm.map((authenticator) => this.mapper.toDomain(authenticator))
}
}

View File

@@ -14,7 +14,7 @@ export class MySQLSessionTraceRepository implements SessionTraceRepositoryInterf
return this.ormRepository
.createQueryBuilder('trace')
.where('trace.creation_date = :creationDate', {
creationDate: new Date(date.getFullYear(), date.getMonth(), date.getDate()),
creationDate: `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`,
})
.andWhere('trace.subscription_plan_name = :subscriptionPlanName', {
subscriptionPlanName: subscriptionPlanName.value,
@@ -26,7 +26,7 @@ export class MySQLSessionTraceRepository implements SessionTraceRepositoryInterf
return this.ormRepository
.createQueryBuilder('trace')
.where('trace.creation_date = :creationDate', {
creationDate: new Date(date.getFullYear(), date.getMonth(), date.getDate()),
creationDate: `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`,
})
.getCount()
}
@@ -44,7 +44,7 @@ export class MySQLSessionTraceRepository implements SessionTraceRepositoryInterf
.createQueryBuilder('trace')
.where('trace.user_uuid = :userUuid AND trace.creation_date = :creationDate', {
userUuid: userUuid.value,
creationDate: new Date(date.getFullYear(), date.getMonth(), date.getDate()),
creationDate: `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`,
})
.getOne()

View File

@@ -0,0 +1,65 @@
import { Column, Entity, Index, PrimaryGeneratedColumn } from 'typeorm'
@Entity({ name: 'authenticators' })
export class TypeORMAuthenticator {
@PrimaryGeneratedColumn('uuid')
declare uuid: string
@Column({
name: 'user_uuid',
length: 36,
})
declare userUuid: string
@Column({
name: 'credential_id',
type: 'varbinary',
length: 1024,
})
@Index('credential_id', { unique: true })
declare credentialId: Buffer
@Column({
name: 'credential_public_key',
type: 'blob',
})
declare credentialPublicKey: Buffer
@Column({
name: 'counter',
type: 'bigint',
})
declare counter: number
@Column({
name: 'credential_device_type',
type: 'varchar',
length: 32,
})
declare credentialDeviceType: string
@Column({
name: 'credential_backed_up',
})
declare credentialBackedUp: boolean
@Column({
name: 'transports',
type: 'varchar',
length: 255,
nullable: true,
})
declare transports: string | null
@Column({
name: 'created_at',
type: 'datetime',
})
declare createdAt: Date
@Column({
name: 'updated_at',
type: 'datetime',
})
declare updatedAt: Date
}

View File

@@ -0,0 +1,27 @@
import { Column, Entity, Index, PrimaryGeneratedColumn } from 'typeorm'
@Entity({ name: 'authenticator_challenges' })
@Index('user_uuid_and_challenge', ['userUuid', 'challenge'])
export class TypeORMAuthenticatorChallenge {
@PrimaryGeneratedColumn('uuid')
declare uuid: string
@Column({
name: 'user_uuid',
length: 36,
})
declare userUuid: string
@Column({
name: 'challenge',
type: 'varchar',
length: 255,
})
declare challenge: Buffer
@Column({
name: 'created_at',
type: 'datetime',
})
declare createdAt: Date
}

View File

@@ -1,6 +1,7 @@
import { Column, Entity, Index, PrimaryGeneratedColumn } from 'typeorm'
@Entity({ name: 'session_traces' })
@Index('user_uuid_and_creation_date', ['userUuid', 'creationDate'], { unique: true })
export class TypeORMSessionTrace {
@PrimaryGeneratedColumn('uuid')
declare uuid: string

View File

@@ -0,0 +1,44 @@
import { MapperInterface, UniqueEntityId, Uuid } from '@standardnotes/domain-core'
import { AuthenticatorChallenge } from '../Domain/Authenticator/AuthenticatorChallenge'
import { TypeORMAuthenticatorChallenge } from '../Infra/TypeORM/TypeORMAuthenticatorChallenge'
export class AuthenticatorChallengePersistenceMapper
implements MapperInterface<AuthenticatorChallenge, TypeORMAuthenticatorChallenge>
{
toDomain(projection: TypeORMAuthenticatorChallenge): AuthenticatorChallenge {
const userUuidOrError = Uuid.create(projection.userUuid)
if (userUuidOrError.isFailed()) {
throw new Error(`Failed to create authenticator challenge from projection: ${userUuidOrError.getError()}`)
}
const userUuid = userUuidOrError.getValue()
const authenticatorChallengeOrError = AuthenticatorChallenge.create(
{
challenge: projection.challenge,
userUuid,
createdAt: projection.createdAt,
},
new UniqueEntityId(projection.uuid),
)
if (authenticatorChallengeOrError.isFailed()) {
throw new Error(
`Failed to create authenticator challenge from projection: ${authenticatorChallengeOrError.getError()}`,
)
}
const authenticatorChallenge = authenticatorChallengeOrError.getValue()
return authenticatorChallenge
}
toProjection(domain: AuthenticatorChallenge): TypeORMAuthenticatorChallenge {
const typeorm = new TypeORMAuthenticatorChallenge()
typeorm.uuid = domain.id.toString()
typeorm.userUuid = domain.props.userUuid.value
typeorm.challenge = domain.props.challenge
typeorm.createdAt = domain.props.createdAt
return typeorm
}
}

View File

@@ -0,0 +1,59 @@
import { Dates, MapperInterface, UniqueEntityId, Uuid } from '@standardnotes/domain-core'
import { Authenticator } from '../Domain/Authenticator/Authenticator'
import { TypeORMAuthenticator } from '../Infra/TypeORM/TypeORMAuthenticator'
export class AuthenticatorPersistenceMapper implements MapperInterface<Authenticator, TypeORMAuthenticator> {
toDomain(projection: TypeORMAuthenticator): Authenticator {
const userUuidOrError = Uuid.create(projection.userUuid)
if (userUuidOrError.isFailed()) {
throw new Error(`Failed to create authenticator from projection: ${userUuidOrError.getError()}`)
}
const userUuid = userUuidOrError.getValue()
const datesOrError = Dates.create(projection.createdAt, projection.updatedAt)
if (datesOrError.isFailed()) {
throw new Error(`Failed to create authenticator from projection: ${datesOrError.getError()}`)
}
const dates = datesOrError.getValue()
const authenticatorOrError = Authenticator.create(
{
userUuid,
counter: projection.counter,
credentialBackedUp: projection.credentialBackedUp,
credentialDeviceType: projection.credentialDeviceType,
credentialId: projection.credentialId,
credentialPublicKey: projection.credentialPublicKey,
dates,
transports: projection.transports ? JSON.parse(projection.transports) : undefined,
},
new UniqueEntityId(projection.uuid),
)
if (authenticatorOrError.isFailed()) {
throw new Error(`Failed to create authenticator from projection: ${authenticatorOrError.getError()}`)
}
const authenticator = authenticatorOrError.getValue()
return authenticator
}
toProjection(domain: Authenticator): TypeORMAuthenticator {
const typeorm = new TypeORMAuthenticator()
typeorm.uuid = domain.id.toString()
typeorm.userUuid = domain.props.userUuid.value
typeorm.credentialId = domain.props.credentialId
typeorm.credentialPublicKey = domain.props.credentialPublicKey
typeorm.counter = domain.props.counter
typeorm.credentialDeviceType = domain.props.credentialDeviceType
typeorm.credentialBackedUp = domain.props.credentialBackedUp
if (domain.props.transports) {
typeorm.transports = JSON.stringify(domain.props.transports)
}
typeorm.createdAt = domain.props.dates.createdAt
typeorm.updatedAt = domain.props.dates.updatedAt
return typeorm
}
}

View File

@@ -3,6 +3,10 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.9.3](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.9.2...@standardnotes/files-server@1.9.3) (2022-12-28)
**Note:** Version bump only for package @standardnotes/files-server
## [1.9.2](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.9.1...@standardnotes/files-server@1.9.2) (2022-12-20)
**Note:** Version bump only for package @standardnotes/files-server

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/files-server",
"version": "1.9.2",
"version": "1.9.3",
"engines": {
"node": ">=18.0.0 <19.0.0"
},
@@ -25,7 +25,7 @@
"upgrade:snjs": "yarn ncu -u '@standardnotes/*'"
},
"dependencies": {
"@sentry/node": "^7.27.0",
"@sentry/node": "^7.28.1",
"@standardnotes/common": "workspace:*",
"@standardnotes/domain-events": "workspace:*",
"@standardnotes/domain-events-infra": "workspace:*",

View File

@@ -3,6 +3,10 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.10.3](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.10.2...@standardnotes/revisions-server@1.10.3) (2022-12-28)
**Note:** Version bump only for package @standardnotes/revisions-server
## [1.10.2](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.10.1...@standardnotes/revisions-server@1.10.2) (2022-12-20)
**Note:** Version bump only for package @standardnotes/revisions-server

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/revisions-server",
"version": "1.10.2",
"version": "1.10.3",
"engines": {
"node": ">=18.0.0 <19.0.0"
},
@@ -24,7 +24,7 @@
},
"dependencies": {
"@newrelic/winston-enricher": "^4.0.0",
"@sentry/node": "^7.27.0",
"@sentry/node": "^7.28.1",
"@standardnotes/api": "^1.19.0",
"@standardnotes/common": "workspace:^",
"@standardnotes/domain-core": "workspace:^",

View File

@@ -3,6 +3,16 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.16.4](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.16.3...@standardnotes/scheduler-server@1.16.4) (2022-12-28)
**Note:** Version bump only for package @standardnotes/scheduler-server
## [1.16.3](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.16.2...@standardnotes/scheduler-server@1.16.3) (2022-12-20)
### Bug Fixes
* **scheduler:** new pricing for subscription encouragement email ([eb21872](https://github.com/standardnotes/server/commit/eb21872db1726c4f8a55b5d16de712650c5e946b))
## [1.16.2](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.16.1...@standardnotes/scheduler-server@1.16.2) (2022-12-20)
**Note:** Version bump only for package @standardnotes/scheduler-server

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/scheduler-server",
"version": "1.16.2",
"version": "1.16.4",
"engines": {
"node": ">=18.0.0 <19.0.0"
},
@@ -25,7 +25,7 @@
},
"dependencies": {
"@newrelic/winston-enricher": "^4.0.0",
"@sentry/node": "^7.27.0",
"@sentry/node": "^7.28.1",
"@standardnotes/common": "workspace:*",
"@standardnotes/domain-core": "workspace:^",
"@standardnotes/domain-events": "workspace:*",

View File

@@ -5,7 +5,5 @@ export function getSubject(): string {
}
export function getBody(registrationDate: string): string {
const body = html
return body.replace('%%REGISTRATION_DATE%%', registrationDate)
return html(registrationDate, 90, 120)
}

View File

@@ -1,4 +1,4 @@
export const html = `<div>
export const html = (registrationDate: string, annualPlusPrice: number, annualProPrice: number) => `<div>
<p>Hi there,</p>
<p>
We hope you've been finding great use out of Standard Notes. We built Standard Notes to be a secure place for
@@ -7,7 +7,7 @@ export const html = `<div>
<p>
As a reminder,
<strong>
<em>you signed up for the Standard Notes free plan on %%REGISTRATION_DATE%%</em>
<em>you signed up for the Standard Notes free plan on ${registrationDate}</em>
</strong>
Your free account comes with standard features like end-to-end encryption, multiple-device sync, and
two-factor authentication.
@@ -19,13 +19,13 @@ export const html = `<div>
<ul>
<li>
<p>
<strong>Productivity</strong> <strong>($59/year)</strong> powers up your editing experience with unique
<strong>Productivity</strong> <strong>($${annualPlusPrice}/year)</strong> powers up your editing experience with unique
and special-built note-types for markdown, rich text, spreadsheets, todo, and more.
</p>
</li>
<li>
<p>
<strong>Professional</strong> <strong>($99/year)</strong> gives you all the power of Productivity plus
<strong>Professional</strong> <strong>($${annualProPrice}/year)</strong> gives you all the power of Productivity plus
100GB of end-to-end encrypted file storage for your private photos, videos, and documents, plus family
subscription sharing with up to 5 people.
</p>

View File

@@ -3,6 +3,10 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.28.3](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.28.2...@standardnotes/syncing-server@1.28.3) (2022-12-28)
**Note:** Version bump only for package @standardnotes/syncing-server
## [1.28.2](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.28.1...@standardnotes/syncing-server@1.28.2) (2022-12-20)
**Note:** Version bump only for package @standardnotes/syncing-server

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/syncing-server",
"version": "1.28.2",
"version": "1.28.3",
"engines": {
"node": ">=18.0.0 <19.0.0"
},
@@ -27,9 +27,9 @@
},
"dependencies": {
"@newrelic/winston-enricher": "^4.0.0",
"@sentry/node": "^7.27.0",
"@sentry/node": "^7.28.1",
"@sentry/profiling-node": "^0.0.12",
"@sentry/tracing": "^7.27.0",
"@sentry/tracing": "^7.28.1",
"@standardnotes/common": "workspace:*",
"@standardnotes/domain-core": "workspace:^",
"@standardnotes/domain-events": "workspace:*",

View File

@@ -3,6 +3,10 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.5.3](https://github.com/standardnotes/server/compare/@standardnotes/websockets-server@1.5.2...@standardnotes/websockets-server@1.5.3) (2022-12-28)
**Note:** Version bump only for package @standardnotes/websockets-server
## [1.5.2](https://github.com/standardnotes/server/compare/@standardnotes/websockets-server@1.5.1...@standardnotes/websockets-server@1.5.2) (2022-12-20)
**Note:** Version bump only for package @standardnotes/websockets-server

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/websockets-server",
"version": "1.5.2",
"version": "1.5.3",
"engines": {
"node": ">=18.0.0 <19.0.0"
},
@@ -23,7 +23,7 @@
},
"dependencies": {
"@newrelic/winston-enricher": "^4.0.0",
"@sentry/node": "^7.27.0",
"@sentry/node": "^7.28.1",
"@standardnotes/api": "^1.19.0",
"@standardnotes/common": "workspace:^",
"@standardnotes/domain-events": "workspace:^",

View File

@@ -3,6 +3,16 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.19.4](https://github.com/standardnotes/server/compare/@standardnotes/workspace-server@1.19.3...@standardnotes/workspace-server@1.19.4) (2022-12-28)
**Note:** Version bump only for package @standardnotes/workspace-server
## [1.19.3](https://github.com/standardnotes/server/compare/@standardnotes/workspace-server@1.19.2...@standardnotes/workspace-server@1.19.3) (2022-12-20)
### Bug Fixes
* **workspace:** specs ([c8203cf](https://github.com/standardnotes/server/commit/c8203cf04cb93cc65d30b69f10fb275f5e6be449))
## [1.19.2](https://github.com/standardnotes/server/compare/@standardnotes/workspace-server@1.19.1...@standardnotes/workspace-server@1.19.2) (2022-12-20)
**Note:** Version bump only for package @standardnotes/workspace-server

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/workspace-server",
"version": "1.19.2",
"version": "1.19.4",
"engines": {
"node": ">=18.0.0 <19.0.0"
},
@@ -23,7 +23,7 @@
},
"dependencies": {
"@newrelic/winston-enricher": "^4.0.0",
"@sentry/node": "^7.27.0",
"@sentry/node": "^7.28.1",
"@standardnotes/api": "^1.19.0",
"@standardnotes/common": "workspace:*",
"@standardnotes/domain-core": "workspace:^",

View File

@@ -5,7 +5,7 @@ import { WorkspaceInviteRepositoryInterface } from '../../Invite/WorkspaceInvite
import { InviteToWorkspace } from './InviteToWorkspace'
import { DomainEventFactoryInterface } from '../../Event/DomainEventFactoryInterface'
import { DomainEventPublisherInterface, WorkspaceInviteCreatedEvent } from '@standardnotes/domain-events'
import { DomainEventPublisherInterface, EmailRequestedEvent } from '@standardnotes/domain-events'
import { WorkspaceAccessLevel } from '@standardnotes/common'
describe('InviteToWorkspace', () => {
@@ -33,9 +33,7 @@ describe('InviteToWorkspace', () => {
domainEventPublisher.publish = jest.fn()
domainEventFactory = {} as jest.Mocked<DomainEventFactoryInterface>
domainEventFactory.createWorkspaceInviteCreatedEvent = jest
.fn()
.mockReturnValue({} as jest.Mocked<WorkspaceInviteCreatedEvent>)
domainEventFactory.createEmailRequestedEvent = jest.fn().mockReturnValue({} as jest.Mocked<EmailRequestedEvent>)
})
it('should create an invite', async () => {

314
yarn.lock
View File

@@ -1323,6 +1323,13 @@ __metadata:
languageName: node
linkType: hard
"@noble/ed25519@npm:^1.6.1":
version: 1.7.1
resolution: "@noble/ed25519@npm:1.7.1"
checksum: b1aa4b9264c2a26d1905b01493c81c124eb05758c00464fcc9ae92880f9696fc4b525d9ff2a22c859ca753982172ba7b180242a6adb0b8ecc52a944d2173e77c
languageName: node
linkType: hard
"@nodelib/fs.scandir@npm:2.1.5":
version: 2.1.5
resolution: "@nodelib/fs.scandir@npm:2.1.5"
@@ -1614,6 +1621,41 @@ __metadata:
languageName: node
linkType: hard
"@peculiar/asn1-android@npm:^2.1.7":
version: 2.3.3
resolution: "@peculiar/asn1-android@npm:2.3.3"
dependencies:
"@peculiar/asn1-schema": "npm:^2.3.3"
asn1js: "npm:^3.0.5"
tslib: "npm:^2.4.0"
checksum: 0c7cad544efe3a7235888a56baf70ce913b3604d53d2733f606b9904c8af52bad0cd55b7a28276676a707c655ee6a6d30ee6232454a0c568bc488dcbb88b943b
languageName: node
linkType: hard
"@peculiar/asn1-schema@npm:^2.1.7, @peculiar/asn1-schema@npm:^2.3.3":
version: 2.3.3
resolution: "@peculiar/asn1-schema@npm:2.3.3"
dependencies:
asn1js: "npm:^3.0.5"
pvtsutils: "npm:^1.3.2"
tslib: "npm:^2.4.0"
checksum: f584f79d5a3652888452e72591cd5f910b1c4c59a359c7495a82d8f6463e3033a715bdd1954b52bcecb864f21f8844335025e84e782cc843c6649bc3304094ec
languageName: node
linkType: hard
"@peculiar/asn1-x509@npm:^2.1.7":
version: 2.3.4
resolution: "@peculiar/asn1-x509@npm:2.3.4"
dependencies:
"@peculiar/asn1-schema": "npm:^2.3.3"
asn1js: "npm:^3.0.5"
ipaddr.js: "npm:^2.0.1"
pvtsutils: "npm:^1.3.2"
tslib: "npm:^2.4.0"
checksum: 10a865998042fc7dc4fff8de5d7b926ba37962fcf8d5b923c6ba322de388788d8fcf0c235d9298bf32d06f1262adebfe5003f92aaa45108d234303a25175a85b
languageName: node
linkType: hard
"@pnpm/network.ca-file@npm:^1.0.1":
version: 1.0.1
resolution: "@pnpm/network.ca-file@npm:1.0.1"
@@ -1717,6 +1759,17 @@ __metadata:
languageName: node
linkType: hard
"@sentry/core@npm:7.28.1":
version: 7.28.1
resolution: "@sentry/core@npm:7.28.1"
dependencies:
"@sentry/types": "npm:7.28.1"
"@sentry/utils": "npm:7.28.1"
tslib: "npm:^1.9.3"
checksum: f29d747d3e15000d8010fe3c192260a78927f37d30a3bb82cd533f3a5beca0c7fd81353ec57420c4295daea5384a045bde70ff6d3af1468ec1201b1d84131d6d
languageName: node
linkType: hard
"@sentry/hub@npm:^7.16.0":
version: 7.27.0
resolution: "@sentry/hub@npm:7.27.0"
@@ -1729,7 +1782,7 @@ __metadata:
languageName: node
linkType: hard
"@sentry/node@npm:^7.16.0, @sentry/node@npm:^7.27.0":
"@sentry/node@npm:^7.16.0":
version: 7.27.0
resolution: "@sentry/node@npm:7.27.0"
dependencies:
@@ -1744,6 +1797,21 @@ __metadata:
languageName: node
linkType: hard
"@sentry/node@npm:^7.28.1":
version: 7.28.1
resolution: "@sentry/node@npm:7.28.1"
dependencies:
"@sentry/core": "npm:7.28.1"
"@sentry/types": "npm:7.28.1"
"@sentry/utils": "npm:7.28.1"
cookie: "npm:^0.4.1"
https-proxy-agent: "npm:^5.0.0"
lru_map: "npm:^0.3.3"
tslib: "npm:^1.9.3"
checksum: b4922d1f0a1b1e96cd73e5381871d0a2d20c4a05dd09f1cb9def6795c5fbe099b2e2b97025262cac595d19a42ebc82a34a8f9e59f87c0176e5206ae1f6377532
languageName: node
linkType: hard
"@sentry/profiling-node@npm:^0.0.12":
version: 0.0.12
resolution: "@sentry/profiling-node@npm:0.0.12"
@@ -1760,7 +1828,7 @@ __metadata:
languageName: node
linkType: hard
"@sentry/tracing@npm:^7.16.0, @sentry/tracing@npm:^7.27.0":
"@sentry/tracing@npm:^7.16.0":
version: 7.27.0
resolution: "@sentry/tracing@npm:7.27.0"
dependencies:
@@ -1772,6 +1840,18 @@ __metadata:
languageName: node
linkType: hard
"@sentry/tracing@npm:^7.28.1":
version: 7.28.1
resolution: "@sentry/tracing@npm:7.28.1"
dependencies:
"@sentry/core": "npm:7.28.1"
"@sentry/types": "npm:7.28.1"
"@sentry/utils": "npm:7.28.1"
tslib: "npm:^1.9.3"
checksum: be501ca9d727f4893121c208f80fa82589964970c5a01155ba1d24cfd7ebdb2a1d6e325ea5556f0747d16519631013315781ad1c178f8721e5eab77de2446b63
languageName: node
linkType: hard
"@sentry/types@npm:7.27.0, @sentry/types@npm:^7.16.0":
version: 7.27.0
resolution: "@sentry/types@npm:7.27.0"
@@ -1779,6 +1859,13 @@ __metadata:
languageName: node
linkType: hard
"@sentry/types@npm:7.28.1":
version: 7.28.1
resolution: "@sentry/types@npm:7.28.1"
checksum: 7dc6639cb7645c37bd8f759b60dbf2a149573b8a24dfb06baf7d7978f785e4635a65b3fb9e007f0eea56d33b543043fcfa1c1a376a83aa9824bb2d25be1a56dc
languageName: node
linkType: hard
"@sentry/utils@npm:7.27.0, @sentry/utils@npm:^7.16.0":
version: 7.27.0
resolution: "@sentry/utils@npm:7.27.0"
@@ -1789,6 +1876,34 @@ __metadata:
languageName: node
linkType: hard
"@sentry/utils@npm:7.28.1":
version: 7.28.1
resolution: "@sentry/utils@npm:7.28.1"
dependencies:
"@sentry/types": "npm:7.28.1"
tslib: "npm:^1.9.3"
checksum: a4b5f73db0e287e49b2eab5da80d6bbf1f6c7e11e1cc06ae06f49a9477d2b45de98310b143198207f3ae1fdd25ef76c90984eb99553a8308f6516e12c0c9c98c
languageName: node
linkType: hard
"@simplewebauthn/server@npm:^6.2.2":
version: 6.2.2
resolution: "@simplewebauthn/server@npm:6.2.2"
dependencies:
"@noble/ed25519": "npm:^1.6.1"
"@peculiar/asn1-android": "npm:^2.1.7"
"@peculiar/asn1-schema": "npm:^2.1.7"
"@peculiar/asn1-x509": "npm:^2.1.7"
base64url: "npm:^3.0.1"
cbor: "npm:^5.1.0"
debug: "npm:^4.3.2"
jsrsasign: "npm:^10.4.0"
jwk-to-pem: "npm:^2.0.4"
node-fetch: "npm:^2.6.0"
checksum: 5ffb9b1c15a69ca74c80adf70d890ba1e0bba21040653d79dc4a443d505aefe9d085763918e491479b0e64dd32c214c2acdc96d44de0384e542411944d01e09b
languageName: node
linkType: hard
"@sinclair/typebox@npm:^0.24.1":
version: 0.24.44
resolution: "@sinclair/typebox@npm:0.24.44"
@@ -1833,7 +1948,7 @@ __metadata:
resolution: "@standardnotes/analytics@workspace:packages/analytics"
dependencies:
"@newrelic/winston-enricher": "npm:^4.0.0"
"@sentry/node": "npm:^7.27.0"
"@sentry/node": "npm:^7.28.1"
"@standardnotes/common": "workspace:*"
"@standardnotes/domain-core": "workspace:^"
"@standardnotes/domain-events": "workspace:*"
@@ -1867,7 +1982,7 @@ __metadata:
resolution: "@standardnotes/api-gateway@workspace:packages/api-gateway"
dependencies:
"@newrelic/winston-enricher": "npm:^4.0.0"
"@sentry/node": "npm:^7.27.0"
"@sentry/node": "npm:^7.28.1"
"@standardnotes/common": "workspace:^"
"@standardnotes/domain-events": "workspace:*"
"@standardnotes/domain-events-infra": "workspace:*"
@@ -1925,9 +2040,10 @@ __metadata:
resolution: "@standardnotes/auth-server@workspace:packages/auth"
dependencies:
"@newrelic/winston-enricher": "npm:^4.0.0"
"@sentry/node": "npm:^7.27.0"
"@sentry/node": "npm:^7.28.1"
"@sentry/profiling-node": "npm:^0.0.12"
"@sentry/tracing": "npm:^7.27.0"
"@sentry/tracing": "npm:^7.28.1"
"@simplewebauthn/server": "npm:^6.2.2"
"@standardnotes/api": "npm:^1.19.0"
"@standardnotes/common": "workspace:*"
"@standardnotes/domain-core": "workspace:^"
@@ -2147,7 +2263,7 @@ __metadata:
version: 0.0.0-use.local
resolution: "@standardnotes/files-server@workspace:packages/files"
dependencies:
"@sentry/node": "npm:^7.27.0"
"@sentry/node": "npm:^7.28.1"
"@standardnotes/common": "workspace:*"
"@standardnotes/config": "npm:2.4.3"
"@standardnotes/domain-events": "workspace:*"
@@ -2277,7 +2393,7 @@ __metadata:
resolution: "@standardnotes/revisions-server@workspace:packages/revisions"
dependencies:
"@newrelic/winston-enricher": "npm:^4.0.0"
"@sentry/node": "npm:^7.27.0"
"@sentry/node": "npm:^7.28.1"
"@standardnotes/api": "npm:^1.19.0"
"@standardnotes/common": "workspace:^"
"@standardnotes/domain-core": "workspace:^"
@@ -2320,7 +2436,7 @@ __metadata:
resolution: "@standardnotes/scheduler-server@workspace:packages/scheduler"
dependencies:
"@newrelic/winston-enricher": "npm:^4.0.0"
"@sentry/node": "npm:^7.27.0"
"@sentry/node": "npm:^7.28.1"
"@standardnotes/common": "workspace:*"
"@standardnotes/domain-core": "workspace:^"
"@standardnotes/domain-events": "workspace:*"
@@ -2377,7 +2493,7 @@ __metadata:
"@lerna-lite/cli": "npm:^1.5.1"
"@lerna-lite/list": "npm:^1.5.1"
"@lerna-lite/run": "npm:^1.5.1"
"@sentry/node": "npm:^7.27.0"
"@sentry/node": "npm:^7.28.1"
"@types/jest": "npm:^29.1.1"
"@types/newrelic": "npm:^7.0.4"
"@types/node": "npm:^18.11.9"
@@ -2436,9 +2552,9 @@ __metadata:
resolution: "@standardnotes/syncing-server@workspace:packages/syncing-server"
dependencies:
"@newrelic/winston-enricher": "npm:^4.0.0"
"@sentry/node": "npm:^7.27.0"
"@sentry/node": "npm:^7.28.1"
"@sentry/profiling-node": "npm:^0.0.12"
"@sentry/tracing": "npm:^7.27.0"
"@sentry/tracing": "npm:^7.28.1"
"@standardnotes/common": "workspace:*"
"@standardnotes/domain-core": "workspace:^"
"@standardnotes/domain-events": "workspace:*"
@@ -2534,7 +2650,7 @@ __metadata:
resolution: "@standardnotes/websockets-server@workspace:packages/websockets"
dependencies:
"@newrelic/winston-enricher": "npm:^4.0.0"
"@sentry/node": "npm:^7.27.0"
"@sentry/node": "npm:^7.28.1"
"@standardnotes/api": "npm:^1.19.0"
"@standardnotes/common": "workspace:^"
"@standardnotes/domain-events": "workspace:^"
@@ -2572,7 +2688,7 @@ __metadata:
resolution: "@standardnotes/workspace-server@workspace:packages/workspace"
dependencies:
"@newrelic/winston-enricher": "npm:^4.0.0"
"@sentry/node": "npm:^7.27.0"
"@sentry/node": "npm:^7.28.1"
"@standardnotes/api": "npm:^1.19.0"
"@standardnotes/common": "workspace:*"
"@standardnotes/domain-core": "workspace:^"
@@ -3589,6 +3705,29 @@ __metadata:
languageName: node
linkType: hard
"asn1.js@npm:^5.3.0":
version: 5.4.1
resolution: "asn1.js@npm:5.4.1"
dependencies:
bn.js: "npm:^4.0.0"
inherits: "npm:^2.0.1"
minimalistic-assert: "npm:^1.0.0"
safer-buffer: "npm:^2.1.0"
checksum: 5c36f81388e344c9417866bd20acd2d4164d2bc2827d4fd0e35714f8701a249b9c6118c70720758fe710a4723d65699c5be1e827f89e9eff1dbd1bfe910300fd
languageName: node
linkType: hard
"asn1js@npm:^3.0.5":
version: 3.0.5
resolution: "asn1js@npm:3.0.5"
dependencies:
pvtsutils: "npm:^1.3.2"
pvutils: "npm:^1.1.3"
tslib: "npm:^2.4.0"
checksum: d0bc57da97696cbf161ad24cb35f9442b59a9e59a30f30e13ba6e2fb9e69f417666d952cb436a9f309a3c88d4d89404493dcc277a5fdb4d0cdbeb03da0303bb1
languageName: node
linkType: hard
"async@npm:^3.2.3, async@npm:^3.2.4":
version: 3.2.4
resolution: "async@npm:3.2.4"
@@ -3729,6 +3868,13 @@ __metadata:
languageName: node
linkType: hard
"base64url@npm:^3.0.1":
version: 3.0.1
resolution: "base64url@npm:3.0.1"
checksum: 72e1401ffe08693524f35bc2912a519bb3bf58f8911f3c4045d8c4bb6b5112187eae2eb45db895f464debe3ff562d46b76305e7cc4de4857365c47f73442c228
languageName: node
linkType: hard
"bcryptjs@npm:2.4.3":
version: 2.4.3
resolution: "bcryptjs@npm:2.4.3"
@@ -3743,6 +3889,13 @@ __metadata:
languageName: node
linkType: hard
"bignumber.js@npm:^9.0.1":
version: 9.1.1
resolution: "bignumber.js@npm:9.1.1"
checksum: e44d00804916c299d01e1a83b435111dbced54c6f165df4a0034a8a0a27182d6698f93f408ec804b3ae80896fd6ad8ad43f37939883dc03ecd04a125742f1483
languageName: node
linkType: hard
"binary-extensions@npm:^2.0.0":
version: 2.2.0
resolution: "binary-extensions@npm:2.2.0"
@@ -3761,6 +3914,13 @@ __metadata:
languageName: node
linkType: hard
"bn.js@npm:^4.0.0, bn.js@npm:^4.11.9":
version: 4.12.0
resolution: "bn.js@npm:4.12.0"
checksum: bfb4590775a29dad10c8d42da5ba7fca9d4f796f6d278cb27f53c6a6272df5e58a3ca58d879487c9584db9e7a8f73ac843117183bebea2d627c1f0db95848ec8
languageName: node
linkType: hard
"body-parser@npm:1.20.1":
version: 1.20.1
resolution: "body-parser@npm:1.20.1"
@@ -3825,6 +3985,13 @@ __metadata:
languageName: node
linkType: hard
"brorand@npm:^1.1.0":
version: 1.1.0
resolution: "brorand@npm:1.1.0"
checksum: f736e127fbac2d704b0b55935c297ec261112b93a178e15170da19c17500d448ebacff3b1edb075821363e8daecc739c062b40e920aa19b8cbed7f4fbe1ff6aa
languageName: node
linkType: hard
"browserslist@npm:^4.20.2":
version: 4.21.1
resolution: "browserslist@npm:4.21.1"
@@ -4038,6 +4205,16 @@ __metadata:
languageName: node
linkType: hard
"cbor@npm:^5.1.0":
version: 5.2.0
resolution: "cbor@npm:5.2.0"
dependencies:
bignumber.js: "npm:^9.0.1"
nofilter: "npm:^1.0.4"
checksum: d60986b9d006dd60e462293629830afe2db89db6a06ee2665ac59618b7a76af5e8cef880e4eb484345c8e978fa8425b1cf1e5f3840b97f39ad9e3d2fa8f28bc6
languageName: node
linkType: hard
"chalk@npm:^2.0.0, chalk@npm:^2.4.2":
version: 2.4.2
resolution: "chalk@npm:2.4.2"
@@ -4983,6 +5160,21 @@ __metadata:
languageName: node
linkType: hard
"elliptic@npm:^6.5.4":
version: 6.5.4
resolution: "elliptic@npm:6.5.4"
dependencies:
bn.js: "npm:^4.11.9"
brorand: "npm:^1.1.0"
hash.js: "npm:^1.0.0"
hmac-drbg: "npm:^1.0.1"
inherits: "npm:^2.0.4"
minimalistic-assert: "npm:^1.0.1"
minimalistic-crypto-utils: "npm:^1.0.1"
checksum: 4453b008cf9e741a87f8e1935398c10124291026e7f2b99a512205a645c59586deaeefbb1e7149574481ec2c4cc7f34efc6ae6ae5bc35a94431be71c0375367e
languageName: node
linkType: hard
"emittery@npm:^0.10.2":
version: 0.10.2
resolution: "emittery@npm:0.10.2"
@@ -6232,6 +6424,16 @@ __metadata:
languageName: node
linkType: hard
"hash.js@npm:^1.0.0, hash.js@npm:^1.0.3":
version: 1.1.7
resolution: "hash.js@npm:1.1.7"
dependencies:
inherits: "npm:^2.0.3"
minimalistic-assert: "npm:^1.0.1"
checksum: e4266370d194fd31ed7bb51f5a943cf4e3b361321ea19a0dfcaab2e21400c3e581d8dec897364ed4530845c2c1b58d44dd6a9b3682cfd5ec02d0ce7bc802f1db
languageName: node
linkType: hard
"helmet@npm:^6.0.0":
version: 6.0.0
resolution: "helmet@npm:6.0.0"
@@ -6246,6 +6448,17 @@ __metadata:
languageName: node
linkType: hard
"hmac-drbg@npm:^1.0.1":
version: 1.0.1
resolution: "hmac-drbg@npm:1.0.1"
dependencies:
hash.js: "npm:^1.0.3"
minimalistic-assert: "npm:^1.0.0"
minimalistic-crypto-utils: "npm:^1.0.1"
checksum: 4e88d58ffc03e027990bbc31c0aa7b90dc4d2b3642ac3a8f3b71e3c43eb03416179ac601f36417312f0375cc382a9e39d80ade1ae239aff188701162bc84226d
languageName: node
linkType: hard
"hosted-git-info@npm:^2.1.4":
version: 2.8.9
resolution: "hosted-git-info@npm:2.8.9"
@@ -6585,6 +6798,13 @@ __metadata:
languageName: node
linkType: hard
"ipaddr.js@npm:^2.0.1":
version: 2.0.1
resolution: "ipaddr.js@npm:2.0.1"
checksum: 04ce6c896c82b163a87d0be70fa1701dda54f1315f27419207c9ea95bea025cacbe6335d5e0c1270657158f60d17eeaa0bbb19b60e230e34532adfca786c6dc7
languageName: node
linkType: hard
"is-arguments@npm:^1.0.4":
version: 1.1.1
resolution: "is-arguments@npm:1.1.1"
@@ -7609,6 +7829,13 @@ __metadata:
languageName: node
linkType: hard
"jsrsasign@npm:^10.4.0":
version: 10.6.1
resolution: "jsrsasign@npm:10.6.1"
checksum: e8e9c1b24f78d506eccd3b0e68e6e9dc8011f2ca4bd5baedc33a3a64b63c5ff7e21d00a73ef95624fd9fd594743cc6dd60b39b17d6938c7a6a712242698bac14
languageName: node
linkType: hard
"jwa@npm:^1.4.1":
version: 1.4.1
resolution: "jwa@npm:1.4.1"
@@ -7620,6 +7847,17 @@ __metadata:
languageName: node
linkType: hard
"jwk-to-pem@npm:^2.0.4":
version: 2.0.5
resolution: "jwk-to-pem@npm:2.0.5"
dependencies:
asn1.js: "npm:^5.3.0"
elliptic: "npm:^6.5.4"
safe-buffer: "npm:^5.0.1"
checksum: fced3a75b0fcc6145e703669e210b670789df5d85dbcbf11d3f97e2bb24954e70e889b69ddb1c6404089ae45c435a9bf09137dfd0290931b49c8ccd09fa5e704
languageName: node
linkType: hard
"jws@npm:^3.2.2":
version: 3.2.2
resolution: "jws@npm:3.2.2"
@@ -8154,6 +8392,20 @@ __metadata:
languageName: node
linkType: hard
"minimalistic-assert@npm:^1.0.0, minimalistic-assert@npm:^1.0.1":
version: 1.0.1
resolution: "minimalistic-assert@npm:1.0.1"
checksum: e2310081d82a7f8a6ee7f338d167c82b3eb5378929b9eda3a9eb633cf0f0f19c029b69e6868264447d4f726644b52fdc4dda3bc985793a1aeba9b02b13ca3f8e
languageName: node
linkType: hard
"minimalistic-crypto-utils@npm:^1.0.1":
version: 1.0.1
resolution: "minimalistic-crypto-utils@npm:1.0.1"
checksum: 7d909decd241bd658f941981ce53db4061c834daba807a5082d08fd2a0c488b8ef67904c90af38b70445e0220951a533ae3a181be5724ad342df4d9454286476
languageName: node
linkType: hard
"minimatch@npm:^3.0.4, minimatch@npm:^3.1.1, minimatch@npm:^3.1.2":
version: 3.1.2
resolution: "minimatch@npm:3.1.2"
@@ -8446,7 +8698,7 @@ __metadata:
languageName: node
linkType: hard
"node-fetch@npm:^2.6.7":
"node-fetch@npm:^2.6.0, node-fetch@npm:^2.6.7":
version: 2.6.7
resolution: "node-fetch@npm:2.6.7"
dependencies:
@@ -8545,6 +8797,13 @@ __metadata:
languageName: node
linkType: hard
"nofilter@npm:^1.0.4":
version: 1.0.4
resolution: "nofilter@npm:1.0.4"
checksum: 9a26874e7d5505acbee413d33311ed6d934ff2695e021b1ea1c9f83adc02e6e8038ed2702fcbcfc022bcf5a10cae6e79c6ad7ec23ecb512cdbfa7994fef6532f
languageName: node
linkType: hard
"nopt@npm:^5.0.0":
version: 5.0.0
resolution: "nopt@npm:5.0.0"
@@ -9499,6 +9758,22 @@ __metadata:
languageName: node
linkType: hard
"pvtsutils@npm:^1.3.2":
version: 1.3.2
resolution: "pvtsutils@npm:1.3.2"
dependencies:
tslib: "npm:^2.4.0"
checksum: eb22d3df60a341da289c59b2a34e4e55cadc70bd43caeb5fdd14d28e40f54112142e0e8bd5906f3d756e2c38b651599243def3ced6f1169335feb7933e210fa7
languageName: node
linkType: hard
"pvutils@npm:^1.1.3":
version: 1.1.3
resolution: "pvutils@npm:1.1.3"
checksum: 0cb4f4878f535b07ad409df26b4e724582a50cc9ddd71375cc8d79dc79b9d712dcc0cbe52f4385c27abe6887aa88a94c98377746d95f35a88f96ebb8a585814c
languageName: node
linkType: hard
"q@npm:^1.5.1":
version: 1.5.1
resolution: "q@npm:1.5.1"
@@ -9978,7 +10253,7 @@ __metadata:
languageName: node
linkType: hard
"safer-buffer@npm:>= 2.1.2 < 3, safer-buffer@npm:>= 2.1.2 < 3.0.0":
"safer-buffer@npm:>= 2.1.2 < 3, safer-buffer@npm:>= 2.1.2 < 3.0.0, safer-buffer@npm:^2.1.0":
version: 2.1.2
resolution: "safer-buffer@npm:2.1.2"
checksum: d4199666e9e792968c0b88c2c35dd400f56d3eecb9affbcf5207922822eadf30cc06995bae3c5d0a653851bbd40fc0af578bf046bbf734199ce22433ba4da659
@@ -10948,6 +11223,13 @@ __metadata:
languageName: node
linkType: hard
"tslib@npm:^2.4.0":
version: 2.4.1
resolution: "tslib@npm:2.4.1"
checksum: a739a21e3ff059e62c7c3c0845333fbc9c081bcc91e015f2d246a31eeaf1fb0e29b10c0913c7d22f692b3203bb469fd60ca5288aa4f27d351a969df2d0714899
languageName: node
linkType: hard
"tsutils@npm:^3.21.0":
version: 3.21.0
resolution: "tsutils@npm:3.21.0"