Compare commits

...

34 Commits

Author SHA1 Message Date
standardci 647aeda1de chore(release): publish new version
- @standardnotes/auth-server@1.163.1
 - @standardnotes/home-server@1.18.11
2023-10-30 11:20:27 +00:00
Karol Sójko 78ff748d91 fix(auth): add more information on the listed creation error 2023-10-30 11:52:26 +01:00
standardci 31f8cf1169 chore(release): publish new version
- @standardnotes/api-gateway@1.81.6
 - @standardnotes/home-server@1.18.10
2023-10-27 10:03:28 +00:00
Karol Sójko 14bcf7b6c9 fix(api-gateway): logs for errors reaching service 2023-10-27 11:36:52 +02:00
standardci 74adddd1e7 chore(release): publish new version
- @standardnotes/analytics@2.32.4
 - @standardnotes/api-gateway@1.81.5
 - @standardnotes/auth-server@1.163.0
 - @standardnotes/domain-core@1.40.0
 - @standardnotes/event-store@1.13.17
 - @standardnotes/files-server@1.32.2
 - @standardnotes/home-server@1.18.9
 - @standardnotes/revisions-server@1.47.3
 - @standardnotes/scheduler-server@1.26.4
 - @standardnotes/settings@1.22.0
 - @standardnotes/syncing-server@1.119.3
 - @standardnotes/websockets-server@1.17.4
2023-10-26 13:52:56 +00:00
Karol Sójko 0e43bc0042 feat: extract setting name to domain-core package 2023-10-26 15:18:11 +02:00
standardci b40d539611 chore(release): publish new version
- @standardnotes/api-gateway@1.81.4
 - @standardnotes/home-server@1.18.8
2023-10-26 11:53:47 +00:00
Karol Sójko 654663d17f fix(api-gateway): retry attempts and logs 2023-10-26 13:27:27 +02:00
standardci 75830c3a98 chore(release): publish new version
- @standardnotes/analytics@2.32.3
 - @standardnotes/api-gateway@1.81.3
 - @standardnotes/auth-server@1.162.0
 - @standardnotes/domain-core@1.39.0
 - @standardnotes/event-store@1.13.16
 - @standardnotes/files-server@1.32.1
 - @standardnotes/home-server@1.18.7
 - @standardnotes/revisions-server@1.47.2
 - @standardnotes/scheduler-server@1.26.3
 - @standardnotes/settings@1.21.47
 - @standardnotes/syncing-server@1.119.2
 - @standardnotes/websockets-server@1.17.3
