Compare commits

...

18 Commits

Author SHA1 Message Date
standardci 0057a5d6ff chore(release): publish new version
- @standardnotes/analytics@2.28.2
 - @standardnotes/api-gateway@1.77.2
 - @standardnotes/auth-server@1.152.2
 - @standardnotes/domain-events-infra@1.14.9
 - @standardnotes/event-store@1.12.12
 - @standardnotes/files-server@1.26.4
 - @standardnotes/home-server@1.16.36
 - @standardnotes/revisions-server@1.40.3
 - @standardnotes/scheduler-server@1.22.2
 - @standardnotes/syncing-server@1.112.4
 - @standardnotes/websockets-server@1.12.1
2023-10-09 08:12:19 +00:00
Karol Sójko b736dab3c1 fix: remove xray sdk in favor of opentelemetry 2023-10-09 09:53:34 +02:00
standardci 951d965304 chore(release): publish new version
- @standardnotes/home-server@1.16.35
 - @standardnotes/revisions-server@1.40.2
 - @standardnotes/syncing-server@1.112.3
2023-10-09 06:45:04 +00:00
Karol Sójko 29e8de3238 fix: logs in transition 2023-10-09 08:26:18 +02:00
standardci eeeacabaa8 chore(release): publish new version
- @standardnotes/home-server@1.16.34
 - @standardnotes/syncing-server@1.112.2
2023-10-06 14:30:24 +00:00
Karol Sójko 51ca8229b8 fix(syncing-server): calling auth server for user key params 2023-10-06 15:56:10 +02:00
Karol Sójko a6a19a391e fix(syncing-server): error log on email backup requested 2023-10-06 15:44:11 +02:00
standardci f6cdb7916c chore(release): publish new version
- @standardnotes/auth-server@1.152.1
 - @standardnotes/home-server@1.16.33
 - @standardnotes/revisions-server@1.40.1
 - @standardnotes/syncing-server@1.112.1
2023-10-06 13:34:07 +00:00
Karol Sójko eafb064d79 fix(syncing-server): increase axios timeout on calling auth 2023-10-06 15:18:26 +02:00
Karol Sójko ba050681f7 fix(syncing-server): logs on request backup handler 2023-10-06 15:16:38 +02:00
Karol Sójko 4780629549 fix(revisions): casting creation date from MongoDB 2023-10-06 15:14:11 +02:00
Karol Sójko 79a44aa51f fix(auth): checking for transition role when triggering transition 2023-10-06 14:56:45 +02:00
standardci dd72769841 chore(release): publish new version
- @standardnotes/auth-server@1.152.0
 - @standardnotes/home-server@1.16.32
 - @standardnotes/revisions-server@1.40.0
 - @standardnotes/syncing-server@1.112.0
2023-10-06 11:22:47 +00:00
Karol Sójko d8f1c66fd5 fix: enable TransitionRequestedEventHandler 2023-10-06 13:02:37 +02:00
Karol Sójko afe9967d26 fix(auth): strip user from transition role after migration 2023-10-06 12:59:18 +02:00
Karol Sójko 27bea444cc feat: switch transition direction 2023-10-06 12:48:08 +02:00
standardci 7a571dec0a chore(release): publish new version
- @standardnotes/home-server@1.16.31
 - @standardnotes/syncing-server@1.111.5
