Compare commits

...

53 Commits

Author SHA1 Message Date
standardci f911473be9 chore(release): publish new version
- @standardnotes/analytics@2.25.7
 - @standardnotes/api-gateway@1.69.2
 - @standardnotes/auth-server@1.128.1
 - @standardnotes/domain-core@1.24.2
 - @standardnotes/event-store@1.11.14
 - @standardnotes/files-server@1.19.17
 - @standardnotes/home-server@1.13.27
 - @standardnotes/revisions-server@1.26.1
 - @standardnotes/scheduler-server@1.20.16
 - @standardnotes/settings@1.21.21
 - @standardnotes/syncing-server@1.75.2
 - @standardnotes/websockets-server@1.10.11
2023-08-02 15:51:56 +00:00
Karol Sójko 71624f1897 fix(domain-core): remove unused content types 2023-08-02 17:34:40 +02:00
standardci 17de6ea7e1 chore(release): publish new version
- @standardnotes/home-server@1.13.26
 - @standardnotes/syncing-server@1.75.1
2023-08-02 11:41:20 +00:00
Karol Sójko 6aad7cd207 fix(syncing-server): update unknown content type on items migration 2023-08-02 13:24:14 +02:00
standardci 63af335877 chore(release): publish new version
- @standardnotes/auth-server@1.128.0
 - @standardnotes/home-server@1.13.25
 - @standardnotes/revisions-server@1.26.0
 - @standardnotes/syncing-server@1.75.0