2023-10-26 11:13:35 +00:00
Karol Sójko 1b5078eb96 feat: refactor settings (#890)
* feat: refactor settings

* fix verify mfa specs and data source metadata

* fix: compound index field names

* fix metadata binding for typeorm repository

* fix responses to preserve e2e

* fixes for e2e

* fix recovery codes e2e

* add missing specs
2023-10-26 12:42:30 +02:00
standardci a5e019e290 chore(release): publish new version
- @standardnotes/auth-server@1.161.0
 - @standardnotes/home-server@1.18.6
2023-10-23 12:29:33 +00:00
Karol Sójko a812f3400a feat(auth): remove axios http calls to payments server (#889)
* feat(auth): remove axios http calls to payments server

* fix: remove unused variable

* fix: remove another unused variable
2023-10-23 14:01:22 +02:00
Karol Sójko 15af5635f0 fix: allow to cancel previous subscription when activating premium features in e2e tests 2023-10-23 11:44:35 +02:00
standardci cee6d62791 chore(release): publish new version
- @standardnotes/api-gateway@1.81.2
 - @standardnotes/home-server@1.18.5
2023-10-20 10:13:15 +00:00
Karol Sójko 6aee51bd45 fix(api-gateway): add session validation retry attempts on timedout requests 2023-10-20 11:46:29 +02:00
standardci 599a84e634 chore(release): publish new version
- @standardnotes/api-gateway@1.81.1
 - @standardnotes/home-server@1.18.4
2023-10-20 08:52:56 +00:00
Karol Sójko 1c3d19cca4 fix(api-gateway): logs severity on retry attempts 2023-10-20 10:21:10 +02:00
standardci 9986e8e7ce chore(release): publish new version
- @standardnotes/home-server@1.18.3
 - @standardnotes/revisions-server@1.47.1
 - @standardnotes/syncing-server@1.119.1
2023-10-20 08:12:46 +00:00
Karol Sójko e19f7a7b7f fix: merge mysql and mysql-legacy together (#883) 2023-10-20 09:42:10 +02:00
Karol Sójko d570146378 fix: publishing workflow 2023-10-20 09:40:54 +02:00
standardci 8a9e4370e5 chore(release): publish new version
- @standardnotes/api-gateway@1.81.0
 - @standardnotes/home-server@1.18.2
2023-10-20 07:40:07 +00:00
Karol Sójko ce357679e9 feat(api-gateway): add retry attempts on timedout requests (#885) 2023-10-20 09:24:01 +02:00
standardci acab402747 chore(release): publish new version
- @standardnotes/api-gateway@1.80.1
 - @standardnotes/home-server@1.18.1
2023-10-19 18:17:41 +00:00
Karol Sójko e385926046 fix(api-gateway): stringify error in service proxy 2023-10-19 20:01:18 +02:00
standardci e9b8d0ceb7 chore(release): publish new version
- @standardnotes/analytics@2.32.2
 - @standardnotes/api-gateway@1.80.0
 - @standardnotes/auth-server@1.160.0
 - @standardnotes/domain-core@1.38.0
 - @standardnotes/domain-events-infra@1.20.2
 - @standardnotes/domain-events@2.133.0
 - @standardnotes/event-store@1.13.15
 - @standardnotes/files-server@1.32.0
 - @standardnotes/home-server@1.18.0
 - @standardnotes/revisions-server@1.47.0
 - @standardnotes/scheduler-server@1.26.2
 - @standardnotes/security@1.16.0
 - @standardnotes/settings@1.21.46
 - @standardnotes/syncing-server@1.119.0
 - @standardnotes/websockets-server@1.17.2
2023-10-19 09:56:55 +00:00
Karol Sójko a2c1ebe675 feat: remove transition state (#882)
* fix: Dockerfile build deps

* feat: remove transition state
2023-10-19 11:38:16 +02:00
Karol Sójko 3ef8e9ea24 fix: re-enable vault tests (#875) 2023-10-18 11:14:24 +02:00
standardci c99334889c chore(release): publish new version
- @standardnotes/analytics@2.32.1
 - @standardnotes/api-gateway@1.79.14
 - @standardnotes/auth-server@1.159.2
 - @standardnotes/domain-events-infra@1.20.1
 - @standardnotes/event-store@1.13.14
 - @standardnotes/files-server@1.31.1
 - @standardnotes/home-server@1.17.17
 - @standardnotes/revisions-server@1.46.1
 - @standardnotes/scheduler-server@1.26.1
 - @standardnotes/syncing-server@1.118.1
 - @standardnotes/websockets-server@1.17.1
2023-10-18 08:41:21 +00:00
Karol Sójko 7ce9aba517 fix: remove ip attributes in opentelemetry http instrumentation (#874) 2023-10-18 10:21:35 +02:00
Karol Sójko 46257a058b chore: allow only direct updates for dependabot: 2023-10-18 09:32:25 +02:00
dependabot[bot] 979dc35cfc chore(deps): bump actions/checkout from 3 to 4 (#817)
Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-17 14:02:56 +02:00
standardci c99a447a04 chore(release): publish new version
- @standardnotes/auth-server@1.159.1
 - @standardnotes/home-server@1.17.16
2023-10-17 11:58:49 +00:00
Karol Sójko 6dd9fd5abd fix: remove secrets from e2e test suites 2023-10-17 13:40:52 +02:00
Karol Sójko 0d37cb293c fix(auth): traversing through users in transition 2023-10-17 13:25:20 +02:00
451 changed files with 6029 additions and 14422 deletions
+40
View File
@@ -9,101 +9,141 @@ updates:
directory: "/"
schedule:
interval: "daily"
allow:
- dependency-type: "direct"
- package-ecosystem: "npm"
directory: "/packages/analytics"
schedule:
interval: "daily"
allow:
- dependency-type: "direct"
- package-ecosystem: "npm"
directory: "/packages/api-gateway"
schedule:
interval: "daily"
allow:
- dependency-type: "direct"
- package-ecosystem: "npm"
directory: "/packages/auth"
schedule:
interval: "daily"
allow:
- dependency-type: "direct"
- package-ecosystem: "npm"
directory: "/packages/common"
schedule:
interval: "daily"
allow:
- dependency-type: "direct"
- package-ecosystem: "npm"
directory: "/packages/domain-core"
schedule:
interval: "daily"
allow:
- dependency-type: "direct"
- package-ecosystem: "npm"
directory: "/packages/domain-events"
schedule:
interval: "daily"
allow:
- dependency-type: "direct"
- package-ecosystem: "npm"
directory: "/packages/domain-events-infra"
schedule:
interval: "daily"
allow:
- dependency-type: "direct"
- package-ecosystem: "npm"
directory: "/packages/event-store"
schedule:
interval: "daily"
allow:
- dependency-type: "direct"
- package-ecosystem: "npm"
directory: "/packages/files"
schedule:
interval: "daily"
allow:
- dependency-type: "direct"
- package-ecosystem: "npm"
directory: "/packages/home-server"
schedule:
interval: "daily"
allow:
- dependency-type: "direct"
- package-ecosystem: "npm"
directory: "/packages/predicates"
schedule:
interval: "daily"
allow:
- dependency-type: "direct"
- package-ecosystem: "npm"
directory: "/packages/revisions"
schedule:
interval: "daily"
allow:
- dependency-type: "direct"
- package-ecosystem: "npm"
directory: "/packages/scheduler"
schedule:
interval: "daily"
allow:
- dependency-type: "direct"
- package-ecosystem: "npm"
directory: "/packages/security"
schedule:
interval: "daily"
allow:
- dependency-type: "direct"
- package-ecosystem: "npm"
directory: "/packages/settings"
schedule:
interval: "daily"
allow:
- dependency-type: "direct"
- package-ecosystem: "npm"
directory: "/packages/sncrypto-node"
schedule:
interval: "daily"
allow:
- dependency-type: "direct"
- package-ecosystem: "npm"
directory: "/packages/syncing-server"
schedule:
interval: "daily"
allow:
- dependency-type: "direct"
- package-ecosystem: "npm"
directory: "/packages/time"
schedule:
interval: "daily"
allow:
- dependency-type: "direct"
- package-ecosystem: "npm"
directory: "/packages/websockets"
schedule:
interval: "daily"
allow:
- dependency-type: "direct"
- package-ecosystem: "github-actions"
directory: "/"
+1 -1
View File
@@ -27,7 +27,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: actions/setup-python@v4
with:
-11
View File
@@ -11,15 +11,6 @@ on:
type: string
default: all
description: The test suite to run
secrets:
DOCKER_USERNAME:
required: true
DOCKER_PASSWORD:
required: true
AWS_ACCESS_KEY_ID:
required: true
AWS_SECRET_ACCESS_KEY:
required: true
jobs:
e2e-self-hosted:
@@ -27,11 +18,9 @@ jobs:
with:
snjs_image_tag: ${{ inputs.snjs_image_tag }}
suite: ${{ inputs.suite }}
secrets: inherit
e2e-home-server:
uses: standardnotes/server/.github/workflows/e2e-home-server.yml@main
with:
snjs_image_tag: ${{ inputs.snjs_image_tag }}
suite: ${{ inputs.suite }}
secrets: inherit
+1 -1
View File
@@ -17,7 +17,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Login to Docker Hub
uses: docker/login-action@v2
+1 -10
View File
@@ -11,15 +11,6 @@ on:
type: string
default: all
description: The test suite to run
secrets:
DOCKER_USERNAME:
required: true
DOCKER_PASSWORD:
required: true
AWS_ACCESS_KEY_ID:
required: true
AWS_SECRET_ACCESS_KEY:
required: true
jobs:
e2e-home-server:
@@ -52,7 +43,7 @@ jobs:
MYSQL_PASSWORD: standardnotes
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Node
uses: actions/setup-node@v3
+1 -10
View File
@@ -11,15 +11,6 @@ on:
type: string
default: all
description: The test suite to run
secrets:
DOCKER_USERNAME:
required: true
DOCKER_PASSWORD:
required: true
AWS_ACCESS_KEY_ID:
required: true
AWS_SECRET_ACCESS_KEY:
required: true
jobs:
e2e:
@@ -35,7 +26,7 @@ jobs:
- 9001:9001
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Node
uses: actions/setup-node@v3
-1
View File
@@ -31,4 +31,3 @@ jobs:
with:
snjs_image_tag: ${{ inputs.snjs_image_tag || 'latest' }}
suite: ${{ inputs.suite || 'all' }}
secrets: inherit
+10 -12
View File
@@ -9,7 +9,7 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Cache build
id: cache-build
@@ -37,7 +37,7 @@ jobs:
needs: build
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Cache build
id: cache-build
@@ -69,7 +69,7 @@ jobs:
needs: build
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Cache build
id: cache-build
@@ -102,13 +102,11 @@ jobs:
with:
snjs_image_tag: 'latest'
suite: 'base'
secrets: inherit
# e2e-vaults:
# needs: build
# name: E2E Vaults Suite
# uses: standardnotes/server/.github/workflows/common-e2e.yml@main
# with:
# snjs_image_tag: 'latest'
# suite: 'vaults'
# secrets: inherit
e2e-vaults:
needs: build
name: E2E Vaults Suite
uses: standardnotes/server/.github/workflows/common-e2e.yml@main
with:
snjs_image_tag: 'latest'
suite: 'vaults'
+13 -15
View File
@@ -9,7 +9,7 @@ jobs:
if: contains(github.event.head_commit.message, 'chore(release)') == false
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Cache build
id: cache-build
@@ -37,7 +37,7 @@ jobs:
needs: build
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Cache build
id: cache-build
@@ -69,7 +69,7 @@ jobs:
needs: build
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Cache build
id: cache-build
@@ -102,31 +102,29 @@ jobs:
with:
snjs_image_tag: 'latest'
suite: 'base'
secrets: inherit
# e2e-vaults:
# needs: build
# name: E2E Vaults Suite
# uses: standardnotes/server/.github/workflows/common-e2e.yml@main
# with:
# snjs_image_tag: 'latest'
# suite: 'vaults'
# secrets: inherit
e2e-vaults:
needs: build
name: E2E Vaults Suite
uses: standardnotes/server/.github/workflows/common-e2e.yml@main
with:
snjs_image_tag: 'latest'
suite: 'vaults'
publish-self-hosting:
needs: [ test, lint, e2e-base ]
needs: [ test, lint, e2e-base, e2e-vaults ]
name: Publish Self Hosting Docker Image
uses: standardnotes/server/.github/workflows/common-self-hosting.yml@main
secrets: inherit
publish-services:
needs: [ test, lint, e2e-base ]
needs: [ test, lint, e2e-base, e2e-vaults ]
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
token: ${{ secrets.CI_PAT_TOKEN }}
fetch-depth: 0
Generated
+355 -531
View File
File diff suppressed because it is too large Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+2
View File
@@ -3,6 +3,8 @@ FROM node:20.6.1-alpine
ENV NODE_ENV production
RUN apk add --update --no-cache \
g++ \
make \
openssl \
curl \
bash \
-3
View File
@@ -57,9 +57,6 @@ fi
if [ -z "$CACHE_TYPE" ]; then
export CACHE_TYPE="redis"
fi
if [ -z "$SECONDARY_DB_ENABLED" ]; then
export SECONDARY_DB_ENABLED=false
fi
export DB_MIGRATIONS_PATH="dist/migrations/*.js"
#########
+16
View File
@@ -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.
## [2.32.4](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.32.3...@standardnotes/analytics@2.32.4) (2023-10-26)
**Note:** Version bump only for package @standardnotes/analytics
## [2.32.3](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.32.2...@standardnotes/analytics@2.32.3) (2023-10-26)
**Note:** Version bump only for package @standardnotes/analytics
## [2.32.2](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.32.1...@standardnotes/analytics@2.32.2) (2023-10-19)
**Note:** Version bump only for package @standardnotes/analytics
## [2.32.1](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.32.0...@standardnotes/analytics@2.32.1) (2023-10-18)
**Note:** Version bump only for package @standardnotes/analytics
# [2.32.0](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.31.7...@standardnotes/analytics@2.32.0) (2023-10-17)
### Features
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/analytics",
"version": "2.32.0",
"version": "2.32.4",
"engines": {
"node": ">=18.0.0 <21.0.0"
},
+54
View File
@@ -3,6 +3,60 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.81.6](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.81.5...@standardnotes/api-gateway@1.81.6) (2023-10-27)
### Bug Fixes
* **api-gateway:** logs for errors reaching service ([14bcf7b](https://github.com/standardnotes/api-gateway/commit/14bcf7b6c9403c3413e7579f58ea17168d14dce7))
## [1.81.5](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.81.4...@standardnotes/api-gateway@1.81.5) (2023-10-26)
**Note:** Version bump only for package @standardnotes/api-gateway
## [1.81.4](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.81.3...@standardnotes/api-gateway@1.81.4) (2023-10-26)
### Bug Fixes
* **api-gateway:** retry attempts and logs ([654663d](https://github.com/standardnotes/api-gateway/commit/654663d17f6eee15f7bf2bc7f40e6c37a3d8e53c))
## [1.81.3](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.81.2...@standardnotes/api-gateway@1.81.3) (2023-10-26)
**Note:** Version bump only for package @standardnotes/api-gateway
## [1.81.2](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.81.1...@standardnotes/api-gateway@1.81.2) (2023-10-20)
### Bug Fixes
* **api-gateway:** add session validation retry attempts on timedout requests ([6aee51b](https://github.com/standardnotes/api-gateway/commit/6aee51bd45c25e85d01075a9c8d2854b32dd6e3c))
## [1.81.1](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.81.0...@standardnotes/api-gateway@1.81.1) (2023-10-20)
### Bug Fixes
* **api-gateway:** logs severity on retry attempts ([1c3d19c](https://github.com/standardnotes/api-gateway/commit/1c3d19cca43a7a3eba2b0d05c820de5112edf89e))
# [1.81.0](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.80.1...@standardnotes/api-gateway@1.81.0) (2023-10-20)
### Features
* **api-gateway:** add retry attempts on timedout requests ([#885](https://github.com/standardnotes/api-gateway/issues/885)) ([ce35767](https://github.com/standardnotes/api-gateway/commit/ce357679e9bc704ab562e9d6ca192f49a794a664))
## [1.80.1](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.80.0...@standardnotes/api-gateway@1.80.1) (2023-10-19)
### Bug Fixes
* **api-gateway:** stringify error in service proxy ([e385926](https://github.com/standardnotes/api-gateway/commit/e38592604644e0f52df0865ffae5b7e79d1d3d07))
# [1.80.0](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.79.14...@standardnotes/api-gateway@1.80.0) (2023-10-19)
### Features
* remove transition state ([#882](https://github.com/standardnotes/api-gateway/issues/882)) ([a2c1ebe](https://github.com/standardnotes/api-gateway/commit/a2c1ebe675cd5678c923715056a6966f465a15d6))
## [1.79.14](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.79.13...@standardnotes/api-gateway@1.79.14) (2023-10-18)
**Note:** Version bump only for package @standardnotes/api-gateway
## [1.79.13](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.79.12...@standardnotes/api-gateway@1.79.13) (2023-10-17)
**Note:** Version bump only for package @standardnotes/api-gateway
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/api-gateway",
"version": "1.79.13",
"version": "1.81.6",
"engines": {
"node": ">=18.0.0 <21.0.0"
},
@@ -103,6 +103,8 @@ export class ContainerConfigLoader {
.to(SubscriptionTokenAuthMiddleware)
// Services
container.bind<TimerInterface>(TYPES.ApiGateway_Timer).toConstantValue(new Timer())
if (isConfiguredForHomeServer) {
if (!configuration?.serviceContainer) {
throw new Error('Service container is required when configured for home server')
@@ -115,7 +117,6 @@ export class ContainerConfigLoader {
} else {
container.bind<ServiceProxyInterface>(TYPES.ApiGateway_ServiceProxy).to(HttpServiceProxy)
}
container.bind<TimerInterface>(TYPES.ApiGateway_Timer).toConstantValue(new Timer())
if (isConfiguredForHomeServer) {
container
@@ -39,7 +39,7 @@ export abstract class AuthMiddleware extends BaseMiddleware {
crossServiceToken = await this.crossServiceTokenCache.get(cacheKey)
}
if (this.crossServiceTokenIsEmptyOrRequiresRevalidation(crossServiceToken)) {
if (crossServiceToken === null) {
const authResponse = await this.serviceProxy.validateSession({
authorization: authHeaderValue,
sharedVaultOwnerContext: sharedVaultOwnerContextHeaderValue,
@@ -129,14 +129,4 @@ export abstract class AuthMiddleware extends BaseMiddleware {
return Math.min(crossServiceTokenDefaultCacheExpiration, sessionAccessExpiration, sessionRefreshExpiration)
}
private crossServiceTokenIsEmptyOrRequiresRevalidation(crossServiceToken: string | null) {
if (crossServiceToken === null) {
return true
}
const decodedToken = <CrossServiceTokenData>verify(crossServiceToken, this.jwtSecret, { algorithms: ['HS256'] })
return decodedToken.ongoing_transition === true
}
}
@@ -34,16 +34,6 @@ export class ItemsController extends BaseHttpController {
)
}
@httpPost('/transition')
async transition(request: Request, response: Response): Promise<void> {
await this.serviceProxy.callSyncingServer(
request,
response,
this.endpointResolver.resolveEndpointOrMethodIdentifier('POST', 'items/transition'),
request.body,
)
}
@httpGet('/:uuid')
async getItem(request: Request, response: Response): Promise<void> {
await this.serviceProxy.callSyncingServer(
@@ -1,6 +1,6 @@
import { Request, Response } from 'express'
import { inject } from 'inversify'
import { BaseHttpController, controller, httpDelete, httpGet, httpPost } from 'inversify-express-utils'
import { BaseHttpController, controller, httpDelete, httpGet } from 'inversify-express-utils'
import { TYPES } from '../../Bootstrap/Types'
import { ServiceProxyInterface } from '../../Service/Http/ServiceProxyInterface'
@@ -55,14 +55,4 @@ export class RevisionsControllerV2 extends BaseHttpController {
),
)
}
@httpPost('/revisions/transition')
async transition(request: Request, response: Response): Promise<void> {
await this.serviceProxy.callRevisionsServer(
request,
response,
this.endpointResolver.resolveEndpointOrMethodIdentifier('POST', 'revisions/transition'),
request.body,
)
}
}
@@ -7,6 +7,7 @@ import { Logger } from 'winston'
import { TYPES } from '../../Bootstrap/Types'
import { CrossServiceTokenCacheInterface } from '../Cache/CrossServiceTokenCacheInterface'
import { ServiceProxyInterface } from './ServiceProxyInterface'
import { TimerInterface } from '@standardnotes/time'
@injectable()
export class HttpServiceProxy implements ServiceProxyInterface {
@@ -22,31 +23,50 @@ export class HttpServiceProxy implements ServiceProxyInterface {
@inject(TYPES.ApiGateway_HTTP_CALL_TIMEOUT) private httpCallTimeout: number,
@inject(TYPES.ApiGateway_CrossServiceTokenCache) private crossServiceTokenCache: CrossServiceTokenCacheInterface,
@inject(TYPES.ApiGateway_Logger) private logger: Logger,
@inject(TYPES.ApiGateway_Timer) private timer: TimerInterface,
) {}
async validateSession(headers: {
authorization: string
sharedVaultOwnerContext?: string
}): Promise<{ status: number; data: unknown; headers: { contentType: string } }> {
const authResponse = await this.httpClient.request({
method: 'POST',
headers: {
Authorization: headers.authorization,
Accept: 'application/json',
'x-shared-vault-owner-context': headers.sharedVaultOwnerContext,
},
validateStatus: (status: number) => {
return status >= 200 && status < 500
},
url: `${this.authServerUrl}/sessions/validate`,
})
async validateSession(
headers: {
authorization: string
sharedVaultOwnerContext?: string
},
retryAttempt?: number,
): Promise<{ status: number; data: unknown; headers: { contentType: string } }> {
try {
const authResponse = await this.httpClient.request({
method: 'POST',
headers: {
Authorization: headers.authorization,
Accept: 'application/json',
'x-shared-vault-owner-context': headers.sharedVaultOwnerContext,
},
validateStatus: (status: number) => {
return status >= 200 && status < 500
},
url: `${this.authServerUrl}/sessions/validate`,
})
return {
status: authResponse.status,
data: authResponse.data,
headers: {
contentType: authResponse.headers['content-type'] as string,
},
return {
status: authResponse.status,
data: authResponse.data,
headers: {
contentType: authResponse.headers['content-type'] as string,
},
}
} catch (error) {
const requestTimedOut =
'code' in (error as Record<string, unknown>) && (error as Record<string, unknown>).code === 'ETIMEDOUT'
const tooManyRetryAttempts = retryAttempt && retryAttempt > 2
if (!tooManyRetryAttempts && requestTimedOut) {
await this.timer.sleep(50)
const nextRetryAttempt = retryAttempt ? retryAttempt + 1 : 1
return this.validateSession(headers, nextRetryAttempt)
}
throw error
}
}
@@ -169,6 +189,7 @@ export class HttpServiceProxy implements ServiceProxyInterface {
response: Response,
endpointOrMethodIdentifier: string,
payload?: Record<string, unknown> | string,
retryAttempt?: number,
): Promise<AxiosResponse | undefined> {
try {
const headers: Record<string, string> = {}
@@ -211,17 +232,47 @@ export class HttpServiceProxy implements ServiceProxyInterface {
await this.crossServiceTokenCache.invalidate(userUuid)
}
if (retryAttempt) {
this.logger.debug(
`Request to ${serverUrl}/${endpointOrMethodIdentifier} succeeded after ${retryAttempt} retries`,
)
}
return serviceResponse
} catch (error) {
const errorMessage = (error as AxiosError).isAxiosError
? JSON.stringify((error as AxiosError).response?.data)
: (error as Error).message
const requestDidNotMakeIt = this.requestTimedOutOrDidNotReachDestination(error as Record<string, unknown>)
const tooManyRetryAttempts = retryAttempt && retryAttempt > 2
if (!tooManyRetryAttempts && requestDidNotMakeIt) {
await this.timer.sleep(50)
const nextRetryAttempt = retryAttempt ? retryAttempt + 1 : 1
this.logger.debug(
`Retrying request to ${serverUrl}/${endpointOrMethodIdentifier} for the ${nextRetryAttempt} time`,
)
return this.getServerResponse(
serverUrl,
request,
response,
endpointOrMethodIdentifier,
payload,
nextRetryAttempt,
)
}
let detailedErrorMessage = (error as Error).message
if (error instanceof AxiosError) {
detailedErrorMessage = `Status: ${error.status}, code: ${error.code}, message: ${error.message}`
}
this.logger.error(
`Could not pass the request to ${serverUrl}/${endpointOrMethodIdentifier} on underlying service: ${errorMessage}`,
tooManyRetryAttempts
? `Request to ${serverUrl}/${endpointOrMethodIdentifier} timed out after ${retryAttempt} retries`
: `Could not pass the request to ${serverUrl}/${endpointOrMethodIdentifier} on underlying service: ${detailedErrorMessage}`,
)
this.logger.debug('Response error: %O', (error as AxiosError).response ?? error)
this.logger.debug(`Response error: ${JSON.stringify(error)}`)
if ((error as AxiosError).response?.headers['content-type']) {
response.setHeader('content-type', (error as AxiosError).response?.headers['content-type'] as string)
@@ -232,7 +283,14 @@ export class HttpServiceProxy implements ServiceProxyInterface {
? +((error as AxiosError).code as string)
: 500
response.status(errorCode).send(errorMessage)
const responseErrorMessage = (error as AxiosError).response?.data
response
.status(errorCode)
.send(
responseErrorMessage ??
"Unfortunately, we couldn't handle your request. Please try again or contact our support if the error persists.",
)
}
return
@@ -363,4 +421,13 @@ export class HttpServiceProxy implements ServiceProxyInterface {
}
})
}
private requestTimedOutOrDidNotReachDestination(error: Record<string, unknown>): boolean {
return (
('code' in error && error.code === 'ETIMEDOUT') ||
('response' in error &&
'status' in (error.response as Record<string, unknown>) &&
[503, 504].includes((error.response as Record<string, unknown>).status as number))
)
}
}
-7
View File
@@ -43,13 +43,6 @@ SNS_AWS_REGION=
SQS_QUEUE_URL=
SQS_AWS_REGION=
SYNCING_SERVER_URL=http://syncing-server-js:3000
# (Optional) User Server
USER_SERVER_REGISTRATION_URL=
USER_SERVER_CHANGE_EMAIL_URL=
USER_SERVER_AUTH_KEY=
VALET_TOKEN_SECRET=
VALET_TOKEN_TTL=
+44
View File
@@ -3,6 +3,50 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.163.1](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.163.0...@standardnotes/auth-server@1.163.1) (2023-10-30)
### Bug Fixes
* **auth:** add more information on the listed creation error ([78ff748](https://github.com/standardnotes/server/commit/78ff748d911a5a4063903847ef761822bbb8f4e2))
# [1.163.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.162.0...@standardnotes/auth-server@1.163.0) (2023-10-26)
### Features
* extract setting name to domain-core package ([0e43bc0](https://github.com/standardnotes/server/commit/0e43bc00427113f421b0c4b67c067f0de96caf52))
# [1.162.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.161.0...@standardnotes/auth-server@1.162.0) (2023-10-26)
### Features
* refactor settings ([#890](https://github.com/standardnotes/server/issues/890)) ([1b5078e](https://github.com/standardnotes/server/commit/1b5078eb9629397822f5403643c60fbf4182df92))
# [1.161.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.160.0...@standardnotes/auth-server@1.161.0) (2023-10-23)
### Bug Fixes
* allow to cancel previous subscription when activating premium features in e2e tests ([15af563](https://github.com/standardnotes/server/commit/15af5635f05a8363336aa33830e0157f519eee83))
### Features
* **auth:** remove axios http calls to payments server ([#889](https://github.com/standardnotes/server/issues/889)) ([a812f34](https://github.com/standardnotes/server/commit/a812f3400af3712fd5481b0c38c8805bb9c79e2c))
# [1.160.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.159.2...@standardnotes/auth-server@1.160.0) (2023-10-19)
### Features
* remove transition state ([#882](https://github.com/standardnotes/server/issues/882)) ([a2c1ebe](https://github.com/standardnotes/server/commit/a2c1ebe675cd5678c923715056a6966f465a15d6))
## [1.159.2](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.159.1...@standardnotes/auth-server@1.159.2) (2023-10-18)
**Note:** Version bump only for package @standardnotes/auth-server
## [1.159.1](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.159.0...@standardnotes/auth-server@1.159.1) (2023-10-17)
### Bug Fixes
* **auth:** traversing through users in transition ([0d37cb2](https://github.com/standardnotes/server/commit/0d37cb293c3f8c1fa798a3c847a1f76c18a8c3aa))
# [1.159.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.158.8...@standardnotes/auth-server@1.159.0) (2023-10-17)
### Features
+5 -5
View File
@@ -1,7 +1,7 @@
import 'reflect-metadata'
import { OpenTelemetrySDK, OpenTelemetryTracer } from '@standardnotes/domain-events-infra'
import { ServiceIdentifier } from '@standardnotes/domain-core'
import { ServiceIdentifier, SettingName } from '@standardnotes/domain-core'
const sdk = new OpenTelemetrySDK({ serviceName: ServiceIdentifier.NAMES.AuthScheduledTask })
sdk.start()
@@ -18,7 +18,7 @@ import { Env } from '../src/Bootstrap/Env'
import { DomainEventPublisherInterface } from '@standardnotes/domain-events'
import { DomainEventFactoryInterface } from '../src/Domain/Event/DomainEventFactoryInterface'
import { SettingRepositoryInterface } from '../src/Domain/Setting/SettingRepositoryInterface'
import { MuteFailedBackupsEmailsOption, SettingName } from '@standardnotes/settings'
import { MuteFailedBackupsEmailsOption } from '@standardnotes/settings'
import { RoleServiceInterface } from '../src/Domain/Role/RoleServiceInterface'
import { PermissionName } from '@standardnotes/features'
import { GetUserKeyParams } from '../src/Domain/UseCase/GetUserKeyParams/GetUserKeyParams'
@@ -62,8 +62,8 @@ const requestBackups = async (
muteEmailsSettingName,
setting.setting_user_uuid,
)
if (emailsMutedSetting !== null && emailsMutedSetting.value !== null) {
userHasEmailsMuted = emailsMutedSetting.value === muteEmailsSettingValue
if (emailsMutedSetting !== null && emailsMutedSetting.props.value !== null) {
userHasEmailsMuted = emailsMutedSetting.props.value === muteEmailsSettingValue
}
const keyParamsResponse = await getUserKeyParamsUseCase.execute({
@@ -74,7 +74,7 @@ const requestBackups = async (
await domainEventPublisher.publish(
domainEventFactory.createEmailBackupRequestedEvent(
setting.setting_user_uuid,
emailsMutedSetting?.uuid as string,
emailsMutedSetting?.id.toString() as string,
userHasEmailsMuted,
keyParamsResponse.keyParams,
),
-158
View File
@@ -1,158 +0,0 @@
import 'reflect-metadata'
import { OpenTelemetrySDK, OpenTelemetryTracer } from '@standardnotes/domain-events-infra'
import { ServiceIdentifier, RoleName, TransitionStatus } from '@standardnotes/domain-core'
const sdk = new OpenTelemetrySDK({ serviceName: ServiceIdentifier.NAMES.AuthScheduledTask })
sdk.start()
import { Logger } from 'winston'
import * as dayjs from 'dayjs'
import * as utc from 'dayjs/plugin/utc'
import { ContainerConfigLoader } from '../src/Bootstrap/Container'
import TYPES from '../src/Bootstrap/Types'
import { Env } from '../src/Bootstrap/Env'
import { DomainEventPublisherInterface } from '@standardnotes/domain-events'
import { DomainEventFactoryInterface } from '../src/Domain/Event/DomainEventFactoryInterface'
import { UserRepositoryInterface } from '../src/Domain/User/UserRepositoryInterface'
import { TimerInterface } from '@standardnotes/time'
import { TransitionStatusRepositoryInterface } from '../src/Domain/Transition/TransitionStatusRepositoryInterface'
const inputArgs = process.argv.slice(2)
const startDateString = inputArgs[0]
const endDateString = inputArgs[1]
const forceRunParam = inputArgs[2]
const requestTransition = async (
transitionStatusRepository: TransitionStatusRepositoryInterface,
userRepository: UserRepositoryInterface,
logger: Logger,
domainEventFactory: DomainEventFactoryInterface,
domainEventPublisher: DomainEventPublisherInterface,
timer: TimerInterface,
): Promise<void> => {
const startDate = new Date(startDateString)
const endDate = new Date(endDateString)
const users = await userRepository.findAllCreatedBetween(startDate, endDate)
const timestamp = timer.getTimestampInMicroseconds()
logger.info(
`[TRANSITION ${timestamp}] Found ${users.length} users created between ${startDateString} and ${endDateString}`,
)
let itemTransitionsTriggered = 0
let revisionTransitionsTriggered = 0
const forceRun = forceRunParam === 'true'
for (const user of users) {
const itemsTransitionStatus = await transitionStatusRepository.getStatus(user.uuid, 'items')
const revisionsTransitionStatus = await transitionStatusRepository.getStatus(user.uuid, 'revisions')
const userRoles = await user.roles
const userHasTransitionRole = userRoles.some((role) => role.name === RoleName.NAMES.TransitionUser)
const bothTransitionStatusesAreVerified =
itemsTransitionStatus?.value === TransitionStatus.STATUSES.Verified &&
revisionsTransitionStatus?.value === TransitionStatus.STATUSES.Verified
if (!userHasTransitionRole && bothTransitionStatusesAreVerified) {
continue
}
logger.info(
`[TRANSITION ${timestamp}] Transition status for user ${user.uuid} - items status: ${itemsTransitionStatus?.value}, revisions status: ${revisionsTransitionStatus?.value}, has transition role: ${userHasTransitionRole}`,
)
if (
itemsTransitionStatus === null ||
itemsTransitionStatus.value === TransitionStatus.STATUSES.Failed ||
(itemsTransitionStatus.value === TransitionStatus.STATUSES.InProgress && forceRun)
) {
await transitionStatusRepository.remove(user.uuid, 'items')
await domainEventPublisher.publish(
domainEventFactory.createTransitionRequestedEvent({
userUuid: user.uuid,
type: 'items',
timestamp,
}),
)
itemTransitionsTriggered++
}
if (
revisionsTransitionStatus === null ||
revisionsTransitionStatus.value === TransitionStatus.STATUSES.Failed ||
(revisionsTransitionStatus.value === TransitionStatus.STATUSES.InProgress && forceRun)
) {
await transitionStatusRepository.remove(user.uuid, 'revisions')
await domainEventPublisher.publish(
domainEventFactory.createTransitionRequestedEvent({
userUuid: user.uuid,
type: 'revisions',
timestamp,
}),
)
revisionTransitionsTriggered++
}
}
logger.info(
`[TRANSITION ${timestamp}] Triggered ${itemTransitionsTriggered} item transitions and ${revisionTransitionsTriggered} revision transitions for users created between ${startDateString} and ${endDateString}`,
)
}
const container = new ContainerConfigLoader('worker')
void container.load().then((container) => {
dayjs.extend(utc)
const env: Env = new Env()
env.load()
const logger: Logger = container.get(TYPES.Auth_Logger)
logger.info(`Starting transition request for users created between ${startDateString} and ${endDateString}`)
const userRepository: UserRepositoryInterface = container.get(TYPES.Auth_UserRepository)
const domainEventFactory: DomainEventFactoryInterface = container.get(TYPES.Auth_DomainEventFactory)
const domainEventPublisher: DomainEventPublisherInterface = container.get(TYPES.Auth_DomainEventPublisher)
const timer = container.get<TimerInterface>(TYPES.Auth_Timer)
const transitionStatusRepository = container.get<TransitionStatusRepositoryInterface>(
TYPES.Auth_TransitionStatusRepository,
)
const tracer = new OpenTelemetryTracer()
tracer.startSpan(ServiceIdentifier.NAMES.AuthScheduledTask, 'transition')
Promise.resolve(
requestTransition(
transitionStatusRepository,
userRepository,
logger,
domainEventFactory,
domainEventPublisher,
timer,
),
)
.then(() => {
logger.info(`Finished transition request for users created between ${startDateString} and ${endDateString}`)
tracer.stopSpan()
process.exit(0)
})
.catch((error) => {
logger.error(
`Error while requesting transition for users created between ${startDateString} and ${endDateString}: ${error}`,
)
tracer.stopSpanWithError(error)
process.exit(1)
})
})
+5 -5
View File
@@ -1,7 +1,7 @@
import 'reflect-metadata'
import { OpenTelemetrySDK, OpenTelemetryTracer } from '@standardnotes/domain-events-infra'
import { Email, ServiceIdentifier } from '@standardnotes/domain-core'
import { Email, ServiceIdentifier, SettingName } from '@standardnotes/domain-core'
const sdk = new OpenTelemetrySDK({ serviceName: ServiceIdentifier.NAMES.AuthScheduledTask })
sdk.start()
@@ -16,7 +16,7 @@ import { Env } from '../src/Bootstrap/Env'
import { DomainEventPublisherInterface } from '@standardnotes/domain-events'
import { DomainEventFactoryInterface } from '../src/Domain/Event/DomainEventFactoryInterface'
import { SettingRepositoryInterface } from '../src/Domain/Setting/SettingRepositoryInterface'
import { MuteFailedBackupsEmailsOption, SettingName } from '@standardnotes/settings'
import { MuteFailedBackupsEmailsOption } from '@standardnotes/settings'
import { RoleServiceInterface } from '../src/Domain/Role/RoleServiceInterface'
import { PermissionName } from '@standardnotes/features'
import { UserRepositoryInterface } from '../src/Domain/User/UserRepositoryInterface'
@@ -55,8 +55,8 @@ const requestBackups = async (
let userHasEmailsMuted = false
const emailsMutedSetting = await settingRepository.findOneByNameAndUserUuid(muteEmailsSettingName, user.uuid)
if (emailsMutedSetting !== null && emailsMutedSetting.value !== null) {
userHasEmailsMuted = emailsMutedSetting.value === muteEmailsSettingValue
if (emailsMutedSetting !== null && emailsMutedSetting.props.value !== null) {
userHasEmailsMuted = emailsMutedSetting.props.value === muteEmailsSettingValue
}
const keyParamsResponse = await getUserKeyParamsUseCase.execute({
@@ -67,7 +67,7 @@ const requestBackups = async (
await domainEventPublisher.publish(
domainEventFactory.createEmailBackupRequestedEvent(
user.uuid,
emailsMutedSetting?.uuid as string,
emailsMutedSetting?.id.toString() as string,
userHasEmailsMuted,
keyParamsResponse.keyParams,
),
@@ -1,11 +0,0 @@
'use strict'
const path = require('path')
const pnp = require(path.normalize(path.resolve(__dirname, '../../..', '.pnp.cjs'))).setup()
const index = require(path.normalize(path.resolve(__dirname, '../dist/bin/transition.js')))
Object.defineProperty(exports, '__esModule', { value: true })
exports.default = index
-7
View File
@@ -55,13 +55,6 @@ case "$COMMAND" in
node docker/entrypoint-backup.js one_drive daily
;;
'transition' )
START_DATE=$1 && shift 1
END_DATE=$1 && shift 1
echo "[Docker] Starting Transition..."
node docker/entrypoint-transition.js $START_DATE $END_DATE
;;
* )
echo "[Docker] Unknown command"
;;
@@ -1,10 +1,10 @@
import Redis, { Cluster } from 'ioredis'
import { SettingName } from '@standardnotes/settings'
import { MigrationInterface, QueryRunner } from 'typeorm'
import { Setting } from '../../src/Domain/Setting/Setting'
import { User } from '../../src/Domain/User/User'
import { EncryptionVersion } from '../../src/Domain/Encryption/EncryptionVersion'
import { SettingName, Timestamps, UniqueEntityId, Uuid } from '@standardnotes/domain-core'
export class moveMfaItemsToUserSettings1627638504691 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<void> {
@@ -32,19 +32,21 @@ export class moveMfaItemsToUserSettings1627638504691 implements MigrationInterfa
usersMFAStatus.set(item['user_uuid'], 1)
usersMFAUpdatedAt.set(item['user_uuid'], item['updated_at_timestamp'])
const setting = new Setting()
setting.uuid = item['uuid']
setting.name = SettingName.NAMES.MfaSecret
setting.value = item['content']
const settingOrError = Setting.create(
{
name: SettingName.NAMES.MfaSecret,
value: item['deleted'] ? null : item['content'],
serverEncryptionVersion: EncryptionVersion.Unencrypted,
timestamps: Timestamps.create(item['created_at_timestamp'], item['updated_at_timestamp']).getValue(),
userUuid: Uuid.create(user.uuid).getValue(),
sensitive: true,
},
new UniqueEntityId(item['uuid']),
)
if (item['deleted']) {
setting.value = null
usersMFAStatus.set(item['user_uuid'], 0)
}
setting.serverEncryptionVersion = EncryptionVersion.Unencrypted
setting.createdAt = item['created_at_timestamp']
setting.updatedAt = item['updated_at_timestamp']
setting.user = Promise.resolve(user)
await queryRunner.manager.save(setting)
await queryRunner.manager.save(settingOrError.getValue())
}
const redisClient = this.getRedisClient()
@@ -1,8 +1,8 @@
import { MigrationInterface, QueryRunner } from 'typeorm'
export class UpdateUnknownContent1690975361562 implements MigrationInterface {
export class RemoveTransitionRole1697704066569 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.manager.query('UPDATE items SET content_type = "Note" WHERE content_type = "Unknown"')
await queryRunner.query('DELETE FROM `roles` WHERE name = "TRANSITION_USER"')
}
public async down(): Promise<void> {
+1 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/auth-server",
"version": "1.159.0",
"version": "1.163.1",
"engines": {
"node": ">=18.0.0 <21.0.0"
},
@@ -54,7 +54,6 @@
"@standardnotes/sncrypto-common": "^1.13.4",
"@standardnotes/sncrypto-node": "workspace:*",
"@standardnotes/time": "workspace:*",
"axios": "^1.1.3",
"bcryptjs": "2.4.3",
"cors": "2.8.5",
"dayjs": "^1.11.6",
@@ -3,7 +3,9 @@ import { Result, ServiceInterface } from '@standardnotes/domain-core'
export interface AuthServiceInterface extends ServiceInterface {
activatePremiumFeatures(dto: {
username: string
subscriptionId: number
subscriptionPlanName?: string
endsAt?: Date
cancelPreviousSubscription?: boolean
}): Promise<Result<string>>
}
+394 -163
View File
@@ -10,7 +10,7 @@ import {
DomainEventSubscriberInterface,
} from '@standardnotes/domain-events'
import { TimerInterface, Timer } from '@standardnotes/time'
import { UAParser } from 'ua-parser-js'
import { UAParser, UAParserInstance } from 'ua-parser-js'
import { Env } from './Env'
import TYPES from './Types'
@@ -45,7 +45,6 @@ import { LockRepository } from '../Infra/Redis/LockRepository'
import { TypeORMRevokedSessionRepository } from '../Infra/TypeORM/TypeORMRevokedSessionRepository'
import { AuthenticationMethodResolver } from '../Domain/Auth/AuthenticationMethodResolver'
import { RevokedSession } from '../Domain/Session/RevokedSession'
import { UserRegisteredEventHandler } from '../Domain/Handler/UserRegisteredEventHandler'
import { DomainEventFactory } from '../Domain/Event/DomainEventFactory'
import { AuthenticateRequest } from '../Domain/UseCase/AuthenticateRequest'
import { Role } from '../Domain/Role/Role'
@@ -57,10 +56,7 @@ import { TypeORMSettingRepository } from '../Infra/TypeORM/TypeORMSettingReposit
import { CrypterInterface } from '../Domain/Encryption/CrypterInterface'
import { CrypterNode } from '../Domain/Encryption/CrypterNode'
import { CryptoNode } from '@standardnotes/sncrypto-node'
import { GetSettings } from '../Domain/UseCase/GetSettings/GetSettings'
import { SettingProjector } from '../Projection/SettingProjector'
import { GetSetting } from '../Domain/UseCase/GetSetting/GetSetting'
import { UpdateSetting } from '../Domain/UseCase/UpdateSetting/UpdateSetting'
import { AccountDeletionRequestedEventHandler } from '../Domain/Handler/AccountDeletionRequestedEventHandler'
import { SubscriptionPurchasedEventHandler } from '../Domain/Handler/SubscriptionPurchasedEventHandler'
import { SubscriptionRenewedEventHandler } from '../Domain/Handler/SubscriptionRenewedEventHandler'
@@ -68,11 +64,6 @@ import { SubscriptionRefundedEventHandler } from '../Domain/Handler/Subscription
import { SubscriptionExpiredEventHandler } from '../Domain/Handler/SubscriptionExpiredEventHandler'
import { DeleteAccount } from '../Domain/UseCase/DeleteAccount/DeleteAccount'
import { DeleteSetting } from '../Domain/UseCase/DeleteSetting/DeleteSetting'
import { SettingFactory } from '../Domain/Setting/SettingFactory'
import { SettingService } from '../Domain/Setting/SettingService'
// eslint-disable-next-line @typescript-eslint/no-var-requires
const axios = require('axios')
import { AxiosInstance } from 'axios'
import { UserSubscription } from '../Domain/Subscription/UserSubscription'
import { TypeORMUserSubscriptionRepository } from '../Infra/TypeORM/TypeORMUserSubscriptionRepository'
import { WebSocketsClientService } from '../Infra/WebSockets/WebSocketsClientService'
@@ -84,7 +75,6 @@ import { RoleToSubscriptionMapInterface } from '../Domain/Role/RoleToSubscriptio
import { RoleToSubscriptionMap } from '../Domain/Role/RoleToSubscriptionMap'
import { FeatureServiceInterface } from '../Domain/Feature/FeatureServiceInterface'
import { FeatureService } from '../Domain/Feature/FeatureService'
import { SettingServiceInterface } from '../Domain/Setting/SettingServiceInterface'
import { ExtensionKeyGrantedEventHandler } from '../Domain/Handler/ExtensionKeyGrantedEventHandler'
import {
DirectCallDomainEventPublisher,
@@ -117,7 +107,6 @@ import { AuthenticateOfflineSubscriptionToken } from '../Domain/UseCase/Authenti
import { SubscriptionCancelledEventHandler } from '../Domain/Handler/SubscriptionCancelledEventHandler'
import { ContentDecoder, ContentDecoderInterface, ProtocolVersion } from '@standardnotes/common'
import { GetUserOfflineSubscription } from '../Domain/UseCase/GetUserOfflineSubscription/GetUserOfflineSubscription'
import { UserEmailChangedEventHandler } from '../Domain/Handler/UserEmailChangedEventHandler'
import { SettingsAssociationServiceInterface } from '../Domain/Setting/SettingsAssociationServiceInterface'
import { SettingsAssociationService } from '../Domain/Setting/SettingsAssociationService'
import { SubscriptionSyncRequestedEventHandler } from '../Domain/Handler/SubscriptionSyncRequestedEventHandler'
@@ -143,8 +132,8 @@ import { FileRemovedEventHandler } from '../Domain/Handler/FileRemovedEventHandl
import { UserDisabledSessionUserAgentLoggingEventHandler } from '../Domain/Handler/UserDisabledSessionUserAgentLoggingEventHandler'
import { SettingInterpreterInterface } from '../Domain/Setting/SettingInterpreterInterface'
import { SettingInterpreter } from '../Domain/Setting/SettingInterpreter'
import { SettingDecrypterInterface } from '../Domain/Setting/SettingDecrypterInterface'
import { SettingDecrypter } from '../Domain/Setting/SettingDecrypter'
import { SettingCrypterInterface } from '../Domain/Setting/SettingCrypterInterface'
import { SettingCrypter } from '../Domain/Setting/SettingCrypter'
import { SharedSubscriptionInvitationRepositoryInterface } from '../Domain/SharedSubscription/SharedSubscriptionInvitationRepositoryInterface'
import { TypeORMSharedSubscriptionInvitationRepository } from '../Infra/TypeORM/TypeORMSharedSubscriptionInvitationRepository'
import { InviteToSharedSubscription } from '../Domain/UseCase/InviteToSharedSubscription/InviteToSharedSubscription'
@@ -153,16 +142,9 @@ import { AcceptSharedSubscriptionInvitation } from '../Domain/UseCase/AcceptShar
import { DeclineSharedSubscriptionInvitation } from '../Domain/UseCase/DeclineSharedSubscriptionInvitation/DeclineSharedSubscriptionInvitation'
import { CancelSharedSubscriptionInvitation } from '../Domain/UseCase/CancelSharedSubscriptionInvitation/CancelSharedSubscriptionInvitation'
import { SharedSubscriptionInvitationCreatedEventHandler } from '../Domain/Handler/SharedSubscriptionInvitationCreatedEventHandler'
import { SubscriptionSetting } from '../Domain/Setting/SubscriptionSetting'
import { SubscriptionSettingServiceInterface } from '../Domain/Setting/SubscriptionSettingServiceInterface'
import { SubscriptionSettingService } from '../Domain/Setting/SubscriptionSettingService'
import { SubscriptionSettingRepositoryInterface } from '../Domain/Setting/SubscriptionSettingRepositoryInterface'
import { TypeORMSubscriptionSettingRepository } from '../Infra/TypeORM/TypeORMSubscriptionSettingRepository'
import { SettingFactoryInterface } from '../Domain/Setting/SettingFactoryInterface'
import { ListSharedSubscriptionInvitations } from '../Domain/UseCase/ListSharedSubscriptionInvitations/ListSharedSubscriptionInvitations'
import { UserSubscriptionServiceInterface } from '../Domain/Subscription/UserSubscriptionServiceInterface'
import { UserSubscriptionService } from '../Domain/Subscription/UserSubscriptionService'
import { SubscriptionSettingProjector } from '../Projection/SubscriptionSettingProjector'
import { SubscriptionSettingsAssociationService } from '../Domain/Setting/SubscriptionSettingsAssociationService'
import { SubscriptionSettingsAssociationServiceInterface } from '../Domain/Setting/SubscriptionSettingsAssociationServiceInterface'
import { PKCERepositoryInterface } from '../Domain/User/PKCERepositoryInterface'
@@ -258,11 +240,6 @@ import { UpdateStorageQuotaUsedForUser } from '../Domain/UseCase/UpdateStorageQu
import { SharedVaultFileUploadedEventHandler } from '../Domain/Handler/SharedVaultFileUploadedEventHandler'
import { SharedVaultFileRemovedEventHandler } from '../Domain/Handler/SharedVaultFileRemovedEventHandler'
import { SharedVaultFileMovedEventHandler } from '../Domain/Handler/SharedVaultFileMovedEventHandler'
import { TransitionStatusRepositoryInterface } from '../Domain/Transition/TransitionStatusRepositoryInterface'
import { RedisTransitionStatusRepository } from '../Infra/Redis/RedisTransitionStatusRepository'
import { InMemoryTransitionStatusRepository } from '../Infra/InMemory/InMemoryTransitionStatusRepository'
import { TransitionStatusUpdatedEventHandler } from '../Domain/Handler/TransitionStatusUpdatedEventHandler'
import { UpdateTransitionStatus } from '../Domain/UseCase/UpdateTransitionStatus/UpdateTransitionStatus'
import { TypeORMSharedVaultUser } from '../Infra/TypeORM/TypeORMSharedVaultUser'
import { SharedVaultUserPersistenceMapper } from '../Mapping/SharedVaultUserPersistenceMapper'
import { SharedVaultUserRepositoryInterface } from '../Domain/SharedVault/SharedVaultUserRepositoryInterface'
@@ -276,6 +253,27 @@ import { UserDesignatedAsSurvivorInSharedVaultEventHandler } from '../Domain/Han
import { DisableEmailSettingBasedOnEmailSubscription } from '../Domain/UseCase/DisableEmailSettingBasedOnEmailSubscription/DisableEmailSettingBasedOnEmailSubscription'
import { DomainEventFactoryInterface } from '../Domain/Event/DomainEventFactoryInterface'
import { KeyParamsFactoryInterface } from '../Domain/User/KeyParamsFactoryInterface'
import { TypeORMSubscriptionSetting } from '../Infra/TypeORM/TypeORMSubscriptionSetting'
import { SetSettingValue } from '../Domain/UseCase/SetSettingValue/SetSettingValue'
import { ApplyDefaultSubscriptionSettings } from '../Domain/UseCase/ApplyDefaultSubscriptionSettings/ApplyDefaultSubscriptionSettings'
import { GetSubscriptionSetting } from '../Domain/UseCase/GetSubscriptionSetting/GetSubscriptionSetting'
import { SetSubscriptionSettingValue } from '../Domain/UseCase/SetSubscriptionSettingValue/SetSubscriptionSettingValue'
import { GetSettings } from '../Domain/UseCase/GetSettings/GetSettings'
import { GetSubscriptionSettings } from '../Domain/UseCase/GetSubscriptionSettings/GetSubscriptionSettings'
import { GetAllSettingsForUser } from '../Domain/UseCase/GetAllSettingsForUser/GetAllSettingsForUser'
import { GetRegularSubscriptionForUser } from '../Domain/UseCase/GetRegularSubscriptionForUser/GetRegularSubscriptionForUser'
import { GetSharedSubscriptionForUser } from '../Domain/UseCase/GetSharedSubscriptionForUser/GetSharedSubscriptionForUser'
import { GetSharedOrRegularSubscriptionForUser } from '../Domain/UseCase/GetSharedOrRegularSubscriptionForUser/GetSharedOrRegularSubscriptionForUser'
import { ProjectorInterface } from '../Projection/ProjectorInterface'
import { SettingHttpRepresentation } from '../Mapping/Http/SettingHttpRepresentation'
import { SubscriptionSetting } from '../Domain/Setting/SubscriptionSetting'
import { SubscriptionSettingHttpRepresentation } from '../Mapping/Http/SubscriptionSettingHttpRepresentation'
import { SettingHttpMapper } from '../Mapping/Http/SettingHttpMapper'
import { SubscriptionSettingHttpMapper } from '../Mapping/Http/SubscriptionSettingHttpMapper'
import { TypeORMSetting } from '../Infra/TypeORM/TypeORMSetting'
import { SettingPersistenceMapper } from '../Mapping/Persistence/SettingPersistenceMapper'
import { SubscriptionSettingPersistenceMapper } from '../Mapping/Persistence/SubscriptionSettingPersistenceMapper'
import { ApplyDefaultSettings } from '../Domain/UseCase/ApplyDefaultSettings/ApplyDefaultSettings'
export class ContainerConfigLoader {
constructor(private mode: 'server' | 'worker' = 'server') {}
@@ -406,6 +404,22 @@ export class ContainerConfigLoader {
container
.bind<MapperInterface<SharedVaultUser, TypeORMSharedVaultUser>>(TYPES.Auth_SharedVaultUserPersistenceMapper)
.toConstantValue(new SharedVaultUserPersistenceMapper())
container
.bind<MapperInterface<Setting, SettingHttpRepresentation>>(TYPES.Auth_SettingHttpMapper)
.toConstantValue(new SettingHttpMapper())
container
.bind<MapperInterface<SubscriptionSetting, SubscriptionSettingHttpRepresentation>>(
TYPES.Auth_SubscriptionSettingHttpMapper,
)
.toConstantValue(new SubscriptionSettingHttpMapper())
container
.bind<MapperInterface<Setting, TypeORMSetting>>(TYPES.Auth_SettingPersistenceMapper)
.toConstantValue(new SettingPersistenceMapper())
container
.bind<MapperInterface<SubscriptionSetting, TypeORMSubscriptionSetting>>(
TYPES.Auth_SubscriptionSettingPersistenceMapper,
)
.toConstantValue(new SubscriptionSettingPersistenceMapper())
// ORM
container
@@ -422,14 +436,14 @@ export class ContainerConfigLoader {
.bind<Repository<Session>>(TYPES.Auth_ORMSessionRepository)
.toConstantValue(appDataSource.getRepository(Session))
container
.bind<Repository<Setting>>(TYPES.Auth_ORMSettingRepository)
.toConstantValue(appDataSource.getRepository(Setting))
.bind<Repository<TypeORMSetting>>(TYPES.Auth_ORMSettingRepository)
.toConstantValue(appDataSource.getRepository(TypeORMSetting))
container
.bind<Repository<SharedSubscriptionInvitation>>(TYPES.Auth_ORMSharedSubscriptionInvitationRepository)
.toConstantValue(appDataSource.getRepository(SharedSubscriptionInvitation))
container
.bind<Repository<SubscriptionSetting>>(TYPES.Auth_ORMSubscriptionSettingRepository)
.toConstantValue(appDataSource.getRepository(SubscriptionSetting))
.bind<Repository<TypeORMSubscriptionSetting>>(TYPES.Auth_ORMSubscriptionSettingRepository)
.toConstantValue(appDataSource.getRepository(TypeORMSubscriptionSetting))
container.bind<Repository<User>>(TYPES.Auth_ORMUserRepository).toConstantValue(appDataSource.getRepository(User))
container
.bind<Repository<UserSubscription>>(TYPES.Auth_ORMUserSubscriptionRepository)
@@ -456,10 +470,24 @@ export class ContainerConfigLoader {
.bind<RevokedSessionRepositoryInterface>(TYPES.Auth_RevokedSessionRepository)
.to(TypeORMRevokedSessionRepository)
container.bind<UserRepositoryInterface>(TYPES.Auth_UserRepository).to(TypeORMUserRepository)
container.bind<SettingRepositoryInterface>(TYPES.Auth_SettingRepository).to(TypeORMSettingRepository)
container
.bind<SettingRepositoryInterface>(TYPES.Auth_SettingRepository)
.toConstantValue(
new TypeORMSettingRepository(
container.get<Repository<TypeORMSetting>>(TYPES.Auth_ORMSettingRepository),
container.get<MapperInterface<Setting, TypeORMSetting>>(TYPES.Auth_SettingPersistenceMapper),
),
)
container
.bind<SubscriptionSettingRepositoryInterface>(TYPES.Auth_SubscriptionSettingRepository)
.to(TypeORMSubscriptionSettingRepository)
.toConstantValue(
new TypeORMSubscriptionSettingRepository(
container.get<Repository<TypeORMSubscriptionSetting>>(TYPES.Auth_ORMSubscriptionSettingRepository),
container.get<MapperInterface<SubscriptionSetting, TypeORMSubscriptionSetting>>(
TYPES.Auth_SubscriptionSettingPersistenceMapper,
),
),
)
container
.bind<OfflineSettingRepositoryInterface>(TYPES.Auth_OfflineSettingRepository)
.to(TypeORMOfflineSettingRepository)
@@ -522,13 +550,6 @@ export class ContainerConfigLoader {
container.bind<UserProjector>(TYPES.Auth_UserProjector).to(UserProjector)
container.bind<RoleProjector>(TYPES.Auth_RoleProjector).to(RoleProjector)
container.bind<PermissionProjector>(TYPES.Auth_PermissionProjector).to(PermissionProjector)
container.bind<SettingProjector>(TYPES.Auth_SettingProjector).to(SettingProjector)
container
.bind<SubscriptionSettingProjector>(TYPES.Auth_SubscriptionSettingProjector)
.to(SubscriptionSettingProjector)
// Factories
container.bind<SettingFactoryInterface>(TYPES.Auth_SettingFactory).to(SettingFactory)
// env vars
container.bind(TYPES.Auth_JWT_SECRET).toConstantValue(env.get('JWT_SECRET'))
@@ -567,16 +588,7 @@ export class ContainerConfigLoader {
.toConstantValue(env.get('DISABLE_USER_REGISTRATION', true) === 'true')
container.bind(TYPES.Auth_SNS_AWS_REGION).toConstantValue(env.get('SNS_AWS_REGION', true))
container.bind(TYPES.Auth_SQS_QUEUE_URL).toConstantValue(env.get('SQS_QUEUE_URL', true))
container
.bind(TYPES.Auth_USER_SERVER_REGISTRATION_URL)
.toConstantValue(env.get('USER_SERVER_REGISTRATION_URL', true))
container.bind(TYPES.Auth_USER_SERVER_AUTH_KEY).toConstantValue(env.get('USER_SERVER_AUTH_KEY', true))
container
.bind(TYPES.Auth_USER_SERVER_CHANGE_EMAIL_URL)
.toConstantValue(env.get('USER_SERVER_CHANGE_EMAIL_URL', true))
container.bind(TYPES.Auth_SYNCING_SERVER_URL).toConstantValue(env.get('SYNCING_SERVER_URL', true))
container.bind(TYPES.Auth_VERSION).toConstantValue(env.get('VERSION', true) ?? 'development')
container.bind(TYPES.Auth_PAYMENTS_SERVER_URL).toConstantValue(env.get('PAYMENTS_SERVER_URL', true))
container
.bind(TYPES.Auth_SESSION_TRACE_DAYS_TTL)
.toConstantValue(env.get('SESSION_TRACE_DAYS_TTL', true) ? +env.get('SESSION_TRACE_DAYS_TTL', true) : 90)
@@ -645,9 +657,6 @@ export class ContainerConfigLoader {
container.get(TYPES.Auth_Timer),
),
)
container
.bind<TransitionStatusRepositoryInterface>(TYPES.Auth_TransitionStatusRepository)
.toConstantValue(new InMemoryTransitionStatusRepository())
} else {
container.bind<PKCERepositoryInterface>(TYPES.Auth_PKCERepository).to(RedisPKCERepository)
container.bind<LockRepositoryInterface>(TYPES.Auth_LockRepository).to(LockRepository)
@@ -660,17 +669,57 @@ export class ContainerConfigLoader {
container
.bind<SubscriptionTokenRepositoryInterface>(TYPES.Auth_SubscriptionTokenRepository)
.to(RedisSubscriptionTokenRepository)
container
.bind<TransitionStatusRepositoryInterface>(TYPES.Auth_TransitionStatusRepository)
.toConstantValue(new RedisTransitionStatusRepository(container.get<Redis>(TYPES.Auth_Redis)))
}
// Services
container
.bind<TraceSession>(TYPES.Auth_TraceSession)
.toConstantValue(
new TraceSession(
container.get(TYPES.Auth_SessionTraceRepository),
container.get(TYPES.Auth_Timer),
container.get(TYPES.Auth_SESSION_TRACE_DAYS_TTL),
),
)
container
.bind<SelectorInterface<ProtocolVersion>>(TYPES.Auth_ProtocolVersionSelector)
.toConstantValue(new DeterministicSelector<ProtocolVersion>())
container.bind<UAParser>(TYPES.Auth_DeviceDetector).toConstantValue(new UAParser())
container.bind<SessionService>(TYPES.Auth_SessionService).to(SessionService)
container.bind<UAParserInstance>(TYPES.Auth_DeviceDetector).toConstantValue(new UAParser())
container.bind<CrypterInterface>(TYPES.Auth_Crypter).to(CrypterNode)
container
.bind<SettingCrypterInterface>(TYPES.Auth_SettingCrypter)
.toConstantValue(
new SettingCrypter(
container.get<UserRepositoryInterface>(TYPES.Auth_UserRepository),
container.get<CrypterInterface>(TYPES.Auth_Crypter),
),
)
container
.bind<GetSetting>(TYPES.Auth_GetSetting)
.toConstantValue(
new GetSetting(
container.get<SettingRepositoryInterface>(TYPES.Auth_SettingRepository),
container.get<SettingCrypterInterface>(TYPES.Auth_SettingCrypter),
),
)
container
.bind<SessionService>(TYPES.Auth_SessionService)
.toConstantValue(
new SessionService(
container.get<SessionRepositoryInterface>(TYPES.Auth_SessionRepository),
container.get<EphemeralSessionRepositoryInterface>(TYPES.Auth_EphemeralSessionRepository),
container.get<RevokedSessionRepositoryInterface>(TYPES.Auth_RevokedSessionRepository),
container.get<UAParserInstance>(TYPES.Auth_DeviceDetector),
container.get<TimerInterface>(TYPES.Auth_Timer),
container.get<winston.Logger>(TYPES.Auth_Logger),
container.get<number>(TYPES.Auth_ACCESS_TOKEN_AGE),
container.get<number>(TYPES.Auth_REFRESH_TOKEN_AGE),
container.get<CryptoNode>(TYPES.Auth_CryptoNode),
container.get<TraceSession>(TYPES.Auth_TraceSession),
container.get<UserSubscriptionRepositoryInterface>(TYPES.Auth_UserSubscriptionRepository),
container.get<string[]>(TYPES.Auth_READONLY_USERS),
container.get<GetSetting>(TYPES.Auth_GetSetting),
),
)
container.bind<AuthResponseFactory20161215>(TYPES.Auth_AuthResponseFactory20161215).to(AuthResponseFactory20161215)
container.bind<AuthResponseFactory20190520>(TYPES.Auth_AuthResponseFactory20190520).to(AuthResponseFactory20190520)
container.bind<AuthResponseFactory20200115>(TYPES.Auth_AuthResponseFactory20200115).to(AuthResponseFactory20200115)
@@ -709,12 +758,9 @@ export class ContainerConfigLoader {
.bind<AuthenticationMethodResolver>(TYPES.Auth_AuthenticationMethodResolver)
.to(AuthenticationMethodResolver)
container.bind<DomainEventFactory>(TYPES.Auth_DomainEventFactory).to(DomainEventFactory)
container.bind<AxiosInstance>(TYPES.Auth_HTTPClient).toConstantValue(axios.create())
container.bind<CrypterInterface>(TYPES.Auth_Crypter).to(CrypterNode)
container
.bind<SettingsAssociationServiceInterface>(TYPES.Auth_SettingsAssociationService)
.to(SettingsAssociationService)
container.bind<SettingDecrypterInterface>(TYPES.Auth_SettingDecrypter).to(SettingDecrypter)
container
.bind<GetUserKeyParams>(TYPES.Auth_GetUserKeyParams)
@@ -737,21 +783,6 @@ export class ContainerConfigLoader {
),
)
container
.bind<SettingServiceInterface>(TYPES.Auth_SettingService)
.toConstantValue(
new SettingService(
container.get<SettingFactoryInterface>(TYPES.Auth_SettingFactory),
container.get<SettingRepositoryInterface>(TYPES.Auth_SettingRepository),
container.get<SettingsAssociationServiceInterface>(TYPES.Auth_SettingsAssociationService),
container.get<SettingInterpreterInterface>(TYPES.Auth_SettingInterpreter),
container.get<SettingDecrypterInterface>(TYPES.Auth_SettingDecrypter),
container.get<winston.Logger>(TYPES.Auth_Logger),
),
)
container
.bind<SubscriptionSettingServiceInterface>(TYPES.Auth_SubscriptionSettingService)
.to(SubscriptionSettingService)
container.bind<OfflineSettingServiceInterface>(TYPES.Auth_OfflineSettingService).to(OfflineSettingService)
container.bind<ContentDecoderInterface>(TYPES.Auth_ContenDecoder).toConstantValue(new ContentDecoder())
container.bind<ClientServiceInterface>(TYPES.Auth_WebSocketsClientService).to(WebSocketsClientService)
@@ -764,7 +795,6 @@ export class ContainerConfigLoader {
container
.bind<SelectorInterface<boolean>>(TYPES.Auth_BooleanSelector)
.toConstantValue(new DeterministicSelector<boolean>())
container.bind<UserSubscriptionServiceInterface>(TYPES.Auth_UserSubscriptionService).to(UserSubscriptionService)
// Middleware
container.bind<SessionMiddleware>(TYPES.Auth_SessionMiddleware).to(SessionMiddleware)
@@ -791,15 +821,6 @@ export class ContainerConfigLoader {
container.bind<OfflineUserAuthMiddleware>(TYPES.Auth_OfflineUserAuthMiddleware).to(OfflineUserAuthMiddleware)
// use cases
container
.bind<TraceSession>(TYPES.Auth_TraceSession)
.toConstantValue(
new TraceSession(
container.get(TYPES.Auth_SessionTraceRepository),
container.get(TYPES.Auth_Timer),
container.get(TYPES.Auth_SESSION_TRACE_DAYS_TTL),
),
)
container
.bind<PersistStatistics>(TYPES.Auth_PersistStatistics)
.toConstantValue(
@@ -874,24 +895,65 @@ export class ContainerConfigLoader {
container.get(TYPES.Auth_FeatureService),
),
)
container
.bind<SetSettingValue>(TYPES.Auth_SetSettingValue)
.toConstantValue(
new SetSettingValue(
container.get<GetSetting>(TYPES.Auth_GetSetting),
container.get<SettingRepositoryInterface>(TYPES.Auth_SettingRepository),
container.get<TimerInterface>(TYPES.Auth_Timer),
container.get<SettingsAssociationServiceInterface>(TYPES.Auth_SettingsAssociationService),
container.get<RoleServiceInterface>(TYPES.Auth_RoleService),
container.get<SettingCrypterInterface>(TYPES.Auth_SettingCrypter),
),
)
container
.bind<GenerateRecoveryCodes>(TYPES.Auth_GenerateRecoveryCodes)
.toConstantValue(
new GenerateRecoveryCodes(
container.get(TYPES.Auth_UserRepository),
container.get(TYPES.Auth_SettingService),
container.get(TYPES.Auth_SetSettingValue),
container.get(TYPES.Auth_CryptoNode),
),
)
container
.bind<GetSubscriptionSetting>(TYPES.Auth_GetSubscriptionSetting)
.toConstantValue(
new GetSubscriptionSetting(
container.get<SubscriptionSettingRepositoryInterface>(TYPES.Auth_SubscriptionSettingRepository),
container.get<SettingCrypterInterface>(TYPES.Auth_SettingCrypter),
),
)
container
.bind<SetSubscriptionSettingValue>(TYPES.Auth_SetSubscriptionSettingValue)
.toConstantValue(
new SetSubscriptionSettingValue(
container.get<SubscriptionSettingRepositoryInterface>(TYPES.Auth_SubscriptionSettingRepository),
container.get<GetSubscriptionSetting>(TYPES.Auth_GetSubscriptionSetting),
container.get<TimerInterface>(TYPES.Auth_Timer),
),
)
container
.bind<ApplyDefaultSubscriptionSettings>(TYPES.Auth_ApplyDefaultSubscriptionSettings)
.toConstantValue(
new ApplyDefaultSubscriptionSettings(
container.get<SubscriptionSettingsAssociationServiceInterface>(
TYPES.Auth_SubscriptionSettingsAssociationService,
),
container.get<UserSubscriptionRepositoryInterface>(TYPES.Auth_UserSubscriptionRepository),
container.get<GetSubscriptionSetting>(TYPES.Auth_GetSubscriptionSetting),
container.get<SetSubscriptionSettingValue>(TYPES.Auth_SetSubscriptionSettingValue),
),
)
container
.bind<ActivatePremiumFeatures>(TYPES.Auth_ActivatePremiumFeatures)
.toConstantValue(
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),
container.get<UserRepositoryInterface>(TYPES.Auth_UserRepository),
container.get<UserSubscriptionRepositoryInterface>(TYPES.Auth_UserSubscriptionRepository),
container.get<ApplyDefaultSubscriptionSettings>(TYPES.Auth_ApplyDefaultSubscriptionSettings),
container.get<RoleServiceInterface>(TYPES.Auth_RoleService),
container.get<TimerInterface>(TYPES.Auth_Timer),
),
)
@@ -905,47 +967,136 @@ export class ContainerConfigLoader {
container.bind<AuthenticateRequest>(TYPES.Auth_AuthenticateRequest).to(AuthenticateRequest)
container.bind<RefreshSessionToken>(TYPES.Auth_RefreshSessionToken).to(RefreshSessionToken)
container.bind<SignIn>(TYPES.Auth_SignIn).to(SignIn)
container.bind<VerifyMFA>(TYPES.Auth_VerifyMFA).to(VerifyMFA)
container
.bind<VerifyMFA>(TYPES.Auth_VerifyMFA)
.toConstantValue(
new VerifyMFA(
container.get<UserRepositoryInterface>(TYPES.Auth_UserRepository),
container.get<SelectorInterface<boolean>>(TYPES.Auth_BooleanSelector),
container.get<LockRepositoryInterface>(TYPES.Auth_LockRepository),
container.get<string>(TYPES.Auth_PSEUDO_KEY_PARAMS_KEY),
container.get<AuthenticatorRepositoryInterface>(TYPES.Auth_AuthenticatorRepository),
container.get<VerifyAuthenticatorAuthenticationResponse>(
TYPES.Auth_VerifyAuthenticatorAuthenticationResponse,
),
container.get<GetSetting>(TYPES.Auth_GetSetting),
container.get<winston.Logger>(TYPES.Auth_Logger),
),
)
container.bind<ClearLoginAttempts>(TYPES.Auth_ClearLoginAttempts).to(ClearLoginAttempts)
container.bind<IncreaseLoginAttempts>(TYPES.Auth_IncreaseLoginAttempts).to(IncreaseLoginAttempts)
container
.bind<GetUserKeyParamsRecovery>(TYPES.Auth_GetUserKeyParamsRecovery)
.toConstantValue(
new GetUserKeyParamsRecovery(
container.get(TYPES.Auth_KeyParamsFactory),
container.get(TYPES.Auth_UserRepository),
container.get(TYPES.Auth_PKCERepository),
container.get(TYPES.Auth_SettingService),
container.get<KeyParamsFactoryInterface>(TYPES.Auth_KeyParamsFactory),
container.get<UserRepositoryInterface>(TYPES.Auth_UserRepository),
container.get<PKCERepositoryInterface>(TYPES.Auth_PKCERepository),
container.get<GetSetting>(TYPES.Auth_GetSetting),
),
)
container.bind<UpdateUser>(TYPES.Auth_UpdateUser).to(UpdateUser)
container.bind<Register>(TYPES.Auth_Register).to(Register)
container
.bind<ApplyDefaultSettings>(TYPES.Auth_ApplyDefaultSettings)
.toConstantValue(
new ApplyDefaultSettings(
container.get<SettingsAssociationServiceInterface>(TYPES.Auth_SettingsAssociationService),
container.get<SetSettingValue>(TYPES.Auth_SetSettingValue),
),
)
container
.bind<Register>(TYPES.Auth_Register)
.toConstantValue(
new Register(
container.get<UserRepositoryInterface>(TYPES.Auth_UserRepository),
container.get<RoleRepositoryInterface>(TYPES.Auth_RoleRepository),
container.get<AuthResponseFactory20200115>(TYPES.Auth_AuthResponseFactory20200115),
container.get<CrypterInterface>(TYPES.Auth_Crypter),
container.get<boolean>(TYPES.Auth_DISABLE_USER_REGISTRATION),
container.get<TimerInterface>(TYPES.Auth_Timer),
container.get<ApplyDefaultSettings>(TYPES.Auth_ApplyDefaultSettings),
),
)
container.bind<GetActiveSessionsForUser>(TYPES.Auth_GetActiveSessionsForUser).to(GetActiveSessionsForUser)
container.bind<DeleteOtherSessionsForUser>(TYPES.Auth_DeleteOtherSessionsForUser).to(DeleteOtherSessionsForUser)
container.bind<DeleteSessionForUser>(TYPES.Auth_DeleteSessionForUser).to(DeleteSessionForUser)
container.bind<ChangeCredentials>(TYPES.Auth_ChangeCredentials).to(ChangeCredentials)
container.bind<GetSettings>(TYPES.Auth_GetSettings).to(GetSettings)
container.bind<GetSetting>(TYPES.Auth_GetSetting).to(GetSetting)
container
.bind<GetSettings>(TYPES.Auth_GetSettings)
.toConstantValue(
new GetSettings(
container.get<SettingRepositoryInterface>(TYPES.Auth_SettingRepository),
container.get<SettingCrypterInterface>(TYPES.Auth_SettingCrypter),
),
)
container
.bind<GetSubscriptionSettings>(TYPES.Auth_GetSubscriptionSettings)
.toConstantValue(
new GetSubscriptionSettings(
container.get<SubscriptionSettingRepositoryInterface>(TYPES.Auth_SubscriptionSettingRepository),
container.get<SettingCrypterInterface>(TYPES.Auth_SettingCrypter),
),
)
container
.bind<GetRegularSubscriptionForUser>(TYPES.Auth_GetRegularSubscriptionForUser)
.toConstantValue(
new GetRegularSubscriptionForUser(
container.get<UserSubscriptionRepositoryInterface>(TYPES.Auth_UserSubscriptionRepository),
),
)
container
.bind<GetSharedSubscriptionForUser>(TYPES.Auth_GetSharedSubscriptionForUser)
.toConstantValue(
new GetSharedSubscriptionForUser(
container.get<UserSubscriptionRepositoryInterface>(TYPES.Auth_UserSubscriptionRepository),
),
)
container
.bind<GetSharedOrRegularSubscriptionForUser>(TYPES.Auth_GetSharedOrRegularSubscriptionForUser)
.toConstantValue(
new GetSharedOrRegularSubscriptionForUser(
container.get<GetRegularSubscriptionForUser>(TYPES.Auth_GetRegularSubscriptionForUser),
container.get<GetSharedSubscriptionForUser>(TYPES.Auth_GetSharedSubscriptionForUser),
),
)
container
.bind<GetAllSettingsForUser>(TYPES.Auth_GetAllSettingsForUser)
.toConstantValue(
new GetAllSettingsForUser(
container.get<GetSettings>(TYPES.Auth_GetSettings),
container.get<GetSharedOrRegularSubscriptionForUser>(TYPES.Auth_GetSharedOrRegularSubscriptionForUser),
container.get<GetSubscriptionSettings>(TYPES.Auth_GetSubscriptionSettings),
),
)
container.bind<GetUserFeatures>(TYPES.Auth_GetUserFeatures).to(GetUserFeatures)
container.bind<UpdateSetting>(TYPES.Auth_UpdateSetting).to(UpdateSetting)
container.bind<DeleteSetting>(TYPES.Auth_DeleteSetting).to(DeleteSetting)
container
.bind<SignInWithRecoveryCodes>(TYPES.Auth_SignInWithRecoveryCodes)
.toConstantValue(
new SignInWithRecoveryCodes(
container.get(TYPES.Auth_UserRepository),
container.get(TYPES.Auth_AuthResponseFactory20200115),
container.get(TYPES.Auth_PKCERepository),
container.get(TYPES.Auth_Crypter),
container.get(TYPES.Auth_SettingService),
container.get(TYPES.Auth_GenerateRecoveryCodes),
container.get(TYPES.Auth_IncreaseLoginAttempts),
container.get(TYPES.Auth_ClearLoginAttempts),
container.get(TYPES.Auth_DeleteSetting),
container.get(TYPES.Auth_AuthenticatorRepository),
container.get<UserRepositoryInterface>(TYPES.Auth_UserRepository),
container.get<AuthResponseFactory20200115>(TYPES.Auth_AuthResponseFactory20200115),
container.get<PKCERepositoryInterface>(TYPES.Auth_PKCERepository),
container.get<CrypterInterface>(TYPES.Auth_Crypter),
container.get<GetSetting>(TYPES.Auth_GetSetting),
container.get<GenerateRecoveryCodes>(TYPES.Auth_GenerateRecoveryCodes),
container.get<IncreaseLoginAttempts>(TYPES.Auth_IncreaseLoginAttempts),
container.get<ClearLoginAttempts>(TYPES.Auth_ClearLoginAttempts),
container.get<DeleteSetting>(TYPES.Auth_DeleteSetting),
container.get<AuthenticatorRepositoryInterface>(TYPES.Auth_AuthenticatorRepository),
),
)
container
.bind<DeleteAccount>(TYPES.Auth_DeleteAccount)
.toConstantValue(
new DeleteAccount(
container.get<UserRepositoryInterface>(TYPES.Auth_UserRepository),
container.get<GetRegularSubscriptionForUser>(TYPES.Auth_GetRegularSubscriptionForUser),
container.get<DomainEventPublisherInterface>(TYPES.Auth_DomainEventPublisher),
container.get<DomainEventFactoryInterface>(TYPES.Auth_DomainEventFactory),
container.get<TimerInterface>(TYPES.Auth_Timer),
),
)
container.bind<DeleteAccount>(TYPES.Auth_DeleteAccount).to(DeleteAccount)
container.bind<GetUserSubscription>(TYPES.Auth_GetUserSubscription).to(GetUserSubscription)
container.bind<GetUserOfflineSubscription>(TYPES.Auth_GetUserOfflineSubscription).to(GetUserOfflineSubscription)
container.bind<CreateSubscriptionToken>(TYPES.Auth_CreateSubscriptionToken).to(CreateSubscriptionToken)
@@ -958,12 +1109,38 @@ export class ContainerConfigLoader {
container
.bind<CreateOfflineSubscriptionToken>(TYPES.Auth_CreateOfflineSubscriptionToken)
.to(CreateOfflineSubscriptionToken)
container.bind<CreateValetToken>(TYPES.Auth_CreateValetToken).to(CreateValetToken)
container
.bind<CreateValetToken>(TYPES.Auth_CreateValetToken)
.toConstantValue(
new CreateValetToken(
container.get<TokenEncoderInterface<ValetTokenData>>(TYPES.Auth_ValetTokenEncoder),
container.get<SubscriptionSettingsAssociationServiceInterface>(
TYPES.Auth_SubscriptionSettingsAssociationService,
),
container.get<GetRegularSubscriptionForUser>(TYPES.Auth_GetRegularSubscriptionForUser),
container.get<GetSharedSubscriptionForUser>(TYPES.Auth_GetSharedSubscriptionForUser),
container.get<GetSubscriptionSetting>(TYPES.Auth_GetSubscriptionSetting),
container.get<TimerInterface>(TYPES.Auth_Timer),
container.get<number>(TYPES.Auth_VALET_TOKEN_TTL),
),
)
container.bind<CreateListedAccount>(TYPES.Auth_CreateListedAccount).to(CreateListedAccount)
container.bind<InviteToSharedSubscription>(TYPES.Auth_InviteToSharedSubscription).to(InviteToSharedSubscription)
container
.bind<AcceptSharedSubscriptionInvitation>(TYPES.Auth_AcceptSharedSubscriptionInvitation)
.to(AcceptSharedSubscriptionInvitation)
.toConstantValue(
new AcceptSharedSubscriptionInvitation(
container.get<SharedSubscriptionInvitationRepositoryInterface>(
TYPES.Auth_SharedSubscriptionInvitationRepository,
),
container.get<UserRepositoryInterface>(TYPES.Auth_UserRepository),
container.get<UserSubscriptionRepositoryInterface>(TYPES.Auth_UserSubscriptionRepository),
container.get<RoleServiceInterface>(TYPES.Auth_RoleService),
container.get<ApplyDefaultSubscriptionSettings>(TYPES.Auth_ApplyDefaultSubscriptionSettings),
container.get<TimerInterface>(TYPES.Auth_Timer),
container.get<winston.Logger>(TYPES.Auth_Logger),
),
)
container
.bind<DeclineSharedSubscriptionInvitation>(TYPES.Auth_DeclineSharedSubscriptionInvitation)
.to(DeclineSharedSubscriptionInvitation)
@@ -974,23 +1151,31 @@ export class ContainerConfigLoader {
.bind<ListSharedSubscriptionInvitations>(TYPES.Auth_ListSharedSubscriptionInvitations)
.to(ListSharedSubscriptionInvitations)
container.bind<VerifyPredicate>(TYPES.Auth_VerifyPredicate).to(VerifyPredicate)
container.bind<CreateCrossServiceToken>(TYPES.Auth_CreateCrossServiceToken).to(CreateCrossServiceToken)
container
.bind<CreateCrossServiceToken>(TYPES.Auth_CreateCrossServiceToken)
.toConstantValue(
new CreateCrossServiceToken(
container.get<ProjectorInterface<User>>(TYPES.Auth_UserProjector),
container.get<ProjectorInterface<Session>>(TYPES.Auth_SessionProjector),
container.get<ProjectorInterface<Role>>(TYPES.Auth_RoleProjector),
container.get<TokenEncoderInterface<CrossServiceTokenData>>(TYPES.Auth_CrossServiceTokenEncoder),
container.get<UserRepositoryInterface>(TYPES.Auth_UserRepository),
container.get<number>(TYPES.Auth_AUTH_JWT_TTL),
container.get<GetRegularSubscriptionForUser>(TYPES.Auth_GetRegularSubscriptionForUser),
container.get<GetSubscriptionSetting>(TYPES.Auth_GetSubscriptionSetting),
container.get<SharedVaultUserRepositoryInterface>(TYPES.Auth_SharedVaultUserRepository),
),
)
container.bind<ProcessUserRequest>(TYPES.Auth_ProcessUserRequest).to(ProcessUserRequest)
container
.bind<UpdateStorageQuotaUsedForUser>(TYPES.Auth_UpdateStorageQuotaUsedForUser)
.toConstantValue(
new UpdateStorageQuotaUsedForUser(
container.get(TYPES.Auth_UserRepository),
container.get(TYPES.Auth_UserSubscriptionService),
container.get(TYPES.Auth_SubscriptionSettingService),
),
)
container
.bind<UpdateTransitionStatus>(TYPES.Auth_UpdateTransitionStatus)
.toConstantValue(
new UpdateTransitionStatus(
container.get<TransitionStatusRepositoryInterface>(TYPES.Auth_TransitionStatusRepository),
container.get<RoleServiceInterface>(TYPES.Auth_RoleService),
container.get<UserRepositoryInterface>(TYPES.Auth_UserRepository),
container.get<GetRegularSubscriptionForUser>(TYPES.Auth_GetRegularSubscriptionForUser),
container.get<GetSharedSubscriptionForUser>(TYPES.Auth_GetSharedSubscriptionForUser),
container.get<GetSubscriptionSetting>(TYPES.Auth_GetSubscriptionSetting),
container.get<SetSubscriptionSettingValue>(TYPES.Auth_SetSubscriptionSettingValue),
container.get<winston.Logger>(TYPES.Auth_Logger),
),
)
@@ -1019,8 +1204,9 @@ export class ContainerConfigLoader {
.toConstantValue(
new DisableEmailSettingBasedOnEmailSubscription(
container.get<UserRepositoryInterface>(TYPES.Auth_UserRepository),
container.get<SettingRepositoryInterface>(TYPES.Auth_SettingRepository),
container.get<SettingFactoryInterface>(TYPES.Auth_SettingFactory),
container.get<SetSettingValue>(TYPES.Auth_SetSettingValue),
container.get<SetSubscriptionSettingValue>(TYPES.Auth_SetSubscriptionSettingValue),
container.get<GetSharedOrRegularSubscriptionForUser>(TYPES.Auth_GetSharedOrRegularSubscriptionForUser),
),
)
@@ -1061,7 +1247,6 @@ export class ContainerConfigLoader {
container.bind<UserRequestsController>(TYPES.Auth_UserRequestsController).to(UserRequestsController)
// Handlers
container.bind<UserRegisteredEventHandler>(TYPES.Auth_UserRegisteredEventHandler).to(UserRegisteredEventHandler)
container
.bind<AccountDeletionRequestedEventHandler>(TYPES.Auth_AccountDeletionRequestedEventHandler)
.toConstantValue(
@@ -1075,7 +1260,16 @@ export class ContainerConfigLoader {
)
container
.bind<SubscriptionPurchasedEventHandler>(TYPES.Auth_SubscriptionPurchasedEventHandler)
.to(SubscriptionPurchasedEventHandler)
.toConstantValue(
new SubscriptionPurchasedEventHandler(
container.get<UserRepositoryInterface>(TYPES.Auth_UserRepository),
container.get<UserSubscriptionRepositoryInterface>(TYPES.Auth_UserSubscriptionRepository),
container.get<ApplyDefaultSubscriptionSettings>(TYPES.Auth_ApplyDefaultSubscriptionSettings),
container.get<OfflineUserSubscriptionRepositoryInterface>(TYPES.Auth_OfflineUserSubscriptionRepository),
container.get<RoleServiceInterface>(TYPES.Auth_RoleService),
container.get<winston.Logger>(TYPES.Auth_Logger),
),
)
container
.bind<SubscriptionCancelledEventHandler>(TYPES.Auth_SubscriptionCancelledEventHandler)
.to(SubscriptionCancelledEventHandler)
@@ -1090,16 +1284,42 @@ export class ContainerConfigLoader {
.to(SubscriptionExpiredEventHandler)
container
.bind<SubscriptionSyncRequestedEventHandler>(TYPES.Auth_SubscriptionSyncRequestedEventHandler)
.to(SubscriptionSyncRequestedEventHandler)
.toConstantValue(
new SubscriptionSyncRequestedEventHandler(
container.get<UserRepositoryInterface>(TYPES.Auth_UserRepository),
container.get<UserSubscriptionRepositoryInterface>(TYPES.Auth_UserSubscriptionRepository),
container.get<OfflineUserSubscriptionRepositoryInterface>(TYPES.Auth_OfflineUserSubscriptionRepository),
container.get<RoleServiceInterface>(TYPES.Auth_RoleService),
container.get<ApplyDefaultSubscriptionSettings>(TYPES.Auth_ApplyDefaultSubscriptionSettings),
container.get<SetSettingValue>(TYPES.Auth_SetSettingValue),
container.get<OfflineSettingServiceInterface>(TYPES.Auth_OfflineSettingService),
container.get<ContentDecoderInterface>(TYPES.Auth_ContenDecoder),
container.get<winston.Logger>(TYPES.Auth_Logger),
),
)
container
.bind<ExtensionKeyGrantedEventHandler>(TYPES.Auth_ExtensionKeyGrantedEventHandler)
.to(ExtensionKeyGrantedEventHandler)
.toConstantValue(
new ExtensionKeyGrantedEventHandler(
container.get<UserRepositoryInterface>(TYPES.Auth_UserRepository),
container.get<SetSettingValue>(TYPES.Auth_SetSettingValue),
container.get<OfflineSettingServiceInterface>(TYPES.Auth_OfflineSettingService),
container.get<ContentDecoderInterface>(TYPES.Auth_ContenDecoder),
container.get<winston.Logger>(TYPES.Auth_Logger),
),
)
container
.bind<SubscriptionReassignedEventHandler>(TYPES.Auth_SubscriptionReassignedEventHandler)
.to(SubscriptionReassignedEventHandler)
container
.bind<UserEmailChangedEventHandler>(TYPES.Auth_UserEmailChangedEventHandler)
.to(UserEmailChangedEventHandler)
.toConstantValue(
new SubscriptionReassignedEventHandler(
container.get<UserRepositoryInterface>(TYPES.Auth_UserRepository),
container.get<UserSubscriptionRepositoryInterface>(TYPES.Auth_UserSubscriptionRepository),
container.get<RoleServiceInterface>(TYPES.Auth_RoleService),
container.get<winston.Logger>(TYPES.Auth_Logger),
container.get<ApplyDefaultSubscriptionSettings>(TYPES.Auth_ApplyDefaultSubscriptionSettings),
container.get<SetSettingValue>(TYPES.Auth_SetSettingValue),
),
)
container
.bind<FileUploadedEventHandler>(TYPES.Auth_FileUploadedEventHandler)
.toConstantValue(
@@ -1142,10 +1362,24 @@ export class ContainerConfigLoader {
)
container
.bind<ListedAccountCreatedEventHandler>(TYPES.Auth_ListedAccountCreatedEventHandler)
.to(ListedAccountCreatedEventHandler)
.toConstantValue(
new ListedAccountCreatedEventHandler(
container.get<UserRepositoryInterface>(TYPES.Auth_UserRepository),
container.get<GetSetting>(TYPES.Auth_GetSetting),
container.get<SetSettingValue>(TYPES.Auth_SetSettingValue),
container.get<winston.Logger>(TYPES.Auth_Logger),
),
)
container
.bind<ListedAccountDeletedEventHandler>(TYPES.Auth_ListedAccountDeletedEventHandler)
.to(ListedAccountDeletedEventHandler)
.toConstantValue(
new ListedAccountDeletedEventHandler(
container.get<UserRepositoryInterface>(TYPES.Auth_UserRepository),
container.get<GetSetting>(TYPES.Auth_GetSetting),
container.get<SetSettingValue>(TYPES.Auth_SetSettingValue),
container.get<winston.Logger>(TYPES.Auth_Logger),
),
)
container
.bind<UserDisabledSessionUserAgentLoggingEventHandler>(TYPES.Auth_UserDisabledSessionUserAgentLoggingEventHandler)
.to(UserDisabledSessionUserAgentLoggingEventHandler)
@@ -1174,14 +1408,6 @@ export class ContainerConfigLoader {
container.get(TYPES.Auth_Logger),
),
)
container
.bind<TransitionStatusUpdatedEventHandler>(TYPES.Auth_TransitionStatusUpdatedEventHandler)
.toConstantValue(
new TransitionStatusUpdatedEventHandler(
container.get<UpdateTransitionStatus>(TYPES.Auth_UpdateTransitionStatus),
container.get<winston.Logger>(TYPES.Auth_Logger),
),
)
container
.bind<UserAddedToSharedVaultEventHandler>(TYPES.Auth_UserAddedToSharedVaultEventHandler)
.toConstantValue(
@@ -1210,7 +1436,6 @@ export class ContainerConfigLoader {
)
const eventHandlers: Map<string, DomainEventHandlerInterface> = new Map([
['USER_REGISTERED', container.get(TYPES.Auth_UserRegisteredEventHandler)],
['ACCOUNT_DELETION_REQUESTED', container.get(TYPES.Auth_AccountDeletionRequestedEventHandler)],
['SUBSCRIPTION_PURCHASED', container.get(TYPES.Auth_SubscriptionPurchasedEventHandler)],
['SUBSCRIPTION_CANCELLED', container.get(TYPES.Auth_SubscriptionCancelledEventHandler)],
@@ -1220,7 +1445,6 @@ export class ContainerConfigLoader {
['SUBSCRIPTION_SYNC_REQUESTED', container.get(TYPES.Auth_SubscriptionSyncRequestedEventHandler)],
['EXTENSION_KEY_GRANTED', container.get(TYPES.Auth_ExtensionKeyGrantedEventHandler)],
['SUBSCRIPTION_REASSIGNED', container.get(TYPES.Auth_SubscriptionReassignedEventHandler)],
['USER_EMAIL_CHANGED', container.get(TYPES.Auth_UserEmailChangedEventHandler)],
['FILE_UPLOADED', container.get(TYPES.Auth_FileUploadedEventHandler)],
['SHARED_VAULT_FILE_UPLOADED', container.get(TYPES.Auth_SharedVaultFileUploadedEventHandler)],
['SHARED_VAULT_FILE_MOVED', container.get(TYPES.Auth_SharedVaultFileMovedEventHandler)],
@@ -1239,7 +1463,6 @@ export class ContainerConfigLoader {
['PREDICATE_VERIFICATION_REQUESTED', container.get(TYPES.Auth_PredicateVerificationRequestedEventHandler)],
['EMAIL_SUBSCRIPTION_UNSUBSCRIBED', container.get(TYPES.Auth_EmailSubscriptionUnsubscribedEventHandler)],
['PAYMENTS_ACCOUNT_DELETED', container.get(TYPES.Auth_PaymentsAccountDeletedEventHandler)],
['TRANSITION_STATUS_UPDATED', container.get(TYPES.Auth_TransitionStatusUpdatedEventHandler)],
['USER_ADDED_TO_SHARED_VAULT', container.get(TYPES.Auth_UserAddedToSharedVaultEventHandler)],
['USER_REMOVED_FROM_SHARED_VAULT', container.get(TYPES.Auth_UserRemovedFromSharedVaultEventHandler)],
[
@@ -1372,33 +1595,41 @@ export class ContainerConfigLoader {
.bind<BaseSubscriptionTokensController>(TYPES.Auth_BaseSubscriptionTokensController)
.toConstantValue(
new BaseSubscriptionTokensController(
container.get(TYPES.Auth_CreateSubscriptionToken),
container.get(TYPES.Auth_AuthenticateSubscriptionToken),
container.get(TYPES.Auth_SettingService),
container.get(TYPES.Auth_UserProjector),
container.get(TYPES.Auth_RoleProjector),
container.get(TYPES.Auth_CrossServiceTokenEncoder),
container.get(TYPES.Auth_AUTH_JWT_TTL),
container.get(TYPES.Auth_ControllerContainer),
container.get<CreateSubscriptionToken>(TYPES.Auth_CreateSubscriptionToken),
container.get<AuthenticateSubscriptionToken>(TYPES.Auth_AuthenticateSubscriptionToken),
container.get<GetSetting>(TYPES.Auth_GetSetting),
container.get<ProjectorInterface<User>>(TYPES.Auth_UserProjector),
container.get<ProjectorInterface<Role>>(TYPES.Auth_RoleProjector),
container.get<TokenEncoderInterface<CrossServiceTokenData>>(TYPES.Auth_CrossServiceTokenEncoder),
container.get<number>(TYPES.Auth_AUTH_JWT_TTL),
container.get<ControllerContainerInterface>(TYPES.Auth_ControllerContainer),
),
)
container
.bind<BaseSubscriptionSettingsController>(TYPES.Auth_BaseSubscriptionSettingsController)
.toConstantValue(
new BaseSubscriptionSettingsController(
container.get(TYPES.Auth_GetSetting),
container.get(TYPES.Auth_ControllerContainer),
container.get<GetSubscriptionSetting>(TYPES.Auth_GetSubscriptionSetting),
container.get<GetSharedOrRegularSubscriptionForUser>(TYPES.Auth_GetSharedOrRegularSubscriptionForUser),
container.get<MapperInterface<SubscriptionSetting, SubscriptionSettingHttpRepresentation>>(
TYPES.Auth_SubscriptionSettingHttpMapper,
),
container.get<ControllerContainerInterface>(TYPES.Auth_ControllerContainer),
),
)
container
.bind<BaseSettingsController>(TYPES.Auth_BaseSettingsController)
.toConstantValue(
new BaseSettingsController(
container.get(TYPES.Auth_GetSettings),
container.get(TYPES.Auth_GetSetting),
container.get(TYPES.Auth_UpdateSetting),
container.get(TYPES.Auth_DeleteSetting),
container.get(TYPES.Auth_ControllerContainer),
container.get<GetAllSettingsForUser>(TYPES.Auth_GetAllSettingsForUser),
container.get<GetSetting>(TYPES.Auth_GetSetting),
container.get<SetSettingValue>(TYPES.Auth_SetSettingValue),
container.get<DeleteSetting>(TYPES.Auth_DeleteSetting),
container.get<MapperInterface<Setting, SettingHttpRepresentation>>(TYPES.Auth_SettingHttpMapper),
container.get<MapperInterface<SubscriptionSetting, SubscriptionSettingHttpRepresentation>>(
TYPES.Auth_SubscriptionSettingHttpMapper,
),
container.get<ControllerContainerInterface>(TYPES.Auth_ControllerContainer),
),
)
container
+4 -4
View File
@@ -5,8 +5,6 @@ import { Role } from '../Domain/Role/Role'
import { RevokedSession } from '../Domain/Session/RevokedSession'
import { Session } from '../Domain/Session/Session'
import { OfflineSetting } from '../Domain/Setting/OfflineSetting'
import { Setting } from '../Domain/Setting/Setting'
import { SubscriptionSetting } from '../Domain/Setting/SubscriptionSetting'
import { SharedSubscriptionInvitation } from '../Domain/SharedSubscription/SharedSubscriptionInvitation'
import { OfflineUserSubscription } from '../Domain/Subscription/OfflineUserSubscription'
import { UserSubscription } from '../Domain/Subscription/UserSubscription'
@@ -19,6 +17,8 @@ import { TypeORMSessionTrace } from '../Infra/TypeORM/TypeORMSessionTrace'
import { Env } from './Env'
import { SqliteConnectionOptions } from 'typeorm/driver/sqlite/SqliteConnectionOptions'
import { TypeORMSharedVaultUser } from '../Infra/TypeORM/TypeORMSharedVaultUser'
import { TypeORMSubscriptionSetting } from '../Infra/TypeORM/TypeORMSubscriptionSetting'
import { TypeORMSetting } from '../Infra/TypeORM/TypeORMSetting'
export class AppDataSource {
private _dataSource: DataSource | undefined
@@ -61,10 +61,10 @@ export class AppDataSource {
RevokedSession,
Role,
Permission,
Setting,
TypeORMSetting,
OfflineSetting,
SharedSubscriptionInvitation,
SubscriptionSetting,
TypeORMSubscriptionSetting,
TypeORMSessionTrace,
TypeORMAuthenticator,
TypeORMAuthenticatorChallenge,
+2
View File
@@ -26,9 +26,11 @@ export class Service implements AuthServiceInterface {
async activatePremiumFeatures(dto: {
username: string
subscriptionId: number
subscriptionPlanName?: string
uploadBytesLimit?: number
endsAt?: Date
cancelPreviousSubscription?: boolean
}): Promise<Result<string>> {
if (!this.container) {
return Result.fail('Container not initialized')
+15 -20
View File
@@ -10,6 +10,10 @@ const TYPES = {
Auth_AuthenticatorHttpMapper: Symbol.for('Auth_AuthenticatorHttpMapper'),
Auth_CacheEntryPersistenceMapper: Symbol.for('Auth_CacheEntryPersistenceMapper'),
Auth_SharedVaultUserPersistenceMapper: Symbol.for('Auth_SharedVaultUserPersistenceMapper'),
Auth_SettingHttpMapper: Symbol.for('Auth_SettingHttpMapper'),
Auth_SubscriptionSettingHttpMapper: Symbol.for('Auth_SubscriptionSettingHttpMapper'),
Auth_SubscriptionSettingPersistenceMapper: Symbol.for('Auth_SubscriptionSettingPersistenceMapper'),
Auth_SettingPersistenceMapper: Symbol.for('Auth_SettingPersistenceMapper'),
// Controller
Auth_ControllerContainer: Symbol.for('Auth_ControllerContainer'),
Auth_AuthController: Symbol.for('Auth_AuthController'),
@@ -36,7 +40,6 @@ const TYPES = {
Auth_AuthenticatorRepository: Symbol.for('Auth_AuthenticatorRepository'),
Auth_AuthenticatorChallengeRepository: Symbol.for('Auth_AuthenticatorChallengeRepository'),
Auth_CacheEntryRepository: Symbol.for('Auth_CacheEntryRepository'),
Auth_TransitionStatusRepository: Symbol.for('Auth_TransitionStatusRepository'),
Auth_SharedVaultUserRepository: Symbol.for('Auth_SharedVaultUserRepository'),
// ORM
Auth_ORMOfflineSettingRepository: Symbol.for('Auth_ORMOfflineSettingRepository'),
@@ -66,10 +69,6 @@ const TYPES = {
Auth_UserProjector: Symbol.for('Auth_UserProjector'),
Auth_RoleProjector: Symbol.for('Auth_RoleProjector'),
Auth_PermissionProjector: Symbol.for('Auth_PermissionProjector'),
Auth_SettingProjector: Symbol.for('Auth_SettingProjector'),
Auth_SubscriptionSettingProjector: Symbol.for('Auth_SubscriptionSettingProjector'),
// Factories
Auth_SettingFactory: Symbol.for('Auth_SettingFactory'),
// env vars
Auth_JWT_SECRET: Symbol.for('Auth_JWT_SECRET'),
Auth_LEGACY_JWT_SECRET: Symbol.for('Auth_LEGACY_JWT_SECRET'),
@@ -92,12 +91,7 @@ const TYPES = {
Auth_SNS_AWS_REGION: Symbol.for('Auth_SNS_AWS_REGION'),
Auth_SQS_QUEUE_URL: Symbol.for('Auth_SQS_QUEUE_URL'),
Auth_SQS_AWS_REGION: Symbol.for('Auth_SQS_AWS_REGION'),
Auth_USER_SERVER_REGISTRATION_URL: Symbol.for('Auth_USER_SERVER_REGISTRATION_URL'),
Auth_USER_SERVER_AUTH_KEY: Symbol.for('Auth_USER_SERVER_AUTH_KEY'),
Auth_USER_SERVER_CHANGE_EMAIL_URL: Symbol.for('Auth_USER_SERVER_CHANGE_EMAIL_URL'),
Auth_SYNCING_SERVER_URL: Symbol.for('Auth_SYNCING_SERVER_URL'),
Auth_VERSION: Symbol.for('Auth_VERSION'),
Auth_PAYMENTS_SERVER_URL: Symbol.for('Auth_PAYMENTS_SERVER_URL'),
Auth_SESSION_TRACE_DAYS_TTL: Symbol.for('Auth_SESSION_TRACE_DAYS_TTL'),
Auth_U2F_RELYING_PARTY_ID: Symbol.for('Auth_U2F_RELYING_PARTY_ID'),
Auth_U2F_RELYING_PARTY_NAME: Symbol.for('Auth_U2F_RELYING_PARTY_NAME'),
@@ -121,9 +115,12 @@ const TYPES = {
Auth_DeleteSessionForUser: Symbol.for('Auth_DeleteSessionForUser'),
Auth_ChangeCredentials: Symbol.for('Auth_ChangePassword'),
Auth_GetSettings: Symbol.for('Auth_GetSettings'),
Auth_GetSubscriptionSettings: Symbol.for('Auth_GetSubscriptionSettings'),
Auth_GetRegularSubscriptionForUser: Symbol.for('Auth_GetRegularSubscriptionForUser'),
Auth_GetSharedSubscriptionForUser: Symbol.for('Auth_GetSharedSubscriptionForUser'),
Auth_GetAllSettingsForUser: Symbol.for('Auth_GetAllSettingsForUser'),
Auth_GetSetting: Symbol.for('Auth_GetSetting'),
Auth_GetUserFeatures: Symbol.for('Auth_GetUserFeatures'),
Auth_UpdateSetting: Symbol.for('Auth_UpdateSetting'),
Auth_DeleteSetting: Symbol.for('Auth_DeleteSetting'),
Auth_DeleteAccount: Symbol.for('Auth_DeleteAccount'),
Auth_GetUserSubscription: Symbol.for('Auth_GetUserSubscription'),
@@ -152,18 +149,22 @@ const TYPES = {
Auth_VerifyAuthenticatorAuthenticationResponse: Symbol.for('Auth_VerifyAuthenticatorAuthenticationResponse'),
Auth_ListAuthenticators: Symbol.for('Auth_ListAuthenticators'),
Auth_DeleteAuthenticator: Symbol.for('Auth_DeleteAuthenticator'),
Auth_SetSettingValue: Symbol.for('Auth_SetSettingValue'),
Auth_GenerateRecoveryCodes: Symbol.for('Auth_GenerateRecoveryCodes'),
Auth_GetSubscriptionSetting: Symbol.for('Auth_GetSubscriptionSetting'),
Auth_SetSubscriptionSettingValue: Symbol.for('Auth_SetSubscriptionSettingValue'),
Auth_ApplyDefaultSubscriptionSettings: Symbol.for('Auth_ApplyDefaultSubscriptionSettings'),
Auth_ApplyDefaultSettings: Symbol.for('Auth_ApplyDefaultSettings'),
Auth_ActivatePremiumFeatures: Symbol.for('Auth_ActivatePremiumFeatures'),
Auth_SignInWithRecoveryCodes: Symbol.for('Auth_SignInWithRecoveryCodes'),
Auth_GetUserKeyParamsRecovery: Symbol.for('Auth_GetUserKeyParamsRecovery'),
Auth_UpdateStorageQuotaUsedForUser: Symbol.for('Auth_UpdateStorageQuotaUsedForUser'),
Auth_UpdateTransitionStatus: Symbol.for('Auth_UpdateTransitionStatus'),
Auth_AddSharedVaultUser: Symbol.for('Auth_AddSharedVaultUser'),
Auth_RemoveSharedVaultUser: Symbol.for('Auth_RemoveSharedVaultUser'),
Auth_DesignateSurvivor: Symbol.for('Auth_DesignateSurvivor'),
Auth_GetSharedOrRegularSubscriptionForUser: Symbol.for('Auth_GetSharedOrRegularSubscriptionForUser'),
Auth_DisableEmailSettingBasedOnEmailSubscription: Symbol.for('Auth_DisableEmailSettingBasedOnEmailSubscription'),
// Handlers
Auth_UserRegisteredEventHandler: Symbol.for('Auth_UserRegisteredEventHandler'),
Auth_AccountDeletionRequestedEventHandler: Symbol.for('Auth_AccountDeletionRequestedEventHandler'),
Auth_SubscriptionPurchasedEventHandler: Symbol.for('Auth_SubscriptionPurchasedEventHandler'),
Auth_SubscriptionCancelledEventHandler: Symbol.for('Auth_SubscriptionCancelledEventHandler'),
@@ -173,7 +174,6 @@ const TYPES = {
Auth_SubscriptionExpiredEventHandler: Symbol.for('Auth_SubscriptionExpiredEventHandler'),
Auth_SubscriptionSyncRequestedEventHandler: Symbol.for('Auth_SubscriptionSyncRequestedEventHandler'),
Auth_ExtensionKeyGrantedEventHandler: Symbol.for('Auth_ExtensionKeyGrantedEventHandler'),
Auth_UserEmailChangedEventHandler: Symbol.for('Auth_UserEmailChangedEventHandler'),
Auth_FileUploadedEventHandler: Symbol.for('Auth_FileUploadedEventHandler'),
Auth_SharedVaultFileUploadedEventHandler: Symbol.for('Auth_SharedVaultFileUploadedEventHandler'),
Auth_SharedVaultFileMovedEventHandler: Symbol.for('Auth_SharedVaultFileMovedEventHandler'),
@@ -190,7 +190,6 @@ const TYPES = {
Auth_PredicateVerificationRequestedEventHandler: Symbol.for('Auth_PredicateVerificationRequestedEventHandler'),
Auth_EmailSubscriptionUnsubscribedEventHandler: Symbol.for('Auth_EmailSubscriptionUnsubscribedEventHandler'),
Auth_PaymentsAccountDeletedEventHandler: Symbol.for('Auth_PaymentsAccountDeletedEventHandler'),
Auth_TransitionStatusUpdatedEventHandler: Symbol.for('Auth_TransitionStatusUpdatedEventHandler'),
Auth_UserAddedToSharedVaultEventHandler: Symbol.for('Auth_UserAddedToSharedVaultEventHandler'),
Auth_UserRemovedFromSharedVaultEventHandler: Symbol.for('Auth_UserRemovedFromSharedVaultEventHandler'),
Auth_UserDesignatedAsSurvivorInSharedVaultEventHandler: Symbol.for(
@@ -199,8 +198,6 @@ const TYPES = {
// Services
Auth_DeviceDetector: Symbol.for('Auth_DeviceDetector'),
Auth_SessionService: Symbol.for('Auth_SessionService'),
Auth_SettingService: Symbol.for('Auth_SettingService'),
Auth_SubscriptionSettingService: Symbol.for('Auth_SubscriptionSettingService'),
Auth_OfflineSettingService: Symbol.for('Auth_OfflineSettingService'),
Auth_AuthResponseFactory20161215: Symbol.for('Auth_AuthResponseFactory20161215'),
Auth_AuthResponseFactory20190520: Symbol.for('Auth_AuthResponseFactory20190520'),
@@ -221,7 +218,6 @@ const TYPES = {
Auth_DomainEventSubscriber: Symbol.for('Auth_DomainEventSubscriber'),
Auth_DomainEventFactory: Symbol.for('Auth_DomainEventFactory'),
Auth_DomainEventMessageHandler: Symbol.for('Auth_DomainEventMessageHandler'),
Auth_HTTPClient: Symbol.for('Auth_HTTPClient'),
Auth_Crypter: Symbol.for('Auth_Crypter'),
Auth_CryptoNode: Symbol.for('Auth_CryptoNode'),
Auth_Timer: Symbol.for('Auth_Timer'),
@@ -232,11 +228,10 @@ const TYPES = {
Auth_SettingsAssociationService: Symbol.for('Auth_SettingsAssociationService'),
Auth_SubscriptionSettingsAssociationService: Symbol.for('Auth_SubscriptionSettingsAssociationService'),
Auth_FeatureService: Symbol.for('Auth_FeatureService'),
Auth_SettingDecrypter: Symbol.for('Auth_SettingDecrypter'),
Auth_SettingCrypter: Symbol.for('Auth_SettingCrypter'),
Auth_SettingInterpreter: Symbol.for('Auth_SettingInterpreter'),
Auth_ProtocolVersionSelector: Symbol.for('Auth_ProtocolVersionSelector'),
Auth_BooleanSelector: Symbol.for('Auth_BooleanSelector'),
Auth_UserSubscriptionService: Symbol.for('Auth_UserSubscriptionService'),
Auth_BaseAuthController: Symbol.for('Auth_BaseAuthController'),
Auth_BaseAuthenticatorsController: Symbol.for('Auth_BaseAuthenticatorsController'),
Auth_BaseSubscriptionInvitesController: Symbol.for('Auth_BaseSubscriptionInvitesController'),
@@ -20,7 +20,6 @@ import {
StatisticPersistenceRequestedEvent,
SessionCreatedEvent,
SessionRefreshedEvent,
TransitionRequestedEvent,
} from '@standardnotes/domain-events'
import { Predicate, PredicateVerificationResult } from '@standardnotes/predicates'
import { TimerInterface } from '@standardnotes/time'
@@ -34,25 +33,6 @@ import { KeyParamsData } from '@standardnotes/responses'
export class DomainEventFactory implements DomainEventFactoryInterface {
constructor(@inject(TYPES.Auth_Timer) private timer: TimerInterface) {}
createTransitionRequestedEvent(dto: {
userUuid: string
type: 'items' | 'revisions'
timestamp: number
}): TransitionRequestedEvent {
return {
type: 'TRANSITION_REQUESTED',
createdAt: this.timer.getUTCDate(),
meta: {
correlation: {
userIdentifier: dto.userUuid,
userIdentifierType: 'uuid',
},
origin: DomainEventService.Auth,
},
payload: dto,
}
}
createSessionCreatedEvent(dto: { userUuid: string }): SessionCreatedEvent {
return {
type: 'SESSION_CREATED',
@@ -18,7 +18,6 @@ import {
StatisticPersistenceRequestedEvent,
SessionCreatedEvent,
SessionRefreshedEvent,
TransitionRequestedEvent,
} from '@standardnotes/domain-events'
import { InviteeIdentifierType } from '../SharedSubscription/InviteeIdentifierType'
import { KeyParamsData } from '@standardnotes/responses'
@@ -92,9 +91,4 @@ export interface DomainEventFactoryInterface {
}): StatisticPersistenceRequestedEvent
createSessionCreatedEvent(dto: { userUuid: string }): SessionCreatedEvent
createSessionRefreshedEvent(dto: { userUuid: string }): SessionRefreshedEvent
createTransitionRequestedEvent(dto: {
userUuid: string
type: 'items' | 'revisions'
timestamp: number
}): TransitionRequestedEvent
}
@@ -111,7 +111,6 @@ describe('FeatureService', () => {
cancelled: false,
subscriptionId: 1,
subscriptionType: UserSubscriptionType.Regular,
subscriptionSettings: Promise.resolve([]),
}
subscription2 = {
@@ -125,7 +124,6 @@ describe('FeatureService', () => {
cancelled: false,
subscriptionId: 2,
subscriptionType: UserSubscriptionType.Regular,
subscriptionSettings: Promise.resolve([]),
}
subscription3 = {
@@ -139,7 +137,6 @@ describe('FeatureService', () => {
cancelled: true,
subscriptionId: 3,
subscriptionType: UserSubscriptionType.Regular,
subscriptionSettings: Promise.resolve([]),
}
subscription4 = {
@@ -153,7 +150,6 @@ describe('FeatureService', () => {
cancelled: true,
subscriptionId: 4,
subscriptionType: UserSubscriptionType.Regular,
subscriptionSettings: Promise.resolve([]),
}
user = {
@@ -329,7 +325,6 @@ describe('FeatureService', () => {
cancelled: false,
subscriptionId: 1,
subscriptionType: UserSubscriptionType.Regular,
subscriptionSettings: Promise.resolve([]),
}
user = {
@@ -1,123 +0,0 @@
import 'reflect-metadata'
import { ExtensionKeyGrantedEvent } from '@standardnotes/domain-events'
import { Logger } from 'winston'
import * as dayjs from 'dayjs'
import { User } from '../User/User'
import { UserRepositoryInterface } from '../User/UserRepositoryInterface'
import { ExtensionKeyGrantedEventHandler } from './ExtensionKeyGrantedEventHandler'
import { SettingServiceInterface } from '../Setting/SettingServiceInterface'
import { OfflineSettingServiceInterface } from '../Setting/OfflineSettingServiceInterface'
import { ContentDecoderInterface, SubscriptionName } from '@standardnotes/common'
describe('ExtensionKeyGrantedEventHandler', () => {
let userRepository: UserRepositoryInterface
let logger: Logger
let user: User
let event: ExtensionKeyGrantedEvent
let settingService: SettingServiceInterface
let offlineSettingService: OfflineSettingServiceInterface
let contentDecoder: ContentDecoderInterface
let timestamp: number
const createHandler = () =>
new ExtensionKeyGrantedEventHandler(userRepository, settingService, offlineSettingService, contentDecoder, logger)
beforeEach(() => {
user = {
uuid: '123',
} as jest.Mocked<User>
userRepository = {} as jest.Mocked<UserRepositoryInterface>
userRepository.findOneByUsernameOrEmail = jest.fn().mockReturnValue(user)
settingService = {} as jest.Mocked<SettingServiceInterface>
settingService.createOrReplace = jest.fn()
offlineSettingService = {} as jest.Mocked<OfflineSettingServiceInterface>
offlineSettingService.createOrUpdate = jest.fn()
timestamp = dayjs.utc().valueOf()
event = {} as jest.Mocked<ExtensionKeyGrantedEvent>
event.createdAt = new Date(1)
event.payload = {
userEmail: 'test@test.com',
extensionKey: 'abc123',
offline: false,
offlineFeaturesToken: 'test',
subscriptionName: SubscriptionName.ProPlan,
origin: 'update-subscription',
timestamp,
payAmount: 1000,
billingEveryNMonths: 1,
activeUntil: new Date(10).toString(),
}
contentDecoder = {} as jest.Mocked<ContentDecoderInterface>
contentDecoder.decode = jest.fn().mockReturnValue({
featuresUrl: 'http://features-url',
extensionKey: 'key',
})
logger = {} as jest.Mocked<Logger>
logger.info = jest.fn()
logger.warn = jest.fn()
})
it('should add extension key as an user offline features token for offline user setting', async () => {
event.payload.offline = true
await createHandler().handle(event)
expect(offlineSettingService.createOrUpdate).toHaveBeenCalledWith({
email: 'test@test.com',
name: 'FEATURES_TOKEN',
value: 'key',
})
})
it('should add extension key as an user offline features token if not possible to decode', async () => {
event.payload.offline = true
contentDecoder.decode = jest.fn().mockReturnValue({})
await createHandler().handle(event)
expect(offlineSettingService.createOrUpdate).not.toHaveBeenCalled()
})
it('should add extension key as user setting', async () => {
await createHandler().handle(event)
expect(settingService.createOrReplace).toHaveBeenCalledWith({
props: {
name: 'EXTENSION_KEY',
serverEncryptionVersion: 1,
unencryptedValue: 'abc123',
sensitive: true,
},
user: {
uuid: '123',
},
})
})
it('should not do anything if no user is found for specified email', async () => {
userRepository.findOneByUsernameOrEmail = jest.fn().mockReturnValue(null)
await createHandler().handle(event)
expect(settingService.createOrReplace).not.toHaveBeenCalled()
})
it('should not do anything if user email is invalid', async () => {
event.payload.userEmail = ''
await createHandler().handle(event)
expect(settingService.createOrReplace).not.toHaveBeenCalled()
})
})
@@ -1,26 +1,21 @@
import { DomainEventHandlerInterface, ExtensionKeyGrantedEvent } from '@standardnotes/domain-events'
import { SettingName } from '@standardnotes/settings'
import { SettingName, Username } from '@standardnotes/domain-core'
import { OfflineFeaturesTokenData } from '@standardnotes/security'
import { ContentDecoderInterface } from '@standardnotes/common'
import { inject, injectable } from 'inversify'
import { Logger } from 'winston'
import TYPES from '../../Bootstrap/Types'
import { EncryptionVersion } from '../Encryption/EncryptionVersion'
import { OfflineSettingServiceInterface } from '../Setting/OfflineSettingServiceInterface'
import { OfflineSettingName } from '../Setting/OfflineSettingName'
import { SettingServiceInterface } from '../Setting/SettingServiceInterface'
import { UserRepositoryInterface } from '../User/UserRepositoryInterface'
import { Username } from '@standardnotes/domain-core'
import { SetSettingValue } from '../UseCase/SetSettingValue/SetSettingValue'
@injectable()
export class ExtensionKeyGrantedEventHandler implements DomainEventHandlerInterface {
constructor(
@inject(TYPES.Auth_UserRepository) private userRepository: UserRepositoryInterface,
@inject(TYPES.Auth_SettingService) private settingService: SettingServiceInterface,
@inject(TYPES.Auth_OfflineSettingService) private offlineSettingService: OfflineSettingServiceInterface,
@inject(TYPES.Auth_ContenDecoder) private contentDecoder: ContentDecoderInterface,
@inject(TYPES.Auth_Logger) private logger: Logger,
private userRepository: UserRepositoryInterface,
private setSettingValue: SetSettingValue,
private offlineSettingService: OfflineSettingServiceInterface,
private contentDecoder: ContentDecoderInterface,
private logger: Logger,
) {}
async handle(event: ExtensionKeyGrantedEvent): Promise<void> {
@@ -58,14 +53,14 @@ export class ExtensionKeyGrantedEventHandler implements DomainEventHandlerInterf
return
}
await this.settingService.createOrReplace({
user,
props: {
name: SettingName.NAMES.ExtensionKey,
unencryptedValue: event.payload.extensionKey,
serverEncryptionVersion: EncryptionVersion.Default,
sensitive: true,
},
const result = await this.setSettingValue.execute({
userUuid: user.uuid,
settingName: SettingName.NAMES.ExtensionKey,
value: event.payload.extensionKey,
})
if (result.isFailed()) {
this.logger.error(`Could not set extension key for user ${user.uuid}`)
}
}
}
@@ -1,89 +0,0 @@
import 'reflect-metadata'
import { ListedAccountCreatedEvent } from '@standardnotes/domain-events'
import { Logger } from 'winston'
import { ListedAccountCreatedEventHandler } from './ListedAccountCreatedEventHandler'
import { SettingServiceInterface } from '../Setting/SettingServiceInterface'
import { UserRepositoryInterface } from '../User/UserRepositoryInterface'
import { User } from '../User/User'
import { Setting } from '../Setting/Setting'
describe('ListedAccountCreatedEventHandler', () => {
let settingService: SettingServiceInterface
let userRepository: UserRepositoryInterface
let event: ListedAccountCreatedEvent
let user: User
let logger: Logger
const createHandler = () => new ListedAccountCreatedEventHandler(userRepository, settingService, logger)
beforeEach(() => {
user = {} as jest.Mocked<User>
userRepository = {} as jest.Mocked<UserRepositoryInterface>
userRepository.findOneByUsernameOrEmail = jest.fn().mockReturnValue(user)
settingService = {} as jest.Mocked<SettingServiceInterface>
settingService.findSettingWithDecryptedValue = jest.fn().mockReturnValue(null)
settingService.createOrReplace = jest.fn()
event = {} as jest.Mocked<ListedAccountCreatedEvent>
event.payload = {
userEmail: 'test@test.com',
userId: 1,
userName: 'testuser',
secret: 'new-secret',
hostUrl: 'https://dev.listed.to',
}
logger = {} as jest.Mocked<Logger>
logger.warn = jest.fn()
})
it('should not save the listed secret if username is invalid', async () => {
event.payload.userEmail = ''
await createHandler().handle(event)
expect(settingService.createOrReplace).not.toHaveBeenCalled()
})
it('should not save the listed secret if user is not found', async () => {
userRepository.findOneByUsernameOrEmail = jest.fn().mockReturnValue(null)
await createHandler().handle(event)
expect(settingService.createOrReplace).not.toHaveBeenCalled()
})
it('should save the listed secret as a user setting', async () => {
await createHandler().handle(event)
expect(settingService.createOrReplace).toHaveBeenCalledWith({
user,
props: {
name: 'LISTED_AUTHOR_SECRETS',
sensitive: false,
unencryptedValue: '[{"authorId":1,"secret":"new-secret","hostUrl":"https://dev.listed.to"}]',
},
})
})
it('should add the listed secret as a user setting to an existing list of secrets', async () => {
settingService.findSettingWithDecryptedValue = jest.fn().mockReturnValue({
value: '[{"authorId":2,"secret":"old-secret","hostUrl":"https://dev.listed.to"}]',
} as jest.Mocked<Setting>)
await createHandler().handle(event)
expect(settingService.createOrReplace).toHaveBeenCalledWith({
user,
props: {
name: 'LISTED_AUTHOR_SECRETS',
sensitive: false,
unencryptedValue:
'[{"authorId":2,"secret":"old-secret","hostUrl":"https://dev.listed.to"},{"authorId":1,"secret":"new-secret","hostUrl":"https://dev.listed.to"}]',
},
})
})
})
@@ -1,19 +1,18 @@
import { Username } from '@standardnotes/domain-core'
import { SettingName, Username } from '@standardnotes/domain-core'
import { DomainEventHandlerInterface, ListedAccountCreatedEvent } from '@standardnotes/domain-events'
import { ListedAuthorSecretsData, SettingName } from '@standardnotes/settings'
import { inject, injectable } from 'inversify'
import { ListedAuthorSecretsData } from '@standardnotes/settings'
import { Logger } from 'winston'
import TYPES from '../../Bootstrap/Types'
import { SettingServiceInterface } from '../Setting/SettingServiceInterface'
import { UserRepositoryInterface } from '../User/UserRepositoryInterface'
import { GetSetting } from '../UseCase/GetSetting/GetSetting'
import { SetSettingValue } from '../UseCase/SetSettingValue/SetSettingValue'
@injectable()
export class ListedAccountCreatedEventHandler implements DomainEventHandlerInterface {
constructor(
@inject(TYPES.Auth_UserRepository) private userRepository: UserRepositoryInterface,
@inject(TYPES.Auth_SettingService) private settingService: SettingServiceInterface,
@inject(TYPES.Auth_Logger) private logger: Logger,
private userRepository: UserRepositoryInterface,
private getSetting: GetSetting,
private setSettingValue: SetSettingValue,
private logger: Logger,
) {}
async handle(event: ListedAccountCreatedEvent): Promise<void> {
@@ -34,23 +33,27 @@ export class ListedAccountCreatedEventHandler implements DomainEventHandlerInter
let authSecrets: ListedAuthorSecretsData = [newSecret]
const listedAuthorSecretsSetting = await this.settingService.findSettingWithDecryptedValue({
settingName: SettingName.create(SettingName.NAMES.ListedAuthorSecrets).getValue(),
const listedAuthorSecretsSettingOrError = await this.getSetting.execute({
settingName: SettingName.NAMES.ListedAuthorSecrets,
userUuid: user.uuid,
decrypted: true,
allowSensitiveRetrieval: false,
})
if (listedAuthorSecretsSetting !== null) {
const existingSecrets: ListedAuthorSecretsData = JSON.parse(listedAuthorSecretsSetting.value as string)
if (!listedAuthorSecretsSettingOrError.isFailed()) {
const listedAuthorSecretsSetting = listedAuthorSecretsSettingOrError.getValue()
const existingSecrets: ListedAuthorSecretsData = JSON.parse(listedAuthorSecretsSetting.decryptedValue as string)
existingSecrets.push(newSecret)
authSecrets = existingSecrets
}
await this.settingService.createOrReplace({
user,
props: {
name: SettingName.NAMES.ListedAuthorSecrets,
unencryptedValue: JSON.stringify(authSecrets),
sensitive: false,
},
const result = await this.setSettingValue.execute({
userUuid: user.uuid,
settingName: SettingName.NAMES.ListedAuthorSecrets,
value: JSON.stringify(authSecrets),
})
if (result.isFailed()) {
this.logger.error(`Could not update listed author secrets for user with uuid ${user.uuid}: ${result.getError()}`)
}
}
}
@@ -1,100 +0,0 @@
import 'reflect-metadata'
import { ListedAccountDeletedEvent } from '@standardnotes/domain-events'
import { Logger } from 'winston'
import { ListedAccountDeletedEventHandler } from './ListedAccountDeletedEventHandler'
import { SettingServiceInterface } from '../Setting/SettingServiceInterface'
import { UserRepositoryInterface } from '../User/UserRepositoryInterface'
import { User } from '../User/User'
import { Setting } from '../Setting/Setting'
describe('ListedAccountDeletedEventHandler', () => {
let settingService: SettingServiceInterface
let userRepository: UserRepositoryInterface
let event: ListedAccountDeletedEvent
let user: User
let logger: Logger
const createHandler = () => new ListedAccountDeletedEventHandler(userRepository, settingService, logger)
beforeEach(() => {
user = {} as jest.Mocked<User>
userRepository = {} as jest.Mocked<UserRepositoryInterface>
userRepository.findOneByUsernameOrEmail = jest.fn().mockReturnValue(user)
settingService = {} as jest.Mocked<SettingServiceInterface>
settingService.findSettingWithDecryptedValue = jest.fn().mockReturnValue({
value: '[{"authorId":1,"secret":"my-secret","hostUrl":"https://dev.listed.to"}]',
} as jest.Mocked<Setting>)
settingService.createOrReplace = jest.fn()
event = {} as jest.Mocked<ListedAccountDeletedEvent>
event.payload = {
userEmail: 'test@test.com',
userId: 1,
userName: 'testuser',
secret: 'my-secret',
hostUrl: 'https://dev.listed.to',
}
logger = {} as jest.Mocked<Logger>
logger.warn = jest.fn()
})
it('should not remove the listed secret if username is invalid', async () => {
event.payload.userEmail = ''
await createHandler().handle(event)
expect(settingService.createOrReplace).not.toHaveBeenCalled()
})
it('should not remove the listed secret if user is not found', async () => {
userRepository.findOneByUsernameOrEmail = jest.fn().mockReturnValue(null)
await createHandler().handle(event)
expect(settingService.createOrReplace).not.toHaveBeenCalled()
})
it('should not remove the listed secret if setting is not found', async () => {
settingService.findSettingWithDecryptedValue = jest.fn().mockReturnValue(null)
await createHandler().handle(event)
expect(settingService.createOrReplace).not.toHaveBeenCalled()
})
it('should remove the listed secret from the user setting', async () => {
await createHandler().handle(event)
expect(settingService.createOrReplace).toHaveBeenCalledWith({
user,
props: {
name: 'LISTED_AUTHOR_SECRETS',
sensitive: false,
unencryptedValue: '[]',
},
})
})
it('should remove the listed secret from an existing list of secrets', async () => {
settingService.findSettingWithDecryptedValue = jest.fn().mockReturnValue({
value:
'[{"authorId":2,"secret":"old-secret","hostUrl":"https://dev.listed.to"},{"authorId":1,"secret":"my-secret","hostUrl":"https://dev.listed.to"},{"authorId":1,"secret":"my-secret","hostUrl":"https://local.listed.to"}]',
} as jest.Mocked<Setting>)
await createHandler().handle(event)
expect(settingService.createOrReplace).toHaveBeenCalledWith({
user,
props: {
name: 'LISTED_AUTHOR_SECRETS',
sensitive: false,
unencryptedValue:
'[{"authorId":2,"secret":"old-secret","hostUrl":"https://dev.listed.to"},{"authorId":1,"secret":"my-secret","hostUrl":"https://local.listed.to"}]',
},
})
})
})
@@ -1,19 +1,18 @@
import { Username } from '@standardnotes/domain-core'
import { SettingName, Username } from '@standardnotes/domain-core'
import { DomainEventHandlerInterface, ListedAccountDeletedEvent } from '@standardnotes/domain-events'
import { ListedAuthorSecretsData, SettingName } from '@standardnotes/settings'
import { inject, injectable } from 'inversify'
import { ListedAuthorSecretsData } from '@standardnotes/settings'
import { Logger } from 'winston'
import TYPES from '../../Bootstrap/Types'
import { SettingServiceInterface } from '../Setting/SettingServiceInterface'
import { UserRepositoryInterface } from '../User/UserRepositoryInterface'
import { GetSetting } from '../UseCase/GetSetting/GetSetting'
import { SetSettingValue } from '../UseCase/SetSettingValue/SetSettingValue'
@injectable()
export class ListedAccountDeletedEventHandler implements DomainEventHandlerInterface {
constructor(
@inject(TYPES.Auth_UserRepository) private userRepository: UserRepositoryInterface,
@inject(TYPES.Auth_SettingService) private settingService: SettingServiceInterface,
@inject(TYPES.Auth_Logger) private logger: Logger,
private userRepository: UserRepositoryInterface,
private getSetting: GetSetting,
private setSettingValue: SetSettingValue,
private logger: Logger,
) {}
async handle(event: ListedAccountDeletedEvent): Promise<void> {
@@ -31,30 +30,35 @@ export class ListedAccountDeletedEventHandler implements DomainEventHandlerInter
return
}
const listedAuthorSecretsSetting = await this.settingService.findSettingWithDecryptedValue({
settingName: SettingName.create(SettingName.NAMES.ListedAuthorSecrets).getValue(),
const listedAuthorSecretsSettingOrError = await this.getSetting.execute({
settingName: SettingName.NAMES.ListedAuthorSecrets,
decrypted: true,
userUuid: user.uuid,
allowSensitiveRetrieval: false,
})
if (listedAuthorSecretsSetting === null) {
this.logger.warn(`Could not find listed secrets setting for user ${user.uuid}`)
if (listedAuthorSecretsSettingOrError.isFailed()) {
this.logger.error(`Could not find listed secrets setting for user ${user.uuid}`)
return
}
const existingSecrets: ListedAuthorSecretsData = JSON.parse(listedAuthorSecretsSetting.value as string)
const listedAuthorSecretsSetting = listedAuthorSecretsSettingOrError.getValue()
const existingSecrets: ListedAuthorSecretsData = JSON.parse(listedAuthorSecretsSetting.decryptedValue as string)
const filteredSecrets = existingSecrets.filter(
(secret) =>
secret.authorId !== event.payload.userId ||
(secret.authorId === event.payload.userId && secret.hostUrl !== event.payload.hostUrl),
)
await this.settingService.createOrReplace({
user,
props: {
name: SettingName.NAMES.ListedAuthorSecrets,
unencryptedValue: JSON.stringify(filteredSecrets),
sensitive: false,
},
const result = await this.setSettingValue.execute({
settingName: SettingName.NAMES.ListedAuthorSecrets,
value: JSON.stringify(filteredSecrets),
userUuid: user.uuid,
})
if (result.isFailed()) {
this.logger.error(`Could not update listed author secrets for user with uuid ${user.uuid}`)
}
}
}
@@ -1,48 +0,0 @@
import { Logger } from 'winston'
import { Result } from '@standardnotes/domain-core'
import { PaymentsAccountDeletedEvent } from '@standardnotes/domain-events'
import { DeleteAccount } from '../UseCase/DeleteAccount/DeleteAccount'
import { PaymentsAccountDeletedEventHandler } from './PaymentsAccountDeletedEventHandler'
describe('PaymentsAccountDeletedEventHandler', () => {
let deleteAccountUseCase: DeleteAccount
let logger: Logger
let event: PaymentsAccountDeletedEvent
const createHandler = () => new PaymentsAccountDeletedEventHandler(deleteAccountUseCase, logger)
beforeEach(() => {
deleteAccountUseCase = {} as jest.Mocked<DeleteAccount>
deleteAccountUseCase.execute = jest.fn().mockResolvedValue(Result.ok('success'))
logger = {} as jest.Mocked<Logger>
logger.error = jest.fn()
event = {
payload: {
username: 'username',
},
} as jest.Mocked<PaymentsAccountDeletedEvent>
})
it('should delete account', async () => {
const handler = createHandler()
await handler.handle(event)
expect(deleteAccountUseCase.execute).toHaveBeenCalledWith({
username: 'username',
})
})
it('should log error if delete account fails', async () => {
const handler = createHandler()
deleteAccountUseCase.execute = jest.fn().mockResolvedValue(Result.fail('error'))
await handler.handle(event)
expect(logger.error).toHaveBeenCalledWith('Failed to delete account for user username: error')
})
})
@@ -1,131 +0,0 @@
import 'reflect-metadata'
import {
DomainEventPublisherInterface,
DomainEventService,
PredicateVerificationRequestedEvent,
PredicateVerificationRequestedEventPayload,
PredicateVerifiedEvent,
} from '@standardnotes/domain-events'
import { Predicate, PredicateVerificationResult } from '@standardnotes/predicates'
import { Logger } from 'winston'
import { DomainEventFactoryInterface } from '../Event/DomainEventFactoryInterface'
import { VerifyPredicate } from '../UseCase/VerifyPredicate/VerifyPredicate'
import { UserRepositoryInterface } from '../User/UserRepositoryInterface'
import { PredicateVerificationRequestedEventHandler } from './PredicateVerificationRequestedEventHandler'
import { User } from '../User/User'
describe('PredicateVerificationRequestedEventHandler', () => {
let verifyPredicate: VerifyPredicate
let userRepository: UserRepositoryInterface
let domainEventFactory: DomainEventFactoryInterface
let domainEventPublisher: DomainEventPublisherInterface
let logger: Logger
let event: PredicateVerificationRequestedEvent
const createHandler = () =>
new PredicateVerificationRequestedEventHandler(
verifyPredicate,
userRepository,
domainEventFactory,
domainEventPublisher,
logger,
)
beforeEach(() => {
verifyPredicate = {} as jest.Mocked<VerifyPredicate>
verifyPredicate.execute = jest
.fn()
.mockReturnValue({ predicateVerificationResult: PredicateVerificationResult.Affirmed })
userRepository = {} as jest.Mocked<UserRepositoryInterface>
userRepository.findOneByUsernameOrEmail = jest.fn().mockReturnValue({ uuid: '1-2-3' } as jest.Mocked<User>)
domainEventFactory = {} as jest.Mocked<DomainEventFactoryInterface>
domainEventFactory.createPredicateVerifiedEvent = jest
.fn()
.mockReturnValue({} as jest.Mocked<PredicateVerifiedEvent>)
domainEventPublisher = {} as jest.Mocked<DomainEventPublisherInterface>
domainEventPublisher.publish = jest.fn()
logger = {} as jest.Mocked<Logger>
logger.warn = jest.fn()
logger.info = jest.fn()
logger.debug = jest.fn()
event = {} as jest.Mocked<PredicateVerificationRequestedEvent>
event.meta = {
correlation: {
userIdentifier: '2-3-4',
userIdentifierType: 'uuid',
},
origin: DomainEventService.Auth,
}
event.payload = {
predicate: {} as jest.Mocked<Predicate>,
} as jest.Mocked<PredicateVerificationRequestedEventPayload>
})
it('should verify a predicate by user uuid', async () => {
await createHandler().handle(event)
expect(verifyPredicate.execute).toHaveBeenCalledWith({
predicate: event.payload.predicate,
userUuid: '2-3-4',
})
expect(domainEventPublisher.publish).toHaveBeenCalled()
})
it('should verify a predicate by user email', async () => {
event.meta = {
correlation: {
userIdentifier: 'test@test.te',
userIdentifierType: 'email',
},
origin: DomainEventService.Auth,
}
await createHandler().handle(event)
expect(verifyPredicate.execute).toHaveBeenCalledWith({
predicate: event.payload.predicate,
userUuid: '1-2-3',
})
expect(domainEventPublisher.publish).toHaveBeenCalled()
})
it('should do nothing if username is invalid', async () => {
event.meta = {
correlation: {
userIdentifier: ' ',
userIdentifierType: 'email',
},
origin: DomainEventService.Auth,
}
await createHandler().handle(event)
expect(verifyPredicate.execute).not.toHaveBeenCalled()
expect(domainEventPublisher.publish).not.toHaveBeenCalled()
})
it('should mark a predicate verification with undetermined result if user is missing', async () => {
event.meta = {
correlation: {
userIdentifier: 'test@test.te',
userIdentifierType: 'email',
},
origin: DomainEventService.Auth,
}
userRepository.findOneByUsernameOrEmail = jest.fn().mockReturnValue(null)
await createHandler().handle(event)
expect(verifyPredicate.execute).not.toHaveBeenCalled()
expect(domainEventPublisher.publish).toHaveBeenCalled()
})
})
@@ -1,45 +0,0 @@
import 'reflect-metadata'
import { SharedSubscriptionInvitationCreatedEvent } from '@standardnotes/domain-events'
import { InviteeIdentifierType } from '../SharedSubscription/InviteeIdentifierType'
import { AcceptSharedSubscriptionInvitation } from '../UseCase/AcceptSharedSubscriptionInvitation/AcceptSharedSubscriptionInvitation'
import { SharedSubscriptionInvitationCreatedEventHandler } from './SharedSubscriptionInvitationCreatedEventHandler'
describe('SharedSubscriptionInvitationCreatedEventHandler', () => {
let acceptSharedSubscriptionInvitation: AcceptSharedSubscriptionInvitation
const createHandler = () => new SharedSubscriptionInvitationCreatedEventHandler(acceptSharedSubscriptionInvitation)
beforeEach(() => {
acceptSharedSubscriptionInvitation = {} as jest.Mocked<AcceptSharedSubscriptionInvitation>
acceptSharedSubscriptionInvitation.execute = jest.fn()
})
it('should accept automatically invitation for hash invitees', async () => {
const event = {
payload: {
inviteeIdentifierType: InviteeIdentifierType.Hash,
sharedSubscriptionInvitationUuid: '1-2-3',
},
} as jest.Mocked<SharedSubscriptionInvitationCreatedEvent>
await createHandler().handle(event)
expect(acceptSharedSubscriptionInvitation.execute).toHaveBeenCalled()
})
it('should not accept automatically invitation for email invitees', async () => {
const event = {
payload: {
inviteeIdentifierType: InviteeIdentifierType.Email,
sharedSubscriptionInvitationUuid: '1-2-3',
},
} as jest.Mocked<SharedSubscriptionInvitationCreatedEvent>
await createHandler().handle(event)
expect(acceptSharedSubscriptionInvitation.execute).not.toHaveBeenCalled()
})
})
@@ -1,63 +0,0 @@
import 'reflect-metadata'
import { SubscriptionName } from '@standardnotes/common'
import { SubscriptionCancelledEvent } from '@standardnotes/domain-events'
import * as dayjs from 'dayjs'
import { SubscriptionCancelledEventHandler } from './SubscriptionCancelledEventHandler'
import { UserSubscriptionRepositoryInterface } from '../Subscription/UserSubscriptionRepositoryInterface'
import { OfflineUserSubscriptionRepositoryInterface } from '../Subscription/OfflineUserSubscriptionRepositoryInterface'
describe('SubscriptionCancelledEventHandler', () => {
let userSubscriptionRepository: UserSubscriptionRepositoryInterface
let offlineUserSubscriptionRepository: OfflineUserSubscriptionRepositoryInterface
let event: SubscriptionCancelledEvent
let timestamp: number
const createHandler = () =>
new SubscriptionCancelledEventHandler(userSubscriptionRepository, offlineUserSubscriptionRepository)
beforeEach(() => {
userSubscriptionRepository = {} as jest.Mocked<UserSubscriptionRepositoryInterface>
userSubscriptionRepository.updateCancelled = jest.fn()
offlineUserSubscriptionRepository = {} as jest.Mocked<OfflineUserSubscriptionRepositoryInterface>
offlineUserSubscriptionRepository.updateCancelled = jest.fn()
timestamp = dayjs.utc().valueOf()
event = {} as jest.Mocked<SubscriptionCancelledEvent>
event.createdAt = new Date(1)
event.payload = {
subscriptionId: 1,
userEmail: 'test@test.com',
subscriptionName: SubscriptionName.ProPlan,
timestamp,
offline: false,
replaced: false,
subscriptionCreatedAt: 1,
subscriptionEndsAt: 2,
subscriptionUpdatedAt: 2,
lastPayedAt: 1,
userExistingSubscriptionsCount: 1,
billingFrequency: 1,
payAmount: 12.99,
}
})
it('should update subscription cancelled', async () => {
event.payload.timestamp = 1642395451516000
await createHandler().handle(event)
expect(userSubscriptionRepository.updateCancelled).toHaveBeenCalledWith(1, true, 1642395451516000)
})
it('should update offline subscription cancelled', async () => {
event.payload.offline = true
await createHandler().handle(event)
expect(offlineUserSubscriptionRepository.updateCancelled).toHaveBeenCalledWith(1, true, timestamp)
})
})
@@ -1,123 +0,0 @@
import 'reflect-metadata'
import { SubscriptionName } from '@standardnotes/common'
import { RoleName } from '@standardnotes/domain-core'
import { SubscriptionExpiredEvent } from '@standardnotes/domain-events'
import { Logger } from 'winston'
import * as dayjs from 'dayjs'
import { User } from '../User/User'
import { UserRepositoryInterface } from '../User/UserRepositoryInterface'
import { SubscriptionExpiredEventHandler } from './SubscriptionExpiredEventHandler'
import { UserSubscriptionRepositoryInterface } from '../Subscription/UserSubscriptionRepositoryInterface'
import { RoleServiceInterface } from '../Role/RoleServiceInterface'
import { OfflineUserSubscriptionRepositoryInterface } from '../Subscription/OfflineUserSubscriptionRepositoryInterface'
import { UserSubscription } from '../Subscription/UserSubscription'
describe('SubscriptionExpiredEventHandler', () => {
let userRepository: UserRepositoryInterface
let userSubscriptionRepository: UserSubscriptionRepositoryInterface
let offlineUserSubscriptionRepository: OfflineUserSubscriptionRepositoryInterface
let roleService: RoleServiceInterface
let logger: Logger
let user: User
let event: SubscriptionExpiredEvent
let timestamp: number
const createHandler = () =>
new SubscriptionExpiredEventHandler(
userRepository,
userSubscriptionRepository,
offlineUserSubscriptionRepository,
roleService,
logger,
)
beforeEach(() => {
user = {
uuid: '123',
email: 'test@test.com',
roles: Promise.resolve([
{
name: RoleName.NAMES.ProUser,
},
]),
} as jest.Mocked<User>
userRepository = {} as jest.Mocked<UserRepositoryInterface>
userRepository.findOneByUsernameOrEmail = jest.fn().mockReturnValue(user)
userRepository.save = jest.fn().mockReturnValue(user)
userSubscriptionRepository = {} as jest.Mocked<UserSubscriptionRepositoryInterface>
userSubscriptionRepository.updateEndsAt = jest.fn()
userSubscriptionRepository.countActiveSubscriptions = jest.fn().mockReturnValue(13)
userSubscriptionRepository.findBySubscriptionId = jest
.fn()
.mockReturnValue([{ user: Promise.resolve(user) } as jest.Mocked<UserSubscription>])
offlineUserSubscriptionRepository = {} as jest.Mocked<OfflineUserSubscriptionRepositoryInterface>
offlineUserSubscriptionRepository.updateEndsAt = jest.fn()
roleService = {} as jest.Mocked<RoleServiceInterface>
roleService.removeUserRoleBasedOnSubscription = jest.fn()
timestamp = dayjs.utc().valueOf()
event = {} as jest.Mocked<SubscriptionExpiredEvent>
event.createdAt = new Date(1)
event.payload = {
subscriptionId: 1,
userEmail: 'test@test.com',
subscriptionName: SubscriptionName.PlusPlan,
timestamp,
offline: false,
totalActiveSubscriptionsCount: 123,
userExistingSubscriptionsCount: 2,
billingFrequency: 1,
payAmount: 12.99,
}
logger = {} as jest.Mocked<Logger>
logger.info = jest.fn()
logger.warn = jest.fn()
})
it('should update the user role', async () => {
await createHandler().handle(event)
expect(roleService.removeUserRoleBasedOnSubscription).toHaveBeenCalledWith(user, SubscriptionName.PlusPlan)
})
it('should update subscription ends at', async () => {
await createHandler().handle(event)
expect(userSubscriptionRepository.updateEndsAt).toHaveBeenCalledWith(1, timestamp, timestamp)
})
it('should update offline subscription ends at', async () => {
event.payload.offline = true
await createHandler().handle(event)
expect(offlineUserSubscriptionRepository.updateEndsAt).toHaveBeenCalledWith(1, timestamp, timestamp)
})
it('should not do anything if no user is found for specified email', async () => {
userRepository.findOneByUsernameOrEmail = jest.fn().mockReturnValue(null)
await createHandler().handle(event)
expect(roleService.removeUserRoleBasedOnSubscription).not.toHaveBeenCalled()
expect(userSubscriptionRepository.updateEndsAt).not.toHaveBeenCalled()
})
it('should not do anything if username is invalid', async () => {
event.payload.userEmail = ' '
await createHandler().handle(event)
expect(roleService.removeUserRoleBasedOnSubscription).not.toHaveBeenCalled()
expect(userSubscriptionRepository.updateEndsAt).not.toHaveBeenCalled()
})
})
@@ -1,177 +0,0 @@
import 'reflect-metadata'
import { SubscriptionName } from '@standardnotes/common'
import { RoleName } from '@standardnotes/domain-core'
import { SubscriptionPurchasedEvent } from '@standardnotes/domain-events'
import { Logger } from 'winston'
import * as dayjs from 'dayjs'
import { RoleServiceInterface } from '../Role/RoleServiceInterface'
import { User } from '../User/User'
import { UserRepositoryInterface } from '../User/UserRepositoryInterface'
import { UserSubscriptionRepositoryInterface } from '../Subscription/UserSubscriptionRepositoryInterface'
import { SubscriptionPurchasedEventHandler } from './SubscriptionPurchasedEventHandler'
import { UserSubscription } from '../Subscription/UserSubscription'
import { OfflineUserSubscriptionRepositoryInterface } from '../Subscription/OfflineUserSubscriptionRepositoryInterface'
import { OfflineUserSubscription } from '../Subscription/OfflineUserSubscription'
import { SubscriptionSettingServiceInterface } from '../Setting/SubscriptionSettingServiceInterface'
import { UserSubscriptionType } from '../Subscription/UserSubscriptionType'
describe('SubscriptionPurchasedEventHandler', () => {
let userRepository: UserRepositoryInterface
let userSubscriptionRepository: UserSubscriptionRepositoryInterface
let offlineUserSubscription: OfflineUserSubscription
let offlineUserSubscriptionRepository: OfflineUserSubscriptionRepositoryInterface
let roleService: RoleServiceInterface
let logger: Logger
let user: User
let subscription: UserSubscription
let event: SubscriptionPurchasedEvent
let subscriptionExpiresAt: number
let subscriptionSettingService: SubscriptionSettingServiceInterface
let timestamp: number
const createHandler = () =>
new SubscriptionPurchasedEventHandler(
userRepository,
userSubscriptionRepository,
offlineUserSubscriptionRepository,
roleService,
subscriptionSettingService,
logger,
)
beforeEach(() => {
user = {
uuid: '123',
email: 'test@test.com',
roles: Promise.resolve([
{
name: RoleName.NAMES.CoreUser,
},
]),
} as jest.Mocked<User>
subscription = {
subscriptionType: UserSubscriptionType.Regular,
} as jest.Mocked<UserSubscription>
userRepository = {} as jest.Mocked<UserRepositoryInterface>
userRepository.findOneByUsernameOrEmail = jest.fn().mockReturnValue(user)
userRepository.save = jest.fn().mockReturnValue(user)
userSubscriptionRepository = {} as jest.Mocked<UserSubscriptionRepositoryInterface>
userSubscriptionRepository.countByUserUuid = jest.fn().mockReturnValue(0)
userSubscriptionRepository.countActiveSubscriptions = jest.fn().mockReturnValue(13)
userSubscriptionRepository.save = jest.fn().mockReturnValue(subscription)
offlineUserSubscription = {} as jest.Mocked<OfflineUserSubscription>
offlineUserSubscriptionRepository = {} as jest.Mocked<OfflineUserSubscriptionRepositoryInterface>
offlineUserSubscriptionRepository.findOneBySubscriptionId = jest.fn().mockReturnValue(offlineUserSubscription)
offlineUserSubscriptionRepository.save = jest.fn().mockReturnValue(offlineUserSubscription)
roleService = {} as jest.Mocked<RoleServiceInterface>
roleService.addUserRoleBasedOnSubscription = jest.fn()
roleService.setOfflineUserRole = jest.fn()
subscriptionExpiresAt = timestamp + 365 * 1000
event = {} as jest.Mocked<SubscriptionPurchasedEvent>
event.createdAt = new Date(1)
event.payload = {
subscriptionId: 1,
userEmail: 'test@test.com',
subscriptionName: SubscriptionName.ProPlan,
subscriptionExpiresAt,
timestamp: dayjs.utc().valueOf(),
offline: false,
discountCode: null,
limitedDiscountPurchased: false,
newSubscriber: true,
totalActiveSubscriptionsCount: 123,
userRegisteredAt: dayjs.utc().valueOf() - 23,
billingFrequency: 12,
payAmount: 29.99,
}
subscriptionSettingService = {} as jest.Mocked<SubscriptionSettingServiceInterface>
subscriptionSettingService.applyDefaultSubscriptionSettingsForSubscription = jest.fn()
logger = {} as jest.Mocked<Logger>
logger.info = jest.fn()
logger.warn = jest.fn()
})
it('should update the user role', async () => {
await createHandler().handle(event)
expect(roleService.addUserRoleBasedOnSubscription).toHaveBeenCalledWith(user, SubscriptionName.ProPlan)
})
it('should update user default settings', async () => {
await createHandler().handle(event)
expect(subscriptionSettingService.applyDefaultSubscriptionSettingsForSubscription).toHaveBeenCalledWith(
subscription,
)
})
it('should update the offline user role', async () => {
event.payload.offline = true
await createHandler().handle(event)
expect(roleService.setOfflineUserRole).toHaveBeenCalledWith(offlineUserSubscription)
})
it('should create subscription', async () => {
await createHandler().handle(event)
subscription.planName = SubscriptionName.ProPlan
subscription.endsAt = subscriptionExpiresAt
subscription.subscriptionId = 1
subscription.user = Promise.resolve(user)
expect(userSubscriptionRepository.save).toHaveBeenCalledWith({
...subscription,
createdAt: expect.any(Number),
updatedAt: expect.any(Number),
cancelled: false,
})
})
it('should create an offline subscription', async () => {
event.payload.offline = true
await createHandler().handle(event)
expect(offlineUserSubscriptionRepository.save).toHaveBeenCalledWith({
endsAt: subscriptionExpiresAt,
subscriptionId: 1,
planName: 'PRO_PLAN',
email: 'test@test.com',
createdAt: expect.any(Number),
updatedAt: expect.any(Number),
cancelled: false,
})
})
it('should not do anything if no user is found for specified email', async () => {
userRepository.findOneByUsernameOrEmail = jest.fn().mockReturnValue(null)
await createHandler().handle(event)
expect(roleService.addUserRoleBasedOnSubscription).not.toHaveBeenCalled()
expect(userSubscriptionRepository.save).not.toHaveBeenCalled()
})
it('should not do anything if username is invalid', async () => {
event.payload.userEmail = ' '
await createHandler().handle(event)
expect(roleService.addUserRoleBasedOnSubscription).not.toHaveBeenCalled()
expect(userSubscriptionRepository.save).not.toHaveBeenCalled()
})
})
@@ -1,8 +1,7 @@
import { DomainEventHandlerInterface, SubscriptionPurchasedEvent } from '@standardnotes/domain-events'
import { inject, injectable } from 'inversify'
import { Username } from '@standardnotes/domain-core'
import { Logger } from 'winston'
import TYPES from '../../Bootstrap/Types'
import { RoleServiceInterface } from '../Role/RoleServiceInterface'
import { User } from '../User/User'
import { UserRepositoryInterface } from '../User/UserRepositoryInterface'
@@ -11,21 +10,16 @@ import { UserSubscriptionRepositoryInterface } from '../Subscription/UserSubscri
import { OfflineUserSubscription } from '../Subscription/OfflineUserSubscription'
import { OfflineUserSubscriptionRepositoryInterface } from '../Subscription/OfflineUserSubscriptionRepositoryInterface'
import { UserSubscriptionType } from '../Subscription/UserSubscriptionType'
import { SubscriptionSettingServiceInterface } from '../Setting/SubscriptionSettingServiceInterface'
import { Username } from '@standardnotes/domain-core'
import { ApplyDefaultSubscriptionSettings } from '../UseCase/ApplyDefaultSubscriptionSettings/ApplyDefaultSubscriptionSettings'
@injectable()
export class SubscriptionPurchasedEventHandler implements DomainEventHandlerInterface {
constructor(
@inject(TYPES.Auth_UserRepository) private userRepository: UserRepositoryInterface,
@inject(TYPES.Auth_UserSubscriptionRepository)
private userRepository: UserRepositoryInterface,
private userSubscriptionRepository: UserSubscriptionRepositoryInterface,
@inject(TYPES.Auth_OfflineUserSubscriptionRepository)
private applyDefaultSubscriptionSettings: ApplyDefaultSubscriptionSettings,
private offlineUserSubscriptionRepository: OfflineUserSubscriptionRepositoryInterface,
@inject(TYPES.Auth_RoleService) private roleService: RoleServiceInterface,
@inject(TYPES.Auth_SubscriptionSettingService)
private subscriptionSettingService: SubscriptionSettingServiceInterface,
@inject(TYPES.Auth_Logger) private logger: Logger,
private roleService: RoleServiceInterface,
private logger: Logger,
) {}
async handle(event: SubscriptionPurchasedEvent): Promise<void> {
@@ -66,7 +60,15 @@ export class SubscriptionPurchasedEventHandler implements DomainEventHandlerInte
await this.addUserRole(user, event.payload.subscriptionName)
await this.subscriptionSettingService.applyDefaultSubscriptionSettingsForSubscription(userSubscription)
const result = await this.applyDefaultSubscriptionSettings.execute({
userSubscriptionUuid: userSubscription.uuid,
userUuid: user.uuid,
subscriptionPlanName: event.payload.subscriptionName,
})
if (result.isFailed()) {
this.logger.error(`Could not apply default subscription settings for user ${user.uuid}: ${result.getError()}`)
}
}
private async addUserRole(user: User, subscriptionName: string): Promise<void> {
@@ -1,161 +0,0 @@
import 'reflect-metadata'
import { SubscriptionName } from '@standardnotes/common'
import { RoleName } from '@standardnotes/domain-core'
import { SubscriptionReassignedEvent } from '@standardnotes/domain-events'
import { Logger } from 'winston'
import * as dayjs from 'dayjs'
import { RoleServiceInterface } from '../Role/RoleServiceInterface'
import { User } from '../User/User'
import { UserRepositoryInterface } from '../User/UserRepositoryInterface'
import { UserSubscriptionRepositoryInterface } from '../Subscription/UserSubscriptionRepositoryInterface'
import { SubscriptionReassignedEventHandler } from './SubscriptionReassignedEventHandler'
import { UserSubscription } from '../Subscription/UserSubscription'
import { SettingServiceInterface } from '../Setting/SettingServiceInterface'
import { UserSubscriptionType } from '../Subscription/UserSubscriptionType'
import { SubscriptionSettingServiceInterface } from '../Setting/SubscriptionSettingServiceInterface'
describe('SubscriptionReassignedEventHandler', () => {
let userRepository: UserRepositoryInterface
let userSubscriptionRepository: UserSubscriptionRepositoryInterface
let roleService: RoleServiceInterface
let logger: Logger
let user: User
let subscription: UserSubscription
let event: SubscriptionReassignedEvent
let subscriptionExpiresAt: number
let timestamp: number
let settingService: SettingServiceInterface
let subscriptionSettingService: SubscriptionSettingServiceInterface
const createHandler = () =>
new SubscriptionReassignedEventHandler(
userRepository,
userSubscriptionRepository,
roleService,
settingService,
subscriptionSettingService,
logger,
)
beforeEach(() => {
user = {
uuid: '123',
email: 'test@test.com',
roles: Promise.resolve([
{
name: RoleName.NAMES.CoreUser,
},
]),
} as jest.Mocked<User>
subscription = {
subscriptionType: UserSubscriptionType.Regular,
} as jest.Mocked<UserSubscription>
userRepository = {} as jest.Mocked<UserRepositoryInterface>
userRepository.findOneByUsernameOrEmail = jest.fn().mockReturnValue(user)
userRepository.save = jest.fn().mockReturnValue(user)
userSubscriptionRepository = {} as jest.Mocked<UserSubscriptionRepositoryInterface>
userSubscriptionRepository.save = jest.fn().mockReturnValue(subscription)
roleService = {} as jest.Mocked<RoleServiceInterface>
roleService.addUserRoleBasedOnSubscription = jest.fn()
subscriptionExpiresAt = timestamp + 365 * 1000
event = {} as jest.Mocked<SubscriptionReassignedEvent>
event.createdAt = new Date(1)
event.payload = {
subscriptionId: 1,
offline: false,
extensionKey: 'abc123',
userEmail: 'test@test.com',
subscriptionName: SubscriptionName.ProPlan,
subscriptionExpiresAt,
timestamp: dayjs.utc().valueOf(),
}
settingService = {} as jest.Mocked<SettingServiceInterface>
settingService.createOrReplace = jest.fn()
subscriptionSettingService = {} as jest.Mocked<SubscriptionSettingServiceInterface>
subscriptionSettingService.applyDefaultSubscriptionSettingsForSubscription = jest.fn()
logger = {} as jest.Mocked<Logger>
logger.info = jest.fn()
logger.warn = jest.fn()
})
it('should update user default settings', async () => {
await createHandler().handle(event)
expect(subscriptionSettingService.applyDefaultSubscriptionSettingsForSubscription).toHaveBeenCalledWith(
subscription,
)
})
it('should update the user role', async () => {
await createHandler().handle(event)
expect(roleService.addUserRoleBasedOnSubscription).toHaveBeenCalledWith(user, SubscriptionName.ProPlan)
})
it('should create subscription', async () => {
await createHandler().handle(event)
subscription.planName = SubscriptionName.ProPlan
subscription.endsAt = subscriptionExpiresAt
subscription.subscriptionId = 1
subscription.user = Promise.resolve(user)
expect(userSubscriptionRepository.save).toHaveBeenCalledWith({
...subscription,
createdAt: expect.any(Number),
updatedAt: expect.any(Number),
cancelled: false,
})
})
it('should create an extension key setting for the user', async () => {
await createHandler().handle(event)
expect(settingService.createOrReplace).toHaveBeenCalledWith({
props: {
name: 'EXTENSION_KEY',
serverEncryptionVersion: 1,
unencryptedValue: 'abc123',
sensitive: true,
},
user: {
uuid: '123',
email: 'test@test.com',
roles: Promise.resolve([
{
name: RoleName.NAMES.CoreUser,
},
]),
},
})
})
it('should not do anything if no user is found for specified email', async () => {
userRepository.findOneByUsernameOrEmail = jest.fn().mockReturnValue(null)
await createHandler().handle(event)
expect(roleService.addUserRoleBasedOnSubscription).not.toHaveBeenCalled()
expect(userSubscriptionRepository.save).not.toHaveBeenCalled()
})
it('should not do anything if username is invalid', async () => {
event.payload.userEmail = ' '
await createHandler().handle(event)
expect(roleService.addUserRoleBasedOnSubscription).not.toHaveBeenCalled()
expect(userSubscriptionRepository.save).not.toHaveBeenCalled()
})
})
@@ -1,31 +1,24 @@
import { DomainEventHandlerInterface, SubscriptionReassignedEvent } from '@standardnotes/domain-events'
import { inject, injectable } from 'inversify'
import { Logger } from 'winston'
import TYPES from '../../Bootstrap/Types'
import { RoleServiceInterface } from '../Role/RoleServiceInterface'
import { User } from '../User/User'
import { UserRepositoryInterface } from '../User/UserRepositoryInterface'
import { UserSubscription } from '../Subscription/UserSubscription'
import { UserSubscriptionRepositoryInterface } from '../Subscription/UserSubscriptionRepositoryInterface'
import { SettingServiceInterface } from '../Setting/SettingServiceInterface'
import { SettingName } from '@standardnotes/settings'
import { EncryptionVersion } from '../Encryption/EncryptionVersion'
import { UserSubscriptionType } from '../Subscription/UserSubscriptionType'
import { SubscriptionSettingServiceInterface } from '../Setting/SubscriptionSettingServiceInterface'
import { Username } from '@standardnotes/domain-core'
import { SettingName, Username } from '@standardnotes/domain-core'
import { ApplyDefaultSubscriptionSettings } from '../UseCase/ApplyDefaultSubscriptionSettings/ApplyDefaultSubscriptionSettings'
import { SetSettingValue } from '../UseCase/SetSettingValue/SetSettingValue'
@injectable()
export class SubscriptionReassignedEventHandler implements DomainEventHandlerInterface {
constructor(
@inject(TYPES.Auth_UserRepository) private userRepository: UserRepositoryInterface,
@inject(TYPES.Auth_UserSubscriptionRepository)
private userRepository: UserRepositoryInterface,
private userSubscriptionRepository: UserSubscriptionRepositoryInterface,
@inject(TYPES.Auth_RoleService) private roleService: RoleServiceInterface,
@inject(TYPES.Auth_SettingService) private settingService: SettingServiceInterface,
@inject(TYPES.Auth_SubscriptionSettingService)
private subscriptionSettingService: SubscriptionSettingServiceInterface,
@inject(TYPES.Auth_Logger) private logger: Logger,
private roleService: RoleServiceInterface,
private logger: Logger,
private applyDefaultSubscriptionSettings: ApplyDefaultSubscriptionSettings,
private setSettingValue: SetSettingValue,
) {}
async handle(event: SubscriptionReassignedEvent): Promise<void> {
@@ -53,17 +46,25 @@ export class SubscriptionReassignedEventHandler implements DomainEventHandlerInt
await this.addUserRole(user, event.payload.subscriptionName)
await this.settingService.createOrReplace({
user,
props: {
name: SettingName.NAMES.ExtensionKey,
unencryptedValue: event.payload.extensionKey,
serverEncryptionVersion: EncryptionVersion.Default,
sensitive: true,
},
const result = await this.setSettingValue.execute({
userUuid: user.uuid,
settingName: SettingName.NAMES.ExtensionKey,
value: event.payload.extensionKey,
})
if (result.isFailed()) {
this.logger.error(`Could not set extension key for user ${user.uuid}`)
}
await this.subscriptionSettingService.applyDefaultSubscriptionSettingsForSubscription(userSubscription)
const applyingSettingsResult = await this.applyDefaultSubscriptionSettings.execute({
subscriptionPlanName: event.payload.subscriptionName,
userUuid: user.uuid,
userSubscriptionUuid: userSubscription.uuid,
})
if (applyingSettingsResult.isFailed()) {
this.logger.error(
`Could not apply default subscription settings for user ${user.uuid}: ${applyingSettingsResult.getError()}`,
)
}
}
private async addUserRole(user: User, subscriptionName: string): Promise<void> {

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