2023-10-06 08:48:31 +00:00
Karol Sójko 8c57f505be fix(syncing-server): add more logs on successfull email backups requested 2023-10-06 10:28:50 +02:00
104 changed files with 386 additions and 1550 deletions
Generated
-369
View File
@@ -1605,13 +1605,6 @@ const RAW_RUNTIME_STATE =
["@aws-sdk/service-error-classification", "npm:3.342.0"]\
],\
"linkType": "HARD"\
}],\
["npm:3.370.0", {\
"packageLocation": "./.yarn/cache/@aws-sdk-service-error-classification-npm-3.370.0-0d5b615252-500f067ba1.zip/node_modules/@aws-sdk/service-error-classification/",\
"packageDependencies": [\
["@aws-sdk/service-error-classification", "npm:3.370.0"]\
],\
"linkType": "HARD"\
}]\
]],\
["@aws-sdk/shared-ini-file-loader", [\
@@ -1795,15 +1788,6 @@ const RAW_RUNTIME_STATE =
["tslib", "npm:2.5.2"]\
],\
"linkType": "HARD"\
}],\
["npm:3.418.0", {\
"packageLocation": "./.yarn/cache/@aws-sdk-types-npm-3.418.0-451c0cadd0-627955c2c9.zip/node_modules/@aws-sdk/types/",\
"packageDependencies": [\
["@aws-sdk/types", "npm:3.418.0"],\
["@smithy/types", "npm:2.3.4"],\
["tslib", "npm:2.5.2"]\
],\
"linkType": "HARD"\
}]\
]],\
["@aws-sdk/url-parser", [\
@@ -5504,14 +5488,6 @@ const RAW_RUNTIME_STATE =
["tslib", "npm:2.5.2"]\
],\
"linkType": "HARD"\
}],\
["npm:2.3.4", {\
"packageLocation": "./.yarn/cache/@smithy-types-npm-2.3.4-7d0b3a2a2f-8a5ad3b47e.zip/node_modules/@smithy/types/",\
"packageDependencies": [\
["@smithy/types", "npm:2.3.4"],\
["tslib", "npm:2.5.2"]\
],\
"linkType": "HARD"\
}]\
]],\
["@smithy/url-parser", [\
@@ -5740,7 +5716,6 @@ const RAW_RUNTIME_STATE =
["@types/node", "npm:20.5.7"],\
["@typescript-eslint/eslint-plugin", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:6.5.0"],\
["@typescript-eslint/parser", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:6.5.0"],\
["aws-xray-sdk", "npm:3.5.2"],\
["dayjs", "npm:1.11.7"],\
["dotenv", "npm:16.1.3"],\
["eslint", "npm:8.41.0"],\
@@ -5798,7 +5773,6 @@ const RAW_RUNTIME_STATE =
["@types/prettyjson", "npm:0.0.30"],\
["@typescript-eslint/eslint-plugin", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:6.5.0"],\
["@typescript-eslint/parser", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:6.5.0"],\
["aws-xray-sdk", "npm:3.5.2"],\
["axios", "npm:1.4.0"],\
["cors", "npm:2.8.5"],\
["dotenv", "npm:16.1.3"],\
@@ -5861,7 +5835,6 @@ const RAW_RUNTIME_STATE =
["@types/uuid", "npm:9.0.3"],\
["@typescript-eslint/eslint-plugin", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:6.5.0"],\
["@typescript-eslint/parser", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:6.5.0"],\
["aws-xray-sdk", "npm:3.5.2"],\
["axios", "npm:1.4.0"],\
["bcryptjs", "npm:2.4.3"],\
["cors", "npm:2.8.5"],\
@@ -5965,7 +5938,6 @@ const RAW_RUNTIME_STATE =
["@types/newrelic", "npm:9.14.0"],\
["@typescript-eslint/eslint-plugin", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:6.5.0"],\
["@typescript-eslint/parser", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:6.5.0"],\
["aws-xray-sdk", "npm:3.5.2"],\
["eslint", "npm:8.41.0"],\
["eslint-plugin-prettier", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:5.0.0"],\
["ioredis", "npm:5.3.2"],\
@@ -6055,7 +6027,6 @@ const RAW_RUNTIME_STATE =
["@types/uuid", "npm:9.0.3"],\
["@typescript-eslint/eslint-plugin", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:6.5.0"],\
["@typescript-eslint/parser", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:6.5.0"],\
["aws-xray-sdk", "npm:3.5.2"],\
["connect-busboy", "npm:1.0.0"],\
["cors", "npm:2.8.5"],\
["dayjs", "npm:1.11.7"],\
@@ -6187,12 +6158,10 @@ const RAW_RUNTIME_STATE =
["@types/express", "npm:4.17.17"],\
["@types/ioredis", "npm:5.0.0"],\
["@types/jest", "npm:29.5.2"],\
["@types/mysql", "npm:2.15.22"],\
["@types/newrelic", "npm:9.14.0"],\
["@types/node", "npm:20.5.7"],\
["@typescript-eslint/eslint-plugin", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:6.5.0"],\
["@typescript-eslint/parser", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:6.5.0"],\
["aws-xray-sdk", "npm:3.5.2"],\
["cors", "npm:2.8.5"],\
["dotenv", "npm:16.1.3"],\
["eslint", "npm:8.41.0"],\
@@ -6203,7 +6172,6 @@ const RAW_RUNTIME_STATE =
["ioredis", "npm:5.3.2"],\
["jest", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:29.5.0"],\
["mongodb", "virtual:365b8c88cdf194291829ee28b79556e2328175d26a621363e703848100bea0042e9500db2a1206c9bbc3a4a76a1d169639ef774b2ea3a1a98584a9936b58c6be#npm:6.0.0"],\
["mysql", "npm:2.18.1"],\
["mysql2", "npm:3.3.3"],\
["newrelic", "npm:11.0.0"],\
["prettier", "npm:3.0.3"],\
@@ -6236,7 +6204,6 @@ const RAW_RUNTIME_STATE =
["@types/node", "npm:20.5.7"],\
["@typescript-eslint/eslint-plugin", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:6.5.0"],\
["@typescript-eslint/parser", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:6.5.0"],\
["aws-xray-sdk", "npm:3.5.2"],\
["dayjs", "npm:1.11.7"],\
["dotenv", "npm:16.1.3"],\
["eslint", "npm:8.41.0"],\
@@ -6386,7 +6353,6 @@ const RAW_RUNTIME_STATE =
["@types/uuid", "npm:9.0.3"],\
["@typescript-eslint/eslint-plugin", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:6.5.0"],\
["@typescript-eslint/parser", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:6.5.0"],\
["aws-xray-sdk", "npm:3.5.2"],\
["axios", "npm:1.4.0"],\
["cors", "npm:2.8.5"],\
["dotenv", "npm:16.1.3"],\
@@ -6474,7 +6440,6 @@ const RAW_RUNTIME_STATE =
["@types/newrelic", "npm:9.14.0"],\
["@typescript-eslint/eslint-plugin", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:6.5.0"],\
["@typescript-eslint/parser", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:6.5.0"],\
["aws-xray-sdk", "npm:3.5.2"],\
["axios", "npm:1.4.0"],\
["cors", "npm:2.8.5"],\
["dotenv", "npm:16.1.3"],\
@@ -6644,16 +6609,6 @@ const RAW_RUNTIME_STATE =
"linkType": "HARD"\
}]\
]],\
["@types/cls-hooked", [\
["npm:4.3.6", {\
"packageLocation": "./.yarn/cache/@types-cls-hooked-npm-4.3.6-8787b64e86-f5b9864348.zip/node_modules/@types/cls-hooked/",\
"packageDependencies": [\
["@types/cls-hooked", "npm:4.3.6"],\
["@types/node", "npm:20.2.5"]\
],\
"linkType": "HARD"\
}]\
]],\
["@types/concat-stream", [\
["npm:1.6.1", {\
"packageLocation": "./.yarn/cache/@types-concat-stream-npm-1.6.1-42cd06b019-7d211e7433.zip/node_modules/@types/concat-stream/",\
@@ -6913,16 +6868,6 @@ const RAW_RUNTIME_STATE =
"linkType": "HARD"\
}]\
]],\
["@types/mysql", [\
["npm:2.15.22", {\
"packageLocation": "./.yarn/cache/@types-mysql-npm-2.15.22-d643eb999e-6be0aac58f.zip/node_modules/@types/mysql/",\
"packageDependencies": [\
["@types/mysql", "npm:2.15.22"],\
["@types/node", "npm:20.2.5"]\
],\
"linkType": "HARD"\
}]\
]],\
["@types/newrelic", [\
["npm:9.14.0", {\
"packageLocation": "./.yarn/cache/@types-newrelic-npm-9.14.0-4668da51a1-3a54ea75a4.zip/node_modules/@types/newrelic/",\
@@ -6991,18 +6936,6 @@ const RAW_RUNTIME_STATE =
"linkType": "HARD"\
}]\
]],\
["@types/pg", [\
["npm:8.10.3", {\
"packageLocation": "./.yarn/cache/@types-pg-npm-8.10.3-3fc3365c7b-22d4836bd9.zip/node_modules/@types/pg/",\
"packageDependencies": [\
["@types/pg", "npm:8.10.3"],\
["@types/node", "npm:20.2.5"],\
["pg-protocol", "npm:1.6.0"],\
["pg-types", "npm:4.0.1"]\
],\
"linkType": "HARD"\
}]\
]],\
["@types/prettier", [\
["npm:2.7.3", {\
"packageLocation": "./.yarn/cache/@types-prettier-npm-2.7.3-497316f37c-cda84c19ac.zip/node_modules/@types/prettier/",\
@@ -8013,16 +7946,6 @@ const RAW_RUNTIME_STATE =
"linkType": "HARD"\
}]\
]],\
["async-hook-jl", [\
["npm:1.7.6", {\
"packageLocation": "./.yarn/cache/async-hook-jl-npm-1.7.6-9999815029-f61a3bd4c3.zip/node_modules/async-hook-jl/",\
"packageDependencies": [\
["async-hook-jl", "npm:1.7.6"],\
["stack-chain", "npm:1.3.7"]\
],\
"linkType": "HARD"\
}]\
]],\
["asynckit", [\
["npm:0.4.0", {\
"packageLocation": "./.yarn/cache/asynckit-npm-0.4.0-c718858525-3ce727cbc7.zip/node_modules/asynckit/",\
@@ -8032,112 +7955,6 @@ const RAW_RUNTIME_STATE =
"linkType": "HARD"\
}]\
]],\
["atomic-batcher", [\
["npm:1.0.2", {\
"packageLocation": "./.yarn/cache/atomic-batcher-npm-1.0.2-6fcd3a3097-025e334f1f.zip/node_modules/atomic-batcher/",\
"packageDependencies": [\
["atomic-batcher", "npm:1.0.2"]\
],\
"linkType": "HARD"\
}]\
]],\
["aws-xray-sdk", [\
["npm:3.5.2", {\
"packageLocation": "./.yarn/cache/aws-xray-sdk-npm-3.5.2-15fc4e54ee-576d0d5ccb.zip/node_modules/aws-xray-sdk/",\
"packageDependencies": [\
["aws-xray-sdk", "npm:3.5.2"],\
["aws-xray-sdk-core", "npm:3.5.2"],\
["aws-xray-sdk-express", "virtual:15fc4e54eec18d85ce3f22aa2405619072c35fbd500ad809cce2c9e4ead8a191fcc189cef6a5d76df3bea5576f09735fc4d32f086db561623afc56dd36794c8f#npm:3.5.2"],\
["aws-xray-sdk-mysql", "virtual:15fc4e54eec18d85ce3f22aa2405619072c35fbd500ad809cce2c9e4ead8a191fcc189cef6a5d76df3bea5576f09735fc4d32f086db561623afc56dd36794c8f#npm:3.5.2"],\
["aws-xray-sdk-postgres", "virtual:15fc4e54eec18d85ce3f22aa2405619072c35fbd500ad809cce2c9e4ead8a191fcc189cef6a5d76df3bea5576f09735fc4d32f086db561623afc56dd36794c8f#npm:3.5.2"]\
],\
"linkType": "HARD"\
}]\
]],\
["aws-xray-sdk-core", [\
["npm:3.5.2", {\
"packageLocation": "./.yarn/cache/aws-xray-sdk-core-npm-3.5.2-9083a0c00f-a643998187.zip/node_modules/aws-xray-sdk-core/",\
"packageDependencies": [\
["aws-xray-sdk-core", "npm:3.5.2"],\
["@aws-sdk/service-error-classification", "npm:3.370.0"],\
["@aws-sdk/types", "npm:3.418.0"],\
["@types/cls-hooked", "npm:4.3.6"],\
["atomic-batcher", "npm:1.0.2"],\
["cls-hooked", "npm:4.2.2"],\
["semver", "npm:7.5.4"]\
],\
"linkType": "HARD"\
}]\
]],\
["aws-xray-sdk-express", [\
["npm:3.5.2", {\
"packageLocation": "./.yarn/cache/aws-xray-sdk-express-npm-3.5.2-c4574a664b-62a07d0f3b.zip/node_modules/aws-xray-sdk-express/",\
"packageDependencies": [\
["aws-xray-sdk-express", "npm:3.5.2"]\
],\
"linkType": "SOFT"\
}],\
["virtual:15fc4e54eec18d85ce3f22aa2405619072c35fbd500ad809cce2c9e4ead8a191fcc189cef6a5d76df3bea5576f09735fc4d32f086db561623afc56dd36794c8f#npm:3.5.2", {\
"packageLocation": "./.yarn/__virtual__/aws-xray-sdk-express-virtual-36027c3d91/0/cache/aws-xray-sdk-express-npm-3.5.2-c4574a664b-62a07d0f3b.zip/node_modules/aws-xray-sdk-express/",\
"packageDependencies": [\
["aws-xray-sdk-express", "virtual:15fc4e54eec18d85ce3f22aa2405619072c35fbd500ad809cce2c9e4ead8a191fcc189cef6a5d76df3bea5576f09735fc4d32f086db561623afc56dd36794c8f#npm:3.5.2"],\
["@types/aws-xray-sdk-core", null],\
["@types/express", "npm:4.17.17"],\
["aws-xray-sdk-core", "npm:3.5.2"]\
],\
"packagePeers": [\
"@types/aws-xray-sdk-core",\
"aws-xray-sdk-core"\
],\
"linkType": "HARD"\
}]\
]],\
["aws-xray-sdk-mysql", [\
["npm:3.5.2", {\
"packageLocation": "./.yarn/cache/aws-xray-sdk-mysql-npm-3.5.2-095483ab95-f910a96630.zip/node_modules/aws-xray-sdk-mysql/",\
"packageDependencies": [\
["aws-xray-sdk-mysql", "npm:3.5.2"]\
],\
"linkType": "SOFT"\
}],\
["virtual:15fc4e54eec18d85ce3f22aa2405619072c35fbd500ad809cce2c9e4ead8a191fcc189cef6a5d76df3bea5576f09735fc4d32f086db561623afc56dd36794c8f#npm:3.5.2", {\
"packageLocation": "./.yarn/__virtual__/aws-xray-sdk-mysql-virtual-d8a5f29b75/0/cache/aws-xray-sdk-mysql-npm-3.5.2-095483ab95-f910a96630.zip/node_modules/aws-xray-sdk-mysql/",\
"packageDependencies": [\
["aws-xray-sdk-mysql", "virtual:15fc4e54eec18d85ce3f22aa2405619072c35fbd500ad809cce2c9e4ead8a191fcc189cef6a5d76df3bea5576f09735fc4d32f086db561623afc56dd36794c8f#npm:3.5.2"],\
["@types/aws-xray-sdk-core", null],\
["@types/mysql", "npm:2.15.22"],\
["aws-xray-sdk-core", "npm:3.5.2"]\
],\
"packagePeers": [\
"@types/aws-xray-sdk-core",\
"aws-xray-sdk-core"\
],\
"linkType": "HARD"\
}]\
]],\
["aws-xray-sdk-postgres", [\
["npm:3.5.2", {\
"packageLocation": "./.yarn/cache/aws-xray-sdk-postgres-npm-3.5.2-3a7e7bcc42-f2d6da22c7.zip/node_modules/aws-xray-sdk-postgres/",\
"packageDependencies": [\
["aws-xray-sdk-postgres", "npm:3.5.2"]\
],\
"linkType": "SOFT"\
}],\
["virtual:15fc4e54eec18d85ce3f22aa2405619072c35fbd500ad809cce2c9e4ead8a191fcc189cef6a5d76df3bea5576f09735fc4d32f086db561623afc56dd36794c8f#npm:3.5.2", {\
"packageLocation": "./.yarn/__virtual__/aws-xray-sdk-postgres-virtual-c6edb063fc/0/cache/aws-xray-sdk-postgres-npm-3.5.2-3a7e7bcc42-f2d6da22c7.zip/node_modules/aws-xray-sdk-postgres/",\
"packageDependencies": [\
["aws-xray-sdk-postgres", "virtual:15fc4e54eec18d85ce3f22aa2405619072c35fbd500ad809cce2c9e4ead8a191fcc189cef6a5d76df3bea5576f09735fc4d32f086db561623afc56dd36794c8f#npm:3.5.2"],\
["@types/aws-xray-sdk-core", null],\
["@types/pg", "npm:8.10.3"],\
["aws-xray-sdk-core", "npm:3.5.2"]\
],\
"packagePeers": [\
"@types/aws-xray-sdk-core",\
"aws-xray-sdk-core"\
],\
"linkType": "HARD"\
}]\
]],\
["axios", [\
["npm:0.21.4", {\
"packageLocation": "./.yarn/cache/axios-npm-0.21.4-e278873748-da644592cb.zip/node_modules/axios/",\
@@ -8341,13 +8158,6 @@ const RAW_RUNTIME_STATE =
}]\
]],\
["bignumber.js", [\
["npm:9.0.0", {\
"packageLocation": "./.yarn/cache/bignumber.js-npm-9.0.0-ce190bcd7c-7406d0d11d.zip/node_modules/bignumber.js/",\
"packageDependencies": [\
["bignumber.js", "npm:9.0.0"]\
],\
"linkType": "HARD"\
}],\
["npm:9.1.1", {\
"packageLocation": "./.yarn/cache/bignumber.js-npm-9.1.1-5929e8d8dc-1f771bfa88.zip/node_modules/bignumber.js/",\
"packageDependencies": [\
@@ -8935,18 +8745,6 @@ const RAW_RUNTIME_STATE =
"linkType": "HARD"\
}]\
]],\
["cls-hooked", [\
["npm:4.2.2", {\
"packageLocation": "./.yarn/cache/cls-hooked-npm-4.2.2-db33b9b95f-59081fcc0f.zip/node_modules/cls-hooked/",\
"packageDependencies": [\
["cls-hooked", "npm:4.2.2"],\
["async-hook-jl", "npm:1.7.6"],\
["emitter-listener", "npm:1.1.2"],\
["semver", "npm:5.7.2"]\
],\
"linkType": "HARD"\
}]\
]],\
["cluster-key-slot", [\
["npm:1.1.2", {\
"packageLocation": "./.yarn/cache/cluster-key-slot-npm-1.1.2-0571a28825-516ed8b5e1.zip/node_modules/cluster-key-slot/",\
@@ -9837,16 +9635,6 @@ const RAW_RUNTIME_STATE =
"linkType": "HARD"\
}]\
]],\
["emitter-listener", [\
["npm:1.1.2", {\
"packageLocation": "./.yarn/cache/emitter-listener-npm-1.1.2-0fe118d0b3-697f53c308.zip/node_modules/emitter-listener/",\
"packageDependencies": [\
["emitter-listener", "npm:1.1.2"],\
["shimmer", "npm:1.2.1"]\
],\
"linkType": "HARD"\
}]\
]],\
["emittery", [\
["npm:0.13.1", {\
"packageLocation": "./.yarn/cache/emittery-npm-0.13.1-cb6cd1bb03-fbe214171d.zip/node_modules/emittery/",\
@@ -13730,19 +13518,6 @@ const RAW_RUNTIME_STATE =
"linkType": "HARD"\
}]\
]],\
["mysql", [\
["npm:2.18.1", {\
"packageLocation": "./.yarn/cache/mysql-npm-2.18.1-8fdb56201f-87d80e3747.zip/node_modules/mysql/",\
"packageDependencies": [\
["mysql", "npm:2.18.1"],\
["bignumber.js", "npm:9.0.0"],\
["readable-stream", "npm:2.3.7"],\
["safe-buffer", "npm:5.1.2"],\
["sqlstring", "npm:2.3.1"]\
],\
"linkType": "HARD"\
}]\
]],\
["mysql2", [\
["npm:3.3.3", {\
"packageLocation": "./.yarn/cache/mysql2-npm-3.3.3-d2fe8cf512-4bf7ace8f1.zip/node_modules/mysql2/",\
@@ -14232,15 +14007,6 @@ const RAW_RUNTIME_STATE =
"linkType": "HARD"\
}]\
]],\
["obuf", [\
["npm:1.1.2", {\
"packageLocation": "./.yarn/cache/obuf-npm-1.1.2-8db5fae8dd-53ff4ab3a1.zip/node_modules/obuf/",\
"packageDependencies": [\
["obuf", "npm:1.1.2"]\
],\
"linkType": "HARD"\
}]\
]],\
["on-finished", [\
["npm:2.4.1", {\
"packageLocation": "./.yarn/cache/on-finished-npm-2.4.1-907af70f88-8e81472c50.zip/node_modules/on-finished/",\
@@ -14701,49 +14467,6 @@ const RAW_RUNTIME_STATE =
"linkType": "HARD"\
}]\
]],\
["pg-int8", [\
["npm:1.0.1", {\
"packageLocation": "./.yarn/cache/pg-int8-npm-1.0.1-5cd67f3e22-a1e3a05a69.zip/node_modules/pg-int8/",\
"packageDependencies": [\
["pg-int8", "npm:1.0.1"]\
],\
"linkType": "HARD"\
}]\
]],\
["pg-numeric", [\
["npm:1.0.2", {\
"packageLocation": "./.yarn/cache/pg-numeric-npm-1.0.2-9026ec3427-8899f8200c.zip/node_modules/pg-numeric/",\
"packageDependencies": [\
["pg-numeric", "npm:1.0.2"]\
],\
"linkType": "HARD"\
}]\
]],\
["pg-protocol", [\
["npm:1.6.0", {\
"packageLocation": "./.yarn/cache/pg-protocol-npm-1.6.0-089a4b1d3c-995864cc2a.zip/node_modules/pg-protocol/",\
"packageDependencies": [\
["pg-protocol", "npm:1.6.0"]\
],\
"linkType": "HARD"\
}]\
]],\
["pg-types", [\
["npm:4.0.1", {\
"packageLocation": "./.yarn/cache/pg-types-npm-4.0.1-8f922557d3-2c686ef361.zip/node_modules/pg-types/",\
"packageDependencies": [\
["pg-types", "npm:4.0.1"],\
["pg-int8", "npm:1.0.1"],\
["pg-numeric", "npm:1.0.2"],\
["postgres-array", "npm:3.0.2"],\
["postgres-bytea", "npm:3.0.0"],\
["postgres-date", "npm:2.0.1"],\
["postgres-interval", "npm:3.0.0"],\
["postgres-range", "npm:1.1.3"]\
],\
"linkType": "HARD"\
}]\
]],\
["picocolors", [\
["npm:1.0.0", {\
"packageLocation": "./.yarn/cache/picocolors-npm-1.0.0-d81e0b1927-a2e8092dd8.zip/node_modules/picocolors/",\
@@ -14815,52 +14538,6 @@ const RAW_RUNTIME_STATE =
"linkType": "HARD"\
}]\
]],\
["postgres-array", [\
["npm:3.0.2", {\
"packageLocation": "./.yarn/cache/postgres-array-npm-3.0.2-da6a3f1fed-0159517e4e.zip/node_modules/postgres-array/",\
"packageDependencies": [\
["postgres-array", "npm:3.0.2"]\
],\
"linkType": "HARD"\
}]\
]],\
["postgres-bytea", [\
["npm:3.0.0", {\
"packageLocation": "./.yarn/cache/postgres-bytea-npm-3.0.0-5de4c664f6-f5c01758fd.zip/node_modules/postgres-bytea/",\
"packageDependencies": [\
["postgres-bytea", "npm:3.0.0"],\
["obuf", "npm:1.1.2"]\
],\
"linkType": "HARD"\
}]\
]],\
["postgres-date", [\
["npm:2.0.1", {\
"packageLocation": "./.yarn/cache/postgres-date-npm-2.0.1-00e0e0bc9e-908eacec35.zip/node_modules/postgres-date/",\
"packageDependencies": [\
["postgres-date", "npm:2.0.1"]\
],\
"linkType": "HARD"\
}]\
]],\
["postgres-interval", [\
["npm:3.0.0", {\
"packageLocation": "./.yarn/cache/postgres-interval-npm-3.0.0-936c769b98-c7a1cf006d.zip/node_modules/postgres-interval/",\
"packageDependencies": [\
["postgres-interval", "npm:3.0.0"]\
],\
"linkType": "HARD"\
}]\
]],\
["postgres-range", [\
["npm:1.1.3", {\
"packageLocation": "./.yarn/cache/postgres-range-npm-1.1.3-46f68e1a9e-356a46d97e.zip/node_modules/postgres-range/",\
"packageDependencies": [\
["postgres-range", "npm:1.1.3"]\
],\
"linkType": "HARD"\
}]\
]],\
["prelude-ls", [\
["npm:1.2.1", {\
"packageLocation": "./.yarn/cache/prelude-ls-npm-1.2.1-3e4d272a55-0b9d2c7680.zip/node_modules/prelude-ls/",\
@@ -15280,20 +14957,6 @@ const RAW_RUNTIME_STATE =
}]\
]],\
["readable-stream", [\
["npm:2.3.7", {\
"packageLocation": "./.yarn/cache/readable-stream-npm-2.3.7-77b22a9818-d04c677c17.zip/node_modules/readable-stream/",\
"packageDependencies": [\
["readable-stream", "npm:2.3.7"],\
["core-util-is", "npm:1.0.3"],\
["inherits", "npm:2.0.4"],\
["isarray", "npm:1.0.0"],\
["process-nextick-args", "npm:2.0.1"],\
["safe-buffer", "npm:5.1.2"],\
["string_decoder", "npm:1.1.1"],\
["util-deprecate", "npm:1.0.2"]\
],\
"linkType": "HARD"\
}],\
["npm:2.3.8", {\
"packageLocation": "./.yarn/cache/readable-stream-npm-2.3.8-67a94c2cb1-8500dd3a90.zip/node_modules/readable-stream/",\
"packageDependencies": [\
@@ -15634,13 +15297,6 @@ const RAW_RUNTIME_STATE =
],\
"linkType": "HARD"\
}],\
["npm:5.7.2", {\
"packageLocation": "./.yarn/cache/semver-npm-5.7.2-938ee91eaa-fca14418a1.zip/node_modules/semver/",\
"packageDependencies": [\
["semver", "npm:5.7.2"]\
],\
"linkType": "HARD"\
}],\
["npm:6.3.0", {\
"packageLocation": "./.yarn/cache/semver-npm-6.3.0-b3eace8bfd-8dd72e7c7c.zip/node_modules/semver/",\
"packageDependencies": [\
@@ -15785,15 +15441,6 @@ const RAW_RUNTIME_STATE =
"linkType": "HARD"\
}]\
]],\
["shimmer", [\
["npm:1.2.1", {\
"packageLocation": "./.yarn/cache/shimmer-npm-1.2.1-8b50bf3206-aa0d6252ad.zip/node_modules/shimmer/",\
"packageDependencies": [\
["shimmer", "npm:1.2.1"]\
],\
"linkType": "HARD"\
}]\
]],\
["side-channel", [\
["npm:1.0.4", {\
"packageLocation": "./.yarn/cache/side-channel-npm-1.0.4-e1f38b9e06-c4998d9fc5.zip/node_modules/side-channel/",\
@@ -16061,13 +15708,6 @@ const RAW_RUNTIME_STATE =
}]\
]],\
["sqlstring", [\
["npm:2.3.1", {\
"packageLocation": "./.yarn/cache/sqlstring-npm-2.3.1-2d4ffafe98-bc09237002.zip/node_modules/sqlstring/",\
"packageDependencies": [\
["sqlstring", "npm:2.3.1"]\
],\
"linkType": "HARD"\
}],\
["npm:2.3.3", {\
"packageLocation": "./.yarn/cache/sqlstring-npm-2.3.3-2db6939570-4e5a25af2d.zip/node_modules/sqlstring/",\
"packageDependencies": [\
@@ -16125,15 +15765,6 @@ const RAW_RUNTIME_STATE =
"linkType": "HARD"\
}]\
]],\
["stack-chain", [\
["npm:1.3.7", {\
"packageLocation": "./.yarn/cache/stack-chain-npm-1.3.7-c803ef2abb-6420637b76.zip/node_modules/stack-chain/",\
"packageDependencies": [\
["stack-chain", "npm:1.3.7"]\
],\
"linkType": "HARD"\
}]\
]],\
["stack-trace", [\
["npm:0.0.10", {\
"packageLocation": "./.yarn/cache/stack-trace-npm-0.0.10-9460b173e1-7bd633f0e9.zip/node_modules/stack-trace/",\
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+6
View File
@@ -3,6 +3,12 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [2.28.2](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.28.1...@standardnotes/analytics@2.28.2) (2023-10-09)
### Bug Fixes
* remove xray sdk in favor of opentelemetry ([b736dab](https://github.com/standardnotes/server/commit/b736dab3c1f76c9e03c4bc7bbf153dcb3309b7cb))
## [2.28.1](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.28.0...@standardnotes/analytics@2.28.1) (2023-10-06)
### Bug Fixes
-9
View File
@@ -1,7 +1,6 @@
import 'reflect-metadata'
import { Logger } from 'winston'
import * as AWSXRay from 'aws-xray-sdk'
import { EmailLevel } from '@standardnotes/domain-core'
import { DomainEventPublisherInterface } from '@standardnotes/domain-events'
@@ -254,14 +253,6 @@ void container.load().then((container) => {
const env: Env = new Env()
env.load()
const isConfiguredForAWSProduction =
env.get('MODE', true) !== 'home-server' && env.get('MODE', true) !== 'self-hosted'
if (isConfiguredForAWSProduction) {
AWSXRay.enableManualMode()
AWSXRay.config([AWSXRay.plugins.ECSPlugin])
}
const logger: Logger = container.get(TYPES.Logger)
logger.info('Starting usage report generation...')
-9
View File
@@ -1,7 +1,6 @@
import 'reflect-metadata'
import { Logger } from 'winston'
import * as AWSXRay from 'aws-xray-sdk'
import { DomainEventSubscriberFactoryInterface } from '@standardnotes/domain-events'
import * as dayjs from 'dayjs'
import * as utc from 'dayjs/plugin/utc'
@@ -17,14 +16,6 @@ void container.load().then((container) => {
const env: Env = new Env()
env.load()
const isConfiguredForAWSProduction =
env.get('MODE', true) !== 'home-server' && env.get('MODE', true) !== 'self-hosted'
if (isConfiguredForAWSProduction) {
AWSXRay.enableManualMode()
AWSXRay.config([AWSXRay.plugins.ECSPlugin])
}
const logger: Logger = container.get(TYPES.Logger)
logger.info('Starting worker...')
+1 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/analytics",
"version": "2.28.1",
"version": "2.28.2",
"engines": {
"node": ">=18.0.0 <21.0.0"
},
@@ -46,7 +46,6 @@
"@standardnotes/domain-events": "workspace:*",
"@standardnotes/domain-events-infra": "workspace:*",
"@standardnotes/time": "workspace:*",
"aws-xray-sdk": "^3.5.2",
"dayjs": "^1.11.6",
"dotenv": "^16.0.1",
"inversify": "^6.0.1",
+4 -14
View File
@@ -6,7 +6,7 @@ import {
DomainEventMessageHandlerInterface,
DomainEventSubscriberFactoryInterface,
} from '@standardnotes/domain-events'
import { MapperInterface, ServiceIdentifier } from '@standardnotes/domain-core'
import { MapperInterface } from '@standardnotes/domain-core'
// eslint-disable-next-line @typescript-eslint/no-var-requires
const Mixpanel = require('mixpanel')
@@ -18,7 +18,6 @@ import {
SNSDomainEventPublisher,
SQSDomainEventSubscriberFactory,
SQSEventMessageHandler,
SQSXRayEventMessageHandler,
} from '@standardnotes/domain-events-infra'
import { Timer, TimerInterface } from '@standardnotes/time'
import { PeriodKeyGeneratorInterface } from '../Domain/Time/PeriodKeyGeneratorInterface'
@@ -57,7 +56,6 @@ import { SNSClient, SNSClientConfig } from '@aws-sdk/client-sns'
import { SQSClient, SQSClientConfig } from '@aws-sdk/client-sqs'
import { SessionCreatedEventHandler } from '../Domain/Handler/SessionCreatedEventHandler'
import { SessionRefreshedEventHandler } from '../Domain/Handler/SessionRefreshedEventHandler'
import { captureAWSv3Client } from 'aws-xray-sdk'
export class ContainerConfigLoader {
async load(): Promise<Container> {
@@ -108,7 +106,7 @@ export class ContainerConfigLoader {
secretAccessKey: env.get('SNS_SECRET_ACCESS_KEY', true),
}
}
container.bind<SNSClient>(TYPES.SNS).toConstantValue(captureAWSv3Client(new SNSClient(snsConfig)))
container.bind<SNSClient>(TYPES.SNS).toConstantValue(new SNSClient(snsConfig))
if (env.get('SQS_QUEUE_URL', true)) {
const sqsConfig: SQSClientConfig = {
@@ -123,7 +121,7 @@ export class ContainerConfigLoader {
secretAccessKey: env.get('SQS_SECRET_ACCESS_KEY', true),
}
}
container.bind<SQSClient>(TYPES.SQS).toConstantValue(captureAWSv3Client(new SQSClient(sqsConfig)))
container.bind<SQSClient>(TYPES.SQS).toConstantValue(new SQSClient(sqsConfig))
}
// env vars
@@ -245,15 +243,7 @@ export class ContainerConfigLoader {
container
.bind<DomainEventMessageHandlerInterface>(TYPES.DomainEventMessageHandler)
.toConstantValue(
env.get('NEW_RELIC_ENABLED', true) === 'true'
? new SQSXRayEventMessageHandler(
ServiceIdentifier.NAMES.AnalyticsWorker,
eventHandlers,
container.get(TYPES.Logger),
)
: new SQSEventMessageHandler(eventHandlers, container.get(TYPES.Logger)),
)
.toConstantValue(new SQSEventMessageHandler(eventHandlers, container.get(TYPES.Logger)))
container
.bind<DomainEventSubscriberFactoryInterface>(TYPES.DomainEventSubscriberFactory)
.toConstantValue(
+6
View File
@@ -3,6 +3,12 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.77.2](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.77.1...@standardnotes/api-gateway@1.77.2) (2023-10-09)
### Bug Fixes
* remove xray sdk in favor of opentelemetry ([b736dab](https://github.com/standardnotes/api-gateway/commit/b736dab3c1f76c9e03c4bc7bbf153dcb3309b7cb))
## [1.77.1](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.77.0...@standardnotes/api-gateway@1.77.1) (2023-10-06)
**Note:** Version bump only for package @standardnotes/api-gateway
-17
View File
@@ -29,7 +29,6 @@ import helmet from 'helmet'
import * as cors from 'cors'
import { text, json, Request, Response, NextFunction } from 'express'
import * as winston from 'winston'
import * as AWSXRay from 'aws-xray-sdk'
// eslint-disable-next-line @typescript-eslint/no-var-requires
const robots = require('express-robots-txt')
@@ -37,27 +36,15 @@ 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 { ServiceIdentifier } from '@standardnotes/domain-core'
const container = new ContainerConfigLoader()
void container.load().then((container) => {
const env: Env = new Env()
env.load()
const isConfiguredForAWSProduction =
env.get('MODE', true) !== 'home-server' && env.get('MODE', true) !== 'self-hosted'
if (isConfiguredForAWSProduction) {
AWSXRay.config([AWSXRay.plugins.ECSPlugin])
}
const server = new InversifyExpressServer(container)
server.setConfig((app) => {
if (isConfiguredForAWSProduction) {
app.use(AWSXRay.express.openSegment(ServiceIdentifier.NAMES.ApiGateway))
}
app.use((_request: Request, response: Response, next: NextFunction) => {
response.setHeader('X-API-Gateway-Version', container.get(TYPES.ApiGateway_VERSION))
next()
@@ -117,10 +104,6 @@ void container.load().then((container) => {
const serverInstance = server.build()
if (isConfiguredForAWSProduction) {
serverInstance.use(AWSXRay.express.closeSegment())
}
serverInstance.listen(env.get('PORT'))
logger.info(`Server started on port ${process.env.PORT}`)
+1 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/api-gateway",
"version": "1.77.1",
"version": "1.77.2",
"engines": {
"node": ">=18.0.0 <21.0.0"
},
@@ -31,7 +31,6 @@
"@standardnotes/domain-events-infra": "workspace:*",
"@standardnotes/security": "workspace:*",
"@standardnotes/time": "workspace:*",
"aws-xray-sdk": "^3.5.2",
"axios": "^1.1.3",
"cors": "2.8.5",
"dotenv": "^16.0.1",
@@ -35,8 +35,6 @@ export class ContainerConfigLoader {
const container = new Container()
const isConfiguredForHomeServer = env.get('MODE', true) === 'home-server'
const isConfiguredForSelfHosting = env.get('MODE', true) === 'self-hosted'
const isConfiguredForAWSProduction = !isConfiguredForHomeServer && !isConfiguredForSelfHosting
const isConfiguredForInMemoryCache = env.get('CACHE_TYPE', true) === 'memory'
const winstonFormatters = [winston.format.splat(), winston.format.json()]
@@ -92,9 +90,6 @@ export class ContainerConfigLoader {
.bind(TYPES.ApiGateway_CROSS_SERVICE_TOKEN_CACHE_TTL)
.toConstantValue(+env.get('CROSS_SERVICE_TOKEN_CACHE_TTL', true))
container.bind(TYPES.ApiGateway_IS_CONFIGURED_FOR_HOME_SERVER).toConstantValue(isConfiguredForHomeServer)
container
.bind<boolean>(TYPES.ApiGateway_IS_CONFIGURED_FOR_AWS_PRODUCTION)
.toConstantValue(isConfiguredForAWSProduction)
// Middleware
container
@@ -15,7 +15,6 @@ export const TYPES = {
ApiGateway_VERSION: Symbol.for('ApiGateway_VERSION'),
ApiGateway_CROSS_SERVICE_TOKEN_CACHE_TTL: Symbol.for('ApiGateway_CROSS_SERVICE_TOKEN_CACHE_TTL'),
ApiGateway_IS_CONFIGURED_FOR_HOME_SERVER: Symbol.for('ApiGateway_IS_CONFIGURED_FOR_HOME_SERVER'),
ApiGateway_IS_CONFIGURED_FOR_AWS_PRODUCTION: Symbol.for('ApiGateway_IS_CONFIGURED_FOR_AWS_PRODUCTION'),
// Middleware
ApiGateway_RequiredCrossServiceTokenMiddleware: Symbol.for('ApiGateway_RequiredCrossServiceTokenMiddleware'),
ApiGateway_OptionalCrossServiceTokenMiddleware: Symbol.for('ApiGateway_OptionalCrossServiceTokenMiddleware'),
@@ -8,7 +8,6 @@ import { Logger } from 'winston'
import { CrossServiceTokenCacheInterface } from '../Service/Cache/CrossServiceTokenCacheInterface'
import { ServiceProxyInterface } from '../Service/Http/ServiceProxyInterface'
import { Segment, getSegment } from 'aws-xray-sdk'
export abstract class AuthMiddleware extends BaseMiddleware {
constructor(
@@ -17,7 +16,6 @@ export abstract class AuthMiddleware extends BaseMiddleware {
private crossServiceTokenCacheTTL: number,
private crossServiceTokenCache: CrossServiceTokenCacheInterface,
private timer: TimerInterface,
private isConfiguredForAWSProduction: boolean,
protected logger: Logger,
) {
super()
@@ -75,13 +73,6 @@ export abstract class AuthMiddleware extends BaseMiddleware {
response.locals.roles = decodedToken.roles
response.locals.sharedVaultOwnerContext = decodedToken.shared_vault_owner_context
response.locals.belongsToSharedVaults = decodedToken.belongs_to_shared_vaults ?? []
if (this.isConfiguredForAWSProduction) {
const segment = getSegment()
if (segment instanceof Segment) {
segment.setUser(decodedToken.user.uuid)
}
}
} catch (error) {
const errorMessage = (error as AxiosError).isAxiosError
? JSON.stringify((error as AxiosError).response?.data)
@@ -16,18 +16,9 @@ export class OptionalCrossServiceTokenMiddleware extends AuthMiddleware {
@inject(TYPES.ApiGateway_CROSS_SERVICE_TOKEN_CACHE_TTL) crossServiceTokenCacheTTL: number,
@inject(TYPES.ApiGateway_CrossServiceTokenCache) crossServiceTokenCache: CrossServiceTokenCacheInterface,
@inject(TYPES.ApiGateway_Timer) timer: TimerInterface,
@inject(TYPES.ApiGateway_IS_CONFIGURED_FOR_AWS_PRODUCTION) isConfiguredForAWSProduction: boolean,
@inject(TYPES.ApiGateway_Logger) logger: Logger,
) {
super(
serviceProxy,
jwtSecret,
crossServiceTokenCacheTTL,
crossServiceTokenCache,
timer,
isConfiguredForAWSProduction,
logger,
)
super(serviceProxy, jwtSecret, crossServiceTokenCacheTTL, crossServiceTokenCache, timer, logger)
}
protected override handleSessionValidationResponse(
@@ -16,18 +16,9 @@ export class RequiredCrossServiceTokenMiddleware extends AuthMiddleware {
@inject(TYPES.ApiGateway_CROSS_SERVICE_TOKEN_CACHE_TTL) crossServiceTokenCacheTTL: number,
@inject(TYPES.ApiGateway_CrossServiceTokenCache) crossServiceTokenCache: CrossServiceTokenCacheInterface,
@inject(TYPES.ApiGateway_Timer) timer: TimerInterface,
@inject(TYPES.ApiGateway_IS_CONFIGURED_FOR_AWS_PRODUCTION) isConfiguredForAWSProduction: boolean,
@inject(TYPES.ApiGateway_Logger) logger: Logger,
) {
super(
serviceProxy,
jwtSecret,
crossServiceTokenCacheTTL,
crossServiceTokenCache,
timer,
isConfiguredForAWSProduction,
logger,
)
super(serviceProxy, jwtSecret, crossServiceTokenCacheTTL, crossServiceTokenCache, timer, logger)
}
protected override handleSessionValidationResponse(
+22
View File
@@ -3,6 +3,28 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.152.2](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.152.1...@standardnotes/auth-server@1.152.2) (2023-10-09)
### Bug Fixes
* remove xray sdk in favor of opentelemetry ([b736dab](https://github.com/standardnotes/server/commit/b736dab3c1f76c9e03c4bc7bbf153dcb3309b7cb))
## [1.152.1](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.152.0...@standardnotes/auth-server@1.152.1) (2023-10-06)
### Bug Fixes
* **auth:** checking for transition role when triggering transition ([79a44aa](https://github.com/standardnotes/server/commit/79a44aa51f15311fcaf76c39f93d1934ec1d135d))
# [1.152.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.151.2...@standardnotes/auth-server@1.152.0) (2023-10-06)
### Bug Fixes
* **auth:** strip user from transition role after migration ([afe9967](https://github.com/standardnotes/server/commit/afe9967d26b5be02d1dc76a740df614d81a6984e))
### Features
* switch transition direction ([27bea44](https://github.com/standardnotes/server/commit/27bea444cce4964feda04bad64e5f12a07415e0c))
## [1.151.2](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.151.1...@standardnotes/auth-server@1.151.2) (2023-10-06)
### Bug Fixes
-9
View File
@@ -5,7 +5,6 @@ import { Stream } from 'stream'
import { Logger } from 'winston'
import * as dayjs from 'dayjs'
import * as utc from 'dayjs/plugin/utc'
import * as AWSXRay from 'aws-xray-sdk'
import { ContainerConfigLoader } from '../src/Bootstrap/Container'
import TYPES from '../src/Bootstrap/Types'
@@ -83,14 +82,6 @@ void container.load().then((container) => {
const env: Env = new Env()
env.load()
const isConfiguredForAWSProduction =
env.get('MODE', true) !== 'home-server' && env.get('MODE', true) !== 'self-hosted'
if (isConfiguredForAWSProduction) {
AWSXRay.enableManualMode()
AWSXRay.config([AWSXRay.plugins.ECSPlugin])
}
const logger: Logger = container.get(TYPES.Auth_Logger)
logger.info(`Starting ${backupFrequency} ${backupProvider} backup requesting...`)
-9
View File
@@ -1,7 +1,6 @@
import 'reflect-metadata'
import { Logger } from 'winston'
import * as AWSXRay from 'aws-xray-sdk'
import { ContainerConfigLoader } from '../src/Bootstrap/Container'
import TYPES from '../src/Bootstrap/Types'
@@ -24,14 +23,6 @@ void container.load().then((container) => {
const env: Env = new Env()
env.load()
const isConfiguredForAWSProduction =
env.get('MODE', true) !== 'home-server' && env.get('MODE', true) !== 'self-hosted'
if (isConfiguredForAWSProduction) {
AWSXRay.enableManualMode()
AWSXRay.config([AWSXRay.plugins.ECSPlugin])
}
const logger: Logger = container.get(TYPES.Auth_Logger)
logger.info('Starting sessions and session traces cleanup')
-17
View File
@@ -24,13 +24,11 @@ import { urlencoded, json, Request, Response, NextFunction } from 'express'
import * as winston from 'winston'
import * as dayjs from 'dayjs'
import * as utc from 'dayjs/plugin/utc'
import * as AWSXRay from 'aws-xray-sdk'
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 { ServiceIdentifier } from '@standardnotes/domain-core'
const container = new ContainerConfigLoader()
void container.load().then((container) => {
@@ -39,20 +37,9 @@ void container.load().then((container) => {
const env: Env = new Env()
env.load()
const isConfiguredForAWSProduction =
env.get('MODE', true) !== 'home-server' && env.get('MODE', true) !== 'self-hosted'
if (isConfiguredForAWSProduction) {
AWSXRay.config([AWSXRay.plugins.ECSPlugin])
}
const server = new InversifyExpressServer(container)
server.setConfig((app) => {
if (isConfiguredForAWSProduction) {
app.use(AWSXRay.express.openSegment(ServiceIdentifier.NAMES.Auth))
}
app.use((_request: Request, response: Response, next: NextFunction) => {
response.setHeader('X-Auth-Version', container.get(TYPES.Auth_VERSION))
next()
@@ -79,10 +66,6 @@ void container.load().then((container) => {
const serverInstance = server.build()
if (isConfiguredForAWSProduction) {
serverInstance.use(AWSXRay.express.closeSegment())
}
serverInstance.listen(env.get('PORT'))
logger.info(`Server started on port ${process.env.PORT}`)
-9
View File
@@ -2,7 +2,6 @@ import 'reflect-metadata'
import { Logger } from 'winston'
import { TimerInterface } from '@standardnotes/time'
import * as AWSXRay from 'aws-xray-sdk'
import { ContainerConfigLoader } from '../src/Bootstrap/Container'
import TYPES from '../src/Bootstrap/Types'
@@ -14,14 +13,6 @@ void container.load().then((container) => {
const env: Env = new Env()
env.load()
const isConfiguredForAWSProduction =
env.get('MODE', true) !== 'home-server' && env.get('MODE', true) !== 'self-hosted'
if (isConfiguredForAWSProduction) {
AWSXRay.enableManualMode()
AWSXRay.config([AWSXRay.plugins.ECSPlugin])
}
const logger: Logger = container.get(TYPES.Auth_Logger)
logger.info('Starting session traces cleanup')
+1 -10
View File
@@ -3,7 +3,6 @@ import 'reflect-metadata'
import { Logger } from 'winston'
import * as dayjs from 'dayjs'
import * as utc from 'dayjs/plugin/utc'
import * as AWSXRay from 'aws-xray-sdk'
import { ContainerConfigLoader } from '../src/Bootstrap/Container'
import TYPES from '../src/Bootstrap/Types'
@@ -50,7 +49,7 @@ const requestTransition = async (
itemsTransitionStatus?.value === TransitionStatus.STATUSES.Verified &&
revisionsTransitionStatus?.value === TransitionStatus.STATUSES.Verified
if (userHasTransitionRole && bothTransitionStatusesAreVerified) {
if (!userHasTransitionRole && bothTransitionStatusesAreVerified) {
continue
}
@@ -103,14 +102,6 @@ void container.load().then((container) => {
const env: Env = new Env()
env.load()
const isConfiguredForAWSProduction =
env.get('MODE', true) !== 'home-server' && env.get('MODE', true) !== 'self-hosted'
if (isConfiguredForAWSProduction) {
AWSXRay.enableManualMode()
AWSXRay.config([AWSXRay.plugins.ECSPlugin])
}
const logger: Logger = container.get(TYPES.Auth_Logger)
logger.info(`Starting transition request for users created between ${startDateString} and ${endDateString}`)
-9
View File
@@ -3,7 +3,6 @@ import 'reflect-metadata'
import { Logger } from 'winston'
import * as dayjs from 'dayjs'
import * as utc from 'dayjs/plugin/utc'
import * as AWSXRay from 'aws-xray-sdk'
import { ContainerConfigLoader } from '../src/Bootstrap/Container'
import TYPES from '../src/Bootstrap/Types'
@@ -71,14 +70,6 @@ void container.load().then((container) => {
const env: Env = new Env()
env.load()
const isConfiguredForAWSProduction =
env.get('MODE', true) !== 'home-server' && env.get('MODE', true) !== 'self-hosted'
if (isConfiguredForAWSProduction) {
AWSXRay.enableManualMode()
AWSXRay.config([AWSXRay.plugins.ECSPlugin])
}
const logger: Logger = container.get(TYPES.Auth_Logger)
logger.info(`Starting email backup requesting for ${backupEmail} ...`)
-9
View File
@@ -8,7 +8,6 @@ import { Env } from '../src/Bootstrap/Env'
import { DomainEventSubscriberFactoryInterface } from '@standardnotes/domain-events'
import * as dayjs from 'dayjs'
import * as utc from 'dayjs/plugin/utc'
import * as AWSXRay from 'aws-xray-sdk'
const container = new ContainerConfigLoader('worker')
void container.load().then((container) => {
@@ -17,14 +16,6 @@ void container.load().then((container) => {
const env: Env = new Env()
env.load()
const isConfiguredForAWSProduction =
env.get('MODE', true) !== 'home-server' && env.get('MODE', true) !== 'self-hosted'
if (isConfiguredForAWSProduction) {
AWSXRay.enableManualMode()
AWSXRay.config([AWSXRay.plugins.ECSPlugin])
}
const logger: Logger = container.get(TYPES.Auth_Logger)
logger.info('Starting worker...')
+1 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/auth-server",
"version": "1.151.2",
"version": "1.152.2",
"engines": {
"node": ">=18.0.0 <21.0.0"
},
@@ -54,7 +54,6 @@
"@standardnotes/sncrypto-common": "^1.13.4",
"@standardnotes/sncrypto-node": "workspace:*",
"@standardnotes/time": "workspace:*",
"aws-xray-sdk": "^3.5.2",
"axios": "^1.1.3",
"bcryptjs": "2.4.3",
"cors": "2.8.5",
+3 -22
View File
@@ -1,6 +1,5 @@
import * as winston from 'winston'
import Redis from 'ioredis'
import { captureAWSv3Client } from 'aws-xray-sdk'
import { SNSClient, SNSClientConfig } from '@aws-sdk/client-sns'
import { SQSClient, SQSClientConfig } from '@aws-sdk/client-sqs'
import { Container } from 'inversify'
@@ -93,7 +92,6 @@ import {
SNSDomainEventPublisher,
SQSDomainEventSubscriberFactory,
SQSEventMessageHandler,
SQSXRayEventMessageHandler,
} from '@standardnotes/domain-events-infra'
import { GetUserSubscription } from '../Domain/UseCase/GetUserSubscription/GetUserSubscription'
import { ChangeCredentials } from '../Domain/UseCase/ChangeCredentials/ChangeCredentials'
@@ -190,7 +188,6 @@ import {
ControllerContainer,
ControllerContainerInterface,
MapperInterface,
ServiceIdentifier,
SharedVaultUser,
} from '@standardnotes/domain-core'
import { SessionTracePersistenceMapper } from '../Mapping/SessionTracePersistenceMapper'
@@ -322,8 +319,6 @@ export class ContainerConfigLoader {
logger.debug('Database initialized')
const isConfiguredForHomeServer = env.get('MODE', true) === 'home-server'
const isConfiguredForSelfHosting = env.get('MODE', true) === 'self-hosted'
const isConfiguredForAWSProduction = !isConfiguredForHomeServer && !isConfiguredForSelfHosting
const isConfiguredForInMemoryCache = env.get('CACHE_TYPE', true) === 'memory'
if (!isConfiguredForInMemoryCache) {
@@ -354,10 +349,7 @@ export class ContainerConfigLoader {
secretAccessKey: env.get('SNS_SECRET_ACCESS_KEY', true),
}
}
let snsClient = new SNSClient(snsConfig)
if (isConfiguredForAWSProduction) {
snsClient = captureAWSv3Client(snsClient)
}
const snsClient = new SNSClient(snsConfig)
container.bind<SNSClient>(TYPES.Auth_SNS).toConstantValue(snsClient)
const sqsConfig: SQSClientConfig = {
@@ -372,10 +364,7 @@ export class ContainerConfigLoader {
secretAccessKey: env.get('SQS_SECRET_ACCESS_KEY', true),
}
}
let sqsClient = new SQSClient(sqsConfig)
if (isConfiguredForAWSProduction) {
sqsClient = captureAWSv3Client(sqsClient)
}
const sqsClient = new SQSClient(sqsConfig)
container.bind<SQSClient>(TYPES.Auth_SQS).toConstantValue(sqsClient)
}
@@ -1234,15 +1223,7 @@ export class ContainerConfigLoader {
} else {
container
.bind<DomainEventMessageHandlerInterface>(TYPES.Auth_DomainEventMessageHandler)
.toConstantValue(
isConfiguredForAWSProduction
? new SQSXRayEventMessageHandler(
ServiceIdentifier.NAMES.AuthWorker,
eventHandlers,
container.get(TYPES.Auth_Logger),
)
: new SQSEventMessageHandler(eventHandlers, container.get(TYPES.Auth_Logger)),
)
.toConstantValue(new SQSEventMessageHandler(eventHandlers, container.get(TYPES.Auth_Logger)))
container
.bind<DomainEventSubscriberFactoryInterface>(TYPES.Auth_DomainEventSubscriberFactory)
@@ -118,6 +118,40 @@ describe('RoleService', () => {
})
})
describe('removing roles', () => {
beforeEach(() => {
user = {
uuid: '123',
email: 'test@test.com',
roles: Promise.resolve([basicRole]),
} as jest.Mocked<User>
userRepository.findOneByUuid = jest.fn().mockReturnValue(user)
userRepository.save = jest.fn().mockReturnValue(user)
})
it('should remove a role from a user', async () => {
await createService().removeRoleFromUser(
Uuid.create('00000000-0000-0000-0000-000000000000').getValue(),
RoleName.create(RoleName.NAMES.CoreUser).getValue(),
)
user.roles = Promise.resolve([])
expect(userRepository.save).toHaveBeenCalledWith(user)
})
it('should not remove a role from a user if the user could not be found', async () => {
userRepository.findOneByUuid = jest.fn().mockReturnValue(null)
await createService().removeRoleFromUser(
Uuid.create('00000000-0000-0000-0000-000000000000').getValue(),
RoleName.create(RoleName.NAMES.CoreUser).getValue(),
)
expect(userRepository.save).not.toHaveBeenCalled()
})
})
describe('adding roles based on subscription', () => {
beforeEach(() => {
user = {
@@ -65,6 +65,17 @@ export class RoleService implements RoleServiceInterface {
await this.addToExistingRoles(user, roleName.value)
}
async removeRoleFromUser(userUuid: Uuid, roleName: RoleName): Promise<void> {
const user = await this.userRepository.findOneByUuid(userUuid)
if (user === null) {
this.logger.error(`Could not find user with uuid ${userUuid.value} to remove role ${roleName.value}`)
return
}
await this.removeUserRole(user, roleName.value)
}
async addUserRoleBasedOnSubscription(user: User, subscriptionName: SubscriptionName): Promise<void> {
const roleName = this.roleToSubscriptionMap.getRoleNameForSubscriptionName(subscriptionName)
@@ -108,9 +119,15 @@ export class RoleService implements RoleServiceInterface {
return
}
await this.removeUserRole(user, roleName)
}
private async removeUserRole(user: User, roleName: string): Promise<void> {
const currentRoles = await user.roles
user.roles = Promise.resolve(currentRoles.filter((role) => role.name !== roleName))
await this.userRepository.save(user)
await this.webSocketsClientService.sendUserRolesChangedEvent(user)
}
@@ -5,6 +5,7 @@ import { User } from '../User/User'
export interface RoleServiceInterface {
addRoleToUser(userUuid: Uuid, roleName: RoleName): Promise<void>
removeRoleFromUser(userUuid: Uuid, roleName: RoleName): Promise<void>
addUserRoleBasedOnSubscription(user: User, subscriptionName: string): Promise<void>
setOfflineUserRole(offlineUserSubscription: OfflineUserSubscription): Promise<void>
removeUserRoleBasedOnSubscription(user: User, subscriptionName: string): Promise<void>
@@ -21,7 +21,7 @@ describe('UpdateTransitionStatus', () => {
transitionStatusRepository.getStatus = jest.fn().mockResolvedValue(null)
roleService = {} as jest.Mocked<RoleServiceInterface>
roleService.addRoleToUser = jest.fn()
roleService.removeRoleFromUser = jest.fn()
})
it('should add TRANSITION_USER role', async () => {
@@ -35,7 +35,7 @@ describe('UpdateTransitionStatus', () => {
})
expect(result.isFailed()).toBeFalsy()
expect(roleService.addRoleToUser).toHaveBeenCalledWith(
expect(roleService.removeRoleFromUser).toHaveBeenCalledWith(
Uuid.create('00000000-0000-0000-0000-000000000000').getValue(),
RoleName.create(RoleName.NAMES.TransitionUser).getValue(),
)
@@ -32,7 +32,7 @@ export class UpdateTransitionStatus implements UseCaseInterface<void> {
await this.transitionStatusRepository.updateStatus(dto.userUuid, dto.transitionType, transitionStatus)
if (dto.transitionType === 'items' && transitionStatus.value === TransitionStatus.STATUSES.Verified) {
await this.roleService.addRoleToUser(userUuid, RoleName.create(RoleName.NAMES.TransitionUser).getValue())
await this.roleService.removeRoleFromUser(userUuid, RoleName.create(RoleName.NAMES.TransitionUser).getValue())
}
return Result.ok()
@@ -4,7 +4,7 @@ import { TransitionStatusRepositoryInterface } from '../../Domain/Transition/Tra
import { TransitionStatus } from '@standardnotes/domain-core'
export class RedisTransitionStatusRepository implements TransitionStatusRepositoryInterface {
private readonly PREFIX = 'transition'
private readonly PREFIX = 'transition-back'
constructor(private redisClient: IORedis.Redis) {}
@@ -3,6 +3,12 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.14.9](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.14.8...@standardnotes/domain-events-infra@1.14.9) (2023-10-09)
### Bug Fixes
* remove xray sdk in favor of opentelemetry ([b736dab](https://github.com/standardnotes/server/commit/b736dab3c1f76c9e03c4bc7bbf153dcb3309b7cb))
## [1.14.8](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.14.7...@standardnotes/domain-events-infra@1.14.8) (2023-10-06)
**Note:** Version bump only for package @standardnotes/domain-events-infra
+1 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/domain-events-infra",
"version": "1.14.8",
"version": "1.14.9",
"engines": {
"node": ">=18.0.0 <21.0.0"
},
@@ -27,7 +27,6 @@
"@aws-sdk/client-sns": "^3.332.0",
"@aws-sdk/client-sqs": "^3.332.0",
"@standardnotes/domain-events": "workspace:*",
"aws-xray-sdk": "^3.5.2",
"ioredis": "^5.2.4",
"reflect-metadata": "^0.1.13",
"sqs-consumer": "^7.3.0",
@@ -1,60 +0,0 @@
import { Logger } from 'winston'
import * as zlib from 'zlib'
import { Segment, Subsegment, captureAsyncFunc } from 'aws-xray-sdk'
import {
DomainEventHandlerInterface,
DomainEventInterface,
DomainEventMessageHandlerInterface,
} from '@standardnotes/domain-events'
export class SQSXRayEventMessageHandler implements DomainEventMessageHandlerInterface {
constructor(
private serviceName: string,
private handlers: Map<string, DomainEventHandlerInterface>,
private logger: Logger,
) {}
async handleMessage(message: string): Promise<void> {
const messageParsed = JSON.parse(message)
const domainEventJson = zlib.unzipSync(Buffer.from(messageParsed.Message, 'base64')).toString()
const domainEvent: DomainEventInterface = JSON.parse(domainEventJson)
domainEvent.createdAt = new Date(domainEvent.createdAt)
const handler = this.handlers.get(domainEvent.type)
if (!handler) {
this.logger.debug(`Event handler for event type ${domainEvent.type} does not exist`)
return
}
this.logger.debug(`Received event: ${domainEvent.type}`)
const xRaySegment = new Segment(this.serviceName)
if (domainEvent.meta.correlation.userIdentifierType === 'uuid') {
xRaySegment.setUser(domainEvent.meta.correlation.userIdentifier)
}
await captureAsyncFunc(
domainEvent.type,
async (subsegment?: Subsegment) => {
await handler.handle(domainEvent)
if (subsegment) {
subsegment.close()
}
},
xRaySegment,
)
xRaySegment.close()
}
async handleError(error: Error): Promise<void> {
this.logger.error('Error occured while handling SQS message: %O', error)
}
}
@@ -12,4 +12,3 @@ export * from './SQS/SQSNewRelicBounceNotificiationHandler'
export * from './SQS/SQSDomainEventSubscriberFactory'
export * from './SQS/SQSEventMessageHandler'
export * from './SQS/SQSNewRelicEventMessageHandler'
export * from './SQS/SQSXRayEventMessageHandler'
+4
View File
@@ -3,6 +3,10 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.12.12](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.12.11...@standardnotes/event-store@1.12.12) (2023-10-09)
**Note:** Version bump only for package @standardnotes/event-store
## [1.12.11](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.12.10...@standardnotes/event-store@1.12.11) (2023-10-06)
**Note:** Version bump only for package @standardnotes/event-store
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/event-store",
"version": "1.12.11",
"version": "1.12.12",
"description": "Event Store Service",
"private": true,
"main": "dist/src/index.js",
+6
View File
@@ -3,6 +3,12 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.26.4](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.26.3...@standardnotes/files-server@1.26.4) (2023-10-09)
### Bug Fixes
* remove xray sdk in favor of opentelemetry ([b736dab](https://github.com/standardnotes/files/commit/b736dab3c1f76c9e03c4bc7bbf153dcb3309b7cb))
## [1.26.3](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.26.2...@standardnotes/files-server@1.26.3) (2023-10-06)
**Note:** Version bump only for package @standardnotes/files-server
-17
View File
@@ -10,7 +10,6 @@ import helmet from 'helmet'
import * as cors from 'cors'
import { urlencoded, json, raw, Request, Response, NextFunction } from 'express'
import * as winston from 'winston'
import * as AWSXRay from 'aws-xray-sdk'
// eslint-disable-next-line @typescript-eslint/no-var-requires
const robots = require('express-robots-txt')
@@ -18,27 +17,15 @@ 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 { ServiceIdentifier } from '@standardnotes/domain-core'
const container = new ContainerConfigLoader()
void container.load().then((container) => {
const env: Env = new Env()
env.load()
const isConfiguredForAWSProduction =
env.get('MODE', true) !== 'home-server' && env.get('MODE', true) !== 'self-hosted'
if (isConfiguredForAWSProduction) {
AWSXRay.config([AWSXRay.plugins.ECSPlugin])
}
const server = new InversifyExpressServer(container)
server.setConfig((app) => {
if (isConfiguredForAWSProduction) {
app.use(AWSXRay.express.openSegment(ServiceIdentifier.NAMES.Files))
}
app.use((_request: Request, response: Response, next: NextFunction) => {
response.setHeader('X-Files-Version', container.get(TYPES.Files_VERSION))
next()
@@ -103,10 +90,6 @@ void container.load().then((container) => {
const serverInstance = server.build()
if (isConfiguredForAWSProduction) {
serverInstance.use(AWSXRay.express.closeSegment())
}
serverInstance.listen(env.get('PORT'))
logger.info(`Server started on port ${process.env.PORT}`)
-9
View File
@@ -8,7 +8,6 @@ import { Env } from '../src/Bootstrap/Env'
import { DomainEventSubscriberFactoryInterface } from '@standardnotes/domain-events'
import * as dayjs from 'dayjs'
import * as utc from 'dayjs/plugin/utc'
import * as AWSXRay from 'aws-xray-sdk'
const container = new ContainerConfigLoader()
void container.load().then((container) => {
@@ -17,14 +16,6 @@ void container.load().then((container) => {
const env: Env = new Env()
env.load()
const isConfiguredForAWSProduction =
env.get('MODE', true) !== 'home-server' && env.get('MODE', true) !== 'self-hosted'
if (isConfiguredForAWSProduction) {
AWSXRay.enableManualMode()
AWSXRay.config([AWSXRay.plugins.ECSPlugin])
}
const logger: Logger = container.get(TYPES.Files_Logger)
logger.info('Starting worker...')
+1 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/files-server",
"version": "1.26.3",
"version": "1.26.4",
"engines": {
"node": ">=18.0.0 <21.0.0"
},
@@ -37,7 +37,6 @@
"@standardnotes/sncrypto-common": "^1.13.4",
"@standardnotes/sncrypto-node": "workspace:*",
"@standardnotes/time": "workspace:*",
"aws-xray-sdk": "^3.5.2",
"connect-busboy": "^1.0.0",
"cors": "^2.8.5",
"dayjs": "^1.11.6",
+4 -26
View File
@@ -1,6 +1,5 @@
import * as winston from 'winston'
import Redis from 'ioredis'
import { captureAWSv3Client } from 'aws-xray-sdk'
import { SNSClient, SNSClientConfig } from '@aws-sdk/client-sns'
import { SQSClient, SQSClientConfig } from '@aws-sdk/client-sqs'
import { S3Client, S3ClientConfig } from '@aws-sdk/client-s3'
@@ -20,7 +19,6 @@ import {
SNSDomainEventPublisher,
SQSDomainEventSubscriberFactory,
SQSEventMessageHandler,
SQSXRayEventMessageHandler,
} from '@standardnotes/domain-events-infra'
import { StreamDownloadFile } from '../Domain/UseCase/StreamDownloadFile/StreamDownloadFile'
import { FileDownloaderInterface } from '../Domain/Services/FileDownloaderInterface'
@@ -54,7 +52,6 @@ import { S3FileMover } from '../Infra/S3/S3FileMover'
import { FSFileMover } from '../Infra/FS/FSFileMover'
import { MoveFile } from '../Domain/UseCase/MoveFile/MoveFile'
import { SharedVaultValetTokenAuthMiddleware } from '../Infra/InversifyExpress/Middleware/SharedVaultValetTokenAuthMiddleware'
import { ServiceIdentifier } from '@standardnotes/domain-core'
export class ContainerConfigLoader {
async load(configuration?: {
@@ -85,9 +82,7 @@ export class ContainerConfigLoader {
.toConstantValue(env.get('FILE_UPLOAD_PATH', true) ?? `${__dirname}/../../uploads`)
const isConfiguredForHomeServer = env.get('MODE', true) === 'home-server'
const isConfiguredForSelfHosting = env.get('MODE', true) === 'self-hosted'
const isConfiguredForInMemoryCache = env.get('CACHE_TYPE', true) === 'memory'
const isConfiguredForAWSProduction = !isConfiguredForHomeServer && !isConfiguredForSelfHosting
let logger: winston.Logger
if (configuration?.logger) {
@@ -153,10 +148,7 @@ export class ContainerConfigLoader {
secretAccessKey: env.get('SNS_SECRET_ACCESS_KEY', true),
}
}
let snsClient = new SNSClient(snsConfig)
if (isConfiguredForAWSProduction) {
snsClient = captureAWSv3Client(snsClient)
}
const snsClient = new SNSClient(snsConfig)
container.bind<SNSClient>(TYPES.Files_SNS).toConstantValue(snsClient)
}
@@ -173,10 +165,7 @@ export class ContainerConfigLoader {
secretAccessKey: env.get('SQS_SECRET_ACCESS_KEY', true),
}
}
let sqsClient = new SQSClient(sqsConfig)
if (isConfiguredForAWSProduction) {
sqsClient = captureAWSv3Client(sqsClient)
}
const sqsClient = new SQSClient(sqsConfig)
container.bind<SQSClient>(TYPES.Files_SQS).toConstantValue(sqsClient)
}
@@ -197,10 +186,7 @@ export class ContainerConfigLoader {
if (env.get('S3_ENDPOINT', true)) {
s3Opts.endpoint = env.get('S3_ENDPOINT', true)
}
let s3Client = new S3Client(s3Opts)
if (isConfiguredForAWSProduction) {
s3Client = captureAWSv3Client(s3Client)
}
const s3Client = new S3Client(s3Opts)
container.bind<S3Client>(TYPES.Files_S3).toConstantValue(s3Client)
container.bind<FileDownloaderInterface>(TYPES.Files_FileDownloader).to(S3FileDownloader)
container.bind<FileUploaderInterface>(TYPES.Files_FileUploader).to(S3FileUploader)
@@ -305,15 +291,7 @@ export class ContainerConfigLoader {
} else {
container
.bind<DomainEventMessageHandlerInterface>(TYPES.Files_DomainEventMessageHandler)
.toConstantValue(
env.get('NEW_RELIC_ENABLED', true) === 'true'
? new SQSXRayEventMessageHandler(
ServiceIdentifier.NAMES.FilesWorker,
eventHandlers,
container.get(TYPES.Files_Logger),
)
: new SQSEventMessageHandler(eventHandlers, container.get(TYPES.Files_Logger)),
)
.toConstantValue(new SQSEventMessageHandler(eventHandlers, container.get(TYPES.Files_Logger)))
container
.bind<DomainEventSubscriberFactoryInterface>(TYPES.Files_DomainEventSubscriberFactory)
.toConstantValue(
+24
View File
@@ -3,6 +3,30 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.16.36](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.16.35...@standardnotes/home-server@1.16.36) (2023-10-09)
**Note:** Version bump only for package @standardnotes/home-server
## [1.16.35](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.16.34...@standardnotes/home-server@1.16.35) (2023-10-09)
**Note:** Version bump only for package @standardnotes/home-server
## [1.16.34](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.16.33...@standardnotes/home-server@1.16.34) (2023-10-06)
**Note:** Version bump only for package @standardnotes/home-server
## [1.16.33](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.16.32...@standardnotes/home-server@1.16.33) (2023-10-06)
**Note:** Version bump only for package @standardnotes/home-server
## [1.16.32](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.16.31...@standardnotes/home-server@1.16.32) (2023-10-06)
**Note:** Version bump only for package @standardnotes/home-server
## [1.16.31](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.16.30...@standardnotes/home-server@1.16.31) (2023-10-06)
**Note:** Version bump only for package @standardnotes/home-server
## [1.16.30](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.16.29...@standardnotes/home-server@1.16.30) (2023-10-06)
**Note:** Version bump only for package @standardnotes/home-server
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/home-server",
"version": "1.16.30",
"version": "1.16.36",
"engines": {
"node": ">=18.0.0 <21.0.0"
},
+28
View File
@@ -3,6 +3,34 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.40.3](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.40.2...@standardnotes/revisions-server@1.40.3) (2023-10-09)
### Bug Fixes
* remove xray sdk in favor of opentelemetry ([b736dab](https://github.com/standardnotes/server/commit/b736dab3c1f76c9e03c4bc7bbf153dcb3309b7cb))
## [1.40.2](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.40.1...@standardnotes/revisions-server@1.40.2) (2023-10-09)
### Bug Fixes
* logs in transition ([29e8de3](https://github.com/standardnotes/server/commit/29e8de32383e911bbb431d3fd0da68faefa32d3d))
## [1.40.1](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.40.0...@standardnotes/revisions-server@1.40.1) (2023-10-06)
### Bug Fixes
* **revisions:** casting creation date from MongoDB ([4780629](https://github.com/standardnotes/server/commit/47806295491867ca5fd53e39757f057a0722ae28))
# [1.40.0](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.39.5...@standardnotes/revisions-server@1.40.0) (2023-10-06)
### Bug Fixes
* enable TransitionRequestedEventHandler ([d8f1c66](https://github.com/standardnotes/server/commit/d8f1c66fd5e59285ccaa1be36da2ee9796b81ccb))
### Features
* switch transition direction ([27bea44](https://github.com/standardnotes/server/commit/27bea444cce4964feda04bad64e5f12a07415e0c))
## [1.39.5](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.39.4...@standardnotes/revisions-server@1.39.5) (2023-10-06)
**Note:** Version bump only for package @standardnotes/revisions-server
-17
View File
@@ -3,7 +3,6 @@ import 'reflect-metadata'
import * as cors from 'cors'
import { urlencoded, json, Request, Response, NextFunction } from 'express'
import * as winston from 'winston'
import * as AWSXRay from 'aws-xray-sdk'
import { InversifyExpressServer } from 'inversify-express-utils'
import TYPES from '../src/Bootstrap/Types'
@@ -12,26 +11,14 @@ import { ContainerConfigLoader } from '../src/Bootstrap/Container'
import '../src/Infra/InversifyExpress/AnnotatedRevisionsController'
import '../src/Infra/InversifyExpress/AnnotatedHealthCheckController'
import { ServiceIdentifier } from '@standardnotes/domain-core'
const container = new ContainerConfigLoader()
void container.load().then((container) => {
const env: Env = container.get(TYPES.Revisions_Env)
const isConfiguredForAWSProduction =
env.get('MODE', true) !== 'home-server' && env.get('MODE', true) !== 'self-hosted'
if (isConfiguredForAWSProduction) {
AWSXRay.config([AWSXRay.plugins.ECSPlugin])
}
const server = new InversifyExpressServer(container)
server.setConfig((app) => {
if (isConfiguredForAWSProduction) {
app.use(AWSXRay.express.openSegment(ServiceIdentifier.NAMES.Revisions))
}
app.use((_request: Request, response: Response, next: NextFunction) => {
response.setHeader('X-Revisions-Version', container.get(TYPES.Revisions_VERSION))
next()
@@ -58,10 +45,6 @@ void container.load().then((container) => {
const serverInstance = server.build()
if (isConfiguredForAWSProduction) {
serverInstance.use(AWSXRay.express.closeSegment())
}
serverInstance.listen(env.get('PORT'))
logger.info(`Server started on port ${process.env.PORT}`)
-9
View File
@@ -1,7 +1,6 @@
import 'reflect-metadata'
import { Logger } from 'winston'
import * as AWSXRay from 'aws-xray-sdk'
import TYPES from '../src/Bootstrap/Types'
import { Env } from '../src/Bootstrap/Env'
@@ -13,14 +12,6 @@ void container.load().then((container) => {
const env: Env = new Env()
env.load()
const isConfiguredForAWSProduction =
env.get('MODE', true) !== 'home-server' && env.get('MODE', true) !== 'self-hosted'
if (isConfiguredForAWSProduction) {
AWSXRay.enableManualMode()
AWSXRay.config([AWSXRay.plugins.ECSPlugin])
}
const logger: Logger = container.get(TYPES.Revisions_Logger)
logger.info('Starting worker...')
+1 -4
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/revisions-server",
"version": "1.39.5",
"version": "1.40.3",
"engines": {
"node": ">=18.0.0 <21.0.0"
},
@@ -36,7 +36,6 @@
"@standardnotes/responses": "^1.13.27",
"@standardnotes/security": "workspace:^",
"@standardnotes/time": "workspace:^",
"aws-xray-sdk": "^3.5.2",
"cors": "2.8.5",
"dotenv": "^16.0.1",
"express": "^4.18.2",
@@ -44,7 +43,6 @@
"inversify-express-utils": "^6.4.3",
"ioredis": "^5.3.2",
"mongodb": "^6.0.0",
"mysql": "^2.18.1",
"mysql2": "^3.0.1",
"reflect-metadata": "0.1.13",
"sqlite3": "^5.1.6",
@@ -57,7 +55,6 @@
"@types/express": "^4.17.14",
"@types/ioredis": "^5.0.0",
"@types/jest": "^29.5.1",
"@types/mysql": "^2",
"@types/node": "^20.5.7",
"@typescript-eslint/eslint-plugin": "^6.5.0",
"@typescript-eslint/parser": "^6.5.0",
+4 -32
View File
@@ -1,14 +1,8 @@
import {
ControllerContainer,
ControllerContainerInterface,
MapperInterface,
ServiceIdentifier,
} from '@standardnotes/domain-core'
import { ControllerContainer, ControllerContainerInterface, MapperInterface } from '@standardnotes/domain-core'
import Redis from 'ioredis'
import { Container, interfaces } from 'inversify'
import { MongoRepository, Repository } from 'typeorm'
import * as winston from 'winston'
import { captureAWSv3Client } from 'aws-xray-sdk'
import { SNSClient, SNSClientConfig } from '@aws-sdk/client-sns'
import { Revision } from '../Domain/Revision/Revision'
@@ -41,7 +35,6 @@ import {
DirectCallEventMessageHandler,
DirectCallDomainEventPublisher,
SNSDomainEventPublisher,
SQSXRayEventMessageHandler,
} from '@standardnotes/domain-events-infra'
import { DumpRepositoryInterface } from '../Domain/Dump/DumpRepositoryInterface'
import { AccountDeletionRequestedEventHandler } from '../Domain/Handler/AccountDeletionRequestedEventHandler'
@@ -96,7 +89,6 @@ export class ContainerConfigLoader {
const isConfiguredForHomeServer = env.get('MODE', true) === 'home-server'
const isConfiguredForSelfHosting = env.get('MODE', true) === 'self-hosted'
const isConfiguredForAWSProduction = !isConfiguredForHomeServer && !isConfiguredForSelfHosting
const isConfiguredForHomeServerOrSelfHosting = isConfiguredForHomeServer || isConfiguredForSelfHosting
const isSecondaryDatabaseEnabled = env.get('SECONDARY_DB_ENABLED', true) === 'true'
const isConfiguredForInMemoryCache = env.get('CACHE_TYPE', true) === 'memory'
@@ -180,10 +172,6 @@ export class ContainerConfigLoader {
}
}
if (isConfiguredForAWSProduction) {
return captureAWSv3Client(new SNSClient(snsConfig))
}
return new SNSClient(snsConfig)
})
@@ -212,10 +200,6 @@ export class ContainerConfigLoader {
}
}
if (isConfiguredForAWSProduction) {
return captureAWSv3Client(new SQSClient(sqsConfig))
}
return new SQSClient(sqsConfig)
})
@@ -228,10 +212,6 @@ export class ContainerConfigLoader {
apiVersion: 'latest',
region: env.get('S3_AWS_REGION', true),
})
if (isConfiguredForAWSProduction) {
return captureAWSv3Client(s3Client)
}
}
return s3Client
@@ -268,7 +248,7 @@ export class ContainerConfigLoader {
.toConstantValue(new MongoDBRevisionMetadataPersistenceMapper())
container
.bind<MapperInterface<Revision, MongoDBRevision>>(TYPES.Revisions_MongoDBRevisionPersistenceMapper)
.toConstantValue(new MongoDBRevisionPersistenceMapper())
.toConstantValue(new MongoDBRevisionPersistenceMapper(container.get<TimerInterface>(TYPES.Revisions_Timer)))
// ORM
container
@@ -491,7 +471,7 @@ export class ContainerConfigLoader {
.bind<TransitionRequestedEventHandler>(TYPES.Revisions_TransitionRequestedEventHandler)
.toConstantValue(
new TransitionRequestedEventHandler(
true,
false,
container.get<TransitionRevisionsFromPrimaryToSecondaryDatabaseForUser>(
TYPES.Revisions_TransitionRevisionsFromPrimaryToSecondaryDatabaseForUser,
),
@@ -528,15 +508,7 @@ export class ContainerConfigLoader {
} else {
container
.bind<DomainEventMessageHandlerInterface>(TYPES.Revisions_DomainEventMessageHandler)
.toConstantValue(
env.get('NEW_RELIC_ENABLED', true) === 'true'
? new SQSXRayEventMessageHandler(
ServiceIdentifier.NAMES.RevisionsWorker,
eventHandlers,
container.get(TYPES.Revisions_Logger),
)
: new SQSEventMessageHandler(eventHandlers, container.get(TYPES.Revisions_Logger)),
)
.toConstantValue(new SQSEventMessageHandler(eventHandlers, container.get(TYPES.Revisions_Logger)))
container
.bind<DomainEventSubscriberFactoryInterface>(TYPES.Revisions_DomainEventSubscriberFactory)
@@ -1,5 +1,3 @@
import * as mysqlDriver from 'mysql'
import { captureMySQL } from 'aws-xray-sdk'
import { DataSource, EntityTarget, LoggerOptions, MongoRepository, ObjectLiteral, Repository } from 'typeorm'
import { MysqlConnectionOptions } from 'typeorm/driver/mysql/MysqlConnectionOptions'
@@ -119,15 +117,9 @@ export class AppDataSource {
restoreNodeTimeout: 5,
}
let driver = undefined
if (!isConfiguredForHomeServerOrSelfHosting) {
driver = captureMySQL(mysqlDriver)
}
const mySQLDataSourceOptions: MysqlConnectionOptions = {
...commonDataSourceOptions,
type: 'mysql',
driver,
charset: 'utf8mb4',
supportBigNumbers: true,
bigNumberStrings: false,
@@ -61,7 +61,7 @@ export class TransitionRevisionsFromPrimaryToSecondaryDatabaseForUser implements
this.logger.info(`[${dto.userUuid}] Revisions migrated`)
await this.allowForSecondaryDatabaseToCatchUp()
await this.allowForPrimaryDatabaseToCatchUp()
this.logger.info(`[${dto.userUuid}] Checking integrity between primary and secondary database`)
@@ -75,11 +75,16 @@ export class TransitionRevisionsFromPrimaryToSecondaryDatabaseForUser implements
return Result.fail(integrityCheckResult.getError())
}
const cleanupResult = await this.deleteRevisionsForUser(userUuid, this.primaryRevisionsRepository)
const cleanupResult = await this.deleteRevisionsForUser(
userUuid,
this.secondRevisionsRepository as RevisionRepositoryInterface,
)
if (cleanupResult.isFailed()) {
await this.updateTransitionStatus(userUuid, TransitionStatus.STATUSES.Failed, dto.timestamp)
this.logger.error(`[${dto.userUuid}] Failed to clean up primary database revisions: ${cleanupResult.getError()}`)
this.logger.error(
`[${dto.userUuid}] Failed to clean up secondary database revisions: ${cleanupResult.getError()}`,
)
}
const migrationTimeEnd = this.timer.getTimestampInMicroseconds()
@@ -104,7 +109,9 @@ export class TransitionRevisionsFromPrimaryToSecondaryDatabaseForUser implements
this.logger.info(`[${userUuid.value}] Migrating from page ${initialPage}`)
const totalRevisionsCountForUser = await this.primaryRevisionsRepository.countByUserUuid(userUuid)
const totalRevisionsCountForUser = await (
this.secondRevisionsRepository as RevisionRepositoryInterface
).countByUserUuid(userUuid)
const totalPages = Math.ceil(totalRevisionsCountForUser / this.pageSize)
for (let currentPage = initialPage; currentPage <= totalPages; currentPage++) {
const isPageInEvery10Percent = currentPage % Math.ceil(totalPages / 10) === 0
@@ -128,47 +135,49 @@ export class TransitionRevisionsFromPrimaryToSecondaryDatabaseForUser implements
limit: this.pageSize,
}
const revisions = await this.primaryRevisionsRepository.findByUserUuid(query)
const revisions = await (this.secondRevisionsRepository as RevisionRepositoryInterface).findByUserUuid(query)
for (const revision of revisions) {
try {
const revisionInSecondary = await (
this.secondRevisionsRepository as RevisionRepositoryInterface
).findOneByUuid(Uuid.create(revision.id.toString()).getValue(), revision.props.userUuid as Uuid, [])
const revisionInPrimary = await this.primaryRevisionsRepository.findOneByUuid(
Uuid.create(revision.id.toString()).getValue(),
revision.props.userUuid as Uuid,
[],
)
if (revisionInSecondary !== null) {
if (revisionInSecondary.isIdenticalTo(revision)) {
continue
}
if (revisionInSecondary.props.dates.updatedAt > revision.props.dates.updatedAt) {
if (revisionInPrimary !== null) {
if (revisionInPrimary.props.dates.updatedAt > revision.props.dates.updatedAt) {
this.logger.info(
`[${userUuid.value}] Revision ${revision.id.toString()} is older than revision in secondary database`,
`[${
userUuid.value
}] Revision ${revision.id.toString()} is older in secondary than revision in primary database`,
)
continue
}
if (revisionInPrimary.isIdenticalTo(revision)) {
continue
}
this.logger.info(
`[${
userUuid.value
}] Removing revision ${revision.id.toString()} in secondary database as it is not identical to revision in primary database`,
`[${userUuid.value}] Removing revision ${revision.id.toString()} in primary database: ${JSON.stringify(
revisionInPrimary,
)} as it is not identical to revision in secondary database: ${JSON.stringify(revision)}`,
)
await (this.secondRevisionsRepository as RevisionRepositoryInterface).removeOneByUuid(
Uuid.create(revisionInSecondary.id.toString()).getValue(),
revisionInSecondary.props.userUuid as Uuid,
await this.primaryRevisionsRepository.removeOneByUuid(
Uuid.create(revisionInPrimary.id.toString()).getValue(),
revisionInPrimary.props.userUuid as Uuid,
)
await this.allowForSecondaryDatabaseToCatchUp()
await this.allowForPrimaryDatabaseToCatchUp()
}
const didSave = await (this.secondRevisionsRepository as RevisionRepositoryInterface).insert(revision)
const didSave = await this.primaryRevisionsRepository.insert(revision)
if (!didSave) {
this.logger.error(`Failed to save revision ${revision.id.toString()} to secondary database`)
this.logger.error(`Failed to save revision ${revision.id.toString()} to primary database`)
}
} catch (error) {
this.logger.error(
`Errored when saving revision ${revision.id.toString()} to secondary database: ${
(error as Error).message
}`,
`Errored when saving revision ${revision.id.toString()} to primary database: ${(error as Error).message}`,
)
}
}
@@ -185,7 +194,7 @@ export class TransitionRevisionsFromPrimaryToSecondaryDatabaseForUser implements
revisionRepository: RevisionRepositoryInterface,
): Promise<Result<void>> {
try {
this.logger.info(`[${userUuid.value}] Deleting all revisions from primary database`)
this.logger.info(`[${userUuid.value}] Deleting all revisions from secondary database`)
await revisionRepository.removeByUserUuid(userUuid)
@@ -195,9 +204,9 @@ export class TransitionRevisionsFromPrimaryToSecondaryDatabaseForUser implements
}
}
private async allowForSecondaryDatabaseToCatchUp(): Promise<void> {
const twoSecondsInMilliseconds = 2_000
await this.timer.sleep(twoSecondsInMilliseconds)
private async allowForPrimaryDatabaseToCatchUp(): Promise<void> {
const delay = 1_000
await this.timer.sleep(delay)
}
private async checkIntegrityBetweenPrimaryAndSecondaryDatabase(userUuid: Uuid): Promise<Result<boolean>> {
@@ -208,12 +217,12 @@ export class TransitionRevisionsFromPrimaryToSecondaryDatabaseForUser implements
this.logger.info(`[${userUuid.value}] Checking integrity from page ${initialPage}`)
const totalRevisionsCountForUserInPrimary = await this.primaryRevisionsRepository.countByUserUuid(userUuid)
const totalRevisionsCountForUserInSecondary = await (
this.secondRevisionsRepository as RevisionRepositoryInterface
).countByUserUuid(userUuid)
const totalRevisionsCountForUserInPrimary = await this.primaryRevisionsRepository.countByUserUuid(userUuid)
if (totalRevisionsCountForUserInPrimary > totalRevisionsCountForUserInSecondary) {
if (totalRevisionsCountForUserInPrimary < totalRevisionsCountForUserInSecondary) {
return Result.fail(
`Total revisions count for user ${userUuid.value} in primary database (${totalRevisionsCountForUserInPrimary}) does not match total revisions count in secondary database (${totalRevisionsCountForUserInSecondary})`,
)
@@ -232,7 +241,7 @@ export class TransitionRevisionsFromPrimaryToSecondaryDatabaseForUser implements
limit: this.pageSize,
}
const revisions = await this.primaryRevisionsRepository.findByUserUuid(query)
const revisions = await (this.secondRevisionsRepository as RevisionRepositoryInterface).findByUserUuid(query)
for (const revision of revisions) {
const revisionUuidOrError = Uuid.create(revision.id.toString())
@@ -242,31 +251,29 @@ export class TransitionRevisionsFromPrimaryToSecondaryDatabaseForUser implements
}
const revisionUuid = revisionUuidOrError.getValue()
const revisionInSecondary = await (
this.secondRevisionsRepository as RevisionRepositoryInterface
).findOneByUuid(revisionUuid, userUuid, [])
if (!revisionInSecondary) {
return Result.fail(`Revision ${revision.id.toString()} not found in secondary database`)
const revisionInPrimary = await this.primaryRevisionsRepository.findOneByUuid(revisionUuid, userUuid, [])
if (!revisionInPrimary) {
return Result.fail(`Revision ${revision.id.toString()} not found in primary database`)
}
if (revision.isIdenticalTo(revisionInSecondary)) {
continue
}
if (revisionInSecondary.props.dates.updatedAt > revision.props.dates.updatedAt) {
if (revisionInPrimary.props.dates.updatedAt > revision.props.dates.updatedAt) {
this.logger.info(
`[${
userUuid.value
}] Integrity check of revision ${revision.id.toString()} - is older than revision in secondary database`,
}] Integrity check of revision ${revision.id.toString()} - is older in secondary than revision in primary database`,
)
continue
}
if (revision.isIdenticalTo(revisionInPrimary)) {
continue
}
return Result.fail(
`Revision ${revision.id.toString()} is not identical in primary and secondary database. Revision in primary database: ${JSON.stringify(
revision,
)}, revision in secondary database: ${JSON.stringify(revisionInSecondary)}`,
revisionInPrimary,
)}, revision in secondary database: ${JSON.stringify(revision)}`,
)
}
}
@@ -291,14 +298,16 @@ export class TransitionRevisionsFromPrimaryToSecondaryDatabaseForUser implements
}
private async isAlreadyMigrated(userUuid: Uuid): Promise<boolean> {
const totalRevisionsCountForUserInPrimary = await this.primaryRevisionsRepository.countByUserUuid(userUuid)
const totalRevisionsCountForUserInSecondary = await (
this.secondRevisionsRepository as RevisionRepositoryInterface
).countByUserUuid(userUuid)
if (totalRevisionsCountForUserInPrimary > 0) {
if (totalRevisionsCountForUserInSecondary > 0) {
this.logger.info(
`[${userUuid.value}] User has ${totalRevisionsCountForUserInPrimary} revisions in primary database.`,
`[${userUuid.value}] User has ${totalRevisionsCountForUserInSecondary} revisions in secondary database.`,
)
}
return totalRevisionsCountForUserInPrimary === 0
return totalRevisionsCountForUserInSecondary === 0
}
}
@@ -5,8 +5,11 @@ import { MongoDBRevision } from '../../../Infra/TypeORM/MongoDB/MongoDBRevision'
import { Revision } from '../../../Domain/Revision/Revision'
import { SharedVaultAssociation } from '../../../Domain/SharedVault/SharedVaultAssociation'
import { KeySystemAssociation } from '../../../Domain/KeySystem/KeySystemAssociation'
import { TimerInterface } from '@standardnotes/time'
export class MongoDBRevisionPersistenceMapper implements MapperInterface<Revision, MongoDBRevision> {
constructor(private timer: TimerInterface) {}
toDomain(projection: MongoDBRevision): Revision {
const contentTypeOrError = ContentType.create(projection.contentType)
if (contentTypeOrError.isFailed()) {
@@ -73,7 +76,7 @@ export class MongoDBRevisionPersistenceMapper implements MapperInterface<Revisio
authHash: projection.authHash,
content: projection.content,
contentType,
creationDate: projection.creationDate,
creationDate: new Date(this.timer.convertDateToFormattedString(projection.creationDate, 'YYYY-MM-DD')),
encItemKey: projection.encItemKey,
itemsKeyId: projection.itemsKeyId,
itemUuid,
@@ -99,7 +102,9 @@ export class MongoDBRevisionPersistenceMapper implements MapperInterface<Revisio
mongoDBRevision.contentType = domain.props.contentType.value
mongoDBRevision.createdAt = domain.props.dates.createdAt
mongoDBRevision.updatedAt = domain.props.dates.updatedAt
mongoDBRevision.creationDate = domain.props.creationDate
mongoDBRevision.creationDate = new Date(
this.timer.convertDateToFormattedString(domain.props.creationDate, 'YYYY-MM-DD'),
)
mongoDBRevision.encItemKey = domain.props.encItemKey
mongoDBRevision.itemUuid = domain.props.itemUuid.value
mongoDBRevision.itemsKeyId = domain.props.itemsKeyId
+6
View File
@@ -3,6 +3,12 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.22.2](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.22.1...@standardnotes/scheduler-server@1.22.2) (2023-10-09)
### Bug Fixes
* remove xray sdk in favor of opentelemetry ([b736dab](https://github.com/standardnotes/server/commit/b736dab3c1f76c9e03c4bc7bbf153dcb3309b7cb))
## [1.22.1](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.22.0...@standardnotes/scheduler-server@1.22.1) (2023-10-06)
### Bug Fixes
-9
View File
@@ -3,7 +3,6 @@ import 'reflect-metadata'
import { Logger } from 'winston'
import * as dayjs from 'dayjs'
import * as utc from 'dayjs/plugin/utc'
import * as AWSXRay from 'aws-xray-sdk'
import { TimerInterface } from '@standardnotes/time'
import { ContainerConfigLoader } from '../src/Bootstrap/Container'
@@ -22,14 +21,6 @@ void container.load().then((container) => {
const env: Env = new Env()
env.load()
const isConfiguredForAWSProduction =
env.get('MODE', true) !== 'home-server' && env.get('MODE', true) !== 'self-hosted'
if (isConfiguredForAWSProduction) {
AWSXRay.enableManualMode()
AWSXRay.config([AWSXRay.plugins.ECSPlugin])
}
const logger: Logger = container.get(TYPES.Logger)
const timer: TimerInterface = container.get(TYPES.Timer)
const now = timer.getTimestampInMicroseconds()
-9
View File
@@ -1,7 +1,6 @@
import 'reflect-metadata'
import { Logger } from 'winston'
import * as AWSXRay from 'aws-xray-sdk'
import { DomainEventSubscriberFactoryInterface } from '@standardnotes/domain-events'
import * as dayjs from 'dayjs'
import * as utc from 'dayjs/plugin/utc'
@@ -17,14 +16,6 @@ void container.load().then((container) => {
const env: Env = new Env()
env.load()
const isConfiguredForAWSProduction =
env.get('MODE', true) !== 'home-server' && env.get('MODE', true) !== 'self-hosted'
if (isConfiguredForAWSProduction) {
AWSXRay.enableManualMode()
AWSXRay.config([AWSXRay.plugins.ECSPlugin])
}
const logger: Logger = container.get(TYPES.Logger)
logger.info('Starting worker...')
+1 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/scheduler-server",
"version": "1.22.1",
"version": "1.22.2",
"engines": {
"node": ">=18.0.0 <21.0.0"
},
@@ -30,7 +30,6 @@
"@standardnotes/domain-events-infra": "workspace:*",
"@standardnotes/predicates": "workspace:*",
"@standardnotes/time": "workspace:*",
"aws-xray-sdk": "^3.5.2",
"dayjs": "^1.11.6",
"dotenv": "^16.0.1",
"inversify": "^6.0.1",
+3 -14
View File
@@ -17,7 +17,6 @@ import {
SNSDomainEventPublisher,
SQSDomainEventSubscriberFactory,
SQSEventMessageHandler,
SQSXRayEventMessageHandler,
} from '@standardnotes/domain-events-infra'
import { Timer, TimerInterface } from '@standardnotes/time'
import { PredicateRepositoryInterface } from '../Domain/Predicate/PredicateRepositoryInterface'
@@ -35,8 +34,6 @@ import { VerifyPredicates } from '../Domain/UseCase/VerifyPredicates/VerifyPredi
import { UserRegisteredEventHandler } from '../Domain/Handler/UserRegisteredEventHandler'
import { SubscriptionCancelledEventHandler } from '../Domain/Handler/SubscriptionCancelledEventHandler'
import { ExitDiscountAppliedEventHandler } from '../Domain/Handler/ExitDiscountAppliedEventHandler'
import { ServiceIdentifier } from '@standardnotes/domain-core'
import { captureAWSv3Client } from 'aws-xray-sdk'
export class ContainerConfigLoader {
async load(): Promise<Container> {
@@ -88,7 +85,7 @@ export class ContainerConfigLoader {
secretAccessKey: env.get('SNS_SECRET_ACCESS_KEY', true),
}
}
container.bind<SNSClient>(TYPES.SNS).toConstantValue(captureAWSv3Client(new SNSClient(snsConfig)))
container.bind<SNSClient>(TYPES.SNS).toConstantValue(new SNSClient(snsConfig))
}
if (env.get('SQS_QUEUE_URL', true)) {
@@ -104,7 +101,7 @@ export class ContainerConfigLoader {
secretAccessKey: env.get('SQS_SECRET_ACCESS_KEY', true),
}
}
container.bind<SQSClient>(TYPES.SQS).toConstantValue(captureAWSv3Client(new SQSClient(sqsConfig)))
container.bind<SQSClient>(TYPES.SQS).toConstantValue(new SQSClient(sqsConfig))
}
// env vars
@@ -156,15 +153,7 @@ export class ContainerConfigLoader {
container
.bind<DomainEventMessageHandlerInterface>(TYPES.DomainEventMessageHandler)
.toConstantValue(
env.get('NEW_RELIC_ENABLED', true) === 'true'
? new SQSXRayEventMessageHandler(
ServiceIdentifier.NAMES.SchedulerWorker,
eventHandlers,
container.get(TYPES.Logger),
)
: new SQSEventMessageHandler(eventHandlers, container.get(TYPES.Logger)),
)
.toConstantValue(new SQSEventMessageHandler(eventHandlers, container.get(TYPES.Logger)))
container
.bind<DomainEventSubscriberFactoryInterface>(TYPES.DomainEventSubscriberFactory)
.toConstantValue(
+42
View File
@@ -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.112.4](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.112.3...@standardnotes/syncing-server@1.112.4) (2023-10-09)
### Bug Fixes
* remove xray sdk in favor of opentelemetry ([b736dab](https://github.com/standardnotes/syncing-server-js/commit/b736dab3c1f76c9e03c4bc7bbf153dcb3309b7cb))
## [1.112.3](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.112.2...@standardnotes/syncing-server@1.112.3) (2023-10-09)
### Bug Fixes
* logs in transition ([29e8de3](https://github.com/standardnotes/syncing-server-js/commit/29e8de32383e911bbb431d3fd0da68faefa32d3d))
## [1.112.2](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.112.1...@standardnotes/syncing-server@1.112.2) (2023-10-06)
### Bug Fixes
* **syncing-server:** calling auth server for user key params ([51ca822](https://github.com/standardnotes/syncing-server-js/commit/51ca8229b8d5ebb3b4573a2a9da12dd8f15bf2ec))
* **syncing-server:** error log on email backup requested ([a6a19a3](https://github.com/standardnotes/syncing-server-js/commit/a6a19a391e0495a0f362b98d0f3a34e4f6539863))
## [1.112.1](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.112.0...@standardnotes/syncing-server@1.112.1) (2023-10-06)
### Bug Fixes
* **syncing-server:** increase axios timeout on calling auth ([eafb064](https://github.com/standardnotes/syncing-server-js/commit/eafb064d7992dc8aa31f090e4265498c415c5795))
* **syncing-server:** logs on request backup handler ([ba05068](https://github.com/standardnotes/syncing-server-js/commit/ba050681f772c2f566462be57f6b0731141d85b0))
# [1.112.0](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.111.5...@standardnotes/syncing-server@1.112.0) (2023-10-06)
### Bug Fixes
* enable TransitionRequestedEventHandler ([d8f1c66](https://github.com/standardnotes/syncing-server-js/commit/d8f1c66fd5e59285ccaa1be36da2ee9796b81ccb))
### Features
* switch transition direction ([27bea44](https://github.com/standardnotes/syncing-server-js/commit/27bea444cce4964feda04bad64e5f12a07415e0c))
## [1.111.5](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.111.4...@standardnotes/syncing-server@1.111.5) (2023-10-06)
### Bug Fixes
* **syncing-server:** add more logs on successfull email backups requested ([8c57f50](https://github.com/standardnotes/syncing-server-js/commit/8c57f505be86f3a7af0ab446a409bac276b2242b))
## [1.111.4](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.111.3...@standardnotes/syncing-server@1.111.4) (2023-10-06)
### Bug Fixes
-17
View File
@@ -11,33 +11,20 @@ import helmet from 'helmet'
import * as cors from 'cors'
import { urlencoded, json, Request, Response, NextFunction } from 'express'
import * as winston from 'winston'
import * as AWSXRay from 'aws-xray-sdk'
import { InversifyExpressServer } from 'inversify-express-utils'
import TYPES from '../src/Bootstrap/Types'
import { Env } from '../src/Bootstrap/Env'
import { ContainerConfigLoader } from '../src/Bootstrap/Container'
import { ServiceIdentifier } from '@standardnotes/domain-core'
const container = new ContainerConfigLoader()
void container.load().then((container) => {
const env: Env = new Env()
env.load()
const isConfiguredForAWSProduction =
env.get('MODE', true) !== 'home-server' && env.get('MODE', true) !== 'self-hosted'
if (isConfiguredForAWSProduction) {
AWSXRay.config([AWSXRay.plugins.ECSPlugin])
}
const server = new InversifyExpressServer(container)
server.setConfig((app) => {
if (isConfiguredForAWSProduction) {
app.use(AWSXRay.express.openSegment(ServiceIdentifier.NAMES.SyncingServer))
}
app.use((_request: Request, response: Response, next: NextFunction) => {
response.setHeader('X-SSJS-Version', container.get(TYPES.Sync_VERSION))
next()
@@ -86,10 +73,6 @@ void container.load().then((container) => {
const serverInstance = server.build()
if (isConfiguredForAWSProduction) {
serverInstance.use(AWSXRay.express.closeSegment())
}
serverInstance.listen(env.get('PORT'))
logger.info(`Server started on port ${process.env.PORT}`)
-9
View File
@@ -1,7 +1,6 @@
import 'reflect-metadata'
import { Logger } from 'winston'
import * as AWSXRay from 'aws-xray-sdk'
import TYPES from '../src/Bootstrap/Types'
import { Env } from '../src/Bootstrap/Env'
@@ -13,14 +12,6 @@ void container.load().then((container) => {
const env: Env = new Env()
env.load()
const isConfiguredForAWSProduction =
env.get('MODE', true) !== 'home-server' && env.get('MODE', true) !== 'self-hosted'
if (isConfiguredForAWSProduction) {
AWSXRay.enableManualMode()
AWSXRay.config([AWSXRay.plugins.ECSPlugin])
}
const logger: Logger = container.get(TYPES.Sync_Logger)
logger.info('Starting worker...')
+1 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/syncing-server",
"version": "1.111.4",
"version": "1.112.4",
"engines": {
"node": ">=18.0.0 <21.0.0"
},
@@ -40,7 +40,6 @@
"@standardnotes/settings": "workspace:*",
"@standardnotes/sncrypto-node": "workspace:*",
"@standardnotes/time": "workspace:*",
"aws-xray-sdk": "^3.5.2",
"axios": "^1.1.3",
"cors": "2.8.5",
"dotenv": "^16.0.1",
@@ -5,7 +5,6 @@ import { Container, interfaces } from 'inversify'
import { Env } from './Env'
import TYPES from './Types'
import { AppDataSource } from './DataSource'
import { captureAWSv3Client } from 'aws-xray-sdk'
import { SNSClient, SNSClientConfig } from '@aws-sdk/client-sns'
import { ItemRepositoryInterface } from '../Domain/Item/ItemRepositoryInterface'
import { SQLLegacyItemRepository } from '../Infra/TypeORM/SQLLegacyItemRepository'
@@ -17,7 +16,6 @@ import {
SNSDomainEventPublisher,
SQSDomainEventSubscriberFactory,
SQSEventMessageHandler,
SQSXRayEventMessageHandler,
} from '@standardnotes/domain-events-infra'
import { DomainEventFactoryInterface } from '../Domain/Event/DomainEventFactoryInterface'
import { DomainEventFactory } from '../Domain/Event/DomainEventFactory'
@@ -64,7 +62,6 @@ import {
ControllerContainer,
ControllerContainerInterface,
MapperInterface,
ServiceIdentifier,
SharedVaultUser,
} from '@standardnotes/domain-core'
import { BaseItemsController } from '../Infra/InversifyExpressUtils/Base/BaseItemsController'
@@ -233,7 +230,6 @@ export class ContainerConfigLoader {
const isConfiguredForHomeServer = env.get('MODE', true) === 'home-server'
const isConfiguredForSelfHosting = env.get('MODE', true) === 'self-hosted'
const isConfiguredForAWSProduction = !isConfiguredForHomeServer && !isConfiguredForSelfHosting
const isConfiguredForHomeServerOrSelfHosting = isConfiguredForHomeServer || isConfiguredForSelfHosting
const isSecondaryDatabaseEnabled = env.get('SECONDARY_DB_ENABLED', true) === 'true'
const isConfiguredForInMemoryCache = env.get('CACHE_TYPE', true) === 'memory'
@@ -285,10 +281,6 @@ export class ContainerConfigLoader {
}
}
if (isConfiguredForAWSProduction) {
captureAWSv3Client(new SNSClient(snsConfig))
}
return new SNSClient(snsConfig)
})
@@ -317,10 +309,6 @@ export class ContainerConfigLoader {
}
}
if (isConfiguredForAWSProduction) {
captureAWSv3Client(new SQSClient(sqsConfig))
}
return new SQSClient(sqsConfig)
})
@@ -333,10 +321,6 @@ export class ContainerConfigLoader {
apiVersion: 'latest',
region: env.get('S3_AWS_REGION', true),
})
if (isConfiguredForAWSProduction) {
captureAWSv3Client(s3Client)
}
}
return s3Client
@@ -1066,7 +1050,7 @@ export class ContainerConfigLoader {
.bind<TransitionRequestedEventHandler>(TYPES.Sync_TransitionRequestedEventHandler)
.toConstantValue(
new TransitionRequestedEventHandler(
true,
false,
container.get<TransitionItemsFromPrimaryToSecondaryDatabaseForUser>(
TYPES.Sync_TransitionItemsFromPrimaryToSecondaryDatabaseForUser,
),
@@ -1171,15 +1155,7 @@ export class ContainerConfigLoader {
} else {
container
.bind<DomainEventMessageHandlerInterface>(TYPES.Sync_DomainEventMessageHandler)
.toConstantValue(
env.get('NEW_RELIC_ENABLED', true) === 'true'
? new SQSXRayEventMessageHandler(
ServiceIdentifier.NAMES.SyncingServerWorker,
eventHandlers,
container.get(TYPES.Sync_Logger),
)
: new SQSEventMessageHandler(eventHandlers, container.get(TYPES.Sync_Logger)),
)
.toConstantValue(new SQSEventMessageHandler(eventHandlers, container.get(TYPES.Sync_Logger)))
}
container
@@ -1,5 +1,5 @@
import { KeyParamsData } from '@standardnotes/responses'
export interface AuthHttpServiceInterface {
getUserKeyParams(dto: { email?: string; uuid?: string; authenticated: boolean }): Promise<KeyParamsData>
getUserKeyParams(userUuid: string): Promise<KeyParamsData>
}
@@ -1,132 +0,0 @@
import 'reflect-metadata'
import {
DomainEventPublisherInterface,
DuplicateItemSyncedEvent,
RevisionsCopyRequestedEvent,
} from '@standardnotes/domain-events'
import { Logger } from 'winston'
import { Item } from '../Item/Item'
import { ItemRepositoryInterface } from '../Item/ItemRepositoryInterface'
import { DuplicateItemSyncedEventHandler } from './DuplicateItemSyncedEventHandler'
import { DomainEventFactoryInterface } from '../Event/DomainEventFactoryInterface'
import { Uuid, ContentType, Dates, Timestamps, UniqueEntityId } from '@standardnotes/domain-core'
import { ItemRepositoryResolverInterface } from '../Item/ItemRepositoryResolverInterface'
describe('DuplicateItemSyncedEventHandler', () => {
let itemRepositoryResolver: ItemRepositoryResolverInterface
let itemRepository: ItemRepositoryInterface
let logger: Logger
let duplicateItem: Item
let originalItem: Item
let event: DuplicateItemSyncedEvent
let domainEventFactory: DomainEventFactoryInterface
let domainEventPublisher: DomainEventPublisherInterface
const createHandler = () =>
new DuplicateItemSyncedEventHandler(itemRepositoryResolver, domainEventFactory, domainEventPublisher, logger)
beforeEach(() => {
originalItem = Item.create(
{
userUuid: Uuid.create('00000000-0000-0000-0000-000000000000').getValue(),
updatedWithSession: null,
content: 'foobar',
contentType: ContentType.create(ContentType.TYPES.Note).getValue(),
encItemKey: null,
authHash: null,
itemsKeyId: null,
duplicateOf: null,
deleted: false,
dates: Dates.create(new Date(1616164633241311), new Date(1616164633241311)).getValue(),
timestamps: Timestamps.create(1616164633241311, 1616164633241311).getValue(),
},
new UniqueEntityId('00000000-0000-0000-0000-000000000000'),
).getValue()
duplicateItem = Item.create(
{
userUuid: Uuid.create('00000000-0000-0000-0000-000000000000').getValue(),
updatedWithSession: null,
content: 'foobar',
contentType: ContentType.create(ContentType.TYPES.Note).getValue(),
encItemKey: null,
authHash: null,
itemsKeyId: null,
duplicateOf: Uuid.create('00000000-0000-0000-0000-000000000000').getValue(),
deleted: false,
dates: Dates.create(new Date(1616164633241311), new Date(1616164633241311)).getValue(),
timestamps: Timestamps.create(1616164633241311, 1616164633241311).getValue(),
},
new UniqueEntityId('00000000-0000-0000-0000-000000000001'),
).getValue()
itemRepository = {} as jest.Mocked<ItemRepositoryInterface>
itemRepository.findByUuidAndUserUuid = jest
.fn()
.mockReturnValueOnce(duplicateItem)
.mockReturnValueOnce(originalItem)
itemRepositoryResolver = {} as jest.Mocked<ItemRepositoryResolverInterface>
itemRepositoryResolver.resolve = jest.fn().mockReturnValue(itemRepository)
logger = {} as jest.Mocked<Logger>
logger.warn = jest.fn()
logger.debug = jest.fn()
event = {} as jest.Mocked<DuplicateItemSyncedEvent>
event.createdAt = new Date(1)
event.payload = {
userUuid: '1-2-3',
itemUuid: '2-3-4',
roleNames: ['CORE_USER'],
}
domainEventFactory = {} as jest.Mocked<DomainEventFactoryInterface>
domainEventFactory.createRevisionsCopyRequestedEvent = jest
.fn()
.mockReturnValue({} as jest.Mocked<RevisionsCopyRequestedEvent>)
domainEventPublisher = {} as jest.Mocked<DomainEventPublisherInterface>
domainEventPublisher.publish = jest.fn()
})
it('should copy revisions from original item to the duplicate item', async () => {
await createHandler().handle(event)
expect(domainEventPublisher.publish).toHaveBeenCalled()
})
it('should do nothing if role names are not valid', async () => {
event.payload.roleNames = ['INVALID_ROLE_NAME']
await createHandler().handle(event)
expect(domainEventPublisher.publish).not.toHaveBeenCalled()
})
it('should not copy revisions if original item does not exist', async () => {
itemRepository.findByUuidAndUserUuid = jest.fn().mockReturnValueOnce(duplicateItem).mockReturnValueOnce(null)
itemRepositoryResolver.resolve = jest.fn().mockReturnValue(itemRepository)
await createHandler().handle(event)
expect(domainEventPublisher.publish).not.toHaveBeenCalled()
})
it('should not copy revisions if duplicate item does not exist', async () => {
itemRepository.findByUuidAndUserUuid = jest.fn().mockReturnValueOnce(null).mockReturnValueOnce(originalItem)
itemRepositoryResolver.resolve = jest.fn().mockReturnValue(itemRepository)
await createHandler().handle(event)
expect(domainEventPublisher.publish).not.toHaveBeenCalled()
})
it('should not copy revisions if duplicate item is not pointing to duplicate anything', async () => {
duplicateItem.props.duplicateOf = null
await createHandler().handle(event)
expect(domainEventPublisher.publish).not.toHaveBeenCalled()
})
})
@@ -1,137 +0,0 @@
import 'reflect-metadata'
import {
DomainEventPublisherInterface,
EmailBackupRequestedEvent,
EmailRequestedEvent,
} from '@standardnotes/domain-events'
import { Logger } from 'winston'
import { AuthHttpServiceInterface } from '../Auth/AuthHttpServiceInterface'
import { DomainEventFactoryInterface } from '../Event/DomainEventFactoryInterface'
import { Item } from '../Item/Item'
import { ItemBackupServiceInterface } from '../Item/ItemBackupServiceInterface'
import { ItemRepositoryInterface } from '../Item/ItemRepositoryInterface'
import { EmailBackupRequestedEventHandler } from './EmailBackupRequestedEventHandler'
import { ItemTransferCalculatorInterface } from '../Item/ItemTransferCalculatorInterface'
import { ItemContentSizeDescriptor } from '../Item/ItemContentSizeDescriptor'
describe('EmailBackupRequestedEventHandler', () => {
let primaryItemRepository: ItemRepositoryInterface
let secondaryItemRepository: ItemRepositoryInterface | null
let authHttpService: AuthHttpServiceInterface
let itemBackupService: ItemBackupServiceInterface
let domainEventPublisher: DomainEventPublisherInterface
let domainEventFactory: DomainEventFactoryInterface
const emailAttachmentMaxByteSize = 100
let itemTransferCalculator: ItemTransferCalculatorInterface
let item: Item
let event: EmailBackupRequestedEvent
let logger: Logger
const createHandler = () =>
new EmailBackupRequestedEventHandler(
primaryItemRepository,
secondaryItemRepository,
authHttpService,
itemBackupService,
domainEventPublisher,
domainEventFactory,
emailAttachmentMaxByteSize,
itemTransferCalculator,
's3-backup-bucket-name',
logger,
)
beforeEach(() => {
item = {} as jest.Mocked<Item>
primaryItemRepository = {} as jest.Mocked<ItemRepositoryInterface>
primaryItemRepository.findAll = jest.fn().mockReturnValue([item])
primaryItemRepository.findContentSizeForComputingTransferLimit = jest
.fn()
.mockResolvedValue([ItemContentSizeDescriptor.create('00000000-0000-0000-0000-000000000000', 20).getValue()])
authHttpService = {} as jest.Mocked<AuthHttpServiceInterface>
authHttpService.getUserKeyParams = jest.fn().mockReturnValue({ identifier: 'test@test.com' })
event = {} as jest.Mocked<EmailBackupRequestedEvent>
event.createdAt = new Date(1)
event.payload = {
userUuid: '1-2-3',
userHasEmailsMuted: false,
muteEmailsSettingUuid: '1-2-3',
}
itemBackupService = {} as jest.Mocked<ItemBackupServiceInterface>
itemBackupService.backup = jest.fn().mockReturnValue(['backup-file-name'])
domainEventPublisher = {} as jest.Mocked<DomainEventPublisherInterface>
domainEventPublisher.publish = jest.fn()
domainEventFactory = {} as jest.Mocked<DomainEventFactoryInterface>
domainEventFactory.createEmailRequestedEvent = jest.fn().mockReturnValue({} as jest.Mocked<EmailRequestedEvent>)
itemTransferCalculator = {} as jest.Mocked<ItemTransferCalculatorInterface>
itemTransferCalculator.computeItemUuidBundlesToFetch = jest.fn().mockReturnValue([['1-2-3']])
logger = {} as jest.Mocked<Logger>
logger.debug = jest.fn()
logger.warn = jest.fn()
logger.error = jest.fn()
})
it('should inform that backup attachment for email was created', async () => {
await createHandler().handle(event)
expect(domainEventPublisher.publish).toHaveBeenCalledTimes(1)
expect(domainEventFactory.createEmailRequestedEvent).toHaveBeenCalled()
})
it('should inform that backup attachment for email was created in the secondary repository', async () => {
secondaryItemRepository = {} as jest.Mocked<ItemRepositoryInterface>
secondaryItemRepository.findAll = jest.fn().mockReturnValue([item])
secondaryItemRepository.findContentSizeForComputingTransferLimit = jest
.fn()
.mockResolvedValue([ItemContentSizeDescriptor.create('00000000-0000-0000-0000-000000000000', 20).getValue()])
await createHandler().handle(event)
expect(domainEventPublisher.publish).toHaveBeenCalledTimes(2)
expect(domainEventFactory.createEmailRequestedEvent).toHaveBeenCalledTimes(2)
secondaryItemRepository = null
})
it('should inform that multipart backup attachment for email was created', async () => {
itemBackupService.backup = jest
.fn()
.mockReturnValueOnce(['backup-file-name-1'])
.mockReturnValueOnce(['backup-file-name-2', 'backup-file-name-3'])
itemTransferCalculator.computeItemUuidBundlesToFetch = jest.fn().mockReturnValue([['1-2-3'], ['2-3-4']])
await createHandler().handle(event)
expect(domainEventPublisher.publish).toHaveBeenCalledTimes(3)
expect(domainEventFactory.createEmailRequestedEvent).toHaveBeenCalledTimes(3)
})
it('should not inform that backup attachment for email was created if user key params cannot be obtained', async () => {
authHttpService.getUserKeyParams = jest.fn().mockImplementation(() => {
throw new Error('Oops!')
})
await createHandler().handle(event)
expect(domainEventPublisher.publish).not.toHaveBeenCalled()
expect(domainEventFactory.createEmailRequestedEvent).not.toHaveBeenCalled()
})
it('should not inform that backup attachment for email was created if backup file name is empty', async () => {
itemBackupService.backup = jest.fn().mockReturnValue('')
await createHandler().handle(event)
expect(domainEventPublisher.publish).not.toHaveBeenCalled()
expect(domainEventFactory.createEmailRequestedEvent).not.toHaveBeenCalled()
})
})
@@ -42,12 +42,13 @@ export class EmailBackupRequestedEventHandler implements DomainEventHandlerInter
): Promise<void> {
let authParams: KeyParamsData
try {
authParams = await this.authHttpService.getUserKeyParams({
uuid: event.payload.userUuid,
authenticated: false,
})
authParams = await this.authHttpService.getUserKeyParams(event.payload.userUuid)
} catch (error) {
this.logger.error(`Could not get user key params from auth service: ${JSON.stringify(error)}`)
this.logger.error(
`Could not get user key params from auth service for user ${event.payload.userUuid}: ${
(error as Error).message
}`,
)
return
}
@@ -104,5 +105,7 @@ export class EmailBackupRequestedEventHandler implements DomainEventHandlerInter
}),
)
}
this.logger.info(`Email with backup requested for user ${event.payload.userUuid}`)
}
}
@@ -60,7 +60,7 @@ export class TransitionItemsFromPrimaryToSecondaryDatabaseForUser implements Use
this.logger.info(`[${dto.userUuid}] Items migrated`)
await this.allowForSecondaryDatabaseToCatchUp()
await this.allowForPrimaryDatabaseToCatchUp()
this.logger.info(`[${dto.userUuid}] Checking integrity between primary and secondary database`)
@@ -74,11 +74,14 @@ export class TransitionItemsFromPrimaryToSecondaryDatabaseForUser implements Use
return Result.fail(integrityCheckResult.getError())
}
const cleanupResult = await this.deleteItemsForUser(userUuid, this.primaryItemRepository)
const cleanupResult = await this.deleteItemsForUser(
userUuid,
this.secondaryItemRepository as ItemRepositoryInterface,
)
if (cleanupResult.isFailed()) {
await this.updateTransitionStatus(userUuid, TransitionStatus.STATUSES.Failed, dto.timestamp)
this.logger.error(`[${dto.userUuid}] Failed to clean up primary database items: ${cleanupResult.getError()}`)
this.logger.error(`[${dto.userUuid}] Failed to clean up secondary database items: ${cleanupResult.getError()}`)
}
const migrationTimeEnd = this.timer.getTimestampInMicroseconds()
@@ -95,9 +98,9 @@ export class TransitionItemsFromPrimaryToSecondaryDatabaseForUser implements Use
return Result.ok()
}
private async allowForSecondaryDatabaseToCatchUp(): Promise<void> {
const twoSecondsInMilliseconds = 2_000
await this.timer.sleep(twoSecondsInMilliseconds)
private async allowForPrimaryDatabaseToCatchUp(): Promise<void> {
const delay = 1_000
await this.timer.sleep(delay)
}
private async migrateItemsForUser(userUuid: Uuid, timestamp: number): Promise<Result<void>> {
@@ -108,7 +111,9 @@ export class TransitionItemsFromPrimaryToSecondaryDatabaseForUser implements Use
this.logger.info(`[${userUuid.value}] Migrating from page ${initialPage}`)
const totalItemsCountForUser = await this.primaryItemRepository.countAll({ userUuid: userUuid.value })
const totalItemsCountForUser = await (this.secondaryItemRepository as ItemRepositoryInterface).countAll({
userUuid: userUuid.value,
})
const totalPages = Math.ceil(totalItemsCountForUser / this.pageSize)
for (let currentPage = initialPage; currentPage <= totalPages; currentPage++) {
const isPageInEvery10Percent = currentPage % Math.ceil(totalPages / 10) === 0
@@ -132,37 +137,37 @@ export class TransitionItemsFromPrimaryToSecondaryDatabaseForUser implements Use
sortOrder: 'ASC',
}
const items = await this.primaryItemRepository.findAll(query)
const items = await (this.secondaryItemRepository as ItemRepositoryInterface).findAll(query)
for (const item of items) {
try {
const itemInSecondary = await (this.secondaryItemRepository as ItemRepositoryInterface).findByUuid(
item.uuid,
)
const itemInPrimary = await this.primaryItemRepository.findByUuid(item.uuid)
if (itemInPrimary !== null) {
if (itemInPrimary.props.timestamps.updatedAt > item.props.timestamps.updatedAt) {
this.logger.info(
`[${userUuid.value}] Item ${item.uuid.value} is older in secondary than item in primary database`,
)
if (itemInSecondary !== null) {
if (itemInSecondary.isIdenticalTo(item)) {
continue
}
if (itemInSecondary.props.timestamps.updatedAt > item.props.timestamps.updatedAt) {
this.logger.info(`[${userUuid.value}] Item ${item.uuid.value} is older than item in secondary database`)
if (itemInPrimary.isIdenticalTo(item)) {
continue
}
this.logger.info(
`[${userUuid.value}] Removing item ${item.uuid.value} in secondary database as it is not identical to item in primary database`,
`[${userUuid.value}] Removing item ${item.uuid.value} in primary database as it is not identical to item in primary database`,
)
await (this.secondaryItemRepository as ItemRepositoryInterface).removeByUuid(item.uuid)
await this.primaryItemRepository.removeByUuid(item.uuid)
await this.allowForSecondaryDatabaseToCatchUp()
await this.allowForPrimaryDatabaseToCatchUp()
}
await (this.secondaryItemRepository as ItemRepositoryInterface).save(item)
await this.primaryItemRepository.save(item)
} catch (error) {
this.logger.error(
`Errored when saving item ${item.uuid.value} to secondary database: ${(error as Error).message}`,
`Errored when saving item ${item.uuid.value} to primary database: ${(error as Error).message}`,
)
}
}
@@ -194,14 +199,16 @@ export class TransitionItemsFromPrimaryToSecondaryDatabaseForUser implements Use
this.logger.info(`[${userUuid.value}] Checking integrity from page ${initialPage}`)
const totalItemsCountForUserInPrimary = await this.primaryItemRepository.countAll({ userUuid: userUuid.value })
const totalItemsCountForUserInSecondary = await (
this.secondaryItemRepository as ItemRepositoryInterface
).countAll({
userUuid: userUuid.value,
})
const totalItemsCountForUserInPrimary = await this.primaryItemRepository.countAll({
userUuid: userUuid.value,
})
if (totalItemsCountForUserInPrimary > totalItemsCountForUserInSecondary) {
if (totalItemsCountForUserInPrimary < totalItemsCountForUserInSecondary) {
return Result.fail(
`Total items count for user ${userUuid.value} in primary database (${totalItemsCountForUserInPrimary}) does not match total items count in secondary database (${totalItemsCountForUserInSecondary})`,
)
@@ -222,32 +229,32 @@ export class TransitionItemsFromPrimaryToSecondaryDatabaseForUser implements Use
sortOrder: 'ASC',
}
const items = await this.primaryItemRepository.findAll(query)
const items = await (this.secondaryItemRepository as ItemRepositoryInterface).findAll(query)
for (const item of items) {
const itemInSecondary = await (this.secondaryItemRepository as ItemRepositoryInterface).findByUuid(item.uuid)
if (!itemInSecondary) {
return Result.fail(`Item ${item.uuid.value} not found in secondary database`)
const itemInPrimary = await this.primaryItemRepository.findByUuid(item.uuid)
if (!itemInPrimary) {
return Result.fail(`Item ${item.uuid.value} not found in primary database`)
}
if (item.isIdenticalTo(itemInSecondary)) {
if (itemInPrimary.props.timestamps.updatedAt > item.props.timestamps.updatedAt) {
this.logger.info(
`[${userUuid.value}] Integrity check of Item ${item.uuid.value} - is older in secondary than item in primary database`,
)
continue
}
if (itemInSecondary.props.timestamps.updatedAt > item.props.timestamps.updatedAt) {
this.logger.info(
`[${userUuid.value}] Integrity check of Item ${item.uuid.value} - is older than item in secondary database`,
)
if (item.isIdenticalTo(itemInPrimary)) {
continue
}
return Result.fail(
`Item ${
item.uuid.value
} is not identical in primary and secondary database. Item in primary database: ${JSON.stringify(
} is not identical in primary and secondary database. Item in secondary database: ${JSON.stringify(
item,
)}, item in secondary database: ${JSON.stringify(itemInSecondary)}`,
)}, item in primary database: ${JSON.stringify(itemInPrimary)}`,
)
}
}
@@ -270,14 +277,14 @@ export class TransitionItemsFromPrimaryToSecondaryDatabaseForUser implements Use
}
private async isAlreadyMigrated(userUuid: Uuid): Promise<boolean> {
const totalItemsCountForUserInPrimary = await this.primaryItemRepository.countAll({
const totalItemsCountForUserInSecondary = await (this.secondaryItemRepository as ItemRepositoryInterface).countAll({
userUuid: userUuid.value,
})
if (totalItemsCountForUserInPrimary > 0) {
this.logger.info(`[${userUuid.value}] User has ${totalItemsCountForUserInPrimary} items in primary database.`)
if (totalItemsCountForUserInSecondary > 0) {
this.logger.info(`[${userUuid.value}] User has ${totalItemsCountForUserInSecondary} items in secondary database.`)
}
return totalItemsCountForUserInPrimary === 0
return totalItemsCountForUserInSecondary === 0
}
}
@@ -9,14 +9,14 @@ export class AuthHttpService implements AuthHttpServiceInterface {
private authServerUrl: string,
) {}
async getUserKeyParams(dto: { email?: string; uuid?: string; authenticated: boolean }): Promise<KeyParamsData> {
async getUserKeyParams(userUuid: string): Promise<KeyParamsData> {
const keyParamsResponse = await this.httpClient.request({
method: 'GET',
timeout: 10000,
headers: {
Accept: 'application/json',
},
url: `${this.authServerUrl}/users/params`,
params: dto,
url: `${this.authServerUrl}/users/params?uuid=${userUuid}`,
validateStatus:
/* istanbul ignore next */
(status: number) => status >= 200 && status < 500,
+6
View File
@@ -3,6 +3,12 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.12.1](https://github.com/standardnotes/server/compare/@standardnotes/websockets-server@1.12.0...@standardnotes/websockets-server@1.12.1) (2023-10-09)
### Bug Fixes
* remove xray sdk in favor of opentelemetry ([b736dab](https://github.com/standardnotes/server/commit/b736dab3c1f76c9e03c4bc7bbf153dcb3309b7cb))
# [1.12.0](https://github.com/standardnotes/server/compare/@standardnotes/websockets-server@1.11.10...@standardnotes/websockets-server@1.12.0) (2023-10-06)
### Features
-8
View File
@@ -4,7 +4,6 @@ import '../src/Infra/InversifyExpressUtils/AnnotatedHealthCheckController'
import '../src/Infra/InversifyExpressUtils/AnnotatedWebSocketsController'
import * as cors from 'cors'
import * as AWSXRay from 'aws-xray-sdk'
import { urlencoded, json, Request, Response, NextFunction } from 'express'
import * as winston from 'winston'
@@ -12,20 +11,15 @@ 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 { ServiceIdentifier } from '@standardnotes/domain-core'
const container = new ContainerConfigLoader()
void container.load().then((container) => {
const env: Env = new Env()
env.load()
AWSXRay.config([AWSXRay.plugins.ECSPlugin])
const server = new InversifyExpressServer(container)
server.setConfig((app) => {
app.use(AWSXRay.express.openSegment(ServiceIdentifier.NAMES.Websockets))
app.use((_request: Request, response: Response, next: NextFunction) => {
response.setHeader('X-Websockets-Version', container.get(TYPES.VERSION))
next()
@@ -52,8 +46,6 @@ void container.load().then((container) => {
const serverInstance = server.build()
serverInstance.use(AWSXRay.express.closeSegment())
serverInstance.listen(env.get('PORT'))
logger.info(`Server started on port ${process.env.PORT}`)

Some files were not shown because too many files have changed in this diff Show More