2023-08-02 08:09:24 +00:00
Karol Sójko 8cd7a138ab feat: enable Write Ahead Log mode for SQLite (#681)
Co-authored-by: Karol Sójko <karolsojko@proton.me>
2023-08-02 09:47:37 +02:00
standardci f69cdc7b03 chore(release): publish new version
- @standardnotes/home-server@1.13.24
 - @standardnotes/syncing-server@1.74.1
 - @standardnotes/websockets-server@1.10.10
2023-08-02 07:35:12 +00:00
Karol Sójko 2ca649cf31 fix(syncing-server): encapsulate delete queries into transactions 2023-08-02 08:35:19 +02:00
Mo f2ada08201 chore: remove unused package (#680) 2023-08-02 07:46:10 +02:00
Mo 54ba1f69e5 chore: bump mocha timeout 2023-08-01 16:46:19 -05:00
standardci f13a99f5fd chore(release): publish new version
- @standardnotes/home-server@1.13.23
 - @standardnotes/syncing-server@1.74.0
2023-08-01 16:32:29 +00:00
Karol Sójko e9bba6fd3a feat(syncing-server): remove legacy privileges items (#679)
Co-authored-by: Karol Sójko <karolsojko@proton.me>
2023-08-01 18:15:16 +02:00
standardci f0d1a70c87 chore(release): publish new version
- @standardnotes/auth-server@1.127.2
 - @standardnotes/files-server@1.19.16
 - @standardnotes/home-server@1.13.22
 - @standardnotes/revisions-server@1.25.7
 - @standardnotes/syncing-server@1.73.1
 - @standardnotes/websockets-server@1.10.9
2023-08-01 07:53:07 +00:00
Karol Sójko 56f0aef21d fix: controller naming (#678)
* fix: rename home server controllers to base controllers

* fix: rename inversify express controllers to annotated controllers
2023-08-01 09:34:52 +02:00
standardci 75e266cb9e chore(release): publish new version
- @standardnotes/home-server@1.13.21
 - @standardnotes/syncing-server@1.73.0
2023-08-01 05:16:33 +00:00
Karol Sójko b9bb83c0ce feat(syncing-server): add shared vault snjs filter (#677)
Co-authored-by: Mo <mo@standardnotes.com>
2023-08-01 07:00:14 +02:00
standardci da645c5ab3 chore(release): publish new version
- @standardnotes/auth-server@1.127.1
 - @standardnotes/home-server@1.13.20
2023-07-31 13:33:09 +00:00
Karol Sójko 318af5757d fix(auth): auth middleware on delete account 2023-07-31 15:09:52 +02:00
standardci b1cc156a25 chore(release): publish new version
- @standardnotes/api-gateway@1.69.1
 - @standardnotes/home-server@1.13.19
2023-07-31 12:35:22 +00:00
Karol Sójko 79d71ca161 fix(api-gateway): remove duplicating req/res objects on return raw response from payments 2023-07-31 14:19:01 +02:00
standardci cedd50b366 chore(release): publish new version
- @standardnotes/api-gateway@1.69.0
 - @standardnotes/auth-server@1.127.0
 - @standardnotes/home-server@1.13.18
2023-07-31 11:41:55 +00:00
Karol Sójko 0d5dcdd8ec feat: refactor deleting account (#676)
* fix(api-gateway): TYPES aliases

* feat: refactor account deleting
2023-07-31 13:23:39 +02:00
standardci d2b0fb144b chore(release): publish new version
- @standardnotes/home-server@1.13.17
 - @standardnotes/syncing-server@1.72.2
2023-07-30 13:24:19 +00:00
Mo 053852b46c fix: missing var reference and brackets (#675) 2023-07-30 08:09:23 -05:00
Karol Sójko 6ad349d379 fix: db name encapsulation 2023-07-28 13:32:13 +02:00
Karol Sójko f7d33c7164 fix: separate databases and redis instances 2023-07-28 12:00:17 +02:00
Karol Sójko b53b67328f fix: displaying logs on docker failure 2023-07-28 11:23:16 +02:00
Karol Sójko 573ffbfcf3 fix: add showing logs on docker error 2023-07-28 10:19:32 +02:00
Karol Sójko 501ac0e99f fix: env vars for database runs 2023-07-27 14:32:55 +02:00
Karol Sójko 959a11293a fix: separate database for different configuration 2023-07-27 14:19:21 +02:00
standardci fee1f1a3a7 chore(release): publish new version
- @standardnotes/analytics@2.25.6
 - @standardnotes/api-gateway@1.68.1
 - @standardnotes/auth-server@1.126.5
 - @standardnotes/domain-core@1.24.1
 - @standardnotes/event-store@1.11.13
 - @standardnotes/files-server@1.19.15
 - @standardnotes/home-server@1.13.16
 - @standardnotes/revisions-server@1.25.6
 - @standardnotes/scheduler-server@1.20.15
 - @standardnotes/settings@1.21.20
 - @standardnotes/syncing-server@1.72.1
 - @standardnotes/websockets-server@1.10.8
2023-07-27 11:10:28 +00:00
Karol Sójko b0fbe0bb58 fix: extended access token refresh ttl during home server e2e 2023-07-27 12:54:50 +02:00
Karol Sójko 0087c70007 fix: missing env var on e2e 2023-07-27 12:25:31 +02:00
Karol Sójko 36e496dd7c fix: remove dns aliases on accessing mysql and redis in home server e2e 2023-07-27 12:19:01 +02:00
Karol Sójko f2e2030e85 fix: disable fail-fast on common e2e suite 2023-07-27 12:11:38 +02:00
Karol Sójko 0c3737dc19 fix: redirect STDERR for e2e to common output 2023-07-27 12:07:32 +02:00
Karol Sójko f7471119e1 fix: add logging error stack on home server failure 2023-07-27 12:00:40 +02:00
Karol Sójko 9bd97b95e9 fix: unset the custom dbsqlite path for e2e 2023-07-27 11:46:48 +02:00
Karol Sójko b7400c198f fix: setting env vars on common-e2e test suite 2023-07-27 11:30:49 +02:00
Karol Sójko f87036e3a8 fix: setting env vars on home server in e2e environment 2023-07-27 11:26:05 +02:00
Karol Sójko a43e5ef724 fix: outputing logs on e2e - already existing logs directory 2023-07-27 10:32:43 +02:00
Karol Sójko 913ced70b0 fix: outputing logs on e2e 2023-07-27 08:33:49 +02:00
standardci 6ffce30a36 chore(release): publish new version
- @standardnotes/api-gateway@1.68.0
 - @standardnotes/home-server@1.13.15
 - @standardnotes/syncing-server@1.72.0
2023-07-27 06:28:46 +00:00
Karol Sójko f5a57d886c fix: show logs on failing suite 2023-07-27 08:13:49 +02:00
Karol Sójko e8ba49ecca feat(syncing-server): add deleting outbound messages
Co-authored-by: Mo <mo@standardnotes.com>
2023-07-27 08:06:56 +02:00
Karol Sójko c79a5dc94b fix: add e2e yarn command for convenience 2023-07-26 15:23:08 +02:00
standardci 4db83ae678 chore(release): publish new version
- @standardnotes/analytics@2.25.5
 - @standardnotes/api-gateway@1.67.4
 - @standardnotes/auth-server@1.126.4
 - @standardnotes/domain-core@1.24.0
 - @standardnotes/event-store@1.11.12
 - @standardnotes/files-server@1.19.14
 - @standardnotes/home-server@1.13.14
 - @standardnotes/revisions-server@1.25.5
 - @standardnotes/scheduler-server@1.20.14
 - @standardnotes/settings@1.21.19
 - @standardnotes/syncing-server@1.71.0
 - @standardnotes/websockets-server@1.10.7
2023-07-26 12:07:57 +00:00
basiljelly 84ceb7ffd2 Update docker-compose.example.yml (#673)
added restart policy for container server_self_hosted so it restarts after rebooting system
2023-07-26 13:52:40 +02:00
Karol Sójko e215ac4343 feat: extract shared vault user permission to domain-core 2023-07-26 13:45:53 +02:00
standardci bc8048790f chore(release): publish new version
- @standardnotes/home-server@1.13.13
 - @standardnotes/syncing-server@1.70.5
2023-07-26 11:19:11 +00:00
Karol Sójko 886ccf84c1 fix(syncing-server): uuid comparison when removing user 2023-07-26 13:02:03 +02:00
standardci c067cb9fe4 chore(release): publish new version
- @standardnotes/home-server@1.13.12
 - @standardnotes/syncing-server@1.70.4
2023-07-26 10:54:46 +00:00
Karol Sójko 6b2389cdc3 fix(syncing-serve): removing other users from shared vault 2023-07-26 12:39:24 +02:00
234 changed files with 1799 additions and 709 deletions
+32 -10
View File
@@ -50,14 +50,30 @@ jobs:
run: docker/is-available.sh http://localhost:3123 $(pwd)/logs run: docker/is-available.sh http://localhost:3123 $(pwd)/logs
- name: Run E2E Test Suite - name: Run E2E Test Suite
run: yarn dlx mocha-headless-chrome --timeout 1200000 -f http://localhost:9001/mocha/test.html run: yarn dlx mocha-headless-chrome --timeout 1800000 -f http://localhost:9001/mocha/test.html
- name: Show logs on failure
if: ${{ failure() }}
run: |
echo "# Errors:"
tail -n 100 logs/*.err
echo "# Logs:"
tail -n 100 logs/*.log
e2e-home-server: e2e-home-server:
name: (Home Server) E2E Test Suite name: (Home Server) E2E Test Suite
strategy: strategy:
fail-fast: false
matrix: matrix:
db_type: [mysql, sqlite] db_type: [mysql, sqlite]
cache_type: [redis, memory] cache_type: [redis, memory]
include:
- cache_type: redis
db_type: mysql
redis_port: 6380
- cache_type: redis
db_type: sqlite
redis_port: 6381
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -69,14 +85,14 @@ jobs:
cache: cache:
image: redis image: redis
ports: ports:
- 6379:6379 - ${{ matrix.redis_port }}:6379
db: db:
image: mysql image: mysql
ports: ports:
- 3306:3306 - 3307:3306
env: env:
MYSQL_ROOT_PASSWORD: root MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: standardnotes MYSQL_DATABASE: standardnotes_${{ matrix.cache_type }}
MYSQL_USER: standardnotes MYSQL_USER: standardnotes
MYSQL_PASSWORD: standardnotes MYSQL_PASSWORD: standardnotes
@@ -106,20 +122,22 @@ jobs:
sed -i "s/PSEUDO_KEY_PARAMS_KEY=/PSEUDO_KEY_PARAMS_KEY=$(openssl rand -hex 32)/g" packages/home-server/.env sed -i "s/PSEUDO_KEY_PARAMS_KEY=/PSEUDO_KEY_PARAMS_KEY=$(openssl rand -hex 32)/g" packages/home-server/.env
sed -i "s/VALET_TOKEN_SECRET=/VALET_TOKEN_SECRET=$(openssl rand -hex 32)/g" packages/home-server/.env sed -i "s/VALET_TOKEN_SECRET=/VALET_TOKEN_SECRET=$(openssl rand -hex 32)/g" packages/home-server/.env
echo "ACCESS_TOKEN_AGE=4" >> packages/home-server/.env echo "ACCESS_TOKEN_AGE=4" >> packages/home-server/.env
echo "REFRESH_TOKEN_AGE=7" >> packages/home-server/.env echo "REFRESH_TOKEN_AGE=10" >> packages/home-server/.env
echo "REVISIONS_FREQUENCY=5" >> packages/home-server/.env echo "REVISIONS_FREQUENCY=5" >> packages/home-server/.env
echo "DB_HOST=db" >> packages/home-server/.env echo "DB_HOST=localhost" >> packages/home-server/.env
echo "DB_PORT=3306" >> packages/home-server/.env echo "DB_PORT=3307" >> packages/home-server/.env
echo "DB_DATABASE=standardnotes_${{ matrix.cache_type }}" >> packages/home-server/.env
echo "DB_SQLITE_DATABASE_PATH=sqlite_${{ matrix.cache_type }}.db" >> packages/home-server/.env
echo "DB_USERNAME=standardnotes" >> packages/home-server/.env echo "DB_USERNAME=standardnotes" >> packages/home-server/.env
echo "DB_PASSWORD=standardnotes" >> packages/home-server/.env echo "DB_PASSWORD=standardnotes" >> packages/home-server/.env
echo "DB_TYPE=${{ matrix.db_type }}" >> packages/home-server/.env echo "DB_TYPE=${{ matrix.db_type }}" >> packages/home-server/.env
echo "REDIS_URL=redis://cache" >> packages/home-server/.env echo "REDIS_URL=redis://localhost:${{ matrix.redis_port }}" >> packages/home-server/.env
echo "CACHE_TYPE=${{ matrix.cache_type }}" >> packages/home-server/.env echo "CACHE_TYPE=${{ matrix.cache_type }}" >> packages/home-server/.env
echo "FILES_SERVER_URL=http://localhost:3123" >> packages/home-server/.env echo "FILES_SERVER_URL=http://localhost:3123" >> packages/home-server/.env
echo "E2E_TESTING=true" >> packages/home-server/.env echo "E2E_TESTING=true" >> packages/home-server/.env
- name: Run Server - name: Run Server
run: nohup yarn workspace @standardnotes/home-server start & run: nohup yarn workspace @standardnotes/home-server start > logs/output.log 2>&1 &
env: env:
PORT: 3123 PORT: 3123
@@ -127,4 +145,8 @@ jobs:
run: for i in {1..30}; do curl -s http://localhost:3123/healthcheck && break || sleep 1; done run: for i in {1..30}; do curl -s http://localhost:3123/healthcheck && break || sleep 1; done
- name: Run E2E Test Suite - name: Run E2E Test Suite
run: yarn dlx mocha-headless-chrome --timeout 1200000 -f http://localhost:9001/mocha/test.html run: yarn dlx mocha-headless-chrome --timeout 1800000 -f http://localhost:9001/mocha/test.html
- name: Show logs on failure
if: ${{ failure() }}
run: tail -n 500 logs/output.log
Generated
-1
View File
@@ -5259,7 +5259,6 @@ const RAW_RUNTIME_STATE =
["@standardnotes/domain-events-infra", "workspace:packages/domain-events-infra"],\ ["@standardnotes/domain-events-infra", "workspace:packages/domain-events-infra"],\
["@standardnotes/responses", "npm:1.13.27"],\ ["@standardnotes/responses", "npm:1.13.27"],\
["@standardnotes/security", "workspace:packages/security"],\ ["@standardnotes/security", "workspace:packages/security"],\
["@standardnotes/utils", "npm:1.17.5"],\
["@types/cors", "npm:2.8.13"],\ ["@types/cors", "npm:2.8.13"],\
["@types/express", "npm:4.17.17"],\ ["@types/express", "npm:4.17.17"],\
["@types/ioredis", "npm:5.0.0"],\ ["@types/ioredis", "npm:5.0.0"],\
+1
View File
@@ -3,6 +3,7 @@ services:
image: standardnotes/server image: standardnotes/server
env_file: .env env_file: .env
container_name: server_self_hosted container_name: server_self_hosted
restart: unless-stopped
ports: ports:
- 3000:3000 - 3000:3000
- 3125:3104 - 3125:3104
+3 -1
View File
@@ -12,12 +12,14 @@
}, },
"scripts": { "scripts": {
"lint": "yarn workspaces foreach -p -j 10 --verbose run lint", "lint": "yarn workspaces foreach -p -j 10 --verbose run lint",
"lint:fix": "yarn workspaces foreach -p -j 10 --verbose run lint:fix",
"clean": "yarn workspaces foreach -p --verbose run clean", "clean": "yarn workspaces foreach -p --verbose run clean",
"setup:env": "cp .env.sample .env && yarn workspaces foreach -p --verbose run setup:env", "setup:env": "cp .env.sample .env && yarn workspaces foreach -p --verbose run setup:env",
"release": "lerna version --conventional-graduate --conventional-commits --yes -m \"chore(release): publish new version\"", "release": "lerna version --conventional-graduate --conventional-commits --yes -m \"chore(release): publish new version\"",
"publish": "lerna publish from-git --yes --no-verify-access --loglevel verbose", "publish": "lerna publish from-git --yes --no-verify-access --loglevel verbose",
"postversion": "./scripts/push-tags-one-by-one.sh", "postversion": "./scripts/push-tags-one-by-one.sh",
"upgrade:snjs": "yarn workspaces foreach --verbose run upgrade:snjs" "upgrade:snjs": "yarn workspaces foreach --verbose run upgrade:snjs",
"e2e": "yarn build packages/home-server && PORT=3123 yarn workspace @standardnotes/home-server start"
}, },
"devDependencies": { "devDependencies": {
"@commitlint/cli": "^17.0.2", "@commitlint/cli": "^17.0.2",
+12
View File
@@ -3,6 +3,18 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [2.25.7](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.25.6...@standardnotes/analytics@2.25.7) (2023-08-02)
**Note:** Version bump only for package @standardnotes/analytics
## [2.25.6](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.25.5...@standardnotes/analytics@2.25.6) (2023-07-27)
**Note:** Version bump only for package @standardnotes/analytics
## [2.25.5](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.25.4...@standardnotes/analytics@2.25.5) (2023-07-26)
**Note:** Version bump only for package @standardnotes/analytics
## [2.25.4](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.25.3...@standardnotes/analytics@2.25.4) (2023-07-26) ## [2.25.4](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.25.3...@standardnotes/analytics@2.25.4) (2023-07-26)
**Note:** Version bump only for package @standardnotes/analytics **Note:** Version bump only for package @standardnotes/analytics
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@standardnotes/analytics", "name": "@standardnotes/analytics",
"version": "2.25.4", "version": "2.25.7",
"engines": { "engines": {
"node": ">=18.0.0 <21.0.0" "node": ">=18.0.0 <21.0.0"
}, },
+30
View File
@@ -3,6 +3,36 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.69.2](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.69.1...@standardnotes/api-gateway@1.69.2) (2023-08-02)
**Note:** Version bump only for package @standardnotes/api-gateway
## [1.69.1](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.69.0...@standardnotes/api-gateway@1.69.1) (2023-07-31)
### Bug Fixes
* **api-gateway:** remove duplicating req/res objects on return raw response from payments ([79d71ca](https://github.com/standardnotes/api-gateway/commit/79d71ca161cc18135fcd1a83b021662e189b3ddb))
# [1.69.0](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.68.1...@standardnotes/api-gateway@1.69.0) (2023-07-31)
### Features
* refactor deleting account ([#676](https://github.com/standardnotes/api-gateway/issues/676)) ([0d5dcdd](https://github.com/standardnotes/api-gateway/commit/0d5dcdd8ec2336e41e7604c4157f79a89163ed29))
## [1.68.1](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.68.0...@standardnotes/api-gateway@1.68.1) (2023-07-27)
**Note:** Version bump only for package @standardnotes/api-gateway
# [1.68.0](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.67.4...@standardnotes/api-gateway@1.68.0) (2023-07-27)
### Features
* **syncing-server:** add deleting outbound messages ([e8ba49e](https://github.com/standardnotes/api-gateway/commit/e8ba49ecca38ab10c0ea0e1f4cf4db9fb17366db))
## [1.67.4](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.67.3...@standardnotes/api-gateway@1.67.4) (2023-07-26)
**Note:** Version bump only for package @standardnotes/api-gateway
## [1.67.3](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.67.2...@standardnotes/api-gateway@1.67.3) (2023-07-26) ## [1.67.3](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.67.2...@standardnotes/api-gateway@1.67.3) (2023-07-26)
**Note:** Version bump only for package @standardnotes/api-gateway **Note:** Version bump only for package @standardnotes/api-gateway
+2 -2
View File
@@ -46,7 +46,7 @@ void container.load().then((container) => {
server.setConfig((app) => { server.setConfig((app) => {
app.use((_request: Request, response: Response, next: NextFunction) => { app.use((_request: Request, response: Response, next: NextFunction) => {
response.setHeader('X-API-Gateway-Version', container.get(TYPES.VERSION)) response.setHeader('X-API-Gateway-Version', container.get(TYPES.ApiGateway_VERSION))
next() next()
}) })
app.use( app.use(
@@ -87,7 +87,7 @@ void container.load().then((container) => {
) )
}) })
const logger: winston.Logger = container.get(TYPES.Logger) const logger: winston.Logger = container.get(TYPES.ApiGateway_Logger)
server.setErrorConfig((app) => { server.setErrorConfig((app) => {
app.use((error: Record<string, unknown>, _request: Request, response: Response, _next: NextFunction) => { app.use((error: Record<string, unknown>, _request: Request, response: Response, _next: NextFunction) => {
+2 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@standardnotes/api-gateway", "name": "@standardnotes/api-gateway",
"version": "1.67.3", "version": "1.69.2",
"engines": { "engines": {
"node": ">=18.0.0 <21.0.0" "node": ">=18.0.0 <21.0.0"
}, },
@@ -21,6 +21,7 @@
"clean": "rm -fr dist", "clean": "rm -fr dist",
"build": "tsc --build", "build": "tsc --build",
"lint": "eslint . --ext .ts", "lint": "eslint . --ext .ts",
"lint:fix": "eslint . --fix --ext .ts",
"setup:env": "cp .env.sample .env", "setup:env": "cp .env.sample .env",
"start": "yarn node dist/bin/server.js", "start": "yarn node dist/bin/server.js",
"upgrade:snjs": "yarn ncu -u '@standardnotes/*'" "upgrade:snjs": "yarn ncu -u '@standardnotes/*'"
+31 -26
View File
@@ -57,7 +57,7 @@ export class ContainerConfigLoader {
defaultMeta: { service: 'api-gateway' }, defaultMeta: { service: 'api-gateway' },
}) })
} }
container.bind<winston.Logger>(TYPES.Logger).toConstantValue(logger) container.bind<winston.Logger>(TYPES.ApiGateway_Logger).toConstantValue(logger)
if (!isConfiguredForInMemoryCache) { if (!isConfiguredForInMemoryCache) {
const redisUrl = env.get('REDIS_URL') const redisUrl = env.get('REDIS_URL')
@@ -68,36 +68,39 @@ export class ContainerConfigLoader {
} else { } else {
redis = new Redis(redisUrl) redis = new Redis(redisUrl)
} }
container.bind(TYPES.Redis).toConstantValue(redis) container.bind(TYPES.ApiGateway_Redis).toConstantValue(redis)
} }
container.bind<AxiosInstance>(TYPES.HTTPClient).toConstantValue(axios.create()) container.bind<AxiosInstance>(TYPES.ApiGateway_HTTPClient).toConstantValue(axios.create())
// env vars // env vars
container.bind(TYPES.SYNCING_SERVER_JS_URL).toConstantValue(env.get('SYNCING_SERVER_JS_URL', true)) container.bind(TYPES.ApiGateway_SYNCING_SERVER_JS_URL).toConstantValue(env.get('SYNCING_SERVER_JS_URL', true))
container.bind(TYPES.AUTH_SERVER_URL).toConstantValue(env.get('AUTH_SERVER_URL', true)) container.bind(TYPES.ApiGateway_AUTH_SERVER_URL).toConstantValue(env.get('AUTH_SERVER_URL', true))
container.bind(TYPES.REVISIONS_SERVER_URL).toConstantValue(env.get('REVISIONS_SERVER_URL', true)) container.bind(TYPES.ApiGateway_REVISIONS_SERVER_URL).toConstantValue(env.get('REVISIONS_SERVER_URL', true))
container.bind(TYPES.EMAIL_SERVER_URL).toConstantValue(env.get('EMAIL_SERVER_URL', true)) container.bind(TYPES.ApiGateway_EMAIL_SERVER_URL).toConstantValue(env.get('EMAIL_SERVER_URL', true))
container.bind(TYPES.PAYMENTS_SERVER_URL).toConstantValue(env.get('PAYMENTS_SERVER_URL', true)) container.bind(TYPES.ApiGateway_PAYMENTS_SERVER_URL).toConstantValue(env.get('PAYMENTS_SERVER_URL', true))
container.bind(TYPES.FILES_SERVER_URL).toConstantValue(env.get('FILES_SERVER_URL', true)) container.bind(TYPES.ApiGateway_FILES_SERVER_URL).toConstantValue(env.get('FILES_SERVER_URL', true))
container.bind(TYPES.WEB_SOCKET_SERVER_URL).toConstantValue(env.get('WEB_SOCKET_SERVER_URL', true)) container.bind(TYPES.ApiGateway_WEB_SOCKET_SERVER_URL).toConstantValue(env.get('WEB_SOCKET_SERVER_URL', true))
container.bind(TYPES.AUTH_JWT_SECRET).toConstantValue(env.get('AUTH_JWT_SECRET')) container.bind(TYPES.ApiGateway_AUTH_JWT_SECRET).toConstantValue(env.get('AUTH_JWT_SECRET'))
container container
.bind(TYPES.HTTP_CALL_TIMEOUT) .bind(TYPES.ApiGateway_HTTP_CALL_TIMEOUT)
.toConstantValue(env.get('HTTP_CALL_TIMEOUT', true) ? +env.get('HTTP_CALL_TIMEOUT', true) : 60_000) .toConstantValue(env.get('HTTP_CALL_TIMEOUT', true) ? +env.get('HTTP_CALL_TIMEOUT', true) : 60_000)
container.bind(TYPES.VERSION).toConstantValue(env.get('VERSION', true) ?? 'development') container.bind(TYPES.ApiGateway_VERSION).toConstantValue(env.get('VERSION', true) ?? 'development')
container.bind(TYPES.CROSS_SERVICE_TOKEN_CACHE_TTL).toConstantValue(+env.get('CROSS_SERVICE_TOKEN_CACHE_TTL', true)) container
.bind(TYPES.ApiGateway_CROSS_SERVICE_TOKEN_CACHE_TTL)
.toConstantValue(+env.get('CROSS_SERVICE_TOKEN_CACHE_TTL', true))
container.bind(TYPES.ApiGateway_IS_CONFIGURED_FOR_HOME_SERVER).toConstantValue(isConfiguredForHomeServer)
// Middleware // Middleware
container container
.bind<RequiredCrossServiceTokenMiddleware>(TYPES.RequiredCrossServiceTokenMiddleware) .bind<RequiredCrossServiceTokenMiddleware>(TYPES.ApiGateway_RequiredCrossServiceTokenMiddleware)
.to(RequiredCrossServiceTokenMiddleware) .to(RequiredCrossServiceTokenMiddleware)
container container
.bind<OptionalCrossServiceTokenMiddleware>(TYPES.OptionalCrossServiceTokenMiddleware) .bind<OptionalCrossServiceTokenMiddleware>(TYPES.ApiGateway_OptionalCrossServiceTokenMiddleware)
.to(OptionalCrossServiceTokenMiddleware) .to(OptionalCrossServiceTokenMiddleware)
container.bind<WebSocketAuthMiddleware>(TYPES.WebSocketAuthMiddleware).to(WebSocketAuthMiddleware) container.bind<WebSocketAuthMiddleware>(TYPES.ApiGateway_WebSocketAuthMiddleware).to(WebSocketAuthMiddleware)
container container
.bind<SubscriptionTokenAuthMiddleware>(TYPES.SubscriptionTokenAuthMiddleware) .bind<SubscriptionTokenAuthMiddleware>(TYPES.ApiGateway_SubscriptionTokenAuthMiddleware)
.to(SubscriptionTokenAuthMiddleware) .to(SubscriptionTokenAuthMiddleware)
// Services // Services
@@ -106,24 +109,26 @@ export class ContainerConfigLoader {
throw new Error('Service container is required when configured for home server') throw new Error('Service container is required when configured for home server')
} }
container container
.bind<ServiceProxyInterface>(TYPES.ServiceProxy) .bind<ServiceProxyInterface>(TYPES.ApiGateway_ServiceProxy)
.toConstantValue( .toConstantValue(
new DirectCallServiceProxy(configuration.serviceContainer, container.get(TYPES.FILES_SERVER_URL)), new DirectCallServiceProxy(configuration.serviceContainer, container.get(TYPES.ApiGateway_FILES_SERVER_URL)),
) )
} else { } else {
container.bind<ServiceProxyInterface>(TYPES.ServiceProxy).to(HttpServiceProxy) container.bind<ServiceProxyInterface>(TYPES.ApiGateway_ServiceProxy).to(HttpServiceProxy)
} }
container.bind<TimerInterface>(TYPES.Timer).toConstantValue(new Timer()) container.bind<TimerInterface>(TYPES.ApiGateway_Timer).toConstantValue(new Timer())
if (isConfiguredForHomeServer) { if (isConfiguredForHomeServer) {
container container
.bind<CrossServiceTokenCacheInterface>(TYPES.CrossServiceTokenCache) .bind<CrossServiceTokenCacheInterface>(TYPES.ApiGateway_CrossServiceTokenCache)
.toConstantValue(new InMemoryCrossServiceTokenCache(container.get(TYPES.Timer))) .toConstantValue(new InMemoryCrossServiceTokenCache(container.get(TYPES.ApiGateway_Timer)))
} else { } else {
container.bind<CrossServiceTokenCacheInterface>(TYPES.CrossServiceTokenCache).to(RedisCrossServiceTokenCache) container
.bind<CrossServiceTokenCacheInterface>(TYPES.ApiGateway_CrossServiceTokenCache)
.to(RedisCrossServiceTokenCache)
} }
container container
.bind<EndpointResolverInterface>(TYPES.EndpointResolver) .bind<EndpointResolverInterface>(TYPES.ApiGateway_EndpointResolver)
.toConstantValue(new EndpointResolver(isConfiguredForHomeServer)) .toConstantValue(new EndpointResolver(isConfiguredForHomeServer))
logger.debug('Configuration complete') logger.debug('Configuration complete')
+23 -24
View File
@@ -1,29 +1,28 @@
export const TYPES = { export const TYPES = {
Logger: Symbol.for('Logger'), ApiGateway_Logger: Symbol.for('ApiGateway_Logger'),
Redis: Symbol.for('Redis'), ApiGateway_Redis: Symbol.for('ApiGateway_Redis'),
HTTPClient: Symbol.for('HTTPClient'), ApiGateway_HTTPClient: Symbol.for('ApiGateway_HTTPClient'),
// env vars // env vars
SYNCING_SERVER_JS_URL: Symbol.for('SYNCING_SERVER_JS_URL'), ApiGateway_SYNCING_SERVER_JS_URL: Symbol.for('ApiGateway_SYNCING_SERVER_JS_URL'),
AUTH_SERVER_URL: Symbol.for('AUTH_SERVER_URL'), ApiGateway_AUTH_SERVER_URL: Symbol.for('ApiGateway_AUTH_SERVER_URL'),
PAYMENTS_SERVER_URL: Symbol.for('PAYMENTS_SERVER_URL'), ApiGateway_PAYMENTS_SERVER_URL: Symbol.for('ApiGateway_PAYMENTS_SERVER_URL'),
FILES_SERVER_URL: Symbol.for('FILES_SERVER_URL'), ApiGateway_FILES_SERVER_URL: Symbol.for('ApiGateway_FILES_SERVER_URL'),
REVISIONS_SERVER_URL: Symbol.for('REVISIONS_SERVER_URL'), ApiGateway_REVISIONS_SERVER_URL: Symbol.for('ApiGateway_REVISIONS_SERVER_URL'),
EMAIL_SERVER_URL: Symbol.for('EMAIL_SERVER_URL'), ApiGateway_EMAIL_SERVER_URL: Symbol.for('ApiGateway_EMAIL_SERVER_URL'),
WEB_SOCKET_SERVER_URL: Symbol.for('WEB_SOCKET_SERVER_URL'), ApiGateway_WEB_SOCKET_SERVER_URL: Symbol.for('ApiGateway_WEB_SOCKET_SERVER_URL'),
AUTH_JWT_SECRET: Symbol.for('AUTH_JWT_SECRET'), ApiGateway_AUTH_JWT_SECRET: Symbol.for('ApiGateway_AUTH_JWT_SECRET'),
HTTP_CALL_TIMEOUT: Symbol.for('HTTP_CALL_TIMEOUT'), ApiGateway_HTTP_CALL_TIMEOUT: Symbol.for('ApiGateway_HTTP_CALL_TIMEOUT'),
VERSION: Symbol.for('VERSION'), ApiGateway_VERSION: Symbol.for('ApiGateway_VERSION'),
CROSS_SERVICE_TOKEN_CACHE_TTL: Symbol.for('CROSS_SERVICE_TOKEN_CACHE_TTL'), ApiGateway_CROSS_SERVICE_TOKEN_CACHE_TTL: Symbol.for('ApiGateway_CROSS_SERVICE_TOKEN_CACHE_TTL'),
ApiGateway_IS_CONFIGURED_FOR_HOME_SERVER: Symbol.for('ApiGateway_IS_CONFIGURED_FOR_HOME_SERVER'),
// Middleware // Middleware
RequiredCrossServiceTokenMiddleware: Symbol.for('RequiredCrossServiceTokenMiddleware'), ApiGateway_RequiredCrossServiceTokenMiddleware: Symbol.for('ApiGateway_RequiredCrossServiceTokenMiddleware'),
OptionalCrossServiceTokenMiddleware: Symbol.for('OptionalCrossServiceTokenMiddleware'), ApiGateway_OptionalCrossServiceTokenMiddleware: Symbol.for('ApiGateway_OptionalCrossServiceTokenMiddleware'),
WebSocketAuthMiddleware: Symbol.for('WebSocketAuthMiddleware'), ApiGateway_WebSocketAuthMiddleware: Symbol.for('ApiGateway_WebSocketAuthMiddleware'),
SubscriptionTokenAuthMiddleware: Symbol.for('SubscriptionTokenAuthMiddleware'), ApiGateway_SubscriptionTokenAuthMiddleware: Symbol.for('ApiGateway_SubscriptionTokenAuthMiddleware'),
// Services // Services
ServiceProxy: Symbol.for('ServiceProxy'), ApiGateway_ServiceProxy: Symbol.for('ApiGateway_ServiceProxy'),
CrossServiceTokenCache: Symbol.for('CrossServiceTokenCache'), ApiGateway_CrossServiceTokenCache: Symbol.for('ApiGateway_CrossServiceTokenCache'),
Timer: Symbol.for('Timer'), ApiGateway_Timer: Symbol.for('ApiGateway_Timer'),
EndpointResolver: Symbol.for('EndpointResolver'), ApiGateway_EndpointResolver: Symbol.for('ApiGateway_EndpointResolver'),
} }
// export default TYPES
@@ -9,7 +9,7 @@ export class LegacyController extends BaseHttpController {
private AUTH_ROUTES: Map<string, string> private AUTH_ROUTES: Map<string, string>
private PARAMETRIZED_AUTH_ROUTES: Map<string, string> private PARAMETRIZED_AUTH_ROUTES: Map<string, string>
constructor(@inject(TYPES.ServiceProxy) private httpService: ServiceProxyInterface) { constructor(@inject(TYPES.ApiGateway_ServiceProxy) private httpService: ServiceProxyInterface) {
super() super()
this.AUTH_ROUTES = new Map([ this.AUTH_ROUTES = new Map([
@@ -29,17 +29,17 @@ export class LegacyController extends BaseHttpController {
]) ])
} }
@httpPost('/items/sync', TYPES.RequiredCrossServiceTokenMiddleware) @httpPost('/items/sync', TYPES.ApiGateway_RequiredCrossServiceTokenMiddleware)
async legacyItemsSync(request: Request, response: Response): Promise<void> { async legacyItemsSync(request: Request, response: Response): Promise<void> {
await this.httpService.callLegacySyncingServer(request, response, request.path.substring(1), request.body) await this.httpService.callLegacySyncingServer(request, response, request.path.substring(1), request.body)
} }
@httpGet('/items/:item_id/revisions', TYPES.RequiredCrossServiceTokenMiddleware) @httpGet('/items/:item_id/revisions', TYPES.ApiGateway_RequiredCrossServiceTokenMiddleware)
async legacyGetRevisions(request: Request, response: Response): Promise<void> { async legacyGetRevisions(request: Request, response: Response): Promise<void> {
await this.httpService.callLegacySyncingServer(request, response, request.path.substring(1), request.body) await this.httpService.callLegacySyncingServer(request, response, request.path.substring(1), request.body)
} }
@httpGet('/items/:item_id/revisions/:id', TYPES.RequiredCrossServiceTokenMiddleware) @httpGet('/items/:item_id/revisions/:id', TYPES.ApiGateway_RequiredCrossServiceTokenMiddleware)
async legacyGetRevision(request: Request, response: Response): Promise<void> { async legacyGetRevision(request: Request, response: Response): Promise<void> {
await this.httpService.callLegacySyncingServer(request, response, request.path.substring(1), request.body) await this.httpService.callLegacySyncingServer(request, response, request.path.substring(1), request.body)
} }
@@ -11,12 +11,12 @@ import { AuthMiddleware } from './AuthMiddleware'
@injectable() @injectable()
export class OptionalCrossServiceTokenMiddleware extends AuthMiddleware { export class OptionalCrossServiceTokenMiddleware extends AuthMiddleware {
constructor( constructor(
@inject(TYPES.ServiceProxy) serviceProxy: ServiceProxyInterface, @inject(TYPES.ApiGateway_ServiceProxy) serviceProxy: ServiceProxyInterface,
@inject(TYPES.AUTH_JWT_SECRET) jwtSecret: string, @inject(TYPES.ApiGateway_AUTH_JWT_SECRET) jwtSecret: string,
@inject(TYPES.CROSS_SERVICE_TOKEN_CACHE_TTL) crossServiceTokenCacheTTL: number, @inject(TYPES.ApiGateway_CROSS_SERVICE_TOKEN_CACHE_TTL) crossServiceTokenCacheTTL: number,
@inject(TYPES.CrossServiceTokenCache) crossServiceTokenCache: CrossServiceTokenCacheInterface, @inject(TYPES.ApiGateway_CrossServiceTokenCache) crossServiceTokenCache: CrossServiceTokenCacheInterface,
@inject(TYPES.Timer) timer: TimerInterface, @inject(TYPES.ApiGateway_Timer) timer: TimerInterface,
@inject(TYPES.Logger) logger: Logger, @inject(TYPES.ApiGateway_Logger) logger: Logger,
) { ) {
super(serviceProxy, jwtSecret, crossServiceTokenCacheTTL, crossServiceTokenCache, timer, logger) super(serviceProxy, jwtSecret, crossServiceTokenCacheTTL, crossServiceTokenCache, timer, logger)
} }
@@ -11,12 +11,12 @@ import { AuthMiddleware } from './AuthMiddleware'
@injectable() @injectable()
export class RequiredCrossServiceTokenMiddleware extends AuthMiddleware { export class RequiredCrossServiceTokenMiddleware extends AuthMiddleware {
constructor( constructor(
@inject(TYPES.ServiceProxy) serviceProxy: ServiceProxyInterface, @inject(TYPES.ApiGateway_ServiceProxy) serviceProxy: ServiceProxyInterface,
@inject(TYPES.AUTH_JWT_SECRET) jwtSecret: string, @inject(TYPES.ApiGateway_AUTH_JWT_SECRET) jwtSecret: string,
@inject(TYPES.CROSS_SERVICE_TOKEN_CACHE_TTL) crossServiceTokenCacheTTL: number, @inject(TYPES.ApiGateway_CROSS_SERVICE_TOKEN_CACHE_TTL) crossServiceTokenCacheTTL: number,
@inject(TYPES.CrossServiceTokenCache) crossServiceTokenCache: CrossServiceTokenCacheInterface, @inject(TYPES.ApiGateway_CrossServiceTokenCache) crossServiceTokenCache: CrossServiceTokenCacheInterface,
@inject(TYPES.Timer) timer: TimerInterface, @inject(TYPES.ApiGateway_Timer) timer: TimerInterface,
@inject(TYPES.Logger) logger: Logger, @inject(TYPES.ApiGateway_Logger) logger: Logger,
) { ) {
super(serviceProxy, jwtSecret, crossServiceTokenCacheTTL, crossServiceTokenCache, timer, logger) super(serviceProxy, jwtSecret, crossServiceTokenCacheTTL, crossServiceTokenCache, timer, logger)
} }
@@ -11,10 +11,10 @@ import { TokenAuthenticationMethod } from './TokenAuthenticationMethod'
@injectable() @injectable()
export class SubscriptionTokenAuthMiddleware extends BaseMiddleware { export class SubscriptionTokenAuthMiddleware extends BaseMiddleware {
constructor( constructor(
@inject(TYPES.HTTPClient) private httpClient: AxiosInstance, @inject(TYPES.ApiGateway_HTTPClient) private httpClient: AxiosInstance,
@inject(TYPES.AUTH_SERVER_URL) private authServerUrl: string, @inject(TYPES.ApiGateway_AUTH_SERVER_URL) private authServerUrl: string,
@inject(TYPES.AUTH_JWT_SECRET) private jwtSecret: string, @inject(TYPES.ApiGateway_AUTH_JWT_SECRET) private jwtSecret: string,
@inject(TYPES.Logger) private logger: Logger, @inject(TYPES.ApiGateway_Logger) private logger: Logger,
) { ) {
super() super()
} }
@@ -12,10 +12,10 @@ import { TYPES } from '../Bootstrap/Types'
@injectable() @injectable()
export class WebSocketAuthMiddleware extends BaseMiddleware { export class WebSocketAuthMiddleware extends BaseMiddleware {
constructor( constructor(
@inject(TYPES.HTTPClient) private httpClient: AxiosInstance, @inject(TYPES.ApiGateway_HTTPClient) private httpClient: AxiosInstance,
@inject(TYPES.AUTH_SERVER_URL) private authServerUrl: string, @inject(TYPES.ApiGateway_AUTH_SERVER_URL) private authServerUrl: string,
@inject(TYPES.AUTH_JWT_SECRET) private jwtSecret: string, @inject(TYPES.ApiGateway_AUTH_JWT_SECRET) private jwtSecret: string,
@inject(TYPES.Logger) private logger: Logger, @inject(TYPES.ApiGateway_Logger) private logger: Logger,
) { ) {
super() super()
} }
@@ -8,8 +8,8 @@ import { EndpointResolverInterface } from '../../Service/Resolver/EndpointResolv
@controller('/v1') @controller('/v1')
export class ActionsController extends BaseHttpController { export class ActionsController extends BaseHttpController {
constructor( constructor(
@inject(TYPES.ServiceProxy) private serviceProxy: ServiceProxyInterface, @inject(TYPES.ApiGateway_ServiceProxy) private serviceProxy: ServiceProxyInterface,
@inject(TYPES.EndpointResolver) private endpointResolver: EndpointResolverInterface, @inject(TYPES.ApiGateway_EndpointResolver) private endpointResolver: EndpointResolverInterface,
) { ) {
super() super()
} }
@@ -24,7 +24,7 @@ export class ActionsController extends BaseHttpController {
) )
} }
@httpGet('/login-params', TYPES.OptionalCrossServiceTokenMiddleware) @httpGet('/login-params', TYPES.ApiGateway_OptionalCrossServiceTokenMiddleware)
async loginParams(request: Request, response: Response): Promise<void> { async loginParams(request: Request, response: Response): Promise<void> {
await this.serviceProxy.callAuthServer( await this.serviceProxy.callAuthServer(
request, request,
@@ -34,7 +34,7 @@ export class ActionsController extends BaseHttpController {
) )
} }
@httpPost('/logout', TYPES.OptionalCrossServiceTokenMiddleware) @httpPost('/logout', TYPES.ApiGateway_OptionalCrossServiceTokenMiddleware)
async logout(request: Request, response: Response): Promise<void> { async logout(request: Request, response: Response): Promise<void> {
await this.serviceProxy.callAuthServer( await this.serviceProxy.callAuthServer(
request, request,
@@ -54,7 +54,7 @@ export class ActionsController extends BaseHttpController {
) )
} }
@httpPost('/recovery/codes', TYPES.RequiredCrossServiceTokenMiddleware) @httpPost('/recovery/codes', TYPES.ApiGateway_RequiredCrossServiceTokenMiddleware)
async recoveryCodes(request: Request, response: Response): Promise<void> { async recoveryCodes(request: Request, response: Response): Promise<void> {
await this.serviceProxy.callAuthServer( await this.serviceProxy.callAuthServer(
request, request,
@@ -9,13 +9,13 @@ import { EndpointResolverInterface } from '../../Service/Resolver/EndpointResolv
@controller('/v1/authenticators') @controller('/v1/authenticators')
export class AuthenticatorsController extends BaseHttpController { export class AuthenticatorsController extends BaseHttpController {
constructor( constructor(
@inject(TYPES.ServiceProxy) private httpService: ServiceProxyInterface, @inject(TYPES.ApiGateway_ServiceProxy) private httpService: ServiceProxyInterface,
@inject(TYPES.EndpointResolver) private endpointResolver: EndpointResolverInterface, @inject(TYPES.ApiGateway_EndpointResolver) private endpointResolver: EndpointResolverInterface,
) { ) {
super() super()
} }
@httpDelete('/:authenticatorId', TYPES.RequiredCrossServiceTokenMiddleware) @httpDelete('/:authenticatorId', TYPES.ApiGateway_RequiredCrossServiceTokenMiddleware)
async delete(request: Request, response: Response): Promise<void> { async delete(request: Request, response: Response): Promise<void> {
await this.httpService.callAuthServer( await this.httpService.callAuthServer(
request, request,
@@ -29,7 +29,7 @@ export class AuthenticatorsController extends BaseHttpController {
) )
} }
@httpGet('/', TYPES.RequiredCrossServiceTokenMiddleware) @httpGet('/', TYPES.ApiGateway_RequiredCrossServiceTokenMiddleware)
async list(request: Request, response: Response): Promise<void> { async list(request: Request, response: Response): Promise<void> {
await this.httpService.callAuthServer( await this.httpService.callAuthServer(
request, request,
@@ -39,7 +39,7 @@ export class AuthenticatorsController extends BaseHttpController {
) )
} }
@httpGet('/generate-registration-options', TYPES.RequiredCrossServiceTokenMiddleware) @httpGet('/generate-registration-options', TYPES.ApiGateway_RequiredCrossServiceTokenMiddleware)
async generateRegistrationOptions(request: Request, response: Response): Promise<void> { async generateRegistrationOptions(request: Request, response: Response): Promise<void> {
await this.httpService.callAuthServer( await this.httpService.callAuthServer(
request, request,
@@ -59,7 +59,7 @@ export class AuthenticatorsController extends BaseHttpController {
) )
} }
@httpPost('/verify-registration', TYPES.RequiredCrossServiceTokenMiddleware) @httpPost('/verify-registration', TYPES.ApiGateway_RequiredCrossServiceTokenMiddleware)
async verifyRegistration(request: Request, response: Response): Promise<void> { async verifyRegistration(request: Request, response: Response): Promise<void> {
await this.httpService.callAuthServer( await this.httpService.callAuthServer(
request, request,
@@ -9,13 +9,13 @@ import { EndpointResolverInterface } from '../../Service/Resolver/EndpointResolv
@controller('/v1/files') @controller('/v1/files')
export class FilesController extends BaseHttpController { export class FilesController extends BaseHttpController {
constructor( constructor(
@inject(TYPES.ServiceProxy) private httpService: ServiceProxyInterface, @inject(TYPES.ApiGateway_ServiceProxy) private httpService: ServiceProxyInterface,
@inject(TYPES.EndpointResolver) private endpointResolver: EndpointResolverInterface, @inject(TYPES.ApiGateway_EndpointResolver) private endpointResolver: EndpointResolverInterface,
) { ) {
super() super()
} }
@httpPost('/valet-tokens', TYPES.RequiredCrossServiceTokenMiddleware) @httpPost('/valet-tokens', TYPES.ApiGateway_RequiredCrossServiceTokenMiddleware)
async createToken(request: Request, response: Response): Promise<void> { async createToken(request: Request, response: Response): Promise<void> {
await this.httpService.callAuthServer( await this.httpService.callAuthServer(
request, request,
@@ -6,11 +6,11 @@ import { ServiceProxyInterface } from '../../Service/Http/ServiceProxyInterface'
@controller('/v1') @controller('/v1')
export class InvoicesController extends BaseHttpController { export class InvoicesController extends BaseHttpController {
constructor(@inject(TYPES.ServiceProxy) private httpService: ServiceProxyInterface) { constructor(@inject(TYPES.ApiGateway_ServiceProxy) private httpService: ServiceProxyInterface) {
super() super()
} }
@httpPost('/invoices/send-latest', TYPES.SubscriptionTokenAuthMiddleware) @httpPost('/invoices/send-latest', TYPES.ApiGateway_SubscriptionTokenAuthMiddleware)
async sendLatestInvoice(request: Request, response: Response): Promise<void> { async sendLatestInvoice(request: Request, response: Response): Promise<void> {
await this.httpService.callPaymentsServer(request, response, 'api/pro_users/send-invoice', request.body) await this.httpService.callPaymentsServer(request, response, 'api/pro_users/send-invoice', request.body)
} }
@@ -5,11 +5,11 @@ import { TYPES } from '../../Bootstrap/Types'
import { ServiceProxyInterface } from '../../Service/Http/ServiceProxyInterface' import { ServiceProxyInterface } from '../../Service/Http/ServiceProxyInterface'
import { EndpointResolverInterface } from '../../Service/Resolver/EndpointResolverInterface' import { EndpointResolverInterface } from '../../Service/Resolver/EndpointResolverInterface'
@controller('/v1/items', TYPES.RequiredCrossServiceTokenMiddleware) @controller('/v1/items', TYPES.ApiGateway_RequiredCrossServiceTokenMiddleware)
export class ItemsController extends BaseHttpController { export class ItemsController extends BaseHttpController {
constructor( constructor(
@inject(TYPES.ServiceProxy) private serviceProxy: ServiceProxyInterface, @inject(TYPES.ApiGateway_ServiceProxy) private serviceProxy: ServiceProxyInterface,
@inject(TYPES.EndpointResolver) private endpointResolver: EndpointResolverInterface, @inject(TYPES.ApiGateway_EndpointResolver) private endpointResolver: EndpointResolverInterface,
) { ) {
super() super()
} }
@@ -5,11 +5,11 @@ import { TYPES } from '../../Bootstrap/Types'
import { ServiceProxyInterface } from '../../Service/Http/ServiceProxyInterface' import { ServiceProxyInterface } from '../../Service/Http/ServiceProxyInterface'
import { EndpointResolverInterface } from '../../Service/Resolver/EndpointResolverInterface' import { EndpointResolverInterface } from '../../Service/Resolver/EndpointResolverInterface'
@controller('/v1/messages', TYPES.RequiredCrossServiceTokenMiddleware) @controller('/v1/messages', TYPES.ApiGateway_RequiredCrossServiceTokenMiddleware)
export class MessagesController extends BaseHttpController { export class MessagesController extends BaseHttpController {
constructor( constructor(
@inject(TYPES.ServiceProxy) private httpService: ServiceProxyInterface, @inject(TYPES.ApiGateway_ServiceProxy) private httpService: ServiceProxyInterface,
@inject(TYPES.EndpointResolver) private endpointResolver: EndpointResolverInterface, @inject(TYPES.ApiGateway_EndpointResolver) private endpointResolver: EndpointResolverInterface,
) { ) {
super() super()
} }
@@ -9,8 +9,8 @@ import { EndpointResolverInterface } from '../../Service/Resolver/EndpointResolv
@controller('/v1/offline') @controller('/v1/offline')
export class OfflineController extends BaseHttpController { export class OfflineController extends BaseHttpController {
constructor( constructor(
@inject(TYPES.ServiceProxy) private httpService: ServiceProxyInterface, @inject(TYPES.ApiGateway_ServiceProxy) private httpService: ServiceProxyInterface,
@inject(TYPES.EndpointResolver) private endpointResolver: EndpointResolverInterface, @inject(TYPES.ApiGateway_EndpointResolver) private endpointResolver: EndpointResolverInterface,
) { ) {
super() super()
} }
@@ -6,7 +6,7 @@ import { ServiceProxyInterface } from '../../Service/Http/ServiceProxyInterface'
@controller('/v1') @controller('/v1')
export class PaymentsController extends BaseHttpController { export class PaymentsController extends BaseHttpController {
constructor(@inject(TYPES.ServiceProxy) private httpService: ServiceProxyInterface) { constructor(@inject(TYPES.ApiGateway_ServiceProxy) private httpService: ServiceProxyInterface) {
super() super()
} }
@@ -40,12 +40,12 @@ export class PaymentsController extends BaseHttpController {
await this.httpService.callPaymentsServer(request, response, 'api/extensions', request.body) await this.httpService.callPaymentsServer(request, response, 'api/extensions', request.body)
} }
@httpPost('/subscriptions/tiered', TYPES.SubscriptionTokenAuthMiddleware) @httpPost('/subscriptions/tiered', TYPES.ApiGateway_SubscriptionTokenAuthMiddleware)
async createTieredSubscription(request: Request, response: Response): Promise<void> { async createTieredSubscription(request: Request, response: Response): Promise<void> {
await this.httpService.callPaymentsServer(request, response, 'api/subscriptions/tiered', request.body) await this.httpService.callPaymentsServer(request, response, 'api/subscriptions/tiered', request.body)
} }
@httpPost('/subscriptions/apple_iap_confirm', TYPES.SubscriptionTokenAuthMiddleware) @httpPost('/subscriptions/apple_iap_confirm', TYPES.ApiGateway_SubscriptionTokenAuthMiddleware)
async appleIAPConfirm(request: Request, response: Response): Promise<void> { async appleIAPConfirm(request: Request, response: Response): Promise<void> {
await this.httpService.callPaymentsServer(request, response, 'api/subscriptions/apple_iap_confirm', request.body) await this.httpService.callPaymentsServer(request, response, 'api/subscriptions/apple_iap_confirm', request.body)
} }
@@ -140,7 +140,7 @@ export class PaymentsController extends BaseHttpController {
) )
} }
@httpPost('/payments/stripe-setup-intent', TYPES.SubscriptionTokenAuthMiddleware) @httpPost('/payments/stripe-setup-intent', TYPES.ApiGateway_SubscriptionTokenAuthMiddleware)
async createStripeSetupIntent(request: Request, response: Response): Promise<void> { async createStripeSetupIntent(request: Request, response: Response): Promise<void> {
await this.httpService.callPaymentsServer(request, response, 'api/pro_users/stripe-setup-intent', request.body) await this.httpService.callPaymentsServer(request, response, 'api/pro_users/stripe-setup-intent', request.body)
} }
@@ -1,7 +1,7 @@
import { BaseHttpController, controller, httpDelete, httpGet, results } from 'inversify-express-utils' import { BaseHttpController, controller, httpDelete, httpGet, results } from 'inversify-express-utils'
import { TYPES } from '../../Bootstrap/Types' import { TYPES } from '../../Bootstrap/Types'
@controller('/v1/items/:item_id/revisions', TYPES.RequiredCrossServiceTokenMiddleware) @controller('/v1/items/:item_id/revisions', TYPES.ApiGateway_RequiredCrossServiceTokenMiddleware)
export class RevisionsController extends BaseHttpController { export class RevisionsController extends BaseHttpController {
@httpGet('/') @httpGet('/')
async getRevisions(): Promise<results.JsonResult> { async getRevisions(): Promise<results.JsonResult> {
@@ -8,13 +8,13 @@ import { EndpointResolverInterface } from '../../Service/Resolver/EndpointResolv
@controller('/v1/sessions') @controller('/v1/sessions')
export class SessionsController extends BaseHttpController { export class SessionsController extends BaseHttpController {
constructor( constructor(
@inject(TYPES.ServiceProxy) private httpService: ServiceProxyInterface, @inject(TYPES.ApiGateway_ServiceProxy) private httpService: ServiceProxyInterface,
@inject(TYPES.EndpointResolver) private endpointResolver: EndpointResolverInterface, @inject(TYPES.ApiGateway_EndpointResolver) private endpointResolver: EndpointResolverInterface,
) { ) {
super() super()
} }
@httpGet('/', TYPES.RequiredCrossServiceTokenMiddleware) @httpGet('/', TYPES.ApiGateway_RequiredCrossServiceTokenMiddleware)
async getSessions(request: Request, response: Response): Promise<void> { async getSessions(request: Request, response: Response): Promise<void> {
await this.httpService.callAuthServer( await this.httpService.callAuthServer(
request, request,
@@ -23,7 +23,7 @@ export class SessionsController extends BaseHttpController {
) )
} }
@httpDelete('/:uuid', TYPES.RequiredCrossServiceTokenMiddleware) @httpDelete('/:uuid', TYPES.ApiGateway_RequiredCrossServiceTokenMiddleware)
async deleteSession(request: Request, response: Response): Promise<void> { async deleteSession(request: Request, response: Response): Promise<void> {
await this.httpService.callAuthServer( await this.httpService.callAuthServer(
request, request,
@@ -35,7 +35,7 @@ export class SessionsController extends BaseHttpController {
) )
} }
@httpDelete('/', TYPES.RequiredCrossServiceTokenMiddleware) @httpDelete('/', TYPES.ApiGateway_RequiredCrossServiceTokenMiddleware)
async deleteSessions(request: Request, response: Response): Promise<void> { async deleteSessions(request: Request, response: Response): Promise<void> {
await this.httpService.callAuthServer( await this.httpService.callAuthServer(
request, request,
@@ -5,11 +5,11 @@ import { TYPES } from '../../Bootstrap/Types'
import { ServiceProxyInterface } from '../../Service/Http/ServiceProxyInterface' import { ServiceProxyInterface } from '../../Service/Http/ServiceProxyInterface'
import { EndpointResolverInterface } from '../../Service/Resolver/EndpointResolverInterface' import { EndpointResolverInterface } from '../../Service/Resolver/EndpointResolverInterface'
@controller('/v1/shared-vaults', TYPES.RequiredCrossServiceTokenMiddleware) @controller('/v1/shared-vaults', TYPES.ApiGateway_RequiredCrossServiceTokenMiddleware)
export class SharedVaultInvitesController extends BaseHttpController { export class SharedVaultInvitesController extends BaseHttpController {
constructor( constructor(
@inject(TYPES.ServiceProxy) private httpService: ServiceProxyInterface, @inject(TYPES.ApiGateway_ServiceProxy) private httpService: ServiceProxyInterface,
@inject(TYPES.EndpointResolver) private endpointResolver: EndpointResolverInterface, @inject(TYPES.ApiGateway_EndpointResolver) private endpointResolver: EndpointResolverInterface,
) { ) {
super() super()
} }
@@ -83,6 +83,16 @@ export class SharedVaultInvitesController extends BaseHttpController {
) )
} }
@httpDelete('/invites/outbound')
async deleteOutboundUserInvites(request: Request, response: Response): Promise<void> {
await this.httpService.callSyncingServer(
request,
response,
this.endpointResolver.resolveEndpointOrMethodIdentifier('DELETE', 'shared-vaults/invites/outbound'),
request.body,
)
}
@httpGet('/invites/outbound') @httpGet('/invites/outbound')
async getOutboundUserInvites(request: Request, response: Response): Promise<void> { async getOutboundUserInvites(request: Request, response: Response): Promise<void> {
await this.httpService.callSyncingServer( await this.httpService.callSyncingServer(
@@ -5,11 +5,11 @@ import { TYPES } from '../../Bootstrap/Types'
import { ServiceProxyInterface } from '../../Service/Http/ServiceProxyInterface' import { ServiceProxyInterface } from '../../Service/Http/ServiceProxyInterface'
import { EndpointResolverInterface } from '../../Service/Resolver/EndpointResolverInterface' import { EndpointResolverInterface } from '../../Service/Resolver/EndpointResolverInterface'
@controller('/v1/shared-vaults/:sharedVaultUuid/users', TYPES.RequiredCrossServiceTokenMiddleware) @controller('/v1/shared-vaults/:sharedVaultUuid/users', TYPES.ApiGateway_RequiredCrossServiceTokenMiddleware)
export class SharedVaultUsersController extends BaseHttpController { export class SharedVaultUsersController extends BaseHttpController {
constructor( constructor(
@inject(TYPES.ServiceProxy) private httpService: ServiceProxyInterface, @inject(TYPES.ApiGateway_ServiceProxy) private httpService: ServiceProxyInterface,
@inject(TYPES.EndpointResolver) private endpointResolver: EndpointResolverInterface, @inject(TYPES.ApiGateway_EndpointResolver) private endpointResolver: EndpointResolverInterface,
) { ) {
super() super()
} }
@@ -5,11 +5,11 @@ import { TYPES } from '../../Bootstrap/Types'
import { ServiceProxyInterface } from '../../Service/Http/ServiceProxyInterface' import { ServiceProxyInterface } from '../../Service/Http/ServiceProxyInterface'
import { EndpointResolverInterface } from '../../Service/Resolver/EndpointResolverInterface' import { EndpointResolverInterface } from '../../Service/Resolver/EndpointResolverInterface'
@controller('/v1/shared-vaults', TYPES.RequiredCrossServiceTokenMiddleware) @controller('/v1/shared-vaults', TYPES.ApiGateway_RequiredCrossServiceTokenMiddleware)
export class SharedVaultsController extends BaseHttpController { export class SharedVaultsController extends BaseHttpController {
constructor( constructor(
@inject(TYPES.ServiceProxy) private httpService: ServiceProxyInterface, @inject(TYPES.ApiGateway_ServiceProxy) private httpService: ServiceProxyInterface,
@inject(TYPES.EndpointResolver) private endpointResolver: EndpointResolverInterface, @inject(TYPES.ApiGateway_EndpointResolver) private endpointResolver: EndpointResolverInterface,
) { ) {
super() super()
} }
@@ -9,13 +9,13 @@ import { EndpointResolverInterface } from '../../Service/Resolver/EndpointResolv
@controller('/v1/subscription-invites') @controller('/v1/subscription-invites')
export class SubscriptionInvitesController extends BaseHttpController { export class SubscriptionInvitesController extends BaseHttpController {
constructor( constructor(
@inject(TYPES.ServiceProxy) private httpService: ServiceProxyInterface, @inject(TYPES.ApiGateway_ServiceProxy) private httpService: ServiceProxyInterface,
@inject(TYPES.EndpointResolver) private endpointResolver: EndpointResolverInterface, @inject(TYPES.ApiGateway_EndpointResolver) private endpointResolver: EndpointResolverInterface,
) { ) {
super() super()
} }
@httpPost('/', TYPES.RequiredCrossServiceTokenMiddleware) @httpPost('/', TYPES.ApiGateway_RequiredCrossServiceTokenMiddleware)
async inviteToSubscriptionSharing(request: Request, response: Response): Promise<void> { async inviteToSubscriptionSharing(request: Request, response: Response): Promise<void> {
await this.httpService.callAuthServer( await this.httpService.callAuthServer(
request, request,
@@ -25,7 +25,7 @@ export class SubscriptionInvitesController extends BaseHttpController {
) )
} }
@httpGet('/', TYPES.RequiredCrossServiceTokenMiddleware) @httpGet('/', TYPES.ApiGateway_RequiredCrossServiceTokenMiddleware)
async listInvites(request: Request, response: Response): Promise<void> { async listInvites(request: Request, response: Response): Promise<void> {
await this.httpService.callAuthServer( await this.httpService.callAuthServer(
request, request,
@@ -35,7 +35,7 @@ export class SubscriptionInvitesController extends BaseHttpController {
) )
} }
@httpDelete('/:inviteUuid', TYPES.RequiredCrossServiceTokenMiddleware) @httpDelete('/:inviteUuid', TYPES.ApiGateway_RequiredCrossServiceTokenMiddleware)
async cancelSubscriptionSharing(request: Request, response: Response): Promise<void> { async cancelSubscriptionSharing(request: Request, response: Response): Promise<void> {
await this.httpService.callAuthServer( await this.httpService.callAuthServer(
request, request,
@@ -48,7 +48,7 @@ export class SubscriptionInvitesController extends BaseHttpController {
) )
} }
@httpPost('/:inviteUuid/accept', TYPES.RequiredCrossServiceTokenMiddleware) @httpPost('/:inviteUuid/accept', TYPES.ApiGateway_RequiredCrossServiceTokenMiddleware)
async acceptInvite(request: Request, response: Response): Promise<void> { async acceptInvite(request: Request, response: Response): Promise<void> {
await this.httpService.callAuthServer( await this.httpService.callAuthServer(
request, request,
@@ -9,13 +9,13 @@ import { EndpointResolverInterface } from '../../Service/Resolver/EndpointResolv
@controller('/v1/subscription-tokens') @controller('/v1/subscription-tokens')
export class TokensController extends BaseHttpController { export class TokensController extends BaseHttpController {
constructor( constructor(
@inject(TYPES.ServiceProxy) private httpService: ServiceProxyInterface, @inject(TYPES.ApiGateway_ServiceProxy) private httpService: ServiceProxyInterface,
@inject(TYPES.EndpointResolver) private endpointResolver: EndpointResolverInterface, @inject(TYPES.ApiGateway_EndpointResolver) private endpointResolver: EndpointResolverInterface,
) { ) {
super() super()
} }
@httpPost('/', TYPES.RequiredCrossServiceTokenMiddleware) @httpPost('/', TYPES.ApiGateway_RequiredCrossServiceTokenMiddleware)
async createToken(request: Request, response: Response): Promise<void> { async createToken(request: Request, response: Response): Promise<void> {
await this.httpService.callAuthServer( await this.httpService.callAuthServer(
request, request,
@@ -20,9 +20,10 @@ import { EndpointResolverInterface } from '../../Service/Resolver/EndpointResolv
@controller('/v1/users') @controller('/v1/users')
export class UsersController extends BaseHttpController { export class UsersController extends BaseHttpController {
constructor( constructor(
@inject(TYPES.ServiceProxy) private httpService: ServiceProxyInterface, @inject(TYPES.ApiGateway_ServiceProxy) private httpService: ServiceProxyInterface,
@inject(TYPES.EndpointResolver) private endpointResolver: EndpointResolverInterface, @inject(TYPES.ApiGateway_EndpointResolver) private endpointResolver: EndpointResolverInterface,
@inject(TYPES.Logger) private logger: Logger, @inject(TYPES.ApiGateway_Logger) private logger: Logger,
@inject(TYPES.ApiGateway_IS_CONFIGURED_FOR_HOME_SERVER) private isConfiguredForHomeServer: boolean,
) { ) {
super() super()
} }
@@ -32,12 +33,12 @@ export class UsersController extends BaseHttpController {
await this.httpService.callPaymentsServer(request, response, 'api/pro_users/claim-account', request.body) await this.httpService.callPaymentsServer(request, response, 'api/pro_users/claim-account', request.body)
} }
@httpPost('/send-activation-code', TYPES.SubscriptionTokenAuthMiddleware) @httpPost('/send-activation-code', TYPES.ApiGateway_SubscriptionTokenAuthMiddleware)
async sendActivationCode(request: Request, response: Response): Promise<void> { async sendActivationCode(request: Request, response: Response): Promise<void> {
await this.httpService.callPaymentsServer(request, response, 'api/pro_users/send-activation-code', request.body) await this.httpService.callPaymentsServer(request, response, 'api/pro_users/send-activation-code', request.body)
} }
@httpPatch('/:userId', TYPES.RequiredCrossServiceTokenMiddleware) @httpPatch('/:userId', TYPES.ApiGateway_RequiredCrossServiceTokenMiddleware)
async updateUser(request: Request, response: Response): Promise<void> { async updateUser(request: Request, response: Response): Promise<void> {
await this.httpService.callAuthServer( await this.httpService.callAuthServer(
request, request,
@@ -47,7 +48,7 @@ export class UsersController extends BaseHttpController {
) )
} }
@httpPut('/:userUuid/password', TYPES.RequiredCrossServiceTokenMiddleware) @httpPut('/:userUuid/password', TYPES.ApiGateway_RequiredCrossServiceTokenMiddleware)
async changePassword(request: Request, response: Response): Promise<void> { async changePassword(request: Request, response: Response): Promise<void> {
this.logger.debug( this.logger.debug(
'[DEPRECATED] use endpoint /v1/users/:userUuid/attributes/credentials instead of /v1/users/:userUuid/password', '[DEPRECATED] use endpoint /v1/users/:userUuid/attributes/credentials instead of /v1/users/:userUuid/password',
@@ -65,7 +66,7 @@ export class UsersController extends BaseHttpController {
) )
} }
@httpPut('/:userUuid/attributes/credentials', TYPES.RequiredCrossServiceTokenMiddleware) @httpPut('/:userUuid/attributes/credentials', TYPES.ApiGateway_RequiredCrossServiceTokenMiddleware)
async changeCredentials(request: Request, response: Response): Promise<void> { async changeCredentials(request: Request, response: Response): Promise<void> {
await this.httpService.callAuthServer( await this.httpService.callAuthServer(
request, request,
@@ -79,7 +80,7 @@ export class UsersController extends BaseHttpController {
) )
} }
@httpGet('/:userId/params', TYPES.RequiredCrossServiceTokenMiddleware) @httpGet('/:userId/params', TYPES.ApiGateway_RequiredCrossServiceTokenMiddleware)
async getKeyParams(request: Request, response: Response): Promise<void> { async getKeyParams(request: Request, response: Response): Promise<void> {
await this.httpService.callAuthServer( await this.httpService.callAuthServer(
request, request,
@@ -88,12 +89,12 @@ export class UsersController extends BaseHttpController {
) )
} }
@all('/:userId/mfa', TYPES.RequiredCrossServiceTokenMiddleware) @all('/:userId/mfa', TYPES.ApiGateway_RequiredCrossServiceTokenMiddleware)
async blockMFA(): Promise<results.StatusCodeResult> { async blockMFA(): Promise<results.StatusCodeResult> {
return this.statusCode(401) return this.statusCode(401)
} }
@httpPost('/:userUuid/integrations/listed', TYPES.RequiredCrossServiceTokenMiddleware) @httpPost('/:userUuid/integrations/listed', TYPES.ApiGateway_RequiredCrossServiceTokenMiddleware)
async createListedAccount(request: Request, response: Response): Promise<void> { async createListedAccount(request: Request, response: Response): Promise<void> {
await this.httpService.callAuthServer( await this.httpService.callAuthServer(
request, request,
@@ -113,7 +114,7 @@ export class UsersController extends BaseHttpController {
) )
} }
@httpGet('/:userUuid/settings', TYPES.RequiredCrossServiceTokenMiddleware) @httpGet('/:userUuid/settings', TYPES.ApiGateway_RequiredCrossServiceTokenMiddleware)
async listSettings(request: Request, response: Response): Promise<void> { async listSettings(request: Request, response: Response): Promise<void> {
await this.httpService.callAuthServer( await this.httpService.callAuthServer(
request, request,
@@ -126,7 +127,7 @@ export class UsersController extends BaseHttpController {
) )
} }
@httpPut('/:userUuid/settings', TYPES.RequiredCrossServiceTokenMiddleware) @httpPut('/:userUuid/settings', TYPES.ApiGateway_RequiredCrossServiceTokenMiddleware)
async putSetting(request: Request, response: Response): Promise<void> { async putSetting(request: Request, response: Response): Promise<void> {
await this.httpService.callAuthServer( await this.httpService.callAuthServer(
request, request,
@@ -140,7 +141,7 @@ export class UsersController extends BaseHttpController {
) )
} }
@httpGet('/:userUuid/settings/:settingName', TYPES.RequiredCrossServiceTokenMiddleware) @httpGet('/:userUuid/settings/:settingName', TYPES.ApiGateway_RequiredCrossServiceTokenMiddleware)
async getSetting(request: Request, response: Response): Promise<void> { async getSetting(request: Request, response: Response): Promise<void> {
await this.httpService.callAuthServer( await this.httpService.callAuthServer(
request, request,
@@ -154,7 +155,7 @@ export class UsersController extends BaseHttpController {
) )
} }
@httpDelete('/:userUuid/settings/:settingName', TYPES.RequiredCrossServiceTokenMiddleware) @httpDelete('/:userUuid/settings/:settingName', TYPES.ApiGateway_RequiredCrossServiceTokenMiddleware)
async deleteSetting(request: Request, response: Response): Promise<void> { async deleteSetting(request: Request, response: Response): Promise<void> {
await this.httpService.callAuthServer( await this.httpService.callAuthServer(
request, request,
@@ -169,7 +170,10 @@ export class UsersController extends BaseHttpController {
) )
} }
@httpGet('/:userUuid/subscription-settings/:subscriptionSettingName', TYPES.RequiredCrossServiceTokenMiddleware) @httpGet(
'/:userUuid/subscription-settings/:subscriptionSettingName',
TYPES.ApiGateway_RequiredCrossServiceTokenMiddleware,
)
async getSubscriptionSetting(request: Request, response: Response): Promise<void> { async getSubscriptionSetting(request: Request, response: Response): Promise<void> {
await this.httpService.callAuthServer( await this.httpService.callAuthServer(
request, request,
@@ -183,7 +187,7 @@ export class UsersController extends BaseHttpController {
) )
} }
@httpGet('/:userUuid/features', TYPES.RequiredCrossServiceTokenMiddleware) @httpGet('/:userUuid/features', TYPES.ApiGateway_RequiredCrossServiceTokenMiddleware)
async getFeatures(request: Request, response: Response): Promise<void> { async getFeatures(request: Request, response: Response): Promise<void> {
await this.httpService.callAuthServer( await this.httpService.callAuthServer(
request, request,
@@ -196,7 +200,7 @@ export class UsersController extends BaseHttpController {
) )
} }
@httpGet('/:userUuid/subscription', TYPES.RequiredCrossServiceTokenMiddleware) @httpGet('/:userUuid/subscription', TYPES.ApiGateway_RequiredCrossServiceTokenMiddleware)
async getSubscription(request: Request, response: Response): Promise<void> { async getSubscription(request: Request, response: Response): Promise<void> {
await this.httpService.callAuthServer( await this.httpService.callAuthServer(
request, request,
@@ -209,7 +213,7 @@ export class UsersController extends BaseHttpController {
) )
} }
@httpGet('/subscription', TYPES.SubscriptionTokenAuthMiddleware) @httpGet('/subscription', TYPES.ApiGateway_SubscriptionTokenAuthMiddleware)
async getSubscriptionBySubscriptionToken(request: Request, response: Response): Promise<void> { async getSubscriptionBySubscriptionToken(request: Request, response: Response): Promise<void> {
if (response.locals.tokenAuthenticationMethod === TokenAuthenticationMethod.OfflineSubscriptionToken) { if (response.locals.tokenAuthenticationMethod === TokenAuthenticationMethod.OfflineSubscriptionToken) {
await this.httpService.callAuthServer( await this.httpService.callAuthServer(
@@ -232,12 +236,20 @@ export class UsersController extends BaseHttpController {
) )
} }
@httpDelete('/:userUuid', TYPES.RequiredCrossServiceTokenMiddleware) @httpDelete('/:userUuid', TYPES.ApiGateway_RequiredCrossServiceTokenMiddleware)
async deleteUser(request: Request, response: Response): Promise<void> { async deleteUser(request: Request, response: Response): Promise<void> {
await this.httpService.callPaymentsServer(request, response, 'api/account', request.body) if (!this.isConfiguredForHomeServer) {
await this.httpService.callPaymentsServer(request, response, 'api/account', request.body, true)
}
await this.httpService.callAuthServer(
request,
response,
this.endpointResolver.resolveEndpointOrMethodIdentifier('DELETE', 'users/:userUuid', request.params.userUuid),
)
} }
@httpPost('/:userUuid/requests', TYPES.RequiredCrossServiceTokenMiddleware) @httpPost('/:userUuid/requests', TYPES.ApiGateway_RequiredCrossServiceTokenMiddleware)
async submitRequest(request: Request, response: Response): Promise<void> { async submitRequest(request: Request, response: Response): Promise<void> {
await this.httpService.callAuthServer( await this.httpService.callAuthServer(
request, request,
@@ -10,14 +10,14 @@ import { EndpointResolverInterface } from '../../Service/Resolver/EndpointResolv
@controller('/v1/sockets') @controller('/v1/sockets')
export class WebSocketsController extends BaseHttpController { export class WebSocketsController extends BaseHttpController {
constructor( constructor(
@inject(TYPES.ServiceProxy) private httpService: ServiceProxyInterface, @inject(TYPES.ApiGateway_ServiceProxy) private httpService: ServiceProxyInterface,
@inject(TYPES.EndpointResolver) private endpointResolver: EndpointResolverInterface, @inject(TYPES.ApiGateway_EndpointResolver) private endpointResolver: EndpointResolverInterface,
@inject(TYPES.Logger) private logger: Logger, @inject(TYPES.ApiGateway_Logger) private logger: Logger,
) { ) {
super() super()
} }
@httpPost('/tokens', TYPES.RequiredCrossServiceTokenMiddleware) @httpPost('/tokens', TYPES.ApiGateway_RequiredCrossServiceTokenMiddleware)
async createWebSocketConnectionToken(request: Request, response: Response): Promise<void> { async createWebSocketConnectionToken(request: Request, response: Response): Promise<void> {
await this.httpService.callWebSocketServer( await this.httpService.callWebSocketServer(
request, request,
@@ -27,7 +27,7 @@ export class WebSocketsController extends BaseHttpController {
) )
} }
@httpPost('/connections', TYPES.WebSocketAuthMiddleware) @httpPost('/connections', TYPES.ApiGateway_WebSocketAuthMiddleware)
async createWebSocketConnection(request: Request, response: Response): Promise<void> { async createWebSocketConnection(request: Request, response: Response): Promise<void> {
if (!request.headers.connectionid) { if (!request.headers.connectionid) {
this.logger.error('Could not create a websocket connection. Missing connection id header.') this.logger.error('Could not create a websocket connection. Missing connection id header.')
@@ -9,8 +9,8 @@ import { EndpointResolverInterface } from '../../Service/Resolver/EndpointResolv
@controller('/v2') @controller('/v2')
export class ActionsControllerV2 extends BaseHttpController { export class ActionsControllerV2 extends BaseHttpController {
constructor( constructor(
@inject(TYPES.ServiceProxy) private serviceProxy: ServiceProxyInterface, @inject(TYPES.ApiGateway_ServiceProxy) private serviceProxy: ServiceProxyInterface,
@inject(TYPES.EndpointResolver) private endpointResolver: EndpointResolverInterface, @inject(TYPES.ApiGateway_EndpointResolver) private endpointResolver: EndpointResolverInterface,
) { ) {
super() super()
} }
@@ -25,7 +25,7 @@ export class ActionsControllerV2 extends BaseHttpController {
) )
} }
@httpPost('/login-params', TYPES.OptionalCrossServiceTokenMiddleware) @httpPost('/login-params', TYPES.ApiGateway_OptionalCrossServiceTokenMiddleware)
async loginParams(request: Request, response: Response): Promise<void> { async loginParams(request: Request, response: Response): Promise<void> {
await this.serviceProxy.callAuthServer( await this.serviceProxy.callAuthServer(
request, request,
@@ -6,7 +6,7 @@ import { ServiceProxyInterface } from '../../Service/Http/ServiceProxyInterface'
@controller('/v2') @controller('/v2')
export class PaymentsControllerV2 extends BaseHttpController { export class PaymentsControllerV2 extends BaseHttpController {
constructor(@inject(TYPES.ServiceProxy) private httpService: ServiceProxyInterface) { constructor(@inject(TYPES.ApiGateway_ServiceProxy) private httpService: ServiceProxyInterface) {
super() super()
} }
@@ -15,22 +15,22 @@ export class PaymentsControllerV2 extends BaseHttpController {
await this.httpService.callPaymentsServer(request, response, 'api/subscriptions/features', request.body) await this.httpService.callPaymentsServer(request, response, 'api/subscriptions/features', request.body)
} }
@httpGet('/subscriptions/tailored', TYPES.SubscriptionTokenAuthMiddleware) @httpGet('/subscriptions/tailored', TYPES.ApiGateway_SubscriptionTokenAuthMiddleware)
async getTailoredSubscriptionsWithFeatures(request: Request, response: Response): Promise<void> { async getTailoredSubscriptionsWithFeatures(request: Request, response: Response): Promise<void> {
await this.httpService.callPaymentsServer(request, response, 'api/subscriptions/features', request.body) await this.httpService.callPaymentsServer(request, response, 'api/subscriptions/features', request.body)
} }
@httpGet('/subscriptions/deltas', TYPES.SubscriptionTokenAuthMiddleware) @httpGet('/subscriptions/deltas', TYPES.ApiGateway_SubscriptionTokenAuthMiddleware)
async getSubscriptionDeltasForChangingPlan(request: Request, response: Response): Promise<void> { async getSubscriptionDeltasForChangingPlan(request: Request, response: Response): Promise<void> {
await this.httpService.callPaymentsServer(request, response, 'api/subscriptions/deltas', request.body) await this.httpService.callPaymentsServer(request, response, 'api/subscriptions/deltas', request.body)
} }
@httpPost('/subscriptions/deltas/apply', TYPES.SubscriptionTokenAuthMiddleware) @httpPost('/subscriptions/deltas/apply', TYPES.ApiGateway_SubscriptionTokenAuthMiddleware)
async applySubscriptionDelta(request: Request, response: Response): Promise<void> { async applySubscriptionDelta(request: Request, response: Response): Promise<void> {
await this.httpService.callPaymentsServer(request, response, 'api/subscriptions/deltas/apply', request.body) await this.httpService.callPaymentsServer(request, response, 'api/subscriptions/deltas/apply', request.body)
} }
@httpPost('/subscriptions/change-payment-method', TYPES.SubscriptionTokenAuthMiddleware) @httpPost('/subscriptions/change-payment-method', TYPES.ApiGateway_SubscriptionTokenAuthMiddleware)
async changePaymentMethod(request: Request, response: Response): Promise<void> { async changePaymentMethod(request: Request, response: Response): Promise<void> {
await this.httpService.callPaymentsServer( await this.httpService.callPaymentsServer(
request, request,
@@ -40,7 +40,7 @@ export class PaymentsControllerV2 extends BaseHttpController {
) )
} }
@httpGet('/subscriptions/:subscriptionId', TYPES.SubscriptionTokenAuthMiddleware) @httpGet('/subscriptions/:subscriptionId', TYPES.ApiGateway_SubscriptionTokenAuthMiddleware)
async getSubscription(request: Request, response: Response): Promise<void> { async getSubscription(request: Request, response: Response): Promise<void> {
await this.httpService.callPaymentsServer( await this.httpService.callPaymentsServer(
request, request,
@@ -50,7 +50,7 @@ export class PaymentsControllerV2 extends BaseHttpController {
) )
} }
@httpDelete('/subscriptions/:subscriptionId', TYPES.SubscriptionTokenAuthMiddleware) @httpDelete('/subscriptions/:subscriptionId', TYPES.ApiGateway_SubscriptionTokenAuthMiddleware)
async cancelSubscription(request: Request, response: Response): Promise<void> { async cancelSubscription(request: Request, response: Response): Promise<void> {
await this.httpService.callPaymentsServer( await this.httpService.callPaymentsServer(
request, request,
@@ -60,7 +60,7 @@ export class PaymentsControllerV2 extends BaseHttpController {
) )
} }
@httpPatch('/subscriptions/:subscriptionId', TYPES.SubscriptionTokenAuthMiddleware) @httpPatch('/subscriptions/:subscriptionId', TYPES.ApiGateway_SubscriptionTokenAuthMiddleware)
async updateSubscription(request: Request, response: Response): Promise<void> { async updateSubscription(request: Request, response: Response): Promise<void> {
await this.httpService.callPaymentsServer( await this.httpService.callPaymentsServer(
request, request,
@@ -6,11 +6,11 @@ import { TYPES } from '../../Bootstrap/Types'
import { ServiceProxyInterface } from '../../Service/Http/ServiceProxyInterface' import { ServiceProxyInterface } from '../../Service/Http/ServiceProxyInterface'
import { EndpointResolverInterface } from '../../Service/Resolver/EndpointResolverInterface' import { EndpointResolverInterface } from '../../Service/Resolver/EndpointResolverInterface'
@controller('/v2/items/:itemUuid/revisions', TYPES.RequiredCrossServiceTokenMiddleware) @controller('/v2/items/:itemUuid/revisions', TYPES.ApiGateway_RequiredCrossServiceTokenMiddleware)
export class RevisionsControllerV2 extends BaseHttpController { export class RevisionsControllerV2 extends BaseHttpController {
constructor( constructor(
@inject(TYPES.ServiceProxy) private httpService: ServiceProxyInterface, @inject(TYPES.ApiGateway_ServiceProxy) private httpService: ServiceProxyInterface,
@inject(TYPES.EndpointResolver) private endpointResolver: EndpointResolverInterface, @inject(TYPES.ApiGateway_EndpointResolver) private endpointResolver: EndpointResolverInterface,
) { ) {
super() super()
} }
@@ -9,7 +9,7 @@ export class RedisCrossServiceTokenCache implements CrossServiceTokenCacheInterf
private readonly PREFIX = 'cst' private readonly PREFIX = 'cst'
private readonly USER_CST_PREFIX = 'user-cst' private readonly USER_CST_PREFIX = 'user-cst'
constructor(@inject(TYPES.Redis) private redisClient: IORedis.Redis) {} constructor(@inject(TYPES.ApiGateway_Redis) private redisClient: IORedis.Redis) {}
async set(dto: { async set(dto: {
authorizationHeaderValue: string authorizationHeaderValue: string
@@ -11,17 +11,17 @@ import { ServiceProxyInterface } from './ServiceProxyInterface'
@injectable() @injectable()
export class HttpServiceProxy implements ServiceProxyInterface { export class HttpServiceProxy implements ServiceProxyInterface {
constructor( constructor(
@inject(TYPES.HTTPClient) private httpClient: AxiosInstance, @inject(TYPES.ApiGateway_HTTPClient) private httpClient: AxiosInstance,
@inject(TYPES.AUTH_SERVER_URL) private authServerUrl: string, @inject(TYPES.ApiGateway_AUTH_SERVER_URL) private authServerUrl: string,
@inject(TYPES.SYNCING_SERVER_JS_URL) private syncingServerJsUrl: string, @inject(TYPES.ApiGateway_SYNCING_SERVER_JS_URL) private syncingServerJsUrl: string,
@inject(TYPES.PAYMENTS_SERVER_URL) private paymentsServerUrl: string, @inject(TYPES.ApiGateway_PAYMENTS_SERVER_URL) private paymentsServerUrl: string,
@inject(TYPES.FILES_SERVER_URL) private filesServerUrl: string, @inject(TYPES.ApiGateway_FILES_SERVER_URL) private filesServerUrl: string,
@inject(TYPES.WEB_SOCKET_SERVER_URL) private webSocketServerUrl: string, @inject(TYPES.ApiGateway_WEB_SOCKET_SERVER_URL) private webSocketServerUrl: string,
@inject(TYPES.REVISIONS_SERVER_URL) private revisionsServerUrl: string, @inject(TYPES.ApiGateway_REVISIONS_SERVER_URL) private revisionsServerUrl: string,
@inject(TYPES.EMAIL_SERVER_URL) private emailServerUrl: string, @inject(TYPES.ApiGateway_EMAIL_SERVER_URL) private emailServerUrl: string,
@inject(TYPES.HTTP_CALL_TIMEOUT) private httpCallTimeout: number, @inject(TYPES.ApiGateway_HTTP_CALL_TIMEOUT) private httpCallTimeout: number,
@inject(TYPES.CrossServiceTokenCache) private crossServiceTokenCache: CrossServiceTokenCacheInterface, @inject(TYPES.ApiGateway_CrossServiceTokenCache) private crossServiceTokenCache: CrossServiceTokenCacheInterface,
@inject(TYPES.Logger) private logger: Logger, @inject(TYPES.ApiGateway_Logger) private logger: Logger,
) {} ) {}
async validateSession( async validateSession(
@@ -130,19 +130,26 @@ export class HttpServiceProxy implements ServiceProxyInterface {
response: Response, response: Response,
endpointOrMethodIdentifier: string, endpointOrMethodIdentifier: string,
payload?: Record<string, unknown> | string, payload?: Record<string, unknown> | string,
): Promise<void> { returnRawResponse?: boolean,
): Promise<void | Response<unknown, Record<string, unknown>>> {
if (!this.paymentsServerUrl) { if (!this.paymentsServerUrl) {
this.logger.debug('Payments Server URL not defined. Skipped request to Payments API.') this.logger.debug('Payments Server URL not defined. Skipped request to Payments API.')
return return
} }
await this.callServerWithLegacyFormat(
const rawResponse = await this.callServerWithLegacyFormat(
this.paymentsServerUrl, this.paymentsServerUrl,
request, request,
response, response,
endpointOrMethodIdentifier, endpointOrMethodIdentifier,
payload, payload,
returnRawResponse,
) )
if (returnRawResponse) {
return rawResponse
}
} }
async callAuthServerWithLegacyFormat( async callAuthServerWithLegacyFormat(
@@ -279,7 +286,8 @@ export class HttpServiceProxy implements ServiceProxyInterface {
response: Response, response: Response,
endpointOrMethodIdentifier: string, endpointOrMethodIdentifier: string,
payload?: Record<string, unknown> | string, payload?: Record<string, unknown> | string,
): Promise<void> { returnRawResponse?: boolean,
): Promise<void | Response<unknown, Record<string, unknown>>> {
const serviceResponse = await this.getServerResponse( const serviceResponse = await this.getServerResponse(
serverUrl, serverUrl,
request, request,
@@ -295,9 +303,21 @@ export class HttpServiceProxy implements ServiceProxyInterface {
this.applyResponseHeaders(serviceResponse, response) this.applyResponseHeaders(serviceResponse, response)
if (serviceResponse.request._redirectable._redirectCount > 0) { if (serviceResponse.request._redirectable._redirectCount > 0) {
response.status(302).redirect(serviceResponse.request.res.responseUrl) response.status(302)
if (returnRawResponse) {
return response
}
response.redirect(serviceResponse.request.res.responseUrl)
} else { } else {
response.status(serviceResponse.status).send(serviceResponse.data) response.status(serviceResponse.status)
if (returnRawResponse) {
return response
}
response.send(serviceResponse.data)
} }
} }
@@ -42,7 +42,8 @@ export interface ServiceProxyInterface {
response: Response, response: Response,
endpointOrMethodIdentifier: string, endpointOrMethodIdentifier: string,
payload?: Record<string, unknown> | string, payload?: Record<string, unknown> | string,
): Promise<void> returnRawResponse?: boolean,
): Promise<void | Response<unknown, Record<string, unknown>>>
callWebSocketServer( callWebSocketServer(
request: Request, request: Request,
response: Response, response: Response,
@@ -43,6 +43,7 @@ export class EndpointResolver implements EndpointResolverInterface {
['[PATCH]:users/:userId', 'auth.users.update'], ['[PATCH]:users/:userId', 'auth.users.update'],
['[PUT]:users/:userUuid/attributes/credentials', 'auth.users.updateCredentials'], ['[PUT]:users/:userUuid/attributes/credentials', 'auth.users.updateCredentials'],
['[PUT]:auth/params', 'auth.users.getKeyParams'], ['[PUT]:auth/params', 'auth.users.getKeyParams'],
['[DELETE]:users/:userUuid', 'auth.users.delete'],
['[POST]:listed', 'auth.users.createListedAccount'], ['[POST]:listed', 'auth.users.createListedAccount'],
['[POST]:auth', 'auth.users.register'], ['[POST]:auth', 'auth.users.register'],
['[GET]:users/:userUuid/settings', 'auth.users.getSettings'], ['[GET]:users/:userUuid/settings', 'auth.users.getSettings'],
@@ -79,6 +80,7 @@ export class EndpointResolver implements EndpointResolverInterface {
['[POST]:shared-vaults/:sharedVaultUuid/invites/:inviteUuid/accept', 'sync.shared-vault-invites.accept'], ['[POST]:shared-vaults/:sharedVaultUuid/invites/:inviteUuid/accept', 'sync.shared-vault-invites.accept'],
['[POST]:shared-vaults/:sharedVaultUuid/invites/:inviteUuid/decline', 'sync.shared-vault-invites.decline'], ['[POST]:shared-vaults/:sharedVaultUuid/invites/:inviteUuid/decline', 'sync.shared-vault-invites.decline'],
['[DELETE]:shared-vaults/invites/inbound', 'sync.shared-vault-invites.delete-inbound'], ['[DELETE]:shared-vaults/invites/inbound', 'sync.shared-vault-invites.delete-inbound'],
['[DELETE]:shared-vaults/invites/outbound', 'sync.shared-vault-invites.delete-outbound'],
['[GET]:shared-vaults/invites/outbound', 'sync.shared-vault-invites.get-outbound'], ['[GET]:shared-vaults/invites/outbound', 'sync.shared-vault-invites.get-outbound'],
['[GET]:shared-vaults/invites', 'sync.shared-vault-invites.get-user-invites'], ['[GET]:shared-vaults/invites', 'sync.shared-vault-invites.get-user-invites'],
['[GET]:shared-vaults/:sharedVaultUuid/invites', 'sync.shared-vault-invites.get-vault-invites'], ['[GET]:shared-vaults/:sharedVaultUuid/invites', 'sync.shared-vault-invites.get-vault-invites'],
+36
View File
@@ -3,6 +3,42 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.128.1](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.128.0...@standardnotes/auth-server@1.128.1) (2023-08-02)
**Note:** Version bump only for package @standardnotes/auth-server
# [1.128.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.127.2...@standardnotes/auth-server@1.128.0) (2023-08-02)
### Features
* enable Write Ahead Log mode for SQLite ([#681](https://github.com/standardnotes/server/issues/681)) ([8cd7a13](https://github.com/standardnotes/server/commit/8cd7a138ab56f6a2b0d6c06ef6041ab9b85ae540))
## [1.127.2](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.127.1...@standardnotes/auth-server@1.127.2) (2023-08-01)
### Bug Fixes
* controller naming ([#678](https://github.com/standardnotes/server/issues/678)) ([56f0aef](https://github.com/standardnotes/server/commit/56f0aef21d3fcec7ac7e968cb1c1b071becbbe26))
## [1.127.1](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.127.0...@standardnotes/auth-server@1.127.1) (2023-07-31)
### Bug Fixes
* **auth:** auth middleware on delete account ([318af57](https://github.com/standardnotes/server/commit/318af5757d6c42f580157647b22112a9936765e7))
# [1.127.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.126.5...@standardnotes/auth-server@1.127.0) (2023-07-31)
### Features
* refactor deleting account ([#676](https://github.com/standardnotes/server/issues/676)) ([0d5dcdd](https://github.com/standardnotes/server/commit/0d5dcdd8ec2336e41e7604c4157f79a89163ed29))
## [1.126.5](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.126.4...@standardnotes/auth-server@1.126.5) (2023-07-27)
**Note:** Version bump only for package @standardnotes/auth-server
## [1.126.4](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.126.3...@standardnotes/auth-server@1.126.4) (2023-07-26)
**Note:** Version bump only for package @standardnotes/auth-server
## [1.126.3](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.126.2...@standardnotes/auth-server@1.126.3) (2023-07-26) ## [1.126.3](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.126.2...@standardnotes/auth-server@1.126.3) (2023-07-26)
**Note:** Version bump only for package @standardnotes/auth-server **Note:** Version bump only for package @standardnotes/auth-server
+18 -18
View File
@@ -1,23 +1,23 @@
import 'reflect-metadata' import 'reflect-metadata'
import '../src/Infra/InversifyExpressUtils/InversifyExpressAuthController' import '../src/Infra/InversifyExpressUtils/AnnotatedAuthController'
import '../src/Infra/InversifyExpressUtils/InversifyExpressAuthenticatorsController' import '../src/Infra/InversifyExpressUtils/AnnotatedAuthenticatorsController'
import '../src/Infra/InversifyExpressUtils/InversifyExpressSessionsController' import '../src/Infra/InversifyExpressUtils/AnnotatedSessionsController'
import '../src/Infra/InversifyExpressUtils/InversifyExpressSubscriptionInvitesController' import '../src/Infra/InversifyExpressUtils/AnnotatedSubscriptionInvitesController'
import '../src/Infra/InversifyExpressUtils/InversifyExpressUserRequestsController' import '../src/Infra/InversifyExpressUtils/AnnotatedUserRequestsController'
import '../src/Infra/InversifyExpressUtils/InversifyExpressWebSocketsController' import '../src/Infra/InversifyExpressUtils/AnnotatedWebSocketsController'
import '../src/Infra/InversifyExpressUtils/InversifyExpressUsersController' import '../src/Infra/InversifyExpressUtils/AnnotatedUsersController'
import '../src/Infra/InversifyExpressUtils/InversifyExpressValetTokenController' import '../src/Infra/InversifyExpressUtils/AnnotatedValetTokenController'
import '../src/Infra/InversifyExpressUtils/InversifyExpressAdminController' import '../src/Infra/InversifyExpressUtils/AnnotatedAdminController'
import '../src/Infra/InversifyExpressUtils/InversifyExpressSubscriptionTokensController' import '../src/Infra/InversifyExpressUtils/AnnotatedSubscriptionTokensController'
import '../src/Infra/InversifyExpressUtils/InversifyExpressSubscriptionSettingsController' import '../src/Infra/InversifyExpressUtils/AnnotatedSubscriptionSettingsController'
import '../src/Infra/InversifyExpressUtils/InversifyExpressSettingsController' import '../src/Infra/InversifyExpressUtils/AnnotatedSettingsController'
import '../src/Infra/InversifyExpressUtils/InversifyExpressSessionController' import '../src/Infra/InversifyExpressUtils/AnnotatedSessionController'
import '../src/Infra/InversifyExpressUtils/InversifyExpressOfflineController' import '../src/Infra/InversifyExpressUtils/AnnotatedOfflineController'
import '../src/Infra/InversifyExpressUtils/InversifyExpressListedController' import '../src/Infra/InversifyExpressUtils/AnnotatedListedController'
import '../src/Infra/InversifyExpressUtils/InversifyExpressInternalController' import '../src/Infra/InversifyExpressUtils/AnnotatedInternalController'
import '../src/Infra/InversifyExpressUtils/InversifyExpressHealthCheckController' import '../src/Infra/InversifyExpressUtils/AnnotatedHealthCheckController'
import '../src/Infra/InversifyExpressUtils/InversifyExpressFeaturesController' import '../src/Infra/InversifyExpressUtils/AnnotatedFeaturesController'
import * as cors from 'cors' import * as cors from 'cors'
import { urlencoded, json, Request, Response, NextFunction } from 'express' import { urlencoded, json, Request, Response, NextFunction } from 'express'
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@standardnotes/auth-server", "name": "@standardnotes/auth-server",
"version": "1.126.3", "version": "1.128.1",
"engines": { "engines": {
"node": ">=18.0.0 <21.0.0" "node": ">=18.0.0 <21.0.0"
}, },
+48 -48
View File
@@ -234,22 +234,22 @@ import { OfflineUserAuthMiddleware } from '../Infra/InversifyExpressUtils/Middle
import { LockMiddleware } from '../Infra/InversifyExpressUtils/Middleware/LockMiddleware' import { LockMiddleware } from '../Infra/InversifyExpressUtils/Middleware/LockMiddleware'
import { RequiredCrossServiceTokenMiddleware } from '../Infra/InversifyExpressUtils/Middleware/RequiredCrossServiceTokenMiddleware' import { RequiredCrossServiceTokenMiddleware } from '../Infra/InversifyExpressUtils/Middleware/RequiredCrossServiceTokenMiddleware'
import { OptionalCrossServiceTokenMiddleware } from '../Infra/InversifyExpressUtils/Middleware/OptionalCrossServiceTokenMiddleware' import { OptionalCrossServiceTokenMiddleware } from '../Infra/InversifyExpressUtils/Middleware/OptionalCrossServiceTokenMiddleware'
import { HomeServerSettingsController } from '../Infra/InversifyExpressUtils/HomeServer/HomeServerSettingsController' import { BaseSettingsController } from '../Infra/InversifyExpressUtils/Base/BaseSettingsController'
import { HomeServerAdminController } from '../Infra/InversifyExpressUtils/HomeServer/HomeServerAdminController' import { BaseAdminController } from '../Infra/InversifyExpressUtils/Base/BaseAdminController'
import { HomeServerAuthController } from '../Infra/InversifyExpressUtils/HomeServer/HomeServerAuthController' import { BaseAuthController } from '../Infra/InversifyExpressUtils/Base/BaseAuthController'
import { HomeServerAuthenticatorsController } from '../Infra/InversifyExpressUtils/HomeServer/HomeServerAuthenticatorsController' import { BaseAuthenticatorsController } from '../Infra/InversifyExpressUtils/Base/BaseAuthenticatorsController'
import { HomeServerFeaturesController } from '../Infra/InversifyExpressUtils/HomeServer/HomeServerFeaturesController' import { BaseFeaturesController } from '../Infra/InversifyExpressUtils/Base/BaseFeaturesController'
import { HomeServerListedController } from '../Infra/InversifyExpressUtils/HomeServer/HomeServerListedController' import { BaseListedController } from '../Infra/InversifyExpressUtils/Base/BaseListedController'
import { HomeServerOfflineController } from '../Infra/InversifyExpressUtils/HomeServer/HomeServerOfflineController' import { BaseOfflineController } from '../Infra/InversifyExpressUtils/Base/BaseOfflineController'
import { HomeServerSessionController } from '../Infra/InversifyExpressUtils/HomeServer/HomeServerSessionController' import { BaseSessionController } from '../Infra/InversifyExpressUtils/Base/BaseSessionController'
import { HomeServerSubscriptionInvitesController } from '../Infra/InversifyExpressUtils/HomeServer/HomeServerSubscriptionInvitesController' import { BaseSubscriptionInvitesController } from '../Infra/InversifyExpressUtils/Base/BaseSubscriptionInvitesController'
import { HomeServerSubscriptionSettingsController } from '../Infra/InversifyExpressUtils/HomeServer/HomeServerSubscriptionSettingsController' import { BaseSubscriptionSettingsController } from '../Infra/InversifyExpressUtils/Base/BaseSubscriptionSettingsController'
import { HomeServerSubscriptionTokensController } from '../Infra/InversifyExpressUtils/HomeServer/HomeServerSubscriptionTokensController' import { BaseSubscriptionTokensController } from '../Infra/InversifyExpressUtils/Base/BaseSubscriptionTokensController'
import { HomeServerUserRequestsController } from '../Infra/InversifyExpressUtils/HomeServer/HomeServerUserRequestsController' import { BaseUserRequestsController } from '../Infra/InversifyExpressUtils/Base/BaseUserRequestsController'
import { HomeServerUsersController } from '../Infra/InversifyExpressUtils/HomeServer/HomeServerUsersController' import { BaseUsersController } from '../Infra/InversifyExpressUtils/Base/BaseUsersController'
import { HomeServerValetTokenController } from '../Infra/InversifyExpressUtils/HomeServer/HomeServerValetTokenController' import { BaseValetTokenController } from '../Infra/InversifyExpressUtils/Base/BaseValetTokenController'
import { HomeServerWebSocketsController } from '../Infra/InversifyExpressUtils/HomeServer/HomeServerWebSocketsController' import { BaseWebSocketsController } from '../Infra/InversifyExpressUtils/Base/BaseWebSocketsController'
import { HomeServerSessionsController } from '../Infra/InversifyExpressUtils/HomeServer/HomeServerSessionsController' import { BaseSessionsController } from '../Infra/InversifyExpressUtils/Base/BaseSessionsController'
import { Transform } from 'stream' import { Transform } from 'stream'
import { ActivatePremiumFeatures } from '../Domain/UseCase/ActivatePremiumFeatures/ActivatePremiumFeatures' import { ActivatePremiumFeatures } from '../Domain/UseCase/ActivatePremiumFeatures/ActivatePremiumFeatures'
@@ -1037,9 +1037,9 @@ export class ContainerConfigLoader {
} }
container container
.bind<HomeServerAuthController>(TYPES.Auth_HomeServerAuthController) .bind<BaseAuthController>(TYPES.Auth_BaseAuthController)
.toConstantValue( .toConstantValue(
new HomeServerAuthController( new BaseAuthController(
container.get(TYPES.Auth_VerifyMFA), container.get(TYPES.Auth_VerifyMFA),
container.get(TYPES.Auth_SignIn), container.get(TYPES.Auth_SignIn),
container.get(TYPES.Auth_GetUserKeyParams), container.get(TYPES.Auth_GetUserKeyParams),
@@ -1054,42 +1054,42 @@ export class ContainerConfigLoader {
// Inversify Controllers // Inversify Controllers
if (isConfiguredForHomeServer) { if (isConfiguredForHomeServer) {
container container
.bind<HomeServerAuthenticatorsController>(TYPES.Auth_HomeServerAuthenticatorsController) .bind<BaseAuthenticatorsController>(TYPES.Auth_BaseAuthenticatorsController)
.toConstantValue( .toConstantValue(
new HomeServerAuthenticatorsController( new BaseAuthenticatorsController(
container.get(TYPES.Auth_AuthenticatorsController), container.get(TYPES.Auth_AuthenticatorsController),
container.get(TYPES.Auth_ControllerContainer), container.get(TYPES.Auth_ControllerContainer),
), ),
) )
container container
.bind<HomeServerSubscriptionInvitesController>(TYPES.Auth_HomeServerSubscriptionInvitesController) .bind<BaseSubscriptionInvitesController>(TYPES.Auth_BaseSubscriptionInvitesController)
.toConstantValue( .toConstantValue(
new HomeServerSubscriptionInvitesController( new BaseSubscriptionInvitesController(
container.get(TYPES.Auth_SubscriptionInvitesController), container.get(TYPES.Auth_SubscriptionInvitesController),
container.get(TYPES.Auth_ControllerContainer), container.get(TYPES.Auth_ControllerContainer),
), ),
) )
container container
.bind<HomeServerUserRequestsController>(TYPES.Auth_HomeServerUserRequestsController) .bind<BaseUserRequestsController>(TYPES.Auth_BaseUserRequestsController)
.toConstantValue( .toConstantValue(
new HomeServerUserRequestsController( new BaseUserRequestsController(
container.get(TYPES.Auth_UserRequestsController), container.get(TYPES.Auth_UserRequestsController),
container.get(TYPES.Auth_ControllerContainer), container.get(TYPES.Auth_ControllerContainer),
), ),
) )
container container
.bind<HomeServerWebSocketsController>(TYPES.Auth_HomeServerWebSocketsController) .bind<BaseWebSocketsController>(TYPES.Auth_BaseWebSocketsController)
.toConstantValue( .toConstantValue(
new HomeServerWebSocketsController( new BaseWebSocketsController(
container.get(TYPES.Auth_CreateCrossServiceToken), container.get(TYPES.Auth_CreateCrossServiceToken),
container.get(TYPES.Auth_WebSocketConnectionTokenDecoder), container.get(TYPES.Auth_WebSocketConnectionTokenDecoder),
container.get(TYPES.Auth_ControllerContainer), container.get(TYPES.Auth_ControllerContainer),
), ),
) )
container container
.bind<HomeServerSessionsController>(TYPES.Auth_HomeServerSessionsController) .bind<BaseSessionsController>(TYPES.Auth_BaseSessionsController)
.toConstantValue( .toConstantValue(
new HomeServerSessionsController( new BaseSessionsController(
container.get(TYPES.Auth_GetActiveSessionsForUser), container.get(TYPES.Auth_GetActiveSessionsForUser),
container.get(TYPES.Auth_AuthenticateRequest), container.get(TYPES.Auth_AuthenticateRequest),
container.get(TYPES.Auth_SessionProjector), container.get(TYPES.Auth_SessionProjector),
@@ -1098,17 +1098,17 @@ export class ContainerConfigLoader {
), ),
) )
container container
.bind<HomeServerValetTokenController>(TYPES.Auth_HomeServerValetTokenController) .bind<BaseValetTokenController>(TYPES.Auth_BaseValetTokenController)
.toConstantValue( .toConstantValue(
new HomeServerValetTokenController( new BaseValetTokenController(
container.get(TYPES.Auth_CreateValetToken), container.get(TYPES.Auth_CreateValetToken),
container.get(TYPES.Auth_ControllerContainer), container.get(TYPES.Auth_ControllerContainer),
), ),
) )
container container
.bind<HomeServerUsersController>(TYPES.Auth_HomeServerUsersController) .bind<BaseUsersController>(TYPES.Auth_BaseUsersController)
.toConstantValue( .toConstantValue(
new HomeServerUsersController( new BaseUsersController(
container.get(TYPES.Auth_UpdateUser), container.get(TYPES.Auth_UpdateUser),
container.get(TYPES.Auth_GetUserKeyParams), container.get(TYPES.Auth_GetUserKeyParams),
container.get(TYPES.Auth_DeleteAccount), container.get(TYPES.Auth_DeleteAccount),
@@ -1120,9 +1120,9 @@ export class ContainerConfigLoader {
), ),
) )
container container
.bind<HomeServerAdminController>(TYPES.Auth_HomeServerAdminController) .bind<BaseAdminController>(TYPES.Auth_BaseAdminController)
.toConstantValue( .toConstantValue(
new HomeServerAdminController( new BaseAdminController(
container.get(TYPES.Auth_DeleteSetting), container.get(TYPES.Auth_DeleteSetting),
container.get(TYPES.Auth_UserRepository), container.get(TYPES.Auth_UserRepository),
container.get(TYPES.Auth_CreateSubscriptionToken), container.get(TYPES.Auth_CreateSubscriptionToken),
@@ -1131,9 +1131,9 @@ export class ContainerConfigLoader {
), ),
) )
container container
.bind<HomeServerSubscriptionTokensController>(TYPES.Auth_HomeServerSubscriptionTokensController) .bind<BaseSubscriptionTokensController>(TYPES.Auth_BaseSubscriptionTokensController)
.toConstantValue( .toConstantValue(
new HomeServerSubscriptionTokensController( new BaseSubscriptionTokensController(
container.get(TYPES.Auth_CreateSubscriptionToken), container.get(TYPES.Auth_CreateSubscriptionToken),
container.get(TYPES.Auth_AuthenticateSubscriptionToken), container.get(TYPES.Auth_AuthenticateSubscriptionToken),
container.get(TYPES.Auth_SettingService), container.get(TYPES.Auth_SettingService),
@@ -1145,17 +1145,17 @@ export class ContainerConfigLoader {
), ),
) )
container container
.bind<HomeServerSubscriptionSettingsController>(TYPES.Auth_HomeServerSubscriptionSettingsController) .bind<BaseSubscriptionSettingsController>(TYPES.Auth_BaseSubscriptionSettingsController)
.toConstantValue( .toConstantValue(
new HomeServerSubscriptionSettingsController( new BaseSubscriptionSettingsController(
container.get(TYPES.Auth_GetSetting), container.get(TYPES.Auth_GetSetting),
container.get(TYPES.Auth_ControllerContainer), container.get(TYPES.Auth_ControllerContainer),
), ),
) )
container container
.bind<HomeServerSettingsController>(TYPES.Auth_HomeServerSettingsController) .bind<BaseSettingsController>(TYPES.Auth_BaseSettingsController)
.toConstantValue( .toConstantValue(
new HomeServerSettingsController( new BaseSettingsController(
container.get(TYPES.Auth_GetSettings), container.get(TYPES.Auth_GetSettings),
container.get(TYPES.Auth_GetSetting), container.get(TYPES.Auth_GetSetting),
container.get(TYPES.Auth_UpdateSetting), container.get(TYPES.Auth_UpdateSetting),
@@ -1164,9 +1164,9 @@ export class ContainerConfigLoader {
), ),
) )
container container
.bind<HomeServerSessionController>(TYPES.Auth_HomeServerSessionController) .bind<BaseSessionController>(TYPES.Auth_BaseSessionController)
.toConstantValue( .toConstantValue(
new HomeServerSessionController( new BaseSessionController(
container.get(TYPES.Auth_DeleteSessionForUser), container.get(TYPES.Auth_DeleteSessionForUser),
container.get(TYPES.Auth_DeletePreviousSessionsForUser), container.get(TYPES.Auth_DeletePreviousSessionsForUser),
container.get(TYPES.Auth_RefreshSessionToken), container.get(TYPES.Auth_RefreshSessionToken),
@@ -1174,9 +1174,9 @@ export class ContainerConfigLoader {
), ),
) )
container container
.bind<HomeServerOfflineController>(TYPES.Auth_HomeServerOfflineController) .bind<BaseOfflineController>(TYPES.Auth_BaseOfflineController)
.toConstantValue( .toConstantValue(
new HomeServerOfflineController( new BaseOfflineController(
container.get(TYPES.Auth_GetUserFeatures), container.get(TYPES.Auth_GetUserFeatures),
container.get(TYPES.Auth_GetUserOfflineSubscription), container.get(TYPES.Auth_GetUserOfflineSubscription),
container.get(TYPES.Auth_CreateOfflineSubscriptionToken), container.get(TYPES.Auth_CreateOfflineSubscriptionToken),
@@ -1188,17 +1188,17 @@ export class ContainerConfigLoader {
), ),
) )
container container
.bind<HomeServerListedController>(TYPES.Auth_HomeServerListedController) .bind<BaseListedController>(TYPES.Auth_BaseListedController)
.toConstantValue( .toConstantValue(
new HomeServerListedController( new BaseListedController(
container.get(TYPES.Auth_CreateListedAccount), container.get(TYPES.Auth_CreateListedAccount),
container.get(TYPES.Auth_ControllerContainer), container.get(TYPES.Auth_ControllerContainer),
), ),
) )
container container
.bind<HomeServerFeaturesController>(TYPES.Auth_HomeServerFeaturesController) .bind<BaseFeaturesController>(TYPES.Auth_BaseFeaturesController)
.toConstantValue( .toConstantValue(
new HomeServerFeaturesController( new BaseFeaturesController(
container.get(TYPES.Auth_GetUserFeatures), container.get(TYPES.Auth_GetUserFeatures),
container.get(TYPES.Auth_ControllerContainer), container.get(TYPES.Auth_ControllerContainer),
), ),
@@ -114,6 +114,8 @@ export class AppDataSource {
...commonDataSourceOptions, ...commonDataSourceOptions,
type: 'sqlite', type: 'sqlite',
database: this.env.get('DB_SQLITE_DATABASE_PATH'), database: this.env.get('DB_SQLITE_DATABASE_PATH'),
enableWAL: true,
busyErrorRetry: 2000,
} }
this._dataSource = new DataSource(sqliteDataSourceOptions) this._dataSource = new DataSource(sqliteDataSourceOptions)
+16 -16
View File
@@ -217,22 +217,22 @@ const TYPES = {
Auth_ProtocolVersionSelector: Symbol.for('Auth_ProtocolVersionSelector'), Auth_ProtocolVersionSelector: Symbol.for('Auth_ProtocolVersionSelector'),
Auth_BooleanSelector: Symbol.for('Auth_BooleanSelector'), Auth_BooleanSelector: Symbol.for('Auth_BooleanSelector'),
Auth_UserSubscriptionService: Symbol.for('Auth_UserSubscriptionService'), Auth_UserSubscriptionService: Symbol.for('Auth_UserSubscriptionService'),
Auth_HomeServerAuthController: Symbol.for('Auth_HomeServerAuthController'), Auth_BaseAuthController: Symbol.for('Auth_BaseAuthController'),
Auth_HomeServerAuthenticatorsController: Symbol.for('Auth_HomeServerAuthenticatorsController'), Auth_BaseAuthenticatorsController: Symbol.for('Auth_BaseAuthenticatorsController'),
Auth_HomeServerSubscriptionInvitesController: Symbol.for('Auth_HomeServerSubscriptionInvitesController'), Auth_BaseSubscriptionInvitesController: Symbol.for('Auth_BaseSubscriptionInvitesController'),
Auth_HomeServerUserRequestsController: Symbol.for('Auth_HomeServerUserRequestsController'), Auth_BaseUserRequestsController: Symbol.for('Auth_BaseUserRequestsController'),
Auth_HomeServerWebSocketsController: Symbol.for('Auth_HomeServerWebSocketsController'), Auth_BaseWebSocketsController: Symbol.for('Auth_BaseWebSocketsController'),
Auth_HomeServerSessionsController: Symbol.for('Auth_HomeServerSessionsController'), Auth_BaseSessionsController: Symbol.for('Auth_BaseSessionsController'),
Auth_HomeServerValetTokenController: Symbol.for('Auth_HomeServerValetTokenController'), Auth_BaseValetTokenController: Symbol.for('Auth_BaseValetTokenController'),
Auth_HomeServerUsersController: Symbol.for('Auth_HomeServerUsersController'), Auth_BaseUsersController: Symbol.for('Auth_BaseUsersController'),
Auth_HomeServerAdminController: Symbol.for('Auth_HomeServerAdminController'), Auth_BaseAdminController: Symbol.for('Auth_BaseAdminController'),
Auth_HomeServerSubscriptionTokensController: Symbol.for('Auth_HomeServerSubscriptionTokensController'), Auth_BaseSubscriptionTokensController: Symbol.for('Auth_BaseSubscriptionTokensController'),
Auth_HomeServerSubscriptionSettingsController: Symbol.for('Auth_HomeServerSubscriptionSettingsController'), Auth_BaseSubscriptionSettingsController: Symbol.for('Auth_BaseSubscriptionSettingsController'),
Auth_HomeServerSettingsController: Symbol.for('Auth_HomeServerSettingsController'), Auth_BaseSettingsController: Symbol.for('Auth_BaseSettingsController'),
Auth_HomeServerSessionController: Symbol.for('Auth_HomeServerSessionController'), Auth_BaseSessionController: Symbol.for('Auth_BaseSessionController'),
Auth_HomeServerOfflineController: Symbol.for('Auth_HomeServerOfflineController'), Auth_BaseOfflineController: Symbol.for('Auth_BaseOfflineController'),
Auth_HomeServerListedController: Symbol.for('Auth_HomeServerListedController'), Auth_BaseListedController: Symbol.for('Auth_BaseListedController'),
Auth_HomeServerFeaturesController: Symbol.for('Auth_HomeServerFeaturesController'), Auth_BaseFeaturesController: Symbol.for('Auth_BaseFeaturesController'),
} }
export default TYPES export default TYPES
@@ -30,7 +30,9 @@ describe('AuthenticationMethodResolver', () => {
user = {} as jest.Mocked<User> user = {} as jest.Mocked<User>
session = {} as jest.Mocked<Session> session = {
userUuid: '00000000-0000-0000-0000-000000000000',
} as jest.Mocked<Session>
revokedSession = {} as jest.Mocked<RevokedSession> revokedSession = {} as jest.Mocked<RevokedSession>
@@ -50,17 +52,23 @@ describe('AuthenticationMethodResolver', () => {
}) })
it('should resolve jwt authentication method', async () => { it('should resolve jwt authentication method', async () => {
sessionTokenDecoder.decodeToken = jest.fn().mockReturnValue({ user_uuid: '123' }) sessionTokenDecoder.decodeToken = jest.fn().mockReturnValue({ user_uuid: '00000000-0000-0000-0000-000000000000' })
expect(await createResolver().resolve('test')).toEqual({ expect(await createResolver().resolve('test')).toEqual({
claims: { claims: {
user_uuid: '123', user_uuid: '00000000-0000-0000-0000-000000000000',
}, },
type: 'jwt', type: 'jwt',
user, user,
}) })
}) })
it('should not resolve jwt authentication method with invalid user uuid', async () => {
sessionTokenDecoder.decodeToken = jest.fn().mockReturnValue({ user_uuid: 'invalid' })
expect(await createResolver().resolve('test')).toBeUndefined
})
it('should resolve session authentication method', async () => { it('should resolve session authentication method', async () => {
sessionService.getSessionFromToken = jest.fn().mockReturnValue(session) sessionService.getSessionFromToken = jest.fn().mockReturnValue(session)
@@ -71,6 +79,12 @@ describe('AuthenticationMethodResolver', () => {
}) })
}) })
it('should not resolve session authentication method with invalid user uuid on session', async () => {
sessionService.getSessionFromToken = jest.fn().mockReturnValue({ userUuid: 'invalid' })
expect(await createResolver().resolve('test')).toBeUndefined
})
it('should resolve archvied session authentication method', async () => { it('should resolve archvied session authentication method', async () => {
sessionService.getRevokedSessionFromToken = jest.fn().mockReturnValue(revokedSession) sessionService.getRevokedSessionFromToken = jest.fn().mockReturnValue(revokedSession)
@@ -6,6 +6,7 @@ import { UserRepositoryInterface } from '../User/UserRepositoryInterface'
import { AuthenticationMethod } from './AuthenticationMethod' import { AuthenticationMethod } from './AuthenticationMethod'
import { AuthenticationMethodResolverInterface } from './AuthenticationMethodResolverInterface' import { AuthenticationMethodResolverInterface } from './AuthenticationMethodResolverInterface'
import { Logger } from 'winston' import { Logger } from 'winston'
import { Uuid } from '@standardnotes/domain-core'
@injectable() @injectable()
export class AuthenticationMethodResolver implements AuthenticationMethodResolverInterface { export class AuthenticationMethodResolver implements AuthenticationMethodResolverInterface {
@@ -29,9 +30,15 @@ export class AuthenticationMethodResolver implements AuthenticationMethodResolve
if (decodedToken) { if (decodedToken) {
this.logger.debug('Token decoded successfully. User found.') this.logger.debug('Token decoded successfully. User found.')
const userUuidOrError = Uuid.create(decodedToken.user_uuid as string)
if (userUuidOrError.isFailed()) {
return undefined
}
const userUuid = userUuidOrError.getValue()
return { return {
type: 'jwt', type: 'jwt',
user: await this.userRepository.findOneByUuid(<string>decodedToken.user_uuid), user: await this.userRepository.findOneByUuid(userUuid),
claims: decodedToken, claims: decodedToken,
} }
} }
@@ -40,9 +47,15 @@ export class AuthenticationMethodResolver implements AuthenticationMethodResolve
if (session) { if (session) {
this.logger.debug('Token decoded successfully. Session found.') this.logger.debug('Token decoded successfully. Session found.')
const userUuidOrError = Uuid.create(session.userUuid)
if (userUuidOrError.isFailed()) {
return undefined
}
const userUuid = userUuidOrError.getValue()
return { return {
type: 'session_token', type: 'session_token',
user: await this.userRepository.findOneByUuid(session.userUuid), user: await this.userRepository.findOneByUuid(userUuid),
session: session, session: session,
} }
} }
@@ -50,7 +50,7 @@ describe('AccountDeletionRequestedEventHandler', () => {
ephemeralSession = { ephemeralSession = {
uuid: '2-3-4', uuid: '2-3-4',
userUuid: '1-2-3', userUuid: '00000000-0000-0000-0000-000000000000',
} as jest.Mocked<EphemeralSession> } as jest.Mocked<EphemeralSession>
ephemeralSessionRepository = {} as jest.Mocked<EphemeralSessionRepositoryInterface> ephemeralSessionRepository = {} as jest.Mocked<EphemeralSessionRepositoryInterface>
@@ -68,7 +68,7 @@ describe('AccountDeletionRequestedEventHandler', () => {
event = {} as jest.Mocked<AccountDeletionRequestedEvent> event = {} as jest.Mocked<AccountDeletionRequestedEvent>
event.createdAt = new Date(1) event.createdAt = new Date(1)
event.payload = { event.payload = {
userUuid: '1-2-3', userUuid: '00000000-0000-0000-0000-000000000000',
userCreatedAtTimestamp: 1, userCreatedAtTimestamp: 1,
regularSubscriptionUuid: '2-3-4', regularSubscriptionUuid: '2-3-4',
} }
@@ -84,6 +84,14 @@ describe('AccountDeletionRequestedEventHandler', () => {
expect(userRepository.remove).toHaveBeenCalledWith(user) expect(userRepository.remove).toHaveBeenCalledWith(user)
}) })
it('should not remove a user with invalid uuid', async () => {
event.payload.userUuid = 'invalid'
await createHandler().handle(event)
expect(userRepository.remove).not.toHaveBeenCalled()
})
it('should not remove a user if one does not exist', async () => { it('should not remove a user if one does not exist', async () => {
userRepository.findOneByUuid = jest.fn().mockReturnValue(null) userRepository.findOneByUuid = jest.fn().mockReturnValue(null)
@@ -100,6 +108,6 @@ describe('AccountDeletionRequestedEventHandler', () => {
expect(sessionRepository.remove).toHaveBeenCalledWith(session) expect(sessionRepository.remove).toHaveBeenCalledWith(session)
expect(revokedSessionRepository.remove).toHaveBeenCalledWith(revokedSession) expect(revokedSessionRepository.remove).toHaveBeenCalledWith(revokedSession)
expect(ephemeralSessionRepository.deleteOne).toHaveBeenCalledWith('2-3-4', '1-2-3') expect(ephemeralSessionRepository.deleteOne).toHaveBeenCalledWith('2-3-4', '00000000-0000-0000-0000-000000000000')
}) })
}) })
@@ -6,6 +6,7 @@ import { EphemeralSessionRepositoryInterface } from '../Session/EphemeralSession
import { RevokedSessionRepositoryInterface } from '../Session/RevokedSessionRepositoryInterface' import { RevokedSessionRepositoryInterface } from '../Session/RevokedSessionRepositoryInterface'
import { SessionRepositoryInterface } from '../Session/SessionRepositoryInterface' import { SessionRepositoryInterface } from '../Session/SessionRepositoryInterface'
import { UserRepositoryInterface } from '../User/UserRepositoryInterface' import { UserRepositoryInterface } from '../User/UserRepositoryInterface'
import { Uuid } from '@standardnotes/domain-core'
@injectable() @injectable()
export class AccountDeletionRequestedEventHandler implements DomainEventHandlerInterface { export class AccountDeletionRequestedEventHandler implements DomainEventHandlerInterface {
@@ -19,19 +20,27 @@ export class AccountDeletionRequestedEventHandler implements DomainEventHandlerI
) {} ) {}
async handle(event: AccountDeletionRequestedEvent): Promise<void> { async handle(event: AccountDeletionRequestedEvent): Promise<void> {
const user = await this.userRepository.findOneByUuid(event.payload.userUuid) const userUuidOrError = Uuid.create(event.payload.userUuid)
if (userUuidOrError.isFailed()) {
if (user === null) {
this.logger.warn(`Could not find user with uuid: ${event.payload.userUuid}`) this.logger.warn(`Could not find user with uuid: ${event.payload.userUuid}`)
return return
} }
const userUuid = userUuidOrError.getValue()
await this.removeSessions(event.payload.userUuid) const user = await this.userRepository.findOneByUuid(userUuid)
if (user === null) {
this.logger.warn(`Could not find user with uuid: ${userUuid.value}`)
return
}
await this.removeSessions(userUuid.value)
await this.userRepository.remove(user) await this.userRepository.remove(user)
this.logger.info(`Finished account cleanup for user: ${event.payload.userUuid}`) this.logger.info(`Finished account cleanup for user: ${userUuid.value}`)
} }
private async removeSessions(userUuid: string): Promise<void> { private async removeSessions(userUuid: string): Promise<void> {
@@ -33,7 +33,7 @@ describe('FileUploadedEventHandler', () => {
userRepository.findOneByUuid = jest.fn().mockReturnValue(user) userRepository.findOneByUuid = jest.fn().mockReturnValue(user)
regularSubscription = { regularSubscription = {
uuid: '1-2-3', uuid: '00000000-0000-0000-0000-000000000000',
subscriptionType: UserSubscriptionType.Regular, subscriptionType: UserSubscriptionType.Regular,
user: Promise.resolve(user), user: Promise.resolve(user),
} as jest.Mocked<UserSubscription> } as jest.Mocked<UserSubscription>
@@ -56,9 +56,9 @@ describe('FileUploadedEventHandler', () => {
event = {} as jest.Mocked<FileUploadedEvent> event = {} as jest.Mocked<FileUploadedEvent>
event.createdAt = new Date(1) event.createdAt = new Date(1)
event.payload = { event.payload = {
userUuid: '1-2-3', userUuid: '00000000-0000-0000-0000-000000000000',
fileByteSize: 123, fileByteSize: 123,
filePath: '1-2-3/2-3-4', filePath: '00000000-0000-0000-0000-000000000000/2-3-4',
fileName: '2-3-4', fileName: '2-3-4',
} }
@@ -78,13 +78,21 @@ describe('FileUploadedEventHandler', () => {
}, },
user, user,
userSubscription: { userSubscription: {
uuid: '1-2-3', uuid: '00000000-0000-0000-0000-000000000000',
subscriptionType: 'regular', subscriptionType: 'regular',
user: Promise.resolve(user), user: Promise.resolve(user),
}, },
}) })
}) })
it('should not do anything if a user uuid is invalid', async () => {
event.payload.userUuid = 'invalid'
await createHandler().handle(event)
expect(subscriptionSettingService.createOrReplace).not.toHaveBeenCalled()
})
it('should not do anything if a user is not found', async () => { it('should not do anything if a user is not found', async () => {
userRepository.findOneByUuid = jest.fn().mockReturnValue(null) userRepository.findOneByUuid = jest.fn().mockReturnValue(null)
@@ -121,7 +129,7 @@ describe('FileUploadedEventHandler', () => {
}, },
user, user,
userSubscription: { userSubscription: {
uuid: '1-2-3', uuid: '00000000-0000-0000-0000-000000000000',
subscriptionType: 'regular', subscriptionType: 'regular',
user: Promise.resolve(user), user: Promise.resolve(user),
}, },
@@ -147,7 +155,7 @@ describe('FileUploadedEventHandler', () => {
}, },
user, user,
userSubscription: { userSubscription: {
uuid: '1-2-3', uuid: '00000000-0000-0000-0000-000000000000',
subscriptionType: 'regular', subscriptionType: 'regular',
user: Promise.resolve(user), user: Promise.resolve(user),
}, },
@@ -10,6 +10,7 @@ import { UserSubscription } from '../Subscription/UserSubscription'
import { UserSubscriptionServiceInterface } from '../Subscription/UserSubscriptionServiceInterface' import { UserSubscriptionServiceInterface } from '../Subscription/UserSubscriptionServiceInterface'
import { UserRepositoryInterface } from '../User/UserRepositoryInterface' import { UserRepositoryInterface } from '../User/UserRepositoryInterface'
import { User } from '../User/User' import { User } from '../User/User'
import { Uuid } from '@standardnotes/domain-core'
@injectable() @injectable()
export class FileUploadedEventHandler implements DomainEventHandlerInterface { export class FileUploadedEventHandler implements DomainEventHandlerInterface {
@@ -22,17 +23,25 @@ export class FileUploadedEventHandler implements DomainEventHandlerInterface {
) {} ) {}
async handle(event: FileUploadedEvent): Promise<void> { async handle(event: FileUploadedEvent): Promise<void> {
const user = await this.userRepository.findOneByUuid(event.payload.userUuid) const userUuidOrError = Uuid.create(event.payload.userUuid)
if (userUuidOrError.isFailed()) {
this.logger.warn(userUuidOrError.getError())
return
}
const userUuid = userUuidOrError.getValue()
const user = await this.userRepository.findOneByUuid(userUuid)
if (user === null) { if (user === null) {
this.logger.warn(`Could not find user with uuid: ${event.payload.userUuid}`) this.logger.warn(`Could not find user with uuid: ${userUuid.value}`)
return return
} }
const { regularSubscription, sharedSubscription } = const { regularSubscription, sharedSubscription } =
await this.userSubscriptionService.findRegularSubscriptionForUserUuid(event.payload.userUuid) await this.userSubscriptionService.findRegularSubscriptionForUserUuid(userUuid.value)
if (regularSubscription === null) { if (regularSubscription === null) {
this.logger.warn(`Could not find regular user subscription for user with uuid: ${event.payload.userUuid}`) this.logger.warn(`Could not find regular user subscription for user with uuid: ${userUuid.value}`)
return return
} }
@@ -214,13 +214,25 @@ describe('RoleService', () => {
}) })
it('should indicate if a user has given permission', async () => { it('should indicate if a user has given permission', async () => {
const userHasPermission = await createService().userHasPermission('1-2-3', PermissionName.DailyEmailBackup) const userHasPermission = await createService().userHasPermission(
'00000000-0000-0000-0000-000000000000',
PermissionName.DailyEmailBackup,
)
expect(userHasPermission).toBeTruthy() expect(userHasPermission).toBeTruthy()
}) })
it('should not indiciate if a user has permission if the user uuid is invalid', async () => {
const userHasPermission = await createService().userHasPermission('invalid', PermissionName.DailyEmailBackup)
expect(userHasPermission).toBeFalsy()
})
it('should indicate if a user does not have a given permission', async () => { it('should indicate if a user does not have a given permission', async () => {
const userHasPermission = await createService().userHasPermission('1-2-3', PermissionName.MarkdownProEditor) const userHasPermission = await createService().userHasPermission(
'00000000-0000-0000-0000-000000000000',
PermissionName.MarkdownProEditor,
)
expect(userHasPermission).toBeFalsy() expect(userHasPermission).toBeFalsy()
}) })
@@ -228,7 +240,10 @@ describe('RoleService', () => {
it('should indicate user does not have a permission if user could not be found', async () => { it('should indicate user does not have a permission if user could not be found', async () => {
userRepository.findOneByUuid = jest.fn().mockReturnValue(null) userRepository.findOneByUuid = jest.fn().mockReturnValue(null)
const userHasPermission = await createService().userHasPermission('1-2-3', PermissionName.MarkdownProEditor) const userHasPermission = await createService().userHasPermission(
'00000000-0000-0000-0000-000000000000',
PermissionName.MarkdownProEditor,
)
expect(userHasPermission).toBeFalsy() expect(userHasPermission).toBeFalsy()
}) })
+9 -2
View File
@@ -13,6 +13,7 @@ import { RoleToSubscriptionMapInterface } from './RoleToSubscriptionMapInterface
import { OfflineUserSubscriptionRepositoryInterface } from '../Subscription/OfflineUserSubscriptionRepositoryInterface' import { OfflineUserSubscriptionRepositoryInterface } from '../Subscription/OfflineUserSubscriptionRepositoryInterface'
import { Role } from './Role' import { Role } from './Role'
import { OfflineUserSubscription } from '../Subscription/OfflineUserSubscription' import { OfflineUserSubscription } from '../Subscription/OfflineUserSubscription'
import { Uuid } from '@standardnotes/domain-core'
@injectable() @injectable()
export class RoleService implements RoleServiceInterface { export class RoleService implements RoleServiceInterface {
@@ -26,10 +27,16 @@ export class RoleService implements RoleServiceInterface {
@inject(TYPES.Auth_Logger) private logger: Logger, @inject(TYPES.Auth_Logger) private logger: Logger,
) {} ) {}
async userHasPermission(userUuid: string, permissionName: PermissionName): Promise<boolean> { async userHasPermission(userUuidString: string, permissionName: PermissionName): Promise<boolean> {
const userUuidOrError = Uuid.create(userUuidString)
if (userUuidOrError.isFailed()) {
return false
}
const userUuid = userUuidOrError.getValue()
const user = await this.userRepository.findOneByUuid(userUuid) const user = await this.userRepository.findOneByUuid(userUuid)
if (user === null) { if (user === null) {
this.logger.warn(`Could not find user with uuid ${userUuid} for permissions check`) this.logger.warn(`Could not find user with uuid ${userUuid.value} for permissions check`)
return false return false
} }
@@ -32,7 +32,9 @@ describe('SettingDecrypter', () => {
serverEncryptionVersion: EncryptionVersion.Default, serverEncryptionVersion: EncryptionVersion.Default,
} as jest.Mocked<Setting> } as jest.Mocked<Setting>
expect(await createDecrypter().decryptSettingValue(setting, '1-2-3')).toEqual('decrypted') expect(await createDecrypter().decryptSettingValue(setting, '00000000-0000-0000-0000-000000000000')).toEqual(
'decrypted',
)
}) })
it('should return null if the setting value is null', async () => { it('should return null if the setting value is null', async () => {
@@ -41,7 +43,7 @@ describe('SettingDecrypter', () => {
serverEncryptionVersion: EncryptionVersion.Default, serverEncryptionVersion: EncryptionVersion.Default,
} as jest.Mocked<Setting> } as jest.Mocked<Setting>
expect(await createDecrypter().decryptSettingValue(setting, '1-2-3')).toBeNull() expect(await createDecrypter().decryptSettingValue(setting, '00000000-0000-0000-0000-000000000000')).toBeNull()
}) })
it('should return unencrypted value if the setting value is unencrypted', async () => { it('should return unencrypted value if the setting value is unencrypted', async () => {
@@ -50,7 +52,7 @@ describe('SettingDecrypter', () => {
serverEncryptionVersion: EncryptionVersion.Unencrypted, serverEncryptionVersion: EncryptionVersion.Unencrypted,
} as jest.Mocked<Setting> } as jest.Mocked<Setting>
expect(await createDecrypter().decryptSettingValue(setting, '1-2-3')).toEqual('test') expect(await createDecrypter().decryptSettingValue(setting, '00000000-0000-0000-0000-000000000000')).toEqual('test')
}) })
it('should throw if the user could not be found', async () => { it('should throw if the user could not be found', async () => {
@@ -62,7 +64,23 @@ describe('SettingDecrypter', () => {
let caughtError = null let caughtError = null
try { try {
await createDecrypter().decryptSettingValue(setting, '1-2-3') await createDecrypter().decryptSettingValue(setting, '00000000-0000-0000-0000-000000000000')
} catch (error) {
caughtError = error
}
expect(caughtError).not.toBeNull()
})
it('should throw if the user uuid is invalid', async () => {
const setting = {
value: 'encrypted',
serverEncryptionVersion: EncryptionVersion.Default,
} as jest.Mocked<Setting>
let caughtError = null
try {
await createDecrypter().decryptSettingValue(setting, 'invalid')
} catch (error) { } catch (error) {
caughtError = error caughtError = error
} }
@@ -6,6 +6,7 @@ import { UserRepositoryInterface } from '../User/UserRepositoryInterface'
import { Setting } from './Setting' import { Setting } from './Setting'
import { SettingDecrypterInterface } from './SettingDecrypterInterface' import { SettingDecrypterInterface } from './SettingDecrypterInterface'
import { SubscriptionSetting } from './SubscriptionSetting' import { SubscriptionSetting } from './SubscriptionSetting'
import { Uuid } from '@standardnotes/domain-core'
@injectable() @injectable()
export class SettingDecrypter implements SettingDecrypterInterface { export class SettingDecrypter implements SettingDecrypterInterface {
@@ -14,12 +15,18 @@ export class SettingDecrypter implements SettingDecrypterInterface {
@inject(TYPES.Auth_Crypter) private crypter: CrypterInterface, @inject(TYPES.Auth_Crypter) private crypter: CrypterInterface,
) {} ) {}
async decryptSettingValue(setting: Setting | SubscriptionSetting, userUuid: string): Promise<string | null> { async decryptSettingValue(setting: Setting | SubscriptionSetting, userUuidString: string): Promise<string | null> {
if (setting.value !== null && setting.serverEncryptionVersion === EncryptionVersion.Default) { if (setting.value !== null && setting.serverEncryptionVersion === EncryptionVersion.Default) {
const userUuidOrError = Uuid.create(userUuidString)
if (userUuidOrError.isFailed()) {
throw new Error(userUuidOrError.getError())
}
const userUuid = userUuidOrError.getValue()
const user = await this.userRepository.findOneByUuid(userUuid) const user = await this.userRepository.findOneByUuid(userUuid)
if (user === null) { if (user === null) {
throw new Error(`Could not find user with uuid: ${userUuid}`) throw new Error(`Could not find user with uuid: ${userUuid.value}`)
} }
return this.crypter.decryptForUser(setting.value, user) return this.crypter.decryptForUser(setting.value, user)
@@ -17,7 +17,7 @@ describe('AuthenticateSubscriptionToken', () => {
beforeEach(() => { beforeEach(() => {
subscriptionTokenRepository = {} as jest.Mocked<SubscriptionTokenRepositoryInterface> subscriptionTokenRepository = {} as jest.Mocked<SubscriptionTokenRepositoryInterface>
subscriptionTokenRepository.getUserUuidByToken = jest.fn().mockReturnValue('1-2-3') subscriptionTokenRepository.getUserUuidByToken = jest.fn().mockReturnValue('00000000-0000-0000-0000-000000000000')
user = { user = {
roles: Promise.resolve([{ name: RoleName.NAMES.CoreUser }]), roles: Promise.resolve([{ name: RoleName.NAMES.CoreUser }]),
@@ -30,8 +30,6 @@ describe('AuthenticateSubscriptionToken', () => {
it('should authenticate an subscription token', async () => { it('should authenticate an subscription token', async () => {
const response = await createUseCase().execute({ token: 'test' }) const response = await createUseCase().execute({ token: 'test' })
expect(userRepository.findOneByUuid).toHaveBeenCalledWith('1-2-3')
expect(response.success).toBeTruthy() expect(response.success).toBeTruthy()
expect(response.user).toEqual(user) expect(response.user).toEqual(user)
@@ -6,6 +6,7 @@ import { UserRepositoryInterface } from '../../User/UserRepositoryInterface'
import { UseCaseInterface } from '../UseCaseInterface' import { UseCaseInterface } from '../UseCaseInterface'
import { AuthenticateSubscriptionTokenDTO } from './AuthenticateSubscriptionTokenDTO' import { AuthenticateSubscriptionTokenDTO } from './AuthenticateSubscriptionTokenDTO'
import { AuthenticateSubscriptionTokenResponse } from './AuthenticateSubscriptionTokenResponse' import { AuthenticateSubscriptionTokenResponse } from './AuthenticateSubscriptionTokenResponse'
import { Uuid } from '@standardnotes/domain-core'
@injectable() @injectable()
export class AuthenticateSubscriptionToken implements UseCaseInterface { export class AuthenticateSubscriptionToken implements UseCaseInterface {
@@ -16,12 +17,14 @@ export class AuthenticateSubscriptionToken implements UseCaseInterface {
) {} ) {}
async execute(dto: AuthenticateSubscriptionTokenDTO): Promise<AuthenticateSubscriptionTokenResponse> { async execute(dto: AuthenticateSubscriptionTokenDTO): Promise<AuthenticateSubscriptionTokenResponse> {
const userUuid = await this.subscriptionTokenRepository.getUserUuidByToken(dto.token) const userUuidString = await this.subscriptionTokenRepository.getUserUuidByToken(dto.token)
if (userUuid === undefined) { const userUuidOrError = Uuid.create(userUuidString as string)
if (userUuidOrError.isFailed()) {
return { return {
success: false, success: false,
} }
} }
const userUuid = userUuidOrError.getValue()
const user = await this.userRepository.findOneByUuid(userUuid) const user = await this.userRepository.findOneByUuid(userUuid)
if (user === null) { if (user === null) {
@@ -28,13 +28,15 @@ describe('CreateCrossServiceToken', () => {
session = {} as jest.Mocked<Session> session = {} as jest.Mocked<Session>
user = { user = {
uuid: '1-2-3', uuid: '00000000-0000-0000-0000-000000000000',
email: 'test@test.te', email: 'test@test.te',
} as jest.Mocked<User> } as jest.Mocked<User>
user.roles = Promise.resolve([role]) user.roles = Promise.resolve([role])
userProjector = {} as jest.Mocked<ProjectorInterface<User>> userProjector = {} as jest.Mocked<ProjectorInterface<User>>
userProjector.projectSimple = jest.fn().mockReturnValue({ uuid: '1-2-3', email: 'test@test.te' }) userProjector.projectSimple = jest
.fn()
.mockReturnValue({ uuid: '00000000-0000-0000-0000-000000000000', email: 'test@test.te' })
roleProjector = {} as jest.Mocked<ProjectorInterface<Role>> roleProjector = {} as jest.Mocked<ProjectorInterface<Role>>
roleProjector.projectSimple = jest.fn().mockReturnValue({ name: 'role1', uuid: '1-3-4' }) roleProjector.projectSimple = jest.fn().mockReturnValue({ name: 'role1', uuid: '1-3-4' })
@@ -69,7 +71,7 @@ describe('CreateCrossServiceToken', () => {
}, },
user: { user: {
email: 'test@test.te', email: 'test@test.te',
uuid: '1-2-3', uuid: '00000000-0000-0000-0000-000000000000',
}, },
}, },
60, 60,
@@ -91,7 +93,7 @@ describe('CreateCrossServiceToken', () => {
], ],
user: { user: {
email: 'test@test.te', email: 'test@test.te',
uuid: '1-2-3', uuid: '00000000-0000-0000-0000-000000000000',
}, },
}, },
60, 60,
@@ -100,7 +102,7 @@ describe('CreateCrossServiceToken', () => {
it('should create a cross service token for user by user uuid', async () => { it('should create a cross service token for user by user uuid', async () => {
await createUseCase().execute({ await createUseCase().execute({
userUuid: '1-2-3', userUuid: '00000000-0000-0000-0000-000000000000',
}) })
expect(tokenEncoder.encodeExpirableToken).toHaveBeenCalledWith( expect(tokenEncoder.encodeExpirableToken).toHaveBeenCalledWith(
@@ -113,7 +115,7 @@ describe('CreateCrossServiceToken', () => {
], ],
user: { user: {
email: 'test@test.te', email: 'test@test.te',
uuid: '1-2-3', uuid: '00000000-0000-0000-0000-000000000000',
}, },
}, },
60, 60,
@@ -126,7 +128,20 @@ describe('CreateCrossServiceToken', () => {
let caughtError = null let caughtError = null
try { try {
await createUseCase().execute({ await createUseCase().execute({
userUuid: '1-2-3', userUuid: '00000000-0000-0000-0000-000000000000',
})
} catch (error) {
caughtError = error
}
expect(caughtError).not.toBeNull()
})
it('should throw an error if user uuid is invalid', async () => {
let caughtError = null
try {
await createUseCase().execute({
userUuid: 'invalid',
}) })
} catch (error) { } catch (error) {
caughtError = error caughtError = error
@@ -11,6 +11,7 @@ import { UseCaseInterface } from '../UseCaseInterface'
import { CreateCrossServiceTokenDTO } from './CreateCrossServiceTokenDTO' import { CreateCrossServiceTokenDTO } from './CreateCrossServiceTokenDTO'
import { CreateCrossServiceTokenResponse } from './CreateCrossServiceTokenResponse' import { CreateCrossServiceTokenResponse } from './CreateCrossServiceTokenResponse'
import { Uuid } from '@standardnotes/domain-core'
@injectable() @injectable()
export class CreateCrossServiceToken implements UseCaseInterface { export class CreateCrossServiceToken implements UseCaseInterface {
@@ -26,7 +27,13 @@ export class CreateCrossServiceToken implements UseCaseInterface {
async execute(dto: CreateCrossServiceTokenDTO): Promise<CreateCrossServiceTokenResponse> { async execute(dto: CreateCrossServiceTokenDTO): Promise<CreateCrossServiceTokenResponse> {
let user: User | undefined | null = dto.user let user: User | undefined | null = dto.user
if (user === undefined && dto.userUuid !== undefined) { if (user === undefined && dto.userUuid !== undefined) {
user = await this.userRepository.findOneByUuid(dto.userUuid) const userUuidOrError = Uuid.create(dto.userUuid)
if (userUuidOrError.isFailed()) {
throw new Error(userUuidOrError.getError())
}
const userUuid = userUuidOrError.getValue()
user = await this.userRepository.findOneByUuid(userUuid)
} }
if (!user) { if (!user) {
@@ -34,7 +34,7 @@ describe('DeleteAccount', () => {
} as jest.Mocked<UserSubscription> } as jest.Mocked<UserSubscription>
userRepository = {} as jest.Mocked<UserRepositoryInterface> userRepository = {} as jest.Mocked<UserRepositoryInterface>
userRepository.findOneByUsernameOrEmail = jest.fn().mockReturnValue(user) userRepository.findOneByUuid = jest.fn().mockReturnValue(user)
userSubscriptionService = {} as jest.Mocked<UserSubscriptionServiceInterface> userSubscriptionService = {} as jest.Mocked<UserSubscriptionServiceInterface>
userSubscriptionService.findRegularSubscriptionForUserUuid = jest userSubscriptionService.findRegularSubscriptionForUserUuid = jest
@@ -58,7 +58,7 @@ describe('DeleteAccount', () => {
.fn() .fn()
.mockReturnValue({ regularSubscription: null, sharedSubscription: null }) .mockReturnValue({ regularSubscription: null, sharedSubscription: null })
expect(await createUseCase().execute({ email: 'test@test.te' })).toEqual({ expect(await createUseCase().execute({ userUuid: '00000000-0000-0000-0000-000000000000' })).toEqual({
message: 'Successfully deleted user', message: 'Successfully deleted user',
responseCode: 200, responseCode: 200,
success: true, success: true,
@@ -77,7 +77,7 @@ describe('DeleteAccount', () => {
.fn() .fn()
.mockReturnValue({ regularSubscription, sharedSubscription: null }) .mockReturnValue({ regularSubscription, sharedSubscription: null })
expect(await createUseCase().execute({ email: 'test@test.te' })).toEqual({ expect(await createUseCase().execute({ userUuid: '00000000-0000-0000-0000-000000000000' })).toEqual({
message: 'Successfully deleted user', message: 'Successfully deleted user',
responseCode: 200, responseCode: 200,
success: true, success: true,
@@ -92,9 +92,9 @@ describe('DeleteAccount', () => {
}) })
it('should not trigger account deletion if user is not found', async () => { it('should not trigger account deletion if user is not found', async () => {
userRepository.findOneByUsernameOrEmail = jest.fn().mockReturnValue(null) userRepository.findOneByUuid = jest.fn().mockReturnValue(null)
expect(await createUseCase().execute({ email: 'test@test.te' })).toEqual({ expect(await createUseCase().execute({ userUuid: '00000000-0000-0000-0000-000000000000' })).toEqual({
message: 'User not found', message: 'User not found',
responseCode: 404, responseCode: 404,
success: false, success: false,
@@ -104,9 +104,9 @@ describe('DeleteAccount', () => {
expect(domainEventFactory.createAccountDeletionRequestedEvent).not.toHaveBeenCalled() expect(domainEventFactory.createAccountDeletionRequestedEvent).not.toHaveBeenCalled()
}) })
it('should not trigger account deletion if username is invalid', async () => { it('should not trigger account deletion if user uuid is invalid', async () => {
expect(await createUseCase().execute({ email: '' })).toEqual({ expect(await createUseCase().execute({ userUuid: '' })).toEqual({
message: 'Username cannot be empty', message: 'Given value is not a valid uuid: ',
responseCode: 400, responseCode: 400,
success: false, success: false,
}) })
@@ -1,4 +1,4 @@
import { Username } from '@standardnotes/domain-core' import { Uuid } from '@standardnotes/domain-core'
import { DomainEventPublisherInterface } from '@standardnotes/domain-events' import { DomainEventPublisherInterface } from '@standardnotes/domain-events'
import { TimerInterface } from '@standardnotes/time' import { TimerInterface } from '@standardnotes/time'
import { inject, injectable } from 'inversify' import { inject, injectable } from 'inversify'
@@ -23,17 +23,17 @@ export class DeleteAccount implements UseCaseInterface {
) {} ) {}
async execute(dto: DeleteAccountDTO): Promise<DeleteAccountResponse> { async execute(dto: DeleteAccountDTO): Promise<DeleteAccountResponse> {
const usernameOrError = Username.create(dto.email) const uuidOrError = Uuid.create(dto.userUuid)
if (usernameOrError.isFailed()) { if (uuidOrError.isFailed()) {
return { return {
success: false, success: false,
responseCode: 400, responseCode: 400,
message: usernameOrError.getError(), message: uuidOrError.getError(),
} }
} }
const username = usernameOrError.getValue() const uuid = uuidOrError.getValue()
const user = await this.userRepository.findOneByUsernameOrEmail(username) const user = await this.userRepository.findOneByUuid(uuid)
if (user === null) { if (user === null) {
return { return {
@@ -1,3 +1,3 @@
export type DeleteAccountDTO = { export type DeleteAccountDTO = {
email: string userUuid: string
} }
@@ -20,7 +20,7 @@ export class DeleteAuthenticator implements UseCaseInterface<string> {
} }
const userUuid = userUuidOrError.getValue() const userUuid = userUuidOrError.getValue()
const user = await this.userRepository.findOneByUuid(userUuid.value) const user = await this.userRepository.findOneByUuid(userUuid)
if (user === null) { if (user === null) {
return Result.fail('Could not delete authenticator: user not found.') return Result.fail('Could not delete authenticator: user not found.')
} }
@@ -37,7 +37,7 @@ export class GenerateAuthenticatorRegistrationOptions
} }
const username = usernameOrError.getValue() const username = usernameOrError.getValue()
const user = await this.userRepository.findOneByUuid(userUuid.value) const user = await this.userRepository.findOneByUuid(userUuid)
if (user === null) { if (user === null) {
return Result.fail('Could not generate authenticator registration options: user not found.') return Result.fail('Could not generate authenticator registration options: user not found.')
} }
@@ -19,7 +19,7 @@ export class GenerateRecoveryCodes implements UseCaseInterface<string> {
} }
const userUuid = userUuidOrError.getValue() const userUuid = userUuidOrError.getValue()
const user = await this.userRepository.findOneByUuid(userUuid.value) const user = await this.userRepository.findOneByUuid(userUuid)
if (user === null) { if (user === null) {
return Result.fail('Could not generate recovery codes: user not found') return Result.fail('Could not generate recovery codes: user not found')
} }
@@ -45,6 +45,10 @@ describe('GetSettings', () => {
) )
beforeEach(() => { beforeEach(() => {
user = {
uuid: '00000000-0000-0000-0000-000000000000',
} as jest.Mocked<User>
setting = new Setting() setting = new Setting()
setting.name = 'test' setting.name = 'test'
setting.updatedAt = 345 setting.updatedAt = 345
@@ -90,8 +94,6 @@ describe('GetSettings', () => {
subscriptionSettingProjector = {} as jest.Mocked<SubscriptionSettingProjector> subscriptionSettingProjector = {} as jest.Mocked<SubscriptionSettingProjector>
subscriptionSettingProjector.projectSimple = jest.fn().mockReturnValue({ foo: 'sub-bar' }) subscriptionSettingProjector.projectSimple = jest.fn().mockReturnValue({ foo: 'sub-bar' })
user = {} as jest.Mocked<User>
userRepository = {} as jest.Mocked<UserRepositoryInterface> userRepository = {} as jest.Mocked<UserRepositoryInterface>
userRepository.findOneByUuid = jest.fn().mockReturnValue(user) userRepository.findOneByUuid = jest.fn().mockReturnValue(user)
@@ -103,18 +105,27 @@ describe('GetSettings', () => {
it('should fail if a user is not found', async () => { it('should fail if a user is not found', async () => {
userRepository.findOneByUuid = jest.fn().mockReturnValue(null) userRepository.findOneByUuid = jest.fn().mockReturnValue(null)
expect(await createUseCase().execute({ userUuid: '1-2-3' })).toEqual({ expect(await createUseCase().execute({ userUuid: '00000000-0000-0000-0000-000000000000' })).toEqual({
success: false, success: false,
error: { error: {
message: 'User 1-2-3 not found.', message: 'User 00000000-0000-0000-0000-000000000000 not found.',
},
})
})
it('should fail if a user uuid is invalid', async () => {
expect(await createUseCase().execute({ userUuid: 'invalid' })).toEqual({
success: false,
error: {
message: 'Given value is not a valid uuid: invalid',
}, },
}) })
}) })
it('should return all user settings except mfa', async () => { it('should return all user settings except mfa', async () => {
expect(await createUseCase().execute({ userUuid: '1-2-3' })).toEqual({ expect(await createUseCase().execute({ userUuid: '00000000-0000-0000-0000-000000000000' })).toEqual({
success: true, success: true,
userUuid: '1-2-3', userUuid: '00000000-0000-0000-0000-000000000000',
settings: [{ foo: 'bar' }], settings: [{ foo: 'bar' }],
}) })
@@ -131,9 +142,9 @@ describe('GetSettings', () => {
} as jest.Mocked<Setting> } as jest.Mocked<Setting>
settingRepository.findAllByUserUuid = jest.fn().mockReturnValue([setting]) settingRepository.findAllByUserUuid = jest.fn().mockReturnValue([setting])
expect(await createUseCase().execute({ userUuid: '1-2-3' })).toEqual({ expect(await createUseCase().execute({ userUuid: '00000000-0000-0000-0000-000000000000' })).toEqual({
success: true, success: true,
userUuid: '1-2-3', userUuid: '00000000-0000-0000-0000-000000000000',
settings: [{ foo: 'bar' }], settings: [{ foo: 'bar' }],
}) })
@@ -147,10 +158,14 @@ describe('GetSettings', () => {
it('should return all user settings of certain name', async () => { it('should return all user settings of certain name', async () => {
expect( expect(
await createUseCase().execute({ userUuid: '1-2-3', settingName: 'test', allowSensitiveRetrieval: true }), await createUseCase().execute({
userUuid: '00000000-0000-0000-0000-000000000000',
settingName: 'test',
allowSensitiveRetrieval: true,
}),
).toEqual({ ).toEqual({
success: true, success: true,
userUuid: '1-2-3', userUuid: '00000000-0000-0000-0000-000000000000',
settings: [{ foo: 'bar' }], settings: [{ foo: 'bar' }],
}) })
@@ -159,10 +174,14 @@ describe('GetSettings', () => {
it('should return all user settings updated after', async () => { it('should return all user settings updated after', async () => {
expect( expect(
await createUseCase().execute({ userUuid: '1-2-3', allowSensitiveRetrieval: true, updatedAfter: 123 }), await createUseCase().execute({
userUuid: '00000000-0000-0000-0000-000000000000',
allowSensitiveRetrieval: true,
updatedAfter: 123,
}),
).toEqual({ ).toEqual({
success: true, success: true,
userUuid: '1-2-3', userUuid: '00000000-0000-0000-0000-000000000000',
settings: [{ foo: 'bar' }], settings: [{ foo: 'bar' }],
}) })
@@ -170,9 +189,14 @@ describe('GetSettings', () => {
}) })
it('should return all sensitive user settings if explicit', async () => { it('should return all sensitive user settings if explicit', async () => {
expect(await createUseCase().execute({ userUuid: '1-2-3', allowSensitiveRetrieval: true })).toEqual({ expect(
await createUseCase().execute({
userUuid: '00000000-0000-0000-0000-000000000000',
allowSensitiveRetrieval: true,
}),
).toEqual({
success: true, success: true,
userUuid: '1-2-3', userUuid: '00000000-0000-0000-0000-000000000000',
settings: [{ foo: 'bar' }, { foo: 'bar' }], settings: [{ foo: 'bar' }, { foo: 'bar' }],
}) })
@@ -190,9 +214,9 @@ describe('GetSettings', () => {
}) })
it('should return all user settings except mfa', async () => { it('should return all user settings except mfa', async () => {
expect(await createUseCase().execute({ userUuid: '1-2-3' })).toEqual({ expect(await createUseCase().execute({ userUuid: '00000000-0000-0000-0000-000000000000' })).toEqual({
success: true, success: true,
userUuid: '1-2-3', userUuid: '00000000-0000-0000-0000-000000000000',
settings: [{ foo: 'bar' }, { foo: 'sub-bar' }], settings: [{ foo: 'bar' }, { foo: 'sub-bar' }],
}) })
@@ -210,9 +234,9 @@ describe('GetSettings', () => {
}) })
it('should return all user settings except mfa', async () => { it('should return all user settings except mfa', async () => {
expect(await createUseCase().execute({ userUuid: '1-2-3' })).toEqual({ expect(await createUseCase().execute({ userUuid: '00000000-0000-0000-0000-000000000000' })).toEqual({
success: true, success: true,
userUuid: '1-2-3', userUuid: '00000000-0000-0000-0000-000000000000',
settings: [{ foo: 'bar' }, { foo: 'sub-bar' }], settings: [{ foo: 'bar' }, { foo: 'sub-bar' }],
}) })
@@ -15,6 +15,7 @@ import { SubscriptionSetting } from '../../Setting/SubscriptionSetting'
import { SimpleSetting } from '../../Setting/SimpleSetting' import { SimpleSetting } from '../../Setting/SimpleSetting'
import { SimpleSubscriptionSetting } from '../../Setting/SimpleSubscriptionSetting' import { SimpleSubscriptionSetting } from '../../Setting/SimpleSubscriptionSetting'
import { SubscriptionSettingProjector } from '../../../Projection/SubscriptionSettingProjector' import { SubscriptionSettingProjector } from '../../../Projection/SubscriptionSettingProjector'
import { Uuid } from '@standardnotes/domain-core'
@injectable() @injectable()
export class GetSettings implements UseCaseInterface { export class GetSettings implements UseCaseInterface {
@@ -30,7 +31,16 @@ export class GetSettings implements UseCaseInterface {
) {} ) {}
async execute(dto: GetSettingsDto): Promise<GetSettingsResponse> { async execute(dto: GetSettingsDto): Promise<GetSettingsResponse> {
const { userUuid } = dto const userUuidOrError = Uuid.create(dto.userUuid)
if (userUuidOrError.isFailed()) {
return {
success: false,
error: {
message: userUuidOrError.getError(),
},
}
}
const userUuid = userUuidOrError.getValue()
const user = await this.userRepository.findOneByUuid(userUuid) const user = await this.userRepository.findOneByUuid(userUuid)
@@ -38,13 +48,13 @@ export class GetSettings implements UseCaseInterface {
return { return {
success: false, success: false,
error: { error: {
message: `User ${userUuid} not found.`, message: `User ${userUuid.value} not found.`,
}, },
} }
} }
let settings: Array<Setting | SubscriptionSetting> let settings: Array<Setting | SubscriptionSetting>
settings = await this.settingRepository.findAllByUserUuid(userUuid) settings = await this.settingRepository.findAllByUserUuid(user.uuid)
const { regularSubscription, sharedSubscription } = const { regularSubscription, sharedSubscription } =
await this.userSubscriptionService.findRegularSubscriptionForUserUuid(user.uuid) await this.userSubscriptionService.findRegularSubscriptionForUserUuid(user.uuid)
@@ -83,7 +93,7 @@ export class GetSettings implements UseCaseInterface {
return { return {
success: true, success: true,
userUuid, userUuid: user.uuid,
settings: simpleSettings, settings: simpleSettings,
} }
} }
@@ -31,23 +31,36 @@ describe('GetUserFeatures', () => {
it('should fail if a user is not found', async () => { it('should fail if a user is not found', async () => {
userRepository.findOneByUuid = jest.fn().mockReturnValue(null) userRepository.findOneByUuid = jest.fn().mockReturnValue(null)
expect(await createUseCase().execute({ userUuid: 'user-1-1-1', offline: false })).toEqual({ expect(await createUseCase().execute({ userUuid: '00000000-0000-0000-0000-000000000000', offline: false })).toEqual(
success: false, {
error: { success: false,
message: 'User user-1-1-1 not found.', error: {
message: 'User 00000000-0000-0000-0000-000000000000 not found.',
},
}, },
}) )
}) })
it('should return user features', async () => { it('should return user features', async () => {
expect(await createUseCase().execute({ userUuid: 'user-1-1-1', offline: false })).toEqual({ expect(await createUseCase().execute({ userUuid: '00000000-0000-0000-0000-000000000000', offline: false })).toEqual(
success: true, {
userUuid: 'user-1-1-1', success: true,
features: [ userUuid: '00000000-0000-0000-0000-000000000000',
{ features: [
name: 'foobar', {
}, name: 'foobar',
], },
],
},
)
})
it('should fail if a user uuid is invalid', async () => {
expect(await createUseCase().execute({ userUuid: 'invalid', offline: false })).toEqual({
success: false,
error: {
message: 'Given value is not a valid uuid: invalid',
},
}) })
}) })
@@ -5,6 +5,7 @@ import { GetUserFeaturesDto } from './GetUserFeaturesDto'
import { UserRepositoryInterface } from '../../User/UserRepositoryInterface' import { UserRepositoryInterface } from '../../User/UserRepositoryInterface'
import { GetUserFeaturesResponse } from './GetUserFeaturesResponse' import { GetUserFeaturesResponse } from './GetUserFeaturesResponse'
import { FeatureServiceInterface } from '../../Feature/FeatureServiceInterface' import { FeatureServiceInterface } from '../../Feature/FeatureServiceInterface'
import { Uuid } from '@standardnotes/domain-core'
@injectable() @injectable()
export class GetUserFeatures implements UseCaseInterface { export class GetUserFeatures implements UseCaseInterface {
@@ -24,13 +25,24 @@ export class GetUserFeatures implements UseCaseInterface {
} }
} }
const user = await this.userRepository.findOneByUuid(dto.userUuid) const userUuidOrError = Uuid.create(dto.userUuid)
if (userUuidOrError.isFailed()) {
return {
success: false,
error: {
message: userUuidOrError.getError(),
},
}
}
const userUuid = userUuidOrError.getValue()
const user = await this.userRepository.findOneByUuid(userUuid)
if (user === null) { if (user === null) {
return { return {
success: false, success: false,
error: { error: {
message: `User ${dto.userUuid} not found.`, message: `User ${userUuid.value} not found.`,
}, },
} }
} }
@@ -39,7 +51,7 @@ export class GetUserFeatures implements UseCaseInterface {
return { return {
success: true, success: true,
userUuid: dto.userUuid, userUuid: userUuid.value,
features: userFeatures, features: userFeatures,
} }
} }
@@ -61,7 +61,9 @@ describe('GetUserKeyParams', () => {
}) })
it('should get key params for an authenticated user - searching by uuid', async () => { it('should get key params for an authenticated user - searching by uuid', async () => {
expect(await createUseCase().execute({ userUuid: '1-2-3', authenticated: true })).toEqual({ expect(
await createUseCase().execute({ userUuid: '00000000-0000-0000-0000-000000000000', authenticated: true }),
).toEqual({
keyParams: { keyParams: {
foo: 'bar', foo: 'bar',
}, },
@@ -71,7 +73,9 @@ describe('GetUserKeyParams', () => {
}) })
it('should get key params for an unauthenticated user - searching by uuid', async () => { it('should get key params for an unauthenticated user - searching by uuid', async () => {
expect(await createUseCase().execute({ userUuid: '1-2-3', authenticated: false })).toEqual({ expect(
await createUseCase().execute({ userUuid: '00000000-0000-0000-0000-000000000000', authenticated: false }),
).toEqual({
keyParams: { keyParams: {
foo: 'bar', foo: 'bar',
}, },
@@ -81,7 +85,13 @@ describe('GetUserKeyParams', () => {
}) })
it("should get key params for an unauthenticated user and store it's code challenge", async () => { it("should get key params for an unauthenticated user and store it's code challenge", async () => {
expect(await createUseCase().execute({ userUuid: '1-2-3', authenticated: false, codeChallenge: 'test' })).toEqual({ expect(
await createUseCase().execute({
userUuid: '00000000-0000-0000-0000-000000000000',
authenticated: false,
codeChallenge: 'test',
}),
).toEqual({
keyParams: { keyParams: {
foo: 'bar', foo: 'bar',
}, },
@@ -107,7 +117,18 @@ describe('GetUserKeyParams', () => {
let error = null let error = null
try { try {
await createUseCase().execute({ userUuid: '1-2-3', authenticated: false }) await createUseCase().execute({ userUuid: '00000000-0000-0000-0000-000000000000', authenticated: false })
} catch (e) {
error = e
}
expect(error).not.toBeNull()
})
it('should throw error for an invalid user uuid', async () => {
let error = null
try {
await createUseCase().execute({ userUuid: 'invalid', authenticated: false })
} catch (e) { } catch (e) {
error = e error = e
} }
@@ -10,7 +10,7 @@ import { User } from '../../User/User'
import { PKCERepositoryInterface } from '../../User/PKCERepositoryInterface' import { PKCERepositoryInterface } from '../../User/PKCERepositoryInterface'
import { GetUserKeyParamsDTOV2Challenged } from './GetUserKeyParamsDTOV2Challenged' import { GetUserKeyParamsDTOV2Challenged } from './GetUserKeyParamsDTOV2Challenged'
import { KeyParamsData } from '@standardnotes/responses' import { KeyParamsData } from '@standardnotes/responses'
import { Username } from '@standardnotes/domain-core' import { Username, Uuid } from '@standardnotes/domain-core'
@injectable() @injectable()
export class GetUserKeyParams implements UseCaseInterface { export class GetUserKeyParams implements UseCaseInterface {
@@ -39,7 +39,13 @@ export class GetUserKeyParams implements UseCaseInterface {
} }
} }
} else if (dto.userUuid) { } else if (dto.userUuid) {
user = await this.userRepository.findOneByUuid(dto.userUuid) const userUuidOrError = Uuid.create(dto.userUuid)
if (userUuidOrError.isFailed()) {
throw Error(userUuidOrError.getError())
}
const userUuid = userUuidOrError.getValue()
user = await this.userRepository.findOneByUuid(userUuid)
} }
if (!user) { if (!user) {
@@ -15,7 +15,10 @@ describe('GetUserSubscription', () => {
const createUseCase = () => new GetUserSubscription(userRepository, userSubscriptionRepository) const createUseCase = () => new GetUserSubscription(userRepository, userSubscriptionRepository)
beforeEach(() => { beforeEach(() => {
user = { uuid: 'user-1-1-1', email: 'user-1-1-1@example.com' } as jest.Mocked<User> user = {
uuid: '00000000-0000-0000-0000-000000000000',
email: '00000000-0000-0000-0000-000000000000@example.com',
} as jest.Mocked<User>
userRepository = {} as jest.Mocked<UserRepositoryInterface> userRepository = {} as jest.Mocked<UserRepositoryInterface>
userRepository.findOneByUuid = jest.fn().mockReturnValue(user) userRepository.findOneByUuid = jest.fn().mockReturnValue(user)
@@ -29,18 +32,27 @@ describe('GetUserSubscription', () => {
it('should fail if a user is not found', async () => { it('should fail if a user is not found', async () => {
userRepository.findOneByUuid = jest.fn().mockReturnValue(null) userRepository.findOneByUuid = jest.fn().mockReturnValue(null)
expect(await createUseCase().execute({ userUuid: 'user-1-1-1' })).toEqual({ expect(await createUseCase().execute({ userUuid: '00000000-0000-0000-0000-000000000000' })).toEqual({
success: false, success: false,
error: { error: {
message: 'User user-1-1-1 not found.', message: 'User 00000000-0000-0000-0000-000000000000 not found.',
},
})
})
it('should fail if a user uuid is invalid', async () => {
expect(await createUseCase().execute({ userUuid: 'invalid' })).toEqual({
success: false,
error: {
message: 'Given value is not a valid uuid: invalid',
}, },
}) })
}) })
it('should return user subscription', async () => { it('should return user subscription', async () => {
expect(await createUseCase().execute({ userUuid: 'user-1-1-1' })).toEqual({ expect(await createUseCase().execute({ userUuid: '00000000-0000-0000-0000-000000000000' })).toEqual({
success: true, success: true,
user: { uuid: 'user-1-1-1', email: 'user-1-1-1@example.com' }, user: { uuid: '00000000-0000-0000-0000-000000000000', email: '00000000-0000-0000-0000-000000000000@example.com' },
subscription: { subscription: {
planName: SubscriptionName.ProPlan, planName: SubscriptionName.ProPlan,
}, },
@@ -5,6 +5,7 @@ import { GetUserSubscriptionDto } from './GetUserSubscriptionDto'
import { UserRepositoryInterface } from '../../User/UserRepositoryInterface' import { UserRepositoryInterface } from '../../User/UserRepositoryInterface'
import { GetUserSubscriptionResponse } from './GetUserSubscriptionResponse' import { GetUserSubscriptionResponse } from './GetUserSubscriptionResponse'
import { UserSubscriptionRepositoryInterface } from '../../Subscription/UserSubscriptionRepositoryInterface' import { UserSubscriptionRepositoryInterface } from '../../Subscription/UserSubscriptionRepositoryInterface'
import { Uuid } from '@standardnotes/domain-core'
@injectable() @injectable()
export class GetUserSubscription implements UseCaseInterface { export class GetUserSubscription implements UseCaseInterface {
@@ -15,7 +16,16 @@ export class GetUserSubscription implements UseCaseInterface {
) {} ) {}
async execute(dto: GetUserSubscriptionDto): Promise<GetUserSubscriptionResponse> { async execute(dto: GetUserSubscriptionDto): Promise<GetUserSubscriptionResponse> {
const { userUuid } = dto const userUuidOrError = Uuid.create(dto.userUuid)
if (userUuidOrError.isFailed()) {
return {
success: false,
error: {
message: userUuidOrError.getError(),
},
}
}
const userUuid = userUuidOrError.getValue()
const user = await this.userRepository.findOneByUuid(userUuid) const user = await this.userRepository.findOneByUuid(userUuid)
@@ -23,12 +33,12 @@ export class GetUserSubscription implements UseCaseInterface {
return { return {
success: false, success: false,
error: { error: {
message: `User ${userUuid} not found.`, message: `User ${userUuid.value} not found.`,
}, },
} }
} }
const userSubscription = await this.userSubscriptionRepository.findOneByUserUuid(userUuid) const userSubscription = await this.userSubscriptionRepository.findOneByUserUuid(userUuid.value)
return { return {
success: true, success: true,
@@ -21,7 +21,7 @@ export class ListAuthenticators implements UseCaseInterface<Authenticator[]> {
} }
const userUuid = userUuidOrError.getValue() const userUuid = userUuidOrError.getValue()
const user = await this.userRepository.findOneByUuid(userUuid.value) const user = await this.userRepository.findOneByUuid(userUuid)
if (user === null) { if (user === null) {
return Result.fail('Could not list authenticators: user not found.') return Result.fail('Could not list authenticators: user not found.')
} }
@@ -62,7 +62,7 @@ describe('UpdateSetting', () => {
settingProjector.projectSimple = jest.fn().mockReturnValue(settingProjection) settingProjector.projectSimple = jest.fn().mockReturnValue(settingProjection)
regularSubscription = { regularSubscription = {
uuid: '1-2-3', uuid: '00000000-0000-0000-0000-000000000000',
subscriptionType: UserSubscriptionType.Regular, subscriptionType: UserSubscriptionType.Regular,
user: Promise.resolve(user), user: Promise.resolve(user),
} as jest.Mocked<UserSubscription> } as jest.Mocked<UserSubscription>
@@ -109,7 +109,7 @@ describe('UpdateSetting', () => {
sensitive: false, sensitive: false,
} }
const response = await createUseCase().execute({ props, userUuid: '1-2-3' }) const response = await createUseCase().execute({ props, userUuid: '00000000-0000-0000-0000-000000000000' })
expect(settingService.createOrReplace).toHaveBeenCalledWith({ expect(settingService.createOrReplace).toHaveBeenCalledWith({
props: { props: {
@@ -138,19 +138,40 @@ describe('UpdateSetting', () => {
sensitive: false, sensitive: false,
} }
const response = await createUseCase().execute({ props, userUuid: '1-2-3' }) const response = await createUseCase().execute({ props, userUuid: '00000000-0000-0000-0000-000000000000' })
expect(settingService.createOrReplace).not.toHaveBeenCalled() expect(settingService.createOrReplace).not.toHaveBeenCalled()
expect(response).toEqual({ expect(response).toEqual({
success: false, success: false,
error: { error: {
message: 'User 1-2-3 not found.', message: 'User 00000000-0000-0000-0000-000000000000 not found.',
}, },
statusCode: 404, statusCode: 404,
}) })
}) })
it('should not create a setting if user uuid is invalid', async () => {
const props = {
name: SettingName.NAMES.ExtensionKey,
unencryptedValue: 'test-setting-value',
serverEncryptionVersion: EncryptionVersion.Unencrypted,
sensitive: false,
}
const response = await createUseCase().execute({ props, userUuid: 'invalid' })
expect(settingService.createOrReplace).not.toHaveBeenCalled()
expect(response).toEqual({
success: false,
error: {
message: 'Given value is not a valid uuid: invalid',
},
statusCode: 400,
})
})
it('should not create a subscription setting', async () => { it('should not create a subscription setting', async () => {
const props = { const props = {
name: SettingName.NAMES.MuteSignInEmails, name: SettingName.NAMES.MuteSignInEmails,
@@ -159,14 +180,14 @@ describe('UpdateSetting', () => {
sensitive: false, sensitive: false,
} }
const response = await createUseCase().execute({ props, userUuid: '1-2-3' }) const response = await createUseCase().execute({ props, userUuid: '00000000-0000-0000-0000-000000000000' })
expect(settingService.createOrReplace).not.toHaveBeenCalled() expect(settingService.createOrReplace).not.toHaveBeenCalled()
expect(response).toEqual({ expect(response).toEqual({
success: false, success: false,
error: { error: {
message: 'User 1-2-3 has no subscription to change a subscription setting.', message: 'User 00000000-0000-0000-0000-000000000000 has no subscription to change a subscription setting.',
}, },
statusCode: 400, statusCode: 400,
}) })
@@ -180,7 +201,7 @@ describe('UpdateSetting', () => {
sensitive: false, sensitive: false,
} }
const response = await createUseCase().execute({ props, userUuid: '1-2-3' }) const response = await createUseCase().execute({ props, userUuid: '00000000-0000-0000-0000-000000000000' })
expect(settingService.createOrReplace).not.toHaveBeenCalled() expect(settingService.createOrReplace).not.toHaveBeenCalled()
@@ -207,14 +228,14 @@ describe('UpdateSetting', () => {
sensitive: false, sensitive: false,
} }
const response = await createUseCase().execute({ props, userUuid: '1-2-3' }) const response = await createUseCase().execute({ props, userUuid: '00000000-0000-0000-0000-000000000000' })
expect(settingService.createOrReplace).not.toHaveBeenCalled() expect(settingService.createOrReplace).not.toHaveBeenCalled()
expect(response).toEqual({ expect(response).toEqual({
success: false, success: false,
error: { error: {
message: 'User 1-2-3 is not permitted to change the setting.', message: 'User 00000000-0000-0000-0000-000000000000 is not permitted to change the setting.',
}, },
statusCode: 401, statusCode: 401,
}) })
@@ -230,14 +251,14 @@ describe('UpdateSetting', () => {
sensitive: false, sensitive: false,
} }
const response = await createUseCase().execute({ props, userUuid: '1-2-3' }) const response = await createUseCase().execute({ props, userUuid: '00000000-0000-0000-0000-000000000000' })
expect(settingService.createOrReplace).not.toHaveBeenCalled() expect(settingService.createOrReplace).not.toHaveBeenCalled()
expect(response).toEqual({ expect(response).toEqual({
success: false, success: false,
error: { error: {
message: 'User 1-2-3 is not permitted to change the setting.', message: 'User 00000000-0000-0000-0000-000000000000 is not permitted to change the setting.',
}, },
statusCode: 401, statusCode: 401,
}) })
@@ -259,7 +280,7 @@ describe('UpdateSetting', () => {
sensitive: false, sensitive: false,
} }
const response = await createUseCase().execute({ props, userUuid: '1-2-3' }) const response = await createUseCase().execute({ props, userUuid: '00000000-0000-0000-0000-000000000000' })
expect(subscriptionSettingService.createOrReplace).toHaveBeenCalledWith({ expect(subscriptionSettingService.createOrReplace).toHaveBeenCalledWith({
props: { props: {
@@ -295,7 +316,7 @@ describe('UpdateSetting', () => {
sensitive: false, sensitive: false,
} }
const response = await createUseCase().execute({ props, userUuid: '1-2-3' }) const response = await createUseCase().execute({ props, userUuid: '00000000-0000-0000-0000-000000000000' })
expect(subscriptionSettingService.createOrReplace).toHaveBeenCalledWith({ expect(subscriptionSettingService.createOrReplace).toHaveBeenCalledWith({
props: { props: {
@@ -16,6 +16,7 @@ import { SubscriptionSettingServiceInterface } from '../../Setting/SubscriptionS
import { UserSubscriptionServiceInterface } from '../../Subscription/UserSubscriptionServiceInterface' import { UserSubscriptionServiceInterface } from '../../Subscription/UserSubscriptionServiceInterface'
import { CreateOrReplaceSubscriptionSettingResponse } from '../../Setting/CreateOrReplaceSubscriptionSettingResponse' import { CreateOrReplaceSubscriptionSettingResponse } from '../../Setting/CreateOrReplaceSubscriptionSettingResponse'
import { SubscriptionSettingProjector } from '../../../Projection/SubscriptionSettingProjector' import { SubscriptionSettingProjector } from '../../../Projection/SubscriptionSettingProjector'
import { Uuid } from '@standardnotes/domain-core'
@injectable() @injectable()
export class UpdateSetting implements UseCaseInterface { export class UpdateSetting implements UseCaseInterface {
@@ -48,7 +49,17 @@ export class UpdateSetting implements UseCaseInterface {
this.logger.debug('[%s] Updating setting: %O', dto.userUuid, dto) this.logger.debug('[%s] Updating setting: %O', dto.userUuid, dto)
const { userUuid, props } = dto const userUuidOrError = Uuid.create(dto.userUuid)
if (userUuidOrError.isFailed()) {
return {
success: false,
error: {
message: userUuidOrError.getError(),
},
statusCode: 400,
}
}
const userUuid = userUuidOrError.getValue()
const user = await this.userRepository.findOneByUuid(userUuid) const user = await this.userRepository.findOneByUuid(userUuid)
@@ -56,7 +67,7 @@ export class UpdateSetting implements UseCaseInterface {
return { return {
success: false, success: false,
error: { error: {
message: `User ${userUuid} not found.`, message: `User ${userUuid.value} not found.`,
}, },
statusCode: 404, statusCode: 404,
} }
@@ -66,14 +77,14 @@ export class UpdateSetting implements UseCaseInterface {
return { return {
success: false, success: false,
error: { error: {
message: `User ${userUuid} is not permitted to change the setting.`, message: `User ${userUuid.value} is not permitted to change the setting.`,
}, },
statusCode: 401, statusCode: 401,
} }
} }
props.serverEncryptionVersion = this.settingsAssociationService.getEncryptionVersionForSetting(settingName) dto.props.serverEncryptionVersion = this.settingsAssociationService.getEncryptionVersionForSetting(settingName)
props.sensitive = this.settingsAssociationService.getSensitivityForSetting(settingName) dto.props.sensitive = this.settingsAssociationService.getSensitivityForSetting(settingName)
if (settingName.isASubscriptionSetting()) { if (settingName.isASubscriptionSetting()) {
const { regularSubscription, sharedSubscription } = const { regularSubscription, sharedSubscription } =
@@ -83,7 +94,7 @@ export class UpdateSetting implements UseCaseInterface {
return { return {
success: false, success: false,
error: { error: {
message: `User ${userUuid} has no subscription to change a subscription setting.`, message: `User ${userUuid.value} has no subscription to change a subscription setting.`,
}, },
statusCode: 400, statusCode: 400,
} }
@@ -92,7 +103,7 @@ export class UpdateSetting implements UseCaseInterface {
const response = await this.subscriptionSettingService.createOrReplace({ const response = await this.subscriptionSettingService.createOrReplace({
userSubscription: subscription, userSubscription: subscription,
user, user,
props, props: dto.props,
}) })
return { return {
@@ -104,7 +115,7 @@ export class UpdateSetting implements UseCaseInterface {
const response = await this.settingService.createOrReplace({ const response = await this.settingService.createOrReplace({
user, user,
props, props: dto.props,
}) })
return { return {
@@ -27,7 +27,7 @@ export class VerifyAuthenticatorRegistrationResponse implements UseCaseInterface
} }
const userUuid = userUuidOrError.getValue() const userUuid = userUuidOrError.getValue()
const user = await this.userRepository.findOneByUuid(userUuid.value) const user = await this.userRepository.findOneByUuid(userUuid)
if (user === null) { if (user === null) {
return Result.fail('Could not verify authenticator registration response: user not found.') return Result.fail('Could not verify authenticator registration response: user not found.')
} }
@@ -1,4 +1,4 @@
import { Email, Username } from '@standardnotes/domain-core' import { Email, Username, Uuid } from '@standardnotes/domain-core'
import { ReadStream } from 'fs' import { ReadStream } from 'fs'
import { User } from './User' import { User } from './User'
@@ -6,7 +6,7 @@ import { User } from './User'
export interface UserRepositoryInterface { export interface UserRepositoryInterface {
streamAll(): Promise<ReadStream> streamAll(): Promise<ReadStream>
streamTeam(memberEmail?: Email): Promise<ReadStream> streamTeam(memberEmail?: Email): Promise<ReadStream>
findOneByUuid(uuid: string): Promise<User | null> findOneByUuid(uuid: Uuid): Promise<User | null>
findOneByUsernameOrEmail(usernameOrEmail: Email | Username): Promise<User | null> findOneByUsernameOrEmail(usernameOrEmail: Email | Username): Promise<User | null>
save(user: User): Promise<User> save(user: User): Promise<User>
remove(user: User): Promise<User> remove(user: User): Promise<User>
@@ -1,6 +1,6 @@
import 'reflect-metadata' import 'reflect-metadata'
import { InversifyExpressAdminController } from './InversifyExpressAdminController' import { AnnotatedAdminController } from './AnnotatedAdminController'
import { results } from 'inversify-express-utils' import { results } from 'inversify-express-utils'
import { User } from '../../Domain/User/User' import { User } from '../../Domain/User/User'
import { UserRepositoryInterface } from '../../Domain/User/UserRepositoryInterface' import { UserRepositoryInterface } from '../../Domain/User/UserRepositoryInterface'
@@ -9,7 +9,7 @@ import { DeleteSetting } from '../../Domain/UseCase/DeleteSetting/DeleteSetting'
import { CreateSubscriptionToken } from '../../Domain/UseCase/CreateSubscriptionToken/CreateSubscriptionToken' import { CreateSubscriptionToken } from '../../Domain/UseCase/CreateSubscriptionToken/CreateSubscriptionToken'
import { CreateOfflineSubscriptionToken } from '../../Domain/UseCase/CreateOfflineSubscriptionToken/CreateOfflineSubscriptionToken' import { CreateOfflineSubscriptionToken } from '../../Domain/UseCase/CreateOfflineSubscriptionToken/CreateOfflineSubscriptionToken'
describe('InversifyExpressAdminController', () => { describe('AnnotatedAdminController', () => {
let deleteSetting: DeleteSetting let deleteSetting: DeleteSetting
let userRepository: UserRepositoryInterface let userRepository: UserRepositoryInterface
let createSubscriptionToken: CreateSubscriptionToken let createSubscriptionToken: CreateSubscriptionToken
@@ -18,12 +18,7 @@ describe('InversifyExpressAdminController', () => {
let user: User let user: User
const createController = () => const createController = () =>
new InversifyExpressAdminController( new AnnotatedAdminController(deleteSetting, userRepository, createSubscriptionToken, createOfflineSubscriptionToken)
deleteSetting,
userRepository,
createSubscriptionToken,
createOfflineSubscriptionToken,
)
beforeEach(() => { beforeEach(() => {
user = {} as jest.Mocked<User> user = {} as jest.Mocked<User>
@@ -9,14 +9,14 @@ import {
results, results,
} from 'inversify-express-utils' } from 'inversify-express-utils'
import TYPES from '../../Bootstrap/Types' import TYPES from '../../Bootstrap/Types'
import { HomeServerAdminController } from './HomeServer/HomeServerAdminController' import { BaseAdminController } from './Base/BaseAdminController'
import { CreateOfflineSubscriptionToken } from '../../Domain/UseCase/CreateOfflineSubscriptionToken/CreateOfflineSubscriptionToken' import { CreateOfflineSubscriptionToken } from '../../Domain/UseCase/CreateOfflineSubscriptionToken/CreateOfflineSubscriptionToken'
import { CreateSubscriptionToken } from '../../Domain/UseCase/CreateSubscriptionToken/CreateSubscriptionToken' import { CreateSubscriptionToken } from '../../Domain/UseCase/CreateSubscriptionToken/CreateSubscriptionToken'
import { DeleteSetting } from '../../Domain/UseCase/DeleteSetting/DeleteSetting' import { DeleteSetting } from '../../Domain/UseCase/DeleteSetting/DeleteSetting'
import { UserRepositoryInterface } from '../../Domain/User/UserRepositoryInterface' import { UserRepositoryInterface } from '../../Domain/User/UserRepositoryInterface'
@controller('/admin') @controller('/admin')
export class InversifyExpressAdminController extends HomeServerAdminController { export class AnnotatedAdminController extends BaseAdminController {
constructor( constructor(
@inject(TYPES.Auth_DeleteSetting) override doDeleteSetting: DeleteSetting, @inject(TYPES.Auth_DeleteSetting) override doDeleteSetting: DeleteSetting,
@inject(TYPES.Auth_UserRepository) override userRepository: UserRepositoryInterface, @inject(TYPES.Auth_UserRepository) override userRepository: UserRepositoryInterface,
@@ -16,10 +16,10 @@ import { Logger } from 'winston'
import { GetUserKeyParams } from '../../Domain/UseCase/GetUserKeyParams/GetUserKeyParams' import { GetUserKeyParams } from '../../Domain/UseCase/GetUserKeyParams/GetUserKeyParams'
import { AuthController } from '../../Controller/AuthController' import { AuthController } from '../../Controller/AuthController'
import { inject } from 'inversify' import { inject } from 'inversify'
import { HomeServerAuthController } from './HomeServer/HomeServerAuthController' import { BaseAuthController } from './Base/BaseAuthController'
@controller('/auth') @controller('/auth')
export class InversifyExpressAuthController extends HomeServerAuthController { export class AnnotatedAuthController extends BaseAuthController {
constructor( constructor(
@inject(TYPES.Auth_VerifyMFA) override verifyMFA: VerifyMFA, @inject(TYPES.Auth_VerifyMFA) override verifyMFA: VerifyMFA,
@inject(TYPES.Auth_SignIn) override signInUseCase: SignIn, @inject(TYPES.Auth_SignIn) override signInUseCase: SignIn,
@@ -10,10 +10,10 @@ import {
import TYPES from '../../Bootstrap/Types' import TYPES from '../../Bootstrap/Types'
import { AuthenticatorsController } from '../../Controller/AuthenticatorsController' import { AuthenticatorsController } from '../../Controller/AuthenticatorsController'
import { inject } from 'inversify' import { inject } from 'inversify'
import { HomeServerAuthenticatorsController } from './HomeServer/HomeServerAuthenticatorsController' import { BaseAuthenticatorsController } from './Base/BaseAuthenticatorsController'
@controller('/authenticators') @controller('/authenticators')
export class InversifyExpressAuthenticatorsController extends HomeServerAuthenticatorsController { export class AnnotatedAuthenticatorsController extends BaseAuthenticatorsController {
constructor( constructor(
@inject(TYPES.Auth_AuthenticatorsController) override authenticatorsController: AuthenticatorsController, @inject(TYPES.Auth_AuthenticatorsController) override authenticatorsController: AuthenticatorsController,
) { ) {
@@ -2,19 +2,19 @@ import 'reflect-metadata'
import * as express from 'express' import * as express from 'express'
import { InversifyExpressFeaturesController } from './InversifyExpressFeaturesController' import { AnnotatedFeaturesController } from './AnnotatedFeaturesController'
import { results } from 'inversify-express-utils' import { results } from 'inversify-express-utils'
import { User } from '../../Domain/User/User' import { User } from '../../Domain/User/User'
import { GetUserFeatures } from '../../Domain/UseCase/GetUserFeatures/GetUserFeatures' import { GetUserFeatures } from '../../Domain/UseCase/GetUserFeatures/GetUserFeatures'
describe('InversifyExpressFeaturesController', () => { describe('AnnotatedFeaturesController', () => {
let getUserFeatures: GetUserFeatures let getUserFeatures: GetUserFeatures
let request: express.Request let request: express.Request
let response: express.Response let response: express.Response
let user: User let user: User
const createController = () => new InversifyExpressFeaturesController(getUserFeatures) const createController = () => new AnnotatedFeaturesController(getUserFeatures)
beforeEach(() => { beforeEach(() => {
user = {} as jest.Mocked<User> user = {} as jest.Mocked<User>
@@ -8,10 +8,10 @@ import {
} from 'inversify-express-utils' } from 'inversify-express-utils'
import TYPES from '../../Bootstrap/Types' import TYPES from '../../Bootstrap/Types'
import { GetUserFeatures } from '../../Domain/UseCase/GetUserFeatures/GetUserFeatures' import { GetUserFeatures } from '../../Domain/UseCase/GetUserFeatures/GetUserFeatures'
import { HomeServerFeaturesController } from './HomeServer/HomeServerFeaturesController' import { BaseFeaturesController } from './Base/BaseFeaturesController'
@controller('/users/:userUuid/features') @controller('/users/:userUuid/features')
export class InversifyExpressFeaturesController extends HomeServerFeaturesController { export class AnnotatedFeaturesController extends BaseFeaturesController {
constructor(@inject(TYPES.Auth_GetUserFeatures) override doGetUserFeatures: GetUserFeatures) { constructor(@inject(TYPES.Auth_GetUserFeatures) override doGetUserFeatures: GetUserFeatures) {
super(doGetUserFeatures) super(doGetUserFeatures)
} }
@@ -1,7 +1,7 @@
import { controller, httpGet } from 'inversify-express-utils' import { controller, httpGet } from 'inversify-express-utils'
@controller('/healthcheck') @controller('/healthcheck')
export class InversifyExpressHealthCheckController { export class AnnotatedHealthCheckController {
@httpGet('/') @httpGet('/')
public async get(): Promise<string> { public async get(): Promise<string> {
return 'OK' return 'OK'
@@ -2,13 +2,13 @@ import 'reflect-metadata'
import * as express from 'express' import * as express from 'express'
import { InversifyExpressInternalController } from './InversifyExpressInternalController' import { AnnotatedInternalController } from './AnnotatedInternalController'
import { results } from 'inversify-express-utils' import { results } from 'inversify-express-utils'
import { User } from '../../Domain/User/User' import { User } from '../../Domain/User/User'
import { GetUserFeatures } from '../../Domain/UseCase/GetUserFeatures/GetUserFeatures' import { GetUserFeatures } from '../../Domain/UseCase/GetUserFeatures/GetUserFeatures'
import { GetSetting } from '../../Domain/UseCase/GetSetting/GetSetting' import { GetSetting } from '../../Domain/UseCase/GetSetting/GetSetting'
describe('InversifyExpressInternalController', () => { describe('AnnotatedInternalController', () => {
let getUserFeatures: GetUserFeatures let getUserFeatures: GetUserFeatures
let getSetting: GetSetting let getSetting: GetSetting
@@ -16,7 +16,7 @@ describe('InversifyExpressInternalController', () => {
let response: express.Response let response: express.Response
let user: User let user: User
const createController = () => new InversifyExpressInternalController(getUserFeatures, getSetting) const createController = () => new AnnotatedInternalController(getUserFeatures, getSetting)
beforeEach(() => { beforeEach(() => {
user = {} as jest.Mocked<User> user = {} as jest.Mocked<User>
@@ -12,7 +12,7 @@ import { GetSetting } from '../../Domain/UseCase/GetSetting/GetSetting'
import { GetUserFeatures } from '../../Domain/UseCase/GetUserFeatures/GetUserFeatures' import { GetUserFeatures } from '../../Domain/UseCase/GetUserFeatures/GetUserFeatures'
@controller('/internal') @controller('/internal')
export class InversifyExpressInternalController extends BaseHttpController { export class AnnotatedInternalController extends BaseHttpController {
constructor( constructor(
@inject(TYPES.Auth_GetUserFeatures) private doGetUserFeatures: GetUserFeatures, @inject(TYPES.Auth_GetUserFeatures) private doGetUserFeatures: GetUserFeatures,
@inject(TYPES.Auth_GetSetting) private doGetSetting: GetSetting, @inject(TYPES.Auth_GetSetting) private doGetSetting: GetSetting,
@@ -3,18 +3,18 @@ import 'reflect-metadata'
import * as express from 'express' import * as express from 'express'
import { results } from 'inversify-express-utils' import { results } from 'inversify-express-utils'
import { InversifyExpressListedController } from './InversifyExpressListedController' import { AnnotatedListedController } from './AnnotatedListedController'
import { User } from '../../Domain/User/User' import { User } from '../../Domain/User/User'
import { CreateListedAccount } from '../../Domain/UseCase/CreateListedAccount/CreateListedAccount' import { CreateListedAccount } from '../../Domain/UseCase/CreateListedAccount/CreateListedAccount'
describe('InversifyExpressListedController', () => { describe('AnnotatedListedController', () => {
let createListedAccount: CreateListedAccount let createListedAccount: CreateListedAccount
let request: express.Request let request: express.Request
let response: express.Response let response: express.Response
let user: User let user: User
const createController = () => new InversifyExpressListedController(createListedAccount) const createController = () => new AnnotatedListedController(createListedAccount)
beforeEach(() => { beforeEach(() => {
user = {} as jest.Mocked<User> user = {} as jest.Mocked<User>
@@ -4,10 +4,10 @@ import { controller, httpPost, results } from 'inversify-express-utils'
import { Request, Response } from 'express' import { Request, Response } from 'express'
import TYPES from '../../Bootstrap/Types' import TYPES from '../../Bootstrap/Types'
import { CreateListedAccount } from '../../Domain/UseCase/CreateListedAccount/CreateListedAccount' import { CreateListedAccount } from '../../Domain/UseCase/CreateListedAccount/CreateListedAccount'
import { HomeServerListedController } from './HomeServer/HomeServerListedController' import { BaseListedController } from './Base/BaseListedController'
@controller('/listed') @controller('/listed')
export class InversifyExpressListedController extends HomeServerListedController { export class AnnotatedListedController extends BaseListedController {
constructor(@inject(TYPES.Auth_CreateListedAccount) override doCreateListedAccount: CreateListedAccount) { constructor(@inject(TYPES.Auth_CreateListedAccount) override doCreateListedAccount: CreateListedAccount) {
super(doCreateListedAccount) super(doCreateListedAccount)
} }
@@ -2,7 +2,7 @@ import 'reflect-metadata'
import * as express from 'express' import * as express from 'express'
import { InversifyExpressOfflineController } from './InversifyExpressOfflineController' import { AnnotatedOfflineController } from './AnnotatedOfflineController'
import { results } from 'inversify-express-utils' import { results } from 'inversify-express-utils'
import { User } from '../../Domain/User/User' import { User } from '../../Domain/User/User'
import { GetUserFeatures } from '../../Domain/UseCase/GetUserFeatures/GetUserFeatures' import { GetUserFeatures } from '../../Domain/UseCase/GetUserFeatures/GetUserFeatures'
@@ -15,7 +15,7 @@ import { OfflineUserTokenData, TokenEncoderInterface } from '@standardnotes/secu
import { SubscriptionName } from '@standardnotes/common' import { SubscriptionName } from '@standardnotes/common'
import { Logger } from 'winston' import { Logger } from 'winston'
describe('InversifyExpressOfflineController', () => { describe('AnnotatedOfflineController', () => {
let getUserFeatures: GetUserFeatures let getUserFeatures: GetUserFeatures
let getUserOfflineSubscription: GetUserOfflineSubscription let getUserOfflineSubscription: GetUserOfflineSubscription
let createOfflineSubscriptionToken: CreateOfflineSubscriptionToken let createOfflineSubscriptionToken: CreateOfflineSubscriptionToken
@@ -29,7 +29,7 @@ describe('InversifyExpressOfflineController', () => {
let user: User let user: User
const createController = () => const createController = () =>
new InversifyExpressOfflineController( new AnnotatedOfflineController(
getUserFeatures, getUserFeatures,
getUserOfflineSubscription, getUserOfflineSubscription,
createOfflineSubscriptionToken, createOfflineSubscriptionToken,
@@ -14,10 +14,10 @@ import { AuthenticateOfflineSubscriptionToken } from '../../Domain/UseCase/Authe
import { CreateOfflineSubscriptionToken } from '../../Domain/UseCase/CreateOfflineSubscriptionToken/CreateOfflineSubscriptionToken' import { CreateOfflineSubscriptionToken } from '../../Domain/UseCase/CreateOfflineSubscriptionToken/CreateOfflineSubscriptionToken'
import { GetUserFeatures } from '../../Domain/UseCase/GetUserFeatures/GetUserFeatures' import { GetUserFeatures } from '../../Domain/UseCase/GetUserFeatures/GetUserFeatures'
import { GetUserOfflineSubscription } from '../../Domain/UseCase/GetUserOfflineSubscription/GetUserOfflineSubscription' import { GetUserOfflineSubscription } from '../../Domain/UseCase/GetUserOfflineSubscription/GetUserOfflineSubscription'
import { HomeServerOfflineController } from './HomeServer/HomeServerOfflineController' import { BaseOfflineController } from './Base/BaseOfflineController'
@controller('/offline') @controller('/offline')
export class InversifyExpressOfflineController extends HomeServerOfflineController { export class AnnotatedOfflineController extends BaseOfflineController {
constructor( constructor(
@inject(TYPES.Auth_GetUserFeatures) override doGetUserFeatures: GetUserFeatures, @inject(TYPES.Auth_GetUserFeatures) override doGetUserFeatures: GetUserFeatures,
@inject(TYPES.Auth_GetUserOfflineSubscription) override getUserOfflineSubscription: GetUserOfflineSubscription, @inject(TYPES.Auth_GetUserOfflineSubscription) override getUserOfflineSubscription: GetUserOfflineSubscription,
@@ -2,13 +2,13 @@ import 'reflect-metadata'
import * as express from 'express' import * as express from 'express'
import { InversifyExpressSessionController } from './InversifyExpressSessionController' import { AnnotatedSessionController } from './AnnotatedSessionController'
import { results } from 'inversify-express-utils' import { results } from 'inversify-express-utils'
import { DeletePreviousSessionsForUser } from '../../Domain/UseCase/DeletePreviousSessionsForUser' import { DeletePreviousSessionsForUser } from '../../Domain/UseCase/DeletePreviousSessionsForUser'
import { DeleteSessionForUser } from '../../Domain/UseCase/DeleteSessionForUser' import { DeleteSessionForUser } from '../../Domain/UseCase/DeleteSessionForUser'
import { RefreshSessionToken } from '../../Domain/UseCase/RefreshSessionToken' import { RefreshSessionToken } from '../../Domain/UseCase/RefreshSessionToken'
describe('InversifyExpressSessionController', () => { describe('AnnotatedSessionController', () => {
let deleteSessionForUser: DeleteSessionForUser let deleteSessionForUser: DeleteSessionForUser
let deletePreviousSessionsForUser: DeletePreviousSessionsForUser let deletePreviousSessionsForUser: DeletePreviousSessionsForUser
let refreshSessionToken: RefreshSessionToken let refreshSessionToken: RefreshSessionToken
@@ -16,7 +16,7 @@ describe('InversifyExpressSessionController', () => {
let response: express.Response let response: express.Response
const createController = () => const createController = () =>
new InversifyExpressSessionController(deleteSessionForUser, deletePreviousSessionsForUser, refreshSessionToken) new AnnotatedSessionController(deleteSessionForUser, deletePreviousSessionsForUser, refreshSessionToken)
beforeEach(() => { beforeEach(() => {
deleteSessionForUser = {} as jest.Mocked<DeleteSessionForUser> deleteSessionForUser = {} as jest.Mocked<DeleteSessionForUser>
@@ -11,10 +11,10 @@ import TYPES from '../../Bootstrap/Types'
import { DeletePreviousSessionsForUser } from '../../Domain/UseCase/DeletePreviousSessionsForUser' import { DeletePreviousSessionsForUser } from '../../Domain/UseCase/DeletePreviousSessionsForUser'
import { DeleteSessionForUser } from '../../Domain/UseCase/DeleteSessionForUser' import { DeleteSessionForUser } from '../../Domain/UseCase/DeleteSessionForUser'
import { RefreshSessionToken } from '../../Domain/UseCase/RefreshSessionToken' import { RefreshSessionToken } from '../../Domain/UseCase/RefreshSessionToken'
import { HomeServerSessionController } from './HomeServer/HomeServerSessionController' import { BaseSessionController } from './Base/BaseSessionController'
@controller('/session') @controller('/session')
export class InversifyExpressSessionController extends HomeServerSessionController { export class AnnotatedSessionController extends BaseSessionController {
constructor( constructor(
@inject(TYPES.Auth_DeleteSessionForUser) override deleteSessionForUser: DeleteSessionForUser, @inject(TYPES.Auth_DeleteSessionForUser) override deleteSessionForUser: DeleteSessionForUser,
@inject(TYPES.Auth_DeletePreviousSessionsForUser) @inject(TYPES.Auth_DeletePreviousSessionsForUser)
@@ -2,7 +2,7 @@ import 'reflect-metadata'
import * as express from 'express' import * as express from 'express'
import { InversifyExpressSessionsController } from './InversifyExpressSessionsController' import { AnnotatedSessionsController } from './AnnotatedSessionsController'
import { results } from 'inversify-express-utils' import { results } from 'inversify-express-utils'
import { User } from '@standardnotes/responses' import { User } from '@standardnotes/responses'
@@ -12,7 +12,7 @@ import { GetActiveSessionsForUser } from '../../Domain/UseCase/GetActiveSessions
import { ProjectorInterface } from '../../Projection/ProjectorInterface' import { ProjectorInterface } from '../../Projection/ProjectorInterface'
import { Session } from '../../Domain/Session/Session' import { Session } from '../../Domain/Session/Session'
describe('InversifyExpressSessionsController', () => { describe('AnnotatedSessionsController', () => {
let getActiveSessionsForUser: GetActiveSessionsForUser let getActiveSessionsForUser: GetActiveSessionsForUser
let authenticateRequest: AuthenticateRequest let authenticateRequest: AuthenticateRequest
let sessionProjector: ProjectorInterface<Session> let sessionProjector: ProjectorInterface<Session>
@@ -23,7 +23,7 @@ describe('InversifyExpressSessionsController', () => {
let createCrossServiceToken: CreateCrossServiceToken let createCrossServiceToken: CreateCrossServiceToken
const createController = () => const createController = () =>
new InversifyExpressSessionsController( new AnnotatedSessionsController(
getActiveSessionsForUser, getActiveSessionsForUser,
authenticateRequest, authenticateRequest,
sessionProjector, sessionProjector,
@@ -14,10 +14,10 @@ import { CreateCrossServiceToken } from '../../Domain/UseCase/CreateCrossService
import { GetActiveSessionsForUser } from '../../Domain/UseCase/GetActiveSessionsForUser' import { GetActiveSessionsForUser } from '../../Domain/UseCase/GetActiveSessionsForUser'
import { ProjectorInterface } from '../../Projection/ProjectorInterface' import { ProjectorInterface } from '../../Projection/ProjectorInterface'
import { Session } from '../../Domain/Session/Session' import { Session } from '../../Domain/Session/Session'
import { HomeServerSessionsController } from './HomeServer/HomeServerSessionsController' import { BaseSessionsController } from './Base/BaseSessionsController'
@controller('/sessions') @controller('/sessions')
export class InversifyExpressSessionsController extends HomeServerSessionsController { export class AnnotatedSessionsController extends BaseSessionsController {
constructor( constructor(
@inject(TYPES.Auth_GetActiveSessionsForUser) override getActiveSessionsForUser: GetActiveSessionsForUser, @inject(TYPES.Auth_GetActiveSessionsForUser) override getActiveSessionsForUser: GetActiveSessionsForUser,
@inject(TYPES.Auth_AuthenticateRequest) override authenticateRequest: AuthenticateRequest, @inject(TYPES.Auth_AuthenticateRequest) override authenticateRequest: AuthenticateRequest,
@@ -2,7 +2,7 @@ import 'reflect-metadata'
import * as express from 'express' import * as express from 'express'
import { InversifyExpressSettingsController } from './InversifyExpressSettingsController' import { AnnotatedSettingsController } from './AnnotatedSettingsController'
import { results } from 'inversify-express-utils' import { results } from 'inversify-express-utils'
import { EncryptionVersion } from '../../Domain/Encryption/EncryptionVersion' import { EncryptionVersion } from '../../Domain/Encryption/EncryptionVersion'
import { DeleteSetting } from '../../Domain/UseCase/DeleteSetting/DeleteSetting' import { DeleteSetting } from '../../Domain/UseCase/DeleteSetting/DeleteSetting'
@@ -11,7 +11,7 @@ import { GetSettings } from '../../Domain/UseCase/GetSettings/GetSettings'
import { UpdateSetting } from '../../Domain/UseCase/UpdateSetting/UpdateSetting' import { UpdateSetting } from '../../Domain/UseCase/UpdateSetting/UpdateSetting'
import { User } from '../../Domain/User/User' import { User } from '../../Domain/User/User'
describe('InversifyExpressSettingsController', () => { describe('AnnotatedSettingsController', () => {
let deleteSetting: DeleteSetting let deleteSetting: DeleteSetting
let getSettings: GetSettings let getSettings: GetSettings
let getSetting: GetSetting let getSetting: GetSetting
@@ -21,8 +21,7 @@ describe('InversifyExpressSettingsController', () => {
let response: express.Response let response: express.Response
let user: User let user: User
const createController = () => const createController = () => new AnnotatedSettingsController(getSettings, getSetting, updateSetting, deleteSetting)
new InversifyExpressSettingsController(getSettings, getSetting, updateSetting, deleteSetting)
beforeEach(() => { beforeEach(() => {
deleteSetting = {} as jest.Mocked<DeleteSetting> deleteSetting = {} as jest.Mocked<DeleteSetting>
@@ -13,10 +13,10 @@ import { DeleteSetting } from '../../Domain/UseCase/DeleteSetting/DeleteSetting'
import { GetSetting } from '../../Domain/UseCase/GetSetting/GetSetting' import { GetSetting } from '../../Domain/UseCase/GetSetting/GetSetting'
import { GetSettings } from '../../Domain/UseCase/GetSettings/GetSettings' import { GetSettings } from '../../Domain/UseCase/GetSettings/GetSettings'
import { UpdateSetting } from '../../Domain/UseCase/UpdateSetting/UpdateSetting' import { UpdateSetting } from '../../Domain/UseCase/UpdateSetting/UpdateSetting'
import { HomeServerSettingsController } from './HomeServer/HomeServerSettingsController' import { BaseSettingsController } from './Base/BaseSettingsController'
@controller('/users/:userUuid') @controller('/users/:userUuid')
export class InversifyExpressSettingsController extends HomeServerSettingsController { export class AnnotatedSettingsController extends BaseSettingsController {
constructor( constructor(
@inject(TYPES.Auth_GetSettings) override doGetSettings: GetSettings, @inject(TYPES.Auth_GetSettings) override doGetSettings: GetSettings,
@inject(TYPES.Auth_GetSetting) override doGetSetting: GetSetting, @inject(TYPES.Auth_GetSetting) override doGetSetting: GetSetting,
@@ -11,10 +11,10 @@ import { inject } from 'inversify'
import TYPES from '../../Bootstrap/Types' import TYPES from '../../Bootstrap/Types'
import { SubscriptionInvitesController } from '../../Controller/SubscriptionInvitesController' import { SubscriptionInvitesController } from '../../Controller/SubscriptionInvitesController'
import { HomeServerSubscriptionInvitesController } from './HomeServer/HomeServerSubscriptionInvitesController' import { BaseSubscriptionInvitesController } from './Base/BaseSubscriptionInvitesController'
@controller('/subscription-invites') @controller('/subscription-invites')
export class InversifyExpressSubscriptionInvitesController extends HomeServerSubscriptionInvitesController { export class AnnotatedSubscriptionInvitesController extends BaseSubscriptionInvitesController {
constructor( constructor(
@inject(TYPES.Auth_SubscriptionInvitesController) @inject(TYPES.Auth_SubscriptionInvitesController)
override subscriptionInvitesController: SubscriptionInvitesController, override subscriptionInvitesController: SubscriptionInvitesController,
@@ -3,18 +3,18 @@ import 'reflect-metadata'
import * as express from 'express' import * as express from 'express'
import { results } from 'inversify-express-utils' import { results } from 'inversify-express-utils'
import { InversifyExpressSubscriptionSettingsController } from './InversifyExpressSubscriptionSettingsController' import { AnnotatedSubscriptionSettingsController } from './AnnotatedSubscriptionSettingsController'
import { User } from '../../Domain/User/User' import { User } from '../../Domain/User/User'
import { GetSetting } from '../../Domain/UseCase/GetSetting/GetSetting' import { GetSetting } from '../../Domain/UseCase/GetSetting/GetSetting'
describe('InversifyExpressSubscriptionSettingsController', () => { describe('AnnotatedSubscriptionSettingsController', () => {
let getSetting: GetSetting let getSetting: GetSetting
let request: express.Request let request: express.Request
let response: express.Response let response: express.Response
let user: User let user: User
const createController = () => new InversifyExpressSubscriptionSettingsController(getSetting) const createController = () => new AnnotatedSubscriptionSettingsController(getSetting)
beforeEach(() => { beforeEach(() => {
user = {} as jest.Mocked<User> user = {} as jest.Mocked<User>

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