mirror of
https://github.com/standardnotes/server
synced 2026-04-19 08:02:23 -04:00
Compare commits
58 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 10832f7001 | |||
| 86b050865f | |||
| 6f07aaf87a | |||
| 634e8bd2d0 | |||
| 6853dfbf66 | |||
| 136cf252a1 | |||
| cad28ebba5 | |||
| 460fdf9eaf | |||
| bec1b502ad | |||
| 70bbf11db5 | |||
| c00c7becae | |||
| 89dc6c19bf | |||
| 972a91d59f | |||
| 045358ddbf | |||
| c7217a92ba | |||
| 3da7a21cde | |||
| 351e18f638 | |||
| 4f2129c4e0 | |||
| d7a1c667dd | |||
| 4de0bfa36d | |||
| 0443de88ce | |||
| f830bac873 | |||
| 517ae5ded9 | |||
| 6062f85000 | |||
| e2205c3849 | |||
| 0b46eff16e | |||
| df67982bca | |||
| d44866b3c0 | |||
| 6ee18bffe6 | |||
| a881dd2d79 | |||
| b767e1f072 | |||
| e3cb1faba4 | |||
| 5c5f988055 | |||
| c7d2adf091 | |||
| a4ad37f309 | |||
| 73c2cc1222 | |||
| 9380900aaf | |||
| 02f4d5c717 | |||
| 1f4b26d269 | |||
| e253825da6 | |||
| 2bddd947ba | |||
| b7173346d2 | |||
| 01641975c0 | |||
| 7abd80cdba | |||
| aeb5ea1874 | |||
| d2a371b92c | |||
| 3ea3b24bb6 | |||
| 0c3bc0cae6 | |||
| d56410984a | |||
| 4dd2eb9349 | |||
| 709aec5eeb | |||
| f1aa431c22 | |||
| 86d0e565ed | |||
| 92bb447cac | |||
| 08966e7af7 | |||
| 2c732ff713 | |||
| 1493b7c478 | |||
| efd816a627 |
+1
-1
@@ -27,4 +27,4 @@ AUTH_JWT_SECRET=f95259c5e441f5a4646d76422cfb3df4c4488842901aa50b6c51b8be2e0040e9
|
||||
AUTH_SERVER_ENCRYPTION_SERVER_KEY=1087415dfde3093797f9a7ca93a49e7d7aa1861735eb0d32aae9c303b8c3d060
|
||||
VALET_TOKEN_SECRET=4b886819ebe1e908077c6cae96311b48a8416bd60cc91c03060e15bdf6b30d1f
|
||||
|
||||
SYNCING_SERVER_CONTENT_SIZE_TRANSFER_LIMIT=1000000
|
||||
SYNCING_SERVER_CONTENT_SIZE_TRANSFER_LIMIT=100000
|
||||
|
||||
@@ -70,7 +70,7 @@ jobs:
|
||||
echo "ACCESS_TOKEN_AGE=4" >> packages/home-server/.env
|
||||
echo "REFRESH_TOKEN_AGE=10" >> packages/home-server/.env
|
||||
echo "REVISIONS_FREQUENCY=2" >> packages/home-server/.env
|
||||
echo "CONTENT_SIZE_TRANSFER_LIMIT=1000000" >> packages/home-server/.env
|
||||
echo "CONTENT_SIZE_TRANSFER_LIMIT=100000" >> packages/home-server/.env
|
||||
echo "DB_HOST=localhost" >> packages/home-server/.env
|
||||
echo "DB_PORT=3306" >> packages/home-server/.env
|
||||
echo "DB_DATABASE=standardnotes" >> packages/home-server/.env
|
||||
|
||||
@@ -300,6 +300,57 @@ const RAW_RUNTIME_STATE =
|
||||
"linkType": "HARD"\
|
||||
}]\
|
||||
]],\
|
||||
["@aws-sdk/client-cloudwatch", [\
|
||||
["npm:3.485.0", {\
|
||||
"packageLocation": "./.yarn/cache/@aws-sdk-client-cloudwatch-npm-3.485.0-afe4ac001f-0e02739ef1.zip/node_modules/@aws-sdk/client-cloudwatch/",\
|
||||
"packageDependencies": [\
|
||||
["@aws-sdk/client-cloudwatch", "npm:3.485.0"],\
|
||||
["@aws-crypto/sha256-browser", "npm:3.0.0"],\
|
||||
["@aws-crypto/sha256-js", "npm:3.0.0"],\
|
||||
["@aws-sdk/client-sts", "npm:3.485.0"],\
|
||||
["@aws-sdk/core", "npm:3.485.0"],\
|
||||
["@aws-sdk/credential-provider-node", "npm:3.485.0"],\
|
||||
["@aws-sdk/middleware-host-header", "npm:3.485.0"],\
|
||||
["@aws-sdk/middleware-logger", "npm:3.485.0"],\
|
||||
["@aws-sdk/middleware-recursion-detection", "npm:3.485.0"],\
|
||||
["@aws-sdk/middleware-signing", "npm:3.485.0"],\
|
||||
["@aws-sdk/middleware-user-agent", "npm:3.485.0"],\
|
||||
["@aws-sdk/region-config-resolver", "npm:3.485.0"],\
|
||||
["@aws-sdk/types", "npm:3.485.0"],\
|
||||
["@aws-sdk/util-endpoints", "npm:3.485.0"],\
|
||||
["@aws-sdk/util-user-agent-browser", "npm:3.485.0"],\
|
||||
["@aws-sdk/util-user-agent-node", "virtual:5f6733bd23aee10dd05576af160f1b93e0bb4a20b288e9b818dc0b69bdb08ea1a09d5836816f02bdafc9c01487816ae339c6b680c2f7849dfe249436c5f2b499#npm:3.485.0"],\
|
||||
["@smithy/config-resolver", "npm:2.0.23"],\
|
||||
["@smithy/core", "npm:1.2.2"],\
|
||||
["@smithy/fetch-http-handler", "npm:2.3.2"],\
|
||||
["@smithy/hash-node", "npm:2.0.18"],\
|
||||
["@smithy/invalid-dependency", "npm:2.0.16"],\
|
||||
["@smithy/middleware-content-length", "npm:2.0.18"],\
|
||||
["@smithy/middleware-endpoint", "npm:2.3.0"],\
|
||||
["@smithy/middleware-retry", "npm:2.0.26"],\
|
||||
["@smithy/middleware-serde", "npm:2.0.16"],\
|
||||
["@smithy/middleware-stack", "npm:2.0.10"],\
|
||||
["@smithy/node-config-provider", "npm:2.1.9"],\
|
||||
["@smithy/node-http-handler", "npm:2.2.2"],\
|
||||
["@smithy/protocol-http", "npm:3.0.12"],\
|
||||
["@smithy/smithy-client", "npm:2.2.1"],\
|
||||
["@smithy/types", "npm:2.8.0"],\
|
||||
["@smithy/url-parser", "npm:2.0.16"],\
|
||||
["@smithy/util-base64", "npm:2.0.1"],\
|
||||
["@smithy/util-body-length-browser", "npm:2.0.1"],\
|
||||
["@smithy/util-body-length-node", "npm:2.1.0"],\
|
||||
["@smithy/util-defaults-mode-browser", "npm:2.0.24"],\
|
||||
["@smithy/util-defaults-mode-node", "npm:2.0.32"],\
|
||||
["@smithy/util-endpoints", "npm:1.0.8"],\
|
||||
["@smithy/util-retry", "npm:2.0.9"],\
|
||||
["@smithy/util-utf8", "npm:2.0.2"],\
|
||||
["@smithy/util-waiter", "npm:2.0.16"],\
|
||||
["fast-xml-parser", "npm:4.2.5"],\
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}]\
|
||||
]],\
|
||||
["@aws-sdk/client-s3", [\
|
||||
["npm:3.484.0", {\
|
||||
"packageLocation": "./.yarn/cache/@aws-sdk-client-s3-npm-3.484.0-681638ab7a-701523f3b3.zip/node_modules/@aws-sdk/client-s3/",\
|
||||
@@ -415,6 +466,54 @@ const RAW_RUNTIME_STATE =
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}],\
|
||||
["npm:3.490.0", {\
|
||||
"packageLocation": "./.yarn/cache/@aws-sdk-client-sns-npm-3.490.0-2cd839225d-4d8875521c.zip/node_modules/@aws-sdk/client-sns/",\
|
||||
"packageDependencies": [\
|
||||
["@aws-sdk/client-sns", "npm:3.490.0"],\
|
||||
["@aws-crypto/sha256-browser", "npm:3.0.0"],\
|
||||
["@aws-crypto/sha256-js", "npm:3.0.0"],\
|
||||
["@aws-sdk/client-sts", "npm:3.490.0"],\
|
||||
["@aws-sdk/core", "npm:3.490.0"],\
|
||||
["@aws-sdk/credential-provider-node", "npm:3.490.0"],\
|
||||
["@aws-sdk/middleware-host-header", "npm:3.489.0"],\
|
||||
["@aws-sdk/middleware-logger", "npm:3.489.0"],\
|
||||
["@aws-sdk/middleware-recursion-detection", "npm:3.489.0"],\
|
||||
["@aws-sdk/middleware-signing", "npm:3.489.0"],\
|
||||
["@aws-sdk/middleware-user-agent", "npm:3.489.0"],\
|
||||
["@aws-sdk/region-config-resolver", "npm:3.489.0"],\
|
||||
["@aws-sdk/types", "npm:3.489.0"],\
|
||||
["@aws-sdk/util-endpoints", "npm:3.489.0"],\
|
||||
["@aws-sdk/util-user-agent-browser", "npm:3.489.0"],\
|
||||
["@aws-sdk/util-user-agent-node", "virtual:26ec4a89785e0643103d1dd3b2a86d8c63d7fd76dbfb0e516f1dc429fef4581a7306b382504a8b85e8fb995888356d6341786deec607cb64b29957c728540295#npm:3.489.0"],\
|
||||
["@smithy/config-resolver", "npm:2.0.23"],\
|
||||
["@smithy/core", "npm:1.2.2"],\
|
||||
["@smithy/fetch-http-handler", "npm:2.3.2"],\
|
||||
["@smithy/hash-node", "npm:2.0.18"],\
|
||||
["@smithy/invalid-dependency", "npm:2.0.16"],\
|
||||
["@smithy/middleware-content-length", "npm:2.0.18"],\
|
||||
["@smithy/middleware-endpoint", "npm:2.3.0"],\
|
||||
["@smithy/middleware-retry", "npm:2.0.26"],\
|
||||
["@smithy/middleware-serde", "npm:2.0.16"],\
|
||||
["@smithy/middleware-stack", "npm:2.0.10"],\
|
||||
["@smithy/node-config-provider", "npm:2.1.9"],\
|
||||
["@smithy/node-http-handler", "npm:2.2.2"],\
|
||||
["@smithy/protocol-http", "npm:3.0.12"],\
|
||||
["@smithy/smithy-client", "npm:2.2.1"],\
|
||||
["@smithy/types", "npm:2.8.0"],\
|
||||
["@smithy/url-parser", "npm:2.0.16"],\
|
||||
["@smithy/util-base64", "npm:2.0.1"],\
|
||||
["@smithy/util-body-length-browser", "npm:2.0.1"],\
|
||||
["@smithy/util-body-length-node", "npm:2.1.0"],\
|
||||
["@smithy/util-defaults-mode-browser", "npm:2.0.24"],\
|
||||
["@smithy/util-defaults-mode-node", "npm:2.0.32"],\
|
||||
["@smithy/util-endpoints", "npm:1.0.8"],\
|
||||
["@smithy/util-retry", "npm:2.0.9"],\
|
||||
["@smithy/util-utf8", "npm:2.0.2"],\
|
||||
["fast-xml-parser", "npm:4.2.5"],\
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}]\
|
||||
]],\
|
||||
["@aws-sdk/client-sqs", [\
|
||||
@@ -512,6 +611,94 @@ const RAW_RUNTIME_STATE =
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}],\
|
||||
["npm:3.485.0", {\
|
||||
"packageLocation": "./.yarn/cache/@aws-sdk-client-sso-npm-3.485.0-5f6733bd23-635de0e310.zip/node_modules/@aws-sdk/client-sso/",\
|
||||
"packageDependencies": [\
|
||||
["@aws-sdk/client-sso", "npm:3.485.0"],\
|
||||
["@aws-crypto/sha256-browser", "npm:3.0.0"],\
|
||||
["@aws-crypto/sha256-js", "npm:3.0.0"],\
|
||||
["@aws-sdk/core", "npm:3.485.0"],\
|
||||
["@aws-sdk/middleware-host-header", "npm:3.485.0"],\
|
||||
["@aws-sdk/middleware-logger", "npm:3.485.0"],\
|
||||
["@aws-sdk/middleware-recursion-detection", "npm:3.485.0"],\
|
||||
["@aws-sdk/middleware-user-agent", "npm:3.485.0"],\
|
||||
["@aws-sdk/region-config-resolver", "npm:3.485.0"],\
|
||||
["@aws-sdk/types", "npm:3.485.0"],\
|
||||
["@aws-sdk/util-endpoints", "npm:3.485.0"],\
|
||||
["@aws-sdk/util-user-agent-browser", "npm:3.485.0"],\
|
||||
["@aws-sdk/util-user-agent-node", "virtual:5f6733bd23aee10dd05576af160f1b93e0bb4a20b288e9b818dc0b69bdb08ea1a09d5836816f02bdafc9c01487816ae339c6b680c2f7849dfe249436c5f2b499#npm:3.485.0"],\
|
||||
["@smithy/config-resolver", "npm:2.0.23"],\
|
||||
["@smithy/core", "npm:1.2.2"],\
|
||||
["@smithy/fetch-http-handler", "npm:2.3.2"],\
|
||||
["@smithy/hash-node", "npm:2.0.18"],\
|
||||
["@smithy/invalid-dependency", "npm:2.0.16"],\
|
||||
["@smithy/middleware-content-length", "npm:2.0.18"],\
|
||||
["@smithy/middleware-endpoint", "npm:2.3.0"],\
|
||||
["@smithy/middleware-retry", "npm:2.0.26"],\
|
||||
["@smithy/middleware-serde", "npm:2.0.16"],\
|
||||
["@smithy/middleware-stack", "npm:2.0.10"],\
|
||||
["@smithy/node-config-provider", "npm:2.1.9"],\
|
||||
["@smithy/node-http-handler", "npm:2.2.2"],\
|
||||
["@smithy/protocol-http", "npm:3.0.12"],\
|
||||
["@smithy/smithy-client", "npm:2.2.1"],\
|
||||
["@smithy/types", "npm:2.8.0"],\
|
||||
["@smithy/url-parser", "npm:2.0.16"],\
|
||||
["@smithy/util-base64", "npm:2.0.1"],\
|
||||
["@smithy/util-body-length-browser", "npm:2.0.1"],\
|
||||
["@smithy/util-body-length-node", "npm:2.1.0"],\
|
||||
["@smithy/util-defaults-mode-browser", "npm:2.0.24"],\
|
||||
["@smithy/util-defaults-mode-node", "npm:2.0.32"],\
|
||||
["@smithy/util-endpoints", "npm:1.0.8"],\
|
||||
["@smithy/util-retry", "npm:2.0.9"],\
|
||||
["@smithy/util-utf8", "npm:2.0.2"],\
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}],\
|
||||
["npm:3.490.0", {\
|
||||
"packageLocation": "./.yarn/cache/@aws-sdk-client-sso-npm-3.490.0-26ec4a8978-785147e3c2.zip/node_modules/@aws-sdk/client-sso/",\
|
||||
"packageDependencies": [\
|
||||
["@aws-sdk/client-sso", "npm:3.490.0"],\
|
||||
["@aws-crypto/sha256-browser", "npm:3.0.0"],\
|
||||
["@aws-crypto/sha256-js", "npm:3.0.0"],\
|
||||
["@aws-sdk/core", "npm:3.490.0"],\
|
||||
["@aws-sdk/middleware-host-header", "npm:3.489.0"],\
|
||||
["@aws-sdk/middleware-logger", "npm:3.489.0"],\
|
||||
["@aws-sdk/middleware-recursion-detection", "npm:3.489.0"],\
|
||||
["@aws-sdk/middleware-user-agent", "npm:3.489.0"],\
|
||||
["@aws-sdk/region-config-resolver", "npm:3.489.0"],\
|
||||
["@aws-sdk/types", "npm:3.489.0"],\
|
||||
["@aws-sdk/util-endpoints", "npm:3.489.0"],\
|
||||
["@aws-sdk/util-user-agent-browser", "npm:3.489.0"],\
|
||||
["@aws-sdk/util-user-agent-node", "virtual:26ec4a89785e0643103d1dd3b2a86d8c63d7fd76dbfb0e516f1dc429fef4581a7306b382504a8b85e8fb995888356d6341786deec607cb64b29957c728540295#npm:3.489.0"],\
|
||||
["@smithy/config-resolver", "npm:2.0.23"],\
|
||||
["@smithy/core", "npm:1.2.2"],\
|
||||
["@smithy/fetch-http-handler", "npm:2.3.2"],\
|
||||
["@smithy/hash-node", "npm:2.0.18"],\
|
||||
["@smithy/invalid-dependency", "npm:2.0.16"],\
|
||||
["@smithy/middleware-content-length", "npm:2.0.18"],\
|
||||
["@smithy/middleware-endpoint", "npm:2.3.0"],\
|
||||
["@smithy/middleware-retry", "npm:2.0.26"],\
|
||||
["@smithy/middleware-serde", "npm:2.0.16"],\
|
||||
["@smithy/middleware-stack", "npm:2.0.10"],\
|
||||
["@smithy/node-config-provider", "npm:2.1.9"],\
|
||||
["@smithy/node-http-handler", "npm:2.2.2"],\
|
||||
["@smithy/protocol-http", "npm:3.0.12"],\
|
||||
["@smithy/smithy-client", "npm:2.2.1"],\
|
||||
["@smithy/types", "npm:2.8.0"],\
|
||||
["@smithy/url-parser", "npm:2.0.16"],\
|
||||
["@smithy/util-base64", "npm:2.0.1"],\
|
||||
["@smithy/util-body-length-browser", "npm:2.0.1"],\
|
||||
["@smithy/util-body-length-node", "npm:2.1.0"],\
|
||||
["@smithy/util-defaults-mode-browser", "npm:2.0.24"],\
|
||||
["@smithy/util-defaults-mode-node", "npm:2.0.32"],\
|
||||
["@smithy/util-endpoints", "npm:1.0.8"],\
|
||||
["@smithy/util-retry", "npm:2.0.9"],\
|
||||
["@smithy/util-utf8", "npm:2.0.2"],\
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}]\
|
||||
]],\
|
||||
["@aws-sdk/client-sts", [\
|
||||
@@ -561,6 +748,100 @@ const RAW_RUNTIME_STATE =
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}],\
|
||||
["npm:3.485.0", {\
|
||||
"packageLocation": "./.yarn/cache/@aws-sdk-client-sts-npm-3.485.0-cc69ab3505-98c7f4d722.zip/node_modules/@aws-sdk/client-sts/",\
|
||||
"packageDependencies": [\
|
||||
["@aws-sdk/client-sts", "npm:3.485.0"],\
|
||||
["@aws-crypto/sha256-browser", "npm:3.0.0"],\
|
||||
["@aws-crypto/sha256-js", "npm:3.0.0"],\
|
||||
["@aws-sdk/core", "npm:3.485.0"],\
|
||||
["@aws-sdk/credential-provider-node", "npm:3.485.0"],\
|
||||
["@aws-sdk/middleware-host-header", "npm:3.485.0"],\
|
||||
["@aws-sdk/middleware-logger", "npm:3.485.0"],\
|
||||
["@aws-sdk/middleware-recursion-detection", "npm:3.485.0"],\
|
||||
["@aws-sdk/middleware-user-agent", "npm:3.485.0"],\
|
||||
["@aws-sdk/region-config-resolver", "npm:3.485.0"],\
|
||||
["@aws-sdk/types", "npm:3.485.0"],\
|
||||
["@aws-sdk/util-endpoints", "npm:3.485.0"],\
|
||||
["@aws-sdk/util-user-agent-browser", "npm:3.485.0"],\
|
||||
["@aws-sdk/util-user-agent-node", "virtual:5f6733bd23aee10dd05576af160f1b93e0bb4a20b288e9b818dc0b69bdb08ea1a09d5836816f02bdafc9c01487816ae339c6b680c2f7849dfe249436c5f2b499#npm:3.485.0"],\
|
||||
["@smithy/config-resolver", "npm:2.0.23"],\
|
||||
["@smithy/core", "npm:1.2.2"],\
|
||||
["@smithy/fetch-http-handler", "npm:2.3.2"],\
|
||||
["@smithy/hash-node", "npm:2.0.18"],\
|
||||
["@smithy/invalid-dependency", "npm:2.0.16"],\
|
||||
["@smithy/middleware-content-length", "npm:2.0.18"],\
|
||||
["@smithy/middleware-endpoint", "npm:2.3.0"],\
|
||||
["@smithy/middleware-retry", "npm:2.0.26"],\
|
||||
["@smithy/middleware-serde", "npm:2.0.16"],\
|
||||
["@smithy/middleware-stack", "npm:2.0.10"],\
|
||||
["@smithy/node-config-provider", "npm:2.1.9"],\
|
||||
["@smithy/node-http-handler", "npm:2.2.2"],\
|
||||
["@smithy/protocol-http", "npm:3.0.12"],\
|
||||
["@smithy/smithy-client", "npm:2.2.1"],\
|
||||
["@smithy/types", "npm:2.8.0"],\
|
||||
["@smithy/url-parser", "npm:2.0.16"],\
|
||||
["@smithy/util-base64", "npm:2.0.1"],\
|
||||
["@smithy/util-body-length-browser", "npm:2.0.1"],\
|
||||
["@smithy/util-body-length-node", "npm:2.1.0"],\
|
||||
["@smithy/util-defaults-mode-browser", "npm:2.0.24"],\
|
||||
["@smithy/util-defaults-mode-node", "npm:2.0.32"],\
|
||||
["@smithy/util-endpoints", "npm:1.0.8"],\
|
||||
["@smithy/util-middleware", "npm:2.0.9"],\
|
||||
["@smithy/util-retry", "npm:2.0.9"],\
|
||||
["@smithy/util-utf8", "npm:2.0.2"],\
|
||||
["fast-xml-parser", "npm:4.2.5"],\
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}],\
|
||||
["npm:3.490.0", {\
|
||||
"packageLocation": "./.yarn/cache/@aws-sdk-client-sts-npm-3.490.0-f3cd7f7c70-19d1b98694.zip/node_modules/@aws-sdk/client-sts/",\
|
||||
"packageDependencies": [\
|
||||
["@aws-sdk/client-sts", "npm:3.490.0"],\
|
||||
["@aws-crypto/sha256-browser", "npm:3.0.0"],\
|
||||
["@aws-crypto/sha256-js", "npm:3.0.0"],\
|
||||
["@aws-sdk/core", "npm:3.490.0"],\
|
||||
["@aws-sdk/credential-provider-node", "npm:3.490.0"],\
|
||||
["@aws-sdk/middleware-host-header", "npm:3.489.0"],\
|
||||
["@aws-sdk/middleware-logger", "npm:3.489.0"],\
|
||||
["@aws-sdk/middleware-recursion-detection", "npm:3.489.0"],\
|
||||
["@aws-sdk/middleware-user-agent", "npm:3.489.0"],\
|
||||
["@aws-sdk/region-config-resolver", "npm:3.489.0"],\
|
||||
["@aws-sdk/types", "npm:3.489.0"],\
|
||||
["@aws-sdk/util-endpoints", "npm:3.489.0"],\
|
||||
["@aws-sdk/util-user-agent-browser", "npm:3.489.0"],\
|
||||
["@aws-sdk/util-user-agent-node", "virtual:26ec4a89785e0643103d1dd3b2a86d8c63d7fd76dbfb0e516f1dc429fef4581a7306b382504a8b85e8fb995888356d6341786deec607cb64b29957c728540295#npm:3.489.0"],\
|
||||
["@smithy/config-resolver", "npm:2.0.23"],\
|
||||
["@smithy/core", "npm:1.2.2"],\
|
||||
["@smithy/fetch-http-handler", "npm:2.3.2"],\
|
||||
["@smithy/hash-node", "npm:2.0.18"],\
|
||||
["@smithy/invalid-dependency", "npm:2.0.16"],\
|
||||
["@smithy/middleware-content-length", "npm:2.0.18"],\
|
||||
["@smithy/middleware-endpoint", "npm:2.3.0"],\
|
||||
["@smithy/middleware-retry", "npm:2.0.26"],\
|
||||
["@smithy/middleware-serde", "npm:2.0.16"],\
|
||||
["@smithy/middleware-stack", "npm:2.0.10"],\
|
||||
["@smithy/node-config-provider", "npm:2.1.9"],\
|
||||
["@smithy/node-http-handler", "npm:2.2.2"],\
|
||||
["@smithy/protocol-http", "npm:3.0.12"],\
|
||||
["@smithy/smithy-client", "npm:2.2.1"],\
|
||||
["@smithy/types", "npm:2.8.0"],\
|
||||
["@smithy/url-parser", "npm:2.0.16"],\
|
||||
["@smithy/util-base64", "npm:2.0.1"],\
|
||||
["@smithy/util-body-length-browser", "npm:2.0.1"],\
|
||||
["@smithy/util-body-length-node", "npm:2.1.0"],\
|
||||
["@smithy/util-defaults-mode-browser", "npm:2.0.24"],\
|
||||
["@smithy/util-defaults-mode-node", "npm:2.0.32"],\
|
||||
["@smithy/util-endpoints", "npm:1.0.8"],\
|
||||
["@smithy/util-middleware", "npm:2.0.9"],\
|
||||
["@smithy/util-retry", "npm:2.0.9"],\
|
||||
["@smithy/util-utf8", "npm:2.0.2"],\
|
||||
["fast-xml-parser", "npm:4.2.5"],\
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}]\
|
||||
]],\
|
||||
["@aws-sdk/core", [\
|
||||
@@ -576,6 +857,32 @@ const RAW_RUNTIME_STATE =
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}],\
|
||||
["npm:3.485.0", {\
|
||||
"packageLocation": "./.yarn/cache/@aws-sdk-core-npm-3.485.0-77ed30ee18-b84dafb213.zip/node_modules/@aws-sdk/core/",\
|
||||
"packageDependencies": [\
|
||||
["@aws-sdk/core", "npm:3.485.0"],\
|
||||
["@smithy/core", "npm:1.2.2"],\
|
||||
["@smithy/protocol-http", "npm:3.0.12"],\
|
||||
["@smithy/signature-v4", "npm:2.0.5"],\
|
||||
["@smithy/smithy-client", "npm:2.2.1"],\
|
||||
["@smithy/types", "npm:2.8.0"],\
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}],\
|
||||
["npm:3.490.0", {\
|
||||
"packageLocation": "./.yarn/cache/@aws-sdk-core-npm-3.490.0-3725a806be-3e81f37825.zip/node_modules/@aws-sdk/core/",\
|
||||
"packageDependencies": [\
|
||||
["@aws-sdk/core", "npm:3.490.0"],\
|
||||
["@smithy/core", "npm:1.2.2"],\
|
||||
["@smithy/protocol-http", "npm:3.0.12"],\
|
||||
["@smithy/signature-v4", "npm:2.0.5"],\
|
||||
["@smithy/smithy-client", "npm:2.2.1"],\
|
||||
["@smithy/types", "npm:2.8.0"],\
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}]\
|
||||
]],\
|
||||
["@aws-sdk/credential-provider-env", [\
|
||||
@@ -589,6 +896,28 @@ const RAW_RUNTIME_STATE =
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}],\
|
||||
["npm:3.485.0", {\
|
||||
"packageLocation": "./.yarn/cache/@aws-sdk-credential-provider-env-npm-3.485.0-0fda7f74e0-b8346ea6f5.zip/node_modules/@aws-sdk/credential-provider-env/",\
|
||||
"packageDependencies": [\
|
||||
["@aws-sdk/credential-provider-env", "npm:3.485.0"],\
|
||||
["@aws-sdk/types", "npm:3.485.0"],\
|
||||
["@smithy/property-provider", "npm:2.0.5"],\
|
||||
["@smithy/types", "npm:2.8.0"],\
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}],\
|
||||
["npm:3.489.0", {\
|
||||
"packageLocation": "./.yarn/cache/@aws-sdk-credential-provider-env-npm-3.489.0-e86b20f5e4-95ab96ee49.zip/node_modules/@aws-sdk/credential-provider-env/",\
|
||||
"packageDependencies": [\
|
||||
["@aws-sdk/credential-provider-env", "npm:3.489.0"],\
|
||||
["@aws-sdk/types", "npm:3.489.0"],\
|
||||
["@smithy/property-provider", "npm:2.0.5"],\
|
||||
["@smithy/types", "npm:2.8.0"],\
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}]\
|
||||
]],\
|
||||
["@aws-sdk/credential-provider-ini", [\
|
||||
@@ -608,6 +937,40 @@ const RAW_RUNTIME_STATE =
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}],\
|
||||
["npm:3.485.0", {\
|
||||
"packageLocation": "./.yarn/cache/@aws-sdk-credential-provider-ini-npm-3.485.0-bec3aaa989-3176b03ee1.zip/node_modules/@aws-sdk/credential-provider-ini/",\
|
||||
"packageDependencies": [\
|
||||
["@aws-sdk/credential-provider-ini", "npm:3.485.0"],\
|
||||
["@aws-sdk/credential-provider-env", "npm:3.485.0"],\
|
||||
["@aws-sdk/credential-provider-process", "npm:3.485.0"],\
|
||||
["@aws-sdk/credential-provider-sso", "npm:3.485.0"],\
|
||||
["@aws-sdk/credential-provider-web-identity", "npm:3.485.0"],\
|
||||
["@aws-sdk/types", "npm:3.485.0"],\
|
||||
["@smithy/credential-provider-imds", "npm:2.0.5"],\
|
||||
["@smithy/property-provider", "npm:2.0.5"],\
|
||||
["@smithy/shared-ini-file-loader", "npm:2.0.6"],\
|
||||
["@smithy/types", "npm:2.8.0"],\
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}],\
|
||||
["npm:3.490.0", {\
|
||||
"packageLocation": "./.yarn/cache/@aws-sdk-credential-provider-ini-npm-3.490.0-51f9d0faff-4e4cd2633a.zip/node_modules/@aws-sdk/credential-provider-ini/",\
|
||||
"packageDependencies": [\
|
||||
["@aws-sdk/credential-provider-ini", "npm:3.490.0"],\
|
||||
["@aws-sdk/credential-provider-env", "npm:3.489.0"],\
|
||||
["@aws-sdk/credential-provider-process", "npm:3.489.0"],\
|
||||
["@aws-sdk/credential-provider-sso", "npm:3.490.0"],\
|
||||
["@aws-sdk/credential-provider-web-identity", "npm:3.489.0"],\
|
||||
["@aws-sdk/types", "npm:3.489.0"],\
|
||||
["@smithy/credential-provider-imds", "npm:2.0.5"],\
|
||||
["@smithy/property-provider", "npm:2.0.5"],\
|
||||
["@smithy/shared-ini-file-loader", "npm:2.0.6"],\
|
||||
["@smithy/types", "npm:2.8.0"],\
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}]\
|
||||
]],\
|
||||
["@aws-sdk/credential-provider-node", [\
|
||||
@@ -628,6 +991,42 @@ const RAW_RUNTIME_STATE =
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}],\
|
||||
["npm:3.485.0", {\
|
||||
"packageLocation": "./.yarn/cache/@aws-sdk-credential-provider-node-npm-3.485.0-9f40e4a3cf-d31e5a95ea.zip/node_modules/@aws-sdk/credential-provider-node/",\
|
||||
"packageDependencies": [\
|
||||
["@aws-sdk/credential-provider-node", "npm:3.485.0"],\
|
||||
["@aws-sdk/credential-provider-env", "npm:3.485.0"],\
|
||||
["@aws-sdk/credential-provider-ini", "npm:3.485.0"],\
|
||||
["@aws-sdk/credential-provider-process", "npm:3.485.0"],\
|
||||
["@aws-sdk/credential-provider-sso", "npm:3.485.0"],\
|
||||
["@aws-sdk/credential-provider-web-identity", "npm:3.485.0"],\
|
||||
["@aws-sdk/types", "npm:3.485.0"],\
|
||||
["@smithy/credential-provider-imds", "npm:2.0.5"],\
|
||||
["@smithy/property-provider", "npm:2.0.5"],\
|
||||
["@smithy/shared-ini-file-loader", "npm:2.0.6"],\
|
||||
["@smithy/types", "npm:2.8.0"],\
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}],\
|
||||
["npm:3.490.0", {\
|
||||
"packageLocation": "./.yarn/cache/@aws-sdk-credential-provider-node-npm-3.490.0-3cbe0ec5e6-2f8141c3e1.zip/node_modules/@aws-sdk/credential-provider-node/",\
|
||||
"packageDependencies": [\
|
||||
["@aws-sdk/credential-provider-node", "npm:3.490.0"],\
|
||||
["@aws-sdk/credential-provider-env", "npm:3.489.0"],\
|
||||
["@aws-sdk/credential-provider-ini", "npm:3.490.0"],\
|
||||
["@aws-sdk/credential-provider-process", "npm:3.489.0"],\
|
||||
["@aws-sdk/credential-provider-sso", "npm:3.490.0"],\
|
||||
["@aws-sdk/credential-provider-web-identity", "npm:3.489.0"],\
|
||||
["@aws-sdk/types", "npm:3.489.0"],\
|
||||
["@smithy/credential-provider-imds", "npm:2.0.5"],\
|
||||
["@smithy/property-provider", "npm:2.0.5"],\
|
||||
["@smithy/shared-ini-file-loader", "npm:2.0.6"],\
|
||||
["@smithy/types", "npm:2.8.0"],\
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}]\
|
||||
]],\
|
||||
["@aws-sdk/credential-provider-process", [\
|
||||
@@ -642,6 +1041,30 @@ const RAW_RUNTIME_STATE =
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}],\
|
||||
["npm:3.485.0", {\
|
||||
"packageLocation": "./.yarn/cache/@aws-sdk-credential-provider-process-npm-3.485.0-62d3460338-e740fb949e.zip/node_modules/@aws-sdk/credential-provider-process/",\
|
||||
"packageDependencies": [\
|
||||
["@aws-sdk/credential-provider-process", "npm:3.485.0"],\
|
||||
["@aws-sdk/types", "npm:3.485.0"],\
|
||||
["@smithy/property-provider", "npm:2.0.5"],\
|
||||
["@smithy/shared-ini-file-loader", "npm:2.0.6"],\
|
||||
["@smithy/types", "npm:2.8.0"],\
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}],\
|
||||
["npm:3.489.0", {\
|
||||
"packageLocation": "./.yarn/cache/@aws-sdk-credential-provider-process-npm-3.489.0-9370bfd061-42f4f5f21d.zip/node_modules/@aws-sdk/credential-provider-process/",\
|
||||
"packageDependencies": [\
|
||||
["@aws-sdk/credential-provider-process", "npm:3.489.0"],\
|
||||
["@aws-sdk/types", "npm:3.489.0"],\
|
||||
["@smithy/property-provider", "npm:2.0.5"],\
|
||||
["@smithy/shared-ini-file-loader", "npm:2.0.6"],\
|
||||
["@smithy/types", "npm:2.8.0"],\
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}]\
|
||||
]],\
|
||||
["@aws-sdk/credential-provider-sso", [\
|
||||
@@ -658,6 +1081,34 @@ const RAW_RUNTIME_STATE =
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}],\
|
||||
["npm:3.485.0", {\
|
||||
"packageLocation": "./.yarn/cache/@aws-sdk-credential-provider-sso-npm-3.485.0-42db25db09-7269315797.zip/node_modules/@aws-sdk/credential-provider-sso/",\
|
||||
"packageDependencies": [\
|
||||
["@aws-sdk/credential-provider-sso", "npm:3.485.0"],\
|
||||
["@aws-sdk/client-sso", "npm:3.485.0"],\
|
||||
["@aws-sdk/token-providers", "npm:3.485.0"],\
|
||||
["@aws-sdk/types", "npm:3.485.0"],\
|
||||
["@smithy/property-provider", "npm:2.0.5"],\
|
||||
["@smithy/shared-ini-file-loader", "npm:2.0.6"],\
|
||||
["@smithy/types", "npm:2.8.0"],\
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}],\
|
||||
["npm:3.490.0", {\
|
||||
"packageLocation": "./.yarn/cache/@aws-sdk-credential-provider-sso-npm-3.490.0-9acb6828c0-ef2eff8fbc.zip/node_modules/@aws-sdk/credential-provider-sso/",\
|
||||
"packageDependencies": [\
|
||||
["@aws-sdk/credential-provider-sso", "npm:3.490.0"],\
|
||||
["@aws-sdk/client-sso", "npm:3.490.0"],\
|
||||
["@aws-sdk/token-providers", "npm:3.489.0"],\
|
||||
["@aws-sdk/types", "npm:3.489.0"],\
|
||||
["@smithy/property-provider", "npm:2.0.5"],\
|
||||
["@smithy/shared-ini-file-loader", "npm:2.0.6"],\
|
||||
["@smithy/types", "npm:2.8.0"],\
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}]\
|
||||
]],\
|
||||
["@aws-sdk/credential-provider-web-identity", [\
|
||||
@@ -671,6 +1122,28 @@ const RAW_RUNTIME_STATE =
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}],\
|
||||
["npm:3.485.0", {\
|
||||
"packageLocation": "./.yarn/cache/@aws-sdk-credential-provider-web-identity-npm-3.485.0-420b04bcce-33125ce0b7.zip/node_modules/@aws-sdk/credential-provider-web-identity/",\
|
||||
"packageDependencies": [\
|
||||
["@aws-sdk/credential-provider-web-identity", "npm:3.485.0"],\
|
||||
["@aws-sdk/types", "npm:3.485.0"],\
|
||||
["@smithy/property-provider", "npm:2.0.5"],\
|
||||
["@smithy/types", "npm:2.8.0"],\
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}],\
|
||||
["npm:3.489.0", {\
|
||||
"packageLocation": "./.yarn/cache/@aws-sdk-credential-provider-web-identity-npm-3.489.0-002a8c8ade-911bc3fd28.zip/node_modules/@aws-sdk/credential-provider-web-identity/",\
|
||||
"packageDependencies": [\
|
||||
["@aws-sdk/credential-provider-web-identity", "npm:3.489.0"],\
|
||||
["@aws-sdk/types", "npm:3.489.0"],\
|
||||
["@smithy/property-provider", "npm:2.0.5"],\
|
||||
["@smithy/types", "npm:2.8.0"],\
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}]\
|
||||
]],\
|
||||
["@aws-sdk/middleware-bucket-endpoint", [\
|
||||
@@ -730,6 +1203,28 @@ const RAW_RUNTIME_STATE =
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}],\
|
||||
["npm:3.485.0", {\
|
||||
"packageLocation": "./.yarn/cache/@aws-sdk-middleware-host-header-npm-3.485.0-2e625f9614-9ca3da2a26.zip/node_modules/@aws-sdk/middleware-host-header/",\
|
||||
"packageDependencies": [\
|
||||
["@aws-sdk/middleware-host-header", "npm:3.485.0"],\
|
||||
["@aws-sdk/types", "npm:3.485.0"],\
|
||||
["@smithy/protocol-http", "npm:3.0.12"],\
|
||||
["@smithy/types", "npm:2.8.0"],\
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}],\
|
||||
["npm:3.489.0", {\
|
||||
"packageLocation": "./.yarn/cache/@aws-sdk-middleware-host-header-npm-3.489.0-10c65ea2e3-3f80f71691.zip/node_modules/@aws-sdk/middleware-host-header/",\
|
||||
"packageDependencies": [\
|
||||
["@aws-sdk/middleware-host-header", "npm:3.489.0"],\
|
||||
["@aws-sdk/types", "npm:3.489.0"],\
|
||||
["@smithy/protocol-http", "npm:3.0.12"],\
|
||||
["@smithy/types", "npm:2.8.0"],\
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}]\
|
||||
]],\
|
||||
["@aws-sdk/middleware-location-constraint", [\
|
||||
@@ -754,6 +1249,26 @@ const RAW_RUNTIME_STATE =
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}],\
|
||||
["npm:3.485.0", {\
|
||||
"packageLocation": "./.yarn/cache/@aws-sdk-middleware-logger-npm-3.485.0-3ff7eeabbb-2fcb731794.zip/node_modules/@aws-sdk/middleware-logger/",\
|
||||
"packageDependencies": [\
|
||||
["@aws-sdk/middleware-logger", "npm:3.485.0"],\
|
||||
["@aws-sdk/types", "npm:3.485.0"],\
|
||||
["@smithy/types", "npm:2.8.0"],\
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}],\
|
||||
["npm:3.489.0", {\
|
||||
"packageLocation": "./.yarn/cache/@aws-sdk-middleware-logger-npm-3.489.0-ba04fd0161-0bbf9d08c7.zip/node_modules/@aws-sdk/middleware-logger/",\
|
||||
"packageDependencies": [\
|
||||
["@aws-sdk/middleware-logger", "npm:3.489.0"],\
|
||||
["@aws-sdk/types", "npm:3.489.0"],\
|
||||
["@smithy/types", "npm:2.8.0"],\
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}]\
|
||||
]],\
|
||||
["@aws-sdk/middleware-recursion-detection", [\
|
||||
@@ -767,6 +1282,28 @@ const RAW_RUNTIME_STATE =
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}],\
|
||||
["npm:3.485.0", {\
|
||||
"packageLocation": "./.yarn/cache/@aws-sdk-middleware-recursion-detection-npm-3.485.0-af05ed4810-afdea18930.zip/node_modules/@aws-sdk/middleware-recursion-detection/",\
|
||||
"packageDependencies": [\
|
||||
["@aws-sdk/middleware-recursion-detection", "npm:3.485.0"],\
|
||||
["@aws-sdk/types", "npm:3.485.0"],\
|
||||
["@smithy/protocol-http", "npm:3.0.12"],\
|
||||
["@smithy/types", "npm:2.8.0"],\
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}],\
|
||||
["npm:3.489.0", {\
|
||||
"packageLocation": "./.yarn/cache/@aws-sdk-middleware-recursion-detection-npm-3.489.0-2cefe5fc6b-91eb0b3b46.zip/node_modules/@aws-sdk/middleware-recursion-detection/",\
|
||||
"packageDependencies": [\
|
||||
["@aws-sdk/middleware-recursion-detection", "npm:3.489.0"],\
|
||||
["@aws-sdk/types", "npm:3.489.0"],\
|
||||
["@smithy/protocol-http", "npm:3.0.12"],\
|
||||
["@smithy/types", "npm:2.8.0"],\
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}]\
|
||||
]],\
|
||||
["@aws-sdk/middleware-sdk-s3", [\
|
||||
@@ -815,6 +1352,34 @@ const RAW_RUNTIME_STATE =
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}],\
|
||||
["npm:3.485.0", {\
|
||||
"packageLocation": "./.yarn/cache/@aws-sdk-middleware-signing-npm-3.485.0-3117db6053-f9dbb39d8d.zip/node_modules/@aws-sdk/middleware-signing/",\
|
||||
"packageDependencies": [\
|
||||
["@aws-sdk/middleware-signing", "npm:3.485.0"],\
|
||||
["@aws-sdk/types", "npm:3.485.0"],\
|
||||
["@smithy/property-provider", "npm:2.0.5"],\
|
||||
["@smithy/protocol-http", "npm:3.0.12"],\
|
||||
["@smithy/signature-v4", "npm:2.0.5"],\
|
||||
["@smithy/types", "npm:2.8.0"],\
|
||||
["@smithy/util-middleware", "npm:2.0.9"],\
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}],\
|
||||
["npm:3.489.0", {\
|
||||
"packageLocation": "./.yarn/cache/@aws-sdk-middleware-signing-npm-3.489.0-722d97a2fd-6fedba4569.zip/node_modules/@aws-sdk/middleware-signing/",\
|
||||
"packageDependencies": [\
|
||||
["@aws-sdk/middleware-signing", "npm:3.489.0"],\
|
||||
["@aws-sdk/types", "npm:3.489.0"],\
|
||||
["@smithy/property-provider", "npm:2.0.5"],\
|
||||
["@smithy/protocol-http", "npm:3.0.12"],\
|
||||
["@smithy/signature-v4", "npm:2.0.5"],\
|
||||
["@smithy/types", "npm:2.8.0"],\
|
||||
["@smithy/util-middleware", "npm:2.0.9"],\
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}]\
|
||||
]],\
|
||||
["@aws-sdk/middleware-ssec", [\
|
||||
@@ -841,6 +1406,30 @@ const RAW_RUNTIME_STATE =
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}],\
|
||||
["npm:3.485.0", {\
|
||||
"packageLocation": "./.yarn/cache/@aws-sdk-middleware-user-agent-npm-3.485.0-983204fccf-a8fc812aff.zip/node_modules/@aws-sdk/middleware-user-agent/",\
|
||||
"packageDependencies": [\
|
||||
["@aws-sdk/middleware-user-agent", "npm:3.485.0"],\
|
||||
["@aws-sdk/types", "npm:3.485.0"],\
|
||||
["@aws-sdk/util-endpoints", "npm:3.485.0"],\
|
||||
["@smithy/protocol-http", "npm:3.0.12"],\
|
||||
["@smithy/types", "npm:2.8.0"],\
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}],\
|
||||
["npm:3.489.0", {\
|
||||
"packageLocation": "./.yarn/cache/@aws-sdk-middleware-user-agent-npm-3.489.0-4a9e57c5ff-51fc7a8a03.zip/node_modules/@aws-sdk/middleware-user-agent/",\
|
||||
"packageDependencies": [\
|
||||
["@aws-sdk/middleware-user-agent", "npm:3.489.0"],\
|
||||
["@aws-sdk/types", "npm:3.489.0"],\
|
||||
["@aws-sdk/util-endpoints", "npm:3.489.0"],\
|
||||
["@smithy/protocol-http", "npm:3.0.12"],\
|
||||
["@smithy/types", "npm:2.8.0"],\
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}]\
|
||||
]],\
|
||||
["@aws-sdk/region-config-resolver", [\
|
||||
@@ -855,6 +1444,31 @@ const RAW_RUNTIME_STATE =
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}],\
|
||||
["npm:3.485.0", {\
|
||||
"packageLocation": "./.yarn/cache/@aws-sdk-region-config-resolver-npm-3.485.0-1a69e46754-55bc5128b8.zip/node_modules/@aws-sdk/region-config-resolver/",\
|
||||
"packageDependencies": [\
|
||||
["@aws-sdk/region-config-resolver", "npm:3.485.0"],\
|
||||
["@smithy/node-config-provider", "npm:2.1.9"],\
|
||||
["@smithy/types", "npm:2.8.0"],\
|
||||
["@smithy/util-config-provider", "npm:2.1.0"],\
|
||||
["@smithy/util-middleware", "npm:2.0.9"],\
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}],\
|
||||
["npm:3.489.0", {\
|
||||
"packageLocation": "./.yarn/cache/@aws-sdk-region-config-resolver-npm-3.489.0-0721047a4a-045a630c94.zip/node_modules/@aws-sdk/region-config-resolver/",\
|
||||
"packageDependencies": [\
|
||||
["@aws-sdk/region-config-resolver", "npm:3.489.0"],\
|
||||
["@aws-sdk/types", "npm:3.489.0"],\
|
||||
["@smithy/node-config-provider", "npm:2.1.9"],\
|
||||
["@smithy/types", "npm:2.8.0"],\
|
||||
["@smithy/util-config-provider", "npm:2.1.0"],\
|
||||
["@smithy/util-middleware", "npm:2.0.9"],\
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}]\
|
||||
]],\
|
||||
["@aws-sdk/signature-v4-multi-region", [\
|
||||
@@ -916,6 +1530,94 @@ const RAW_RUNTIME_STATE =
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}],\
|
||||
["npm:3.485.0", {\
|
||||
"packageLocation": "./.yarn/cache/@aws-sdk-token-providers-npm-3.485.0-1fb5ab9dfb-aed270b625.zip/node_modules/@aws-sdk/token-providers/",\
|
||||
"packageDependencies": [\
|
||||
["@aws-sdk/token-providers", "npm:3.485.0"],\
|
||||
["@aws-crypto/sha256-browser", "npm:3.0.0"],\
|
||||
["@aws-crypto/sha256-js", "npm:3.0.0"],\
|
||||
["@aws-sdk/middleware-host-header", "npm:3.485.0"],\
|
||||
["@aws-sdk/middleware-logger", "npm:3.485.0"],\
|
||||
["@aws-sdk/middleware-recursion-detection", "npm:3.485.0"],\
|
||||
["@aws-sdk/middleware-user-agent", "npm:3.485.0"],\
|
||||
["@aws-sdk/region-config-resolver", "npm:3.485.0"],\
|
||||
["@aws-sdk/types", "npm:3.485.0"],\
|
||||
["@aws-sdk/util-endpoints", "npm:3.485.0"],\
|
||||
["@aws-sdk/util-user-agent-browser", "npm:3.485.0"],\
|
||||
["@aws-sdk/util-user-agent-node", "virtual:5f6733bd23aee10dd05576af160f1b93e0bb4a20b288e9b818dc0b69bdb08ea1a09d5836816f02bdafc9c01487816ae339c6b680c2f7849dfe249436c5f2b499#npm:3.485.0"],\
|
||||
["@smithy/config-resolver", "npm:2.0.23"],\
|
||||
["@smithy/fetch-http-handler", "npm:2.3.2"],\
|
||||
["@smithy/hash-node", "npm:2.0.18"],\
|
||||
["@smithy/invalid-dependency", "npm:2.0.16"],\
|
||||
["@smithy/middleware-content-length", "npm:2.0.18"],\
|
||||
["@smithy/middleware-endpoint", "npm:2.3.0"],\
|
||||
["@smithy/middleware-retry", "npm:2.0.26"],\
|
||||
["@smithy/middleware-serde", "npm:2.0.16"],\
|
||||
["@smithy/middleware-stack", "npm:2.0.10"],\
|
||||
["@smithy/node-config-provider", "npm:2.1.9"],\
|
||||
["@smithy/node-http-handler", "npm:2.2.2"],\
|
||||
["@smithy/property-provider", "npm:2.0.5"],\
|
||||
["@smithy/protocol-http", "npm:3.0.12"],\
|
||||
["@smithy/shared-ini-file-loader", "npm:2.0.6"],\
|
||||
["@smithy/smithy-client", "npm:2.2.1"],\
|
||||
["@smithy/types", "npm:2.8.0"],\
|
||||
["@smithy/url-parser", "npm:2.0.16"],\
|
||||
["@smithy/util-base64", "npm:2.0.1"],\
|
||||
["@smithy/util-body-length-browser", "npm:2.0.1"],\
|
||||
["@smithy/util-body-length-node", "npm:2.1.0"],\
|
||||
["@smithy/util-defaults-mode-browser", "npm:2.0.24"],\
|
||||
["@smithy/util-defaults-mode-node", "npm:2.0.32"],\
|
||||
["@smithy/util-endpoints", "npm:1.0.8"],\
|
||||
["@smithy/util-retry", "npm:2.0.9"],\
|
||||
["@smithy/util-utf8", "npm:2.0.2"],\
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}],\
|
||||
["npm:3.489.0", {\
|
||||
"packageLocation": "./.yarn/cache/@aws-sdk-token-providers-npm-3.489.0-05002406d6-ee7a20eff7.zip/node_modules/@aws-sdk/token-providers/",\
|
||||
"packageDependencies": [\
|
||||
["@aws-sdk/token-providers", "npm:3.489.0"],\
|
||||
["@aws-crypto/sha256-browser", "npm:3.0.0"],\
|
||||
["@aws-crypto/sha256-js", "npm:3.0.0"],\
|
||||
["@aws-sdk/middleware-host-header", "npm:3.489.0"],\
|
||||
["@aws-sdk/middleware-logger", "npm:3.489.0"],\
|
||||
["@aws-sdk/middleware-recursion-detection", "npm:3.489.0"],\
|
||||
["@aws-sdk/middleware-user-agent", "npm:3.489.0"],\
|
||||
["@aws-sdk/region-config-resolver", "npm:3.489.0"],\
|
||||
["@aws-sdk/types", "npm:3.489.0"],\
|
||||
["@aws-sdk/util-endpoints", "npm:3.489.0"],\
|
||||
["@aws-sdk/util-user-agent-browser", "npm:3.489.0"],\
|
||||
["@aws-sdk/util-user-agent-node", "virtual:26ec4a89785e0643103d1dd3b2a86d8c63d7fd76dbfb0e516f1dc429fef4581a7306b382504a8b85e8fb995888356d6341786deec607cb64b29957c728540295#npm:3.489.0"],\
|
||||
["@smithy/config-resolver", "npm:2.0.23"],\
|
||||
["@smithy/fetch-http-handler", "npm:2.3.2"],\
|
||||
["@smithy/hash-node", "npm:2.0.18"],\
|
||||
["@smithy/invalid-dependency", "npm:2.0.16"],\
|
||||
["@smithy/middleware-content-length", "npm:2.0.18"],\
|
||||
["@smithy/middleware-endpoint", "npm:2.3.0"],\
|
||||
["@smithy/middleware-retry", "npm:2.0.26"],\
|
||||
["@smithy/middleware-serde", "npm:2.0.16"],\
|
||||
["@smithy/middleware-stack", "npm:2.0.10"],\
|
||||
["@smithy/node-config-provider", "npm:2.1.9"],\
|
||||
["@smithy/node-http-handler", "npm:2.2.2"],\
|
||||
["@smithy/property-provider", "npm:2.0.5"],\
|
||||
["@smithy/protocol-http", "npm:3.0.12"],\
|
||||
["@smithy/shared-ini-file-loader", "npm:2.0.6"],\
|
||||
["@smithy/smithy-client", "npm:2.2.1"],\
|
||||
["@smithy/types", "npm:2.8.0"],\
|
||||
["@smithy/url-parser", "npm:2.0.16"],\
|
||||
["@smithy/util-base64", "npm:2.0.1"],\
|
||||
["@smithy/util-body-length-browser", "npm:2.0.1"],\
|
||||
["@smithy/util-body-length-node", "npm:2.1.0"],\
|
||||
["@smithy/util-defaults-mode-browser", "npm:2.0.24"],\
|
||||
["@smithy/util-defaults-mode-node", "npm:2.0.32"],\
|
||||
["@smithy/util-endpoints", "npm:1.0.8"],\
|
||||
["@smithy/util-retry", "npm:2.0.9"],\
|
||||
["@smithy/util-utf8", "npm:2.0.2"],\
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}]\
|
||||
]],\
|
||||
["@aws-sdk/types", [\
|
||||
@@ -935,6 +1637,24 @@ const RAW_RUNTIME_STATE =
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}],\
|
||||
["npm:3.485.0", {\
|
||||
"packageLocation": "./.yarn/cache/@aws-sdk-types-npm-3.485.0-6aa8cab069-588aae4b49.zip/node_modules/@aws-sdk/types/",\
|
||||
"packageDependencies": [\
|
||||
["@aws-sdk/types", "npm:3.485.0"],\
|
||||
["@smithy/types", "npm:2.8.0"],\
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}],\
|
||||
["npm:3.489.0", {\
|
||||
"packageLocation": "./.yarn/cache/@aws-sdk-types-npm-3.489.0-f0f748fbaa-48778dad14.zip/node_modules/@aws-sdk/types/",\
|
||||
"packageDependencies": [\
|
||||
["@aws-sdk/types", "npm:3.489.0"],\
|
||||
["@smithy/types", "npm:2.8.0"],\
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}]\
|
||||
]],\
|
||||
["@aws-sdk/util-arn-parser", [\
|
||||
@@ -957,6 +1677,27 @@ const RAW_RUNTIME_STATE =
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}],\
|
||||
["npm:3.485.0", {\
|
||||
"packageLocation": "./.yarn/cache/@aws-sdk-util-endpoints-npm-3.485.0-5e0fad395e-c1844fed8b.zip/node_modules/@aws-sdk/util-endpoints/",\
|
||||
"packageDependencies": [\
|
||||
["@aws-sdk/util-endpoints", "npm:3.485.0"],\
|
||||
["@aws-sdk/types", "npm:3.485.0"],\
|
||||
["@smithy/util-endpoints", "npm:1.0.8"],\
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}],\
|
||||
["npm:3.489.0", {\
|
||||
"packageLocation": "./.yarn/cache/@aws-sdk-util-endpoints-npm-3.489.0-1f2dd7e944-68f921982f.zip/node_modules/@aws-sdk/util-endpoints/",\
|
||||
"packageDependencies": [\
|
||||
["@aws-sdk/util-endpoints", "npm:3.489.0"],\
|
||||
["@aws-sdk/types", "npm:3.489.0"],\
|
||||
["@smithy/types", "npm:2.8.0"],\
|
||||
["@smithy/util-endpoints", "npm:1.0.8"],\
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}]\
|
||||
]],\
|
||||
["@aws-sdk/util-locate-window", [\
|
||||
@@ -980,6 +1721,28 @@ const RAW_RUNTIME_STATE =
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}],\
|
||||
["npm:3.485.0", {\
|
||||
"packageLocation": "./.yarn/cache/@aws-sdk-util-user-agent-browser-npm-3.485.0-23925a5581-d1e4d4c635.zip/node_modules/@aws-sdk/util-user-agent-browser/",\
|
||||
"packageDependencies": [\
|
||||
["@aws-sdk/util-user-agent-browser", "npm:3.485.0"],\
|
||||
["@aws-sdk/types", "npm:3.485.0"],\
|
||||
["@smithy/types", "npm:2.8.0"],\
|
||||
["bowser", "npm:2.11.0"],\
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}],\
|
||||
["npm:3.489.0", {\
|
||||
"packageLocation": "./.yarn/cache/@aws-sdk-util-user-agent-browser-npm-3.489.0-ffb94f7b1d-2bb414b8d8.zip/node_modules/@aws-sdk/util-user-agent-browser/",\
|
||||
"packageDependencies": [\
|
||||
["@aws-sdk/util-user-agent-browser", "npm:3.489.0"],\
|
||||
["@aws-sdk/types", "npm:3.489.0"],\
|
||||
["@smithy/types", "npm:2.8.0"],\
|
||||
["bowser", "npm:2.11.0"],\
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}]\
|
||||
]],\
|
||||
["@aws-sdk/util-user-agent-node", [\
|
||||
@@ -990,6 +1753,54 @@ const RAW_RUNTIME_STATE =
|
||||
],\
|
||||
"linkType": "SOFT"\
|
||||
}],\
|
||||
["npm:3.485.0", {\
|
||||
"packageLocation": "./.yarn/cache/@aws-sdk-util-user-agent-node-npm-3.485.0-7991a74cb3-e2805ef37b.zip/node_modules/@aws-sdk/util-user-agent-node/",\
|
||||
"packageDependencies": [\
|
||||
["@aws-sdk/util-user-agent-node", "npm:3.485.0"]\
|
||||
],\
|
||||
"linkType": "SOFT"\
|
||||
}],\
|
||||
["npm:3.489.0", {\
|
||||
"packageLocation": "./.yarn/cache/@aws-sdk-util-user-agent-node-npm-3.489.0-082349e8a9-95dc1e07b6.zip/node_modules/@aws-sdk/util-user-agent-node/",\
|
||||
"packageDependencies": [\
|
||||
["@aws-sdk/util-user-agent-node", "npm:3.489.0"]\
|
||||
],\
|
||||
"linkType": "SOFT"\
|
||||
}],\
|
||||
["virtual:26ec4a89785e0643103d1dd3b2a86d8c63d7fd76dbfb0e516f1dc429fef4581a7306b382504a8b85e8fb995888356d6341786deec607cb64b29957c728540295#npm:3.489.0", {\
|
||||
"packageLocation": "./.yarn/__virtual__/@aws-sdk-util-user-agent-node-virtual-73c334651c/0/cache/@aws-sdk-util-user-agent-node-npm-3.489.0-082349e8a9-95dc1e07b6.zip/node_modules/@aws-sdk/util-user-agent-node/",\
|
||||
"packageDependencies": [\
|
||||
["@aws-sdk/util-user-agent-node", "virtual:26ec4a89785e0643103d1dd3b2a86d8c63d7fd76dbfb0e516f1dc429fef4581a7306b382504a8b85e8fb995888356d6341786deec607cb64b29957c728540295#npm:3.489.0"],\
|
||||
["@aws-sdk/types", "npm:3.489.0"],\
|
||||
["@smithy/node-config-provider", "npm:2.1.9"],\
|
||||
["@smithy/types", "npm:2.8.0"],\
|
||||
["@types/aws-crt", null],\
|
||||
["aws-crt", null],\
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"packagePeers": [\
|
||||
"@types/aws-crt",\
|
||||
"aws-crt"\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}],\
|
||||
["virtual:5f6733bd23aee10dd05576af160f1b93e0bb4a20b288e9b818dc0b69bdb08ea1a09d5836816f02bdafc9c01487816ae339c6b680c2f7849dfe249436c5f2b499#npm:3.485.0", {\
|
||||
"packageLocation": "./.yarn/__virtual__/@aws-sdk-util-user-agent-node-virtual-c26ab353dd/0/cache/@aws-sdk-util-user-agent-node-npm-3.485.0-7991a74cb3-e2805ef37b.zip/node_modules/@aws-sdk/util-user-agent-node/",\
|
||||
"packageDependencies": [\
|
||||
["@aws-sdk/util-user-agent-node", "virtual:5f6733bd23aee10dd05576af160f1b93e0bb4a20b288e9b818dc0b69bdb08ea1a09d5836816f02bdafc9c01487816ae339c6b680c2f7849dfe249436c5f2b499#npm:3.485.0"],\
|
||||
["@aws-sdk/types", "npm:3.485.0"],\
|
||||
["@smithy/node-config-provider", "npm:2.1.9"],\
|
||||
["@smithy/types", "npm:2.8.0"],\
|
||||
["@types/aws-crt", null],\
|
||||
["aws-crt", null],\
|
||||
["tslib", "npm:2.5.2"]\
|
||||
],\
|
||||
"packagePeers": [\
|
||||
"@types/aws-crt",\
|
||||
"aws-crt"\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}],\
|
||||
["virtual:f5e5a564ba918754c8b3b080eb29a2688af35b9c1a773de63eb148390564369a40f304a7384da1d22d51cb840254882c972d18d82a96c4804ada9a0446f624d6#npm:3.470.0", {\
|
||||
"packageLocation": "./.yarn/__virtual__/@aws-sdk-util-user-agent-node-virtual-92b1b7bd6e/0/cache/@aws-sdk-util-user-agent-node-npm-3.470.0-99b784cecc-05571ba83d.zip/node_modules/@aws-sdk/util-user-agent-node/",\
|
||||
"packageDependencies": [\
|
||||
@@ -5577,6 +6388,7 @@ const RAW_RUNTIME_STATE =
|
||||
"packageLocation": "./packages/api-gateway/",\
|
||||
"packageDependencies": [\
|
||||
["@standardnotes/api-gateway", "workspace:packages/api-gateway"],\
|
||||
["@aws-sdk/client-sns", "npm:3.490.0"],\
|
||||
["@grpc/grpc-js", "npm:1.9.13"],\
|
||||
["@standardnotes/domain-core", "workspace:packages/domain-core"],\
|
||||
["@standardnotes/domain-events", "workspace:packages/domain-events"],\
|
||||
@@ -6125,6 +6937,7 @@ const RAW_RUNTIME_STATE =
|
||||
"packageLocation": "./packages/syncing-server/",\
|
||||
"packageDependencies": [\
|
||||
["@standardnotes/syncing-server", "workspace:packages/syncing-server"],\
|
||||
["@aws-sdk/client-cloudwatch", "npm:3.485.0"],\
|
||||
["@aws-sdk/client-s3", "npm:3.484.0"],\
|
||||
["@aws-sdk/client-sns", "npm:3.484.0"],\
|
||||
["@aws-sdk/client-sqs", "npm:3.484.0"],\
|
||||
|
||||
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.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
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.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -3,6 +3,18 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [2.34.16](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.34.15...@standardnotes/analytics@2.34.16) (2024-01-19)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/analytics
|
||||
|
||||
## [2.34.15](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.34.14...@standardnotes/analytics@2.34.15) (2024-01-18)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/analytics
|
||||
|
||||
## [2.34.14](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.34.13...@standardnotes/analytics@2.34.14) (2024-01-04)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/analytics
|
||||
|
||||
## [2.34.13](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.34.12...@standardnotes/analytics@2.34.13) (2024-01-03)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/analytics
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/analytics",
|
||||
"version": "2.34.13",
|
||||
"version": "2.34.16",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <21.0.0"
|
||||
},
|
||||
|
||||
@@ -3,6 +3,48 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.90.1](https://github.com/standardnotes/server/compare/@standardnotes/api-gateway@1.90.0...@standardnotes/api-gateway@1.90.1) (2024-01-19)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||
|
||||
# [1.90.0](https://github.com/standardnotes/server/compare/@standardnotes/api-gateway@1.89.20...@standardnotes/api-gateway@1.90.0) (2024-01-18)
|
||||
|
||||
### Features
|
||||
|
||||
* add content sizes fixing upon grpc resource exhausted error ([#1029](https://github.com/standardnotes/server/issues/1029)) ([634e8bd](https://github.com/standardnotes/server/commit/634e8bd2d0f055abbda1150587ab9a444281e600))
|
||||
|
||||
## [1.89.20](https://github.com/standardnotes/server/compare/@standardnotes/api-gateway@1.89.19...@standardnotes/api-gateway@1.89.20) (2024-01-18)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **api-gateway:** add codetag metadata to error logs ([136cf25](https://github.com/standardnotes/server/commit/136cf252a134efe7d99f79d8622c43dbebbb5ac8))
|
||||
|
||||
## [1.89.19](https://github.com/standardnotes/server/compare/@standardnotes/api-gateway@1.89.18...@standardnotes/api-gateway@1.89.19) (2024-01-10)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add dedicated http code response upon a request with too large payload ([#1019](https://github.com/standardnotes/server/issues/1019)) ([6062f85](https://github.com/standardnotes/server/commit/6062f850000477983315d2d9b7c913956f755ebb))
|
||||
|
||||
## [1.89.18](https://github.com/standardnotes/server/compare/@standardnotes/api-gateway@1.89.17...@standardnotes/api-gateway@1.89.18) (2024-01-08)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||
|
||||
## [1.89.17](https://github.com/standardnotes/server/compare/@standardnotes/api-gateway@1.89.16...@standardnotes/api-gateway@1.89.17) (2024-01-04)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **api-gateway:** disable http call retries ([7abd80c](https://github.com/standardnotes/server/commit/7abd80cdbaba53840f632d418bd557b35b722699))
|
||||
|
||||
## [1.89.16](https://github.com/standardnotes/server/compare/@standardnotes/api-gateway@1.89.15...@standardnotes/api-gateway@1.89.16) (2024-01-04)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **api-gateway:** disable sync request retries ([d2a371b](https://github.com/standardnotes/server/commit/d2a371b92c8b2b7f8921fe57f162e74d4944715d))
|
||||
|
||||
## [1.89.15](https://github.com/standardnotes/server/compare/@standardnotes/api-gateway@1.89.14...@standardnotes/api-gateway@1.89.15) (2024-01-04)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||
|
||||
## [1.89.14](https://github.com/standardnotes/server/compare/@standardnotes/api-gateway@1.89.13...@standardnotes/api-gateway@1.89.14) (2024-01-03)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||
|
||||
@@ -36,12 +36,17 @@ import { InversifyExpressServer } from 'inversify-express-utils'
|
||||
import { ContainerConfigLoader } from '../src/Bootstrap/Container'
|
||||
import { TYPES } from '../src/Bootstrap/Types'
|
||||
import { Env } from '../src/Bootstrap/Env'
|
||||
import { ResponseLocals } from '../src/Controller/ResponseLocals'
|
||||
|
||||
const container = new ContainerConfigLoader()
|
||||
void container.load().then((container) => {
|
||||
const env: Env = new Env()
|
||||
env.load()
|
||||
|
||||
const requestPayloadLimit = env.get('HTTP_REQUEST_PAYLOAD_LIMIT_MEGABYTES', true)
|
||||
? `${+env.get('HTTP_REQUEST_PAYLOAD_LIMIT_MEGABYTES', true)}mb`
|
||||
: '50mb'
|
||||
|
||||
const server = new InversifyExpressServer(container)
|
||||
|
||||
server.setConfig((app) => {
|
||||
@@ -72,7 +77,7 @@ void container.load().then((container) => {
|
||||
}),
|
||||
)
|
||||
|
||||
app.use(json({ limit: '50mb' }))
|
||||
app.use(json({ limit: requestPayloadLimit }))
|
||||
app.use(
|
||||
text({
|
||||
type: ['text/plain', 'application/x-www-form-urlencoded', 'application/x-www-form-urlencoded; charset=utf-8'],
|
||||
@@ -91,12 +96,15 @@ void container.load().then((container) => {
|
||||
|
||||
server.setErrorConfig((app) => {
|
||||
app.use((error: Record<string, unknown>, request: Request, response: Response, _next: NextFunction) => {
|
||||
const locals = response.locals as ResponseLocals
|
||||
|
||||
logger.error(`${error.stack}`, {
|
||||
codeTag: 'server.ts',
|
||||
method: request.method,
|
||||
url: request.url,
|
||||
snjs: request.headers['x-snjs-version'],
|
||||
application: request.headers['x-application-version'],
|
||||
userId: response.locals.user ? response.locals.user.uuid : undefined,
|
||||
userId: locals.user ? locals.user.uuid : undefined,
|
||||
})
|
||||
logger.debug(
|
||||
`[URL: |${request.method}| ${request.url}][SNJS: ${request.headers['x-snjs-version']}][Application: ${
|
||||
@@ -104,6 +112,16 @@ void container.load().then((container) => {
|
||||
}] Request body: ${JSON.stringify(request.body)}`,
|
||||
)
|
||||
|
||||
if ('type' in error && error.type === 'entity.too.large') {
|
||||
response.status(413).send({
|
||||
error: {
|
||||
message: 'The request payload is too large.',
|
||||
},
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
response.status(500).send({
|
||||
error: {
|
||||
message:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/api-gateway",
|
||||
"version": "1.89.14",
|
||||
"version": "1.90.1",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <21.0.0"
|
||||
},
|
||||
@@ -31,6 +31,7 @@
|
||||
"start": "yarn node dist/bin/server.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-sns": "^3.490.0",
|
||||
"@grpc/grpc-js": "^1.9.13",
|
||||
"@standardnotes/domain-core": "workspace:^",
|
||||
"@standardnotes/domain-events": "workspace:*",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import * as winston from 'winston'
|
||||
import * as AgentKeepAlive from 'agentkeepalive'
|
||||
import * as grpc from '@grpc/grpc-js'
|
||||
import { SNSClient, SNSClientConfig } from '@aws-sdk/client-sns'
|
||||
import axios, { AxiosInstance } from 'axios'
|
||||
import Redis from 'ioredis'
|
||||
import { Container } from 'inversify'
|
||||
@@ -29,6 +30,10 @@ import { SyncResponseHttpRepresentation } from '../Mapping/Sync/Http/SyncRespons
|
||||
import { SyncRequestGRPCMapper } from '../Mapping/Sync/GRPC/SyncRequestGRPCMapper'
|
||||
import { SyncResponseGRPCMapper } from '../Mapping/Sync/GRPC/SyncResponseGRPCMapper'
|
||||
import { GRPCWebSocketAuthMiddleware } from '../Controller/GRPCWebSocketAuthMiddleware'
|
||||
import { DomainEventPublisherInterface } from '@standardnotes/domain-events'
|
||||
import { SNSDomainEventPublisher } from '@standardnotes/domain-events-infra'
|
||||
import { DomainEventFactoryInterface } from '../Event/DomainEventFactoryInterface'
|
||||
import { DomainEventFactory } from '../Event/DomainEventFactory'
|
||||
|
||||
export class ContainerConfigLoader {
|
||||
async load(configuration?: {
|
||||
@@ -51,6 +56,34 @@ export class ContainerConfigLoader {
|
||||
.bind<boolean>(TYPES.ApiGateway_IS_CONFIGURED_FOR_HOME_SERVER_OR_SELF_HOSTING)
|
||||
.toConstantValue(isConfiguredForHomeServerOrSelfHosting)
|
||||
|
||||
if (!isConfiguredForHomeServerOrSelfHosting) {
|
||||
const snsConfig: SNSClientConfig = {
|
||||
region: env.get('SNS_AWS_REGION', true),
|
||||
}
|
||||
if (env.get('SNS_ENDPOINT', true)) {
|
||||
snsConfig.endpoint = env.get('SNS_ENDPOINT', true)
|
||||
}
|
||||
if (env.get('SNS_ACCESS_KEY_ID', true) && env.get('SNS_SECRET_ACCESS_KEY', true)) {
|
||||
snsConfig.credentials = {
|
||||
accessKeyId: env.get('SNS_ACCESS_KEY_ID', true),
|
||||
secretAccessKey: env.get('SNS_SECRET_ACCESS_KEY', true),
|
||||
}
|
||||
}
|
||||
const snsClient = new SNSClient(snsConfig)
|
||||
container.bind<SNSClient>(TYPES.ApiGateway_SNS).toConstantValue(snsClient)
|
||||
|
||||
container.bind(TYPES.ApiGateway_SNS_TOPIC_ARN).toConstantValue(env.get('SNS_TOPIC_ARN', true))
|
||||
|
||||
container
|
||||
.bind<DomainEventPublisherInterface>(TYPES.ApiGateway_DomainEventPublisher)
|
||||
.toConstantValue(
|
||||
new SNSDomainEventPublisher(
|
||||
container.get(TYPES.ApiGateway_SNS),
|
||||
container.get(TYPES.ApiGateway_SNS_TOPIC_ARN),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
const winstonFormatters = [winston.format.splat(), winston.format.json()]
|
||||
|
||||
let logger: winston.Logger
|
||||
@@ -192,6 +225,10 @@ export class ContainerConfigLoader {
|
||||
.bind<MapperInterface<SyncResponse, SyncResponseHttpRepresentation>>(TYPES.Mapper_SyncResponseGRPCMapper)
|
||||
.toConstantValue(new SyncResponseGRPCMapper())
|
||||
|
||||
container
|
||||
.bind<DomainEventFactoryInterface>(TYPES.ApiGateway_DomainEventFactory)
|
||||
.toConstantValue(new DomainEventFactory(container.get<TimerInterface>(TYPES.ApiGateway_Timer)))
|
||||
|
||||
container
|
||||
.bind<GRPCSyncingServerServiceProxy>(TYPES.ApiGateway_GRPCSyncingServerServiceProxy)
|
||||
.toConstantValue(
|
||||
@@ -202,6 +239,10 @@ export class ContainerConfigLoader {
|
||||
TYPES.Mapper_SyncResponseGRPCMapper,
|
||||
),
|
||||
container.get<winston.Logger>(TYPES.ApiGateway_Logger),
|
||||
container.get<DomainEventFactoryInterface>(TYPES.ApiGateway_DomainEventFactory),
|
||||
isConfiguredForHomeServerOrSelfHosting
|
||||
? undefined
|
||||
: container.get<DomainEventPublisherInterface>(TYPES.ApiGateway_DomainEventPublisher),
|
||||
),
|
||||
)
|
||||
container
|
||||
|
||||
@@ -2,7 +2,11 @@ export const TYPES = {
|
||||
ApiGateway_Logger: Symbol.for('ApiGateway_Logger'),
|
||||
ApiGateway_Redis: Symbol.for('ApiGateway_Redis'),
|
||||
ApiGateway_HTTPClient: Symbol.for('ApiGateway_HTTPClient'),
|
||||
ApiGateway_SNS: Symbol.for('ApiGateway_SNS'),
|
||||
ApiGateway_DomainEventPublisher: Symbol.for('ApiGateway_DomainEventPublisher'),
|
||||
// env vars
|
||||
ApiGateway_SNS_TOPIC_ARN: Symbol.for('ApiGateway_SNS_TOPIC_ARN'),
|
||||
ApiGateway_SNS_AWS_REGION: Symbol.for('ApiGateway_SNS_AWS_REGION'),
|
||||
ApiGateway_SYNCING_SERVER_JS_URL: Symbol.for('ApiGateway_SYNCING_SERVER_JS_URL'),
|
||||
ApiGateway_AUTH_SERVER_URL: Symbol.for('ApiGateway_AUTH_SERVER_URL'),
|
||||
ApiGateway_AUTH_SERVER_GRPC_URL: Symbol.for('ApiGateway_AUTH_SERVER_GRPC_URL'),
|
||||
@@ -29,6 +33,7 @@ export const TYPES = {
|
||||
Mapper_SyncRequestGRPCMapper: Symbol.for('Mapper_SyncRequestGRPCMapper'),
|
||||
Mapper_SyncResponseGRPCMapper: Symbol.for('Mapper_SyncResponseGRPCMapper'),
|
||||
// Services
|
||||
ApiGateway_DomainEventFactory: Symbol.for('ApiGateway_DomainEventFactory'),
|
||||
ApiGateway_GRPCSyncingServerServiceProxy: Symbol.for('ApiGateway_GRPCSyncingServerServiceProxy'),
|
||||
ApiGateway_ServiceProxy: Symbol.for('ApiGateway_ServiceProxy'),
|
||||
ApiGateway_CrossServiceTokenCache: Symbol.for('ApiGateway_CrossServiceTokenCache'),
|
||||
|
||||
@@ -8,6 +8,8 @@ import { Logger } from 'winston'
|
||||
|
||||
import { CrossServiceTokenCacheInterface } from '../Service/Cache/CrossServiceTokenCacheInterface'
|
||||
import { ServiceProxyInterface } from '../Service/Proxy/ServiceProxyInterface'
|
||||
import { ResponseLocals } from './ResponseLocals'
|
||||
import { RoleName } from '@standardnotes/domain-core'
|
||||
|
||||
export abstract class AuthMiddleware extends BaseMiddleware {
|
||||
constructor(
|
||||
@@ -55,33 +57,27 @@ export abstract class AuthMiddleware extends BaseMiddleware {
|
||||
crossServiceTokenFetchedFromCache = false
|
||||
}
|
||||
|
||||
response.locals.authToken = crossServiceToken
|
||||
|
||||
const decodedToken = <CrossServiceTokenData>(
|
||||
verify(response.locals.authToken, this.jwtSecret, { algorithms: ['HS256'] })
|
||||
)
|
||||
const decodedToken = <CrossServiceTokenData>verify(crossServiceToken, this.jwtSecret, { algorithms: ['HS256'] })
|
||||
|
||||
if (this.crossServiceTokenCacheTTL && !crossServiceTokenFetchedFromCache) {
|
||||
await this.crossServiceTokenCache.set({
|
||||
key: cacheKey,
|
||||
encodedCrossServiceToken: response.locals.authToken,
|
||||
encodedCrossServiceToken: crossServiceToken,
|
||||
expiresAtInSeconds: this.getCrossServiceTokenCacheExpireTimestamp(decodedToken),
|
||||
userUuid: decodedToken.user.uuid,
|
||||
})
|
||||
}
|
||||
|
||||
response.locals.user = decodedToken.user
|
||||
response.locals.session = decodedToken.session
|
||||
response.locals.roles = decodedToken.roles
|
||||
response.locals.sharedVaultOwnerContext = decodedToken.shared_vault_owner_context
|
||||
response.locals.readOnlyAccess = decodedToken.session?.readonly_access ?? false
|
||||
if (response.locals.readOnlyAccess) {
|
||||
this.logger.debug('User operates on read-only access', {
|
||||
codeTag: 'AuthMiddleware',
|
||||
userId: response.locals.user.uuid,
|
||||
})
|
||||
}
|
||||
response.locals.belongsToSharedVaults = decodedToken.belongs_to_shared_vaults ?? []
|
||||
Object.assign(response.locals, {
|
||||
authToken: crossServiceToken,
|
||||
user: decodedToken.user,
|
||||
session: decodedToken.session,
|
||||
roles: decodedToken.roles,
|
||||
sharedVaultOwnerContext: decodedToken.shared_vault_owner_context,
|
||||
readOnlyAccess: decodedToken.session?.readonly_access ?? false,
|
||||
isFreeUser: decodedToken.roles.length === 1 && decodedToken.roles[0].name === RoleName.NAMES.CoreUser,
|
||||
belongsToSharedVaults: decodedToken.belongs_to_shared_vaults ?? [],
|
||||
} as ResponseLocals)
|
||||
} catch (error) {
|
||||
let detailedErrorMessage = (error as Error).message
|
||||
if (error instanceof AxiosError) {
|
||||
|
||||
@@ -6,6 +6,7 @@ import { verify } from 'jsonwebtoken'
|
||||
import { Logger } from 'winston'
|
||||
import { ConnectionValidationResponse, IAuthClient, WebsocketConnectionAuthorizationHeader } from '@standardnotes/grpc'
|
||||
import { RoleName } from '@standardnotes/domain-core'
|
||||
import { ResponseLocals } from './ResponseLocals'
|
||||
|
||||
export class GRPCWebSocketAuthMiddleware extends BaseMiddleware {
|
||||
constructor(
|
||||
@@ -90,15 +91,16 @@ export class GRPCWebSocketAuthMiddleware extends BaseMiddleware {
|
||||
|
||||
const crossServiceToken = authResponse.data.authToken as string
|
||||
|
||||
response.locals.authToken = crossServiceToken
|
||||
|
||||
const decodedToken = <CrossServiceTokenData>verify(crossServiceToken, this.jwtSecret, { algorithms: ['HS256'] })
|
||||
|
||||
response.locals.user = decodedToken.user
|
||||
response.locals.session = decodedToken.session
|
||||
response.locals.roles = decodedToken.roles
|
||||
response.locals.isFreeUser =
|
||||
decodedToken.roles.length === 1 && decodedToken.roles[0].name === RoleName.NAMES.CoreUser
|
||||
Object.assign(response.locals, {
|
||||
authToken: crossServiceToken,
|
||||
user: decodedToken.user,
|
||||
session: decodedToken.session,
|
||||
roles: decodedToken.roles,
|
||||
isFreeUser: decodedToken.roles.length === 1 && decodedToken.roles[0].name === RoleName.NAMES.CoreUser,
|
||||
readOnlyAccess: decodedToken.session?.readonly_access ?? false,
|
||||
} as ResponseLocals)
|
||||
} catch (error) {
|
||||
this.logger.error(
|
||||
`Could not pass the request to websocket connection validation on underlying service: ${
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
export interface OfflineResponseLocals {
|
||||
offlineAuthToken: string
|
||||
userEmail: string
|
||||
featuresToken: string
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import { Role } from '@standardnotes/security'
|
||||
|
||||
export interface ResponseLocals {
|
||||
authToken: string
|
||||
user: {
|
||||
uuid: string
|
||||
email: string
|
||||
}
|
||||
roles: Array<Role>
|
||||
session?: {
|
||||
uuid: string
|
||||
api_version: string
|
||||
created_at: string
|
||||
updated_at: string
|
||||
device_info: string
|
||||
readonly_access: boolean
|
||||
access_expiration: string
|
||||
refresh_expiration: string
|
||||
}
|
||||
readOnlyAccess: boolean
|
||||
isFreeUser: boolean
|
||||
belongsToSharedVaults?: Array<{
|
||||
shared_vault_uuid: string
|
||||
permission: string
|
||||
}>
|
||||
sharedVaultOwnerContext?: {
|
||||
upload_bytes_limit: number
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import { TokenAuthenticationMethod } from './TokenAuthenticationMethod'
|
||||
|
||||
export interface SubscriptionResponseLocals {
|
||||
tokenAuthenticationMethod: TokenAuthenticationMethod
|
||||
}
|
||||
@@ -7,6 +7,9 @@ import { AxiosError, AxiosInstance, AxiosResponse } from 'axios'
|
||||
import { Logger } from 'winston'
|
||||
import { TYPES } from '../Bootstrap/Types'
|
||||
import { TokenAuthenticationMethod } from './TokenAuthenticationMethod'
|
||||
import { ResponseLocals } from './ResponseLocals'
|
||||
import { OfflineResponseLocals } from './OfflineResponseLocals'
|
||||
import { SubscriptionResponseLocals } from './SubscriptionResponseLocals'
|
||||
|
||||
@injectable()
|
||||
export class SubscriptionTokenAuthMiddleware extends BaseMiddleware {
|
||||
@@ -34,13 +37,16 @@ export class SubscriptionTokenAuthMiddleware extends BaseMiddleware {
|
||||
return
|
||||
}
|
||||
|
||||
response.locals.tokenAuthenticationMethod = email
|
||||
? TokenAuthenticationMethod.OfflineSubscriptionToken
|
||||
: TokenAuthenticationMethod.SubscriptionToken
|
||||
const locals = {
|
||||
tokenAuthenticationMethod: email
|
||||
? TokenAuthenticationMethod.OfflineSubscriptionToken
|
||||
: TokenAuthenticationMethod.SubscriptionToken,
|
||||
} as SubscriptionResponseLocals
|
||||
Object.assign(response.locals, locals)
|
||||
|
||||
try {
|
||||
const url =
|
||||
response.locals.tokenAuthenticationMethod == TokenAuthenticationMethod.OfflineSubscriptionToken
|
||||
locals.tokenAuthenticationMethod == TokenAuthenticationMethod.OfflineSubscriptionToken
|
||||
? `${this.authServerUrl}/offline/subscription-tokens/${subscriptionToken}/validate`
|
||||
: `${this.authServerUrl}/subscription-tokens/${subscriptionToken}/validate`
|
||||
|
||||
@@ -65,7 +71,7 @@ export class SubscriptionTokenAuthMiddleware extends BaseMiddleware {
|
||||
return
|
||||
}
|
||||
|
||||
if (response.locals.tokenAuthenticationMethod == TokenAuthenticationMethod.OfflineSubscriptionToken) {
|
||||
if (locals.tokenAuthenticationMethod == TokenAuthenticationMethod.OfflineSubscriptionToken) {
|
||||
this.handleOfflineAuthTokenValidationResponse(response, authResponse)
|
||||
|
||||
return next()
|
||||
@@ -101,24 +107,26 @@ export class SubscriptionTokenAuthMiddleware extends BaseMiddleware {
|
||||
}
|
||||
|
||||
private handleOfflineAuthTokenValidationResponse(response: Response, authResponse: AxiosResponse) {
|
||||
response.locals.offlineAuthToken = authResponse.data.authToken
|
||||
|
||||
const decodedToken = <OfflineUserTokenData>(
|
||||
verify(authResponse.data.authToken, this.jwtSecret, { algorithms: ['HS256'] })
|
||||
)
|
||||
|
||||
response.locals.offlineUserEmail = decodedToken.userEmail
|
||||
response.locals.offlineFeaturesToken = decodedToken.featuresToken
|
||||
Object.assign(response.locals, {
|
||||
offlineAuthToken: authResponse.data.authToken,
|
||||
userEmail: decodedToken.userEmail,
|
||||
featuresToken: decodedToken.featuresToken,
|
||||
} as OfflineResponseLocals)
|
||||
}
|
||||
|
||||
private handleAuthTokenValidationResponse(response: Response, authResponse: AxiosResponse) {
|
||||
response.locals.authToken = authResponse.data.authToken
|
||||
|
||||
const decodedToken = <CrossServiceTokenData>(
|
||||
verify(authResponse.data.authToken, this.jwtSecret, { algorithms: ['HS256'] })
|
||||
)
|
||||
|
||||
response.locals.user = decodedToken.user
|
||||
response.locals.roles = decodedToken.roles
|
||||
Object.assign(response.locals, {
|
||||
authToken: authResponse.data.authToken,
|
||||
user: decodedToken.user,
|
||||
roles: decodedToken.roles,
|
||||
} as ResponseLocals)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import { AxiosError, AxiosInstance } from 'axios'
|
||||
import { Logger } from 'winston'
|
||||
|
||||
import { TYPES } from '../Bootstrap/Types'
|
||||
import { ResponseLocals } from './ResponseLocals'
|
||||
|
||||
@injectable()
|
||||
export class WebSocketAuthMiddleware extends BaseMiddleware {
|
||||
@@ -55,13 +56,14 @@ export class WebSocketAuthMiddleware extends BaseMiddleware {
|
||||
|
||||
const crossServiceToken = authResponse.data.authToken
|
||||
|
||||
response.locals.authToken = crossServiceToken
|
||||
|
||||
const decodedToken = <CrossServiceTokenData>verify(crossServiceToken, this.jwtSecret, { algorithms: ['HS256'] })
|
||||
|
||||
response.locals.user = decodedToken.user
|
||||
response.locals.session = decodedToken.session
|
||||
response.locals.roles = decodedToken.roles
|
||||
Object.assign(response.locals, {
|
||||
authToken: crossServiceToken,
|
||||
user: decodedToken.user,
|
||||
session: decodedToken.session,
|
||||
roles: decodedToken.roles,
|
||||
} as ResponseLocals)
|
||||
} catch (error) {
|
||||
const errorMessage = (error as AxiosError).isAxiosError
|
||||
? JSON.stringify((error as AxiosError).response?.data)
|
||||
|
||||
@@ -16,6 +16,8 @@ import { TYPES } from '../../Bootstrap/Types'
|
||||
import { ServiceProxyInterface } from '../../Service/Proxy/ServiceProxyInterface'
|
||||
import { TokenAuthenticationMethod } from '../TokenAuthenticationMethod'
|
||||
import { EndpointResolverInterface } from '../../Service/Resolver/EndpointResolverInterface'
|
||||
import { ResponseLocals } from '../ResponseLocals'
|
||||
import { SubscriptionResponseLocals } from '../SubscriptionResponseLocals'
|
||||
|
||||
@controller('/v1/users')
|
||||
export class UsersController extends BaseHttpController {
|
||||
@@ -214,7 +216,9 @@ export class UsersController extends BaseHttpController {
|
||||
|
||||
@httpGet('/subscription', TYPES.ApiGateway_SubscriptionTokenAuthMiddleware)
|
||||
async getSubscriptionBySubscriptionToken(request: Request, response: Response): Promise<void> {
|
||||
if (response.locals.tokenAuthenticationMethod === TokenAuthenticationMethod.OfflineSubscriptionToken) {
|
||||
const locals = response.locals as SubscriptionResponseLocals & ResponseLocals
|
||||
|
||||
if (locals.tokenAuthenticationMethod === TokenAuthenticationMethod.OfflineSubscriptionToken) {
|
||||
await this.httpService.callAuthServer(
|
||||
request,
|
||||
response,
|
||||
@@ -227,11 +231,7 @@ export class UsersController extends BaseHttpController {
|
||||
await this.httpService.callAuthServer(
|
||||
request,
|
||||
response,
|
||||
this.endpointResolver.resolveEndpointOrMethodIdentifier(
|
||||
'GET',
|
||||
'users/:userUuid/subscription',
|
||||
response.locals.user.uuid,
|
||||
),
|
||||
this.endpointResolver.resolveEndpointOrMethodIdentifier('GET', 'users/:userUuid/subscription', locals.user.uuid),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
import { TimerInterface } from '@standardnotes/time'
|
||||
|
||||
import { DomainEventFactoryInterface } from './DomainEventFactoryInterface'
|
||||
import { ContentSizesFixRequestedEvent, DomainEventService } from '@standardnotes/domain-events'
|
||||
|
||||
export class DomainEventFactory implements DomainEventFactoryInterface {
|
||||
constructor(private timer: TimerInterface) {}
|
||||
|
||||
createContentSizesFixRequestedEvent(dto: { userUuid: string }): ContentSizesFixRequestedEvent {
|
||||
return {
|
||||
type: 'CONTENT_SIZES_FIX_REQUESTED',
|
||||
createdAt: this.timer.getUTCDate(),
|
||||
meta: {
|
||||
correlation: {
|
||||
userIdentifier: dto.userUuid,
|
||||
userIdentifierType: 'uuid',
|
||||
},
|
||||
origin: DomainEventService.Auth,
|
||||
},
|
||||
payload: dto,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import { ContentSizesFixRequestedEvent } from '@standardnotes/domain-events'
|
||||
|
||||
export interface DomainEventFactoryInterface {
|
||||
createContentSizesFixRequestedEvent(dto: { userUuid: string }): ContentSizesFixRequestedEvent
|
||||
}
|
||||
@@ -2,6 +2,7 @@ import { Request, Response } from 'express'
|
||||
import { ServiceContainerInterface, ServiceIdentifier } from '@standardnotes/domain-core'
|
||||
|
||||
import { ServiceProxyInterface } from '../Proxy/ServiceProxyInterface'
|
||||
import { ResponseLocals } from '../../Controller/ResponseLocals'
|
||||
|
||||
export class DirectCallServiceProxy implements ServiceProxyInterface {
|
||||
constructor(
|
||||
@@ -134,11 +135,13 @@ export class DirectCallServiceProxy implements ServiceProxyInterface {
|
||||
response: Response,
|
||||
serviceResponse: { statusCode: number; json: Record<string, unknown> },
|
||||
): void {
|
||||
const locals = response.locals as ResponseLocals
|
||||
|
||||
void response.status(serviceResponse.statusCode).send({
|
||||
meta: {
|
||||
auth: {
|
||||
userUuid: response.locals.user?.uuid,
|
||||
roles: response.locals.roles,
|
||||
userUuid: locals.user?.uuid,
|
||||
roles: locals.roles,
|
||||
},
|
||||
server: {
|
||||
filesServerUrl: this.filesServerUrl,
|
||||
|
||||
@@ -8,6 +8,8 @@ import { TYPES } from '../../Bootstrap/Types'
|
||||
import { CrossServiceTokenCacheInterface } from '../Cache/CrossServiceTokenCacheInterface'
|
||||
import { ServiceProxyInterface } from '../Proxy/ServiceProxyInterface'
|
||||
import { TimerInterface } from '@standardnotes/time'
|
||||
import { ResponseLocals } from '../../Controller/ResponseLocals'
|
||||
import { OfflineResponseLocals } from '../../Controller/OfflineResponseLocals'
|
||||
|
||||
@injectable()
|
||||
export class HttpServiceProxy implements ServiceProxyInterface {
|
||||
@@ -175,8 +177,9 @@ export class HttpServiceProxy implements ServiceProxyInterface {
|
||||
response: Response,
|
||||
endpoint: string,
|
||||
payload?: Record<string, unknown> | string,
|
||||
retryAttempt?: number,
|
||||
): Promise<AxiosResponse | undefined> {
|
||||
const locals = response.locals as ResponseLocals | OfflineResponseLocals
|
||||
|
||||
try {
|
||||
const headers: Record<string, string> = {}
|
||||
for (const headerName of Object.keys(request.headers)) {
|
||||
@@ -186,12 +189,12 @@ export class HttpServiceProxy implements ServiceProxyInterface {
|
||||
delete headers.host
|
||||
delete headers['content-length']
|
||||
|
||||
if (response.locals.authToken) {
|
||||
headers['X-Auth-Token'] = response.locals.authToken
|
||||
if ('authToken' in locals && locals.authToken) {
|
||||
headers['X-Auth-Token'] = locals.authToken
|
||||
}
|
||||
|
||||
if (response.locals.offlineAuthToken) {
|
||||
headers['X-Auth-Offline-Token'] = response.locals.offlineAuthToken
|
||||
if ('offlineAuthToken' in locals && locals.offlineAuthToken) {
|
||||
headers['X-Auth-Offline-Token'] = locals.offlineAuthToken
|
||||
}
|
||||
|
||||
const serviceResponse = await this.httpClient.request({
|
||||
@@ -213,35 +216,17 @@ export class HttpServiceProxy implements ServiceProxyInterface {
|
||||
await this.crossServiceTokenCache.invalidate(userUuid)
|
||||
}
|
||||
|
||||
if (retryAttempt) {
|
||||
this.logger.debug(`Request to ${serverUrl}/${endpoint} succeeded after ${retryAttempt} retries`)
|
||||
}
|
||||
|
||||
return serviceResponse
|
||||
} catch (error) {
|
||||
const requestDidNotMakeIt = this.requestTimedOutOrDidNotReachDestination(error as Record<string, unknown>)
|
||||
const tooManyRetryAttempts = retryAttempt && retryAttempt > 2
|
||||
if (!tooManyRetryAttempts && requestDidNotMakeIt) {
|
||||
await this.timer.sleep(50)
|
||||
|
||||
const nextRetryAttempt = retryAttempt ? retryAttempt + 1 : 1
|
||||
|
||||
this.logger.debug(`Retrying request to ${serverUrl}/${endpoint} for the ${nextRetryAttempt} time`)
|
||||
|
||||
return this.getServerResponse(serverUrl, request, response, endpoint, payload, nextRetryAttempt)
|
||||
}
|
||||
|
||||
let detailedErrorMessage = (error as Error).message
|
||||
if (error instanceof AxiosError) {
|
||||
detailedErrorMessage = `Status: ${error.status}, code: ${error.code}, message: ${error.message}`
|
||||
}
|
||||
|
||||
this.logger.error(
|
||||
tooManyRetryAttempts
|
||||
? `Request to ${serverUrl}/${endpoint} timed out after ${retryAttempt} retries`
|
||||
: `Could not pass the request to ${serverUrl}/${endpoint} on underlying service: ${detailedErrorMessage}`,
|
||||
`Could not pass the request to ${serverUrl}/${endpoint} on underlying service: ${detailedErrorMessage}`,
|
||||
{
|
||||
userId: response.locals.user ? response.locals.user.uuid : undefined,
|
||||
userId: (locals as ResponseLocals).user ? (locals as ResponseLocals).user.uuid : undefined,
|
||||
},
|
||||
)
|
||||
|
||||
@@ -276,6 +261,7 @@ export class HttpServiceProxy implements ServiceProxyInterface {
|
||||
endpoint: string,
|
||||
payload?: Record<string, unknown> | string,
|
||||
): Promise<void> {
|
||||
const locals = response.locals as ResponseLocals
|
||||
const serviceResponse = await this.getServerResponse(serverUrl, request, response, endpoint, payload)
|
||||
|
||||
if (!serviceResponse) {
|
||||
@@ -293,8 +279,8 @@ export class HttpServiceProxy implements ServiceProxyInterface {
|
||||
response.status(serviceResponse.status).send({
|
||||
meta: {
|
||||
auth: {
|
||||
userUuid: response.locals.user?.uuid,
|
||||
roles: response.locals.roles,
|
||||
userUuid: locals.user?.uuid,
|
||||
roles: locals.roles,
|
||||
},
|
||||
server: {
|
||||
filesServerUrl: this.filesServerUrl,
|
||||
|
||||
@@ -40,7 +40,6 @@ export class EndpointResolver implements EndpointResolverInterface {
|
||||
// Tokens Controller
|
||||
['[POST]:subscription-tokens', 'auth.subscription-tokens.create'],
|
||||
// Users Controller
|
||||
['[PATCH]:users/:userId', 'auth.users.update'],
|
||||
['[PUT]:users/:userUuid/attributes/credentials', 'auth.users.updateCredentials'],
|
||||
['[DELETE]:users/:userUuid', 'auth.users.delete'],
|
||||
['[POST]:listed', 'auth.users.createListedAccount'],
|
||||
|
||||
@@ -9,6 +9,8 @@ import { CrossServiceTokenCacheInterface } from '../Cache/CrossServiceTokenCache
|
||||
import { ServiceProxyInterface } from '../Proxy/ServiceProxyInterface'
|
||||
import { GRPCSyncingServerServiceProxy } from './GRPCSyncingServerServiceProxy'
|
||||
import { Status } from '@grpc/grpc-js/build/src/constants'
|
||||
import { ResponseLocals } from '../../Controller/ResponseLocals'
|
||||
import { OfflineResponseLocals } from '../../Controller/OfflineResponseLocals'
|
||||
|
||||
export class GRPCServiceProxy implements ServiceProxyInterface {
|
||||
constructor(
|
||||
@@ -134,48 +136,23 @@ export class GRPCServiceProxy implements ServiceProxyInterface {
|
||||
request: Request,
|
||||
response: Response,
|
||||
payload?: Record<string, unknown> | string,
|
||||
retryAttempt?: number,
|
||||
): Promise<void> {
|
||||
try {
|
||||
const result = await this.gRPCSyncingServerServiceProxy.sync(request, response, payload)
|
||||
const locals = response.locals as ResponseLocals
|
||||
|
||||
response.status(result.status).send({
|
||||
meta: {
|
||||
auth: {
|
||||
userUuid: response.locals.user?.uuid,
|
||||
roles: response.locals.roles,
|
||||
},
|
||||
server: {
|
||||
filesServerUrl: this.filesServerUrl,
|
||||
},
|
||||
const result = await this.gRPCSyncingServerServiceProxy.sync(request, response, payload)
|
||||
|
||||
response.status(result.status).send({
|
||||
meta: {
|
||||
auth: {
|
||||
userUuid: locals.user?.uuid,
|
||||
roles: locals.roles,
|
||||
},
|
||||
data: result.data,
|
||||
})
|
||||
|
||||
if (retryAttempt) {
|
||||
this.logger.debug(`Request to Syncing Server succeeded after ${retryAttempt} retries`, {
|
||||
userId: response.locals.user ? response.locals.user.uuid : undefined,
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
const requestDidNotMakeIt =
|
||||
'code' in (error as Record<string, unknown>) && (error as Record<string, unknown>).code === Status.UNAVAILABLE
|
||||
|
||||
const tooManyRetryAttempts = retryAttempt && retryAttempt > 2
|
||||
if (!tooManyRetryAttempts && requestDidNotMakeIt) {
|
||||
await this.timer.sleep(50)
|
||||
|
||||
const nextRetryAttempt = retryAttempt ? retryAttempt + 1 : 1
|
||||
|
||||
this.logger.debug(`Retrying request to Syncing Server for the ${nextRetryAttempt} time`, {
|
||||
userId: response.locals.user ? response.locals.user.uuid : undefined,
|
||||
})
|
||||
|
||||
return this.callSyncingServerGRPC(request, response, payload, nextRetryAttempt)
|
||||
}
|
||||
|
||||
throw error
|
||||
}
|
||||
server: {
|
||||
filesServerUrl: this.filesServerUrl,
|
||||
},
|
||||
},
|
||||
data: result.data,
|
||||
})
|
||||
}
|
||||
|
||||
async callRevisionsServer(
|
||||
@@ -277,6 +254,8 @@ export class GRPCServiceProxy implements ServiceProxyInterface {
|
||||
payload?: Record<string, unknown> | string,
|
||||
retryAttempt?: number,
|
||||
): Promise<AxiosResponse | undefined> {
|
||||
const locals = response.locals as ResponseLocals | OfflineResponseLocals
|
||||
|
||||
try {
|
||||
const headers: Record<string, string> = {}
|
||||
for (const headerName of Object.keys(request.headers)) {
|
||||
@@ -286,12 +265,12 @@ export class GRPCServiceProxy implements ServiceProxyInterface {
|
||||
delete headers.host
|
||||
delete headers['content-length']
|
||||
|
||||
if (response.locals.authToken) {
|
||||
headers['X-Auth-Token'] = response.locals.authToken
|
||||
if ('authToken' in locals && locals.authToken) {
|
||||
headers['X-Auth-Token'] = locals.authToken
|
||||
}
|
||||
|
||||
if (response.locals.offlineAuthToken) {
|
||||
headers['X-Auth-Offline-Token'] = response.locals.offlineAuthToken
|
||||
if ('offlineAuthToken' in locals && locals.offlineAuthToken) {
|
||||
headers['X-Auth-Offline-Token'] = locals.offlineAuthToken
|
||||
}
|
||||
|
||||
const serviceResponse = await this.httpClient.request({
|
||||
@@ -341,7 +320,7 @@ export class GRPCServiceProxy implements ServiceProxyInterface {
|
||||
? `Request to ${serverUrl}/${endpoint} timed out after ${retryAttempt} retries`
|
||||
: `Could not pass the request to ${serverUrl}/${endpoint} on underlying service: ${detailedErrorMessage}`,
|
||||
{
|
||||
userId: response.locals.user ? response.locals.user.uuid : undefined,
|
||||
userId: (locals as ResponseLocals).user ? (locals as ResponseLocals).user.uuid : undefined,
|
||||
},
|
||||
)
|
||||
|
||||
@@ -376,6 +355,8 @@ export class GRPCServiceProxy implements ServiceProxyInterface {
|
||||
endpoint: string,
|
||||
payload?: Record<string, unknown> | string,
|
||||
): Promise<void> {
|
||||
const locals = response.locals as ResponseLocals
|
||||
|
||||
const serviceResponse = await this.getServerResponse(serverUrl, request, response, endpoint, payload)
|
||||
|
||||
if (!serviceResponse) {
|
||||
@@ -393,8 +374,8 @@ export class GRPCServiceProxy implements ServiceProxyInterface {
|
||||
response.status(serviceResponse.status).send({
|
||||
meta: {
|
||||
auth: {
|
||||
userUuid: response.locals.user?.uuid,
|
||||
roles: response.locals.roles,
|
||||
userUuid: locals.user?.uuid,
|
||||
roles: locals.roles,
|
||||
},
|
||||
server: {
|
||||
filesServerUrl: this.filesServerUrl,
|
||||
|
||||
@@ -1,18 +1,23 @@
|
||||
import { Request, Response } from 'express'
|
||||
import { ISyncingClient, SyncRequest, SyncResponse } from '@standardnotes/grpc'
|
||||
import { DomainEventPublisherInterface } from '@standardnotes/domain-events'
|
||||
import { MapperInterface } from '@standardnotes/domain-core'
|
||||
import { Metadata } from '@grpc/grpc-js'
|
||||
|
||||
import { SyncResponseHttpRepresentation } from '../../Mapping/Sync/Http/SyncResponseHttpRepresentation'
|
||||
import { Status } from '@grpc/grpc-js/build/src/constants'
|
||||
import { Logger } from 'winston'
|
||||
|
||||
import { SyncResponseHttpRepresentation } from '../../Mapping/Sync/Http/SyncResponseHttpRepresentation'
|
||||
import { ResponseLocals } from '../../Controller/ResponseLocals'
|
||||
import { DomainEventFactoryInterface } from '../../Event/DomainEventFactoryInterface'
|
||||
|
||||
export class GRPCSyncingServerServiceProxy {
|
||||
constructor(
|
||||
private syncingClient: ISyncingClient,
|
||||
private syncRequestGRPCMapper: MapperInterface<Record<string, unknown>, SyncRequest>,
|
||||
private syncResponseGRPCMapper: MapperInterface<SyncResponse, SyncResponseHttpRepresentation>,
|
||||
private logger: Logger,
|
||||
private domainEventFactory: DomainEventFactoryInterface,
|
||||
private domainEventPublisher?: DomainEventPublisherInterface,
|
||||
) {}
|
||||
|
||||
async sync(
|
||||
@@ -20,24 +25,26 @@ export class GRPCSyncingServerServiceProxy {
|
||||
response: Response,
|
||||
payload?: Record<string, unknown> | string,
|
||||
): Promise<{ status: number; data: unknown }> {
|
||||
const locals = response.locals as ResponseLocals
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
const syncRequest = this.syncRequestGRPCMapper.toProjection(payload as Record<string, unknown>)
|
||||
|
||||
const metadata = new Metadata()
|
||||
metadata.set('x-user-uuid', response.locals.user.uuid)
|
||||
metadata.set('x-user-uuid', locals.user.uuid)
|
||||
metadata.set('x-snjs-version', request.headers['x-snjs-version'] as string)
|
||||
metadata.set('x-read-only-access', response.locals.readOnlyAccess ? 'true' : 'false')
|
||||
if (response.locals.readOnlyAccess) {
|
||||
metadata.set('x-read-only-access', locals.readOnlyAccess ? 'true' : 'false')
|
||||
if (locals.readOnlyAccess) {
|
||||
this.logger.debug('Syncing with read-only access', {
|
||||
codeTag: 'GRPCSyncingServerServiceProxy',
|
||||
userId: response.locals.user.uuid,
|
||||
userId: locals.user.uuid,
|
||||
})
|
||||
}
|
||||
if (response.locals.session) {
|
||||
metadata.set('x-session-uuid', response.locals.session.uuid)
|
||||
if (locals.session) {
|
||||
metadata.set('x-session-uuid', locals.session.uuid)
|
||||
}
|
||||
metadata.set('x-is-free-user', response.locals.isFreeUser ? 'true' : 'false')
|
||||
metadata.set('x-is-free-user', locals.isFreeUser ? 'true' : 'false')
|
||||
|
||||
this.syncingClient.syncItems(syncRequest, metadata, (error, syncResponse) => {
|
||||
if (error) {
|
||||
@@ -52,10 +59,16 @@ export class GRPCSyncingServerServiceProxy {
|
||||
if (error.code === Status.INTERNAL) {
|
||||
this.logger.error(`Internal gRPC error: ${error.message}. Payload: ${JSON.stringify(payload)}`, {
|
||||
codeTag: 'GRPCSyncingServerServiceProxy',
|
||||
userId: response.locals.user.uuid,
|
||||
userId: locals.user.uuid,
|
||||
})
|
||||
}
|
||||
|
||||
if (error.code === Status.RESOURCE_EXHAUSTED && this.domainEventPublisher !== undefined) {
|
||||
void this.domainEventPublisher.publish(
|
||||
this.domainEventFactory.createContentSizesFixRequestedEvent({ userUuid: locals.user.uuid }),
|
||||
)
|
||||
}
|
||||
|
||||
return reject(error)
|
||||
}
|
||||
|
||||
@@ -68,7 +81,7 @@ export class GRPCSyncingServerServiceProxy {
|
||||
) {
|
||||
this.logger.error(`Internal gRPC error: ${JSON.stringify(error)}. Payload: ${JSON.stringify(payload)}`, {
|
||||
codeTag: 'GRPCSyncingServerServiceProxy.catch',
|
||||
userId: response.locals.user.uuid,
|
||||
userId: locals.user.uuid,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,55 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [1.178.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.177.20...@standardnotes/auth-server@1.178.0) (2024-01-19)
|
||||
|
||||
### Features
|
||||
|
||||
* **auth:** add script for fixing subscriptions with missing id state ([#1030](https://github.com/standardnotes/server/issues/1030)) ([86b0508](https://github.com/standardnotes/server/commit/86b050865f8090ed33d5ce05528ff0e1e23657ef))
|
||||
|
||||
## [1.177.20](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.177.19...@standardnotes/auth-server@1.177.20) (2024-01-18)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/auth-server
|
||||
|
||||
## [1.177.19](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.177.18...@standardnotes/auth-server@1.177.19) (2024-01-17)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **auth:** add server daily email backup permission for all versions of core user role ([#1028](https://github.com/standardnotes/server/issues/1028)) ([460fdf9](https://github.com/standardnotes/server/commit/460fdf9eafe2db629637ba481f2b135ed21560b9))
|
||||
|
||||
## [1.177.18](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.177.17...@standardnotes/auth-server@1.177.18) (2024-01-15)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **auth:** add more logs to syncing subscription ([c7217a9](https://github.com/standardnotes/server/commit/c7217a92ba89d8b5f4963a832aa7561dd146ca0d))
|
||||
* **auth:** add renewal for shared offline subscriptions ([045358d](https://github.com/standardnotes/server/commit/045358ddbf300996a23bba8d6945b1d7b5f6e862))
|
||||
|
||||
## [1.177.17](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.177.16...@standardnotes/auth-server@1.177.17) (2024-01-15)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **auth:** add debug logs for subscription sync requested event ([351e18f](https://github.com/standardnotes/server/commit/351e18f6389c2dbaa2107e6549be9928c2e8834f))
|
||||
|
||||
## [1.177.16](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.177.15...@standardnotes/auth-server@1.177.16) (2024-01-15)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **auth:** update shared subscriptions upon subscription sync ([#1022](https://github.com/standardnotes/server/issues/1022)) ([d7a1c66](https://github.com/standardnotes/server/commit/d7a1c667dd62dacc1ef15f2a4f408dc07045fcad))
|
||||
|
||||
## [1.177.15](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.177.14...@standardnotes/auth-server@1.177.15) (2024-01-09)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **auth:** check for user agent persisting on session during a session refresh ([#1016](https://github.com/standardnotes/server/issues/1016)) ([0b46eff](https://github.com/standardnotes/server/commit/0b46eff16ea0c32cac91ead04474303500359f4f))
|
||||
|
||||
## [1.177.14](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.177.13...@standardnotes/auth-server@1.177.14) (2024-01-08)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/auth-server
|
||||
|
||||
## [1.177.13](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.177.12...@standardnotes/auth-server@1.177.13) (2024-01-04)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/auth-server
|
||||
|
||||
## [1.177.12](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.177.11...@standardnotes/auth-server@1.177.12) (2024-01-03)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/auth-server
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
import 'reflect-metadata'
|
||||
|
||||
import { Logger } from 'winston'
|
||||
|
||||
import { ContainerConfigLoader } from '../src/Bootstrap/Container'
|
||||
import TYPES from '../src/Bootstrap/Types'
|
||||
import { Env } from '../src/Bootstrap/Env'
|
||||
import { UserSubscriptionRepositoryInterface } from '../src/Domain/Subscription/UserSubscriptionRepositoryInterface'
|
||||
import { DomainEventFactoryInterface } from '../src/Domain/Event/DomainEventFactoryInterface'
|
||||
import { DomainEventPublisherInterface } from '@standardnotes/domain-events'
|
||||
import { UserRepositoryInterface } from '../src/Domain/User/UserRepositoryInterface'
|
||||
import { Uuid } from '@standardnotes/domain-core'
|
||||
|
||||
const fixSubscriptions = async (
|
||||
userRepository: UserRepositoryInterface,
|
||||
userSubscriptionRepository: UserSubscriptionRepositoryInterface,
|
||||
domainEventFactory: DomainEventFactoryInterface,
|
||||
domainEventPublisher: DomainEventPublisherInterface,
|
||||
): Promise<void> => {
|
||||
const subscriptions = await userSubscriptionRepository.findBySubscriptionId(0)
|
||||
|
||||
for (const subscription of subscriptions) {
|
||||
const userUuidOrError = Uuid.create(subscription.userUuid)
|
||||
if (userUuidOrError.isFailed()) {
|
||||
continue
|
||||
}
|
||||
const userUuid = userUuidOrError.getValue()
|
||||
|
||||
const user = await userRepository.findOneByUuid(userUuid)
|
||||
if (!user) {
|
||||
continue
|
||||
}
|
||||
|
||||
await domainEventPublisher.publish(
|
||||
domainEventFactory.createSubscriptionStateRequestedEvent({
|
||||
userEmail: user.email,
|
||||
}),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const container = new ContainerConfigLoader('worker')
|
||||
void container.load().then((container) => {
|
||||
const env: Env = new Env()
|
||||
env.load()
|
||||
|
||||
const logger: Logger = container.get(TYPES.Auth_Logger)
|
||||
|
||||
logger.info('Starting to fix subscriptions with missing subscriptionId ...')
|
||||
|
||||
const userRepository = container.get<UserRepositoryInterface>(TYPES.Auth_UserRepository)
|
||||
const userSubscriptionRepository = container.get<UserSubscriptionRepositoryInterface>(
|
||||
TYPES.Auth_UserSubscriptionRepository,
|
||||
)
|
||||
const domainEventFactory = container.get<DomainEventFactoryInterface>(TYPES.Auth_DomainEventFactory)
|
||||
const domainEventPublisher = container.get<DomainEventPublisherInterface>(TYPES.Auth_DomainEventPublisher)
|
||||
|
||||
Promise.resolve(
|
||||
fixSubscriptions(userRepository, userSubscriptionRepository, domainEventFactory, domainEventPublisher),
|
||||
)
|
||||
.then(() => {
|
||||
logger.info('Finished fixing subscriptions with missing subscriptionId.')
|
||||
|
||||
process.exit(0)
|
||||
})
|
||||
.catch((error) => {
|
||||
logger.error('Failed to fix subscriptions with missing subscriptionId.', {
|
||||
error: error.message,
|
||||
stack: error.stack,
|
||||
})
|
||||
|
||||
process.exit(1)
|
||||
})
|
||||
})
|
||||
@@ -35,6 +35,7 @@ import { AuthService } from '@standardnotes/grpc'
|
||||
import { AuthenticateRequest } from '../src/Domain/UseCase/AuthenticateRequest'
|
||||
import { CreateCrossServiceToken } from '../src/Domain/UseCase/CreateCrossServiceToken/CreateCrossServiceToken'
|
||||
import { TokenDecoderInterface, WebSocketConnectionTokenData } from '@standardnotes/security'
|
||||
import { ResponseLocals } from '../src/Infra/InversifyExpressUtils/ResponseLocals'
|
||||
|
||||
const container = new ContainerConfigLoader()
|
||||
void container.load().then((container) => {
|
||||
@@ -59,12 +60,13 @@ void container.load().then((container) => {
|
||||
|
||||
server.setErrorConfig((app) => {
|
||||
app.use((error: Record<string, unknown>, request: Request, response: Response, _next: NextFunction) => {
|
||||
const locals = response.locals as ResponseLocals
|
||||
logger.error(`${error.stack}`, {
|
||||
method: request.method,
|
||||
url: request.url,
|
||||
snjs: request.headers['x-snjs-version'],
|
||||
application: request.headers['x-application-version'],
|
||||
userId: response.locals.user ? response.locals.user.uuid : undefined,
|
||||
userId: locals.user ? locals.user.uuid : undefined,
|
||||
})
|
||||
|
||||
response.status(500).send({
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
'use strict'
|
||||
|
||||
const path = require('path')
|
||||
|
||||
const pnp = require(path.normalize(path.resolve(__dirname, '../../..', '.pnp.cjs'))).setup()
|
||||
|
||||
const index = require(path.normalize(path.resolve(__dirname, '../dist/bin/fix_subscriptions.js')))
|
||||
|
||||
Object.defineProperty(exports, '__esModule', { value: true })
|
||||
|
||||
exports.default = index
|
||||
@@ -42,6 +42,10 @@ case "$COMMAND" in
|
||||
exec node docker/entrypoint-fix-roles.js
|
||||
;;
|
||||
|
||||
'fix-subscriptions' )
|
||||
exec node docker/entrypoint-fix-subscriptions.js
|
||||
;;
|
||||
|
||||
'delete-accounts' )
|
||||
FILE_NAME=$1 && shift 1
|
||||
MODE=$1 && shift 1
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm'
|
||||
|
||||
export class EnableEmailBackupsForAll1705493201352 implements MigrationInterface {
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
// Core User v1 Permissions
|
||||
await queryRunner.query(
|
||||
'INSERT INTO `role_permissions` (role_uuid, permission_uuid) VALUES \
|
||||
("bde42e26-628c-44e6-9d76-21b08954b0bf", "eb0575a2-6e26-49e3-9501-f2e75d7dbda3") \
|
||||
',
|
||||
)
|
||||
// Core User v2 Permissions
|
||||
await queryRunner.query(
|
||||
'INSERT INTO `role_permissions` (role_uuid, permission_uuid) VALUES \
|
||||
("23bf88ca-bee1-4a4c-adf0-b7a48749eea7", "eb0575a2-6e26-49e3-9501-f2e75d7dbda3") \
|
||||
',
|
||||
)
|
||||
}
|
||||
|
||||
public async down(): Promise<void> {
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm'
|
||||
|
||||
export class EnableEmailBackupsForAll1705493490376 implements MigrationInterface {
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
// Core User v1 Permissions
|
||||
await queryRunner.query(
|
||||
'INSERT INTO `role_permissions` (role_uuid, permission_uuid) VALUES \
|
||||
("bde42e26-628c-44e6-9d76-21b08954b0bf", "eb0575a2-6e26-49e3-9501-f2e75d7dbda3") \
|
||||
',
|
||||
)
|
||||
// Core User v2 Permissions
|
||||
await queryRunner.query(
|
||||
'INSERT INTO `role_permissions` (role_uuid, permission_uuid) VALUES \
|
||||
("23bf88ca-bee1-4a4c-adf0-b7a48749eea7", "eb0575a2-6e26-49e3-9501-f2e75d7dbda3") \
|
||||
',
|
||||
)
|
||||
}
|
||||
|
||||
public async down(): Promise<void> {
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/auth-server",
|
||||
"version": "1.177.12",
|
||||
"version": "1.178.0",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <21.0.0"
|
||||
},
|
||||
|
||||
@@ -284,6 +284,8 @@ import { AccountDeletionVerificationPassedEventHandler } from '../Domain/Handler
|
||||
import { RenewSharedSubscriptions } from '../Domain/UseCase/RenewSharedSubscriptions/RenewSharedSubscriptions'
|
||||
import { FixStorageQuotaForUser } from '../Domain/UseCase/FixStorageQuotaForUser/FixStorageQuotaForUser'
|
||||
import { FileQuotaRecalculatedEventHandler } from '../Domain/Handler/FileQuotaRecalculatedEventHandler'
|
||||
import { SessionServiceInterface } from '../Domain/Session/SessionServiceInterface'
|
||||
import { SubscriptionStateFetchedEventHandler } from '../Domain/Handler/SubscriptionStateFetchedEventHandler'
|
||||
|
||||
export class ContainerConfigLoader {
|
||||
constructor(private mode: 'server' | 'worker' = 'server') {}
|
||||
@@ -986,7 +988,18 @@ export class ContainerConfigLoader {
|
||||
.toConstantValue(new CleanupExpiredSessions(container.get(TYPES.Auth_SessionRepository)))
|
||||
container.bind<AuthenticateUser>(TYPES.Auth_AuthenticateUser).to(AuthenticateUser)
|
||||
container.bind<AuthenticateRequest>(TYPES.Auth_AuthenticateRequest).to(AuthenticateRequest)
|
||||
container.bind<RefreshSessionToken>(TYPES.Auth_RefreshSessionToken).to(RefreshSessionToken)
|
||||
container
|
||||
.bind<RefreshSessionToken>(TYPES.Auth_RefreshSessionToken)
|
||||
.toConstantValue(
|
||||
new RefreshSessionToken(
|
||||
container.get<SessionServiceInterface>(TYPES.Auth_SessionService),
|
||||
container.get<DomainEventFactoryInterface>(TYPES.Auth_DomainEventFactory),
|
||||
container.get<DomainEventPublisherInterface>(TYPES.Auth_DomainEventPublisher),
|
||||
container.get<TimerInterface>(TYPES.Auth_Timer),
|
||||
container.get<GetSetting>(TYPES.Auth_GetSetting),
|
||||
container.get<winston.Logger>(TYPES.Auth_Logger),
|
||||
),
|
||||
)
|
||||
container.bind<SignIn>(TYPES.Auth_SignIn).to(SignIn)
|
||||
container
|
||||
.bind<VerifyMFA>(TYPES.Auth_VerifyMFA)
|
||||
@@ -1409,6 +1422,7 @@ export class ContainerConfigLoader {
|
||||
container.get<SetSettingValue>(TYPES.Auth_SetSettingValue),
|
||||
container.get<OfflineSettingServiceInterface>(TYPES.Auth_OfflineSettingService),
|
||||
container.get<ContentDecoderInterface>(TYPES.Auth_ContenDecoder),
|
||||
container.get<RenewSharedSubscriptions>(TYPES.Auth_RenewSharedSubscriptions),
|
||||
container.get<winston.Logger>(TYPES.Auth_Logger),
|
||||
),
|
||||
)
|
||||
@@ -1566,6 +1580,16 @@ export class ContainerConfigLoader {
|
||||
container.get<winston.Logger>(TYPES.Auth_Logger),
|
||||
),
|
||||
)
|
||||
container
|
||||
.bind<SubscriptionStateFetchedEventHandler>(TYPES.Auth_SubscriptionStateFetchedEventHandler)
|
||||
.toConstantValue(
|
||||
new SubscriptionStateFetchedEventHandler(
|
||||
container.get<UserRepositoryInterface>(TYPES.Auth_UserRepository),
|
||||
container.get<UserSubscriptionRepositoryInterface>(TYPES.Auth_UserSubscriptionRepository),
|
||||
container.get<OfflineUserSubscriptionRepositoryInterface>(TYPES.Auth_OfflineUserSubscriptionRepository),
|
||||
container.get<winston.Logger>(TYPES.Auth_Logger),
|
||||
),
|
||||
)
|
||||
|
||||
const eventHandlers: Map<string, DomainEventHandlerInterface> = new Map([
|
||||
['ACCOUNT_DELETION_REQUESTED', container.get(TYPES.Auth_AccountDeletionRequestedEventHandler)],
|
||||
@@ -1607,6 +1631,7 @@ export class ContainerConfigLoader {
|
||||
'FILE_QUOTA_RECALCULATED',
|
||||
container.get<FileQuotaRecalculatedEventHandler>(TYPES.Auth_FileQuotaRecalculatedEventHandler),
|
||||
],
|
||||
['SUBSCRIPTION_STATE_FETCHED', container.get(TYPES.Auth_SubscriptionStateFetchedEventHandler)],
|
||||
])
|
||||
|
||||
if (isConfiguredForHomeServer) {
|
||||
@@ -1708,7 +1733,6 @@ export class ContainerConfigLoader {
|
||||
.bind<BaseUsersController>(TYPES.Auth_BaseUsersController)
|
||||
.toConstantValue(
|
||||
new BaseUsersController(
|
||||
container.get<UpdateUser>(TYPES.Auth_UpdateUser),
|
||||
container.get<DeleteAccount>(TYPES.Auth_DeleteAccount),
|
||||
container.get<GetUserSubscription>(TYPES.Auth_GetUserSubscription),
|
||||
container.get<ClearLoginAttempts>(TYPES.Auth_ClearLoginAttempts),
|
||||
|
||||
@@ -205,6 +205,7 @@ const TYPES = {
|
||||
),
|
||||
Auth_UserInvitedToSharedVaultEventHandler: Symbol.for('Auth_UserInvitedToSharedVaultEventHandler'),
|
||||
Auth_FileQuotaRecalculatedEventHandler: Symbol.for('Auth_FileQuotaRecalculatedEventHandler'),
|
||||
Auth_SubscriptionStateFetchedEventHandler: Symbol.for('Auth_SubscriptionStateFetchedEventHandler'),
|
||||
// Services
|
||||
Auth_DeviceDetector: Symbol.for('Auth_DeviceDetector'),
|
||||
Auth_SessionService: Symbol.for('Auth_SessionService'),
|
||||
|
||||
@@ -22,6 +22,7 @@ import {
|
||||
SessionRefreshedEvent,
|
||||
AccountDeletionVerificationRequestedEvent,
|
||||
FileQuotaRecalculationRequestedEvent,
|
||||
SubscriptionStateRequestedEvent,
|
||||
} from '@standardnotes/domain-events'
|
||||
import { Predicate, PredicateVerificationResult } from '@standardnotes/predicates'
|
||||
import { TimerInterface } from '@standardnotes/time'
|
||||
@@ -34,6 +35,21 @@ import { KeyParamsData } from '@standardnotes/responses'
|
||||
@injectable()
|
||||
export class DomainEventFactory implements DomainEventFactoryInterface {
|
||||
constructor(@inject(TYPES.Auth_Timer) private timer: TimerInterface) {}
|
||||
createSubscriptionStateRequestedEvent(dto: { userEmail: string }): SubscriptionStateRequestedEvent {
|
||||
return {
|
||||
type: 'SUBSCRIPTION_STATE_REQUESTED',
|
||||
createdAt: this.timer.getUTCDate(),
|
||||
meta: {
|
||||
correlation: {
|
||||
userIdentifier: dto.userEmail,
|
||||
userIdentifierType: 'email',
|
||||
},
|
||||
origin: DomainEventService.Auth,
|
||||
},
|
||||
payload: dto,
|
||||
}
|
||||
}
|
||||
|
||||
createFileQuotaRecalculationRequestedEvent(dto: { userUuid: string }): FileQuotaRecalculationRequestedEvent {
|
||||
return {
|
||||
type: 'FILE_QUOTA_RECALCULATION_REQUESTED',
|
||||
|
||||
@@ -20,11 +20,13 @@ import {
|
||||
SessionRefreshedEvent,
|
||||
AccountDeletionVerificationRequestedEvent,
|
||||
FileQuotaRecalculationRequestedEvent,
|
||||
SubscriptionStateRequestedEvent,
|
||||
} from '@standardnotes/domain-events'
|
||||
import { InviteeIdentifierType } from '../SharedSubscription/InviteeIdentifierType'
|
||||
import { KeyParamsData } from '@standardnotes/responses'
|
||||
|
||||
export interface DomainEventFactoryInterface {
|
||||
createSubscriptionStateRequestedEvent(dto: { userEmail: string }): SubscriptionStateRequestedEvent
|
||||
createFileQuotaRecalculationRequestedEvent(dto: { userUuid: string }): FileQuotaRecalculationRequestedEvent
|
||||
createWebSocketMessageRequestedEvent(dto: { userUuid: string; message: JSONString }): WebSocketMessageRequestedEvent
|
||||
createEmailRequestedEvent(dto: {
|
||||
|
||||
@@ -4,6 +4,7 @@ import { inject, injectable } from 'inversify'
|
||||
import TYPES from '../../Bootstrap/Types'
|
||||
import { UserSubscriptionRepositoryInterface } from '../Subscription/UserSubscriptionRepositoryInterface'
|
||||
import { OfflineUserSubscriptionRepositoryInterface } from '../Subscription/OfflineUserSubscriptionRepositoryInterface'
|
||||
import { Logger } from 'winston'
|
||||
|
||||
@injectable()
|
||||
export class SubscriptionCancelledEventHandler implements DomainEventHandlerInterface {
|
||||
@@ -12,9 +13,20 @@ export class SubscriptionCancelledEventHandler implements DomainEventHandlerInte
|
||||
private userSubscriptionRepository: UserSubscriptionRepositoryInterface,
|
||||
@inject(TYPES.Auth_OfflineUserSubscriptionRepository)
|
||||
private offlineUserSubscriptionRepository: OfflineUserSubscriptionRepositoryInterface,
|
||||
@inject(TYPES.Auth_Logger) private logger: Logger,
|
||||
) {}
|
||||
|
||||
async handle(event: SubscriptionCancelledEvent): Promise<void> {
|
||||
if (!event.payload.subscriptionId) {
|
||||
this.logger.error('Subscription ID is missing', {
|
||||
codeTag: 'SubscriptionCancelledEventHandler.handle',
|
||||
subscriptionId: event.payload.subscriptionId,
|
||||
userId: event.payload.userEmail,
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if (event.payload.offline) {
|
||||
await this.updateOfflineSubscriptionCancelled(event.payload.subscriptionId, event.payload.timestamp)
|
||||
|
||||
|
||||
@@ -22,6 +22,16 @@ export class SubscriptionExpiredEventHandler implements DomainEventHandlerInterf
|
||||
) {}
|
||||
|
||||
async handle(event: SubscriptionExpiredEvent): Promise<void> {
|
||||
if (!event.payload.subscriptionId) {
|
||||
this.logger.error('Subscription ID is missing', {
|
||||
codeTag: 'SubscriptionExpiredEventHandler.handle',
|
||||
subscriptionId: event.payload.subscriptionId,
|
||||
userId: event.payload.userEmail,
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if (event.payload.offline) {
|
||||
await this.updateOfflineSubscriptionEndsAt(event.payload.subscriptionId, event.payload.timestamp)
|
||||
|
||||
|
||||
@@ -25,6 +25,16 @@ export class SubscriptionPurchasedEventHandler implements DomainEventHandlerInte
|
||||
) {}
|
||||
|
||||
async handle(event: SubscriptionPurchasedEvent): Promise<void> {
|
||||
if (!event.payload.subscriptionId) {
|
||||
this.logger.error('Subscription ID is missing', {
|
||||
codeTag: 'SubscriptionPurchasedEventHandler.handle',
|
||||
subscriptionId: event.payload.subscriptionId,
|
||||
userId: event.payload.userEmail,
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if (event.payload.offline) {
|
||||
const offlineUserSubscription = await this.createOfflineSubscription(
|
||||
event.payload.subscriptionId,
|
||||
@@ -34,6 +44,19 @@ export class SubscriptionPurchasedEventHandler implements DomainEventHandlerInte
|
||||
event.payload.timestamp,
|
||||
)
|
||||
|
||||
const renewalResult = await this.renewSharedSubscriptions.execute({
|
||||
inviterEmail: event.payload.userEmail,
|
||||
newSubscriptionId: event.payload.subscriptionId,
|
||||
newSubscriptionName: event.payload.subscriptionName,
|
||||
newSubscriptionExpiresAt: event.payload.subscriptionExpiresAt,
|
||||
timestamp: event.payload.timestamp,
|
||||
})
|
||||
if (renewalResult.isFailed()) {
|
||||
this.logger.error(`Could not renew shared offline subscriptions: ${renewalResult.getError()}`, {
|
||||
subscriptionId: event.payload.subscriptionId,
|
||||
})
|
||||
}
|
||||
|
||||
await this.roleService.setOfflineUserRole(offlineUserSubscription)
|
||||
|
||||
return
|
||||
|
||||
@@ -22,6 +22,16 @@ export class SubscriptionReassignedEventHandler implements DomainEventHandlerInt
|
||||
) {}
|
||||
|
||||
async handle(event: SubscriptionReassignedEvent): Promise<void> {
|
||||
if (!event.payload.subscriptionId) {
|
||||
this.logger.error('Subscription ID is missing', {
|
||||
codeTag: 'SubscriptionReassignedEventHandler.handle',
|
||||
subscriptionId: event.payload.subscriptionId,
|
||||
userId: event.payload.userEmail,
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
const usernameOrError = Username.create(event.payload.userEmail)
|
||||
if (usernameOrError.isFailed()) {
|
||||
return
|
||||
|
||||
@@ -22,6 +22,16 @@ export class SubscriptionRefundedEventHandler implements DomainEventHandlerInter
|
||||
) {}
|
||||
|
||||
async handle(event: SubscriptionRefundedEvent): Promise<void> {
|
||||
if (!event.payload.subscriptionId) {
|
||||
this.logger.error('Subscription ID is missing', {
|
||||
codeTag: 'SubscriptionRefundedEventHandler.handle',
|
||||
subscriptionId: event.payload.subscriptionId,
|
||||
userId: event.payload.userEmail,
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if (event.payload.offline) {
|
||||
await this.updateOfflineSubscriptionEndsAt(event.payload.subscriptionId, event.payload.timestamp)
|
||||
|
||||
|
||||
@@ -23,6 +23,16 @@ export class SubscriptionRenewedEventHandler implements DomainEventHandlerInterf
|
||||
) {}
|
||||
|
||||
async handle(event: SubscriptionRenewedEvent): Promise<void> {
|
||||
if (!event.payload.subscriptionId) {
|
||||
this.logger.error('Subscription ID is missing', {
|
||||
codeTag: 'SubscriptionRenewedEventHandler.handle',
|
||||
subscriptionId: event.payload.subscriptionId,
|
||||
userId: event.payload.userEmail,
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if (event.payload.offline) {
|
||||
const offlineUserSubscription = await this.offlineUserSubscriptionRepository.findOneBySubscriptionId(
|
||||
event.payload.subscriptionId,
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
import { Username } from '@standardnotes/domain-core'
|
||||
import { DomainEventHandlerInterface, SubscriptionStateFetchedEvent } from '@standardnotes/domain-events'
|
||||
import { Logger } from 'winston'
|
||||
|
||||
import { UserRepositoryInterface } from '../User/UserRepositoryInterface'
|
||||
import { UserSubscriptionRepositoryInterface } from '../Subscription/UserSubscriptionRepositoryInterface'
|
||||
import { OfflineUserSubscriptionRepositoryInterface } from '../Subscription/OfflineUserSubscriptionRepositoryInterface'
|
||||
|
||||
export class SubscriptionStateFetchedEventHandler implements DomainEventHandlerInterface {
|
||||
constructor(
|
||||
private userRepository: UserRepositoryInterface,
|
||||
private userSubscriptionRepository: UserSubscriptionRepositoryInterface,
|
||||
private offlineUserSubscriptionRepository: OfflineUserSubscriptionRepositoryInterface,
|
||||
private logger: Logger,
|
||||
) {}
|
||||
|
||||
async handle(event: SubscriptionStateFetchedEvent): Promise<void> {
|
||||
if (!event.payload.subscriptionId) {
|
||||
this.logger.error('Subscription ID is missing', {
|
||||
codeTag: 'SubscriptionStateFetchedEventHandler.handle',
|
||||
subscriptionId: event.payload.subscriptionId,
|
||||
userId: event.payload.userEmail,
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
this.logger.info('Subscription state update fetched', {
|
||||
subscriptionId: event.payload.subscriptionId,
|
||||
})
|
||||
|
||||
if (event.payload.offline) {
|
||||
this.logger.info('Updating offline subscription', {
|
||||
subscriptionId: event.payload.subscriptionId,
|
||||
})
|
||||
|
||||
const subscription = await this.offlineUserSubscriptionRepository.findOneByEmailAndSubscriptionId(
|
||||
event.payload.userEmail,
|
||||
0,
|
||||
)
|
||||
if (!subscription) {
|
||||
this.logger.error('Offline subscription not found', {
|
||||
subscriptionId: event.payload.subscriptionId,
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
subscription.planName = event.payload.subscriptionName
|
||||
subscription.email = event.payload.userEmail
|
||||
subscription.endsAt = event.payload.subscriptionExpiresAt
|
||||
subscription.cancelled = event.payload.canceled
|
||||
if (subscription.subscriptionId !== event.payload.subscriptionId) {
|
||||
this.logger.warn('Subscription IDs do not match', {
|
||||
previousSubscriptionId: subscription.subscriptionId,
|
||||
subscriptionId: event.payload.subscriptionId,
|
||||
})
|
||||
}
|
||||
subscription.subscriptionId = event.payload.subscriptionId
|
||||
|
||||
await this.offlineUserSubscriptionRepository.save(subscription)
|
||||
|
||||
this.logger.info('Offline subscription updated', {
|
||||
subscriptionId: event.payload.subscriptionId,
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
const usernameOrError = Username.create(event.payload.userEmail)
|
||||
if (usernameOrError.isFailed()) {
|
||||
this.logger.warn(`Could not update subscription: ${usernameOrError.getError()}`, {
|
||||
subscriptionId: event.payload.subscriptionId,
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
const username = usernameOrError.getValue()
|
||||
|
||||
const user = await this.userRepository.findOneByUsernameOrEmail(username)
|
||||
|
||||
if (user === null) {
|
||||
this.logger.warn(`Could not find user with email: ${username.value}`, {
|
||||
subscriptionId: event.payload.subscriptionId,
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
this.logger.info('Updating subscription', {
|
||||
userId: user.uuid,
|
||||
subscriptionId: event.payload.subscriptionId,
|
||||
})
|
||||
|
||||
const subscription = await this.userSubscriptionRepository.findOneByUserUuidAndSubscriptionId(user.uuid, 0)
|
||||
if (!subscription) {
|
||||
this.logger.error('Subscription not found', {
|
||||
userId: user.uuid,
|
||||
subscriptionId: event.payload.subscriptionId,
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
subscription.planName = event.payload.subscriptionName
|
||||
subscription.endsAt = event.payload.subscriptionExpiresAt
|
||||
subscription.cancelled = event.payload.canceled
|
||||
if (subscription.subscriptionId !== event.payload.subscriptionId) {
|
||||
this.logger.warn('Subscription IDs do not match', {
|
||||
previousSubscriptionId: subscription.subscriptionId,
|
||||
subscriptionId: event.payload.subscriptionId,
|
||||
})
|
||||
}
|
||||
subscription.subscriptionId = event.payload.subscriptionId
|
||||
|
||||
await this.userSubscriptionRepository.save(subscription)
|
||||
|
||||
this.logger.info('Subscription updated to current state', {
|
||||
userId: user.uuid,
|
||||
subscriptionId: event.payload.subscriptionId,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@ import { OfflineSettingName } from '../Setting/OfflineSettingName'
|
||||
import { UserSubscriptionType } from '../Subscription/UserSubscriptionType'
|
||||
import { ApplyDefaultSubscriptionSettings } from '../UseCase/ApplyDefaultSubscriptionSettings/ApplyDefaultSubscriptionSettings'
|
||||
import { SetSettingValue } from '../UseCase/SetSettingValue/SetSettingValue'
|
||||
import { RenewSharedSubscriptions } from '../UseCase/RenewSharedSubscriptions/RenewSharedSubscriptions'
|
||||
|
||||
export class SubscriptionSyncRequestedEventHandler implements DomainEventHandlerInterface {
|
||||
constructor(
|
||||
@@ -27,11 +28,30 @@ export class SubscriptionSyncRequestedEventHandler implements DomainEventHandler
|
||||
private setSettingValue: SetSettingValue,
|
||||
private offlineSettingService: OfflineSettingServiceInterface,
|
||||
private contentDecoder: ContentDecoderInterface,
|
||||
private renewSharedSubscriptions: RenewSharedSubscriptions,
|
||||
private logger: Logger,
|
||||
) {}
|
||||
|
||||
async handle(event: SubscriptionSyncRequestedEvent): Promise<void> {
|
||||
if (!event.payload.subscriptionId) {
|
||||
this.logger.error('Subscription ID is missing', {
|
||||
codeTag: 'SubscriptionSyncRequestedEventHandler.handle',
|
||||
subscriptionId: event.payload.subscriptionId,
|
||||
userId: event.payload.userEmail,
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
this.logger.info('Subscription sync requested', {
|
||||
subscriptionId: event.payload.subscriptionId,
|
||||
})
|
||||
|
||||
if (event.payload.offline) {
|
||||
this.logger.info('Syncing offline subscription', {
|
||||
subscriptionId: event.payload.subscriptionId,
|
||||
})
|
||||
|
||||
const offlineUserSubscription = await this.createOrUpdateOfflineSubscription(
|
||||
event.payload.subscriptionId,
|
||||
event.payload.subscriptionName,
|
||||
@@ -41,6 +61,19 @@ export class SubscriptionSyncRequestedEventHandler implements DomainEventHandler
|
||||
event.payload.timestamp,
|
||||
)
|
||||
|
||||
const renewalResult = await this.renewSharedSubscriptions.execute({
|
||||
inviterEmail: event.payload.userEmail,
|
||||
newSubscriptionId: event.payload.subscriptionId,
|
||||
newSubscriptionName: event.payload.subscriptionName,
|
||||
newSubscriptionExpiresAt: event.payload.subscriptionExpiresAt,
|
||||
timestamp: event.payload.timestamp,
|
||||
})
|
||||
if (renewalResult.isFailed()) {
|
||||
this.logger.error(`Could not renew shared offline subscriptions for user: ${renewalResult.getError()}`, {
|
||||
subscriptionId: event.payload.subscriptionId,
|
||||
})
|
||||
}
|
||||
|
||||
await this.roleService.setOfflineUserRole(offlineUserSubscription)
|
||||
|
||||
const offlineFeaturesTokenDecoded = this.contentDecoder.decode(
|
||||
@@ -60,11 +93,19 @@ export class SubscriptionSyncRequestedEventHandler implements DomainEventHandler
|
||||
value: offlineFeaturesTokenDecoded.extensionKey,
|
||||
})
|
||||
|
||||
this.logger.info('Offline subscription synced', {
|
||||
subscriptionId: event.payload.subscriptionId,
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
const usernameOrError = Username.create(event.payload.userEmail)
|
||||
if (usernameOrError.isFailed()) {
|
||||
this.logger.warn(`Could not sync subscription: ${usernameOrError.getError()}`, {
|
||||
subscriptionId: event.payload.subscriptionId,
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
const username = usernameOrError.getValue()
|
||||
@@ -72,10 +113,18 @@ export class SubscriptionSyncRequestedEventHandler implements DomainEventHandler
|
||||
const user = await this.userRepository.findOneByUsernameOrEmail(username)
|
||||
|
||||
if (user === null) {
|
||||
this.logger.warn(`Could not find user with email: ${username.value}`)
|
||||
this.logger.warn(`Could not find user with email: ${username.value}`, {
|
||||
subscriptionId: event.payload.subscriptionId,
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
this.logger.info('Syncing subscription', {
|
||||
userId: user.uuid,
|
||||
subscriptionId: event.payload.subscriptionId,
|
||||
})
|
||||
|
||||
const userSubscription = await this.createOrUpdateSubscription(
|
||||
event.payload.subscriptionId,
|
||||
event.payload.subscriptionName,
|
||||
@@ -85,6 +134,19 @@ export class SubscriptionSyncRequestedEventHandler implements DomainEventHandler
|
||||
event.payload.timestamp,
|
||||
)
|
||||
|
||||
const renewalResult = await this.renewSharedSubscriptions.execute({
|
||||
inviterEmail: user.email,
|
||||
newSubscriptionId: event.payload.subscriptionId,
|
||||
newSubscriptionName: event.payload.subscriptionName,
|
||||
newSubscriptionExpiresAt: event.payload.subscriptionExpiresAt,
|
||||
timestamp: event.payload.timestamp,
|
||||
})
|
||||
if (renewalResult.isFailed()) {
|
||||
this.logger.error(`Could not renew shared subscriptions for user: ${renewalResult.getError()}`, {
|
||||
userId: user.uuid,
|
||||
})
|
||||
}
|
||||
|
||||
await this.roleService.addUserRoleBasedOnSubscription(user, event.payload.subscriptionName)
|
||||
|
||||
const applyingSettingsResult = await this.applyDefaultSubscriptionSettings.execute({
|
||||
@@ -107,6 +169,11 @@ export class SubscriptionSyncRequestedEventHandler implements DomainEventHandler
|
||||
if (result.isFailed()) {
|
||||
this.logger.error(`Could not set extension key for user ${user.uuid}`)
|
||||
}
|
||||
|
||||
this.logger.info('Subscription synced', {
|
||||
userId: user.uuid,
|
||||
subscriptionId: event.payload.subscriptionId,
|
||||
})
|
||||
}
|
||||
|
||||
private async createOrUpdateSubscription(
|
||||
|
||||
@@ -2,6 +2,7 @@ import { OfflineUserSubscription } from './OfflineUserSubscription'
|
||||
|
||||
export interface OfflineUserSubscriptionRepositoryInterface {
|
||||
findOneByEmail(email: string): Promise<OfflineUserSubscription | null>
|
||||
findOneByEmailAndSubscriptionId(email: string, subscriptionId: number): Promise<OfflineUserSubscription | null>
|
||||
findOneBySubscriptionId(subscriptionId: number): Promise<OfflineUserSubscription | null>
|
||||
findByEmail(email: string, activeAfter: number): Promise<OfflineUserSubscription[]>
|
||||
updateEndsAt(subscriptionId: number, endsAt: number, updatedAt: number): Promise<void>
|
||||
|
||||
@@ -7,6 +7,10 @@ import { DomainEventPublisherInterface } from '@standardnotes/domain-events'
|
||||
import { TimerInterface } from '@standardnotes/time'
|
||||
import { Logger } from 'winston'
|
||||
import { DomainEventFactoryInterface } from '../Event/DomainEventFactoryInterface'
|
||||
import { GetSetting } from './GetSetting/GetSetting'
|
||||
import { Result } from '@standardnotes/domain-core'
|
||||
import { LogSessionUserAgentOption } from '@standardnotes/settings'
|
||||
import { Setting } from '../Setting/Setting'
|
||||
|
||||
describe('RefreshSessionToken', () => {
|
||||
let sessionService: SessionServiceInterface
|
||||
@@ -14,16 +18,20 @@ describe('RefreshSessionToken', () => {
|
||||
let domainEventFactory: DomainEventFactoryInterface
|
||||
let domainEventPublisher: DomainEventPublisherInterface
|
||||
let timer: TimerInterface
|
||||
let getSetting: GetSetting
|
||||
let logger: Logger
|
||||
|
||||
const createUseCase = () =>
|
||||
new RefreshSessionToken(sessionService, domainEventFactory, domainEventPublisher, timer, logger)
|
||||
new RefreshSessionToken(sessionService, domainEventFactory, domainEventPublisher, timer, getSetting, logger)
|
||||
|
||||
beforeEach(() => {
|
||||
session = {} as jest.Mocked<Session>
|
||||
session.uuid = '1-2-3'
|
||||
session.refreshExpiration = new Date(123)
|
||||
|
||||
getSetting = {} as jest.Mocked<GetSetting>
|
||||
getSetting.execute = jest.fn().mockReturnValue(Result.fail('not found'))
|
||||
|
||||
sessionService = {} as jest.Mocked<SessionServiceInterface>
|
||||
sessionService.isRefreshTokenMatchingHashedSessionToken = jest.fn().mockReturnValue(true)
|
||||
sessionService.getSessionFromToken = jest.fn().mockReturnValue({ session, isEphemeral: false })
|
||||
@@ -69,6 +77,35 @@ describe('RefreshSessionToken', () => {
|
||||
expect(domainEventPublisher.publish).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should refresh session token and update user agent if enabled', async () => {
|
||||
getSetting.execute = jest.fn().mockReturnValue(
|
||||
Result.ok({
|
||||
setting: {} as jest.Mocked<Setting>,
|
||||
decryptedValue: LogSessionUserAgentOption.Enabled,
|
||||
}),
|
||||
)
|
||||
|
||||
const result = await createUseCase().execute({
|
||||
accessToken: '123',
|
||||
refreshToken: '234',
|
||||
userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)',
|
||||
})
|
||||
|
||||
expect(sessionService.refreshTokens).toHaveBeenCalledWith({ session, isEphemeral: false })
|
||||
|
||||
expect(result).toEqual({
|
||||
success: true,
|
||||
sessionPayload: {
|
||||
access_token: 'token1',
|
||||
refresh_token: 'token2',
|
||||
access_expiration: 123,
|
||||
refresh_expiration: 234,
|
||||
},
|
||||
})
|
||||
|
||||
expect(domainEventPublisher.publish).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should refresh a session token even if publishing domain event fails', async () => {
|
||||
domainEventPublisher.publish = jest.fn().mockRejectedValue(new Error('test'))
|
||||
|
||||
|
||||
@@ -1,23 +1,24 @@
|
||||
import { inject, injectable } from 'inversify'
|
||||
import { DomainEventPublisherInterface } from '@standardnotes/domain-events'
|
||||
import { TimerInterface } from '@standardnotes/time'
|
||||
import { SettingName } from '@standardnotes/domain-core'
|
||||
import { LogSessionUserAgentOption } from '@standardnotes/settings'
|
||||
import { Logger } from 'winston'
|
||||
|
||||
import TYPES from '../../Bootstrap/Types'
|
||||
import { SessionServiceInterface } from '../Session/SessionServiceInterface'
|
||||
import { DomainEventFactoryInterface } from '../Event/DomainEventFactoryInterface'
|
||||
|
||||
import { RefreshSessionTokenResponse } from './RefreshSessionTokenResponse'
|
||||
import { RefreshSessionTokenDTO } from './RefreshSessionTokenDTO'
|
||||
import { GetSetting } from './GetSetting/GetSetting'
|
||||
|
||||
@injectable()
|
||||
export class RefreshSessionToken {
|
||||
constructor(
|
||||
@inject(TYPES.Auth_SessionService) private sessionService: SessionServiceInterface,
|
||||
@inject(TYPES.Auth_DomainEventFactory) private domainEventFactory: DomainEventFactoryInterface,
|
||||
@inject(TYPES.Auth_DomainEventPublisher) private domainEventPublisher: DomainEventPublisherInterface,
|
||||
@inject(TYPES.Auth_Timer) private timer: TimerInterface,
|
||||
@inject(TYPES.Auth_Logger) private logger: Logger,
|
||||
private sessionService: SessionServiceInterface,
|
||||
private domainEventFactory: DomainEventFactoryInterface,
|
||||
private domainEventPublisher: DomainEventPublisherInterface,
|
||||
private timer: TimerInterface,
|
||||
private getSetting: GetSetting,
|
||||
private logger: Logger,
|
||||
) {}
|
||||
|
||||
async execute(dto: RefreshSessionTokenDTO): Promise<RefreshSessionTokenResponse> {
|
||||
@@ -46,7 +47,9 @@ export class RefreshSessionToken {
|
||||
}
|
||||
}
|
||||
|
||||
session.userAgent = dto.userAgent
|
||||
if (await this.isLoggingUserAgentEnabledOnSessions(session.userUuid)) {
|
||||
session.userAgent = dto.userAgent
|
||||
}
|
||||
|
||||
const sessionPayload = await this.sessionService.refreshTokens({ session, isEphemeral })
|
||||
|
||||
@@ -64,4 +67,19 @@ export class RefreshSessionToken {
|
||||
userUuid: session.userUuid,
|
||||
}
|
||||
}
|
||||
|
||||
private async isLoggingUserAgentEnabledOnSessions(userUuid: string): Promise<boolean> {
|
||||
const loggingSettingOrError = await this.getSetting.execute({
|
||||
settingName: SettingName.NAMES.LogSessionUserAgent,
|
||||
decrypted: true,
|
||||
userUuid: userUuid,
|
||||
allowSensitiveRetrieval: true,
|
||||
})
|
||||
if (loggingSettingOrError.isFailed()) {
|
||||
return true
|
||||
}
|
||||
const loggingSetting = loggingSettingOrError.getValue()
|
||||
|
||||
return loggingSetting.decryptedValue === LogSessionUserAgentOption.Enabled
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,14 +4,12 @@ import {
|
||||
controller,
|
||||
httpDelete,
|
||||
httpGet,
|
||||
httpPatch,
|
||||
httpPut,
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
results,
|
||||
} from 'inversify-express-utils'
|
||||
import TYPES from '../../Bootstrap/Types'
|
||||
import { DeleteAccount } from '../../Domain/UseCase/DeleteAccount/DeleteAccount'
|
||||
import { UpdateUser } from '../../Domain/UseCase/UpdateUser'
|
||||
import { GetUserSubscription } from '../../Domain/UseCase/GetUserSubscription/GetUserSubscription'
|
||||
import { ClearLoginAttempts } from '../../Domain/UseCase/ClearLoginAttempts'
|
||||
import { IncreaseLoginAttempts } from '../../Domain/UseCase/IncreaseLoginAttempts'
|
||||
@@ -21,26 +19,13 @@ import { BaseUsersController } from './Base/BaseUsersController'
|
||||
@controller('/users')
|
||||
export class AnnotatedUsersController extends BaseUsersController {
|
||||
constructor(
|
||||
@inject(TYPES.Auth_UpdateUser) override updateUser: UpdateUser,
|
||||
@inject(TYPES.Auth_DeleteAccount) override doDeleteAccount: DeleteAccount,
|
||||
@inject(TYPES.Auth_GetUserSubscription) override doGetUserSubscription: GetUserSubscription,
|
||||
@inject(TYPES.Auth_ClearLoginAttempts) override clearLoginAttempts: ClearLoginAttempts,
|
||||
@inject(TYPES.Auth_IncreaseLoginAttempts) override increaseLoginAttempts: IncreaseLoginAttempts,
|
||||
@inject(TYPES.Auth_ChangeCredentials) override changeCredentialsUseCase: ChangeCredentials,
|
||||
) {
|
||||
super(
|
||||
updateUser,
|
||||
doDeleteAccount,
|
||||
doGetUserSubscription,
|
||||
clearLoginAttempts,
|
||||
increaseLoginAttempts,
|
||||
changeCredentialsUseCase,
|
||||
)
|
||||
}
|
||||
|
||||
@httpPatch('/:userId', TYPES.Auth_RequiredCrossServiceTokenMiddleware)
|
||||
override async update(request: Request, response: Response): Promise<results.JsonResult> {
|
||||
return super.update(request, response)
|
||||
super(doDeleteAccount, doGetUserSubscription, clearLoginAttempts, increaseLoginAttempts, changeCredentialsUseCase)
|
||||
}
|
||||
|
||||
@httpDelete('/:userUuid', TYPES.Auth_RequiredCrossServiceTokenMiddleware)
|
||||
|
||||
@@ -8,6 +8,7 @@ import { IncreaseLoginAttempts } from '../../../Domain/UseCase/IncreaseLoginAtte
|
||||
import { SignIn } from '../../../Domain/UseCase/SignIn'
|
||||
import { VerifyMFA } from '../../../Domain/UseCase/VerifyMFA'
|
||||
import { AuthController } from '../../../Controller/AuthController'
|
||||
import { ResponseLocals } from '../ResponseLocals'
|
||||
import { BaseHttpController, results } from 'inversify-express-utils'
|
||||
|
||||
export class BaseAuthController extends BaseHttpController {
|
||||
@@ -37,9 +38,11 @@ export class BaseAuthController extends BaseHttpController {
|
||||
}
|
||||
|
||||
async params(request: Request, response: Response): Promise<results.JsonResult> {
|
||||
if (response.locals.session) {
|
||||
const locals = response.locals as ResponseLocals
|
||||
|
||||
if (locals.session) {
|
||||
const result = await this.getUserKeyParams.execute({
|
||||
email: response.locals.user.email,
|
||||
email: locals.user.email,
|
||||
authenticated: true,
|
||||
})
|
||||
|
||||
@@ -145,6 +148,8 @@ export class BaseAuthController extends BaseHttpController {
|
||||
}
|
||||
|
||||
async pkceParams(request: Request, response: Response): Promise<results.JsonResult> {
|
||||
const locals = response.locals as ResponseLocals
|
||||
|
||||
if (!request.body.code_challenge) {
|
||||
return this.json(
|
||||
{
|
||||
@@ -156,9 +161,9 @@ export class BaseAuthController extends BaseHttpController {
|
||||
)
|
||||
}
|
||||
|
||||
if (response.locals.session) {
|
||||
if (locals.session) {
|
||||
const result = await this.getUserKeyParams.execute({
|
||||
email: response.locals.user.email,
|
||||
email: locals.user.email,
|
||||
authenticated: true,
|
||||
codeChallenge: request.body.code_challenge as string,
|
||||
})
|
||||
@@ -248,8 +253,10 @@ export class BaseAuthController extends BaseHttpController {
|
||||
}
|
||||
|
||||
async generateRecoveryCodes(_request: Request, response: Response): Promise<results.JsonResult> {
|
||||
const locals = response.locals as ResponseLocals
|
||||
|
||||
const result = await this.authController.generateRecoveryCodes({
|
||||
userUuid: response.locals.user.uuid,
|
||||
userUuid: locals.user.uuid,
|
||||
})
|
||||
|
||||
return this.json(result.data, result.status)
|
||||
@@ -280,8 +287,10 @@ export class BaseAuthController extends BaseHttpController {
|
||||
}
|
||||
|
||||
async signOut(request: Request, response: Response): Promise<results.JsonResult | void> {
|
||||
const locals = response.locals as ResponseLocals
|
||||
|
||||
const result = await this.authController.signOut({
|
||||
readOnlyAccess: response.locals.readOnlyAccess,
|
||||
readOnlyAccess: locals.readOnlyAccess,
|
||||
authorizationHeader: <string>request.headers.authorization,
|
||||
})
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import { Request, Response } from 'express'
|
||||
|
||||
import { AuthenticatorsController } from '../../../Controller/AuthenticatorsController'
|
||||
import { BaseHttpController, results } from 'inversify-express-utils'
|
||||
import { ResponseLocals } from '../ResponseLocals'
|
||||
|
||||
export class BaseAuthenticatorsController extends BaseHttpController {
|
||||
constructor(
|
||||
@@ -30,16 +31,20 @@ export class BaseAuthenticatorsController extends BaseHttpController {
|
||||
}
|
||||
|
||||
async list(_request: Request, response: Response): Promise<results.JsonResult> {
|
||||
const locals = response.locals as ResponseLocals
|
||||
|
||||
const result = await this.authenticatorsController.list({
|
||||
userUuid: response.locals.user.uuid,
|
||||
userUuid: locals.user.uuid,
|
||||
})
|
||||
|
||||
return this.json(result.data, result.status)
|
||||
}
|
||||
|
||||
async delete(request: Request, response: Response): Promise<results.JsonResult> {
|
||||
const locals = response.locals as ResponseLocals
|
||||
|
||||
const result = await this.authenticatorsController.delete({
|
||||
userUuid: response.locals.user.uuid,
|
||||
userUuid: locals.user.uuid,
|
||||
authenticatorId: request.params.authenticatorId,
|
||||
})
|
||||
|
||||
@@ -47,17 +52,21 @@ export class BaseAuthenticatorsController extends BaseHttpController {
|
||||
}
|
||||
|
||||
async generateRegistrationOptions(_request: Request, response: Response): Promise<results.JsonResult> {
|
||||
const locals = response.locals as ResponseLocals
|
||||
|
||||
const result = await this.authenticatorsController.generateRegistrationOptions({
|
||||
username: response.locals.user.email,
|
||||
userUuid: response.locals.user.uuid,
|
||||
username: locals.user.email,
|
||||
userUuid: locals.user.uuid,
|
||||
})
|
||||
|
||||
return this.json(result.data, result.status)
|
||||
}
|
||||
|
||||
async verifyRegistration(request: Request, response: Response): Promise<results.JsonResult> {
|
||||
const locals = response.locals as ResponseLocals
|
||||
|
||||
const result = await this.authenticatorsController.verifyRegistrationResponse({
|
||||
userUuid: response.locals.user.uuid,
|
||||
userUuid: locals.user.uuid,
|
||||
attestationResponse: request.body.attestationResponse,
|
||||
})
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import { Request, Response } from 'express'
|
||||
|
||||
import { GetUserFeatures } from '../../../Domain/UseCase/GetUserFeatures/GetUserFeatures'
|
||||
import { BaseHttpController, results } from 'inversify-express-utils'
|
||||
import { ResponseLocals } from '../ResponseLocals'
|
||||
|
||||
export class BaseFeaturesController extends BaseHttpController {
|
||||
constructor(
|
||||
@@ -17,7 +18,9 @@ export class BaseFeaturesController extends BaseHttpController {
|
||||
}
|
||||
|
||||
async getFeatures(request: Request, response: Response): Promise<results.JsonResult> {
|
||||
if (request.params.userUuid !== response.locals.user.uuid) {
|
||||
const locals = response.locals as ResponseLocals
|
||||
|
||||
if (request.params.userUuid !== locals.user.uuid) {
|
||||
return this.json(
|
||||
{
|
||||
error: {
|
||||
|
||||
@@ -4,6 +4,7 @@ import { Request, Response } from 'express'
|
||||
|
||||
import { CreateListedAccount } from '../../../Domain/UseCase/CreateListedAccount/CreateListedAccount'
|
||||
import { BaseHttpController, results } from 'inversify-express-utils'
|
||||
import { ResponseLocals } from '../ResponseLocals'
|
||||
|
||||
export class BaseListedController extends BaseHttpController {
|
||||
constructor(
|
||||
@@ -18,7 +19,9 @@ export class BaseListedController extends BaseHttpController {
|
||||
}
|
||||
|
||||
async createListedAccount(_request: Request, response: Response): Promise<results.JsonResult> {
|
||||
if (response.locals.readOnlyAccess) {
|
||||
const locals = response.locals as ResponseLocals
|
||||
|
||||
if (locals.readOnlyAccess) {
|
||||
return this.json(
|
||||
{
|
||||
error: {
|
||||
@@ -31,8 +34,8 @@ export class BaseListedController extends BaseHttpController {
|
||||
}
|
||||
|
||||
await this.doCreateListedAccount.execute({
|
||||
userUuid: response.locals.user.uuid,
|
||||
userEmail: response.locals.user.email,
|
||||
userUuid: locals.user.uuid,
|
||||
userEmail: locals.user.email,
|
||||
})
|
||||
|
||||
return this.json({
|
||||
|
||||
@@ -8,6 +8,7 @@ import { AuthenticateOfflineSubscriptionToken } from '../../../Domain/UseCase/Au
|
||||
import { CreateOfflineSubscriptionToken } from '../../../Domain/UseCase/CreateOfflineSubscriptionToken/CreateOfflineSubscriptionToken'
|
||||
import { GetUserFeatures } from '../../../Domain/UseCase/GetUserFeatures/GetUserFeatures'
|
||||
import { GetUserOfflineSubscription } from '../../../Domain/UseCase/GetUserOfflineSubscription/GetUserOfflineSubscription'
|
||||
import { OfflineResponseLocals } from '../OfflineResponseLocals'
|
||||
|
||||
export class BaseOfflineController extends BaseHttpController {
|
||||
constructor(
|
||||
@@ -30,8 +31,10 @@ export class BaseOfflineController extends BaseHttpController {
|
||||
}
|
||||
|
||||
async getOfflineFeatures(_request: Request, response: Response): Promise<results.JsonResult> {
|
||||
const locals = response.locals as OfflineResponseLocals
|
||||
|
||||
const result = await this.doGetUserFeatures.execute({
|
||||
email: response.locals.offlineUserEmail,
|
||||
email: locals.userEmail,
|
||||
offline: true,
|
||||
})
|
||||
|
||||
@@ -115,8 +118,10 @@ export class BaseOfflineController extends BaseHttpController {
|
||||
}
|
||||
|
||||
async getSubscription(_request: Request, response: Response): Promise<results.JsonResult> {
|
||||
const locals = response.locals as OfflineResponseLocals
|
||||
|
||||
const result = await this.getUserOfflineSubscription.execute({
|
||||
userEmail: response.locals.userEmail,
|
||||
userEmail: locals.userEmail,
|
||||
})
|
||||
|
||||
if (result.success) {
|
||||
|
||||
@@ -6,6 +6,7 @@ import { ErrorTag } from '@standardnotes/responses'
|
||||
import { DeleteOtherSessionsForUser } from '../../../Domain/UseCase/DeleteOtherSessionsForUser'
|
||||
import { DeleteSessionForUser } from '../../../Domain/UseCase/DeleteSessionForUser'
|
||||
import { RefreshSessionToken } from '../../../Domain/UseCase/RefreshSessionToken'
|
||||
import { ResponseLocals } from '../ResponseLocals'
|
||||
|
||||
export class BaseSessionController extends BaseHttpController {
|
||||
constructor(
|
||||
@@ -24,7 +25,9 @@ export class BaseSessionController extends BaseHttpController {
|
||||
}
|
||||
|
||||
async deleteSession(request: Request, response: Response): Promise<results.JsonResult | results.StatusCodeResult> {
|
||||
if (response.locals.readOnlyAccess) {
|
||||
const locals = response.locals as ResponseLocals
|
||||
|
||||
if (locals.readOnlyAccess) {
|
||||
return this.json(
|
||||
{
|
||||
error: {
|
||||
@@ -36,7 +39,7 @@ export class BaseSessionController extends BaseHttpController {
|
||||
)
|
||||
}
|
||||
|
||||
if (!request.body.uuid) {
|
||||
if (!request.body.uuid || !locals.session) {
|
||||
return this.json(
|
||||
{
|
||||
error: {
|
||||
@@ -47,7 +50,7 @@ export class BaseSessionController extends BaseHttpController {
|
||||
)
|
||||
}
|
||||
|
||||
if (request.body.uuid === response.locals.session.uuid) {
|
||||
if (request.body.uuid === locals.session.uuid) {
|
||||
return this.json(
|
||||
{
|
||||
error: {
|
||||
@@ -59,7 +62,7 @@ export class BaseSessionController extends BaseHttpController {
|
||||
}
|
||||
|
||||
const useCaseResponse = await this.deleteSessionForUser.execute({
|
||||
userUuid: response.locals.user.uuid,
|
||||
userUuid: locals.user.uuid,
|
||||
sessionUuid: request.body.uuid,
|
||||
})
|
||||
|
||||
@@ -74,7 +77,7 @@ export class BaseSessionController extends BaseHttpController {
|
||||
)
|
||||
}
|
||||
|
||||
response.setHeader('x-invalidate-cache', response.locals.user.uuid)
|
||||
response.setHeader('x-invalidate-cache', locals.user.uuid)
|
||||
|
||||
return this.statusCode(204)
|
||||
}
|
||||
@@ -83,7 +86,9 @@ export class BaseSessionController extends BaseHttpController {
|
||||
_request: Request,
|
||||
response: Response,
|
||||
): Promise<results.JsonResult | results.StatusCodeResult> {
|
||||
if (response.locals.readOnlyAccess) {
|
||||
const locals = response.locals as ResponseLocals
|
||||
|
||||
if (locals.readOnlyAccess) {
|
||||
return this.json(
|
||||
{
|
||||
error: {
|
||||
@@ -95,7 +100,7 @@ export class BaseSessionController extends BaseHttpController {
|
||||
)
|
||||
}
|
||||
|
||||
if (!response.locals.user) {
|
||||
if (!locals.user || !locals.session) {
|
||||
return this.json(
|
||||
{
|
||||
error: {
|
||||
@@ -107,12 +112,12 @@ export class BaseSessionController extends BaseHttpController {
|
||||
}
|
||||
|
||||
await this.deleteOtherSessionsForUser.execute({
|
||||
userUuid: response.locals.user.uuid,
|
||||
currentSessionUuid: response.locals.session.uuid,
|
||||
userUuid: locals.user.uuid,
|
||||
currentSessionUuid: locals.session.uuid,
|
||||
markAsRevoked: true,
|
||||
})
|
||||
|
||||
response.setHeader('x-invalidate-cache', response.locals.user.uuid)
|
||||
response.setHeader('x-invalidate-cache', locals.user.uuid)
|
||||
|
||||
return this.statusCode(204)
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import { Session } from '../../../Domain/Session/Session'
|
||||
import { BaseHttpController, results } from 'inversify-express-utils'
|
||||
import { User } from '../../../Domain/User/User'
|
||||
import { SessionProjector } from '../../../Projection/SessionProjector'
|
||||
import { ResponseLocals } from '../ResponseLocals'
|
||||
|
||||
export class BaseSessionsController extends BaseHttpController {
|
||||
constructor(
|
||||
@@ -67,12 +68,14 @@ export class BaseSessionsController extends BaseHttpController {
|
||||
}
|
||||
|
||||
async getSessions(_request: Request, response: Response): Promise<results.JsonResult> {
|
||||
if (response.locals.readOnlyAccess) {
|
||||
const locals = response.locals as ResponseLocals
|
||||
|
||||
if (locals.readOnlyAccess) {
|
||||
return this.json([])
|
||||
}
|
||||
|
||||
const useCaseResponse = await this.getActiveSessionsForUser.execute({
|
||||
userUuid: response.locals.user.uuid,
|
||||
userUuid: locals.user.uuid,
|
||||
})
|
||||
|
||||
return this.json(
|
||||
@@ -80,7 +83,7 @@ export class BaseSessionsController extends BaseHttpController {
|
||||
this.sessionProjector.projectCustom(
|
||||
SessionProjector.CURRENT_SESSION_PROJECTION.toString(),
|
||||
session,
|
||||
response.locals.session,
|
||||
locals.session,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
@@ -13,6 +13,7 @@ import { SubscriptionSetting } from '../../../Domain/Setting/SubscriptionSetting
|
||||
import { SubscriptionSettingHttpRepresentation } from '../../../Mapping/Http/SubscriptionSettingHttpRepresentation'
|
||||
import { SettingHttpRepresentation } from '../../../Mapping/Http/SettingHttpRepresentation'
|
||||
import { TriggerPostSettingUpdateActions } from '../../../Domain/UseCase/TriggerPostSettingUpdateActions/TriggerPostSettingUpdateActions'
|
||||
import { ResponseLocals } from '../ResponseLocals'
|
||||
|
||||
export class BaseSettingsController extends BaseHttpController {
|
||||
constructor(
|
||||
@@ -40,7 +41,9 @@ export class BaseSettingsController extends BaseHttpController {
|
||||
}
|
||||
|
||||
async getSettings(request: Request, response: Response): Promise<results.JsonResult> {
|
||||
if (request.params.userUuid !== response.locals.user.uuid) {
|
||||
const locals = response.locals as ResponseLocals
|
||||
|
||||
if (request.params.userUuid !== locals.user.uuid) {
|
||||
return this.json(
|
||||
{
|
||||
error: {
|
||||
@@ -86,7 +89,9 @@ export class BaseSettingsController extends BaseHttpController {
|
||||
}
|
||||
|
||||
async getSetting(request: Request, response: Response): Promise<results.JsonResult> {
|
||||
if (request.params.userUuid !== response.locals.user.uuid) {
|
||||
const locals = response.locals as ResponseLocals
|
||||
|
||||
if (request.params.userUuid !== locals.user.uuid) {
|
||||
return this.json(
|
||||
{
|
||||
error: {
|
||||
@@ -135,7 +140,9 @@ export class BaseSettingsController extends BaseHttpController {
|
||||
}
|
||||
|
||||
async updateSetting(request: Request, response: Response): Promise<results.JsonResult | results.StatusCodeResult> {
|
||||
if (response.locals.readOnlyAccess) {
|
||||
const locals = response.locals as ResponseLocals
|
||||
|
||||
if (locals.readOnlyAccess) {
|
||||
return this.json(
|
||||
{
|
||||
error: {
|
||||
@@ -147,7 +154,7 @@ export class BaseSettingsController extends BaseHttpController {
|
||||
)
|
||||
}
|
||||
|
||||
if (request.params.userUuid !== response.locals.user.uuid) {
|
||||
if (request.params.userUuid !== locals.user.uuid) {
|
||||
return this.json(
|
||||
{
|
||||
error: {
|
||||
@@ -163,7 +170,7 @@ export class BaseSettingsController extends BaseHttpController {
|
||||
const result = await this.setSettingValue.execute({
|
||||
settingName: name,
|
||||
value,
|
||||
userUuid: response.locals.user.uuid,
|
||||
userUuid: locals.user.uuid,
|
||||
checkUserPermissions: true,
|
||||
})
|
||||
|
||||
@@ -181,8 +188,8 @@ export class BaseSettingsController extends BaseHttpController {
|
||||
|
||||
const triggerResult = await this.triggerPostSettingUpdateActions.execute({
|
||||
updatedSettingName: setting.props.name,
|
||||
userUuid: response.locals.user.uuid,
|
||||
userEmail: response.locals.user.email,
|
||||
userUuid: locals.user.uuid,
|
||||
userEmail: locals.user.email,
|
||||
unencryptedValue: value,
|
||||
})
|
||||
if (triggerResult.isFailed()) {
|
||||
@@ -196,7 +203,9 @@ export class BaseSettingsController extends BaseHttpController {
|
||||
}
|
||||
|
||||
async deleteSetting(request: Request, response: Response): Promise<results.JsonResult> {
|
||||
if (response.locals.readOnlyAccess) {
|
||||
const locals = response.locals as ResponseLocals
|
||||
|
||||
if (locals.readOnlyAccess) {
|
||||
return this.json(
|
||||
{
|
||||
error: {
|
||||
@@ -208,7 +217,7 @@ export class BaseSettingsController extends BaseHttpController {
|
||||
)
|
||||
}
|
||||
|
||||
if (request.params.userUuid !== response.locals.user.uuid) {
|
||||
if (request.params.userUuid !== locals.user.uuid) {
|
||||
return this.json(
|
||||
{
|
||||
error: {
|
||||
|
||||
+16
-7
@@ -4,7 +4,8 @@ import { BaseHttpController, results } from 'inversify-express-utils'
|
||||
import { ApiVersion } from '@standardnotes/api'
|
||||
|
||||
import { SubscriptionInvitesController } from '../../../Controller/SubscriptionInvitesController'
|
||||
import { Role } from '../../../Domain/Role/Role'
|
||||
import { ResponseLocals } from '../ResponseLocals'
|
||||
import { Role } from '@standardnotes/security'
|
||||
|
||||
export class BaseSubscriptionInvitesController extends BaseHttpController {
|
||||
constructor(
|
||||
@@ -23,12 +24,14 @@ export class BaseSubscriptionInvitesController extends BaseHttpController {
|
||||
}
|
||||
|
||||
async acceptInvite(request: Request, response: Response): Promise<results.JsonResult> {
|
||||
const locals = response.locals as ResponseLocals
|
||||
|
||||
const result = await this.subscriptionInvitesController.acceptInvite({
|
||||
api: request.query.api as ApiVersion,
|
||||
inviteUuid: request.params.inviteUuid,
|
||||
})
|
||||
|
||||
response.setHeader('x-invalidate-cache', response.locals.user.uuid)
|
||||
response.setHeader('x-invalidate-cache', locals.user.uuid)
|
||||
|
||||
return this.json(result.data, result.status)
|
||||
}
|
||||
@@ -43,30 +46,36 @@ export class BaseSubscriptionInvitesController extends BaseHttpController {
|
||||
}
|
||||
|
||||
async inviteToSubscriptionSharing(request: Request, response: Response): Promise<results.JsonResult> {
|
||||
const locals = response.locals as ResponseLocals
|
||||
|
||||
const result = await this.subscriptionInvitesController.invite({
|
||||
...request.body,
|
||||
inviterEmail: response.locals.user.email,
|
||||
inviterUuid: response.locals.user.uuid,
|
||||
inviterRoles: response.locals.roles.map((role: Role) => role.name),
|
||||
inviterEmail: locals.user.email,
|
||||
inviterUuid: locals.user.uuid,
|
||||
inviterRoles: locals.roles.map((role: Role) => role.name),
|
||||
})
|
||||
|
||||
return this.json(result.data, result.status)
|
||||
}
|
||||
|
||||
async cancelSubscriptionSharing(request: Request, response: Response): Promise<results.JsonResult> {
|
||||
const locals = response.locals as ResponseLocals
|
||||
|
||||
const result = await this.subscriptionInvitesController.cancelInvite({
|
||||
...request.body,
|
||||
inviteUuid: request.params.inviteUuid,
|
||||
inviterEmail: response.locals.user.email,
|
||||
inviterEmail: locals.user.email,
|
||||
})
|
||||
|
||||
return this.json(result.data, result.status)
|
||||
}
|
||||
|
||||
async listInvites(request: Request, response: Response): Promise<results.JsonResult> {
|
||||
const locals = response.locals as ResponseLocals
|
||||
|
||||
const result = await this.subscriptionInvitesController.listInvites({
|
||||
...request.body,
|
||||
inviterEmail: response.locals.user.email,
|
||||
inviterEmail: locals.user.email,
|
||||
})
|
||||
|
||||
return this.json(result.data, result.status)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user