mirror of
https://github.com/standardnotes/server
synced 2026-01-17 05:04:27 -05:00
Compare commits
46 Commits
@standardn
...
@standardn
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
352e02028d | ||
|
|
1bbb639c83 | ||
|
|
c14265f103 | ||
|
|
c030a6b3d8 | ||
|
|
af997ea658 | ||
|
|
efa4d7fc60 | ||
|
|
f714aaa0e9 | ||
|
|
aee6e60583 | ||
|
|
4e602687d5 | ||
|
|
d026152ac8 | ||
|
|
3f21a358d2 | ||
|
|
dc55e47c98 | ||
|
|
3b804e2321 | ||
|
|
b32f851a90 | ||
|
|
479d20e76f | ||
|
|
fae4553fc8 | ||
|
|
cb74b23e45 | ||
|
|
af8f12c33a | ||
|
|
a148c4d1f6 | ||
|
|
f7190c0c9c | ||
|
|
c00d7765a9 | ||
|
|
2b651d86e2 | ||
|
|
9be3517093 | ||
|
|
fcfedaf7e7 | ||
|
|
0b82794e9c | ||
|
|
2a52e398cb | ||
|
|
c31e882ad2 | ||
|
|
2f0903e0eb | ||
|
|
2396053bc1 | ||
|
|
17fd12305e | ||
|
|
425ea4374d | ||
|
|
c076c3c74a | ||
|
|
547cdfd8ec | ||
|
|
a0af8f0025 | ||
|
|
c970b1ea68 | ||
|
|
4d1e2dec26 | ||
|
|
108408a944 | ||
|
|
18d07d431f | ||
|
|
cbc024f67a | ||
|
|
55ec5970da | ||
|
|
58bdca6659 | ||
|
|
ef49b0d3f8 | ||
|
|
9cb691e5ad | ||
|
|
04d09582d4 | ||
|
|
8f90dc172b | ||
|
|
f759261919 |
4
.github/workflows/common-e2e.yml
vendored
4
.github/workflows/common-e2e.yml
vendored
@@ -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
|
||||
|
||||
94
.pnp.cjs
generated
94
.pnp.cjs
generated
@@ -4560,17 +4560,16 @@ const RAW_RUNTIME_STATE =
|
||||
}]\
|
||||
]],\
|
||||
["@standardnotes/api", [\
|
||||
["npm:1.26.10", {\
|
||||
"packageLocation": "./.yarn/cache/@standardnotes-api-npm-1.26.10-f6165cafd3-3c3561aec8.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.10"],\
|
||||
["@standardnotes/api", "npm:1.26.26"],\
|
||||
["@standardnotes/common", "workspace:packages/common"],\
|
||||
["@standardnotes/domain-core", "workspace:packages/domain-core"],\
|
||||
["@standardnotes/encryption", "npm:1.21.38"],\
|
||||
["@standardnotes/models", "npm:1.45.5"],\
|
||||
["@standardnotes/responses", "npm:1.13.24"],\
|
||||
["@standardnotes/models", "npm:1.46.8"],\
|
||||
["@standardnotes/responses", "npm:1.13.27"],\
|
||||
["@standardnotes/security", "workspace:packages/security"],\
|
||||
["@standardnotes/utils", "npm:1.16.5"],\
|
||||
["@standardnotes/utils", "npm:1.17.5"],\
|
||||
["reflect-metadata", "npm:0.1.13"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
@@ -4635,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.10"],\
|
||||
["@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"],\
|
||||
@@ -4781,21 +4780,6 @@ const RAW_RUNTIME_STATE =
|
||||
"linkType": "SOFT"\
|
||||
}]\
|
||||
]],\
|
||||
["@standardnotes/encryption", [\
|
||||
["npm:1.21.38", {\
|
||||
"packageLocation": "./.yarn/cache/@standardnotes-encryption-npm-1.21.38-d08c3d4766-1393840523.zip/node_modules/@standardnotes/encryption/",\
|
||||
"packageDependencies": [\
|
||||
["@standardnotes/encryption", "npm:1.21.38"],\
|
||||
["@standardnotes/common", "workspace:packages/common"],\
|
||||
["@standardnotes/models", "npm:1.45.5"],\
|
||||
["@standardnotes/responses", "npm:1.13.24"],\
|
||||
["@standardnotes/sncrypto-common", "npm:1.13.3"],\
|
||||
["@standardnotes/utils", "npm:1.16.5"],\
|
||||
["reflect-metadata", "npm:0.1.13"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}]\
|
||||
]],\
|
||||
["@standardnotes/event-store", [\
|
||||
["workspace:packages/event-store", {\
|
||||
"packageLocation": "./packages/event-store/",\
|
||||
@@ -4831,10 +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/features", "npm:1.59.7"],\
|
||||
["@standardnotes/common", "workspace:packages/common"],\
|
||||
["@standardnotes/domain-core", "workspace:packages/domain-core"],\
|
||||
["@standardnotes/security", "workspace:packages/security"],\
|
||||
@@ -4855,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"],\
|
||||
@@ -4935,14 +4919,16 @@ const RAW_RUNTIME_STATE =
|
||||
}]\
|
||||
]],\
|
||||
["@standardnotes/models", [\
|
||||
["npm:1.45.5", {\
|
||||
"packageLocation": "./.yarn/cache/@standardnotes-models-npm-1.45.5-29326e959c-15f26c11b2.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.45.5"],\
|
||||
["@standardnotes/models", "npm:1.46.8"],\
|
||||
["@standardnotes/common", "workspace:packages/common"],\
|
||||
["@standardnotes/features", "npm:1.59.5"],\
|
||||
["@standardnotes/responses", "npm:1.13.24"],\
|
||||
["@standardnotes/utils", "npm:1.16.5"],\
|
||||
["@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.5"],\
|
||||
["lodash", "npm:4.17.21"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
@@ -4967,12 +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/features", "npm:1.59.7"],\
|
||||
["@standardnotes/security", "workspace:packages/security"],\
|
||||
["reflect-metadata", "npm:0.1.13"]\
|
||||
],\
|
||||
@@ -4987,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.10"],\
|
||||
["@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"],\
|
||||
@@ -5129,10 +5115,10 @@ 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/",\
|
||||
["npm:1.13.4", {\
|
||||
"packageLocation": "./.yarn/cache/@standardnotes-sncrypto-common-npm-1.13.4-3186513fa6-48e0e207f2.zip/node_modules/@standardnotes/sncrypto-common/",\
|
||||
"packageDependencies": [\
|
||||
["@standardnotes/sncrypto-common", "npm:1.13.3"],\
|
||||
["@standardnotes/sncrypto-common", "npm:1.13.4"],\
|
||||
["reflect-metadata", "npm:0.1.13"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
@@ -5143,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"],\
|
||||
@@ -5171,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.10"],\
|
||||
["@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"],\
|
||||
@@ -5247,10 +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/utils", "npm:1.17.5"],\
|
||||
["@standardnotes/common", "workspace:packages/common"],\
|
||||
["dompurify", "npm:2.4.5"],\
|
||||
["lodash", "npm:4.17.21"],\
|
||||
@@ -5266,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.10"],\
|
||||
["@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"],\
|
||||
|
||||
Binary file not shown.
BIN
.yarn/cache/@standardnotes-api-npm-1.26.26-4338a5fe92-db41aedfa3.zip
vendored
Normal file
BIN
.yarn/cache/@standardnotes-api-npm-1.26.26-4338a5fe92-db41aedfa3.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/@standardnotes-models-npm-1.46.8-bc0390832e-8404340f27.zip
vendored
Normal file
BIN
.yarn/cache/@standardnotes-models-npm-1.46.8-bc0390832e-8404340f27.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/@standardnotes-responses-npm-1.13.27-829dec3e6e-9bf55e5f02.zip
vendored
Normal file
BIN
.yarn/cache/@standardnotes-responses-npm-1.13.27-829dec3e6e-9bf55e5f02.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -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.
|
||||
|
||||
## [2.25.2](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.25.1...@standardnotes/analytics@2.25.2) (2023-07-21)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/analytics
|
||||
|
||||
## [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
|
||||
|
||||
## [2.24.8](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.24.7...@standardnotes/analytics@2.24.8) (2023-07-07)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/analytics
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/analytics",
|
||||
"version": "2.24.8",
|
||||
"version": "2.25.2",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <21.0.0"
|
||||
},
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -3,6 +3,36 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.67.1](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.67.0...@standardnotes/api-gateway@1.67.1) (2023-07-21)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||
|
||||
# [1.67.0](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.66.1...@standardnotes/api-gateway@1.67.0) (2023-07-20)
|
||||
|
||||
### Features
|
||||
|
||||
* **syncing-server:** add shared vaults, invites, messages and notifications to sync response ([#665](https://github.com/standardnotes/api-gateway/issues/665)) ([efa4d7f](https://github.com/standardnotes/api-gateway/commit/efa4d7fc6007ef668e3de3b04853ac11b2d13c30))
|
||||
|
||||
## [1.66.1](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.66.0...@standardnotes/api-gateway@1.66.1) (2023-07-19)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add missing imports and exports for controllers ([#664](https://github.com/standardnotes/api-gateway/issues/664)) ([aee6e60](https://github.com/standardnotes/api-gateway/commit/aee6e6058359e2b5231cc13387656f837699300f))
|
||||
|
||||
# [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
|
||||
|
||||
## [1.65.5](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.65.4...@standardnotes/api-gateway@1.65.5) (2023-07-07)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/api-gateway",
|
||||
"version": "1.65.5",
|
||||
"version": "1.67.1",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <21.0.0"
|
||||
},
|
||||
|
||||
@@ -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'
|
||||
@@ -13,6 +13,8 @@ export * from './v1/OfflineController'
|
||||
export * from './v1/PaymentsController'
|
||||
export * from './v1/RevisionsController'
|
||||
export * from './v1/SessionsController'
|
||||
export * from './v1/SharedVaultInvitesController'
|
||||
export * from './v1/SharedVaultUsersController'
|
||||
export * from './v1/SharedVaultsController'
|
||||
export * from './v1/SubscriptionInvitesController'
|
||||
export * from './v1/TokensController'
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
70
packages/api-gateway/src/Controller/v1/MessagesController.ts
Normal file
70
packages/api-gateway/src/Controller/v1/MessagesController.ts
Normal 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,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
@@ -75,7 +100,7 @@ export class EndpointResolver implements EndpointResolverInterface {
|
||||
const identifier = this.endpointToIdentifierMap.get(`[${method}]:${endpoint}`)
|
||||
|
||||
if (!identifier) {
|
||||
throw new Error(`Endpoint ${endpoint} not found`)
|
||||
throw new Error(`Endpoint [${method}]:${endpoint} not found`)
|
||||
}
|
||||
|
||||
return identifier
|
||||
|
||||
@@ -3,6 +3,58 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.126.1](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.126.0...@standardnotes/auth-server@1.126.1) (2023-07-21)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/auth-server
|
||||
|
||||
# [1.126.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.125.1...@standardnotes/auth-server@1.126.0) (2023-07-20)
|
||||
|
||||
### Features
|
||||
|
||||
* **syncing-server:** add shared vaults, invites, messages and notifications to sync response ([#665](https://github.com/standardnotes/server/issues/665)) ([efa4d7f](https://github.com/standardnotes/server/commit/efa4d7fc6007ef668e3de3b04853ac11b2d13c30))
|
||||
|
||||
## [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
|
||||
|
||||
* domain items ([#655](https://github.com/standardnotes/server/issues/655)) ([a0af8f0](https://github.com/standardnotes/server/commit/a0af8f00252e1219e58cb7e066c11a8e71692e9d))
|
||||
|
||||
## [1.122.2](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.122.1...@standardnotes/auth-server@1.122.2) (2023-07-07)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm'
|
||||
|
||||
export class AddNotifications1688540448427 implements MigrationInterface {
|
||||
name = 'AddNotifications1688540448427'
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
'CREATE TABLE `notifications` (`uuid` varchar(36) NOT NULL, `user_uuid` varchar(36) NOT NULL, `type` varchar(36) NOT NULL, `payload` text NOT NULL, `created_at_timestamp` bigint NOT NULL, `updated_at_timestamp` bigint NOT NULL, INDEX `index_notifications_on_user_uuid` (`user_uuid`), PRIMARY KEY (`uuid`)) ENGINE=InnoDB',
|
||||
)
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query('DROP INDEX `index_notifications_on_user_uuid` ON `notifications`')
|
||||
await queryRunner.query('DROP TABLE `notifications`')
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm'
|
||||
|
||||
export class RemoveNotifications1688540448428 implements MigrationInterface {
|
||||
name = 'RemoveNotifications1688540448428'
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query('DROP INDEX `index_notifications_on_user_uuid` ON `notifications`')
|
||||
await queryRunner.query('DROP TABLE `notifications`')
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
'CREATE TABLE `notifications` (`uuid` varchar(36) NOT NULL, `user_uuid` varchar(36) NOT NULL, `type` varchar(36) NOT NULL, `payload` text NOT NULL, `created_at_timestamp` bigint NOT NULL, `updated_at_timestamp` bigint NOT NULL, INDEX `index_notifications_on_user_uuid` (`user_uuid`), PRIMARY KEY (`uuid`)) ENGINE=InnoDB',
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm'
|
||||
|
||||
export class AddNotifications1688540623272 implements MigrationInterface {
|
||||
name = 'AddNotifications1688540623272'
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
'CREATE TABLE "notifications" ("uuid" varchar PRIMARY KEY NOT NULL, "user_uuid" varchar(36) NOT NULL, "type" varchar(36) NOT NULL, "payload" text NOT NULL, "created_at_timestamp" bigint NOT NULL, "updated_at_timestamp" bigint NOT NULL)',
|
||||
)
|
||||
await queryRunner.query('CREATE INDEX "index_notifications_on_user_uuid" ON "notifications" ("user_uuid") ')
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query('DROP INDEX "index_notifications_on_user_uuid"')
|
||||
await queryRunner.query('DROP TABLE "notifications"')
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm'
|
||||
|
||||
export class RemoveNotifications1688540623273 implements MigrationInterface {
|
||||
name = 'RemoveNotifications1688540623273'
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query('DROP INDEX "index_notifications_on_user_uuid"')
|
||||
await queryRunner.query('DROP TABLE "notifications"')
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
'CREATE TABLE "notifications" ("uuid" varchar PRIMARY KEY NOT NULL, "user_uuid" varchar(36) NOT NULL, "type" varchar(36) NOT NULL, "payload" text NOT NULL, "created_at_timestamp" bigint NOT NULL, "updated_at_timestamp" bigint NOT NULL)',
|
||||
)
|
||||
await queryRunner.query('CREATE INDEX "index_notifications_on_user_uuid" ON "notifications" ("user_uuid") ')
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/auth-server",
|
||||
"version": "1.122.2",
|
||||
"version": "1.126.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.25.3",
|
||||
"@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",
|
||||
|
||||
@@ -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>>
|
||||
}
|
||||
|
||||
@@ -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),
|
||||
),
|
||||
|
||||
@@ -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> {
|
||||
|
||||
@@ -8,12 +8,12 @@ import { User } from '../Domain/User/User'
|
||||
import { Register } from '../Domain/UseCase/Register'
|
||||
import { DomainEventFactoryInterface } from '../Domain/Event/DomainEventFactoryInterface'
|
||||
import { KeyParamsOrigination, ProtocolVersion } from '@standardnotes/common'
|
||||
import { ApiVersion } from '@standardnotes/api'
|
||||
import { SignInWithRecoveryCodes } from '../Domain/UseCase/SignInWithRecoveryCodes/SignInWithRecoveryCodes'
|
||||
import { GetUserKeyParamsRecovery } from '../Domain/UseCase/GetUserKeyParamsRecovery/GetUserKeyParamsRecovery'
|
||||
import { GenerateRecoveryCodes } from '../Domain/UseCase/GenerateRecoveryCodes/GenerateRecoveryCodes'
|
||||
import { Logger } from 'winston'
|
||||
import { SessionServiceInterface } from '../Domain/Session/SessionServiceInterface'
|
||||
import { ApiVersion } from '../Domain/Api/ApiVersion'
|
||||
|
||||
describe('AuthController', () => {
|
||||
let clearLoginAttempts: ClearLoginAttempts
|
||||
@@ -73,7 +73,7 @@ describe('AuthController', () => {
|
||||
email: 'test@test.te',
|
||||
password: 'asdzxc',
|
||||
version: ProtocolVersion.V004,
|
||||
api: ApiVersion.v0,
|
||||
api: ApiVersion.v20200115,
|
||||
origination: KeyParamsOrigination.Registration,
|
||||
userAgent: 'Google Chrome',
|
||||
identifier: 'test@test.te',
|
||||
@@ -103,7 +103,7 @@ describe('AuthController', () => {
|
||||
email: 'test@test.te',
|
||||
password: '',
|
||||
version: ProtocolVersion.V004,
|
||||
api: ApiVersion.v0,
|
||||
api: ApiVersion.v20200115,
|
||||
origination: KeyParamsOrigination.Registration,
|
||||
userAgent: 'Google Chrome',
|
||||
identifier: 'test@test.te',
|
||||
@@ -123,7 +123,7 @@ describe('AuthController', () => {
|
||||
email: 'test@test.te',
|
||||
password: 'test',
|
||||
version: ProtocolVersion.V004,
|
||||
api: ApiVersion.v0,
|
||||
api: ApiVersion.v20200115,
|
||||
origination: KeyParamsOrigination.Registration,
|
||||
userAgent: 'Google Chrome',
|
||||
identifier: 'test@test.te',
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { DomainEventPublisherInterface } from '@standardnotes/domain-events'
|
||||
import {
|
||||
ApiVersion,
|
||||
UserRegistrationRequestParams,
|
||||
UserServerInterface,
|
||||
UserDeletionResponseBody,
|
||||
UserRegistrationResponseBody,
|
||||
UserUpdateRequestParams,
|
||||
} from '@standardnotes/api'
|
||||
import { ErrorTag, HttpResponse, HttpStatusCode } from '@standardnotes/responses'
|
||||
import { ProtocolVersion } from '@standardnotes/common'
|
||||
@@ -23,6 +23,8 @@ import { GenerateRecoveryCodes } from '../Domain/UseCase/GenerateRecoveryCodes/G
|
||||
import { GenerateRecoveryCodesRequestParams } from '../Infra/Http/Request/GenerateRecoveryCodesRequestParams'
|
||||
import { Logger } from 'winston'
|
||||
import { SessionServiceInterface } from '../Domain/Session/SessionServiceInterface'
|
||||
import { ApiVersion } from '../Domain/Api/ApiVersion'
|
||||
import { UserUpdateResponse } from '@standardnotes/api/dist/Domain/Response/User/UserUpdateResponse'
|
||||
|
||||
export class AuthController implements UserServerInterface {
|
||||
constructor(
|
||||
@@ -37,6 +39,10 @@ export class AuthController implements UserServerInterface {
|
||||
private sessionService: SessionServiceInterface,
|
||||
) {}
|
||||
|
||||
async update(_params: UserUpdateRequestParams): Promise<HttpResponse<UserUpdateResponse>> {
|
||||
throw new Error('Method not implemented.')
|
||||
}
|
||||
|
||||
async deleteAccount(_params: never): Promise<HttpResponse<UserDeletionResponseBody>> {
|
||||
throw new Error('This method is implemented on the payments server.')
|
||||
}
|
||||
@@ -121,7 +127,7 @@ export class AuthController implements UserServerInterface {
|
||||
async signInWithRecoveryCodes(
|
||||
params: SignInWithRecoveryCodesRequestParams,
|
||||
): Promise<HttpResponse<SignInWithRecoveryCodesResponseBody>> {
|
||||
if (params.apiVersion !== ApiVersion.v0) {
|
||||
if (params.apiVersion !== ApiVersion.v20200115) {
|
||||
return {
|
||||
status: HttpStatusCode.BadRequest,
|
||||
data: {
|
||||
@@ -162,7 +168,7 @@ export class AuthController implements UserServerInterface {
|
||||
async recoveryKeyParams(
|
||||
params: RecoveryKeyParamsRequestParams,
|
||||
): Promise<HttpResponse<RecoveryKeyParamsResponseBody>> {
|
||||
if (params.apiVersion !== ApiVersion.v0) {
|
||||
if (params.apiVersion !== ApiVersion.v20200115) {
|
||||
return {
|
||||
status: HttpStatusCode.BadRequest,
|
||||
data: {
|
||||
|
||||
@@ -7,7 +7,7 @@ import { AcceptSharedSubscriptionInvitation } from '../Domain/UseCase/AcceptShar
|
||||
import { DeclineSharedSubscriptionInvitation } from '../Domain/UseCase/DeclineSharedSubscriptionInvitation/DeclineSharedSubscriptionInvitation'
|
||||
import { CancelSharedSubscriptionInvitation } from '../Domain/UseCase/CancelSharedSubscriptionInvitation/CancelSharedSubscriptionInvitation'
|
||||
import { ListSharedSubscriptionInvitations } from '../Domain/UseCase/ListSharedSubscriptionInvitations/ListSharedSubscriptionInvitations'
|
||||
import { ApiVersion } from '@standardnotes/api'
|
||||
import { ApiVersion } from '../Domain/Api/ApiVersion'
|
||||
|
||||
describe('SubscriptionInvitesController', () => {
|
||||
let inviteToSharedSubscription: InviteToSharedSubscription
|
||||
@@ -53,7 +53,7 @@ describe('SubscriptionInvitesController', () => {
|
||||
invitations: [],
|
||||
})
|
||||
|
||||
const result = await createController().listInvites({ api: ApiVersion.v0, inviterEmail: 'test@test.te' })
|
||||
const result = await createController().listInvites({ api: ApiVersion.v20200115, inviterEmail: 'test@test.te' })
|
||||
|
||||
expect(listSharedSubscriptionInvitations.execute).toHaveBeenCalledWith({
|
||||
inviterEmail: 'test@test.te',
|
||||
@@ -68,7 +68,7 @@ describe('SubscriptionInvitesController', () => {
|
||||
})
|
||||
|
||||
const result = await createController().cancelInvite({
|
||||
api: ApiVersion.v0,
|
||||
api: ApiVersion.v20200115,
|
||||
inviteUuid: '1-2-3',
|
||||
inviterEmail: 'test@test.te',
|
||||
})
|
||||
@@ -87,7 +87,7 @@ describe('SubscriptionInvitesController', () => {
|
||||
})
|
||||
|
||||
const result = await createController().cancelInvite({
|
||||
api: ApiVersion.v0,
|
||||
api: ApiVersion.v20200115,
|
||||
inviteUuid: '1-2-3',
|
||||
})
|
||||
|
||||
@@ -100,7 +100,7 @@ describe('SubscriptionInvitesController', () => {
|
||||
})
|
||||
|
||||
const result = await createController().declineInvite({
|
||||
api: ApiVersion.v0,
|
||||
api: ApiVersion.v20200115,
|
||||
inviteUuid: '1-2-3',
|
||||
})
|
||||
|
||||
@@ -117,7 +117,7 @@ describe('SubscriptionInvitesController', () => {
|
||||
})
|
||||
|
||||
const result = await createController().declineInvite({
|
||||
api: ApiVersion.v0,
|
||||
api: ApiVersion.v20200115,
|
||||
inviteUuid: '1-2-3',
|
||||
})
|
||||
|
||||
@@ -134,7 +134,7 @@ describe('SubscriptionInvitesController', () => {
|
||||
})
|
||||
|
||||
const result = await createController().acceptInvite({
|
||||
api: ApiVersion.v0,
|
||||
api: ApiVersion.v20200115,
|
||||
inviteUuid: '1-2-3',
|
||||
})
|
||||
|
||||
@@ -151,7 +151,7 @@ describe('SubscriptionInvitesController', () => {
|
||||
})
|
||||
|
||||
const result = await createController().acceptInvite({
|
||||
api: ApiVersion.v0,
|
||||
api: ApiVersion.v20200115,
|
||||
inviteUuid: '1-2-3',
|
||||
})
|
||||
|
||||
@@ -168,7 +168,7 @@ describe('SubscriptionInvitesController', () => {
|
||||
})
|
||||
|
||||
const result = await createController().invite({
|
||||
api: ApiVersion.v0,
|
||||
api: ApiVersion.v20200115,
|
||||
identifier: 'invitee@test.te',
|
||||
inviterUuid: '1-2-3',
|
||||
inviterEmail: 'test@test.te',
|
||||
@@ -187,7 +187,7 @@ describe('SubscriptionInvitesController', () => {
|
||||
|
||||
it('should not invite to user subscription if the identifier is missing in request', async () => {
|
||||
const result = await createController().invite({
|
||||
api: ApiVersion.v0,
|
||||
api: ApiVersion.v20200115,
|
||||
identifier: '',
|
||||
inviterUuid: '1-2-3',
|
||||
inviterEmail: 'test@test.te',
|
||||
@@ -205,7 +205,7 @@ describe('SubscriptionInvitesController', () => {
|
||||
})
|
||||
|
||||
const result = await createController().invite({
|
||||
api: ApiVersion.v0,
|
||||
api: ApiVersion.v20200115,
|
||||
identifier: 'invitee@test.te',
|
||||
inviterUuid: '1-2-3',
|
||||
inviterEmail: 'test@test.te',
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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),
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -114,8 +114,6 @@ describe('SubscriptionPurchasedEventHandler', () => {
|
||||
|
||||
expect(subscriptionSettingService.applyDefaultSubscriptionSettingsForSubscription).toHaveBeenCalledWith(
|
||||
subscription,
|
||||
SubscriptionName.ProPlan,
|
||||
'123',
|
||||
)
|
||||
})
|
||||
|
||||
|
||||
@@ -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> {
|
||||
|
||||
@@ -94,8 +94,6 @@ describe('SubscriptionReassignedEventHandler', () => {
|
||||
|
||||
expect(subscriptionSettingService.applyDefaultSubscriptionSettingsForSubscription).toHaveBeenCalledWith(
|
||||
subscription,
|
||||
SubscriptionName.ProPlan,
|
||||
'123',
|
||||
)
|
||||
})
|
||||
|
||||
|
||||
@@ -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> {
|
||||
|
||||
@@ -129,8 +129,6 @@ describe('SubscriptionSyncRequestedEventHandler', () => {
|
||||
|
||||
expect(subscriptionSettingService.applyDefaultSubscriptionSettingsForSubscription).toHaveBeenCalledWith(
|
||||
subscription,
|
||||
SubscriptionName.ProPlan,
|
||||
'123',
|
||||
)
|
||||
|
||||
expect(settingService.createOrReplace).toHaveBeenCalledWith({
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
}
|
||||
|
||||
@@ -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',
|
||||
)
|
||||
})
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -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.')
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
export interface ActivatePremiumFeaturesDTO {
|
||||
username: string
|
||||
subscriptionPlanName?: string
|
||||
endsAt?: Date
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import * as bcrypt from 'bcryptjs'
|
||||
import { RoleName, Username } from '@standardnotes/domain-core'
|
||||
import { ApiVersion } from '@standardnotes/api'
|
||||
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import { inject, injectable } from 'inversify'
|
||||
@@ -16,6 +15,7 @@ import { TimerInterface } from '@standardnotes/time'
|
||||
import { SettingServiceInterface } from '../Setting/SettingServiceInterface'
|
||||
import { AuthResponseFactory20200115 } from '../Auth/AuthResponseFactory20200115'
|
||||
import { AuthResponse20200115 } from '../Auth/AuthResponse20200115'
|
||||
import { ApiVersion } from '../Api/ApiVersion'
|
||||
|
||||
@injectable()
|
||||
export class Register implements UseCaseInterface {
|
||||
@@ -39,7 +39,7 @@ export class Register implements UseCaseInterface {
|
||||
|
||||
const { email, password, apiVersion, ephemeralSession, ...registrationFields } = dto
|
||||
|
||||
if (apiVersion !== ApiVersion.v0) {
|
||||
if (apiVersion !== ApiVersion.v20200115) {
|
||||
return {
|
||||
success: false,
|
||||
errorMessage: `Unsupported api version: ${apiVersion}`,
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import * as bcrypt from 'bcryptjs'
|
||||
import { Result, UseCaseInterface, Username, Uuid, Validator } from '@standardnotes/domain-core'
|
||||
import { SettingName } from '@standardnotes/settings'
|
||||
import { ApiVersion } from '@standardnotes/api'
|
||||
|
||||
import { AuthResponse20200115 } from '../../Auth/AuthResponse20200115'
|
||||
import { SettingServiceInterface } from '../../Setting/SettingServiceInterface'
|
||||
@@ -16,6 +15,7 @@ import { IncreaseLoginAttempts } from '../IncreaseLoginAttempts'
|
||||
import { ClearLoginAttempts } from '../ClearLoginAttempts'
|
||||
import { DeleteSetting } from '../DeleteSetting/DeleteSetting'
|
||||
import { AuthenticatorRepositoryInterface } from '../../Authenticator/AuthenticatorRepositoryInterface'
|
||||
import { ApiVersion } from '../../Api/ApiVersion'
|
||||
|
||||
export class SignInWithRecoveryCodes implements UseCaseInterface<AuthResponse20200115> {
|
||||
constructor(
|
||||
@@ -100,7 +100,7 @@ export class SignInWithRecoveryCodes implements UseCaseInterface<AuthResponse202
|
||||
|
||||
const authResponse = await this.authResponseFactory.createResponse({
|
||||
user,
|
||||
apiVersion: ApiVersion.v0,
|
||||
apiVersion: ApiVersion.v20200115,
|
||||
userAgent: dto.userAgent,
|
||||
ephemeralSession: false,
|
||||
readonlyAccess: false,
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
|
||||
|
||||
@@ -91,6 +91,7 @@ export class UpdateSetting implements UseCaseInterface {
|
||||
|
||||
const response = await this.subscriptionSettingService.createOrReplace({
|
||||
userSubscription: subscription,
|
||||
user,
|
||||
props,
|
||||
})
|
||||
|
||||
|
||||
@@ -3,6 +3,12 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [1.50.0](https://github.com/standardnotes/server/compare/@standardnotes/common@1.49.0...@standardnotes/common@1.50.0) (2023-07-12)
|
||||
|
||||
### Features
|
||||
|
||||
* domain items ([#655](https://github.com/standardnotes/server/issues/655)) ([a0af8f0](https://github.com/standardnotes/server/commit/a0af8f00252e1219e58cb7e066c11a8e71692e9d))
|
||||
|
||||
# [1.49.0](https://github.com/standardnotes/server/compare/@standardnotes/common@1.48.3...@standardnotes/common@1.49.0) (2023-06-30)
|
||||
|
||||
### Features
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/common",
|
||||
"version": "1.49.0",
|
||||
"version": "1.50.0",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <21.0.0"
|
||||
},
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
/* istanbul ignore file */
|
||||
export enum ContentType {
|
||||
Any = '*',
|
||||
Item = 'SF|Item',
|
||||
KeySystemItemsKey = 'SN|KeySystemItemsKey',
|
||||
KeySystemRootKey = 'SN|KeySystemRootKey',
|
||||
TrustedContact = 'SN|TrustedContact',
|
||||
VaultListing = 'SN|VaultListing',
|
||||
RootKey = 'SN|RootKey|NoSync',
|
||||
ItemsKey = 'SN|ItemsKey',
|
||||
EncryptedStorage = 'SN|EncryptedStorage',
|
||||
Privileges = 'SN|Privileges',
|
||||
Note = 'Note',
|
||||
Tag = 'Tag',
|
||||
SmartView = 'SN|SmartTag',
|
||||
Component = 'SN|Component',
|
||||
Editor = 'SN|Editor',
|
||||
ActionsExtension = 'Extension',
|
||||
UserPrefs = 'SN|UserPreferences',
|
||||
HistorySession = 'SN|HistorySession',
|
||||
Theme = 'SN|Theme',
|
||||
File = 'SN|File',
|
||||
FilesafeCredentials = 'SN|FileSafe|Credentials',
|
||||
FilesafeFileMetadata = 'SN|FileSafe|FileMetadata',
|
||||
FilesafeIntegration = 'SN|FileSafe|Integration',
|
||||
ExtensionRepo = 'SN|ExtensionRepo',
|
||||
Unknown = 'Unknown',
|
||||
}
|
||||
|
||||
export function DisplayStringForContentType(contentType: ContentType): string | undefined {
|
||||
const map: Partial<Record<ContentType, string>> = {
|
||||
[ContentType.ActionsExtension]: 'action-based extension',
|
||||
[ContentType.Component]: 'component',
|
||||
[ContentType.Editor]: 'editor',
|
||||
[ContentType.File]: 'file',
|
||||
[ContentType.FilesafeCredentials]: 'FileSafe credential',
|
||||
[ContentType.FilesafeFileMetadata]: 'FileSafe file',
|
||||
[ContentType.FilesafeIntegration]: 'FileSafe integration',
|
||||
[ContentType.ItemsKey]: 'encryption key',
|
||||
[ContentType.Note]: 'note',
|
||||
[ContentType.SmartView]: 'smart view',
|
||||
[ContentType.Tag]: 'tag',
|
||||
[ContentType.Theme]: 'theme',
|
||||
[ContentType.UserPrefs]: 'user preferences',
|
||||
}
|
||||
|
||||
return map[contentType]
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
export * from './Content/ContentType'
|
||||
export * from './Content/ContentDecoder'
|
||||
export * from './Content/ContentDecoderInterface'
|
||||
export * from './DataType/AnyRecord'
|
||||
|
||||
@@ -3,6 +3,30 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.23.2](https://github.com/standardnotes/server/compare/@standardnotes/domain-core@1.23.1...@standardnotes/domain-core@1.23.2) (2023-07-21)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* user notifications structure ([#667](https://github.com/standardnotes/server/issues/667)) ([1bbb639](https://github.com/standardnotes/server/commit/1bbb639c83922ec09e3778f85419d76669d36ae3))
|
||||
|
||||
## [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
|
||||
|
||||
* domain items ([#655](https://github.com/standardnotes/server/issues/655)) ([a0af8f0](https://github.com/standardnotes/server/commit/a0af8f00252e1219e58cb7e066c11a8e71692e9d))
|
||||
|
||||
## [1.21.1](https://github.com/standardnotes/server/compare/@standardnotes/domain-core@1.21.0...@standardnotes/domain-core@1.21.1) (2023-07-07)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/domain-core",
|
||||
"version": "1.21.1",
|
||||
"version": "1.23.2",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <21.0.0"
|
||||
},
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
39
packages/domain-core/src/Domain/Common/ContentType.spec.ts
Normal file
39
packages/domain-core/src/Domain/Common/ContentType.spec.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import { ContentType } from './ContentType'
|
||||
|
||||
describe('ContentType', () => {
|
||||
it('should create a value object', () => {
|
||||
const valueOrError = ContentType.create(ContentType.TYPES.Component)
|
||||
|
||||
expect(valueOrError.isFailed()).toBeFalsy()
|
||||
expect(valueOrError.getValue().value).toEqual('SN|Component')
|
||||
})
|
||||
|
||||
it('should not create an invalid value object', () => {
|
||||
for (const value of ['', undefined, 0, 'FOOBAR']) {
|
||||
const valueOrError = ContentType.create(value as string)
|
||||
|
||||
expect(valueOrError.isFailed()).toBeTruthy()
|
||||
}
|
||||
})
|
||||
|
||||
it('should return a display name', () => {
|
||||
const valueOrError = ContentType.create(ContentType.TYPES.FilesafeFileMetadata)
|
||||
|
||||
expect(valueOrError.isFailed()).toBeFalsy()
|
||||
expect(valueOrError.getValue().getDisplayName()).toEqual('FileSafe file')
|
||||
})
|
||||
|
||||
it('should return null for a display name if the value is null', () => {
|
||||
const valueOrError = ContentType.create(null)
|
||||
|
||||
expect(valueOrError.isFailed()).toBeFalsy()
|
||||
expect(valueOrError.getValue().getDisplayName()).toBeNull()
|
||||
})
|
||||
|
||||
it('should fallback to the value if the display name is not found', () => {
|
||||
const valueOrError = ContentType.create(ContentType.TYPES.Unknown)
|
||||
|
||||
expect(valueOrError.isFailed()).toBeFalsy()
|
||||
expect(valueOrError.getValue().getDisplayName()).toEqual('Unknown')
|
||||
})
|
||||
})
|
||||
79
packages/domain-core/src/Domain/Common/ContentType.ts
Normal file
79
packages/domain-core/src/Domain/Common/ContentType.ts
Normal file
@@ -0,0 +1,79 @@
|
||||
import { Result } from '../Core/Result'
|
||||
import { ValueObject } from '../Core/ValueObject'
|
||||
|
||||
import { ContentTypeProps } from './ContentTypeProps'
|
||||
|
||||
export class ContentType extends ValueObject<ContentTypeProps> {
|
||||
static readonly TYPES = {
|
||||
Any: '*',
|
||||
Item: 'SF|Item',
|
||||
KeySystemItemsKey: 'SN|KeySystemItemsKey',
|
||||
KeySystemRootKey: 'SN|KeySystemRootKey',
|
||||
TrustedContact: 'SN|TrustedContact',
|
||||
VaultListing: 'SN|VaultListing',
|
||||
RootKey: 'SN|RootKey|NoSync',
|
||||
ItemsKey: 'SN|ItemsKey',
|
||||
EncryptedStorage: 'SN|EncryptedStorage',
|
||||
Privileges: 'SN|Privileges',
|
||||
Note: 'Note',
|
||||
Tag: 'Tag',
|
||||
SmartView: 'SN|SmartTag',
|
||||
Component: 'SN|Component',
|
||||
Editor: 'SN|Editor',
|
||||
ActionsExtension: 'Extension',
|
||||
UserPrefs: 'SN|UserPreferences',
|
||||
HistorySession: 'SN|HistorySession',
|
||||
Theme: 'SN|Theme',
|
||||
File: 'SN|File',
|
||||
FilesafeCredentials: 'SN|FileSafe|Credentials',
|
||||
FilesafeFileMetadata: 'SN|FileSafe|FileMetadata',
|
||||
FilesafeIntegration: 'SN|FileSafe|Integration',
|
||||
ExtensionRepo: 'SN|ExtensionRepo',
|
||||
Unknown: 'Unknown',
|
||||
}
|
||||
|
||||
private readonly displayNamesMap: Partial<Record<string, string>> = {
|
||||
[ContentType.TYPES.ActionsExtension]: 'action-based extension',
|
||||
[ContentType.TYPES.Component]: 'component',
|
||||
[ContentType.TYPES.Editor]: 'editor',
|
||||
[ContentType.TYPES.File]: 'file',
|
||||
[ContentType.TYPES.FilesafeCredentials]: 'FileSafe credential',
|
||||
[ContentType.TYPES.FilesafeFileMetadata]: 'FileSafe file',
|
||||
[ContentType.TYPES.FilesafeIntegration]: 'FileSafe integration',
|
||||
[ContentType.TYPES.ItemsKey]: 'encryption key',
|
||||
[ContentType.TYPES.Note]: 'note',
|
||||
[ContentType.TYPES.SmartView]: 'smart view',
|
||||
[ContentType.TYPES.Tag]: 'tag',
|
||||
[ContentType.TYPES.Theme]: 'theme',
|
||||
[ContentType.TYPES.UserPrefs]: 'user preferences',
|
||||
}
|
||||
|
||||
get value(): string | null {
|
||||
return this.props.value
|
||||
}
|
||||
|
||||
private constructor(props: ContentTypeProps) {
|
||||
super(props)
|
||||
}
|
||||
|
||||
static create(type: string | null): Result<ContentType> {
|
||||
if (type === null) {
|
||||
return Result.ok<ContentType>(new ContentType({ value: null }))
|
||||
}
|
||||
|
||||
const isValidType = Object.values(this.TYPES).includes(type)
|
||||
if (!isValidType) {
|
||||
return Result.fail<ContentType>(`Invalid content type: ${type}`)
|
||||
} else {
|
||||
return Result.ok<ContentType>(new ContentType({ value: type }))
|
||||
}
|
||||
}
|
||||
|
||||
getDisplayName(): string | null {
|
||||
if (!this.value) {
|
||||
return null
|
||||
}
|
||||
|
||||
return this.displayNamesMap[this.value] || this.value
|
||||
}
|
||||
}
|
||||
@@ -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> {}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
import { ValueObject } from '../Core/ValueObject'
|
||||
import { Result } from '../Core/Result'
|
||||
|
||||
import { NotificationPayloadProps } from './NotificationPayloadProps'
|
||||
import { NotificationType } from './NotificationType'
|
||||
|
||||
export class NotificationPayload extends ValueObject<NotificationPayloadProps> {
|
||||
private constructor(props: NotificationPayloadProps) {
|
||||
super(props)
|
||||
}
|
||||
|
||||
override toString(): string {
|
||||
return JSON.stringify(this.props)
|
||||
}
|
||||
|
||||
static createFromString(jsonPayload: string): Result<NotificationPayload> {
|
||||
try {
|
||||
const props = JSON.parse(jsonPayload)
|
||||
|
||||
return NotificationPayload.create(props)
|
||||
} catch (error) {
|
||||
return Result.fail<NotificationPayload>((error as Error).message)
|
||||
}
|
||||
}
|
||||
|
||||
static create(props: NotificationPayloadProps): Result<NotificationPayload> {
|
||||
if (
|
||||
props.itemUuid === undefined &&
|
||||
props.type.equals(NotificationType.create(NotificationType.TYPES.SharedVaultItemRemoved).getValue())
|
||||
) {
|
||||
return Result.fail<NotificationPayload>(
|
||||
`Item uuid is required for ${NotificationType.TYPES.SharedVaultItemRemoved} notification type`,
|
||||
)
|
||||
}
|
||||
|
||||
return Result.ok<NotificationPayload>(new NotificationPayload(props))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import { Uuid } from '../Common/Uuid'
|
||||
import { NotificationType } from './NotificationType'
|
||||
|
||||
export interface NotificationPayloadProps {
|
||||
type: NotificationType
|
||||
sharedVaultUuid: Uuid
|
||||
version: string
|
||||
itemUuid?: Uuid
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ValueObject, Result } from '@standardnotes/domain-core'
|
||||
|
||||
import { Result } from '../Core/Result'
|
||||
import { ValueObject } from '../Core/ValueObject'
|
||||
import { NotificationTypeProps } from './NotificationTypeProps'
|
||||
|
||||
export class NotificationType extends ValueObject<NotificationTypeProps> {
|
||||
@@ -17,9 +17,9 @@ export class NotificationType extends ValueObject<NotificationTypeProps> {
|
||||
}
|
||||
|
||||
static create(notificationType: string): Result<NotificationType> {
|
||||
const isValidPermission = Object.values(this.TYPES).includes(notificationType)
|
||||
if (!isValidPermission) {
|
||||
return Result.fail<NotificationType>(`Invalid shared vault user permission ${notificationType}`)
|
||||
const isValidType = Object.values(this.TYPES).includes(notificationType)
|
||||
if (!isValidType) {
|
||||
return Result.fail<NotificationType>(`Invalid notification type: ${notificationType}`)
|
||||
} else {
|
||||
return Result.ok<NotificationType>(new NotificationType({ value: notificationType }))
|
||||
}
|
||||
@@ -9,6 +9,8 @@ export * from './Cache/CacheEntry'
|
||||
export * from './Cache/CacheEntryProps'
|
||||
export * from './Cache/CacheEntryRepositoryInterface'
|
||||
|
||||
export * from './Common/ContentType'
|
||||
export * from './Common/ContentTypeProps'
|
||||
export * from './Common/Dates'
|
||||
export * from './Common/DatesProps'
|
||||
export * from './Common/Email'
|
||||
@@ -43,6 +45,11 @@ export * from './Env/AbstractEnv'
|
||||
|
||||
export * from './Mapping/MapperInterface'
|
||||
|
||||
export * from './Notification/NotificationPayload'
|
||||
export * from './Notification/NotificationPayloadProps'
|
||||
export * from './Notification/NotificationType'
|
||||
export * from './Notification/NotificationTypeProps'
|
||||
|
||||
export * from './Service/ServiceConfiguration'
|
||||
export * from './Service/ServiceContainer'
|
||||
export * from './Service/ServiceContainerInterface'
|
||||
|
||||
@@ -3,6 +3,22 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.11.9](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.11.8...@standardnotes/event-store@1.11.9) (2023-07-21)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/event-store
|
||||
|
||||
## [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
|
||||
|
||||
## [1.11.5](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.11.4...@standardnotes/event-store@1.11.5) (2023-07-07)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/event-store
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/event-store",
|
||||
"version": "1.11.5",
|
||||
"version": "1.11.9",
|
||||
"description": "Event Store Service",
|
||||
"private": true,
|
||||
"main": "dist/src/index.js",
|
||||
|
||||
@@ -3,6 +3,32 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.19.11](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.19.10...@standardnotes/files-server@1.19.11) (2023-07-21)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/files-server
|
||||
|
||||
## [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
|
||||
|
||||
## [1.19.5](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.19.4...@standardnotes/files-server@1.19.5) (2023-07-07)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/files-server
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/files-server",
|
||||
"version": "1.19.5",
|
||||
"version": "1.19.11",
|
||||
"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",
|
||||
|
||||
@@ -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()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -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.',
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
LOG_LEVEL=debug
|
||||
NODE_ENV=development
|
||||
E2E_TESTING=false
|
||||
|
||||
JWT_SECRET=
|
||||
AUTH_JWT_SECRET=
|
||||
|
||||
@@ -3,6 +3,96 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.13.4](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.13.3...@standardnotes/home-server@1.13.4) (2023-07-21)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/home-server
|
||||
|
||||
## [1.13.3](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.13.2...@standardnotes/home-server@1.13.3) (2023-07-21)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/home-server
|
||||
|
||||
## [1.13.2](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.13.1...@standardnotes/home-server@1.13.2) (2023-07-20)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/home-server
|
||||
|
||||
## [1.13.1](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.13.0...@standardnotes/home-server@1.13.1) (2023-07-19)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/home-server
|
||||
|
||||
# [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
|
||||
|
||||
## [1.11.38](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.11.37...@standardnotes/home-server@1.11.38) (2023-07-11)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/home-server
|
||||
|
||||
## [1.11.37](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.11.36...@standardnotes/home-server@1.11.37) (2023-07-10)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/home-server
|
||||
|
||||
## [1.11.36](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.11.35...@standardnotes/home-server@1.11.36) (2023-07-10)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/home-server
|
||||
|
||||
## [1.11.35](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.11.34...@standardnotes/home-server@1.11.35) (2023-07-10)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/home-server
|
||||
|
||||
## [1.11.34](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.11.33...@standardnotes/home-server@1.11.34) (2023-07-10)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/home-server
|
||||
|
||||
## [1.11.33](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.11.32...@standardnotes/home-server@1.11.33) (2023-07-10)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/home-server
|
||||
|
||||
## [1.11.32](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.11.31...@standardnotes/home-server@1.11.32) (2023-07-07)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/home-server
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/home-server",
|
||||
"version": "1.11.32",
|
||||
"version": "1.13.4",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <21.0.0"
|
||||
},
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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>
|
||||
}
|
||||
|
||||
@@ -3,6 +3,30 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.25.2](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.25.1...@standardnotes/revisions-server@1.25.2) (2023-07-21)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/revisions-server
|
||||
|
||||
## [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
|
||||
|
||||
* domain items ([#655](https://github.com/standardnotes/server/issues/655)) ([a0af8f0](https://github.com/standardnotes/server/commit/a0af8f00252e1219e58cb7e066c11a8e71692e9d))
|
||||
|
||||
## [1.23.9](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.23.8...@standardnotes/revisions-server@1.23.9) (2023-07-07)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/revisions-server
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/revisions-server",
|
||||
"version": "1.23.9",
|
||||
"version": "1.25.2",
|
||||
"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.25.3",
|
||||
"@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",
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user