Compare commits

...

24 Commits

Author SHA1 Message Date
standardci
4e602687d5 chore(release): publish new version
- @standardnotes/analytics@2.25.1
 - @standardnotes/api-gateway@1.66.0
 - @standardnotes/auth-server@1.125.1
 - @standardnotes/domain-core@1.23.1
 - @standardnotes/event-store@1.11.8
 - @standardnotes/files-server@1.19.10
 - @standardnotes/home-server@1.13.0
 - @standardnotes/revisions-server@1.25.1
 - @standardnotes/scheduler-server@1.20.10
 - @standardnotes/settings@1.21.15
 - @standardnotes/syncing-server@1.67.0
 - @standardnotes/websockets-server@1.10.3
2023-07-19 06:47:26 +00:00
Karol Sójko
d026152ac8 fix(syncing-server): add missing messages and key system identifier sql representations (#663) 2023-07-19 08:31:23 +02:00
Karol Sójko
3f21a358d2 feat(syncing-server): add persistence of shared vaults with users and invites + controllers (#662)
* feat(syncing-server): associating existing items with key systems and shared vaults

* fix(syncing-server): find item query

* feat(syncing-server): add persistence of shared vaults with users and invites

* feat: shared vault controllers
2023-07-19 07:28:03 +02:00
standardci
dc55e47c98 chore(release): publish new version
- @standardnotes/home-server@1.12.6
 - @standardnotes/syncing-server@1.66.0
2023-07-18 11:39:37 +00:00
Karol Sójko
3b804e2321 feat(syncing-server): associating existing items with key systems and shared vaults (#661)
* feat(syncing-server): associating existing items with key systems and shared vaults

* fix(syncing-server): find item query

* feat(syncing-server): add persistence of shared vaults with users and invites
2023-07-18 13:21:30 +02:00
standardci
b32f851a90 chore(release): publish new version
- @standardnotes/home-server@1.12.5
 - @standardnotes/syncing-server@1.65.0
2023-07-18 09:55:28 +00:00
Karol Sójko
479d20e76f feat(syncing-server): persisting shared vault and key system associations (#660) 2023-07-18 11:39:02 +02:00
standardci
fae4553fc8 chore(release): publish new version
- @standardnotes/analytics@2.25.0
 - @standardnotes/api-gateway@1.65.7
 - @standardnotes/auth-server@1.125.0
 - @standardnotes/domain-core@1.23.0
 - @standardnotes/event-store@1.11.7
 - @standardnotes/files-server@1.19.9
 - @standardnotes/home-server@1.12.4
 - @standardnotes/revisions-server@1.25.0
 - @standardnotes/scheduler-server@1.20.9
 - @standardnotes/settings@1.21.14
 - @standardnotes/syncing-server@1.64.0
 - @standardnotes/websockets-server@1.10.2
2023-07-17 11:46:13 +00:00
Karol Sójko
cb74b23e45 feat(syncing-server): refactor syncing to decouple getting and saving items (#659)
* feat(syncing-server): refactor syncing to decouple getting and saving items

* fix(syncing-server): item hash http representation mapping

* fix(syncing-server): remove redundant specs for inversify express controller
2023-07-17 13:28:50 +02:00
Karol Sójko
af8f12c33a fix: remove skip_paid_features flag from home server e2e testing 2023-07-14 10:30:22 +02:00
standardci
a148c4d1f6 chore(release): publish new version
- @standardnotes/auth-server@1.124.2
 - @standardnotes/home-server@1.12.3
2023-07-14 08:14:31 +00:00
Karol Sójko
f7190c0c9c fix(home-server): allow custom atributtes for activating premium features 2023-07-14 09:59:20 +02:00
Karol Sójko
c00d7765a9 fix: add missing files server url env var to e2e test suite 2023-07-14 09:34:31 +02:00
standardci
2b651d86e2 chore(release): publish new version
- @standardnotes/auth-server@1.124.1
 - @standardnotes/files-server@1.19.8
 - @standardnotes/home-server@1.12.2
2023-07-13 12:30:31 +00:00
Karol Sójko
9be3517093 fix(files): handling unlimited storage quota on home server 2023-07-13 14:16:05 +02:00
standardci
fcfedaf7e7 chore(release): publish new version
- @standardnotes/auth-server@1.124.0
 - @standardnotes/home-server@1.12.1
2023-07-13 12:08:15 +00:00
Karol Sójko
0b82794e9c feat(auth): add overriding subscription settings on home server (#656) 2023-07-13 13:53:33 +02:00
standardci
2a52e398cb chore(release): publish new version
- @standardnotes/home-server@1.12.0
2023-07-13 09:22:59 +00:00
Karol Sójko
c31e882ad2 chore: fix workflow to run e2e test suite mode in home server 2023-07-13 11:05:37 +02:00
Karol Sójko
2f0903e0eb feat(home-server): add activating premium features during an e2e test suite run 2023-07-13 10:58:35 +02:00
standardci
2396053bc1 chore(release): publish new version
- @standardnotes/auth-server@1.123.2
 - @standardnotes/files-server@1.19.7
 - @standardnotes/home-server@1.11.41
 - @standardnotes/revisions-server@1.24.1
 - @standardnotes/sncrypto-node@1.15.3
 - @standardnotes/syncing-server@1.63.1
 - @standardnotes/websockets-server@1.10.1
2023-07-12 12:42:08 +00:00
Karol Sójko
17fd12305e chore(deps): upgrade @standardnotes deps 2023-07-12 14:25:23 +02:00
standardci
425ea4374d chore(release): publish new version
- @standardnotes/auth-server@1.123.1
 - @standardnotes/home-server@1.11.40
2023-07-12 09:20:55 +00:00
Karol Sójko
c076c3c74a chore(deps): upgrade @standardnotes/features 2023-07-12 11:05:44 +02:00
172 changed files with 3852 additions and 1955 deletions

View File

@@ -115,6 +115,8 @@ jobs:
echo "DB_TYPE=${{ matrix.db_type }}" >> packages/home-server/.env
echo "REDIS_URL=redis://cache" >> packages/home-server/.env
echo "CACHE_TYPE=${{ matrix.cache_type }}" >> packages/home-server/.env
echo "FILES_SERVER_URL=http://localhost:3123" >> packages/home-server/.env
echo "E2E_TESTING=true" >> packages/home-server/.env
- name: Run Server
run: nohup yarn workspace @standardnotes/home-server start &
@@ -125,4 +127,4 @@ jobs:
run: for i in {1..30}; do curl -s http://localhost:3123/healthcheck && break || sleep 1; done
- name: Run E2E Test Suite
run: yarn dlx mocha-headless-chrome --timeout 1200000 -f http://localhost:9001/mocha/test.html?skip_paid_features=true
run: yarn dlx mocha-headless-chrome --timeout 1200000 -f http://localhost:9001/mocha/test.html

112
.pnp.cjs generated
View File

@@ -4560,16 +4560,16 @@ const RAW_RUNTIME_STATE =
}]\
]],\
["@standardnotes/api", [\
["npm:1.26.25", {\
"packageLocation": "./.yarn/cache/@standardnotes-api-npm-1.26.25-fbb86eb9b7-68a820bd36.zip/node_modules/@standardnotes/api/",\
["npm:1.26.26", {\
"packageLocation": "./.yarn/cache/@standardnotes-api-npm-1.26.26-4338a5fe92-db41aedfa3.zip/node_modules/@standardnotes/api/",\
"packageDependencies": [\
["@standardnotes/api", "npm:1.26.25"],\
["@standardnotes/api", "npm:1.26.26"],\
["@standardnotes/common", "workspace:packages/common"],\
["@standardnotes/domain-core", "workspace:packages/domain-core"],\
["@standardnotes/models", "npm:1.46.7"],\
["@standardnotes/responses", "npm:1.13.26"],\
["@standardnotes/models", "npm:1.46.8"],\
["@standardnotes/responses", "npm:1.13.27"],\
["@standardnotes/security", "workspace:packages/security"],\
["@standardnotes/utils", "npm:1.17.4"],\
["@standardnotes/utils", "npm:1.17.5"],\
["reflect-metadata", "npm:0.1.13"]\
],\
"linkType": "HARD"\
@@ -4634,17 +4634,17 @@ const RAW_RUNTIME_STATE =
["@newrelic/winston-enricher", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:4.0.1"],\
["@simplewebauthn/server", "npm:7.2.0"],\
["@simplewebauthn/typescript-types", "npm:7.0.0"],\
["@standardnotes/api", "npm:1.26.25"],\
["@standardnotes/api", "npm:1.26.26"],\
["@standardnotes/common", "workspace:packages/common"],\
["@standardnotes/domain-core", "workspace:packages/domain-core"],\
["@standardnotes/domain-events", "workspace:packages/domain-events"],\
["@standardnotes/domain-events-infra", "workspace:packages/domain-events-infra"],\
["@standardnotes/features", "npm:1.59.5"],\
["@standardnotes/features", "npm:1.59.7"],\
["@standardnotes/predicates", "workspace:packages/predicates"],\
["@standardnotes/responses", "npm:1.13.24"],\
["@standardnotes/responses", "npm:1.13.27"],\
["@standardnotes/security", "workspace:packages/security"],\
["@standardnotes/settings", "workspace:packages/settings"],\
["@standardnotes/sncrypto-common", "npm:1.13.3"],\
["@standardnotes/sncrypto-common", "npm:1.13.4"],\
["@standardnotes/sncrypto-node", "workspace:packages/sncrypto-node"],\
["@standardnotes/time", "workspace:packages/time"],\
["@types/bcryptjs", "npm:2.4.2"],\
@@ -4815,21 +4815,10 @@ const RAW_RUNTIME_STATE =
}]\
]],\
["@standardnotes/features", [\
["npm:1.59.5", {\
"packageLocation": "./.yarn/cache/@standardnotes-features-npm-1.59.5-83c83acde9-173b1f5d52.zip/node_modules/@standardnotes/features/",\
["npm:1.59.7", {\
"packageLocation": "./.yarn/cache/@standardnotes-features-npm-1.59.7-27c3e5296e-1632d64cc1.zip/node_modules/@standardnotes/features/",\
"packageDependencies": [\
["@standardnotes/features", "npm:1.59.5"],\
["@standardnotes/common", "workspace:packages/common"],\
["@standardnotes/domain-core", "workspace:packages/domain-core"],\
["@standardnotes/security", "workspace:packages/security"],\
["reflect-metadata", "npm:0.1.13"]\
],\
"linkType": "HARD"\
}],\
["npm:1.59.6", {\
"packageLocation": "./.yarn/cache/@standardnotes-features-npm-1.59.6-2bcea0cc35-2c855396f7.zip/node_modules/@standardnotes/features/",\
"packageDependencies": [\
["@standardnotes/features", "npm:1.59.6"],\
["@standardnotes/features", "npm:1.59.7"],\
["@standardnotes/common", "workspace:packages/common"],\
["@standardnotes/domain-core", "workspace:packages/domain-core"],\
["@standardnotes/security", "workspace:packages/security"],\
@@ -4850,7 +4839,7 @@ const RAW_RUNTIME_STATE =
["@standardnotes/domain-events", "workspace:packages/domain-events"],\
["@standardnotes/domain-events-infra", "workspace:packages/domain-events-infra"],\
["@standardnotes/security", "workspace:packages/security"],\
["@standardnotes/sncrypto-common", "npm:1.13.3"],\
["@standardnotes/sncrypto-common", "npm:1.13.4"],\
["@standardnotes/sncrypto-node", "workspace:packages/sncrypto-node"],\
["@standardnotes/time", "workspace:packages/time"],\
["@types/connect-busboy", "npm:1.0.0"],\
@@ -4930,15 +4919,16 @@ const RAW_RUNTIME_STATE =
}]\
]],\
["@standardnotes/models", [\
["npm:1.46.7", {\
"packageLocation": "./.yarn/cache/@standardnotes-models-npm-1.46.7-ef9a3fc3ad-50589454f1.zip/node_modules/@standardnotes/models/",\
["npm:1.46.8", {\
"packageLocation": "./.yarn/cache/@standardnotes-models-npm-1.46.8-bc0390832e-8404340f27.zip/node_modules/@standardnotes/models/",\
"packageDependencies": [\
["@standardnotes/models", "npm:1.46.7"],\
["@standardnotes/models", "npm:1.46.8"],\
["@standardnotes/common", "workspace:packages/common"],\
["@standardnotes/features", "npm:1.59.6"],\
["@standardnotes/responses", "npm:1.13.26"],\
["@standardnotes/domain-core", "workspace:packages/domain-core"],\
["@standardnotes/features", "npm:1.59.7"],\
["@standardnotes/responses", "npm:1.13.27"],\
["@standardnotes/sncrypto-common", "npm:1.13.4"],\
["@standardnotes/utils", "npm:1.17.4"],\
["@standardnotes/utils", "npm:1.17.5"],\
["lodash", "npm:4.17.21"]\
],\
"linkType": "HARD"\
@@ -4963,23 +4953,12 @@ const RAW_RUNTIME_STATE =
}]\
]],\
["@standardnotes/responses", [\
["npm:1.13.24", {\
"packageLocation": "./.yarn/cache/@standardnotes-responses-npm-1.13.24-3b4167c7ea-3bcfee90f0.zip/node_modules/@standardnotes/responses/",\
["npm:1.13.27", {\
"packageLocation": "./.yarn/cache/@standardnotes-responses-npm-1.13.27-829dec3e6e-9bf55e5f02.zip/node_modules/@standardnotes/responses/",\
"packageDependencies": [\
["@standardnotes/responses", "npm:1.13.24"],\
["@standardnotes/responses", "npm:1.13.27"],\
["@standardnotes/common", "workspace:packages/common"],\
["@standardnotes/features", "npm:1.59.5"],\
["@standardnotes/security", "workspace:packages/security"],\
["reflect-metadata", "npm:0.1.13"]\
],\
"linkType": "HARD"\
}],\
["npm:1.13.26", {\
"packageLocation": "./.yarn/cache/@standardnotes-responses-npm-1.13.26-cd12940788-6c5e3bf896.zip/node_modules/@standardnotes/responses/",\
"packageDependencies": [\
["@standardnotes/responses", "npm:1.13.26"],\
["@standardnotes/common", "workspace:packages/common"],\
["@standardnotes/features", "npm:1.59.6"],\
["@standardnotes/features", "npm:1.59.7"],\
["@standardnotes/security", "workspace:packages/security"],\
["reflect-metadata", "npm:0.1.13"]\
],\
@@ -4994,12 +4973,12 @@ const RAW_RUNTIME_STATE =
["@aws-sdk/client-s3", "npm:3.342.0"],\
["@aws-sdk/client-sqs", "npm:3.342.0"],\
["@newrelic/winston-enricher", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:4.0.1"],\
["@standardnotes/api", "npm:1.26.25"],\
["@standardnotes/api", "npm:1.26.26"],\
["@standardnotes/common", "workspace:packages/common"],\
["@standardnotes/domain-core", "workspace:packages/domain-core"],\
["@standardnotes/domain-events", "workspace:packages/domain-events"],\
["@standardnotes/domain-events-infra", "workspace:packages/domain-events-infra"],\
["@standardnotes/responses", "npm:1.13.24"],\
["@standardnotes/responses", "npm:1.13.27"],\
["@standardnotes/security", "workspace:packages/security"],\
["@standardnotes/time", "workspace:packages/time"],\
["@types/cors", "npm:2.8.13"],\
@@ -5136,14 +5115,6 @@ const RAW_RUNTIME_STATE =
}]\
]],\
["@standardnotes/sncrypto-common", [\
["npm:1.13.3", {\
"packageLocation": "./.yarn/cache/@standardnotes-sncrypto-common-npm-1.13.3-97ef3850ce-a73af90962.zip/node_modules/@standardnotes/sncrypto-common/",\
"packageDependencies": [\
["@standardnotes/sncrypto-common", "npm:1.13.3"],\
["reflect-metadata", "npm:0.1.13"]\
],\
"linkType": "HARD"\
}],\
["npm:1.13.4", {\
"packageLocation": "./.yarn/cache/@standardnotes-sncrypto-common-npm-1.13.4-3186513fa6-48e0e207f2.zip/node_modules/@standardnotes/sncrypto-common/",\
"packageDependencies": [\
@@ -5158,7 +5129,7 @@ const RAW_RUNTIME_STATE =
"packageLocation": "./packages/sncrypto-node/",\
"packageDependencies": [\
["@standardnotes/sncrypto-node", "workspace:packages/sncrypto-node"],\
["@standardnotes/sncrypto-common", "npm:1.13.3"],\
["@standardnotes/sncrypto-common", "npm:1.13.4"],\
["@types/jest", "npm:29.5.2"],\
["@types/node", "npm:20.2.5"],\
["@typescript-eslint/eslint-plugin", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:5.59.8"],\
@@ -5186,12 +5157,12 @@ const RAW_RUNTIME_STATE =
["@aws-sdk/client-sns", "npm:3.342.0"],\
["@aws-sdk/client-sqs", "npm:3.342.0"],\
["@newrelic/winston-enricher", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:4.0.1"],\
["@standardnotes/api", "npm:1.26.25"],\
["@standardnotes/api", "npm:1.26.26"],\
["@standardnotes/common", "workspace:packages/common"],\
["@standardnotes/domain-core", "workspace:packages/domain-core"],\
["@standardnotes/domain-events", "workspace:packages/domain-events"],\
["@standardnotes/domain-events-infra", "workspace:packages/domain-events-infra"],\
["@standardnotes/responses", "npm:1.13.24"],\
["@standardnotes/responses", "npm:1.13.27"],\
["@standardnotes/security", "workspace:packages/security"],\
["@standardnotes/settings", "workspace:packages/settings"],\
["@standardnotes/sncrypto-node", "workspace:packages/sncrypto-node"],\
@@ -5262,21 +5233,10 @@ const RAW_RUNTIME_STATE =
}]\
]],\
["@standardnotes/utils", [\
["npm:1.16.5", {\
"packageLocation": "./.yarn/cache/@standardnotes-utils-npm-1.16.5-47f537f49f-d5caa7181f.zip/node_modules/@standardnotes/utils/",\
["npm:1.17.5", {\
"packageLocation": "./.yarn/cache/@standardnotes-utils-npm-1.17.5-210b60222d-47e8520174.zip/node_modules/@standardnotes/utils/",\
"packageDependencies": [\
["@standardnotes/utils", "npm:1.16.5"],\
["@standardnotes/common", "workspace:packages/common"],\
["dompurify", "npm:2.4.5"],\
["lodash", "npm:4.17.21"],\
["reflect-metadata", "npm:0.1.13"]\
],\
"linkType": "HARD"\
}],\
["npm:1.17.4", {\
"packageLocation": "./.yarn/cache/@standardnotes-utils-npm-1.17.4-e5908cc204-7cb3fc838d.zip/node_modules/@standardnotes/utils/",\
"packageDependencies": [\
["@standardnotes/utils", "npm:1.17.4"],\
["@standardnotes/utils", "npm:1.17.5"],\
["@standardnotes/common", "workspace:packages/common"],\
["dompurify", "npm:2.4.5"],\
["lodash", "npm:4.17.21"],\
@@ -5292,14 +5252,14 @@ const RAW_RUNTIME_STATE =
["@standardnotes/websockets-server", "workspace:packages/websockets"],\
["@aws-sdk/client-sqs", "npm:3.342.0"],\
["@newrelic/winston-enricher", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:4.0.1"],\
["@standardnotes/api", "npm:1.26.25"],\
["@standardnotes/api", "npm:1.26.26"],\
["@standardnotes/common", "workspace:packages/common"],\
["@standardnotes/domain-core", "workspace:packages/domain-core"],\
["@standardnotes/domain-events", "workspace:packages/domain-events"],\
["@standardnotes/domain-events-infra", "workspace:packages/domain-events-infra"],\
["@standardnotes/responses", "npm:1.13.24"],\
["@standardnotes/responses", "npm:1.13.27"],\
["@standardnotes/security", "workspace:packages/security"],\
["@standardnotes/utils", "npm:1.16.5"],\
["@standardnotes/utils", "npm:1.17.5"],\
["@types/cors", "npm:2.8.13"],\
["@types/express", "npm:4.17.17"],\
["@types/ioredis", "npm:5.0.0"],\

View File

@@ -3,6 +3,16 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [2.25.1](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.25.0...@standardnotes/analytics@2.25.1) (2023-07-19)
**Note:** Version bump only for package @standardnotes/analytics
# [2.25.0](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.24.9...@standardnotes/analytics@2.25.0) (2023-07-17)
### Features
* **syncing-server:** refactor syncing to decouple getting and saving items ([#659](https://github.com/standardnotes/server/issues/659)) ([cb74b23](https://github.com/standardnotes/server/commit/cb74b23e45b207136e299ce8a3db2c04dc87e21e))
## [2.24.9](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.24.8...@standardnotes/analytics@2.24.9) (2023-07-12)
**Note:** Version bump only for package @standardnotes/analytics

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/analytics",
"version": "2.24.9",
"version": "2.25.1",
"engines": {
"node": ">=18.0.0 <21.0.0"
},

View File

@@ -3,10 +3,6 @@ import { Result, Entity, UniqueEntityId } from '@standardnotes/domain-core'
import { StatisticMeasureProps } from './StatisticMeasureProps'
export class StatisticMeasure extends Entity<StatisticMeasureProps> {
get id(): UniqueEntityId {
return this._id
}
get name(): string {
return this.props.name.value
}

View File

@@ -3,10 +3,6 @@ import { Entity, Result, UniqueEntityId } from '@standardnotes/domain-core'
import { SubscriptionProps } from './SubscriptionProps'
export class Subscription extends Entity<SubscriptionProps> {
get id(): UniqueEntityId {
return this._id
}
private constructor(props: SubscriptionProps, id?: UniqueEntityId) {
super(props, id)
}

View File

@@ -3,10 +3,6 @@ import { Entity, Result, UniqueEntityId } from '@standardnotes/domain-core'
import { UserProps } from './UserProps'
export class User extends Entity<UserProps> {
get id(): UniqueEntityId {
return this._id
}
private constructor(props: UserProps, id?: UniqueEntityId) {
super(props, id)
}

View File

@@ -3,6 +3,16 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [1.66.0](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.65.7...@standardnotes/api-gateway@1.66.0) (2023-07-19)
### Features
* **syncing-server:** add persistence of shared vaults with users and invites + controllers ([#662](https://github.com/standardnotes/api-gateway/issues/662)) ([3f21a35](https://github.com/standardnotes/api-gateway/commit/3f21a358d24d70daf541aa62dc86cd9e29500e62))
## [1.65.7](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.65.6...@standardnotes/api-gateway@1.65.7) (2023-07-17)
**Note:** Version bump only for package @standardnotes/api-gateway
## [1.65.6](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.65.5...@standardnotes/api-gateway@1.65.6) (2023-07-12)
**Note:** Version bump only for package @standardnotes/api-gateway

View File

@@ -16,8 +16,10 @@ import '../src/Controller/v1/OfflineController'
import '../src/Controller/v1/FilesController'
import '../src/Controller/v1/SubscriptionInvitesController'
import '../src/Controller/v1/AuthenticatorsController'
import '../src/Controller/v1/AsymmetricMessagesController'
import '../src/Controller/v1/MessagesController'
import '../src/Controller/v1/SharedVaultsController'
import '../src/Controller/v1/SharedVaultInvitesController'
import '../src/Controller/v1/SharedVaultUsersController'
import '../src/Controller/v2/PaymentsControllerV2'
import '../src/Controller/v2/ActionsControllerV2'

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/api-gateway",
"version": "1.65.6",
"version": "1.66.0",
"engines": {
"node": ">=18.0.0 <21.0.0"
},

View File

@@ -4,7 +4,7 @@ export * from './SubscriptionTokenAuthMiddleware'
export * from './TokenAuthenticationMethod'
export * from './WebSocketAuthMiddleware'
export * from './v1/ActionsController'
export * from './v1/AsymmetricMessagesController'
export * from './v1/MessagesController'
export * from './v1/AuthenticatorsController'
export * from './v1/FilesController'
export * from './v1/InvoicesController'

View File

@@ -1,17 +0,0 @@
import { Request, Response } from 'express'
import { inject } from 'inversify'
import { BaseHttpController, controller, all } from 'inversify-express-utils'
import { TYPES } from '../../Bootstrap/Types'
import { ServiceProxyInterface } from '../../Service/Http/ServiceProxyInterface'
@controller('/v1/asymmetric-messages')
export class AsymmetricMessagesController extends BaseHttpController {
constructor(@inject(TYPES.ServiceProxy) private serviceProxy: ServiceProxyInterface) {
super()
}
@all('*', TYPES.RequiredCrossServiceTokenMiddleware)
async subscriptions(request: Request, response: Response): Promise<void> {
await this.serviceProxy.callSyncingServer(request, response, request.path.replace('/v1/', ''), request.body)
}
}

View File

@@ -0,0 +1,70 @@
import { Request, Response } from 'express'
import { inject } from 'inversify'
import { BaseHttpController, controller, httpDelete, httpGet, httpPost } from 'inversify-express-utils'
import { TYPES } from '../../Bootstrap/Types'
import { ServiceProxyInterface } from '../../Service/Http/ServiceProxyInterface'
import { EndpointResolverInterface } from '../../Service/Resolver/EndpointResolverInterface'
@controller('/v1/messages', TYPES.RequiredCrossServiceTokenMiddleware)
export class MessagesController extends BaseHttpController {
constructor(
@inject(TYPES.ServiceProxy) private httpService: ServiceProxyInterface,
@inject(TYPES.EndpointResolver) private endpointResolver: EndpointResolverInterface,
) {
super()
}
@httpGet('/')
async getMessages(request: Request, response: Response): Promise<void> {
await this.httpService.callSyncingServer(
request,
response,
this.endpointResolver.resolveEndpointOrMethodIdentifier('GET', 'messages/'),
request.body,
)
}
@httpGet('/outbound')
async getMessagesSent(request: Request, response: Response): Promise<void> {
await this.httpService.callSyncingServer(
request,
response,
this.endpointResolver.resolveEndpointOrMethodIdentifier('GET', 'messages/outbound'),
request.body,
)
}
@httpPost('/')
async sendMessage(request: Request, response: Response): Promise<void> {
await this.httpService.callSyncingServer(
request,
response,
this.endpointResolver.resolveEndpointOrMethodIdentifier('POST', 'messages/'),
request.body,
)
}
@httpDelete('/inbound')
async deleteMessagesSentToUser(request: Request, response: Response): Promise<void> {
await this.httpService.callSyncingServer(
request,
response,
this.endpointResolver.resolveEndpointOrMethodIdentifier('DELETE', 'messages/inbound'),
request.body,
)
}
@httpDelete('/:messageUuid')
async deleteMessage(request: Request, response: Response): Promise<void> {
await this.httpService.callSyncingServer(
request,
response,
this.endpointResolver.resolveEndpointOrMethodIdentifier(
'DELETE',
'messages/:messageUuid',
request.params.messageUuid,
),
request.body,
)
}
}

View File

@@ -0,0 +1,148 @@
import { Request, Response } from 'express'
import { inject } from 'inversify'
import { BaseHttpController, controller, httpDelete, httpGet, httpPatch, httpPost } from 'inversify-express-utils'
import { TYPES } from '../../Bootstrap/Types'
import { ServiceProxyInterface } from '../../Service/Http/ServiceProxyInterface'
import { EndpointResolverInterface } from '../../Service/Resolver/EndpointResolverInterface'
@controller('/v1/shared-vaults', TYPES.RequiredCrossServiceTokenMiddleware)
export class SharedVaultInvitesController extends BaseHttpController {
constructor(
@inject(TYPES.ServiceProxy) private httpService: ServiceProxyInterface,
@inject(TYPES.EndpointResolver) private endpointResolver: EndpointResolverInterface,
) {
super()
}
@httpPost('/:sharedVaultUuid/invites')
async createSharedVaultInvite(request: Request, response: Response): Promise<void> {
await this.httpService.callSyncingServer(
request,
response,
this.endpointResolver.resolveEndpointOrMethodIdentifier(
'POST',
'shared-vaults/:sharedVaultUuid/invites',
request.params.sharedVaultUuid,
),
request.body,
)
}
@httpPatch('/:sharedVaultUuid/invites/:inviteUuid')
async updateSharedVaultInvite(request: Request, response: Response): Promise<void> {
await this.httpService.callSyncingServer(
request,
response,
this.endpointResolver.resolveEndpointOrMethodIdentifier(
'PATCH',
'shared-vaults/:sharedVaultUuid/invites/:inviteUuid',
request.params.sharedVaultUuid,
request.params.inviteUuid,
),
request.body,
)
}
@httpPost('/:sharedVaultUuid/invites/:inviteUuid/accept')
async acceptSharedVaultInvite(request: Request, response: Response): Promise<void> {
await this.httpService.callSyncingServer(
request,
response,
this.endpointResolver.resolveEndpointOrMethodIdentifier(
'POST',
'shared-vaults/:sharedVaultUuid/invites/:inviteUuid/accept',
request.params.sharedVaultUuid,
request.params.inviteUuid,
),
request.body,
)
}
@httpPost('/:sharedVaultUuid/invites/:inviteUuid/decline')
async declineSharedVaultInvite(request: Request, response: Response): Promise<void> {
await this.httpService.callSyncingServer(
request,
response,
this.endpointResolver.resolveEndpointOrMethodIdentifier(
'POST',
'shared-vaults/:sharedVaultUuid/invites/:inviteUuid/decline',
request.params.sharedVaultUuid,
request.params.inviteUuid,
),
request.body,
)
}
@httpDelete('/invites/inbound')
async deleteInboundUserInvites(request: Request, response: Response): Promise<void> {
await this.httpService.callSyncingServer(
request,
response,
this.endpointResolver.resolveEndpointOrMethodIdentifier('DELETE', 'shared-vaults/invites/inbound'),
request.body,
)
}
@httpGet('/invites/outbound')
async getOutboundUserInvites(request: Request, response: Response): Promise<void> {
await this.httpService.callSyncingServer(
request,
response,
this.endpointResolver.resolveEndpointOrMethodIdentifier('GET', 'shared-vaults/invites/outbound'),
request.body,
)
}
@httpGet('/invites')
async getUserInvites(request: Request, response: Response): Promise<void> {
await this.httpService.callSyncingServer(
request,
response,
this.endpointResolver.resolveEndpointOrMethodIdentifier('GET', 'shared-vaults/invites'),
request.body,
)
}
@httpGet('/:sharedVaultUuid/invites')
async getSharedVaultInvites(request: Request, response: Response): Promise<void> {
await this.httpService.callSyncingServer(
request,
response,
this.endpointResolver.resolveEndpointOrMethodIdentifier(
'GET',
'shared-vaults/:sharedVaultUuid/invites',
request.params.sharedVaultUuid,
),
request.body,
)
}
@httpDelete('/:sharedVaultUuid/invites/:inviteUuid')
async deleteSharedVaultInvite(request: Request, response: Response): Promise<void> {
await this.httpService.callSyncingServer(
request,
response,
this.endpointResolver.resolveEndpointOrMethodIdentifier(
'DELETE',
'shared-vaults/:sharedVaultUuid/invites/:inviteUuid',
request.params.sharedVaultUuid,
request.params.inviteUuid,
),
request.body,
)
}
@httpDelete('/:sharedVaultUuid/invites')
async deleteAllSharedVaultInvites(request: Request, response: Response): Promise<void> {
await this.httpService.callSyncingServer(
request,
response,
this.endpointResolver.resolveEndpointOrMethodIdentifier(
'DELETE',
'shared-vaults/:sharedVaultUuid/invites',
request.params.sharedVaultUuid,
),
request.body,
)
}
}

View File

@@ -0,0 +1,45 @@
import { Request, Response } from 'express'
import { inject } from 'inversify'
import { BaseHttpController, controller, httpDelete, httpGet } from 'inversify-express-utils'
import { TYPES } from '../../Bootstrap/Types'
import { ServiceProxyInterface } from '../../Service/Http/ServiceProxyInterface'
import { EndpointResolverInterface } from '../../Service/Resolver/EndpointResolverInterface'
@controller('/v1/shared-vaults/:sharedVaultUuid/users', TYPES.RequiredCrossServiceTokenMiddleware)
export class SharedVaultUsersController extends BaseHttpController {
constructor(
@inject(TYPES.ServiceProxy) private httpService: ServiceProxyInterface,
@inject(TYPES.EndpointResolver) private endpointResolver: EndpointResolverInterface,
) {
super()
}
@httpGet('/')
async getSharedVaultUsers(request: Request, response: Response): Promise<void> {
await this.httpService.callSyncingServer(
request,
response,
this.endpointResolver.resolveEndpointOrMethodIdentifier(
'GET',
'/shared-vaults/:sharedVaultUuid/users',
request.params.sharedVaultUuid,
),
request.body,
)
}
@httpDelete('/:userUuid')
async removeUserFromSharedVault(request: Request, response: Response): Promise<void> {
await this.httpService.callSyncingServer(
request,
response,
this.endpointResolver.resolveEndpointOrMethodIdentifier(
'DELETE',
'/shared-vaults/:sharedVaultUuid/users/:userUuid',
request.params.sharedVaultUuid,
request.params.userUuid,
),
request.body,
)
}
}

View File

@@ -1,17 +1,64 @@
import { Request, Response } from 'express'
import { inject } from 'inversify'
import { BaseHttpController, controller, all } from 'inversify-express-utils'
import { BaseHttpController, controller, httpDelete, httpGet, httpPost } from 'inversify-express-utils'
import { TYPES } from '../../Bootstrap/Types'
import { ServiceProxyInterface } from '../../Service/Http/ServiceProxyInterface'
import { EndpointResolverInterface } from '../../Service/Resolver/EndpointResolverInterface'
@controller('/v1/shared-vaults')
@controller('/v1/shared-vaults', TYPES.RequiredCrossServiceTokenMiddleware)
export class SharedVaultsController extends BaseHttpController {
constructor(@inject(TYPES.ServiceProxy) private serviceProxy: ServiceProxyInterface) {
constructor(
@inject(TYPES.ServiceProxy) private httpService: ServiceProxyInterface,
@inject(TYPES.EndpointResolver) private endpointResolver: EndpointResolverInterface,
) {
super()
}
@all('*', TYPES.RequiredCrossServiceTokenMiddleware)
async subscriptions(request: Request, response: Response): Promise<void> {
await this.serviceProxy.callSyncingServer(request, response, request.path.replace('/v1/', ''), request.body)
@httpGet('/')
async getSharedVaults(request: Request, response: Response): Promise<void> {
await this.httpService.callSyncingServer(
request,
response,
this.endpointResolver.resolveEndpointOrMethodIdentifier('GET', 'shared-vaults/'),
request.body,
)
}
@httpPost('/')
async createSharedVault(request: Request, response: Response): Promise<void> {
await this.httpService.callSyncingServer(
request,
response,
this.endpointResolver.resolveEndpointOrMethodIdentifier('POST', 'shared-vaults/'),
request.body,
)
}
@httpDelete('/:sharedVaultUuid')
async deleteSharedVault(request: Request, response: Response): Promise<void> {
await this.httpService.callSyncingServer(
request,
response,
this.endpointResolver.resolveEndpointOrMethodIdentifier(
'DELETE',
'shared-vaults/:sharedVaultUuid',
request.params.sharedVaultUuid,
),
request.body,
)
}
@httpPost('/:sharedVaultUuid/valet-tokens')
async createValetTokenForSharedVaultFile(request: Request, response: Response): Promise<void> {
await this.httpService.callSyncingServer(
request,
response,
this.endpointResolver.resolveEndpointOrMethodIdentifier(
'POST',
'shared-vaults/:sharedVaultUuid/valet-tokens',
request.params.sharedVaultUuid,
),
request.body,
)
}
}

View File

@@ -62,6 +62,31 @@ export class EndpointResolver implements EndpointResolverInterface {
['[GET]:items/:itemUuid/revisions', 'revisions.revisions.getRevisions'],
['[GET]:items/:itemUuid/revisions/:id', 'revisions.revisions.getRevision'],
['[DELETE]:items/:itemUuid/revisions/:id', 'revisions.revisions.deleteRevision'],
// Messages Controller
['[GET]:messages/', 'sync.messages.get-received'],
['[GET]:messages/outbound', 'sync.messages.get-sent'],
['[POST]:messages/', 'sync.messages.send'],
['[DELETE]:messages/inbound', 'sync.messages.delete-all'],
['[DELETE]:messages/:messageUuid', 'sync.messages.delete'],
// Shared Vaults Controller
['[GET]:shared-vaults/', 'sync.shared-vaults.get-vaults'],
['[POST]:shared-vaults/', 'sync.shared-vaults.create-vault'],
['[DELETE]:shared-vaults/:sharedVaultUuid', 'sync.shared-vaults.delete-vault'],
['[POST]:shared-vaults/:sharedVaultUuid/valet-tokens', 'sync.shared-vaults.create-file-valet-token'],
// Shared Vault Invites Controller
['[POST]:shared-vaults/:sharedVaultUuid/invites', 'sync.shared-vault-invites.create'],
['[PATCH]:shared-vaults/:sharedVaultUuid/invites/:inviteUuid', 'sync.shared-vault-invites.update'],
['[POST]:shared-vaults/:sharedVaultUuid/invites/:inviteUuid/accept', 'sync.shared-vault-invites.accept'],
['[POST]:shared-vaults/:sharedVaultUuid/invites/:inviteUuid/decline', 'sync.shared-vault-invites.decline'],
['[DELETE]:shared-vaults/invites/inbound', 'sync.shared-vault-invites.delete-inbound'],
['[GET]:shared-vaults/invites/outbound', 'sync.shared-vault-invites.get-outbound'],
['[GET]:shared-vaults/invites', 'sync.shared-vault-invites.get-user-invites'],
['[GET]:shared-vaults/:sharedVaultUuid/invites', 'sync.shared-vault-invites.get-vault-invites'],
['[DELETE]:shared-vaults/:sharedVaultUuid/invites/:inviteUuid', 'sync.shared-vault-invites.delete-invite'],
['[DELETE]:shared-vaults/:sharedVaultUuid/invites', 'sync.shared-vault-invites.delete-all'],
// Shared Vault Users Controller
['[GET]:shared-vaults/:sharedVaultUuid/users', 'sync.shared-vault-users.get-users'],
['[DELETE]:shared-vaults/:sharedVaultUuid/users/:userUuid', 'sync.shared-vault-users.remove-user'],
])
resolveEndpointOrMethodIdentifier(method: string, endpoint: string, ...params: string[]): string {

View File

@@ -3,6 +3,42 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.125.1](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.125.0...@standardnotes/auth-server@1.125.1) (2023-07-19)
**Note:** Version bump only for package @standardnotes/auth-server
# [1.125.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.124.2...@standardnotes/auth-server@1.125.0) (2023-07-17)
### Features
* **syncing-server:** refactor syncing to decouple getting and saving items ([#659](https://github.com/standardnotes/server/issues/659)) ([cb74b23](https://github.com/standardnotes/server/commit/cb74b23e45b207136e299ce8a3db2c04dc87e21e))
## [1.124.2](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.124.1...@standardnotes/auth-server@1.124.2) (2023-07-14)
### Bug Fixes
* **home-server:** allow custom atributtes for activating premium features ([f7190c0](https://github.com/standardnotes/server/commit/f7190c0c9c2d105f97d1cf980ce6a4f0dae34805))
## [1.124.1](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.124.0...@standardnotes/auth-server@1.124.1) (2023-07-13)
### Bug Fixes
* **files:** handling unlimited storage quota on home server ([9be3517](https://github.com/standardnotes/server/commit/9be3517093f8dd7bbdd7507c1e2ff059e6c9a889))
# [1.124.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.123.2...@standardnotes/auth-server@1.124.0) (2023-07-13)
### Features
* **auth:** add overriding subscription settings on home server ([#656](https://github.com/standardnotes/server/issues/656)) ([0b82794](https://github.com/standardnotes/server/commit/0b82794e9c7ed82cfc08a92eafc016fbde5c4fcc))
## [1.123.2](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.123.1...@standardnotes/auth-server@1.123.2) (2023-07-12)
**Note:** Version bump only for package @standardnotes/auth-server
## [1.123.1](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.123.0...@standardnotes/auth-server@1.123.1) (2023-07-12)
**Note:** Version bump only for package @standardnotes/auth-server
# [1.123.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.122.2...@standardnotes/auth-server@1.123.0) (2023-07-12)
### Features

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/auth-server",
"version": "1.123.0",
"version": "1.125.1",
"engines": {
"node": ">=18.0.0 <21.0.0"
},
@@ -42,17 +42,17 @@
"@cbor-extract/cbor-extract-linux-x64": "^2.1.1",
"@simplewebauthn/server": "^7.2.0",
"@simplewebauthn/typescript-types": "^7.0.0",
"@standardnotes/api": "^1.26.25",
"@standardnotes/api": "^1.26.26",
"@standardnotes/common": "workspace:*",
"@standardnotes/domain-core": "workspace:^",
"@standardnotes/domain-events": "workspace:*",
"@standardnotes/domain-events-infra": "workspace:*",
"@standardnotes/features": "^1.58.12",
"@standardnotes/features": "^1.59.7",
"@standardnotes/predicates": "workspace:*",
"@standardnotes/responses": "^1.13.9",
"@standardnotes/responses": "^1.13.27",
"@standardnotes/security": "workspace:*",
"@standardnotes/settings": "workspace:*",
"@standardnotes/sncrypto-common": "^1.9.0",
"@standardnotes/sncrypto-common": "^1.13.4",
"@standardnotes/sncrypto-node": "workspace:*",
"@standardnotes/time": "workspace:*",
"axios": "^1.1.3",

View File

@@ -1,5 +1,9 @@
import { Result, ServiceInterface } from '@standardnotes/domain-core'
export interface AuthServiceInterface extends ServiceInterface {
activatePremiumFeatures(username: string): Promise<Result<string>>
activatePremiumFeatures(dto: {
username: string
subscriptionPlanName?: string
endsAt?: Date
}): Promise<Result<string>>
}

View File

@@ -793,6 +793,7 @@ export class ContainerConfigLoader {
new ActivatePremiumFeatures(
container.get(TYPES.Auth_UserRepository),
container.get(TYPES.Auth_UserSubscriptionRepository),
container.get(TYPES.Auth_SubscriptionSettingService),
container.get(TYPES.Auth_RoleService),
container.get(TYPES.Auth_Timer),
),

View File

@@ -24,14 +24,18 @@ export class Service implements AuthServiceInterface {
this.serviceContainer.register(this.getId(), this)
}
async activatePremiumFeatures(username: string): Promise<Result<string>> {
async activatePremiumFeatures(dto: {
username: string
subscriptionPlanName?: string
endsAt?: Date
}): Promise<Result<string>> {
if (!this.container) {
return Result.fail('Container not initialized')
}
const activatePremiumFeatures = this.container.get(TYPES.Auth_ActivatePremiumFeatures) as ActivatePremiumFeatures
return activatePremiumFeatures.execute({ username })
return activatePremiumFeatures.execute(dto)
}
async handleRequest(request: never, response: never, endpointOrMethodIdentifier: string): Promise<unknown> {

View File

@@ -3,10 +3,6 @@ import { Entity, Result, UniqueEntityId } from '@standardnotes/domain-core'
import { AuthenticatorProps } from './AuthenticatorProps'
export class Authenticator extends Entity<AuthenticatorProps> {
get id(): UniqueEntityId {
return this._id
}
private constructor(props: AuthenticatorProps, id?: UniqueEntityId) {
super(props, id)
}

View File

@@ -3,10 +3,6 @@ import { Entity, Result, UniqueEntityId } from '@standardnotes/domain-core'
import { AuthenticatorChallengeProps } from './AuthenticatorChallengeProps'
export class AuthenticatorChallenge extends Entity<AuthenticatorChallengeProps> {
get id(): UniqueEntityId {
return this._id
}
private constructor(props: AuthenticatorChallengeProps, id?: UniqueEntityId) {
super(props, id)
}

View File

@@ -3,10 +3,6 @@ import { Entity, Result, UniqueEntityId } from '@standardnotes/domain-core'
import { EmergencyAccessInvitationProps } from './EmergencyAccessInvitationProps'
export class EmergencyAccessInvitation extends Entity<EmergencyAccessInvitationProps> {
get id(): UniqueEntityId {
return this._id
}
private constructor(props: EmergencyAccessInvitationProps, id?: UniqueEntityId) {
super(props, id)
}

View File

@@ -13,7 +13,8 @@ import { UserSubscriptionServiceInterface } from '../Subscription/UserSubscripti
describe('FileRemovedEventHandler', () => {
let userSubscriptionService: UserSubscriptionServiceInterface
let logger: Logger
let user: User
let regularUser: User
let sharedUser: User
let event: FileRemovedEvent
let subscriptionSettingService: SubscriptionSettingServiceInterface
let regularSubscription: UserSubscription
@@ -22,20 +23,24 @@ describe('FileRemovedEventHandler', () => {
const createHandler = () => new FileRemovedEventHandler(userSubscriptionService, subscriptionSettingService, logger)
beforeEach(() => {
user = {
regularUser = {
uuid: '123',
} as jest.Mocked<User>
sharedUser = {
uuid: '234',
} as jest.Mocked<User>
regularSubscription = {
uuid: '1-2-3',
subscriptionType: UserSubscriptionType.Regular,
user: Promise.resolve(user),
user: Promise.resolve(regularUser),
} as jest.Mocked<UserSubscription>
sharedSubscription = {
uuid: '2-3-4',
subscriptionType: UserSubscriptionType.Shared,
user: Promise.resolve(user),
user: Promise.resolve(sharedUser),
} as jest.Mocked<UserSubscription>
userSubscriptionService = {} as jest.Mocked<UserSubscriptionServiceInterface>
@@ -93,10 +98,11 @@ describe('FileRemovedEventHandler', () => {
unencryptedValue: '222',
serverEncryptionVersion: 0,
},
user: regularUser,
userSubscription: {
uuid: '1-2-3',
subscriptionType: 'regular',
user: Promise.resolve(user),
user: Promise.resolve(regularUser),
},
})
})
@@ -118,10 +124,11 @@ describe('FileRemovedEventHandler', () => {
unencryptedValue: '222',
serverEncryptionVersion: 0,
},
user: regularUser,
userSubscription: {
uuid: '1-2-3',
subscriptionType: 'regular',
user: Promise.resolve(user),
user: Promise.resolve(regularUser),
},
})
@@ -132,10 +139,11 @@ describe('FileRemovedEventHandler', () => {
unencryptedValue: '222',
serverEncryptionVersion: 0,
},
user: sharedUser,
userSubscription: {
uuid: '2-3-4',
subscriptionType: 'shared',
user: Promise.resolve(user),
user: Promise.resolve(sharedUser),
},
})
})

View File

@@ -51,6 +51,7 @@ export class FileRemovedEventHandler implements DomainEventHandlerInterface {
await this.subscriptionSettingService.createOrReplace({
userSubscription: subscription,
user,
props: {
name: SettingName.NAMES.FileUploadBytesUsed,
unencryptedValue: (+bytesUsed - byteSize).toString(),

View File

@@ -76,6 +76,7 @@ describe('FileUploadedEventHandler', () => {
unencryptedValue: '123',
serverEncryptionVersion: 0,
},
user,
userSubscription: {
uuid: '1-2-3',
subscriptionType: 'regular',
@@ -118,6 +119,7 @@ describe('FileUploadedEventHandler', () => {
unencryptedValue: '468',
serverEncryptionVersion: 0,
},
user,
userSubscription: {
uuid: '1-2-3',
subscriptionType: 'regular',
@@ -143,6 +145,7 @@ describe('FileUploadedEventHandler', () => {
unencryptedValue: '468',
serverEncryptionVersion: 0,
},
user,
userSubscription: {
uuid: '1-2-3',
subscriptionType: 'regular',
@@ -157,6 +160,7 @@ describe('FileUploadedEventHandler', () => {
unencryptedValue: '468',
serverEncryptionVersion: 0,
},
user,
userSubscription: {
uuid: '2-3-4',
subscriptionType: 'shared',

View File

@@ -9,6 +9,7 @@ import { SubscriptionSettingServiceInterface } from '../Setting/SubscriptionSett
import { UserSubscription } from '../Subscription/UserSubscription'
import { UserSubscriptionServiceInterface } from '../Subscription/UserSubscriptionServiceInterface'
import { UserRepositoryInterface } from '../User/UserRepositoryInterface'
import { User } from '../User/User'
@injectable()
export class FileUploadedEventHandler implements DomainEventHandlerInterface {
@@ -36,14 +37,18 @@ export class FileUploadedEventHandler implements DomainEventHandlerInterface {
return
}
await this.updateUploadBytesUsedSetting(regularSubscription, event.payload.fileByteSize)
await this.updateUploadBytesUsedSetting(regularSubscription, user, event.payload.fileByteSize)
if (sharedSubscription !== null) {
await this.updateUploadBytesUsedSetting(sharedSubscription, event.payload.fileByteSize)
await this.updateUploadBytesUsedSetting(sharedSubscription, user, event.payload.fileByteSize)
}
}
private async updateUploadBytesUsedSetting(subscription: UserSubscription, byteSize: number): Promise<void> {
private async updateUploadBytesUsedSetting(
subscription: UserSubscription,
user: User,
byteSize: number,
): Promise<void> {
let bytesUsed = '0'
const bytesUsedSetting = await this.subscriptionSettingService.findSubscriptionSettingWithDecryptedValue({
userUuid: (await subscription.user).uuid,
@@ -56,6 +61,7 @@ export class FileUploadedEventHandler implements DomainEventHandlerInterface {
await this.subscriptionSettingService.createOrReplace({
userSubscription: subscription,
user,
props: {
name: SettingName.NAMES.FileUploadBytesUsed,
unencryptedValue: (+bytesUsed + byteSize).toString(),

View File

@@ -114,8 +114,6 @@ describe('SubscriptionPurchasedEventHandler', () => {
expect(subscriptionSettingService.applyDefaultSubscriptionSettingsForSubscription).toHaveBeenCalledWith(
subscription,
SubscriptionName.ProPlan,
'123',
)
})

View File

@@ -66,11 +66,7 @@ export class SubscriptionPurchasedEventHandler implements DomainEventHandlerInte
await this.addUserRole(user, event.payload.subscriptionName)
await this.subscriptionSettingService.applyDefaultSubscriptionSettingsForSubscription(
userSubscription,
event.payload.subscriptionName,
user.uuid,
)
await this.subscriptionSettingService.applyDefaultSubscriptionSettingsForSubscription(userSubscription)
}
private async addUserRole(user: User, subscriptionName: string): Promise<void> {

View File

@@ -94,8 +94,6 @@ describe('SubscriptionReassignedEventHandler', () => {
expect(subscriptionSettingService.applyDefaultSubscriptionSettingsForSubscription).toHaveBeenCalledWith(
subscription,
SubscriptionName.ProPlan,
'123',
)
})

View File

@@ -63,11 +63,7 @@ export class SubscriptionReassignedEventHandler implements DomainEventHandlerInt
},
})
await this.subscriptionSettingService.applyDefaultSubscriptionSettingsForSubscription(
userSubscription,
event.payload.subscriptionName,
user.uuid,
)
await this.subscriptionSettingService.applyDefaultSubscriptionSettingsForSubscription(userSubscription)
}
private async addUserRole(user: User, subscriptionName: string): Promise<void> {

View File

@@ -129,8 +129,6 @@ describe('SubscriptionSyncRequestedEventHandler', () => {
expect(subscriptionSettingService.applyDefaultSubscriptionSettingsForSubscription).toHaveBeenCalledWith(
subscription,
SubscriptionName.ProPlan,
'123',
)
expect(settingService.createOrReplace).toHaveBeenCalledWith({

View File

@@ -95,11 +95,7 @@ export class SubscriptionSyncRequestedEventHandler implements DomainEventHandler
await this.roleService.addUserRole(user, event.payload.subscriptionName)
await this.subscriptionSettingService.applyDefaultSubscriptionSettingsForSubscription(
userSubscription,
event.payload.subscriptionName,
user.uuid,
)
await this.subscriptionSettingService.applyDefaultSubscriptionSettingsForSubscription(userSubscription)
await this.settingService.createOrReplace({
user,

View File

@@ -3,10 +3,6 @@ import { Entity, Result, UniqueEntityId } from '@standardnotes/domain-core'
import { SessionTraceProps } from './SessionTraceProps'
export class SessionTrace extends Entity<SessionTraceProps> {
get id(): UniqueEntityId {
return this._id
}
private constructor(props: SessionTraceProps, id?: UniqueEntityId) {
super(props, id)
}

View File

@@ -1,7 +1,9 @@
import { UserSubscription } from '../Subscription/UserSubscription'
import { User } from '../User/User'
import { SubscriptionSettingProps } from './SubscriptionSettingProps'
export type CreateOrReplaceSubscriptionSettingDTO = {
userSubscription: UserSubscription
user: User
props: SubscriptionSettingProps
}

View File

@@ -45,6 +45,7 @@ describe('SubscriptionSettingService', () => {
userSubscription = {
uuid: '1-2-3',
user: Promise.resolve(user),
planName: SubscriptionName.PlusPlan,
} as jest.Mocked<UserSubscription>
setting = {
@@ -97,15 +98,70 @@ describe('SubscriptionSettingService', () => {
})
it('should create default settings for a subscription', async () => {
await createService().applyDefaultSubscriptionSettingsForSubscription(
userSubscription,
SubscriptionName.PlusPlan,
'1-2-3',
)
await createService().applyDefaultSubscriptionSettingsForSubscription(userSubscription)
expect(subscriptionSettingRepository.save).toHaveBeenCalledWith(setting)
})
it('should create default settings for a subscription with overrides', async () => {
subscriptionSettingsAssociationService.getDefaultSettingsAndValuesForSubscriptionName = jest.fn().mockReturnValue(
new Map([
[
SettingName.NAMES.FileUploadBytesUsed,
{
value: '0',
sensitive: 0,
serverEncryptionVersion: EncryptionVersion.Unencrypted,
replaceable: false,
},
],
[
SettingName.NAMES.FileUploadBytesLimit,
{
value: '345',
sensitive: 0,
serverEncryptionVersion: EncryptionVersion.Unencrypted,
replaceable: true,
},
],
]),
)
await createService().applyDefaultSubscriptionSettingsForSubscription(
userSubscription,
new Map([[SettingName.NAMES.FileUploadBytesLimit, '123']]),
)
expect(factory.createSubscriptionSetting).toHaveBeenNthCalledWith(
1,
{
name: SettingName.NAMES.FileUploadBytesUsed,
sensitive: 0,
serverEncryptionVersion: EncryptionVersion.Unencrypted,
unencryptedValue: '0',
},
{
planName: SubscriptionName.PlusPlan,
user: Promise.resolve(user),
uuid: '1-2-3',
},
)
expect(factory.createSubscriptionSetting).toHaveBeenNthCalledWith(
2,
{
name: SettingName.NAMES.FileUploadBytesLimit,
sensitive: 0,
serverEncryptionVersion: EncryptionVersion.Unencrypted,
unencryptedValue: '123',
},
{
planName: SubscriptionName.PlusPlan,
user: Promise.resolve(user),
uuid: '1-2-3',
},
)
})
it('should throw error if subscription setting is invalid', async () => {
subscriptionSettingsAssociationService.getDefaultSettingsAndValuesForSubscriptionName = jest.fn().mockReturnValue(
new Map([
@@ -121,13 +177,7 @@ describe('SubscriptionSettingService', () => {
]),
)
await expect(
createService().applyDefaultSubscriptionSettingsForSubscription(
userSubscription,
SubscriptionName.PlusPlan,
'1-2-3',
),
).rejects.toThrow()
await expect(createService().applyDefaultSubscriptionSettingsForSubscription(userSubscription)).rejects.toThrow()
})
it('should throw error if setting name is not a subscription setting when applying defaults', async () => {
@@ -145,13 +195,7 @@ describe('SubscriptionSettingService', () => {
]),
)
await expect(
createService().applyDefaultSubscriptionSettingsForSubscription(
userSubscription,
SubscriptionName.PlusPlan,
'1-2-3',
),
).rejects.toThrow()
await expect(createService().applyDefaultSubscriptionSettingsForSubscription(userSubscription)).rejects.toThrow()
})
it('should reassign existing default settings for a subscription if it is not replaceable', async () => {
@@ -170,11 +214,7 @@ describe('SubscriptionSettingService', () => {
)
subscriptionSettingRepository.findLastByNameAndUserSubscriptionUuid = jest.fn().mockReturnValue(setting)
await createService().applyDefaultSubscriptionSettingsForSubscription(
userSubscription,
SubscriptionName.PlusPlan,
'1-2-3',
)
await createService().applyDefaultSubscriptionSettingsForSubscription(userSubscription)
expect(subscriptionSettingRepository.save).toHaveBeenCalled()
})
@@ -195,11 +235,7 @@ describe('SubscriptionSettingService', () => {
)
subscriptionSettingRepository.findLastByNameAndUserSubscriptionUuid = jest.fn().mockReturnValue(null)
await createService().applyDefaultSubscriptionSettingsForSubscription(
userSubscription,
SubscriptionName.PlusPlan,
'1-2-3',
)
await createService().applyDefaultSubscriptionSettingsForSubscription(userSubscription)
expect(subscriptionSettingRepository.save).toHaveBeenCalledWith(setting)
})
@@ -225,11 +261,7 @@ describe('SubscriptionSettingService', () => {
} as jest.Mocked<UserSubscription>,
])
await createService().applyDefaultSubscriptionSettingsForSubscription(
userSubscription,
SubscriptionName.PlusPlan,
'1-2-3',
)
await createService().applyDefaultSubscriptionSettingsForSubscription(userSubscription)
expect(subscriptionSettingRepository.save).toHaveBeenCalledWith(setting)
})
@@ -239,11 +271,7 @@ describe('SubscriptionSettingService', () => {
.fn()
.mockReturnValue(undefined)
await createService().applyDefaultSubscriptionSettingsForSubscription(
userSubscription,
SubscriptionName.PlusPlan,
'1-2-3',
)
await createService().applyDefaultSubscriptionSettingsForSubscription(userSubscription)
expect(subscriptionSettingRepository.save).not.toHaveBeenCalled()
})
@@ -251,6 +279,7 @@ describe('SubscriptionSettingService', () => {
it("should create setting if it doesn't exist", async () => {
const result = await createService().createOrReplace({
userSubscription,
user,
props: {
name: SettingName.NAMES.FileUploadBytesLimit,
unencryptedValue: 'value',
@@ -266,6 +295,7 @@ describe('SubscriptionSettingService', () => {
await expect(
createService().createOrReplace({
userSubscription,
user,
props: {
name: 'invalid',
unencryptedValue: 'value',
@@ -280,6 +310,7 @@ describe('SubscriptionSettingService', () => {
await expect(
createService().createOrReplace({
userSubscription,
user,
props: {
name: SettingName.NAMES.DropboxBackupFrequency,
unencryptedValue: 'value',
@@ -295,6 +326,7 @@ describe('SubscriptionSettingService', () => {
const result = await createService().createOrReplace({
userSubscription,
user,
props: {
uuid: '1-2-3',
name: SettingName.NAMES.FileUploadBytesLimit,
@@ -312,6 +344,7 @@ describe('SubscriptionSettingService', () => {
const result = await createService().createOrReplace({
userSubscription,
user,
props: {
...setting,
unencryptedValue: 'value',
@@ -327,6 +360,7 @@ describe('SubscriptionSettingService', () => {
const result = await createService().createOrReplace({
userSubscription,
user,
props: {
...setting,
uuid: '1-2-3',

View File

@@ -1,4 +1,3 @@
import { SubscriptionName } from '@standardnotes/common'
import { inject, injectable } from 'inversify'
import { Logger } from 'winston'
@@ -36,17 +35,20 @@ export class SubscriptionSettingService implements SubscriptionSettingServiceInt
async applyDefaultSubscriptionSettingsForSubscription(
userSubscription: UserSubscription,
subscriptionName: SubscriptionName,
userUuid: string,
overrides?: Map<string, string>,
): Promise<void> {
const defaultSettingsWithValues =
await this.subscriptionSettingAssociationService.getDefaultSettingsAndValuesForSubscriptionName(subscriptionName)
await this.subscriptionSettingAssociationService.getDefaultSettingsAndValuesForSubscriptionName(
userSubscription.planName,
)
if (defaultSettingsWithValues === undefined) {
this.logger.warn(`Could not find settings for subscription: ${subscriptionName}`)
this.logger.warn(`Could not find settings for subscription: ${userSubscription.planName}`)
return
}
const user = await userSubscription.user
for (const settingNameString of defaultSettingsWithValues.keys()) {
const settingNameOrError = SettingName.create(settingNameString)
if (settingNameOrError.isFailed()) {
@@ -59,7 +61,11 @@ export class SubscriptionSettingService implements SubscriptionSettingServiceInt
const setting = defaultSettingsWithValues.get(settingName.value) as SettingDescription
if (!setting.replaceable) {
const existingSetting = await this.findPreviousSubscriptionSetting(settingName, userSubscription.uuid, userUuid)
const existingSetting = await this.findPreviousSubscriptionSetting(
settingName,
userSubscription.uuid,
user.uuid,
)
if (existingSetting !== null) {
existingSetting.userSubscription = Promise.resolve(userSubscription)
await this.subscriptionSettingRepository.save(existingSetting)
@@ -68,11 +74,17 @@ export class SubscriptionSettingService implements SubscriptionSettingServiceInt
}
}
let unencryptedValue = setting.value
if (overrides && overrides.has(settingName.value)) {
unencryptedValue = overrides.get(settingName.value) as string
}
await this.createOrReplace({
userSubscription,
user,
props: {
name: settingName.value,
unencryptedValue: setting.value,
unencryptedValue,
serverEncryptionVersion: setting.serverEncryptionVersion,
sensitive: setting.sensitive,
},
@@ -109,7 +121,7 @@ export class SubscriptionSettingService implements SubscriptionSettingServiceInt
async createOrReplace(
dto: CreateOrReplaceSubscriptionSettingDTO,
): Promise<CreateOrReplaceSubscriptionSettingResponse> {
const { userSubscription, props } = dto
const { userSubscription, user, props } = dto
const settingNameOrError = SettingName.create(props.name)
if (settingNameOrError.isFailed()) {
@@ -121,7 +133,6 @@ export class SubscriptionSettingService implements SubscriptionSettingServiceInt
throw new Error(`Setting ${settingName.value} is not a subscription setting`)
}
const user = await userSubscription.user
const existing = await this.findSubscriptionSettingWithDecryptedValue({
userUuid: user.uuid,
userSubscriptionUuid: userSubscription.uuid,

View File

@@ -8,8 +8,7 @@ import { SubscriptionSetting } from './SubscriptionSetting'
export interface SubscriptionSettingServiceInterface {
applyDefaultSubscriptionSettingsForSubscription(
userSubscription: UserSubscription,
subscriptionName: string,
userUuid: string,
overrides?: Map<string, string>,
): Promise<void>
createOrReplace(dto: CreateOrReplaceSubscriptionSettingDTO): Promise<CreateOrReplaceSubscriptionSettingResponse>
findSubscriptionSettingWithDecryptedValue(dto: FindSubscriptionSettingDTO): Promise<SubscriptionSetting | null>

View File

@@ -4,7 +4,7 @@ import { SettingDescription } from './SettingDescription'
export interface SubscriptionSettingsAssociationServiceInterface {
getDefaultSettingsAndValuesForSubscriptionName(
subscriptionName: SubscriptionName,
subscriptionName: string,
): Promise<Map<string, SettingDescription> | undefined>
getFileUploadLimit(subscriptionName: SubscriptionName): Promise<number>
}

View File

@@ -106,8 +106,6 @@ describe('AcceptSharedSubscriptionInvitation', () => {
expect(roleService.addUserRole).toHaveBeenCalledWith(invitee, 'PLUS_PLAN')
expect(subscriptionSettingService.applyDefaultSubscriptionSettingsForSubscription).toHaveBeenCalledWith(
inviteeSubscription,
'PLUS_PLAN',
'123',
)
})
@@ -148,8 +146,6 @@ describe('AcceptSharedSubscriptionInvitation', () => {
expect(roleService.addUserRole).toHaveBeenCalledWith(invitee, 'PLUS_PLAN')
expect(subscriptionSettingService.applyDefaultSubscriptionSettingsForSubscription).toHaveBeenCalledWith(
inviteeSubscription,
'PLUS_PLAN',
'123',
)
})

View File

@@ -92,11 +92,7 @@ export class AcceptSharedSubscriptionInvitation implements UseCaseInterface {
await this.addUserRole(invitee, inviterUserSubscription.planName as SubscriptionName)
await this.subscriptionSettingService.applyDefaultSubscriptionSettingsForSubscription(
inviteeSubscription,
inviteeSubscription.planName as SubscriptionName,
invitee.uuid,
)
await this.subscriptionSettingService.applyDefaultSubscriptionSettingsForSubscription(inviteeSubscription)
return {
success: true,

View File

@@ -5,16 +5,24 @@ import { UserRepositoryInterface } from '../../User/UserRepositoryInterface'
import { ActivatePremiumFeatures } from './ActivatePremiumFeatures'
import { User } from '../../User/User'
import { SubscriptionSettingServiceInterface } from '../../Setting/SubscriptionSettingServiceInterface'
describe('ActivatePremiumFeatures', () => {
let userRepository: UserRepositoryInterface
let userSubscriptionRepository: UserSubscriptionRepositoryInterface
let subscriptionSettingsService: SubscriptionSettingServiceInterface
let roleService: RoleServiceInterface
let timer: TimerInterface
let user: User
const createUseCase = () =>
new ActivatePremiumFeatures(userRepository, userSubscriptionRepository, roleService, timer)
new ActivatePremiumFeatures(
userRepository,
userSubscriptionRepository,
subscriptionSettingsService,
roleService,
timer,
)
beforeEach(() => {
user = {} as jest.Mocked<User>
@@ -32,6 +40,9 @@ describe('ActivatePremiumFeatures', () => {
timer.getTimestampInMicroseconds = jest.fn().mockReturnValue(123456789)
timer.convertDateToMicroseconds = jest.fn().mockReturnValue(123456789)
timer.getUTCDateNDaysAhead = jest.fn().mockReturnValue(new Date('2024-01-01T00:00:00.000Z'))
subscriptionSettingsService = {} as jest.Mocked<SubscriptionSettingServiceInterface>
subscriptionSettingsService.applyDefaultSubscriptionSettingsForSubscription = jest.fn()
})
it('should return error when username is invalid', async () => {
@@ -64,4 +75,28 @@ describe('ActivatePremiumFeatures', () => {
expect(userSubscriptionRepository.save).toHaveBeenCalled()
expect(roleService.addUserRole).toHaveBeenCalled()
})
it('should save a subscription with custom plan name and endsAt', async () => {
const useCase = createUseCase()
const result = await useCase.execute({
username: 'test@test.te',
subscriptionPlanName: 'PRO_PLAN',
endsAt: new Date('2024-01-01T00:00:00.000Z'),
})
expect(result.isFailed()).toBe(false)
})
it('should fail when subscription plan name is invalid', async () => {
const useCase = createUseCase()
const result = await useCase.execute({
username: 'test@test.te',
subscriptionPlanName: 'some invalid plan name',
endsAt: new Date('2024-01-01T00:00:00.000Z'),
})
expect(result.isFailed()).toBe(true)
})
})

View File

@@ -7,11 +7,14 @@ import { UserRepositoryInterface } from '../../User/UserRepositoryInterface'
import { UserSubscription } from '../../Subscription/UserSubscription'
import { UserSubscriptionType } from '../../Subscription/UserSubscriptionType'
import { ActivatePremiumFeaturesDTO } from './ActivatePremiumFeaturesDTO'
import { SubscriptionSettingServiceInterface } from '../../Setting/SubscriptionSettingServiceInterface'
import { SettingName } from '@standardnotes/settings'
export class ActivatePremiumFeatures implements UseCaseInterface<string> {
constructor(
private userRepository: UserRepositoryInterface,
private userSubscriptionRepository: UserSubscriptionRepositoryInterface,
private subscriptionSettingService: SubscriptionSettingServiceInterface,
private roleService: RoleServiceInterface,
private timer: TimerInterface,
) {}
@@ -27,22 +30,35 @@ export class ActivatePremiumFeatures implements UseCaseInterface<string> {
if (user === null) {
return Result.fail(`User not found with username: ${username.value}`)
}
const subscriptionPlanNameString = dto.subscriptionPlanName ?? SubscriptionPlanName.NAMES.ProPlan
const subscriptionPlanNameOrError = SubscriptionPlanName.create(subscriptionPlanNameString)
if (subscriptionPlanNameOrError.isFailed()) {
return Result.fail(subscriptionPlanNameOrError.getError())
}
const subscriptionPlanName = subscriptionPlanNameOrError.getValue()
const timestamp = this.timer.getTimestampInMicroseconds()
const endsAt = dto.endsAt ?? this.timer.getUTCDateNDaysAhead(365)
const subscription = new UserSubscription()
subscription.planName = SubscriptionPlanName.NAMES.ProPlan
subscription.planName = subscriptionPlanName.value
subscription.user = Promise.resolve(user)
subscription.createdAt = timestamp
subscription.updatedAt = timestamp
subscription.endsAt = this.timer.convertDateToMicroseconds(this.timer.getUTCDateNDaysAhead(365))
subscription.endsAt = this.timer.convertDateToMicroseconds(endsAt)
subscription.cancelled = false
subscription.subscriptionId = 1
subscription.subscriptionType = UserSubscriptionType.Regular
await this.userSubscriptionRepository.save(subscription)
await this.roleService.addUserRole(user, SubscriptionPlanName.NAMES.ProPlan)
await this.roleService.addUserRole(user, subscriptionPlanName.value)
await this.subscriptionSettingService.applyDefaultSubscriptionSettingsForSubscription(
subscription,
new Map([[SettingName.NAMES.FileUploadBytesLimit, '-1']]),
)
return Result.ok('Premium features activated.')
}

View File

@@ -1,3 +1,5 @@
export interface ActivatePremiumFeaturesDTO {
username: string
subscriptionPlanName?: string
endsAt?: Date
}

View File

@@ -268,6 +268,7 @@ describe('UpdateSetting', () => {
serverEncryptionVersion: 1,
sensitive: false,
},
user,
userSubscription: regularSubscription,
})
@@ -303,6 +304,7 @@ describe('UpdateSetting', () => {
serverEncryptionVersion: 1,
sensitive: false,
},
user,
userSubscription: sharedSubscription,
})

View File

@@ -91,6 +91,7 @@ export class UpdateSetting implements UseCaseInterface {
const response = await this.subscriptionSettingService.createOrReplace({
userSubscription: subscription,
user,
props,
})

View File

@@ -3,6 +3,18 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.23.1](https://github.com/standardnotes/server/compare/@standardnotes/domain-core@1.23.0...@standardnotes/domain-core@1.23.1) (2023-07-19)
### Bug Fixes
* **syncing-server:** add missing messages and key system identifier sql representations ([#663](https://github.com/standardnotes/server/issues/663)) ([d026152](https://github.com/standardnotes/server/commit/d026152ac8cb2ecda2eee8d3f7385d655b210938))
# [1.23.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-core@1.22.0...@standardnotes/domain-core@1.23.0) (2023-07-17)
### Features
* **syncing-server:** refactor syncing to decouple getting and saving items ([#659](https://github.com/standardnotes/server/issues/659)) ([cb74b23](https://github.com/standardnotes/server/commit/cb74b23e45b207136e299ce8a3db2c04dc87e21e))
# [1.22.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-core@1.21.1...@standardnotes/domain-core@1.22.0) (2023-07-12)
### Features

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/domain-core",
"version": "1.22.0",
"version": "1.23.1",
"engines": {
"node": ">=18.0.0 <21.0.0"
},

View File

@@ -4,10 +4,6 @@ import { UniqueEntityId } from '../Core/UniqueEntityId'
import { CacheEntryProps } from './CacheEntryProps'
export class CacheEntry extends Entity<CacheEntryProps> {
get id(): UniqueEntityId {
return this._id
}
private constructor(props: CacheEntryProps, id?: UniqueEntityId) {
super(props, id)
}

View File

@@ -1,10 +1,5 @@
/* istanbul ignore file */
import { Entity } from './Entity'
import { UniqueEntityId } from './UniqueEntityId'
export abstract class Aggregate<T> extends Entity<T> {
get id(): UniqueEntityId {
return this._id
}
}
export abstract class Aggregate<T> extends Entity<T> {}

View File

@@ -9,6 +9,10 @@ export abstract class Entity<T> {
this._id = id ? id : new UniqueEntityId()
}
get id(): UniqueEntityId {
return this._id
}
public equals(object?: Entity<T>): boolean {
if (object == null || object == undefined) {
return false

View File

@@ -78,4 +78,18 @@ describe('Validator', () => {
expect(Validator.isNotEmpty(value).isFailed()).toBeTruthy()
}
})
describe('is not empty string', () => {
it('should not validate invalid string', () => {
expect(Validator.isNotEmptyString(123 as unknown as string).isFailed()).toBeTruthy()
})
it('should not validate an empty string', () => {
expect(Validator.isNotEmptyString('').isFailed()).toBeTruthy()
})
it('should validate a string', () => {
expect(Validator.isNotEmptyString('foo').isFailed()).toBeFalsy()
})
})
})

View File

@@ -42,4 +42,18 @@ export class Validator {
return Result.ok()
}
static isNotEmptyString(value: unknown): Result<string> {
const isStringResult = Validator.isString(value)
if (isStringResult.isFailed()) {
return isStringResult
}
const isNotEmptyResult = Validator.isNotEmpty(value)
if (isNotEmptyResult.isFailed()) {
return isNotEmptyResult
}
return Result.ok()
}
}

View File

@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.11.8](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.11.7...@standardnotes/event-store@1.11.8) (2023-07-19)
**Note:** Version bump only for package @standardnotes/event-store
## [1.11.7](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.11.6...@standardnotes/event-store@1.11.7) (2023-07-17)
**Note:** Version bump only for package @standardnotes/event-store
## [1.11.6](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.11.5...@standardnotes/event-store@1.11.6) (2023-07-12)
**Note:** Version bump only for package @standardnotes/event-store

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/event-store",
"version": "1.11.6",
"version": "1.11.8",
"description": "Event Store Service",
"private": true,
"main": "dist/src/index.js",

View File

@@ -3,6 +3,24 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.19.10](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.19.9...@standardnotes/files-server@1.19.10) (2023-07-19)
**Note:** Version bump only for package @standardnotes/files-server
## [1.19.9](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.19.8...@standardnotes/files-server@1.19.9) (2023-07-17)
**Note:** Version bump only for package @standardnotes/files-server
## [1.19.8](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.19.7...@standardnotes/files-server@1.19.8) (2023-07-13)
### Bug Fixes
* **files:** handling unlimited storage quota on home server ([9be3517](https://github.com/standardnotes/files/commit/9be3517093f8dd7bbdd7507c1e2ff059e6c9a889))
## [1.19.7](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.19.6...@standardnotes/files-server@1.19.7) (2023-07-12)
**Note:** Version bump only for package @standardnotes/files-server
## [1.19.6](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.19.5...@standardnotes/files-server@1.19.6) (2023-07-12)
**Note:** Version bump only for package @standardnotes/files-server

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/files-server",
"version": "1.19.6",
"version": "1.19.10",
"engines": {
"node": ">=18.0.0 <21.0.0"
},
@@ -35,7 +35,7 @@
"@standardnotes/domain-events": "workspace:*",
"@standardnotes/domain-events-infra": "workspace:*",
"@standardnotes/security": "workspace:*",
"@standardnotes/sncrypto-common": "^1.9.0",
"@standardnotes/sncrypto-common": "^1.13.4",
"@standardnotes/sncrypto-node": "workspace:*",
"@standardnotes/time": "workspace:*",
"connect-busboy": "^1.0.0",

View File

@@ -135,4 +135,27 @@ describe('FinishUploadSession', () => {
expect(fileUploader.finishUploadSession).not.toHaveBeenCalled()
expect(domainEventPublisher.publish).not.toHaveBeenCalled()
})
it('should ignore the storage quota if user has unlimited storage', async () => {
uploadRepository.retrieveUploadChunkResults = jest.fn().mockReturnValue([
{ tag: '123', chunkId: 1, chunkSize: 60 },
{ tag: '234', chunkId: 2, chunkSize: 10 },
{ tag: '345', chunkId: 3, chunkSize: 20 },
])
expect(
await createUseCase().execute({
resourceRemoteIdentifier: '2-3-4',
ownerUuid: '1-2-3',
ownerType: 'user',
uploadBytesLimit: -1,
uploadBytesUsed: 20,
}),
).toEqual({
success: true,
})
expect(fileUploader.finishUploadSession).toHaveBeenCalled()
expect(domainEventPublisher.publish).toHaveBeenCalled()
})
})

View File

@@ -43,8 +43,9 @@ export class FinishUploadSession implements UseCaseInterface {
totalFileSize += uploadChunkResult.chunkSize
}
const userHasUnlimitedStorage = dto.uploadBytesLimit === -1
const remainingSpaceLeft = dto.uploadBytesLimit - dto.uploadBytesUsed
if (remainingSpaceLeft < totalFileSize) {
if (!userHasUnlimitedStorage && remainingSpaceLeft < totalFileSize) {
return {
success: false,
message: 'Could not finish upload session. You are out of space.',

View File

@@ -1,5 +1,6 @@
LOG_LEVEL=debug
NODE_ENV=development
E2E_TESTING=false
JWT_SECRET=
AUTH_JWT_SECRET=

View File

@@ -3,6 +3,52 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [1.13.0](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.12.6...@standardnotes/home-server@1.13.0) (2023-07-19)
### Features
* **syncing-server:** add persistence of shared vaults with users and invites + controllers ([#662](https://github.com/standardnotes/server/issues/662)) ([3f21a35](https://github.com/standardnotes/server/commit/3f21a358d24d70daf541aa62dc86cd9e29500e62))
## [1.12.6](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.12.5...@standardnotes/home-server@1.12.6) (2023-07-18)
**Note:** Version bump only for package @standardnotes/home-server
## [1.12.5](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.12.4...@standardnotes/home-server@1.12.5) (2023-07-18)
**Note:** Version bump only for package @standardnotes/home-server
## [1.12.4](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.12.3...@standardnotes/home-server@1.12.4) (2023-07-17)
**Note:** Version bump only for package @standardnotes/home-server
## [1.12.3](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.12.2...@standardnotes/home-server@1.12.3) (2023-07-14)
### Bug Fixes
* **home-server:** allow custom atributtes for activating premium features ([f7190c0](https://github.com/standardnotes/server/commit/f7190c0c9c2d105f97d1cf980ce6a4f0dae34805))
## [1.12.2](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.12.1...@standardnotes/home-server@1.12.2) (2023-07-13)
**Note:** Version bump only for package @standardnotes/home-server
## [1.12.1](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.12.0...@standardnotes/home-server@1.12.1) (2023-07-13)
**Note:** Version bump only for package @standardnotes/home-server
# [1.12.0](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.11.41...@standardnotes/home-server@1.12.0) (2023-07-13)
### Features
* **home-server:** add activating premium features during an e2e test suite run ([2f0903e](https://github.com/standardnotes/server/commit/2f0903e0ebba95bcf0ece45045dc18e8a988b930))
## [1.11.41](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.11.40...@standardnotes/home-server@1.11.41) (2023-07-12)
**Note:** Version bump only for package @standardnotes/home-server
## [1.11.40](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.11.39...@standardnotes/home-server@1.11.40) (2023-07-12)
**Note:** Version bump only for package @standardnotes/home-server
## [1.11.39](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.11.38...@standardnotes/home-server@1.11.39) (2023-07-12)
**Note:** Version bump only for package @standardnotes/home-server

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/home-server",
"version": "1.11.39",
"version": "1.13.0",
"engines": {
"node": ">=18.0.0 <21.0.0"
},

View File

@@ -138,6 +138,22 @@ export class HomeServer implements HomeServerInterface {
Disallow: '/',
}),
)
if (env.get('E2E_TESTING', true) === 'true') {
app.post('/e2e/activate-premium', (request: Request, response: Response) => {
void this.activatePremiumFeatures({
username: request.body.username,
subscriptionPlanName: request.body.subscriptionPlanName,
endsAt: request.body.endsAt ? new Date(request.body.endsAt) : undefined,
}).then((result) => {
if (result.isFailed()) {
response.status(400).send({ error: { message: result.getError() } })
} else {
response.status(200).send({ message: result.getValue() })
}
})
})
}
})
const logger: winston.Logger = winston.loggers.get('home-server')
@@ -163,6 +179,8 @@ export class HomeServer implements HomeServerInterface {
return Result.ok('Server started.')
} catch (error) {
console.error((error as Error).stack)
return Result.fail((error as Error).message)
}
}
@@ -200,12 +218,16 @@ export class HomeServer implements HomeServerInterface {
return this.serverInstance.address() !== null
}
async activatePremiumFeatures(username: string): Promise<Result<string>> {
async activatePremiumFeatures(dto: {
username: string
subscriptionPlanName?: string
endsAt?: Date
}): Promise<Result<string>> {
if (!this.isRunning() || !this.authService) {
return Result.fail('Home server is not running.')
}
return this.authService.activatePremiumFeatures(username)
return this.authService.activatePremiumFeatures(dto)
}
private configureLoggers(env: Env, configuration: HomeServerConfiguration): void {

View File

@@ -3,7 +3,11 @@ import { HomeServerConfiguration } from './HomeServerConfiguration'
export interface HomeServerInterface {
start(configuration?: HomeServerConfiguration): Promise<Result<string>>
activatePremiumFeatures(username: string): Promise<Result<string>>
activatePremiumFeatures(dto: {
username: string
subscriptionPlanName?: string
endsAt?: Date
}): Promise<Result<string>>
stop(): Promise<Result<string>>
isRunning(): Promise<boolean>
}

View File

@@ -3,6 +3,20 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.25.1](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.25.0...@standardnotes/revisions-server@1.25.1) (2023-07-19)
**Note:** Version bump only for package @standardnotes/revisions-server
# [1.25.0](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.24.1...@standardnotes/revisions-server@1.25.0) (2023-07-17)
### Features
* **syncing-server:** refactor syncing to decouple getting and saving items ([#659](https://github.com/standardnotes/server/issues/659)) ([cb74b23](https://github.com/standardnotes/server/commit/cb74b23e45b207136e299ce8a3db2c04dc87e21e))
## [1.24.1](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.24.0...@standardnotes/revisions-server@1.24.1) (2023-07-12)
**Note:** Version bump only for package @standardnotes/revisions-server
# [1.24.0](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.23.9...@standardnotes/revisions-server@1.24.0) (2023-07-12)
### Features

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/revisions-server",
"version": "1.24.0",
"version": "1.25.1",
"engines": {
"node": ">=18.0.0 <21.0.0"
},
@@ -27,12 +27,12 @@
"dependencies": {
"@aws-sdk/client-s3": "^3.332.0",
"@aws-sdk/client-sqs": "^3.332.0",
"@standardnotes/api": "^1.26.25",
"@standardnotes/api": "^1.26.26",
"@standardnotes/common": "workspace:^",
"@standardnotes/domain-core": "workspace:^",
"@standardnotes/domain-events": "workspace:*",
"@standardnotes/domain-events-infra": "workspace:*",
"@standardnotes/responses": "^1.13.9",
"@standardnotes/responses": "^1.13.27",
"@standardnotes/security": "workspace:^",
"@standardnotes/time": "workspace:^",
"cors": "2.8.5",

View File

@@ -3,10 +3,6 @@ import { Entity, Result, UniqueEntityId } from '@standardnotes/domain-core'
import { RevisionProps } from './RevisionProps'
export class Revision extends Entity<RevisionProps> {
get id(): UniqueEntityId {
return this._id
}
private constructor(props: RevisionProps, id?: UniqueEntityId) {
super(props, id)
}

View File

@@ -3,10 +3,6 @@ import { Entity, Result, UniqueEntityId } from '@standardnotes/domain-core'
import { RevisionMetadataProps } from './RevisionMetadataProps'
export class RevisionMetadata extends Entity<RevisionMetadataProps> {
get id(): UniqueEntityId {
return this._id
}
private constructor(props: RevisionMetadataProps, id?: UniqueEntityId) {
super(props, id)
}

View File

@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.20.10](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.20.9...@standardnotes/scheduler-server@1.20.10) (2023-07-19)
**Note:** Version bump only for package @standardnotes/scheduler-server
## [1.20.9](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.20.8...@standardnotes/scheduler-server@1.20.9) (2023-07-17)
**Note:** Version bump only for package @standardnotes/scheduler-server
## [1.20.8](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.20.7...@standardnotes/scheduler-server@1.20.8) (2023-07-12)
**Note:** Version bump only for package @standardnotes/scheduler-server

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/scheduler-server",
"version": "1.20.8",
"version": "1.20.10",
"engines": {
"node": ">=18.0.0 <21.0.0"
},

View File

@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.21.15](https://github.com/standardnotes/server/compare/@standardnotes/settings@1.21.14...@standardnotes/settings@1.21.15) (2023-07-19)
**Note:** Version bump only for package @standardnotes/settings
## [1.21.14](https://github.com/standardnotes/server/compare/@standardnotes/settings@1.21.13...@standardnotes/settings@1.21.14) (2023-07-17)
**Note:** Version bump only for package @standardnotes/settings
## [1.21.13](https://github.com/standardnotes/server/compare/@standardnotes/settings@1.21.12...@standardnotes/settings@1.21.13) (2023-07-12)
**Note:** Version bump only for package @standardnotes/settings

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/settings",
"version": "1.21.13",
"version": "1.21.15",
"engines": {
"node": ">=18.0.0 <21.0.0"
},

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.15.3](https://github.com/standardnotes/server/compare/@standardnotes/sncrypto-node@1.15.2...@standardnotes/sncrypto-node@1.15.3) (2023-07-12)
**Note:** Version bump only for package @standardnotes/sncrypto-node
## [1.15.2](https://github.com/standardnotes/server/compare/@standardnotes/sncrypto-node@1.15.0...@standardnotes/sncrypto-node@1.15.2) (2023-06-01)
### Bug Fixes

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/sncrypto-node",
"version": "1.15.2",
"version": "1.15.3",
"engines": {
"node": ">=18.0.0 <21.0.0"
},
@@ -23,7 +23,7 @@
"test": "jest spec"
},
"dependencies": {
"@standardnotes/sncrypto-common": "^1.9.0",
"@standardnotes/sncrypto-common": "^1.13.4",
"reflect-metadata": "^0.1.13"
},
"devDependencies": {

View File

@@ -49,3 +49,6 @@ NEW_RELIC_LOG_LEVEL=info
# (Optional) Revision Dumps
FILE_UPLOAD_PATH=
VALET_TOKEN_SECRET=change-me-!
VALET_TOKEN_TTL=7200

View File

@@ -3,6 +3,38 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [1.67.0](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.66.0...@standardnotes/syncing-server@1.67.0) (2023-07-19)
### Bug Fixes
* **syncing-server:** add missing messages and key system identifier sql representations ([#663](https://github.com/standardnotes/syncing-server-js/issues/663)) ([d026152](https://github.com/standardnotes/syncing-server-js/commit/d026152ac8cb2ecda2eee8d3f7385d655b210938))
### Features
* **syncing-server:** add persistence of shared vaults with users and invites + controllers ([#662](https://github.com/standardnotes/syncing-server-js/issues/662)) ([3f21a35](https://github.com/standardnotes/syncing-server-js/commit/3f21a358d24d70daf541aa62dc86cd9e29500e62))
# [1.66.0](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.65.0...@standardnotes/syncing-server@1.66.0) (2023-07-18)
### Features
* **syncing-server:** associating existing items with key systems and shared vaults ([#661](https://github.com/standardnotes/syncing-server-js/issues/661)) ([3b804e2](https://github.com/standardnotes/syncing-server-js/commit/3b804e2321f9d8444722f1d336689e12598121ca))
# [1.65.0](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.64.0...@standardnotes/syncing-server@1.65.0) (2023-07-18)
### Features
* **syncing-server:** persisting shared vault and key system associations ([#660](https://github.com/standardnotes/syncing-server-js/issues/660)) ([479d20e](https://github.com/standardnotes/syncing-server-js/commit/479d20e76f7766006dfa34a0d14401b090dec775))
# [1.64.0](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.63.1...@standardnotes/syncing-server@1.64.0) (2023-07-17)
### Features
* **syncing-server:** refactor syncing to decouple getting and saving items ([#659](https://github.com/standardnotes/syncing-server-js/issues/659)) ([cb74b23](https://github.com/standardnotes/syncing-server-js/commit/cb74b23e45b207136e299ce8a3db2c04dc87e21e))
## [1.63.1](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.63.0...@standardnotes/syncing-server@1.63.1) (2023-07-12)
**Note:** Version bump only for package @standardnotes/syncing-server
# [1.63.0](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.62.1...@standardnotes/syncing-server@1.63.0) (2023-07-12)
### Features

View File

@@ -0,0 +1,25 @@
import { MigrationInterface, QueryRunner } from 'typeorm'
export class AddSharedVaultAndKeySystemAssociations1689671563305 implements MigrationInterface {
name = 'AddSharedVaultAndKeySystemAssociations1689671563305'
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
'CREATE TABLE `shared_vault_associations` (`uuid` varchar(36) NOT NULL, `shared_vault_uuid` varchar(36) NOT NULL, `item_uuid` varchar(36) NOT NULL, `last_edited_by` varchar(36) NOT NULL, `created_at_timestamp` bigint NOT NULL, `updated_at_timestamp` bigint NOT NULL, INDEX `shared_vault_uuid_on_shared_vault_associations` (`shared_vault_uuid`), INDEX `item_uuid_on_shared_vault_associations` (`item_uuid`), PRIMARY KEY (`uuid`)) ENGINE=InnoDB',
)
await queryRunner.query(
'CREATE TABLE `key_system_associations` (`uuid` varchar(36) NOT NULL, `key_system_uuid` varchar(36) NOT NULL, `item_uuid` varchar(36) NOT NULL, `created_at_timestamp` bigint NOT NULL, `updated_at_timestamp` bigint NOT NULL, INDEX `key_system_uuid_on_key_system_associations` (`key_system_uuid`), INDEX `item_uuid_on_key_system_associations` (`item_uuid`), PRIMARY KEY (`uuid`)) ENGINE=InnoDB',
)
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query('DROP INDEX `item_uuid_on_key_system_associations` ON `key_system_associations`')
await queryRunner.query('DROP INDEX `key_system_uuid_on_key_system_associations` ON `key_system_associations`')
await queryRunner.query('DROP TABLE `key_system_associations`')
await queryRunner.query('DROP INDEX `item_uuid_on_shared_vault_associations` ON `shared_vault_associations`')
await queryRunner.query(
'DROP INDEX `shared_vault_uuid_on_shared_vault_associations` ON `shared_vault_associations`',
)
await queryRunner.query('DROP TABLE `shared_vault_associations`')
}
}

View File

@@ -0,0 +1,29 @@
import { MigrationInterface, QueryRunner } from 'typeorm'
export class AddSharedVaultsWithUsersAndInvites1689677728282 implements MigrationInterface {
name = 'AddSharedVaultsWithUsersAndInvites1689677728282'
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
'CREATE TABLE `shared_vaults` (`uuid` varchar(36) NOT NULL, `user_uuid` varchar(36) NOT NULL, `file_upload_bytes_used` int NOT NULL, `file_upload_bytes_limit` int NOT NULL, `created_at_timestamp` bigint NOT NULL, `updated_at_timestamp` bigint NOT NULL, INDEX `user_uuid_on_shared_vaults` (`user_uuid`), PRIMARY KEY (`uuid`)) ENGINE=InnoDB',
)
await queryRunner.query(
'CREATE TABLE `shared_vault_users` (`uuid` varchar(36) NOT NULL, `shared_vault_uuid` varchar(36) NOT NULL, `user_uuid` varchar(36) NOT NULL, `permission` varchar(24) NOT NULL, `created_at_timestamp` bigint NOT NULL, `updated_at_timestamp` bigint NOT NULL, INDEX `shared_vault_uuid_on_shared_vault_users` (`shared_vault_uuid`), INDEX `user_uuid_on_shared_vault_users` (`user_uuid`), PRIMARY KEY (`uuid`)) ENGINE=InnoDB',
)
await queryRunner.query(
'CREATE TABLE `shared_vault_invites` (`uuid` varchar(36) NOT NULL, `shared_vault_uuid` varchar(36) NOT NULL, `user_uuid` varchar(36) NOT NULL, `sender_uuid` varchar(36) NOT NULL, `encrypted_message` text NOT NULL, `permission` varchar(24) NOT NULL, `created_at_timestamp` bigint NOT NULL, `updated_at_timestamp` bigint NOT NULL, INDEX `shared_vault_uuid_on_shared_vault_invites` (`shared_vault_uuid`), INDEX `user_uuid_on_shared_vault_invites` (`user_uuid`), INDEX `sender_uuid_on_shared_vault_invites` (`sender_uuid`), PRIMARY KEY (`uuid`)) ENGINE=InnoDB',
)
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query('DROP INDEX `sender_uuid_on_shared_vault_invites` ON `shared_vault_invites`')
await queryRunner.query('DROP INDEX `user_uuid_on_shared_vault_invites` ON `shared_vault_invites`')
await queryRunner.query('DROP INDEX `shared_vault_uuid_on_shared_vault_invites` ON `shared_vault_invites`')
await queryRunner.query('DROP TABLE `shared_vault_invites`')
await queryRunner.query('DROP INDEX `user_uuid_on_shared_vault_users` ON `shared_vault_users`')
await queryRunner.query('DROP INDEX `shared_vault_uuid_on_shared_vault_users` ON `shared_vault_users`')
await queryRunner.query('DROP TABLE `shared_vault_users`')
await queryRunner.query('DROP INDEX `user_uuid_on_shared_vaults` ON `shared_vaults`')
await queryRunner.query('DROP TABLE `shared_vaults`')
}
}

View File

@@ -0,0 +1,17 @@
import { MigrationInterface, QueryRunner } from 'typeorm'
export class AddMessages1689745128577 implements MigrationInterface {
name = 'AddMessages1689745128577'
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
'CREATE TABLE `messages` (`uuid` varchar(36) NOT NULL, `recipient_uuid` varchar(36) NOT NULL, `sender_uuid` varchar(36) NOT NULL, `encrypted_message` text NOT NULL, `replaceability_identifier` varchar(255) NULL, `created_at_timestamp` bigint NOT NULL, `updated_at_timestamp` bigint NOT NULL, INDEX `recipient_uuid_on_messages` (`recipient_uuid`), INDEX `sender_uuid_on_messages` (`sender_uuid`), PRIMARY KEY (`uuid`)) ENGINE=InnoDB',
)
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query('DROP INDEX `sender_uuid_on_messages` ON `messages`')
await queryRunner.query('DROP INDEX `recipient_uuid_on_messages` ON `messages`')
await queryRunner.query('DROP TABLE `messages`')
}
}

View File

@@ -0,0 +1,27 @@
import { MigrationInterface, QueryRunner } from 'typeorm'
export class RenameKeyMessageIdentifier1689746180559 implements MigrationInterface {
name = 'RenameKeyMessageIdentifier1689746180559'
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query('DROP INDEX `key_system_uuid_on_key_system_associations` ON `key_system_associations`')
await queryRunner.query(
'ALTER TABLE `key_system_associations` CHANGE `key_system_uuid` `key_system_identifier` varchar(36) NOT NULL',
)
await queryRunner.query(
'CREATE INDEX `key_system_identifier_on_key_system_associations` ON `key_system_associations` (`key_system_identifier`)',
)
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
'DROP INDEX `key_system_identifier_on_key_system_associations` ON `key_system_associations`',
)
await queryRunner.query(
'ALTER TABLE `key_system_associations` CHANGE `key_system_identifier` `key_system_uuid` varchar(36) NOT NULL',
)
await queryRunner.query(
'CREATE INDEX `key_system_uuid_on_key_system_associations` ON `key_system_associations` (`key_system_uuid`)',
)
}
}

View File

@@ -0,0 +1,35 @@
import { MigrationInterface, QueryRunner } from 'typeorm'
export class AddSharedVaultAndKeySystemAssociations1689672099829 implements MigrationInterface {
name = 'AddSharedVaultAndKeySystemAssociations1689672099829'
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
'CREATE TABLE "shared_vault_associations" ("uuid" varchar PRIMARY KEY NOT NULL, "shared_vault_uuid" varchar(36) NOT NULL, "item_uuid" varchar(36) NOT NULL, "last_edited_by" varchar(36) NOT NULL, "created_at_timestamp" bigint NOT NULL, "updated_at_timestamp" bigint NOT NULL)',
)
await queryRunner.query(
'CREATE INDEX "shared_vault_uuid_on_shared_vault_associations" ON "shared_vault_associations" ("shared_vault_uuid") ',
)
await queryRunner.query(
'CREATE INDEX "item_uuid_on_shared_vault_associations" ON "shared_vault_associations" ("item_uuid") ',
)
await queryRunner.query(
'CREATE TABLE "key_system_associations" ("uuid" varchar PRIMARY KEY NOT NULL, "key_system_uuid" varchar(36) NOT NULL, "item_uuid" varchar(36) NOT NULL, "created_at_timestamp" bigint NOT NULL, "updated_at_timestamp" bigint NOT NULL)',
)
await queryRunner.query(
'CREATE INDEX "key_system_uuid_on_key_system_associations" ON "key_system_associations" ("key_system_uuid") ',
)
await queryRunner.query(
'CREATE INDEX "item_uuid_on_key_system_associations" ON "key_system_associations" ("item_uuid") ',
)
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query('DROP INDEX "item_uuid_on_key_system_associations"')
await queryRunner.query('DROP INDEX "key_system_uuid_on_key_system_associations"')
await queryRunner.query('DROP TABLE "key_system_associations"')
await queryRunner.query('DROP INDEX "item_uuid_on_shared_vault_associations"')
await queryRunner.query('DROP INDEX "shared_vault_uuid_on_shared_vault_associations"')
await queryRunner.query('DROP TABLE "shared_vault_associations"')
}
}

View File

@@ -0,0 +1,41 @@
import { MigrationInterface, QueryRunner } from 'typeorm'
export class AddSharedVaultsWithUsersAndInvites1689677867175 implements MigrationInterface {
name = 'AddSharedVaultsWithUsersAndInvites1689677867175'
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
'CREATE TABLE "shared_vaults" ("uuid" varchar PRIMARY KEY NOT NULL, "user_uuid" varchar(36) NOT NULL, "file_upload_bytes_used" integer NOT NULL, "file_upload_bytes_limit" integer NOT NULL, "created_at_timestamp" bigint NOT NULL, "updated_at_timestamp" bigint NOT NULL)',
)
await queryRunner.query('CREATE INDEX "user_uuid_on_shared_vaults" ON "shared_vaults" ("user_uuid") ')
await queryRunner.query(
'CREATE TABLE "shared_vault_users" ("uuid" varchar PRIMARY KEY NOT NULL, "shared_vault_uuid" varchar(36) NOT NULL, "user_uuid" varchar(36) NOT NULL, "permission" varchar(24) NOT NULL, "created_at_timestamp" bigint NOT NULL, "updated_at_timestamp" bigint NOT NULL)',
)
await queryRunner.query(
'CREATE INDEX "shared_vault_uuid_on_shared_vault_users" ON "shared_vault_users" ("shared_vault_uuid") ',
)
await queryRunner.query('CREATE INDEX "user_uuid_on_shared_vault_users" ON "shared_vault_users" ("user_uuid") ')
await queryRunner.query(
'CREATE TABLE "shared_vault_invites" ("uuid" varchar PRIMARY KEY NOT NULL, "shared_vault_uuid" varchar(36) NOT NULL, "user_uuid" varchar(36) NOT NULL, "sender_uuid" varchar(36) NOT NULL, "encrypted_message" text NOT NULL, "permission" varchar(24) NOT NULL, "created_at_timestamp" bigint NOT NULL, "updated_at_timestamp" bigint NOT NULL)',
)
await queryRunner.query(
'CREATE INDEX "shared_vault_uuid_on_shared_vault_invites" ON "shared_vault_invites" ("shared_vault_uuid") ',
)
await queryRunner.query('CREATE INDEX "user_uuid_on_shared_vault_invites" ON "shared_vault_invites" ("user_uuid") ')
await queryRunner.query(
'CREATE INDEX "sender_uuid_on_shared_vault_invites" ON "shared_vault_invites" ("sender_uuid") ',
)
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query('DROP INDEX "sender_uuid_on_shared_vault_invites"')
await queryRunner.query('DROP INDEX "user_uuid_on_shared_vault_invites"')
await queryRunner.query('DROP INDEX "shared_vault_uuid_on_shared_vault_invites"')
await queryRunner.query('DROP TABLE "shared_vault_invites"')
await queryRunner.query('DROP INDEX "user_uuid_on_shared_vault_users"')
await queryRunner.query('DROP INDEX "shared_vault_uuid_on_shared_vault_users"')
await queryRunner.query('DROP TABLE "shared_vault_users"')
await queryRunner.query('DROP INDEX "user_uuid_on_shared_vaults"')
await queryRunner.query('DROP TABLE "shared_vaults"')
}
}

View File

@@ -0,0 +1,19 @@
import { MigrationInterface, QueryRunner } from 'typeorm'
export class AddMessages1689744778643 implements MigrationInterface {
name = 'AddMessages1689744778643'
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
'CREATE TABLE "messages" ("uuid" varchar PRIMARY KEY NOT NULL, "recipient_uuid" varchar(36) NOT NULL, "sender_uuid" varchar(36) NOT NULL, "encrypted_message" text NOT NULL, "replaceability_identifier" varchar(255), "created_at_timestamp" bigint NOT NULL, "updated_at_timestamp" bigint NOT NULL)',
)
await queryRunner.query('CREATE INDEX "recipient_uuid_on_messages" ON "messages" ("recipient_uuid") ')
await queryRunner.query('CREATE INDEX "sender_uuid_on_messages" ON "messages" ("sender_uuid") ')
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query('DROP INDEX "sender_uuid_on_messages"')
await queryRunner.query('DROP INDEX "recipient_uuid_on_messages"')
await queryRunner.query('DROP TABLE "messages"')
}
}

View File

@@ -0,0 +1,43 @@
import { MigrationInterface, QueryRunner } from 'typeorm'
export class RenameKeyMessageIdentifier1689746527310 implements MigrationInterface {
name = 'RenameKeyMessageIdentifier1689746527310'
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query('DROP INDEX "key_system_uuid_on_key_system_associations"')
await queryRunner.query('DROP INDEX "item_uuid_on_key_system_associations"')
await queryRunner.query(
'CREATE TABLE "temporary_key_system_associations" ("uuid" varchar PRIMARY KEY NOT NULL, "key_system_identifier" varchar(36) NOT NULL, "item_uuid" varchar(36) NOT NULL, "created_at_timestamp" bigint NOT NULL, "updated_at_timestamp" bigint NOT NULL)',
)
await queryRunner.query(
'INSERT INTO "temporary_key_system_associations"("uuid", "key_system_identifier", "item_uuid", "created_at_timestamp", "updated_at_timestamp") SELECT "uuid", "key_system_uuid", "item_uuid", "created_at_timestamp", "updated_at_timestamp" FROM "key_system_associations"',
)
await queryRunner.query('DROP TABLE "key_system_associations"')
await queryRunner.query('ALTER TABLE "temporary_key_system_associations" RENAME TO "key_system_associations"')
await queryRunner.query(
'CREATE INDEX "item_uuid_on_key_system_associations" ON "key_system_associations" ("item_uuid") ',
)
await queryRunner.query(
'CREATE INDEX "key_system_identifier_on_key_system_associations" ON "key_system_associations" ("key_system_identifier") ',
)
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query('DROP INDEX "key_system_identifier_on_key_system_associations"')
await queryRunner.query('DROP INDEX "item_uuid_on_key_system_associations"')
await queryRunner.query('ALTER TABLE "key_system_associations" RENAME TO "temporary_key_system_associations"')
await queryRunner.query(
'CREATE TABLE "key_system_associations" ("uuid" varchar PRIMARY KEY NOT NULL, "key_system_uuid" varchar(36) NOT NULL, "item_uuid" varchar(36) NOT NULL, "created_at_timestamp" bigint NOT NULL, "updated_at_timestamp" bigint NOT NULL)',
)
await queryRunner.query(
'INSERT INTO "key_system_associations"("uuid", "key_system_uuid", "item_uuid", "created_at_timestamp", "updated_at_timestamp") SELECT "uuid", "key_system_identifier", "item_uuid", "created_at_timestamp", "updated_at_timestamp" FROM "temporary_key_system_associations"',
)
await queryRunner.query('DROP TABLE "temporary_key_system_associations"')
await queryRunner.query(
'CREATE INDEX "item_uuid_on_key_system_associations" ON "key_system_associations" ("item_uuid") ',
)
await queryRunner.query(
'CREATE INDEX "key_system_uuid_on_key_system_associations" ON "key_system_associations" ("key_system_uuid") ',
)
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/syncing-server",
"version": "1.63.0",
"version": "1.67.0",
"engines": {
"node": ">=18.0.0 <21.0.0"
},
@@ -31,12 +31,12 @@
"@aws-sdk/client-s3": "^3.332.0",
"@aws-sdk/client-sns": "^3.332.0",
"@aws-sdk/client-sqs": "^3.332.0",
"@standardnotes/api": "^1.26.25",
"@standardnotes/api": "^1.26.26",
"@standardnotes/common": "workspace:*",
"@standardnotes/domain-core": "workspace:^",
"@standardnotes/domain-events": "workspace:*",
"@standardnotes/domain-events-infra": "workspace:*",
"@standardnotes/responses": "^1.13.9",
"@standardnotes/responses": "^1.13.27",
"@standardnotes/security": "workspace:*",
"@standardnotes/settings": "workspace:*",
"@standardnotes/sncrypto-node": "workspace:*",

View File

@@ -23,8 +23,6 @@ import { Timer, TimerInterface } from '@standardnotes/time'
import { ItemTransferCalculatorInterface } from '../Domain/Item/ItemTransferCalculatorInterface'
import { ItemTransferCalculator } from '../Domain/Item/ItemTransferCalculator'
import { ItemConflict } from '../Domain/Item/ItemConflict'
import { ItemService } from '../Domain/Item/ItemService'
import { ItemServiceInterface } from '../Domain/Item/ItemServiceInterface'
import { ContentFilter } from '../Domain/Item/SaveRule/ContentFilter'
import { ContentTypeFilter } from '../Domain/Item/SaveRule/ContentTypeFilter'
import { OwnershipFilter } from '../Domain/Item/SaveRule/OwnershipFilter'
@@ -75,6 +73,80 @@ import { ItemBackupRepresentation } from '../Mapping/Backup/ItemBackupRepresenta
import { ItemBackupMapper } from '../Mapping/Backup/ItemBackupMapper'
import { SaveNewItem } from '../Domain/UseCase/Syncing/SaveNewItem/SaveNewItem'
import { UpdateExistingItem } from '../Domain/UseCase/Syncing/UpdateExistingItem/UpdateExistingItem'
import { GetItems } from '../Domain/UseCase/Syncing/GetItems/GetItems'
import { SaveItems } from '../Domain/UseCase/Syncing/SaveItems/SaveItems'
import { ItemHashHttpMapper } from '../Mapping/Http/ItemHashHttpMapper'
import { ItemHash } from '../Domain/Item/ItemHash'
import { ItemHashHttpRepresentation } from '../Mapping/Http/ItemHashHttpRepresentation'
import { TypeORMKeySystemAssociation } from '../Infra/TypeORM/TypeORMKeySystemAssociation'
import { SharedVaultAssociation } from '../Domain/SharedVault/SharedVaultAssociation'
import { TypeORMSharedVaultAssociation } from '../Infra/TypeORM/TypeORMSharedVaultAssociation'
import { SharedVaultAssociationPersistenceMapper } from '../Mapping/Persistence/SharedVaultAssociationPersistenceMapper'
import { TypeORMKeySystemAssociationRepository } from '../Infra/TypeORM/TypeORMKeySystemAssociationRepository'
import { SharedVaultAssociationRepositoryInterface } from '../Domain/SharedVault/SharedVaultAssociationRepositoryInterface'
import { TypeORMSharedVaultAssociationRepository } from '../Infra/TypeORM/TypeORMSharedVaultAssociationRepository'
import { KeySystemAssociation } from '../Domain/KeySystem/KeySystemAssociation'
import { KeySystemAssociationRepositoryInterface } from '../Domain/KeySystem/KeySystemAssociationRepositoryInterface'
import { KeySystemAssociationPersistenceMapper } from '../Mapping/Persistence/KeySystemAssociationPersistenceMapper'
import { HomeServerSharedVaultInvitesController } from '../Infra/InversifyExpressUtils/HomeServer/HomeServerSharedVaultInvitesController'
import { InviteUserToSharedVault } from '../Domain/UseCase/SharedVaults/InviteUserToSharedVault/InviteUserToSharedVault'
import { TypeORMSharedVaultRepository } from '../Infra/TypeORM/TypeORMSharedVaultRepository'
import { TypeORMSharedVault } from '../Infra/TypeORM/TypeORMSharedVault'
import { TypeORMSharedVaultInvite } from '../Infra/TypeORM/TypeORMSharedVaultInvite'
import { TypeORMSharedVaultUser } from '../Infra/TypeORM/TypeORMSharedVaultUser'
import { SharedVaultRepositoryInterface } from '../Domain/SharedVault/SharedVaultRepositoryInterface'
import { SharedVaultPersistenceMapper } from '../Mapping/Persistence/SharedVaultPersistenceMapper'
import { SharedVault } from '../Domain/SharedVault/SharedVault'
import { SharedVaultUser } from '../Domain/SharedVault/User/SharedVaultUser'
import { SharedVaultUserPersistenceMapper } from '../Mapping/Persistence/SharedVaultUserPersistenceMapper'
import { SharedVaultInvite } from '../Domain/SharedVault/User/Invite/SharedVaultInvite'
import { SharedVaultInvitePersistenceMapper } from '../Mapping/Persistence/SharedVaultInvitePersistenceMapper'
import { SharedVaultUserRepositoryInterface } from '../Domain/SharedVault/User/SharedVaultUserRepositoryInterface'
import { TypeORMSharedVaultUserRepository } from '../Infra/TypeORM/TypeORMSharedVaultUserRepository'
import { SharedVaultInviteRepositoryInterface } from '../Domain/SharedVault/User/Invite/SharedVaultInviteRepositoryInterface'
import { TypeORMSharedVaultInviteRepository } from '../Infra/TypeORM/TypeORMSharedVaultInviteRepository'
import { UpdateSharedVaultInvite } from '../Domain/UseCase/SharedVaults/UpdateSharedVaultInvite/UpdateSharedVaultInvite'
import { AcceptInviteToSharedVault } from '../Domain/UseCase/SharedVaults/AcceptInviteToSharedVault/AcceptInviteToSharedVault'
import { AddUserToSharedVault } from '../Domain/UseCase/SharedVaults/AddUserToSharedVault/AddUserToSharedVault'
import { DeclineInviteToSharedVault } from '../Domain/UseCase/SharedVaults/DeclineInviteToSharedVault/DeclineInviteToSharedVault'
import { DeleteSharedVaultInvitesToUser } from '../Domain/UseCase/SharedVaults/DeleteSharedVaultInvitesToUser/DeleteSharedVaultInvitesToUser'
import { DeleteSharedVaultInvitesSentByUser } from '../Domain/UseCase/SharedVaults/DeleteSharedVaultInvitesSentByUser/DeleteSharedVaultInvitesSentByUser'
import { GetSharedVaultInvitesSentByUser } from '../Domain/UseCase/SharedVaults/GetSharedVaultInvitesSentByUser/GetSharedVaultInvitesSentByUser'
import { GetSharedVaultInvitesSentToUser } from '../Domain/UseCase/SharedVaults/GetSharedVaultInvitesSentToUser/GetSharedVaultInvitesSentToUser'
import { HomeServerSharedVaultUsersController } from '../Infra/InversifyExpressUtils/HomeServer/HomeServerSharedVaultUsersController'
import { GetSharedVaultUsers } from '../Domain/UseCase/SharedVaults/GetSharedVaultUsers/GetSharedVaultUsers'
import { RemoveUserFromSharedVault } from '../Domain/UseCase/SharedVaults/RemoveUserFromSharedVault/RemoveUserFromSharedVault'
import { AddNotificationForUser } from '../Domain/UseCase/Messaging/AddNotificationForUser/AddNotificationForUser'
import { TypeORMNotification } from '../Infra/TypeORM/TypeORMNotification'
import { NotificationRepositoryInterface } from '../Domain/Notifications/NotificationRepositoryInterface'
import { TypeORMNotificationRepository } from '../Infra/TypeORM/TypeORMNotificationRepository'
import { NotificationPersistenceMapper } from '../Mapping/Persistence/NotificationPersistenceMapper'
import { Notification } from '../Domain/Notifications/Notification'
import { SharedVaultUserHttpRepresentation } from '../Mapping/Http/SharedVaultUserHttpRepresentation'
import { SharedVaultUserHttpMapper } from '../Mapping/Http/SharedVaultUserHttpMapper'
import { HomeServerSharedVaultsController } from '../Infra/InversifyExpressUtils/HomeServer/HomeServerSharedVaultsController'
import { GetSharedVaults } from '../Domain/UseCase/SharedVaults/GetSharedVaults/GetSharedVaults'
import { CreateSharedVault } from '../Domain/UseCase/SharedVaults/CreateSharedVault/CreateSharedVault'
import { DeleteSharedVault } from '../Domain/UseCase/SharedVaults/DeleteSharedVault/DeleteSharedVault'
import { CreateSharedVaultFileValetToken } from '../Domain/UseCase/SharedVaults/CreateSharedVaultFileValetToken/CreateSharedVaultFileValetToken'
import { SharedVaultValetTokenData, TokenEncoder, TokenEncoderInterface } from '@standardnotes/security'
import { SharedVaultHttpRepresentation } from '../Mapping/Http/SharedVaultHttpRepresentation'
import { SharedVaultHttpMapper } from '../Mapping/Http/SharedVaultHttpMapper'
import { SharedVaultInviteHttpRepresentation } from '../Mapping/Http/SharedVaultInviteHttpRepresentation'
import { SharedVaultInviteHttpMapper } from '../Mapping/Http/SharedVaultInviteHttpMapper'
import { HomeServerMessagesController } from '../Infra/InversifyExpressUtils/HomeServer/HomeServerMessagesController'
import { GetMessagesSentToUser } from '../Domain/UseCase/Messaging/GetMessagesSentToUser/GetMessagesSentToUser'
import { TypeORMMessage } from '../Infra/TypeORM/TypeORMMessage'
import { MessageRepositoryInterface } from '../Domain/Message/MessageRepositoryInterface'
import { TypeORMMessageRepository } from '../Infra/TypeORM/TypeORMMessageRepository'
import { Message } from '../Domain/Message/Message'
import { MessagePersistenceMapper } from '../Mapping/Persistence/MessagePersistenceMapper'
import { GetMessagesSentByUser } from '../Domain/UseCase/Messaging/GetMessagesSentByUser/GetMessagesSentByUser'
import { SendMessageToUser } from '../Domain/UseCase/Messaging/SendMessageToUser/SendMessageToUser'
import { DeleteAllMessagesSentToUser } from '../Domain/UseCase/Messaging/DeleteAllMessagesSentToUser/DeleteAllMessagesSentToUser'
import { DeleteMessage } from '../Domain/UseCase/Messaging/DeleteMessage/DeleteMessage'
import { MessageHttpRepresentation } from '../Mapping/Http/MessageHttpRepresentation'
import { MessageHttpMapper } from '../Mapping/Http/MessageHttpMapper'
export class ContainerConfigLoader {
private readonly DEFAULT_CONTENT_SIZE_TRANSFER_LIMIT = 10_000_000
@@ -209,6 +281,9 @@ export class ContainerConfigLoader {
container
.bind<MapperInterface<Item, TypeORMItem>>(TYPES.Sync_ItemPersistenceMapper)
.toConstantValue(new ItemPersistenceMapper())
container
.bind<MapperInterface<ItemHash, ItemHashHttpRepresentation>>(TYPES.Sync_ItemHashHttpMapper)
.toConstantValue(new ItemHashHttpMapper())
container
.bind<MapperInterface<Item, ItemHttpRepresentation>>(TYPES.Sync_ItemHttpMapper)
.toConstantValue(new ItemHttpMapper(container.get(TYPES.Sync_Timer)))
@@ -217,23 +292,146 @@ export class ContainerConfigLoader {
.toConstantValue(new SavedItemHttpMapper(container.get(TYPES.Sync_Timer)))
container
.bind<MapperInterface<ItemConflict, ItemConflictHttpRepresentation>>(TYPES.Sync_ItemConflictHttpMapper)
.toConstantValue(new ItemConflictHttpMapper(container.get(TYPES.Sync_ItemHttpMapper)))
.toConstantValue(
new ItemConflictHttpMapper(
container.get(TYPES.Sync_ItemHttpMapper),
container.get(TYPES.Sync_ItemHashHttpMapper),
),
)
container
.bind<MapperInterface<Item, ItemBackupRepresentation>>(TYPES.Sync_ItemBackupMapper)
.toConstantValue(new ItemBackupMapper(container.get(TYPES.Sync_Timer)))
container
.bind<MapperInterface<KeySystemAssociation, TypeORMKeySystemAssociation>>(
TYPES.Sync_KeySystemAssociationPersistenceMapper,
)
.toConstantValue(new KeySystemAssociationPersistenceMapper())
container
.bind<MapperInterface<SharedVaultAssociation, TypeORMSharedVaultAssociation>>(
TYPES.Sync_SharedVaultAssociationPersistenceMapper,
)
.toConstantValue(new SharedVaultAssociationPersistenceMapper())
container
.bind<MapperInterface<SharedVault, TypeORMSharedVault>>(TYPES.Sync_SharedVaultPersistenceMapper)
.toConstantValue(new SharedVaultPersistenceMapper())
container
.bind<MapperInterface<SharedVaultUser, TypeORMSharedVaultUser>>(TYPES.Sync_SharedVaultUserPersistenceMapper)
.toConstantValue(new SharedVaultUserPersistenceMapper())
container
.bind<MapperInterface<SharedVaultInvite, TypeORMSharedVaultInvite>>(TYPES.Sync_SharedVaultInvitePersistenceMapper)
.toConstantValue(new SharedVaultInvitePersistenceMapper())
container
.bind<MapperInterface<Notification, TypeORMNotification>>(TYPES.Sync_NotificationPersistenceMapper)
.toConstantValue(new NotificationPersistenceMapper())
container
.bind<MapperInterface<SharedVaultUser, SharedVaultUserHttpRepresentation>>(TYPES.Sync_SharedVaultUserHttpMapper)
.toConstantValue(new SharedVaultUserHttpMapper())
container
.bind<MapperInterface<SharedVault, SharedVaultHttpRepresentation>>(TYPES.Sync_SharedVaultHttpMapper)
.toConstantValue(new SharedVaultHttpMapper())
container
.bind<MapperInterface<SharedVaultInvite, SharedVaultInviteHttpRepresentation>>(
TYPES.Sync_SharedVaultInviteHttpMapper,
)
.toConstantValue(new SharedVaultInviteHttpMapper())
container
.bind<MapperInterface<Message, TypeORMMessage>>(TYPES.Sync_MessagePersistenceMapper)
.toConstantValue(new MessagePersistenceMapper())
container
.bind<MapperInterface<Message, MessageHttpRepresentation>>(TYPES.Sync_MessageHttpMapper)
.toConstantValue(new MessageHttpMapper())
// ORM
container
.bind<Repository<TypeORMItem>>(TYPES.Sync_ORMItemRepository)
.toDynamicValue(() => appDataSource.getRepository(TypeORMItem))
container
.bind<Repository<TypeORMSharedVaultAssociation>>(TYPES.Sync_ORMSharedVaultAssociationRepository)
.toConstantValue(appDataSource.getRepository(TypeORMSharedVaultAssociation))
container
.bind<Repository<TypeORMKeySystemAssociation>>(TYPES.Sync_ORMKeySystemAssociationRepository)
.toConstantValue(appDataSource.getRepository(TypeORMKeySystemAssociation))
container
.bind<Repository<TypeORMSharedVault>>(TYPES.Sync_ORMSharedVaultRepository)
.toConstantValue(appDataSource.getRepository(TypeORMSharedVault))
container
.bind<Repository<TypeORMSharedVaultInvite>>(TYPES.Sync_ORMSharedVaultInviteRepository)
.toConstantValue(appDataSource.getRepository(TypeORMSharedVaultInvite))
container
.bind<Repository<TypeORMSharedVaultUser>>(TYPES.Sync_ORMSharedVaultUserRepository)
.toConstantValue(appDataSource.getRepository(TypeORMSharedVaultUser))
container
.bind<Repository<TypeORMNotification>>(TYPES.Sync_ORMNotificationRepository)
.toConstantValue(appDataSource.getRepository(TypeORMNotification))
container
.bind<Repository<TypeORMMessage>>(TYPES.Sync_ORMMessageRepository)
.toConstantValue(appDataSource.getRepository(TypeORMMessage))
// Repositories
container
.bind<KeySystemAssociationRepositoryInterface>(TYPES.Sync_KeySystemAssociationRepository)
.toConstantValue(
new TypeORMKeySystemAssociationRepository(
container.get(TYPES.Sync_ORMKeySystemAssociationRepository),
container.get(TYPES.Sync_KeySystemAssociationPersistenceMapper),
),
)
container
.bind<SharedVaultAssociationRepositoryInterface>(TYPES.Sync_SharedVaultAssociationRepository)
.toConstantValue(
new TypeORMSharedVaultAssociationRepository(
container.get(TYPES.Sync_ORMSharedVaultAssociationRepository),
container.get(TYPES.Sync_SharedVaultAssociationPersistenceMapper),
),
)
container
.bind<ItemRepositoryInterface>(TYPES.Sync_ItemRepository)
.toConstantValue(
new TypeORMItemRepository(
container.get(TYPES.Sync_ORMItemRepository),
container.get(TYPES.Sync_ItemPersistenceMapper),
container.get(TYPES.Sync_KeySystemAssociationRepository),
container.get(TYPES.Sync_SharedVaultAssociationRepository),
),
)
container
.bind<SharedVaultRepositoryInterface>(TYPES.Sync_SharedVaultRepository)
.toConstantValue(
new TypeORMSharedVaultRepository(
container.get(TYPES.Sync_ORMSharedVaultRepository),
container.get(TYPES.Sync_SharedVaultPersistenceMapper),
),
)
container
.bind<SharedVaultUserRepositoryInterface>(TYPES.Sync_SharedVaultUserRepository)
.toConstantValue(
new TypeORMSharedVaultUserRepository(
container.get(TYPES.Sync_ORMSharedVaultUserRepository),
container.get(TYPES.Sync_SharedVaultUserPersistenceMapper),
),
)
container
.bind<SharedVaultInviteRepositoryInterface>(TYPES.Sync_SharedVaultInviteRepository)
.toConstantValue(
new TypeORMSharedVaultInviteRepository(
container.get(TYPES.Sync_ORMSharedVaultInviteRepository),
container.get(TYPES.Sync_SharedVaultInvitePersistenceMapper),
),
)
container
.bind<NotificationRepositoryInterface>(TYPES.Sync_NotificationRepository)
.toConstantValue(
new TypeORMNotificationRepository(
container.get(TYPES.Sync_ORMNotificationRepository),
container.get(TYPES.Sync_NotificationPersistenceMapper),
),
)
container
.bind<MessageRepositoryInterface>(TYPES.Sync_MessageRepository)
.toConstantValue(
new TypeORMMessageRepository(
container.get(TYPES.Sync_ORMMessageRepository),
container.get(TYPES.Sync_MessagePersistenceMapper),
),
)
@@ -281,17 +479,44 @@ export class ContainerConfigLoader {
.toConstantValue(
env.get('MAX_ITEMS_LIMIT', true) ? +env.get('MAX_ITEMS_LIMIT', true) : this.DEFAULT_MAX_ITEMS_LIMIT,
)
container.bind(TYPES.Sync_VALET_TOKEN_SECRET).toConstantValue(env.get('VALET_TOKEN_SECRET', true))
container
.bind(TYPES.Sync_VALET_TOKEN_TTL)
.toConstantValue(env.get('VALET_TOKEN_TTL', true) ? +env.get('VALET_TOKEN_TTL', true) : 7200)
container
.bind<TokenEncoderInterface<SharedVaultValetTokenData>>(TYPES.Sync_SharedVaultValetTokenEncoder)
.toConstantValue(new TokenEncoder<SharedVaultValetTokenData>(container.get(TYPES.Sync_VALET_TOKEN_SECRET)))
container.bind<OwnershipFilter>(TYPES.Sync_OwnershipFilter).toConstantValue(new OwnershipFilter())
container
.bind<TimeDifferenceFilter>(TYPES.Sync_TimeDifferenceFilter)
.toConstantValue(new TimeDifferenceFilter(container.get(TYPES.Sync_Timer)))
container.bind<ContentTypeFilter>(TYPES.Sync_ContentTypeFilter).toConstantValue(new ContentTypeFilter())
container.bind<ContentFilter>(TYPES.Sync_ContentFilter).toConstantValue(new ContentFilter())
container
.bind<ItemSaveValidatorInterface>(TYPES.Sync_ItemSaveValidator)
.toConstantValue(
new ItemSaveValidator([
container.get(TYPES.Sync_OwnershipFilter),
container.get(TYPES.Sync_TimeDifferenceFilter),
container.get(TYPES.Sync_ContentTypeFilter),
container.get(TYPES.Sync_ContentFilter),
]),
)
// use cases
container.bind<SyncItems>(TYPES.Sync_SyncItems).toDynamicValue((context: interfaces.Context) => {
return new SyncItems(context.container.get(TYPES.Sync_ItemService))
})
container.bind<CheckIntegrity>(TYPES.Sync_CheckIntegrity).toDynamicValue((context: interfaces.Context) => {
return new CheckIntegrity(context.container.get(TYPES.Sync_ItemRepository))
})
container.bind<GetItem>(TYPES.Sync_GetItem).toDynamicValue((context: interfaces.Context) => {
return new GetItem(context.container.get(TYPES.Sync_ItemRepository))
})
container
.bind<GetItems>(TYPES.Sync_GetItems)
.toConstantValue(
new GetItems(
container.get(TYPES.Sync_ItemRepository),
container.get(TYPES.Sync_CONTENT_SIZE_TRANSFER_LIMIT),
container.get(TYPES.Sync_ItemTransferCalculator),
container.get(TYPES.Sync_Timer),
container.get(TYPES.Sync_MAX_ITEMS_LIMIT),
),
)
container
.bind<SaveNewItem>(TYPES.Sync_SaveNewItem)
.toConstantValue(
@@ -313,41 +538,175 @@ export class ContainerConfigLoader {
container.get(TYPES.Sync_REVISIONS_FREQUENCY),
),
)
// Services
container.bind<OwnershipFilter>(TYPES.Sync_OwnershipFilter).toConstantValue(new OwnershipFilter())
container
.bind<TimeDifferenceFilter>(TYPES.Sync_TimeDifferenceFilter)
.toConstantValue(new TimeDifferenceFilter(container.get(TYPES.Sync_Timer)))
container.bind<ContentTypeFilter>(TYPES.Sync_ContentTypeFilter).toConstantValue(new ContentTypeFilter())
container.bind<ContentFilter>(TYPES.Sync_ContentFilter).toConstantValue(new ContentFilter())
container
.bind<ItemSaveValidatorInterface>(TYPES.Sync_ItemSaveValidator)
.toDynamicValue((context: interfaces.Context) => {
return new ItemSaveValidator([
context.container.get(TYPES.Sync_OwnershipFilter),
context.container.get(TYPES.Sync_TimeDifferenceFilter),
context.container.get(TYPES.Sync_ContentTypeFilter),
context.container.get(TYPES.Sync_ContentFilter),
])
})
container
.bind<ItemServiceInterface>(TYPES.Sync_ItemService)
.bind<SaveItems>(TYPES.Sync_SaveItems)
.toConstantValue(
new ItemService(
new SaveItems(
container.get(TYPES.Sync_ItemSaveValidator),
container.get(TYPES.Sync_ItemRepository),
container.get(TYPES.Sync_CONTENT_SIZE_TRANSFER_LIMIT),
container.get(TYPES.Sync_ItemTransferCalculator),
container.get(TYPES.Sync_Timer),
container.get(TYPES.Sync_MAX_ITEMS_LIMIT),
container.get(TYPES.Sync_SaveNewItem),
container.get(TYPES.Sync_UpdateExistingItem),
container.get(TYPES.Sync_Logger),
),
)
container
.bind<SyncItems>(TYPES.Sync_SyncItems)
.toConstantValue(
new SyncItems(
container.get(TYPES.Sync_ItemRepository),
container.get(TYPES.Sync_GetItems),
container.get(TYPES.Sync_SaveItems),
),
)
container.bind<CheckIntegrity>(TYPES.Sync_CheckIntegrity).toDynamicValue((context: interfaces.Context) => {
return new CheckIntegrity(context.container.get(TYPES.Sync_ItemRepository))
})
container.bind<GetItem>(TYPES.Sync_GetItem).toDynamicValue((context: interfaces.Context) => {
return new GetItem(context.container.get(TYPES.Sync_ItemRepository))
})
container
.bind<InviteUserToSharedVault>(TYPES.Sync_InviteUserToSharedVault)
.toConstantValue(
new InviteUserToSharedVault(
container.get(TYPES.Sync_SharedVaultRepository),
container.get(TYPES.Sync_SharedVaultInviteRepository),
container.get(TYPES.Sync_Timer),
),
)
container
.bind<UpdateSharedVaultInvite>(TYPES.Sync_UpdateSharedVaultInvite)
.toConstantValue(
new UpdateSharedVaultInvite(
container.get(TYPES.Sync_SharedVaultInviteRepository),
container.get(TYPES.Sync_Timer),
),
)
container
.bind<AddUserToSharedVault>(TYPES.Sync_AddUserToSharedVault)
.toConstantValue(
new AddUserToSharedVault(
container.get(TYPES.Sync_SharedVaultRepository),
container.get(TYPES.Sync_SharedVaultUserRepository),
container.get(TYPES.Sync_Timer),
),
)
container
.bind<AcceptInviteToSharedVault>(TYPES.Sync_AcceptInviteToSharedVault)
.toConstantValue(
new AcceptInviteToSharedVault(
container.get(TYPES.Sync_AddUserToSharedVault),
container.get(TYPES.Sync_SharedVaultInviteRepository),
),
)
container
.bind<DeclineInviteToSharedVault>(TYPES.Sync_DeclineInviteToSharedVault)
.toConstantValue(new DeclineInviteToSharedVault(container.get(TYPES.Sync_SharedVaultInviteRepository)))
container
.bind<DeleteSharedVaultInvitesToUser>(TYPES.Sync_DeleteSharedVaultInvitesToUser)
.toConstantValue(
new DeleteSharedVaultInvitesToUser(
container.get(TYPES.Sync_SharedVaultInviteRepository),
container.get(TYPES.Sync_DeclineInviteToSharedVault),
),
)
container
.bind<DeleteSharedVaultInvitesSentByUser>(TYPES.Sync_DeleteSharedVaultInvitesSentByUser)
.toConstantValue(
new DeleteSharedVaultInvitesSentByUser(
container.get(TYPES.Sync_SharedVaultInviteRepository),
container.get(TYPES.Sync_DeclineInviteToSharedVault),
),
)
container
.bind<GetSharedVaultInvitesSentByUser>(TYPES.Sync_GetSharedVaultInvitesSentByUser)
.toConstantValue(new GetSharedVaultInvitesSentByUser(container.get(TYPES.Sync_SharedVaultInviteRepository)))
container
.bind<GetSharedVaultInvitesSentToUser>(TYPES.Sync_GetSharedVaultInvitesSentToUser)
.toConstantValue(new GetSharedVaultInvitesSentToUser(container.get(TYPES.Sync_SharedVaultInviteRepository)))
container
.bind<GetSharedVaultUsers>(TYPES.Sync_GetSharedVaultUsers)
.toConstantValue(
new GetSharedVaultUsers(
container.get(TYPES.Sync_SharedVaultUserRepository),
container.get(TYPES.Sync_SharedVaultRepository),
),
)
container
.bind<AddNotificationForUser>(TYPES.Sync_AddNotificationForUser)
.toConstantValue(
new AddNotificationForUser(container.get(TYPES.Sync_NotificationRepository), container.get(TYPES.Sync_Timer)),
)
container
.bind<RemoveUserFromSharedVault>(TYPES.Sync_RemoveSharedVaultUser)
.toConstantValue(
new RemoveUserFromSharedVault(
container.get(TYPES.Sync_SharedVaultUserRepository),
container.get(TYPES.Sync_SharedVaultRepository),
container.get(TYPES.Sync_AddNotificationForUser),
),
)
container
.bind<GetSharedVaults>(TYPES.Sync_GetSharedVaults)
.toConstantValue(
new GetSharedVaults(
container.get(TYPES.Sync_SharedVaultUserRepository),
container.get(TYPES.Sync_SharedVaultRepository),
),
)
container
.bind<CreateSharedVault>(TYPES.Sync_CreateSharedVault)
.toConstantValue(
new CreateSharedVault(
container.get(TYPES.Sync_AddUserToSharedVault),
container.get(TYPES.Sync_SharedVaultRepository),
container.get(TYPES.Sync_Timer),
),
)
container
.bind<DeleteSharedVault>(TYPES.Sync_DeleteSharedVault)
.toConstantValue(
new DeleteSharedVault(
container.get(TYPES.Sync_SharedVaultRepository),
container.get(TYPES.Sync_SharedVaultUserRepository),
container.get(TYPES.Sync_SharedVaultInviteRepository),
container.get(TYPES.Sync_RemoveSharedVaultUser),
),
)
container
.bind<CreateSharedVaultFileValetToken>(TYPES.Sync_CreateSharedVaultFileValetToken)
.toConstantValue(
new CreateSharedVaultFileValetToken(
container.get(TYPES.Sync_SharedVaultRepository),
container.get(TYPES.Sync_SharedVaultUserRepository),
container.get(TYPES.Sync_SharedVaultValetTokenEncoder),
container.get(TYPES.Sync_VALET_TOKEN_TTL),
),
)
container
.bind<GetMessagesSentToUser>(TYPES.Sync_GetMessagesSentToUser)
.toConstantValue(new GetMessagesSentToUser(container.get(TYPES.Sync_MessageRepository)))
container
.bind<GetMessagesSentByUser>(TYPES.Sync_GetMessagesSentByUser)
.toConstantValue(new GetMessagesSentByUser(container.get(TYPES.Sync_MessageRepository)))
container
.bind<SendMessageToUser>(TYPES.Sync_SendMessageToUser)
.toConstantValue(
new SendMessageToUser(container.get(TYPES.Sync_MessageRepository), container.get(TYPES.Sync_Timer)),
)
container
.bind<DeleteMessage>(TYPES.Sync_DeleteMessage)
.toConstantValue(new DeleteMessage(container.get(TYPES.Sync_MessageRepository)))
container
.bind<DeleteAllMessagesSentToUser>(TYPES.Sync_DeleteAllMessagesSentToUser)
.toConstantValue(
new DeleteAllMessagesSentToUser(
container.get(TYPES.Sync_MessageRepository),
container.get(TYPES.Sync_DeleteMessage),
),
)
// Services
container
.bind<SyncResponseFactory20161215>(TYPES.Sync_SyncResponseFactory20161215)
.toConstantValue(new SyncResponseFactory20161215(container.get(TYPES.Sync_ItemHttpMapper)))
@@ -533,6 +892,58 @@ export class ContainerConfigLoader {
container.get(TYPES.Sync_ControllerContainer),
),
)
container
.bind<HomeServerSharedVaultInvitesController>(TYPES.Sync_HomeServerSharedVaultInvitesController)
.toConstantValue(
new HomeServerSharedVaultInvitesController(
container.get(TYPES.Sync_InviteUserToSharedVault),
container.get(TYPES.Sync_UpdateSharedVaultInvite),
container.get(TYPES.Sync_AcceptInviteToSharedVault),
container.get(TYPES.Sync_DeclineInviteToSharedVault),
container.get(TYPES.Sync_DeleteSharedVaultInvitesToUser),
container.get(TYPES.Sync_DeleteSharedVaultInvitesSentByUser),
container.get(TYPES.Sync_GetSharedVaultInvitesSentByUser),
container.get(TYPES.Sync_GetSharedVaultInvitesSentToUser),
container.get(TYPES.Sync_SharedVaultInviteHttpMapper),
container.get(TYPES.Sync_ControllerContainer),
),
)
container
.bind<HomeServerSharedVaultUsersController>(TYPES.Sync_HomeServerSharedVaultUsersController)
.toConstantValue(
new HomeServerSharedVaultUsersController(
container.get(TYPES.Sync_GetSharedVaultUsers),
container.get(TYPES.Sync_RemoveSharedVaultUser),
container.get(TYPES.Sync_SharedVaultUserHttpMapper),
container.get(TYPES.Sync_ControllerContainer),
),
)
container
.bind<HomeServerSharedVaultsController>(TYPES.Sync_HomeServerSharedVaultsController)
.toConstantValue(
new HomeServerSharedVaultsController(
container.get(TYPES.Sync_GetSharedVaults),
container.get(TYPES.Sync_CreateSharedVault),
container.get(TYPES.Sync_DeleteSharedVault),
container.get(TYPES.Sync_CreateSharedVaultFileValetToken),
container.get(TYPES.Sync_SharedVaultHttpMapper),
container.get(TYPES.Sync_SharedVaultUserHttpMapper),
container.get(TYPES.Sync_ControllerContainer),
),
)
container
.bind<HomeServerMessagesController>(TYPES.Sync_HomeServerMessagesController)
.toConstantValue(
new HomeServerMessagesController(
container.get(TYPES.Sync_GetMessagesSentToUser),
container.get(TYPES.Sync_GetMessagesSentByUser),
container.get(TYPES.Sync_SendMessageToUser),
container.get(TYPES.Sync_DeleteAllMessagesSentToUser),
container.get(TYPES.Sync_DeleteMessage),
container.get(TYPES.Sync_MessageHttpMapper),
container.get(TYPES.Sync_ControllerContainer),
),
)
}
logger.debug('Configuration complete')

View File

@@ -4,6 +4,12 @@ import { Env } from './Env'
import { SqliteConnectionOptions } from 'typeorm/driver/sqlite/SqliteConnectionOptions'
import { TypeORMItem } from '../Infra/TypeORM/TypeORMItem'
import { TypeORMNotification } from '../Infra/TypeORM/TypeORMNotification'
import { TypeORMSharedVaultAssociation } from '../Infra/TypeORM/TypeORMSharedVaultAssociation'
import { TypeORMKeySystemAssociation } from '../Infra/TypeORM/TypeORMKeySystemAssociation'
import { TypeORMSharedVault } from '../Infra/TypeORM/TypeORMSharedVault'
import { TypeORMSharedVaultUser } from '../Infra/TypeORM/TypeORMSharedVaultUser'
import { TypeORMSharedVaultInvite } from '../Infra/TypeORM/TypeORMSharedVaultInvite'
import { TypeORMMessage } from '../Infra/TypeORM/TypeORMMessage'
export class AppDataSource {
private _dataSource: DataSource | undefined
@@ -33,7 +39,16 @@ export class AppDataSource {
const commonDataSourceOptions = {
maxQueryExecutionTime,
entities: [TypeORMItem, TypeORMNotification],
entities: [
TypeORMItem,
TypeORMNotification,
TypeORMSharedVaultAssociation,
TypeORMKeySystemAssociation,
TypeORMSharedVault,
TypeORMSharedVaultUser,
TypeORMSharedVaultInvite,
TypeORMMessage,
],
migrations: [`${__dirname}/../../migrations/${isConfiguredForMySQL ? 'mysql' : 'sqlite'}/*.js`],
migrationsRun: true,
logging: <LoggerOptions>this.env.get('DB_DEBUG_LEVEL', true) ?? 'info',

View File

@@ -8,8 +8,22 @@ const TYPES = {
Sync_Env: Symbol.for('Sync_Env'),
// Repositories
Sync_ItemRepository: Symbol.for('Sync_ItemRepository'),
Sync_KeySystemAssociationRepository: Symbol.for('Sync_KeySystemAssociationRepository'),
Sync_SharedVaultAssociationRepository: Symbol.for('Sync_SharedVaultAssociationRepository'),
Sync_SharedVaultRepository: Symbol.for('Sync_SharedVaultRepository'),
Sync_SharedVaultInviteRepository: Symbol.for('Sync_SharedVaultInviteRepository'),
Sync_SharedVaultUserRepository: Symbol.for('Sync_SharedVaultUserRepository'),
Sync_NotificationRepository: Symbol.for('Sync_NotificationRepository'),
Sync_MessageRepository: Symbol.for('Sync_MessageRepository'),
// ORM
Sync_ORMItemRepository: Symbol.for('Sync_ORMItemRepository'),
Sync_ORMSharedVaultAssociationRepository: Symbol.for('Sync_ORMSharedVaultAssociationRepository'),
Sync_ORMKeySystemAssociationRepository: Symbol.for('Sync_ORMKeySystemAssociationRepository'),
Sync_ORMSharedVaultRepository: Symbol.for('Sync_ORMSharedVaultRepository'),
Sync_ORMSharedVaultInviteRepository: Symbol.for('Sync_ORMSharedVaultInviteRepository'),
Sync_ORMSharedVaultUserRepository: Symbol.for('Sync_ORMSharedVaultUserRepository'),
Sync_ORMNotificationRepository: Symbol.for('Sync_ORMNotificationRepository'),
Sync_ORMMessageRepository: Symbol.for('Sync_ORMMessageRepository'),
// Middleware
Sync_AuthMiddleware: Symbol.for('Sync_AuthMiddleware'),
// env vars
@@ -30,6 +44,8 @@ const TYPES = {
Sync_CONTENT_SIZE_TRANSFER_LIMIT: Symbol.for('Sync_CONTENT_SIZE_TRANSFER_LIMIT'),
Sync_MAX_ITEMS_LIMIT: Symbol.for('Sync_MAX_ITEMS_LIMIT'),
Sync_FILE_UPLOAD_PATH: Symbol.for('Sync_FILE_UPLOAD_PATH'),
Sync_VALET_TOKEN_SECRET: Symbol.for('Sync_VALET_TOKEN_SECRET'),
Sync_VALET_TOKEN_TTL: Symbol.for('Sync_VALET_TOKEN_TTL'),
// use cases
Sync_SyncItems: Symbol.for('Sync_SyncItems'),
Sync_CheckIntegrity: Symbol.for('Sync_CheckIntegrity'),
@@ -39,6 +55,8 @@ const TYPES = {
Sync_DeleteSharedVault: Symbol.for('Sync_DeleteSharedVault'),
Sync_CreateSharedVaultFileValetToken: Symbol.for('Sync_CreateSharedVaultFileValetToken'),
Sync_GetSharedVaultUsers: Symbol.for('Sync_GetSharedVaultUsers'),
Sync_AddUserToSharedVault: Symbol.for('Sync_AddUserToSharedVault'),
Sync_AddNotificationForUser: Symbol.for('Sync_AddNotificationForUser'),
Sync_RemoveSharedVaultUser: Symbol.for('Sync_RemoveSharedVaultUser'),
Sync_InviteUserToSharedVault: Symbol.for('Sync_InviteUserToSharedVault'),
Sync_UpdateSharedVaultInvite: Symbol.for('Sync_UpdateSharedVaultInvite'),
@@ -55,6 +73,8 @@ const TYPES = {
Sync_DeleteMessage: Symbol.for('Sync_DeleteMessage'),
Sync_SaveNewItem: Symbol.for('Sync_SaveNewItem'),
Sync_UpdateExistingItem: Symbol.for('Sync_UpdateExistingItem'),
Sync_GetItems: Symbol.for('Sync_GetItems'),
Sync_SaveItems: Symbol.for('Sync_SaveItems'),
// Handlers
Sync_AccountDeletionRequestedEventHandler: Symbol.for('Sync_AccountDeletionRequestedEventHandler'),
Sync_DuplicateItemSyncedEventHandler: Symbol.for('Sync_DuplicateItemSyncedEventHandler'),
@@ -67,8 +87,8 @@ const TYPES = {
Sync_DomainEventFactory: Symbol.for('Sync_DomainEventFactory'),
Sync_DomainEventMessageHandler: Symbol.for('Sync_DomainEventMessageHandler'),
Sync_HTTPClient: Symbol.for('Sync_HTTPClient'),
Sync_ItemService: Symbol.for('Sync_ItemService'),
Sync_Timer: Symbol.for('Sync_Timer'),
Sync_SharedVaultValetTokenEncoder: Symbol.for('Sync_SharedVaultValetTokenEncoder'),
Sync_SyncResponseFactory20161215: Symbol.for('Sync_SyncResponseFactory20161215'),
Sync_SyncResponseFactory20200115: Symbol.for('Sync_SyncResponseFactory20200115'),
Sync_SyncResponseFactoryResolver: Symbol.for('Sync_SyncResponseFactoryResolver'),
@@ -83,16 +103,28 @@ const TYPES = {
Sync_ItemTransferCalculator: Symbol.for('Sync_ItemTransferCalculator'),
Sync_ControllerContainer: Symbol.for('Sync_ControllerContainer'),
Sync_HomeServerItemsController: Symbol.for('Sync_HomeServerItemsController'),
Sync_HomeServerSharedVaultInvitesController: Symbol.for('Sync_HomeServerSharedVaultInvitesController'),
Sync_HomeServerSharedVaultUsersController: Symbol.for('Sync_HomeServerSharedVaultUsersController'),
Sync_HomeServerSharedVaultsController: Symbol.for('Sync_HomeServerSharedVaultsController'),
Sync_HomeServerMessagesController: Symbol.for('Sync_HomeServerMessagesController'),
// Mapping
Sync_SharedVaultHttpMapper: Symbol.for('Sync_SharedVaultHttpMapper'),
Sync_SharedVaultUserHttpMapper: Symbol.for('Sync_SharedVaultUserHttpMapper'),
Sync_SharedVaultInviteHttpMapper: Symbol.for('Sync_SharedVaultInviteHttpMapper'),
Sync_MessagePersistenceMapper: Symbol.for('Sync_MessagePersistenceMapper'),
Sync_MessageHttpMapper: Symbol.for('Sync_MessageHttpMapper'),
Sync_ItemPersistenceMapper: Symbol.for('Sync_ItemPersistenceMapper'),
Sync_ItemHttpMapper: Symbol.for('Sync_ItemHttpMapper'),
Sync_ItemHashHttpMapper: Symbol.for('Sync_ItemHashHttpMapper'),
Sync_SavedItemHttpMapper: Symbol.for('Sync_SavedItemHttpMapper'),
Sync_ItemConflictHttpMapper: Symbol.for('Sync_ItemConflictHttpMapper'),
Sync_ItemBackupMapper: Symbol.for('Sync_ItemBackupMapper'),
Sync_KeySystemAssociationPersistenceMapper: Symbol.for('Sync_KeySystemAssociationPersistenceMapper'),
Sync_SharedVaultAssociationPersistenceMapper: Symbol.for('Sync_SharedVaultAssociationPersistenceMapper'),
Sync_SharedVaultPersistenceMapper: Symbol.for('Sync_SharedVaultPersistenceMapper'),
Sync_SharedVaultUserPersistenceMapper: Symbol.for('Sync_SharedVaultUserPersistenceMapper'),
Sync_SharedVaultInvitePersistenceMapper: Symbol.for('Sync_SharedVaultInvitePersistenceMapper'),
Sync_NotificationPersistenceMapper: Symbol.for('Sync_NotificationPersistenceMapper'),
}
export default TYPES

View File

@@ -53,7 +53,7 @@ describe('ItemRevisionCreationRequestedEventHandler', () => {
event = {} as jest.Mocked<ItemRevisionCreationRequestedEvent>
event.createdAt = new Date(1)
event.payload = {
itemUuid: '2-3-4',
itemUuid: '00000000-0000-0000-0000-000000000000',
}
event.meta = {
correlation: {
@@ -96,4 +96,13 @@ describe('ItemRevisionCreationRequestedEventHandler', () => {
expect(domainEventPublisher.publish).not.toHaveBeenCalled()
expect(domainEventFactory.createItemDumpedEvent).not.toHaveBeenCalled()
})
it('should not create a revision if the item uuid is invalid', async () => {
event.payload.itemUuid = 'invalid-uuid'
await createHandler().handle(event)
expect(domainEventPublisher.publish).not.toHaveBeenCalled()
expect(domainEventFactory.createItemDumpedEvent).not.toHaveBeenCalled()
})
})

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