mirror of
https://github.com/standardnotes/server
synced 2026-04-02 06:01:12 -04:00
Compare commits
17 Commits
@standardn
...
@standardn
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4b8a9e448a | ||
|
|
1e4c7d0f31 | ||
|
|
ec75795a02 | ||
|
|
ad26b64b28 | ||
|
|
9e4715ebbd | ||
|
|
cc612296d0 | ||
|
|
1148b3948c | ||
|
|
c7e605fd60 | ||
|
|
4ab32c670e | ||
|
|
2d810568a8 | ||
|
|
b8353aa817 | ||
|
|
7924f63e28 | ||
|
|
b3b617ea0b | ||
|
|
18a5071618 | ||
|
|
fea58029b9 | ||
|
|
e748723209 | ||
|
|
8a47d81936 |
4
.github/workflows/common-e2e.yml
vendored
4
.github/workflows/common-e2e.yml
vendored
@@ -83,6 +83,8 @@ jobs:
|
|||||||
sed -i "s/AUTH_JWT_SECRET=/AUTH_JWT_SECRET=$(openssl rand -hex 32)/g" packages/home-server/.env
|
sed -i "s/AUTH_JWT_SECRET=/AUTH_JWT_SECRET=$(openssl rand -hex 32)/g" packages/home-server/.env
|
||||||
sed -i "s/ENCRYPTION_SERVER_KEY=/ENCRYPTION_SERVER_KEY=$(openssl rand -hex 32)/g" packages/home-server/.env
|
sed -i "s/ENCRYPTION_SERVER_KEY=/ENCRYPTION_SERVER_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/PSEUDO_KEY_PARAMS_KEY=/PSEUDO_KEY_PARAMS_KEY=$(openssl rand -hex 32)/g" packages/home-server/.env
|
||||||
|
echo "ACCESS_TOKEN_AGE=4" >> packages/home-server/.env
|
||||||
|
echo "REFRESH_TOKEN_AGE=7" >> 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 &
|
||||||
@@ -94,4 +96,4 @@ jobs:
|
|||||||
|
|
||||||
- name: Run E2E Test Suite
|
- name: Run E2E Test Suite
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
run: yarn dlx mocha-headless-chrome --timeout 1200000 -f http://localhost:9001/mocha/test.html
|
run: yarn dlx mocha-headless-chrome --timeout 1200000 -f http://localhost:9001/mocha/test.html?skip_paid_features=true
|
||||||
|
|||||||
24
.pnp.cjs
generated
24
.pnp.cjs
generated
@@ -4625,6 +4625,8 @@ const RAW_RUNTIME_STATE =
|
|||||||
["@standardnotes/api-gateway", "workspace:packages/api-gateway"],\
|
["@standardnotes/api-gateway", "workspace:packages/api-gateway"],\
|
||||||
["@standardnotes/auth-server", "workspace:packages/auth"],\
|
["@standardnotes/auth-server", "workspace:packages/auth"],\
|
||||||
["@standardnotes/domain-core", "workspace:packages/domain-core"],\
|
["@standardnotes/domain-core", "workspace:packages/domain-core"],\
|
||||||
|
["@standardnotes/domain-events-infra", "workspace:packages/domain-events-infra"],\
|
||||||
|
["@standardnotes/syncing-server", "workspace:packages/syncing-server"],\
|
||||||
["@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/prettyjson", "npm:0.0.30"],\
|
["@types/prettyjson", "npm:0.0.30"],\
|
||||||
@@ -4712,7 +4714,6 @@ const RAW_RUNTIME_STATE =
|
|||||||
["@types/cors", "npm:2.8.13"],\
|
["@types/cors", "npm:2.8.13"],\
|
||||||
["@types/dotenv", "npm:8.2.0"],\
|
["@types/dotenv", "npm:8.2.0"],\
|
||||||
["@types/express", "npm:4.17.17"],\
|
["@types/express", "npm:4.17.17"],\
|
||||||
["@types/inversify-express-utils", "npm:2.0.0"],\
|
|
||||||
["@types/jest", "npm:29.5.1"],\
|
["@types/jest", "npm:29.5.1"],\
|
||||||
["@types/newrelic", "npm:9.13.0"],\
|
["@types/newrelic", "npm:9.13.0"],\
|
||||||
["@typescript-eslint/eslint-plugin", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:5.59.2"],\
|
["@typescript-eslint/eslint-plugin", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:5.59.2"],\
|
||||||
@@ -4732,7 +4733,7 @@ const RAW_RUNTIME_STATE =
|
|||||||
["reflect-metadata", "npm:0.1.13"],\
|
["reflect-metadata", "npm:0.1.13"],\
|
||||||
["sqlite3", "virtual:31b5a94a105c89c9294c3d524a7f8929fe63ee5a2efadf21951ca4c0cfd2ecf02e8f4ef5a066bbda091f1e3a56e57c6749069a080618c96b22e51131a330fc4a#npm:5.1.6"],\
|
["sqlite3", "virtual:31b5a94a105c89c9294c3d524a7f8929fe63ee5a2efadf21951ca4c0cfd2ecf02e8f4ef5a066bbda091f1e3a56e57c6749069a080618c96b22e51131a330fc4a#npm:5.1.6"],\
|
||||||
["ts-jest", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:29.1.0"],\
|
["ts-jest", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:29.1.0"],\
|
||||||
["typeorm", "virtual:365b8c88cdf194291829ee28b79556e2328175d26a621363e703848100bea0042e9500db2a1206c9bbc3a4a76a1d169639ef774b2ea3a1a98584a9936b58c6be#npm:0.3.15"],\
|
["typeorm", "virtual:67ad3a1ca34e24ce4821cc48979e98af0c3e5dd7aabc7ad0b5d22d1d977d6f943f81c9f141a420105ebdc61ef777e508a96c7946081decd98f8c30543d468b33#npm:0.3.15"],\
|
||||||
["typescript", "patch:typescript@npm%3A5.0.4#optional!builtin<compat/typescript>::version=5.0.4&hash=b5f058"],\
|
["typescript", "patch:typescript@npm%3A5.0.4#optional!builtin<compat/typescript>::version=5.0.4&hash=b5f058"],\
|
||||||
["winston", "npm:3.8.2"]\
|
["winston", "npm:3.8.2"]\
|
||||||
],\
|
],\
|
||||||
@@ -4896,7 +4897,6 @@ const RAW_RUNTIME_STATE =
|
|||||||
["@types/cors", "npm:2.8.13"],\
|
["@types/cors", "npm:2.8.13"],\
|
||||||
["@types/dotenv", "npm:8.2.0"],\
|
["@types/dotenv", "npm:8.2.0"],\
|
||||||
["@types/express", "npm:4.17.17"],\
|
["@types/express", "npm:4.17.17"],\
|
||||||
["@types/inversify-express-utils", "npm:2.0.0"],\
|
|
||||||
["@types/jest", "npm:29.5.1"],\
|
["@types/jest", "npm:29.5.1"],\
|
||||||
["@types/jsonwebtoken", "npm:9.0.2"],\
|
["@types/jsonwebtoken", "npm:9.0.2"],\
|
||||||
["@types/newrelic", "npm:9.13.0"],\
|
["@types/newrelic", "npm:9.13.0"],\
|
||||||
@@ -4925,7 +4925,7 @@ const RAW_RUNTIME_STATE =
|
|||||||
["reflect-metadata", "npm:0.1.13"],\
|
["reflect-metadata", "npm:0.1.13"],\
|
||||||
["sqlite3", "virtual:31b5a94a105c89c9294c3d524a7f8929fe63ee5a2efadf21951ca4c0cfd2ecf02e8f4ef5a066bbda091f1e3a56e57c6749069a080618c96b22e51131a330fc4a#npm:5.1.6"],\
|
["sqlite3", "virtual:31b5a94a105c89c9294c3d524a7f8929fe63ee5a2efadf21951ca4c0cfd2ecf02e8f4ef5a066bbda091f1e3a56e57c6749069a080618c96b22e51131a330fc4a#npm:5.1.6"],\
|
||||||
["ts-jest", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:29.1.0"],\
|
["ts-jest", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:29.1.0"],\
|
||||||
["typeorm", "virtual:365b8c88cdf194291829ee28b79556e2328175d26a621363e703848100bea0042e9500db2a1206c9bbc3a4a76a1d169639ef774b2ea3a1a98584a9936b58c6be#npm:0.3.15"],\
|
["typeorm", "virtual:67ad3a1ca34e24ce4821cc48979e98af0c3e5dd7aabc7ad0b5d22d1d977d6f943f81c9f141a420105ebdc61ef777e508a96c7946081decd98f8c30543d468b33#npm:0.3.15"],\
|
||||||
["typescript", "patch:typescript@npm%3A5.0.4#optional!builtin<compat/typescript>::version=5.0.4&hash=b5f058"],\
|
["typescript", "patch:typescript@npm%3A5.0.4#optional!builtin<compat/typescript>::version=5.0.4&hash=b5f058"],\
|
||||||
["ua-parser-js", "npm:1.0.35"],\
|
["ua-parser-js", "npm:1.0.35"],\
|
||||||
["uuid", "npm:9.0.0"],\
|
["uuid", "npm:9.0.0"],\
|
||||||
@@ -5298,16 +5298,6 @@ const RAW_RUNTIME_STATE =
|
|||||||
"linkType": "HARD"\
|
"linkType": "HARD"\
|
||||||
}]\
|
}]\
|
||||||
]],\
|
]],\
|
||||||
["@types/inversify-express-utils", [\
|
|
||||||
["npm:2.0.0", {\
|
|
||||||
"packageLocation": "./.yarn/cache/@types-inversify-express-utils-npm-2.0.0-e78182955d-9841bfddff.zip/node_modules/@types/inversify-express-utils/",\
|
|
||||||
"packageDependencies": [\
|
|
||||||
["@types/inversify-express-utils", "npm:2.0.0"],\
|
|
||||||
["inversify-express-utils", "npm:6.4.3"]\
|
|
||||||
],\
|
|
||||||
"linkType": "HARD"\
|
|
||||||
}]\
|
|
||||||
]],\
|
|
||||||
["@types/ioredis", [\
|
["@types/ioredis", [\
|
||||||
["npm:5.0.0", {\
|
["npm:5.0.0", {\
|
||||||
"packageLocation": "./.yarn/cache/@types-ioredis-npm-5.0.0-6efa70abfa-439770c9da.zip/node_modules/@types/ioredis/",\
|
"packageLocation": "./.yarn/cache/@types-ioredis-npm-5.0.0-6efa70abfa-439770c9da.zip/node_modules/@types/ioredis/",\
|
||||||
@@ -15176,10 +15166,10 @@ const RAW_RUNTIME_STATE =
|
|||||||
],\
|
],\
|
||||||
"linkType": "HARD"\
|
"linkType": "HARD"\
|
||||||
}],\
|
}],\
|
||||||
["virtual:365b8c88cdf194291829ee28b79556e2328175d26a621363e703848100bea0042e9500db2a1206c9bbc3a4a76a1d169639ef774b2ea3a1a98584a9936b58c6be#npm:0.3.15", {\
|
["virtual:67ad3a1ca34e24ce4821cc48979e98af0c3e5dd7aabc7ad0b5d22d1d977d6f943f81c9f141a420105ebdc61ef777e508a96c7946081decd98f8c30543d468b33#npm:0.3.15", {\
|
||||||
"packageLocation": "./.yarn/__virtual__/typeorm-virtual-7fe891193c/0/cache/typeorm-npm-0.3.15-20a6c4f754-db890f14cb.zip/node_modules/typeorm/",\
|
"packageLocation": "./.yarn/__virtual__/typeorm-virtual-91f15b21d5/0/cache/typeorm-npm-0.3.15-20a6c4f754-db890f14cb.zip/node_modules/typeorm/",\
|
||||||
"packageDependencies": [\
|
"packageDependencies": [\
|
||||||
["typeorm", "virtual:365b8c88cdf194291829ee28b79556e2328175d26a621363e703848100bea0042e9500db2a1206c9bbc3a4a76a1d169639ef774b2ea3a1a98584a9936b58c6be#npm:0.3.15"],\
|
["typeorm", "virtual:67ad3a1ca34e24ce4821cc48979e98af0c3e5dd7aabc7ad0b5d22d1d977d6f943f81c9f141a420105ebdc61ef777e508a96c7946081decd98f8c30543d468b33#npm:0.3.15"],\
|
||||||
["@google-cloud/spanner", null],\
|
["@google-cloud/spanner", null],\
|
||||||
["@sap/hana-client", null],\
|
["@sap/hana-client", null],\
|
||||||
["@sqltools/formatter", "npm:1.2.5"],\
|
["@sqltools/formatter", "npm:1.2.5"],\
|
||||||
|
|||||||
Binary file not shown.
@@ -3,6 +3,10 @@
|
|||||||
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.22.4](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.22.3...@standardnotes/analytics@2.22.4) (2023-05-17)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/analytics
|
||||||
|
|
||||||
## [2.22.3](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.22.2...@standardnotes/analytics@2.22.3) (2023-05-16)
|
## [2.22.3](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.22.2...@standardnotes/analytics@2.22.3) (2023-05-16)
|
||||||
|
|
||||||
**Note:** Version bump only for package @standardnotes/analytics
|
**Note:** Version bump only for package @standardnotes/analytics
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/analytics",
|
"name": "@standardnotes/analytics",
|
||||||
"version": "2.22.3",
|
"version": "2.22.4",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.0.0 <21.0.0"
|
"node": ">=18.0.0 <21.0.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,6 +3,35 @@
|
|||||||
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.57.0](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.56.2...@standardnotes/api-gateway@1.57.0) (2023-05-25)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* refactor auth middleware to handle required and optional cross service token scenarios ([#612](https://github.com/standardnotes/api-gateway/issues/612)) ([1e4c7d0](https://github.com/standardnotes/api-gateway/commit/1e4c7d0f317d5c2d98065da12ffeb950b10ee5dc))
|
||||||
|
|
||||||
|
## [1.56.2](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.56.1...@standardnotes/api-gateway@1.56.2) (2023-05-18)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **api-gateway:** decorating responses for direct call proxy ([4ab32c6](https://github.com/standardnotes/api-gateway/commit/4ab32c670eedcfc64611a191bc25566d43372b23))
|
||||||
|
* **api-gateway:** pkce endpoints resolution for direct code calls ([c7e605f](https://github.com/standardnotes/api-gateway/commit/c7e605fd6046e8476c493658c6feaed365e82e5d))
|
||||||
|
|
||||||
|
## [1.56.1](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.56.0...@standardnotes/api-gateway@1.56.1) (2023-05-18)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||||
|
|
||||||
|
# [1.56.0](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.55.0...@standardnotes/api-gateway@1.56.0) (2023-05-17)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* bundle syncing server into home server setup ([#611](https://github.com/standardnotes/api-gateway/issues/611)) ([b3b617e](https://github.com/standardnotes/api-gateway/commit/b3b617ea0b4f4574f6aa7cfae0e9fa8f868f1f4c))
|
||||||
|
|
||||||
|
# [1.55.0](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.54.0...@standardnotes/api-gateway@1.55.0) (2023-05-17)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add direct event handling for home server ([#608](https://github.com/standardnotes/api-gateway/issues/608)) ([8a47d81](https://github.com/standardnotes/api-gateway/commit/8a47d81936acd765224e74fd083810579a83c9a7))
|
||||||
|
|
||||||
# [1.54.0](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.53.1...@standardnotes/api-gateway@1.54.0) (2023-05-16)
|
# [1.54.0](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.53.1...@standardnotes/api-gateway@1.54.0) (2023-05-16)
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/api-gateway",
|
"name": "@standardnotes/api-gateway",
|
||||||
"version": "1.54.0",
|
"version": "1.57.0",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.0.0 <21.0.0"
|
"node": ">=18.0.0 <21.0.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import { Timer, TimerInterface } from '@standardnotes/time'
|
|||||||
|
|
||||||
import { Env } from './Env'
|
import { Env } from './Env'
|
||||||
import { TYPES } from './Types'
|
import { TYPES } from './Types'
|
||||||
import { AuthMiddleware } from '../Controller/AuthMiddleware'
|
|
||||||
import { ServiceProxyInterface } from '../Service/Http/ServiceProxyInterface'
|
import { ServiceProxyInterface } from '../Service/Http/ServiceProxyInterface'
|
||||||
import { HttpServiceProxy } from '../Service/Http/HttpServiceProxy'
|
import { HttpServiceProxy } from '../Service/Http/HttpServiceProxy'
|
||||||
import { SubscriptionTokenAuthMiddleware } from '../Controller/SubscriptionTokenAuthMiddleware'
|
import { SubscriptionTokenAuthMiddleware } from '../Controller/SubscriptionTokenAuthMiddleware'
|
||||||
@@ -20,6 +19,8 @@ import { DirectCallServiceProxy } from '../Service/Proxy/DirectCallServiceProxy'
|
|||||||
import { ServiceContainerInterface } from '@standardnotes/domain-core'
|
import { ServiceContainerInterface } from '@standardnotes/domain-core'
|
||||||
import { EndpointResolverInterface } from '../Service/Resolver/EndpointResolverInterface'
|
import { EndpointResolverInterface } from '../Service/Resolver/EndpointResolverInterface'
|
||||||
import { EndpointResolver } from '../Service/Resolver/EndpointResolver'
|
import { EndpointResolver } from '../Service/Resolver/EndpointResolver'
|
||||||
|
import { RequiredCrossServiceTokenMiddleware } from '../Controller/RequiredCrossServiceTokenMiddleware'
|
||||||
|
import { OptionalCrossServiceTokenMiddleware } from '../Controller/OptionalCrossServiceTokenMiddleware'
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||||
const newrelicFormatter = require('@newrelic/winston-enricher')
|
const newrelicFormatter = require('@newrelic/winston-enricher')
|
||||||
@@ -43,6 +44,7 @@ export class ContainerConfigLoader {
|
|||||||
level: env.get('LOG_LEVEL') || 'info',
|
level: env.get('LOG_LEVEL') || 'info',
|
||||||
format: winston.format.combine(...winstonFormatters),
|
format: winston.format.combine(...winstonFormatters),
|
||||||
transports: [new winston.transports.Console({ level: env.get('LOG_LEVEL') || 'info' })],
|
transports: [new winston.transports.Console({ level: env.get('LOG_LEVEL') || 'info' })],
|
||||||
|
defaultMeta: { service: 'api-gateway' },
|
||||||
})
|
})
|
||||||
container.bind<winston.Logger>(TYPES.Logger).toConstantValue(logger)
|
container.bind<winston.Logger>(TYPES.Logger).toConstantValue(logger)
|
||||||
|
|
||||||
@@ -76,7 +78,12 @@ export class ContainerConfigLoader {
|
|||||||
container.bind(TYPES.CROSS_SERVICE_TOKEN_CACHE_TTL).toConstantValue(+env.get('CROSS_SERVICE_TOKEN_CACHE_TTL', true))
|
container.bind(TYPES.CROSS_SERVICE_TOKEN_CACHE_TTL).toConstantValue(+env.get('CROSS_SERVICE_TOKEN_CACHE_TTL', true))
|
||||||
|
|
||||||
// Middleware
|
// Middleware
|
||||||
container.bind<AuthMiddleware>(TYPES.AuthMiddleware).to(AuthMiddleware)
|
container
|
||||||
|
.bind<RequiredCrossServiceTokenMiddleware>(TYPES.RequiredCrossServiceTokenMiddleware)
|
||||||
|
.to(RequiredCrossServiceTokenMiddleware)
|
||||||
|
container
|
||||||
|
.bind<OptionalCrossServiceTokenMiddleware>(TYPES.OptionalCrossServiceTokenMiddleware)
|
||||||
|
.to(OptionalCrossServiceTokenMiddleware)
|
||||||
container.bind<WebSocketAuthMiddleware>(TYPES.WebSocketAuthMiddleware).to(WebSocketAuthMiddleware)
|
container.bind<WebSocketAuthMiddleware>(TYPES.WebSocketAuthMiddleware).to(WebSocketAuthMiddleware)
|
||||||
container
|
container
|
||||||
.bind<SubscriptionTokenAuthMiddleware>(TYPES.SubscriptionTokenAuthMiddleware)
|
.bind<SubscriptionTokenAuthMiddleware>(TYPES.SubscriptionTokenAuthMiddleware)
|
||||||
@@ -89,7 +96,7 @@ export class ContainerConfigLoader {
|
|||||||
}
|
}
|
||||||
container
|
container
|
||||||
.bind<ServiceProxyInterface>(TYPES.ServiceProxy)
|
.bind<ServiceProxyInterface>(TYPES.ServiceProxy)
|
||||||
.toConstantValue(new DirectCallServiceProxy(serviceContainer))
|
.toConstantValue(new DirectCallServiceProxy(serviceContainer, container.get(TYPES.FILES_SERVER_URL)))
|
||||||
} else {
|
} else {
|
||||||
container.bind<ServiceProxyInterface>(TYPES.ServiceProxy).to(HttpServiceProxy)
|
container.bind<ServiceProxyInterface>(TYPES.ServiceProxy).to(HttpServiceProxy)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,28 +1,14 @@
|
|||||||
import {
|
import { ServiceContainerInterface, ServiceIdentifier, ServiceInterface } from '@standardnotes/domain-core'
|
||||||
ControllerContainerInterface,
|
|
||||||
ServiceContainerInterface,
|
|
||||||
ServiceIdentifier,
|
|
||||||
ServiceInterface,
|
|
||||||
} from '@standardnotes/domain-core'
|
|
||||||
|
|
||||||
import { ContainerConfigLoader } from './Container'
|
import { ContainerConfigLoader } from './Container'
|
||||||
|
|
||||||
export class Service implements ServiceInterface {
|
export class Service implements ServiceInterface {
|
||||||
constructor(
|
constructor(private serviceContainer: ServiceContainerInterface) {
|
||||||
private serviceContainer: ServiceContainerInterface,
|
this.serviceContainer.register(this.getId(), this)
|
||||||
private controllerContainer: ControllerContainerInterface,
|
|
||||||
) {
|
|
||||||
this.serviceContainer.register(ServiceIdentifier.create(ServiceIdentifier.NAMES.ApiGateway).getValue(), this)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async handleRequest(request: never, response: never, endpointOrMethodIdentifier: string): Promise<unknown> {
|
async handleRequest(_request: never, _response: never, _endpointOrMethodIdentifier: string): Promise<unknown> {
|
||||||
const method = this.controllerContainer.get(endpointOrMethodIdentifier)
|
throw new Error('Requests are handled via inversify-express at ApiGateway level')
|
||||||
|
|
||||||
if (!method) {
|
|
||||||
throw new Error(`Method ${endpointOrMethodIdentifier} not found`)
|
|
||||||
}
|
|
||||||
|
|
||||||
return method(request, response)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async getContainer(): Promise<unknown> {
|
async getContainer(): Promise<unknown> {
|
||||||
|
|||||||
@@ -15,7 +15,8 @@ export const TYPES = {
|
|||||||
VERSION: Symbol.for('VERSION'),
|
VERSION: Symbol.for('VERSION'),
|
||||||
CROSS_SERVICE_TOKEN_CACHE_TTL: Symbol.for('CROSS_SERVICE_TOKEN_CACHE_TTL'),
|
CROSS_SERVICE_TOKEN_CACHE_TTL: Symbol.for('CROSS_SERVICE_TOKEN_CACHE_TTL'),
|
||||||
// Middleware
|
// Middleware
|
||||||
AuthMiddleware: Symbol.for('AuthMiddleware'),
|
RequiredCrossServiceTokenMiddleware: Symbol.for('RequiredCrossServiceTokenMiddleware'),
|
||||||
|
OptionalCrossServiceTokenMiddleware: Symbol.for('OptionalCrossServiceTokenMiddleware'),
|
||||||
WebSocketAuthMiddleware: Symbol.for('WebSocketAuthMiddleware'),
|
WebSocketAuthMiddleware: Symbol.for('WebSocketAuthMiddleware'),
|
||||||
SubscriptionTokenAuthMiddleware: Symbol.for('SubscriptionTokenAuthMiddleware'),
|
SubscriptionTokenAuthMiddleware: Symbol.for('SubscriptionTokenAuthMiddleware'),
|
||||||
// Services
|
// Services
|
||||||
|
|||||||
@@ -2,43 +2,33 @@ import { CrossServiceTokenData } from '@standardnotes/security'
|
|||||||
import { RoleName } from '@standardnotes/domain-core'
|
import { RoleName } from '@standardnotes/domain-core'
|
||||||
import { TimerInterface } from '@standardnotes/time'
|
import { TimerInterface } from '@standardnotes/time'
|
||||||
import { NextFunction, Request, Response } from 'express'
|
import { NextFunction, Request, Response } from 'express'
|
||||||
import { inject, injectable } from 'inversify'
|
|
||||||
import { BaseMiddleware } from 'inversify-express-utils'
|
import { BaseMiddleware } from 'inversify-express-utils'
|
||||||
import { verify } from 'jsonwebtoken'
|
import { verify } from 'jsonwebtoken'
|
||||||
import { AxiosError, AxiosInstance } from 'axios'
|
import { AxiosError } from 'axios'
|
||||||
import { Logger } from 'winston'
|
import { Logger } from 'winston'
|
||||||
|
|
||||||
import { TYPES } from '../Bootstrap/Types'
|
|
||||||
import { CrossServiceTokenCacheInterface } from '../Service/Cache/CrossServiceTokenCacheInterface'
|
import { CrossServiceTokenCacheInterface } from '../Service/Cache/CrossServiceTokenCacheInterface'
|
||||||
|
import { ServiceProxyInterface } from '../Service/Http/ServiceProxyInterface'
|
||||||
|
|
||||||
@injectable()
|
export abstract class AuthMiddleware extends BaseMiddleware {
|
||||||
export class AuthMiddleware extends BaseMiddleware {
|
|
||||||
constructor(
|
constructor(
|
||||||
@inject(TYPES.HTTPClient) private httpClient: AxiosInstance,
|
private serviceProxy: ServiceProxyInterface,
|
||||||
@inject(TYPES.AUTH_SERVER_URL) private authServerUrl: string,
|
private jwtSecret: string,
|
||||||
@inject(TYPES.AUTH_JWT_SECRET) private jwtSecret: string,
|
private crossServiceTokenCacheTTL: number,
|
||||||
@inject(TYPES.CROSS_SERVICE_TOKEN_CACHE_TTL) private crossServiceTokenCacheTTL: number,
|
private crossServiceTokenCache: CrossServiceTokenCacheInterface,
|
||||||
@inject(TYPES.CrossServiceTokenCache) private crossServiceTokenCache: CrossServiceTokenCacheInterface,
|
private timer: TimerInterface,
|
||||||
@inject(TYPES.Timer) private timer: TimerInterface,
|
private logger: Logger,
|
||||||
@inject(TYPES.Logger) private logger: Logger,
|
|
||||||
) {
|
) {
|
||||||
super()
|
super()
|
||||||
}
|
}
|
||||||
|
|
||||||
async handler(request: Request, response: Response, next: NextFunction): Promise<void> {
|
async handler(request: Request, response: Response, next: NextFunction): Promise<void> {
|
||||||
const authHeaderValue = request.headers.authorization as string
|
if (!this.handleMissingAuthHeader(request.headers.authorization, response, next)) {
|
||||||
|
|
||||||
if (!authHeaderValue) {
|
|
||||||
response.status(401).send({
|
|
||||||
error: {
|
|
||||||
tag: 'invalid-auth',
|
|
||||||
message: 'Invalid login credentials.',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const authHeaderValue = request.headers.authorization as string
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let crossServiceTokenFetchedFromCache = true
|
let crossServiceTokenFetchedFromCache = true
|
||||||
let crossServiceToken = null
|
let crossServiceToken = null
|
||||||
@@ -47,26 +37,13 @@ export class AuthMiddleware extends BaseMiddleware {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (crossServiceToken === null) {
|
if (crossServiceToken === null) {
|
||||||
const authResponse = await this.httpClient.request({
|
const authResponse = await this.serviceProxy.validateSession(authHeaderValue)
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
Authorization: authHeaderValue,
|
|
||||||
Accept: 'application/json',
|
|
||||||
},
|
|
||||||
validateStatus: (status: number) => {
|
|
||||||
return status >= 200 && status < 500
|
|
||||||
},
|
|
||||||
url: `${this.authServerUrl}/sessions/validate`,
|
|
||||||
})
|
|
||||||
|
|
||||||
if (authResponse.status > 200) {
|
|
||||||
response.setHeader('content-type', authResponse.headers['content-type'] as string)
|
|
||||||
response.status(authResponse.status).send(authResponse.data)
|
|
||||||
|
|
||||||
|
if (!this.handleSessionValidationResponse(authResponse, response, next)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
crossServiceToken = authResponse.data.authToken
|
crossServiceToken = (authResponse.data as { authToken: string }).authToken
|
||||||
crossServiceTokenFetchedFromCache = false
|
crossServiceTokenFetchedFromCache = false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,16 +64,15 @@ export class AuthMiddleware extends BaseMiddleware {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
response.locals.userUuid = decodedToken.user.uuid
|
response.locals.user = decodedToken.user
|
||||||
|
response.locals.session = decodedToken.session
|
||||||
response.locals.roles = decodedToken.roles
|
response.locals.roles = decodedToken.roles
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const errorMessage = (error as AxiosError).isAxiosError
|
const errorMessage = (error as AxiosError).isAxiosError
|
||||||
? JSON.stringify((error as AxiosError).response?.data)
|
? JSON.stringify((error as AxiosError).response?.data)
|
||||||
: (error as Error).message
|
: (error as Error).message
|
||||||
|
|
||||||
this.logger.error(
|
this.logger.error(`Could not pass the request to sessions/validate on underlying service: ${errorMessage}`)
|
||||||
`Could not pass the request to ${this.authServerUrl}/sessions/validate on underlying service: ${errorMessage}`,
|
|
||||||
)
|
|
||||||
|
|
||||||
this.logger.debug('Response error: %O', (error as AxiosError).response ?? error)
|
this.logger.debug('Response error: %O', (error as AxiosError).response ?? error)
|
||||||
|
|
||||||
@@ -117,6 +93,24 @@ export class AuthMiddleware extends BaseMiddleware {
|
|||||||
return next()
|
return next()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected abstract handleSessionValidationResponse(
|
||||||
|
authResponse: {
|
||||||
|
status: number
|
||||||
|
data: unknown
|
||||||
|
headers: {
|
||||||
|
contentType: string
|
||||||
|
}
|
||||||
|
},
|
||||||
|
response: Response,
|
||||||
|
next: NextFunction,
|
||||||
|
): boolean
|
||||||
|
|
||||||
|
protected abstract handleMissingAuthHeader(
|
||||||
|
authHeaderValue: string | undefined,
|
||||||
|
response: Response,
|
||||||
|
next: NextFunction,
|
||||||
|
): boolean
|
||||||
|
|
||||||
private getCrossServiceTokenCacheExpireTimestamp(token: CrossServiceTokenData): number {
|
private getCrossServiceTokenCacheExpireTimestamp(token: CrossServiceTokenData): number {
|
||||||
const crossServiceTokenDefaultCacheExpiration = this.timer.getTimestampInSeconds() + this.crossServiceTokenCacheTTL
|
const crossServiceTokenDefaultCacheExpiration = this.timer.getTimestampInSeconds() + this.crossServiceTokenCacheTTL
|
||||||
|
|
||||||
|
|||||||
@@ -29,17 +29,17 @@ export class LegacyController extends BaseHttpController {
|
|||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
@httpPost('/items/sync', TYPES.AuthMiddleware)
|
@httpPost('/items/sync', TYPES.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.AuthMiddleware)
|
@httpGet('/items/:item_id/revisions', TYPES.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.AuthMiddleware)
|
@httpGet('/items/:item_id/revisions/:id', TYPES.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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
import { TimerInterface } from '@standardnotes/time'
|
||||||
|
import { NextFunction, Response } from 'express'
|
||||||
|
import { inject, injectable } from 'inversify'
|
||||||
|
import { Logger } from 'winston'
|
||||||
|
|
||||||
|
import { TYPES } from '../Bootstrap/Types'
|
||||||
|
import { CrossServiceTokenCacheInterface } from '../Service/Cache/CrossServiceTokenCacheInterface'
|
||||||
|
import { ServiceProxyInterface } from '../Service/Http/ServiceProxyInterface'
|
||||||
|
import { AuthMiddleware } from './AuthMiddleware'
|
||||||
|
|
||||||
|
@injectable()
|
||||||
|
export class OptionalCrossServiceTokenMiddleware extends AuthMiddleware {
|
||||||
|
constructor(
|
||||||
|
@inject(TYPES.ServiceProxy) serviceProxy: ServiceProxyInterface,
|
||||||
|
@inject(TYPES.AUTH_JWT_SECRET) jwtSecret: string,
|
||||||
|
@inject(TYPES.CROSS_SERVICE_TOKEN_CACHE_TTL) crossServiceTokenCacheTTL: number,
|
||||||
|
@inject(TYPES.CrossServiceTokenCache) crossServiceTokenCache: CrossServiceTokenCacheInterface,
|
||||||
|
@inject(TYPES.Timer) timer: TimerInterface,
|
||||||
|
@inject(TYPES.Logger) logger: Logger,
|
||||||
|
) {
|
||||||
|
super(serviceProxy, jwtSecret, crossServiceTokenCacheTTL, crossServiceTokenCache, timer, logger)
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override handleSessionValidationResponse(
|
||||||
|
authResponse: { status: number; data: unknown; headers: { contentType: string } },
|
||||||
|
_response: Response,
|
||||||
|
next: NextFunction,
|
||||||
|
): boolean {
|
||||||
|
if (authResponse.status > 200) {
|
||||||
|
next()
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override handleMissingAuthHeader(
|
||||||
|
authHeaderValue: string | undefined,
|
||||||
|
_response: Response,
|
||||||
|
next: NextFunction,
|
||||||
|
): boolean {
|
||||||
|
if (!authHeaderValue) {
|
||||||
|
next()
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
import { TimerInterface } from '@standardnotes/time'
|
||||||
|
import { NextFunction, Response } from 'express'
|
||||||
|
import { inject, injectable } from 'inversify'
|
||||||
|
import { Logger } from 'winston'
|
||||||
|
|
||||||
|
import { TYPES } from '../Bootstrap/Types'
|
||||||
|
import { CrossServiceTokenCacheInterface } from '../Service/Cache/CrossServiceTokenCacheInterface'
|
||||||
|
import { ServiceProxyInterface } from '../Service/Http/ServiceProxyInterface'
|
||||||
|
import { AuthMiddleware } from './AuthMiddleware'
|
||||||
|
|
||||||
|
@injectable()
|
||||||
|
export class RequiredCrossServiceTokenMiddleware extends AuthMiddleware {
|
||||||
|
constructor(
|
||||||
|
@inject(TYPES.ServiceProxy) serviceProxy: ServiceProxyInterface,
|
||||||
|
@inject(TYPES.AUTH_JWT_SECRET) jwtSecret: string,
|
||||||
|
@inject(TYPES.CROSS_SERVICE_TOKEN_CACHE_TTL) crossServiceTokenCacheTTL: number,
|
||||||
|
@inject(TYPES.CrossServiceTokenCache) crossServiceTokenCache: CrossServiceTokenCacheInterface,
|
||||||
|
@inject(TYPES.Timer) timer: TimerInterface,
|
||||||
|
@inject(TYPES.Logger) logger: Logger,
|
||||||
|
) {
|
||||||
|
super(serviceProxy, jwtSecret, crossServiceTokenCacheTTL, crossServiceTokenCache, timer, logger)
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override handleSessionValidationResponse(
|
||||||
|
authResponse: { status: number; data: unknown; headers: { contentType: string } },
|
||||||
|
response: Response,
|
||||||
|
_next: NextFunction,
|
||||||
|
): boolean {
|
||||||
|
if (authResponse.status > 200) {
|
||||||
|
response.setHeader('content-type', authResponse.headers.contentType)
|
||||||
|
response.status(authResponse.status).send(authResponse.data)
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override handleMissingAuthHeader(
|
||||||
|
authHeaderValue: string | undefined,
|
||||||
|
response: Response,
|
||||||
|
_next: NextFunction,
|
||||||
|
): boolean {
|
||||||
|
if (!authHeaderValue) {
|
||||||
|
response.status(401).send({
|
||||||
|
error: {
|
||||||
|
tag: 'invalid-auth',
|
||||||
|
message: 'Invalid login credentials.',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -118,7 +118,7 @@ export class SubscriptionTokenAuthMiddleware extends BaseMiddleware {
|
|||||||
verify(authResponse.data.authToken, this.jwtSecret, { algorithms: ['HS256'] })
|
verify(authResponse.data.authToken, this.jwtSecret, { algorithms: ['HS256'] })
|
||||||
)
|
)
|
||||||
|
|
||||||
response.locals.userUuid = decodedToken.user.uuid
|
response.locals.user = decodedToken.user
|
||||||
response.locals.roles = decodedToken.roles
|
response.locals.roles = decodedToken.roles
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ export class WebSocketAuthMiddleware extends BaseMiddleware {
|
|||||||
response.locals.freeUser =
|
response.locals.freeUser =
|
||||||
decodedToken.roles.length === 1 &&
|
decodedToken.roles.length === 1 &&
|
||||||
decodedToken.roles.find((role) => role.name === RoleName.NAMES.CoreUser) !== undefined
|
decodedToken.roles.find((role) => role.name === RoleName.NAMES.CoreUser) !== undefined
|
||||||
response.locals.userUuid = decodedToken.user.uuid
|
response.locals.user = decodedToken.user
|
||||||
response.locals.roles = decodedToken.roles
|
response.locals.roles = decodedToken.roles
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const errorMessage = (error as AxiosError).isAxiosError
|
const errorMessage = (error as AxiosError).isAxiosError
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ export class ActionsController extends BaseHttpController {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@httpGet('/login-params')
|
@httpGet('/login-params', TYPES.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')
|
@httpPost('/logout', TYPES.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.AuthMiddleware)
|
@httpPost('/recovery/codes', TYPES.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,
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ export class AuthenticatorsController extends BaseHttpController {
|
|||||||
super()
|
super()
|
||||||
}
|
}
|
||||||
|
|
||||||
@httpDelete('/:authenticatorId', TYPES.AuthMiddleware)
|
@httpDelete('/:authenticatorId', TYPES.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.AuthMiddleware)
|
@httpGet('/', TYPES.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.AuthMiddleware)
|
@httpGet('/generate-registration-options', TYPES.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.AuthMiddleware)
|
@httpPost('/verify-registration', TYPES.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,
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ export class FilesController extends BaseHttpController {
|
|||||||
super()
|
super()
|
||||||
}
|
}
|
||||||
|
|
||||||
@httpPost('/valet-tokens', TYPES.AuthMiddleware)
|
@httpPost('/valet-tokens', TYPES.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,
|
||||||
|
|||||||
@@ -5,10 +5,10 @@ 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.AuthMiddleware)
|
@controller('/v1/items', TYPES.RequiredCrossServiceTokenMiddleware)
|
||||||
export class ItemsController extends BaseHttpController {
|
export class ItemsController extends BaseHttpController {
|
||||||
constructor(
|
constructor(
|
||||||
@inject(TYPES.ServiceProxy) private httpService: ServiceProxyInterface,
|
@inject(TYPES.ServiceProxy) private serviceProxy: ServiceProxyInterface,
|
||||||
@inject(TYPES.EndpointResolver) private endpointResolver: EndpointResolverInterface,
|
@inject(TYPES.EndpointResolver) private endpointResolver: EndpointResolverInterface,
|
||||||
) {
|
) {
|
||||||
super()
|
super()
|
||||||
@@ -16,7 +16,7 @@ export class ItemsController extends BaseHttpController {
|
|||||||
|
|
||||||
@httpPost('/')
|
@httpPost('/')
|
||||||
async sync(request: Request, response: Response): Promise<void> {
|
async sync(request: Request, response: Response): Promise<void> {
|
||||||
await this.httpService.callSyncingServer(
|
await this.serviceProxy.callSyncingServer(
|
||||||
request,
|
request,
|
||||||
response,
|
response,
|
||||||
this.endpointResolver.resolveEndpointOrMethodIdentifier('POST', 'items/sync'),
|
this.endpointResolver.resolveEndpointOrMethodIdentifier('POST', 'items/sync'),
|
||||||
@@ -26,7 +26,7 @@ export class ItemsController extends BaseHttpController {
|
|||||||
|
|
||||||
@httpPost('/check-integrity')
|
@httpPost('/check-integrity')
|
||||||
async checkIntegrity(request: Request, response: Response): Promise<void> {
|
async checkIntegrity(request: Request, response: Response): Promise<void> {
|
||||||
await this.httpService.callSyncingServer(
|
await this.serviceProxy.callSyncingServer(
|
||||||
request,
|
request,
|
||||||
response,
|
response,
|
||||||
this.endpointResolver.resolveEndpointOrMethodIdentifier('POST', 'items/check-integrity'),
|
this.endpointResolver.resolveEndpointOrMethodIdentifier('POST', 'items/check-integrity'),
|
||||||
@@ -36,7 +36,7 @@ export class ItemsController extends BaseHttpController {
|
|||||||
|
|
||||||
@httpGet('/:uuid')
|
@httpGet('/:uuid')
|
||||||
async getItem(request: Request, response: Response): Promise<void> {
|
async getItem(request: Request, response: Response): Promise<void> {
|
||||||
await this.httpService.callSyncingServer(
|
await this.serviceProxy.callSyncingServer(
|
||||||
request,
|
request,
|
||||||
response,
|
response,
|
||||||
this.endpointResolver.resolveEndpointOrMethodIdentifier('GET', 'items/:uuid', request.params.uuid),
|
this.endpointResolver.resolveEndpointOrMethodIdentifier('GET', 'items/:uuid', request.params.uuid),
|
||||||
|
|||||||
@@ -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.AuthMiddleware)
|
@controller('/v1/items/:item_id/revisions', TYPES.RequiredCrossServiceTokenMiddleware)
|
||||||
export class RevisionsController extends BaseHttpController {
|
export class RevisionsController extends BaseHttpController {
|
||||||
@httpGet('/')
|
@httpGet('/')
|
||||||
async getRevisions(): Promise<results.JsonResult> {
|
async getRevisions(): Promise<results.JsonResult> {
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ export class SessionsController extends BaseHttpController {
|
|||||||
super()
|
super()
|
||||||
}
|
}
|
||||||
|
|
||||||
@httpGet('/', TYPES.AuthMiddleware)
|
@httpGet('/', TYPES.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.AuthMiddleware)
|
@httpDelete('/:uuid', TYPES.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.AuthMiddleware)
|
@httpDelete('/', TYPES.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,
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ export class SubscriptionInvitesController extends BaseHttpController {
|
|||||||
super()
|
super()
|
||||||
}
|
}
|
||||||
|
|
||||||
@httpPost('/', TYPES.AuthMiddleware)
|
@httpPost('/', TYPES.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.AuthMiddleware)
|
@httpGet('/', TYPES.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.AuthMiddleware)
|
@httpDelete('/:inviteUuid', TYPES.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.AuthMiddleware)
|
@httpPost('/:inviteUuid/accept', TYPES.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,
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ export class TokensController extends BaseHttpController {
|
|||||||
super()
|
super()
|
||||||
}
|
}
|
||||||
|
|
||||||
@httpPost('/', TYPES.AuthMiddleware)
|
@httpPost('/', TYPES.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,
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ export class UsersController extends BaseHttpController {
|
|||||||
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.AuthMiddleware)
|
@httpPatch('/:userId', TYPES.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 +47,7 @@ export class UsersController extends BaseHttpController {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@httpPut('/:userUuid/password', TYPES.AuthMiddleware)
|
@httpPut('/:userUuid/password', TYPES.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 +65,7 @@ export class UsersController extends BaseHttpController {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@httpPut('/:userUuid/attributes/credentials', TYPES.AuthMiddleware)
|
@httpPut('/:userUuid/attributes/credentials', TYPES.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 +79,7 @@ export class UsersController extends BaseHttpController {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@httpGet('/:userId/params', TYPES.AuthMiddleware)
|
@httpGet('/:userId/params', TYPES.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 +88,12 @@ export class UsersController extends BaseHttpController {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@all('/:userId/mfa', TYPES.AuthMiddleware)
|
@all('/:userId/mfa', TYPES.RequiredCrossServiceTokenMiddleware)
|
||||||
async blockMFA(): Promise<results.StatusCodeResult> {
|
async blockMFA(): Promise<results.StatusCodeResult> {
|
||||||
return this.statusCode(401)
|
return this.statusCode(401)
|
||||||
}
|
}
|
||||||
|
|
||||||
@httpPost('/:userUuid/integrations/listed', TYPES.AuthMiddleware)
|
@httpPost('/:userUuid/integrations/listed', TYPES.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 +113,7 @@ export class UsersController extends BaseHttpController {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@httpGet('/:userUuid/settings', TYPES.AuthMiddleware)
|
@httpGet('/:userUuid/settings', TYPES.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 +126,7 @@ export class UsersController extends BaseHttpController {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@httpPut('/:userUuid/settings', TYPES.AuthMiddleware)
|
@httpPut('/:userUuid/settings', TYPES.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 +140,7 @@ export class UsersController extends BaseHttpController {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@httpGet('/:userUuid/settings/:settingName', TYPES.AuthMiddleware)
|
@httpGet('/:userUuid/settings/:settingName', TYPES.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 +154,7 @@ export class UsersController extends BaseHttpController {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@httpDelete('/:userUuid/settings/:settingName', TYPES.AuthMiddleware)
|
@httpDelete('/:userUuid/settings/:settingName', TYPES.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 +169,7 @@ export class UsersController extends BaseHttpController {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@httpGet('/:userUuid/subscription-settings/:subscriptionSettingName', TYPES.AuthMiddleware)
|
@httpGet('/:userUuid/subscription-settings/:subscriptionSettingName', TYPES.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 +183,7 @@ export class UsersController extends BaseHttpController {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@httpGet('/:userUuid/features', TYPES.AuthMiddleware)
|
@httpGet('/:userUuid/features', TYPES.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 +196,7 @@ export class UsersController extends BaseHttpController {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@httpGet('/:userUuid/subscription', TYPES.AuthMiddleware)
|
@httpGet('/:userUuid/subscription', TYPES.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,
|
||||||
@@ -227,17 +227,17 @@ export class UsersController extends BaseHttpController {
|
|||||||
this.endpointResolver.resolveEndpointOrMethodIdentifier(
|
this.endpointResolver.resolveEndpointOrMethodIdentifier(
|
||||||
'GET',
|
'GET',
|
||||||
'users/:userUuid/subscription',
|
'users/:userUuid/subscription',
|
||||||
response.locals.userUuid,
|
response.locals.user.uuid,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@httpDelete('/:userUuid', TYPES.AuthMiddleware)
|
@httpDelete('/:userUuid', TYPES.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)
|
await this.httpService.callPaymentsServer(request, response, 'api/account', request.body)
|
||||||
}
|
}
|
||||||
|
|
||||||
@httpPost('/:userUuid/requests', TYPES.AuthMiddleware)
|
@httpPost('/:userUuid/requests', TYPES.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,
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ export class WebSocketsController extends BaseHttpController {
|
|||||||
super()
|
super()
|
||||||
}
|
}
|
||||||
|
|
||||||
@httpPost('/tokens', TYPES.AuthMiddleware)
|
@httpPost('/tokens', TYPES.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,
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ 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 httpService: ServiceProxyInterface,
|
@inject(TYPES.ServiceProxy) private serviceProxy: ServiceProxyInterface,
|
||||||
@inject(TYPES.EndpointResolver) private endpointResolver: EndpointResolverInterface,
|
@inject(TYPES.EndpointResolver) private endpointResolver: EndpointResolverInterface,
|
||||||
) {
|
) {
|
||||||
super()
|
super()
|
||||||
@@ -17,7 +17,7 @@ export class ActionsControllerV2 extends BaseHttpController {
|
|||||||
|
|
||||||
@httpPost('/login')
|
@httpPost('/login')
|
||||||
async login(request: Request, response: Response): Promise<void> {
|
async login(request: Request, response: Response): Promise<void> {
|
||||||
await this.httpService.callAuthServer(
|
await this.serviceProxy.callAuthServer(
|
||||||
request,
|
request,
|
||||||
response,
|
response,
|
||||||
this.endpointResolver.resolveEndpointOrMethodIdentifier('POST', 'auth/pkce_sign_in'),
|
this.endpointResolver.resolveEndpointOrMethodIdentifier('POST', 'auth/pkce_sign_in'),
|
||||||
@@ -25,9 +25,9 @@ export class ActionsControllerV2 extends BaseHttpController {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@httpPost('/login-params')
|
@httpPost('/login-params', TYPES.OptionalCrossServiceTokenMiddleware)
|
||||||
async loginParams(request: Request, response: Response): Promise<void> {
|
async loginParams(request: Request, response: Response): Promise<void> {
|
||||||
await this.httpService.callAuthServer(
|
await this.serviceProxy.callAuthServer(
|
||||||
request,
|
request,
|
||||||
response,
|
response,
|
||||||
this.endpointResolver.resolveEndpointOrMethodIdentifier('POST', 'auth/pkce_params'),
|
this.endpointResolver.resolveEndpointOrMethodIdentifier('POST', 'auth/pkce_params'),
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ 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.AuthMiddleware)
|
@controller('/v2/items/:itemUuid/revisions', TYPES.RequiredCrossServiceTokenMiddleware)
|
||||||
export class RevisionsControllerV2 extends BaseHttpController {
|
export class RevisionsControllerV2 extends BaseHttpController {
|
||||||
constructor(
|
constructor(
|
||||||
@inject(TYPES.ServiceProxy) private httpService: ServiceProxyInterface,
|
@inject(TYPES.ServiceProxy) private httpService: ServiceProxyInterface,
|
||||||
|
|||||||
@@ -24,6 +24,30 @@ export class HttpServiceProxy implements ServiceProxyInterface {
|
|||||||
@inject(TYPES.Logger) private logger: Logger,
|
@inject(TYPES.Logger) private logger: Logger,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
async validateSession(
|
||||||
|
authorizationHeaderValue: string,
|
||||||
|
): Promise<{ status: number; data: unknown; headers: { contentType: string } }> {
|
||||||
|
const authResponse = await this.httpClient.request({
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
Authorization: authorizationHeaderValue,
|
||||||
|
Accept: 'application/json',
|
||||||
|
},
|
||||||
|
validateStatus: (status: number) => {
|
||||||
|
return status >= 200 && status < 500
|
||||||
|
},
|
||||||
|
url: `${this.authServerUrl}/sessions/validate`,
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
status: authResponse.status,
|
||||||
|
data: authResponse.data,
|
||||||
|
headers: {
|
||||||
|
contentType: authResponse.headers['content-type'] as string,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async callSyncingServer(
|
async callSyncingServer(
|
||||||
request: Request,
|
request: Request,
|
||||||
response: Response,
|
response: Response,
|
||||||
@@ -238,7 +262,7 @@ export class HttpServiceProxy implements ServiceProxyInterface {
|
|||||||
response.status(serviceResponse.status).send({
|
response.status(serviceResponse.status).send({
|
||||||
meta: {
|
meta: {
|
||||||
auth: {
|
auth: {
|
||||||
userUuid: response.locals.userUuid,
|
userUuid: response.locals.user?.uuid,
|
||||||
roles: response.locals.roles,
|
roles: response.locals.roles,
|
||||||
},
|
},
|
||||||
server: {
|
server: {
|
||||||
|
|||||||
@@ -49,4 +49,11 @@ export interface ServiceProxyInterface {
|
|||||||
endpointOrMethodIdentifier: string,
|
endpointOrMethodIdentifier: string,
|
||||||
payload?: Record<string, unknown> | string,
|
payload?: Record<string, unknown> | string,
|
||||||
): Promise<void>
|
): Promise<void>
|
||||||
|
validateSession(authorizationHeaderValue: string): Promise<{
|
||||||
|
status: number
|
||||||
|
data: unknown
|
||||||
|
headers: {
|
||||||
|
contentType: string
|
||||||
|
}
|
||||||
|
}>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,35 @@ import { ServiceProxyInterface } from '../Http/ServiceProxyInterface'
|
|||||||
import { ServiceContainerInterface, ServiceIdentifier } from '@standardnotes/domain-core'
|
import { ServiceContainerInterface, ServiceIdentifier } from '@standardnotes/domain-core'
|
||||||
|
|
||||||
export class DirectCallServiceProxy implements ServiceProxyInterface {
|
export class DirectCallServiceProxy implements ServiceProxyInterface {
|
||||||
constructor(private serviceContainer: ServiceContainerInterface) {}
|
constructor(private serviceContainer: ServiceContainerInterface, private filesServerUrl: string) {}
|
||||||
|
|
||||||
|
async validateSession(
|
||||||
|
authorizationHeaderValue: string,
|
||||||
|
): Promise<{ status: number; data: unknown; headers: { contentType: string } }> {
|
||||||
|
const authService = this.serviceContainer.get(ServiceIdentifier.create(ServiceIdentifier.NAMES.Auth).getValue())
|
||||||
|
if (!authService) {
|
||||||
|
throw new Error('Auth service not found')
|
||||||
|
}
|
||||||
|
|
||||||
|
const serviceResponse = (await authService.handleRequest(
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
authorization: authorizationHeaderValue,
|
||||||
|
},
|
||||||
|
} as never,
|
||||||
|
{} as never,
|
||||||
|
'auth.sessions.validate',
|
||||||
|
)) as {
|
||||||
|
statusCode: number
|
||||||
|
json: Record<string, unknown>
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
status: serviceResponse.statusCode,
|
||||||
|
data: serviceResponse.json,
|
||||||
|
headers: { contentType: 'application/json' },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async callEmailServer(_request: Request, _response: Response, _endpointOrMethodIdentifier: string): Promise<void> {
|
async callEmailServer(_request: Request, _response: Response, _endpointOrMethodIdentifier: string): Promise<void> {
|
||||||
throw new Error('Email server is not available.')
|
throw new Error('Email server is not available.')
|
||||||
@@ -21,7 +49,7 @@ export class DirectCallServiceProxy implements ServiceProxyInterface {
|
|||||||
json: Record<string, unknown>
|
json: Record<string, unknown>
|
||||||
}
|
}
|
||||||
|
|
||||||
void (response as Response).status(serviceResponse.statusCode).send(serviceResponse.json)
|
this.sendDecoratedResponse(response, serviceResponse)
|
||||||
}
|
}
|
||||||
|
|
||||||
async callAuthServerWithLegacyFormat(
|
async callAuthServerWithLegacyFormat(
|
||||||
@@ -49,7 +77,12 @@ export class DirectCallServiceProxy implements ServiceProxyInterface {
|
|||||||
throw new Error('Syncing service not found')
|
throw new Error('Syncing service not found')
|
||||||
}
|
}
|
||||||
|
|
||||||
await service.handleRequest(request, response, endpointOrMethodIdentifier)
|
const serviceResponse = (await service.handleRequest(request, response, endpointOrMethodIdentifier)) as {
|
||||||
|
statusCode: number
|
||||||
|
json: Record<string, unknown>
|
||||||
|
}
|
||||||
|
|
||||||
|
this.sendDecoratedResponse(response, serviceResponse)
|
||||||
}
|
}
|
||||||
|
|
||||||
async callLegacySyncingServer(
|
async callLegacySyncingServer(
|
||||||
@@ -71,4 +104,22 @@ export class DirectCallServiceProxy implements ServiceProxyInterface {
|
|||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
throw new Error('Websockets server is not available.')
|
throw new Error('Websockets server is not available.')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private sendDecoratedResponse(
|
||||||
|
response: Response,
|
||||||
|
serviceResponse: { statusCode: number; json: Record<string, unknown> },
|
||||||
|
): void {
|
||||||
|
void response.status(serviceResponse.statusCode).send({
|
||||||
|
meta: {
|
||||||
|
auth: {
|
||||||
|
userUuid: response.locals.user?.uuid,
|
||||||
|
roles: response.locals.roles,
|
||||||
|
},
|
||||||
|
server: {
|
||||||
|
filesServerUrl: this.filesServerUrl,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data: serviceResponse.json,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ export class EndpointResolver implements EndpointResolverInterface {
|
|||||||
constructor(private isConfiguredForHomeServer: boolean) {}
|
constructor(private isConfiguredForHomeServer: boolean) {}
|
||||||
|
|
||||||
private readonly endpointToIdentifierMap: Map<string, string> = new Map([
|
private readonly endpointToIdentifierMap: Map<string, string> = new Map([
|
||||||
|
// Auth Middleware
|
||||||
|
['[POST]:sessions/validate', 'auth.sessions.validate'],
|
||||||
// Actions Controller
|
// Actions Controller
|
||||||
['[POST]:auth/sign_in', 'auth.signIn'],
|
['[POST]:auth/sign_in', 'auth.signIn'],
|
||||||
['[GET]:auth/params', 'auth.params'],
|
['[GET]:auth/params', 'auth.params'],
|
||||||
@@ -11,6 +13,9 @@ export class EndpointResolver implements EndpointResolverInterface {
|
|||||||
['[POST]:auth/recovery/codes', 'auth.generateRecoveryCodes'],
|
['[POST]:auth/recovery/codes', 'auth.generateRecoveryCodes'],
|
||||||
['[POST]:auth/recovery/login', 'auth.signInWithRecoveryCodes'],
|
['[POST]:auth/recovery/login', 'auth.signInWithRecoveryCodes'],
|
||||||
['[POST]:auth/recovery/params', 'auth.recoveryKeyParams'],
|
['[POST]:auth/recovery/params', 'auth.recoveryKeyParams'],
|
||||||
|
// v2 Actions Controller
|
||||||
|
['[POST]:auth/pkce_sign_in', 'auth.pkceSignIn'],
|
||||||
|
['[POST]:auth/pkce_params', 'auth.pkceParams'],
|
||||||
// Authenticators Controller
|
// Authenticators Controller
|
||||||
['[DELETE]:authenticators/:authenticatorId', 'auth.authenticators.delete'],
|
['[DELETE]:authenticators/:authenticatorId', 'auth.authenticators.delete'],
|
||||||
['[GET]:authenticators/', 'auth.authenticators.list'],
|
['[GET]:authenticators/', 'auth.authenticators.list'],
|
||||||
@@ -49,6 +54,10 @@ export class EndpointResolver implements EndpointResolverInterface {
|
|||||||
['[GET]:users/:userUuid/subscription', 'auth.users.getSubscription'],
|
['[GET]:users/:userUuid/subscription', 'auth.users.getSubscription'],
|
||||||
['[GET]:offline/users/subscription', 'auth.users.getOfflineSubscriptionByToken'],
|
['[GET]:offline/users/subscription', 'auth.users.getOfflineSubscriptionByToken'],
|
||||||
['[POST]:users/:userUuid/requests', 'auth.users.createRequest'],
|
['[POST]:users/:userUuid/requests', 'auth.users.createRequest'],
|
||||||
|
// Syncing Server
|
||||||
|
['[POST]:items/sync', 'sync.items.sync'],
|
||||||
|
['[POST]:items/check-integrity', 'sync.items.check_integrity'],
|
||||||
|
['[GET]:items/:uuid', 'sync.items.get_item'],
|
||||||
])
|
])
|
||||||
|
|
||||||
resolveEndpointOrMethodIdentifier(method: string, endpoint: string, ...params: string[]): string {
|
resolveEndpointOrMethodIdentifier(method: string, endpoint: string, ...params: string[]): string {
|
||||||
|
|||||||
@@ -3,6 +3,40 @@
|
|||||||
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.110.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.109.2...@standardnotes/auth-server@1.110.0) (2023-05-25)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* refactor auth middleware to handle required and optional cross service token scenarios ([#612](https://github.com/standardnotes/server/issues/612)) ([1e4c7d0](https://github.com/standardnotes/server/commit/1e4c7d0f317d5c2d98065da12ffeb950b10ee5dc))
|
||||||
|
|
||||||
|
## [1.109.2](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.109.1...@standardnotes/auth-server@1.109.2) (2023-05-18)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **auth:** changing user credentials to work both on http proxy and direct code call ([cc61229](https://github.com/standardnotes/server/commit/cc612296d0fbfa7e95556fda45eb9706845e4f58))
|
||||||
|
|
||||||
|
## [1.109.1](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.109.0...@standardnotes/auth-server@1.109.1) (2023-05-18)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/auth-server
|
||||||
|
|
||||||
|
# [1.109.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.108.0...@standardnotes/auth-server@1.109.0) (2023-05-17)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* bundle syncing server into home server setup ([#611](https://github.com/standardnotes/server/issues/611)) ([b3b617e](https://github.com/standardnotes/server/commit/b3b617ea0b4f4574f6aa7cfae0e9fa8f868f1f4c))
|
||||||
|
|
||||||
|
# [1.108.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.107.0...@standardnotes/auth-server@1.108.0) (2023-05-17)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **auth:** move inversify express controllers to different structure ([#610](https://github.com/standardnotes/server/issues/610)) ([fea5802](https://github.com/standardnotes/server/commit/fea58029b90804dba31faa3c26dcd7dabe541648))
|
||||||
|
|
||||||
|
# [1.107.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.106.0...@standardnotes/auth-server@1.107.0) (2023-05-17)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add direct event handling for home server ([#608](https://github.com/standardnotes/server/issues/608)) ([8a47d81](https://github.com/standardnotes/server/commit/8a47d81936acd765224e74fd083810579a83c9a7))
|
||||||
|
|
||||||
# [1.106.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.105.2...@standardnotes/auth-server@1.106.0) (2023-05-16)
|
# [1.106.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.105.2...@standardnotes/auth-server@1.106.0) (2023-05-16)
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|||||||
@@ -2,25 +2,24 @@ import 'reflect-metadata'
|
|||||||
|
|
||||||
import 'newrelic'
|
import 'newrelic'
|
||||||
|
|
||||||
import '../src/Controller/HealthCheckController'
|
|
||||||
import '../src/Controller/SessionController'
|
|
||||||
import '../src/Controller/SessionsController'
|
|
||||||
import '../src/Controller/UsersController'
|
|
||||||
import '../src/Controller/SettingsController'
|
|
||||||
import '../src/Controller/FeaturesController'
|
|
||||||
import '../src/Controller/AdminController'
|
|
||||||
import '../src/Controller/InternalController'
|
|
||||||
import '../src/Controller/SubscriptionTokensController'
|
|
||||||
import '../src/Controller/OfflineController'
|
|
||||||
import '../src/Controller/ValetTokenController'
|
|
||||||
import '../src/Controller/ListedController'
|
|
||||||
import '../src/Controller/SubscriptionSettingsController'
|
|
||||||
|
|
||||||
import '../src/Infra/InversifyExpressUtils/InversifyExpressAuthController'
|
import '../src/Infra/InversifyExpressUtils/InversifyExpressAuthController'
|
||||||
import '../src/Infra/InversifyExpressUtils/InversifyExpressAuthenticatorsController'
|
import '../src/Infra/InversifyExpressUtils/InversifyExpressAuthenticatorsController'
|
||||||
|
import '../src/Infra/InversifyExpressUtils/InversifyExpressSessionsController'
|
||||||
import '../src/Infra/InversifyExpressUtils/InversifyExpressSubscriptionInvitesController'
|
import '../src/Infra/InversifyExpressUtils/InversifyExpressSubscriptionInvitesController'
|
||||||
import '../src/Infra/InversifyExpressUtils/InversifyExpressUserRequestsController'
|
import '../src/Infra/InversifyExpressUtils/InversifyExpressUserRequestsController'
|
||||||
import '../src/Infra/InversifyExpressUtils/InversifyExpressWebSocketsController'
|
import '../src/Infra/InversifyExpressUtils/InversifyExpressWebSocketsController'
|
||||||
|
import '../src/Infra/InversifyExpressUtils/InversifyExpressUsersController'
|
||||||
|
import '../src/Infra/InversifyExpressUtils/InversifyExpressValetTokenController'
|
||||||
|
import '../src/Infra/InversifyExpressUtils/InversifyExpressAdminController'
|
||||||
|
import '../src/Infra/InversifyExpressUtils/InversifyExpressSubscriptionTokensController'
|
||||||
|
import '../src/Infra/InversifyExpressUtils/InversifyExpressSubscriptionSettingsController'
|
||||||
|
import '../src/Infra/InversifyExpressUtils/InversifyExpressSettingsController'
|
||||||
|
import '../src/Infra/InversifyExpressUtils/InversifyExpressSessionController'
|
||||||
|
import '../src/Infra/InversifyExpressUtils/InversifyExpressOfflineController'
|
||||||
|
import '../src/Infra/InversifyExpressUtils/InversifyExpressListedController'
|
||||||
|
import '../src/Infra/InversifyExpressUtils/InversifyExpressInternalController'
|
||||||
|
import '../src/Infra/InversifyExpressUtils/InversifyExpressHealthCheckController'
|
||||||
|
import '../src/Infra/InversifyExpressUtils/InversifyExpressFeaturesController'
|
||||||
|
|
||||||
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,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/auth-server",
|
"name": "@standardnotes/auth-server",
|
||||||
"version": "1.106.0",
|
"version": "1.110.0",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.0.0 <21.0.0"
|
"node": ">=18.0.0 <21.0.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { Container } from 'inversify'
|
|||||||
import {
|
import {
|
||||||
DomainEventHandlerInterface,
|
DomainEventHandlerInterface,
|
||||||
DomainEventMessageHandlerInterface,
|
DomainEventMessageHandlerInterface,
|
||||||
|
DomainEventPublisherInterface,
|
||||||
DomainEventSubscriberFactoryInterface,
|
DomainEventSubscriberFactoryInterface,
|
||||||
} from '@standardnotes/domain-events'
|
} from '@standardnotes/domain-events'
|
||||||
import { TimerInterface, Timer } from '@standardnotes/time'
|
import { TimerInterface, Timer } from '@standardnotes/time'
|
||||||
@@ -13,7 +14,6 @@ import { UAParser } from 'ua-parser-js'
|
|||||||
|
|
||||||
import { Env } from './Env'
|
import { Env } from './Env'
|
||||||
import TYPES from './Types'
|
import TYPES from './Types'
|
||||||
import { AuthMiddleware } from '../Controller/AuthMiddleware'
|
|
||||||
import { AuthenticateUser } from '../Domain/UseCase/AuthenticateUser'
|
import { AuthenticateUser } from '../Domain/UseCase/AuthenticateUser'
|
||||||
import { Repository } from 'typeorm'
|
import { Repository } from 'typeorm'
|
||||||
import { AppDataSource } from './DataSource'
|
import { AppDataSource } from './DataSource'
|
||||||
@@ -23,7 +23,6 @@ import { SessionService } from '../Domain/Session/SessionService'
|
|||||||
import { TypeORMSessionRepository } from '../Infra/TypeORM/TypeORMSessionRepository'
|
import { TypeORMSessionRepository } from '../Infra/TypeORM/TypeORMSessionRepository'
|
||||||
import { TypeORMUserRepository } from '../Infra/TypeORM/TypeORMUserRepository'
|
import { TypeORMUserRepository } from '../Infra/TypeORM/TypeORMUserRepository'
|
||||||
import { SessionProjector } from '../Projection/SessionProjector'
|
import { SessionProjector } from '../Projection/SessionProjector'
|
||||||
import { SessionMiddleware } from '../Controller/SessionMiddleware'
|
|
||||||
import { RefreshSessionToken } from '../Domain/UseCase/RefreshSessionToken'
|
import { RefreshSessionToken } from '../Domain/UseCase/RefreshSessionToken'
|
||||||
import { KeyParamsFactory } from '../Domain/User/KeyParamsFactory'
|
import { KeyParamsFactory } from '../Domain/User/KeyParamsFactory'
|
||||||
import { SignIn } from '../Domain/UseCase/SignIn'
|
import { SignIn } from '../Domain/UseCase/SignIn'
|
||||||
@@ -35,8 +34,6 @@ import { AuthResponseFactory20200115 } from '../Domain/Auth/AuthResponseFactory2
|
|||||||
import { AuthResponseFactoryResolver } from '../Domain/Auth/AuthResponseFactoryResolver'
|
import { AuthResponseFactoryResolver } from '../Domain/Auth/AuthResponseFactoryResolver'
|
||||||
import { ClearLoginAttempts } from '../Domain/UseCase/ClearLoginAttempts'
|
import { ClearLoginAttempts } from '../Domain/UseCase/ClearLoginAttempts'
|
||||||
import { IncreaseLoginAttempts } from '../Domain/UseCase/IncreaseLoginAttempts'
|
import { IncreaseLoginAttempts } from '../Domain/UseCase/IncreaseLoginAttempts'
|
||||||
import { LockMiddleware } from '../Controller/LockMiddleware'
|
|
||||||
import { AuthMiddlewareWithoutResponse } from '../Controller/AuthMiddlewareWithoutResponse'
|
|
||||||
import { GetUserKeyParams } from '../Domain/UseCase/GetUserKeyParams/GetUserKeyParams'
|
import { GetUserKeyParams } from '../Domain/UseCase/GetUserKeyParams/GetUserKeyParams'
|
||||||
import { UpdateUser } from '../Domain/UseCase/UpdateUser'
|
import { UpdateUser } from '../Domain/UseCase/UpdateUser'
|
||||||
import { RedisEphemeralSessionRepository } from '../Infra/Redis/RedisEphemeralSessionRepository'
|
import { RedisEphemeralSessionRepository } from '../Infra/Redis/RedisEphemeralSessionRepository'
|
||||||
@@ -90,6 +87,8 @@ import { FeatureService } from '../Domain/Feature/FeatureService'
|
|||||||
import { SettingServiceInterface } from '../Domain/Setting/SettingServiceInterface'
|
import { SettingServiceInterface } from '../Domain/Setting/SettingServiceInterface'
|
||||||
import { ExtensionKeyGrantedEventHandler } from '../Domain/Handler/ExtensionKeyGrantedEventHandler'
|
import { ExtensionKeyGrantedEventHandler } from '../Domain/Handler/ExtensionKeyGrantedEventHandler'
|
||||||
import {
|
import {
|
||||||
|
DirectCallDomainEventPublisher,
|
||||||
|
DirectCallEventMessageHandler,
|
||||||
SNSDomainEventPublisher,
|
SNSDomainEventPublisher,
|
||||||
SQSDomainEventSubscriberFactory,
|
SQSDomainEventSubscriberFactory,
|
||||||
SQSEventMessageHandler,
|
SQSEventMessageHandler,
|
||||||
@@ -100,7 +99,6 @@ import { ChangeCredentials } from '../Domain/UseCase/ChangeCredentials/ChangeCre
|
|||||||
import { SubscriptionReassignedEventHandler } from '../Domain/Handler/SubscriptionReassignedEventHandler'
|
import { SubscriptionReassignedEventHandler } from '../Domain/Handler/SubscriptionReassignedEventHandler'
|
||||||
import { UserSubscriptionRepositoryInterface } from '../Domain/Subscription/UserSubscriptionRepositoryInterface'
|
import { UserSubscriptionRepositoryInterface } from '../Domain/Subscription/UserSubscriptionRepositoryInterface'
|
||||||
import { CreateSubscriptionToken } from '../Domain/UseCase/CreateSubscriptionToken/CreateSubscriptionToken'
|
import { CreateSubscriptionToken } from '../Domain/UseCase/CreateSubscriptionToken/CreateSubscriptionToken'
|
||||||
import { ApiGatewayAuthMiddleware } from '../Controller/ApiGatewayAuthMiddleware'
|
|
||||||
import { SubscriptionTokenRepositoryInterface } from '../Domain/Subscription/SubscriptionTokenRepositoryInterface'
|
import { SubscriptionTokenRepositoryInterface } from '../Domain/Subscription/SubscriptionTokenRepositoryInterface'
|
||||||
import { RedisSubscriptionTokenRepository } from '../Infra/Redis/RedisSubscriptionTokenRepository'
|
import { RedisSubscriptionTokenRepository } from '../Infra/Redis/RedisSubscriptionTokenRepository'
|
||||||
import { AuthenticateSubscriptionToken } from '../Domain/UseCase/AuthenticateSubscriptionToken/AuthenticateSubscriptionToken'
|
import { AuthenticateSubscriptionToken } from '../Domain/UseCase/AuthenticateSubscriptionToken/AuthenticateSubscriptionToken'
|
||||||
@@ -113,7 +111,6 @@ import { TypeORMOfflineSettingRepository } from '../Infra/TypeORM/TypeORMOffline
|
|||||||
import { OfflineUserSubscription } from '../Domain/Subscription/OfflineUserSubscription'
|
import { OfflineUserSubscription } from '../Domain/Subscription/OfflineUserSubscription'
|
||||||
import { OfflineUserSubscriptionRepositoryInterface } from '../Domain/Subscription/OfflineUserSubscriptionRepositoryInterface'
|
import { OfflineUserSubscriptionRepositoryInterface } from '../Domain/Subscription/OfflineUserSubscriptionRepositoryInterface'
|
||||||
import { TypeORMOfflineUserSubscriptionRepository } from '../Infra/TypeORM/TypeORMOfflineUserSubscriptionRepository'
|
import { TypeORMOfflineUserSubscriptionRepository } from '../Infra/TypeORM/TypeORMOfflineUserSubscriptionRepository'
|
||||||
import { OfflineUserAuthMiddleware } from '../Controller/OfflineUserAuthMiddleware'
|
|
||||||
import { OfflineSubscriptionTokenRepositoryInterface } from '../Domain/Auth/OfflineSubscriptionTokenRepositoryInterface'
|
import { OfflineSubscriptionTokenRepositoryInterface } from '../Domain/Auth/OfflineSubscriptionTokenRepositoryInterface'
|
||||||
import { RedisOfflineSubscriptionTokenRepository } from '../Infra/Redis/RedisOfflineSubscriptionTokenRepository'
|
import { RedisOfflineSubscriptionTokenRepository } from '../Infra/Redis/RedisOfflineSubscriptionTokenRepository'
|
||||||
import { CreateOfflineSubscriptionToken } from '../Domain/UseCase/CreateOfflineSubscriptionToken/CreateOfflineSubscriptionToken'
|
import { CreateOfflineSubscriptionToken } from '../Domain/UseCase/CreateOfflineSubscriptionToken/CreateOfflineSubscriptionToken'
|
||||||
@@ -121,7 +118,6 @@ import { AuthenticateOfflineSubscriptionToken } from '../Domain/UseCase/Authenti
|
|||||||
import { SubscriptionCancelledEventHandler } from '../Domain/Handler/SubscriptionCancelledEventHandler'
|
import { SubscriptionCancelledEventHandler } from '../Domain/Handler/SubscriptionCancelledEventHandler'
|
||||||
import { ContentDecoder, ContentDecoderInterface, ProtocolVersion } from '@standardnotes/common'
|
import { ContentDecoder, ContentDecoderInterface, ProtocolVersion } from '@standardnotes/common'
|
||||||
import { GetUserOfflineSubscription } from '../Domain/UseCase/GetUserOfflineSubscription/GetUserOfflineSubscription'
|
import { GetUserOfflineSubscription } from '../Domain/UseCase/GetUserOfflineSubscription/GetUserOfflineSubscription'
|
||||||
import { ApiGatewayOfflineAuthMiddleware } from '../Controller/ApiGatewayOfflineAuthMiddleware'
|
|
||||||
import { UserEmailChangedEventHandler } from '../Domain/Handler/UserEmailChangedEventHandler'
|
import { UserEmailChangedEventHandler } from '../Domain/Handler/UserEmailChangedEventHandler'
|
||||||
import { SettingsAssociationServiceInterface } from '../Domain/Setting/SettingsAssociationServiceInterface'
|
import { SettingsAssociationServiceInterface } from '../Domain/Setting/SettingsAssociationServiceInterface'
|
||||||
import { SettingsAssociationService } from '../Domain/Setting/SettingsAssociationService'
|
import { SettingsAssociationService } from '../Domain/Setting/SettingsAssociationService'
|
||||||
@@ -237,12 +233,36 @@ import { InversifyExpressAuthenticatorsController } from '../Infra/InversifyExpr
|
|||||||
import { InversifyExpressSubscriptionInvitesController } from '../Infra/InversifyExpressUtils/InversifyExpressSubscriptionInvitesController'
|
import { InversifyExpressSubscriptionInvitesController } from '../Infra/InversifyExpressUtils/InversifyExpressSubscriptionInvitesController'
|
||||||
import { InversifyExpressUserRequestsController } from '../Infra/InversifyExpressUtils/InversifyExpressUserRequestsController'
|
import { InversifyExpressUserRequestsController } from '../Infra/InversifyExpressUtils/InversifyExpressUserRequestsController'
|
||||||
import { InversifyExpressWebSocketsController } from '../Infra/InversifyExpressUtils/InversifyExpressWebSocketsController'
|
import { InversifyExpressWebSocketsController } from '../Infra/InversifyExpressUtils/InversifyExpressWebSocketsController'
|
||||||
|
import { InversifyExpressSessionsController } from '../Infra/InversifyExpressUtils/InversifyExpressSessionsController'
|
||||||
|
import { InversifyExpressValetTokenController } from '../Infra/InversifyExpressUtils/InversifyExpressValetTokenController'
|
||||||
|
import { InversifyExpressUsersController } from '../Infra/InversifyExpressUtils/InversifyExpressUsersController'
|
||||||
|
import { InversifyExpressAdminController } from '../Infra/InversifyExpressUtils/InversifyExpressAdminController'
|
||||||
|
import { InversifyExpressSubscriptionTokensController } from '../Infra/InversifyExpressUtils/InversifyExpressSubscriptionTokensController'
|
||||||
|
import { InversifyExpressSubscriptionSettingsController } from '../Infra/InversifyExpressUtils/InversifyExpressSubscriptionSettingsController'
|
||||||
|
import { InversifyExpressSettingsController } from '../Infra/InversifyExpressUtils/InversifyExpressSettingsController'
|
||||||
|
import { SessionMiddleware } from '../Infra/InversifyExpressUtils/Middleware/SessionMiddleware'
|
||||||
|
import { ApiGatewayOfflineAuthMiddleware } from '../Infra/InversifyExpressUtils/Middleware/ApiGatewayOfflineAuthMiddleware'
|
||||||
|
import { OfflineUserAuthMiddleware } from '../Infra/InversifyExpressUtils/Middleware/OfflineUserAuthMiddleware'
|
||||||
|
import { LockMiddleware } from '../Infra/InversifyExpressUtils/Middleware/LockMiddleware'
|
||||||
|
import { InversifyExpressSessionController } from '../Infra/InversifyExpressUtils/InversifyExpressSessionController'
|
||||||
|
import { InversifyExpressOfflineController } from '../Infra/InversifyExpressUtils/InversifyExpressOfflineController'
|
||||||
|
import { InversifyExpressListedController } from '../Infra/InversifyExpressUtils/InversifyExpressListedController'
|
||||||
|
import { InversifyExpressInternalController } from '../Infra/InversifyExpressUtils/InversifyExpressInternalController'
|
||||||
|
import { InversifyExpressFeaturesController } from '../Infra/InversifyExpressUtils/InversifyExpressFeaturesController'
|
||||||
|
import { RequiredCrossServiceTokenMiddleware } from '../Infra/InversifyExpressUtils/Middleware/RequiredCrossServiceTokenMiddleware'
|
||||||
|
import { OptionalCrossServiceTokenMiddleware } from '../Infra/InversifyExpressUtils/Middleware/OptionalCrossServiceTokenMiddleware'
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||||
const newrelicFormatter = require('@newrelic/winston-enricher')
|
const newrelicFormatter = require('@newrelic/winston-enricher')
|
||||||
|
|
||||||
export class ContainerConfigLoader {
|
export class ContainerConfigLoader {
|
||||||
async load(controllerConatiner?: ControllerContainerInterface): Promise<Container> {
|
async load(configuration?: {
|
||||||
|
controllerConatiner?: ControllerContainerInterface
|
||||||
|
directCallDomainEventPublisher?: DirectCallDomainEventPublisher
|
||||||
|
}): Promise<Container> {
|
||||||
|
const directCallDomainEventPublisher =
|
||||||
|
configuration?.directCallDomainEventPublisher ?? new DirectCallDomainEventPublisher()
|
||||||
|
|
||||||
const env: Env = new Env()
|
const env: Env = new Env()
|
||||||
env.load()
|
env.load()
|
||||||
|
|
||||||
@@ -275,11 +295,13 @@ export class ContainerConfigLoader {
|
|||||||
level: env.get('LOG_LEVEL') || 'info',
|
level: env.get('LOG_LEVEL') || 'info',
|
||||||
format: winston.format.combine(...winstonFormatters),
|
format: winston.format.combine(...winstonFormatters),
|
||||||
transports: [new winston.transports.Console({ level: env.get('LOG_LEVEL') || 'info' })],
|
transports: [new winston.transports.Console({ level: env.get('LOG_LEVEL') || 'info' })],
|
||||||
|
defaultMeta: { service: 'auth' },
|
||||||
})
|
})
|
||||||
container.bind<winston.Logger>(TYPES.Auth_Logger).toConstantValue(logger)
|
container.bind<winston.Logger>(TYPES.Auth_Logger).toConstantValue(logger)
|
||||||
|
|
||||||
container.bind<TimerInterface>(TYPES.Auth_Timer).toConstantValue(new Timer())
|
container.bind<TimerInterface>(TYPES.Auth_Timer).toConstantValue(new Timer())
|
||||||
|
|
||||||
|
if (!isConfiguredForHomeServer) {
|
||||||
const snsConfig: SNSClientConfig = {
|
const snsConfig: SNSClientConfig = {
|
||||||
region: env.get('SNS_AWS_REGION', true),
|
region: env.get('SNS_AWS_REGION', true),
|
||||||
}
|
}
|
||||||
@@ -307,6 +329,7 @@ export class ContainerConfigLoader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
container.bind<SQSClient>(TYPES.Auth_SQS).toConstantValue(new SQSClient(sqsConfig))
|
container.bind<SQSClient>(TYPES.Auth_SQS).toConstantValue(new SQSClient(sqsConfig))
|
||||||
|
}
|
||||||
|
|
||||||
// Mapping
|
// Mapping
|
||||||
container
|
container
|
||||||
@@ -424,13 +447,14 @@ export class ContainerConfigLoader {
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Middleware
|
// Middleware
|
||||||
container.bind<AuthMiddleware>(TYPES.Auth_AuthMiddleware).to(AuthMiddleware)
|
|
||||||
container.bind<SessionMiddleware>(TYPES.Auth_SessionMiddleware).to(SessionMiddleware)
|
container.bind<SessionMiddleware>(TYPES.Auth_SessionMiddleware).to(SessionMiddleware)
|
||||||
container.bind<LockMiddleware>(TYPES.Auth_LockMiddleware).to(LockMiddleware)
|
container.bind<LockMiddleware>(TYPES.Auth_LockMiddleware).to(LockMiddleware)
|
||||||
container
|
container
|
||||||
.bind<AuthMiddlewareWithoutResponse>(TYPES.Auth_AuthMiddlewareWithoutResponse)
|
.bind<RequiredCrossServiceTokenMiddleware>(TYPES.Auth_RequiredCrossServiceTokenMiddleware)
|
||||||
.to(AuthMiddlewareWithoutResponse)
|
.to(RequiredCrossServiceTokenMiddleware)
|
||||||
container.bind<ApiGatewayAuthMiddleware>(TYPES.Auth_ApiGatewayAuthMiddleware).to(ApiGatewayAuthMiddleware)
|
container
|
||||||
|
.bind<OptionalCrossServiceTokenMiddleware>(TYPES.Auth_OptionalCrossServiceTokenMiddleware)
|
||||||
|
.to(OptionalCrossServiceTokenMiddleware)
|
||||||
container
|
container
|
||||||
.bind<ApiGatewayOfflineAuthMiddleware>(TYPES.Auth_ApiGatewayOfflineAuthMiddleware)
|
.bind<ApiGatewayOfflineAuthMiddleware>(TYPES.Auth_ApiGatewayOfflineAuthMiddleware)
|
||||||
.to(ApiGatewayOfflineAuthMiddleware)
|
.to(ApiGatewayOfflineAuthMiddleware)
|
||||||
@@ -494,7 +518,7 @@ export class ContainerConfigLoader {
|
|||||||
.toConstantValue(env.get('USER_SERVER_CHANGE_EMAIL_URL', true))
|
.toConstantValue(env.get('USER_SERVER_CHANGE_EMAIL_URL', true))
|
||||||
container.bind(TYPES.Auth_NEW_RELIC_ENABLED).toConstantValue(env.get('NEW_RELIC_ENABLED', true))
|
container.bind(TYPES.Auth_NEW_RELIC_ENABLED).toConstantValue(env.get('NEW_RELIC_ENABLED', true))
|
||||||
container.bind(TYPES.Auth_SYNCING_SERVER_URL).toConstantValue(env.get('SYNCING_SERVER_URL', true))
|
container.bind(TYPES.Auth_SYNCING_SERVER_URL).toConstantValue(env.get('SYNCING_SERVER_URL', true))
|
||||||
container.bind(TYPES.Auth_VERSION).toConstantValue(env.get('VERSION'))
|
container.bind(TYPES.Auth_VERSION).toConstantValue(env.get('VERSION', true) ?? 'development')
|
||||||
container.bind(TYPES.Auth_PAYMENTS_SERVER_URL).toConstantValue(env.get('PAYMENTS_SERVER_URL', true))
|
container.bind(TYPES.Auth_PAYMENTS_SERVER_URL).toConstantValue(env.get('PAYMENTS_SERVER_URL', true))
|
||||||
container
|
container
|
||||||
.bind(TYPES.Auth_SESSION_TRACE_DAYS_TTL)
|
.bind(TYPES.Auth_SESSION_TRACE_DAYS_TTL)
|
||||||
@@ -649,9 +673,11 @@ export class ContainerConfigLoader {
|
|||||||
container.bind<UserSubscriptionServiceInterface>(TYPES.Auth_UserSubscriptionService).to(UserSubscriptionService)
|
container.bind<UserSubscriptionServiceInterface>(TYPES.Auth_UserSubscriptionService).to(UserSubscriptionService)
|
||||||
|
|
||||||
container
|
container
|
||||||
.bind<SNSDomainEventPublisher>(TYPES.Auth_DomainEventPublisher)
|
.bind<DomainEventPublisherInterface>(TYPES.Auth_DomainEventPublisher)
|
||||||
.toConstantValue(
|
.toConstantValue(
|
||||||
new SNSDomainEventPublisher(container.get(TYPES.Auth_SNS), container.get(TYPES.Auth_SNS_TOPIC_ARN)),
|
isConfiguredForHomeServer
|
||||||
|
? directCallDomainEventPublisher
|
||||||
|
: new SNSDomainEventPublisher(container.get(TYPES.Auth_SNS), container.get(TYPES.Auth_SNS_TOPIC_ARN)),
|
||||||
)
|
)
|
||||||
|
|
||||||
// use cases
|
// use cases
|
||||||
@@ -836,7 +862,7 @@ export class ContainerConfigLoader {
|
|||||||
// Controller
|
// Controller
|
||||||
container
|
container
|
||||||
.bind<ControllerContainerInterface>(TYPES.Auth_ControllerContainer)
|
.bind<ControllerContainerInterface>(TYPES.Auth_ControllerContainer)
|
||||||
.toConstantValue(controllerConatiner ?? new ControllerContainer())
|
.toConstantValue(configuration?.controllerConatiner ?? new ControllerContainer())
|
||||||
container
|
container
|
||||||
.bind<AuthController>(TYPES.Auth_AuthController)
|
.bind<AuthController>(TYPES.Auth_AuthController)
|
||||||
.toConstantValue(
|
.toConstantValue(
|
||||||
@@ -956,6 +982,16 @@ export class ContainerConfigLoader {
|
|||||||
['EMAIL_SUBSCRIPTION_UNSUBSCRIBED', container.get(TYPES.Auth_EmailSubscriptionUnsubscribedEventHandler)],
|
['EMAIL_SUBSCRIPTION_UNSUBSCRIBED', container.get(TYPES.Auth_EmailSubscriptionUnsubscribedEventHandler)],
|
||||||
])
|
])
|
||||||
|
|
||||||
|
if (isConfiguredForHomeServer) {
|
||||||
|
const directCallEventMessageHandler = new DirectCallEventMessageHandler(
|
||||||
|
eventHandlers,
|
||||||
|
container.get(TYPES.Auth_Logger),
|
||||||
|
)
|
||||||
|
directCallDomainEventPublisher.register(directCallEventMessageHandler)
|
||||||
|
container
|
||||||
|
.bind<DomainEventMessageHandlerInterface>(TYPES.Auth_DomainEventMessageHandler)
|
||||||
|
.toConstantValue(directCallEventMessageHandler)
|
||||||
|
} else {
|
||||||
container
|
container
|
||||||
.bind<DomainEventMessageHandlerInterface>(TYPES.Auth_DomainEventMessageHandler)
|
.bind<DomainEventMessageHandlerInterface>(TYPES.Auth_DomainEventMessageHandler)
|
||||||
.toConstantValue(
|
.toConstantValue(
|
||||||
@@ -963,6 +999,7 @@ export class ContainerConfigLoader {
|
|||||||
? new SQSNewRelicEventMessageHandler(eventHandlers, container.get(TYPES.Auth_Logger))
|
? new SQSNewRelicEventMessageHandler(eventHandlers, container.get(TYPES.Auth_Logger))
|
||||||
: new SQSEventMessageHandler(eventHandlers, container.get(TYPES.Auth_Logger)),
|
: new SQSEventMessageHandler(eventHandlers, container.get(TYPES.Auth_Logger)),
|
||||||
)
|
)
|
||||||
|
|
||||||
container
|
container
|
||||||
.bind<DomainEventSubscriberFactoryInterface>(TYPES.Auth_DomainEventSubscriberFactory)
|
.bind<DomainEventSubscriberFactoryInterface>(TYPES.Auth_DomainEventSubscriberFactory)
|
||||||
.toConstantValue(
|
.toConstantValue(
|
||||||
@@ -972,6 +1009,7 @@ export class ContainerConfigLoader {
|
|||||||
container.get(TYPES.Auth_DomainEventMessageHandler),
|
container.get(TYPES.Auth_DomainEventMessageHandler),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
container
|
container
|
||||||
.bind<InversifyExpressAuthController>(TYPES.Auth_InversifyExpressAuthController)
|
.bind<InversifyExpressAuthController>(TYPES.Auth_InversifyExpressAuthController)
|
||||||
@@ -987,6 +1025,9 @@ export class ContainerConfigLoader {
|
|||||||
container.get(TYPES.Auth_ControllerContainer),
|
container.get(TYPES.Auth_ControllerContainer),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Inversify Controllers
|
||||||
|
if (isConfiguredForHomeServer) {
|
||||||
container
|
container
|
||||||
.bind<InversifyExpressAuthenticatorsController>(TYPES.Auth_InversifyExpressAuthenticatorsController)
|
.bind<InversifyExpressAuthenticatorsController>(TYPES.Auth_InversifyExpressAuthenticatorsController)
|
||||||
.toConstantValue(
|
.toConstantValue(
|
||||||
@@ -1020,6 +1061,132 @@ export class ContainerConfigLoader {
|
|||||||
container.get(TYPES.Auth_ControllerContainer),
|
container.get(TYPES.Auth_ControllerContainer),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
container
|
||||||
|
.bind<InversifyExpressSessionsController>(TYPES.Auth_SessionsController)
|
||||||
|
.toConstantValue(
|
||||||
|
new InversifyExpressSessionsController(
|
||||||
|
container.get(TYPES.Auth_GetActiveSessionsForUser),
|
||||||
|
container.get(TYPES.Auth_AuthenticateRequest),
|
||||||
|
container.get(TYPES.Auth_SessionProjector),
|
||||||
|
container.get(TYPES.Auth_CreateCrossServiceToken),
|
||||||
|
container.get(TYPES.Auth_ControllerContainer),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
container
|
||||||
|
.bind<InversifyExpressValetTokenController>(TYPES.Auth_InversifyExpressValetTokenController)
|
||||||
|
.toConstantValue(
|
||||||
|
new InversifyExpressValetTokenController(
|
||||||
|
container.get(TYPES.Auth_CreateValetToken),
|
||||||
|
container.get(TYPES.Auth_ControllerContainer),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
container
|
||||||
|
.bind<InversifyExpressUsersController>(TYPES.Auth_InversifyExpressUsersController)
|
||||||
|
.toConstantValue(
|
||||||
|
new InversifyExpressUsersController(
|
||||||
|
container.get(TYPES.Auth_UpdateUser),
|
||||||
|
container.get(TYPES.Auth_GetUserKeyParams),
|
||||||
|
container.get(TYPES.Auth_DeleteAccount),
|
||||||
|
container.get(TYPES.Auth_GetUserSubscription),
|
||||||
|
container.get(TYPES.Auth_ClearLoginAttempts),
|
||||||
|
container.get(TYPES.Auth_IncreaseLoginAttempts),
|
||||||
|
container.get(TYPES.Auth_ChangeCredentials),
|
||||||
|
container.get(TYPES.Auth_ControllerContainer),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
container
|
||||||
|
.bind<InversifyExpressAdminController>(TYPES.Auth_InversifyExpressAdminController)
|
||||||
|
.toConstantValue(
|
||||||
|
new InversifyExpressAdminController(
|
||||||
|
container.get(TYPES.Auth_DeleteSetting),
|
||||||
|
container.get(TYPES.Auth_UserRepository),
|
||||||
|
container.get(TYPES.Auth_CreateSubscriptionToken),
|
||||||
|
container.get(TYPES.Auth_CreateOfflineSubscriptionToken),
|
||||||
|
container.get(TYPES.Auth_ControllerContainer),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
container
|
||||||
|
.bind<InversifyExpressSubscriptionTokensController>(TYPES.Auth_InversifyExpressSubscriptionTokensController)
|
||||||
|
.toConstantValue(
|
||||||
|
new InversifyExpressSubscriptionTokensController(
|
||||||
|
container.get(TYPES.Auth_CreateSubscriptionToken),
|
||||||
|
container.get(TYPES.Auth_AuthenticateSubscriptionToken),
|
||||||
|
container.get(TYPES.Auth_SettingService),
|
||||||
|
container.get(TYPES.Auth_UserProjector),
|
||||||
|
container.get(TYPES.Auth_RoleProjector),
|
||||||
|
container.get(TYPES.Auth_CrossServiceTokenEncoder),
|
||||||
|
container.get(TYPES.Auth_AUTH_JWT_TTL),
|
||||||
|
container.get(TYPES.Auth_ControllerContainer),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
container
|
||||||
|
.bind<InversifyExpressSubscriptionSettingsController>(TYPES.Auth_InversifyExpressSubscriptionSettingsController)
|
||||||
|
.toConstantValue(
|
||||||
|
new InversifyExpressSubscriptionSettingsController(
|
||||||
|
container.get(TYPES.Auth_GetSetting),
|
||||||
|
container.get(TYPES.Auth_ControllerContainer),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
container
|
||||||
|
.bind<InversifyExpressSettingsController>(TYPES.Auth_InversifyExpressSettingsController)
|
||||||
|
.toConstantValue(
|
||||||
|
new InversifyExpressSettingsController(
|
||||||
|
container.get(TYPES.Auth_GetSettings),
|
||||||
|
container.get(TYPES.Auth_GetSetting),
|
||||||
|
container.get(TYPES.Auth_UpdateSetting),
|
||||||
|
container.get(TYPES.Auth_DeleteSetting),
|
||||||
|
container.get(TYPES.Auth_ControllerContainer),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
container
|
||||||
|
.bind<InversifyExpressSessionController>(TYPES.Auth_InversifyExpressSessionController)
|
||||||
|
.toConstantValue(
|
||||||
|
new InversifyExpressSessionController(
|
||||||
|
container.get(TYPES.Auth_DeleteSessionForUser),
|
||||||
|
container.get(TYPES.Auth_DeletePreviousSessionsForUser),
|
||||||
|
container.get(TYPES.Auth_RefreshSessionToken),
|
||||||
|
container.get(TYPES.Auth_ControllerContainer),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
container
|
||||||
|
.bind<InversifyExpressOfflineController>(TYPES.Auth_InversifyExpressOfflineController)
|
||||||
|
.toConstantValue(
|
||||||
|
new InversifyExpressOfflineController(
|
||||||
|
container.get(TYPES.Auth_GetUserFeatures),
|
||||||
|
container.get(TYPES.Auth_GetUserOfflineSubscription),
|
||||||
|
container.get(TYPES.Auth_CreateOfflineSubscriptionToken),
|
||||||
|
container.get(TYPES.Auth_AuthenticateOfflineSubscriptionToken),
|
||||||
|
container.get(TYPES.Auth_OfflineUserTokenEncoder),
|
||||||
|
container.get(TYPES.Auth_AUTH_JWT_TTL),
|
||||||
|
container.get(TYPES.Auth_Logger),
|
||||||
|
container.get(TYPES.Auth_ControllerContainer),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
container
|
||||||
|
.bind<InversifyExpressListedController>(TYPES.Auth_InversifyExpressListedController)
|
||||||
|
.toConstantValue(
|
||||||
|
new InversifyExpressListedController(
|
||||||
|
container.get(TYPES.Auth_CreateListedAccount),
|
||||||
|
container.get(TYPES.Auth_ControllerContainer),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
container
|
||||||
|
.bind<InversifyExpressInternalController>(TYPES.Auth_InversifyExpressInternalController)
|
||||||
|
.toConstantValue(
|
||||||
|
new InversifyExpressInternalController(
|
||||||
|
container.get(TYPES.Auth_GetUserFeatures),
|
||||||
|
container.get(TYPES.Auth_GetSetting),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
container
|
||||||
|
.bind<InversifyExpressFeaturesController>(TYPES.Auth_InversifyExpressFeaturesController)
|
||||||
|
.toConstantValue(
|
||||||
|
new InversifyExpressFeaturesController(
|
||||||
|
container.get(TYPES.Auth_GetUserFeatures),
|
||||||
|
container.get(TYPES.Auth_ControllerContainer),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
return container
|
return container
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,13 +6,15 @@ import {
|
|||||||
} from '@standardnotes/domain-core'
|
} from '@standardnotes/domain-core'
|
||||||
|
|
||||||
import { ContainerConfigLoader } from './Container'
|
import { ContainerConfigLoader } from './Container'
|
||||||
|
import { DirectCallDomainEventPublisher } from '@standardnotes/domain-events-infra'
|
||||||
|
|
||||||
export class Service implements ServiceInterface {
|
export class Service implements ServiceInterface {
|
||||||
constructor(
|
constructor(
|
||||||
private serviceContainer: ServiceContainerInterface,
|
private serviceContainer: ServiceContainerInterface,
|
||||||
private controllerContainer: ControllerContainerInterface,
|
private controllerContainer: ControllerContainerInterface,
|
||||||
|
private directCallDomainEventPublisher: DirectCallDomainEventPublisher,
|
||||||
) {
|
) {
|
||||||
this.serviceContainer.register(ServiceIdentifier.create(ServiceIdentifier.NAMES.Auth).getValue(), this)
|
this.serviceContainer.register(this.getId(), this)
|
||||||
}
|
}
|
||||||
|
|
||||||
async handleRequest(request: never, response: never, endpointOrMethodIdentifier: string): Promise<unknown> {
|
async handleRequest(request: never, response: never, endpointOrMethodIdentifier: string): Promise<unknown> {
|
||||||
@@ -28,7 +30,10 @@ export class Service implements ServiceInterface {
|
|||||||
async getContainer(): Promise<unknown> {
|
async getContainer(): Promise<unknown> {
|
||||||
const config = new ContainerConfigLoader()
|
const config = new ContainerConfigLoader()
|
||||||
|
|
||||||
return config.load(this.controllerContainer)
|
return config.load({
|
||||||
|
controllerConatiner: this.controllerContainer,
|
||||||
|
directCallDomainEventPublisher: this.directCallDomainEventPublisher,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
getId(): ServiceIdentifier {
|
getId(): ServiceIdentifier {
|
||||||
|
|||||||
@@ -51,11 +51,10 @@ const TYPES = {
|
|||||||
Auth_ORMAuthenticatorChallengeRepository: Symbol.for('Auth_ORMAuthenticatorChallengeRepository'),
|
Auth_ORMAuthenticatorChallengeRepository: Symbol.for('Auth_ORMAuthenticatorChallengeRepository'),
|
||||||
Auth_ORMCacheEntryRepository: Symbol.for('Auth_ORMCacheEntryRepository'),
|
Auth_ORMCacheEntryRepository: Symbol.for('Auth_ORMCacheEntryRepository'),
|
||||||
// Middleware
|
// Middleware
|
||||||
Auth_AuthMiddleware: Symbol.for('Auth_AuthMiddleware'),
|
Auth_RequiredCrossServiceTokenMiddleware: Symbol.for('Auth_RequiredCrossServiceTokenMiddleware'),
|
||||||
Auth_ApiGatewayAuthMiddleware: Symbol.for('Auth_ApiGatewayAuthMiddleware'),
|
Auth_OptionalCrossServiceTokenMiddleware: Symbol.for('Auth_OptionalCrossServiceTokenMiddleware'),
|
||||||
Auth_ApiGatewayOfflineAuthMiddleware: Symbol.for('Auth_ApiGatewayOfflineAuthMiddleware'),
|
Auth_ApiGatewayOfflineAuthMiddleware: Symbol.for('Auth_ApiGatewayOfflineAuthMiddleware'),
|
||||||
Auth_OfflineUserAuthMiddleware: Symbol.for('Auth_OfflineUserAuthMiddleware'),
|
Auth_OfflineUserAuthMiddleware: Symbol.for('Auth_OfflineUserAuthMiddleware'),
|
||||||
Auth_AuthMiddlewareWithoutResponse: Symbol.for('Auth_AuthMiddlewareWithoutResponse'),
|
|
||||||
Auth_LockMiddleware: Symbol.for('Auth_LockMiddleware'),
|
Auth_LockMiddleware: Symbol.for('Auth_LockMiddleware'),
|
||||||
Auth_SessionMiddleware: Symbol.for('Auth_SessionMiddleware'),
|
Auth_SessionMiddleware: Symbol.for('Auth_SessionMiddleware'),
|
||||||
// Projectors
|
// Projectors
|
||||||
@@ -222,6 +221,20 @@ const TYPES = {
|
|||||||
Auth_InversifyExpressSubscriptionInvitesController: Symbol.for('Auth_InversifyExpressSubscriptionInvitesController'),
|
Auth_InversifyExpressSubscriptionInvitesController: Symbol.for('Auth_InversifyExpressSubscriptionInvitesController'),
|
||||||
Auth_InversifyExpressUserRequestsController: Symbol.for('Auth_InversifyExpressUserRequestsController'),
|
Auth_InversifyExpressUserRequestsController: Symbol.for('Auth_InversifyExpressUserRequestsController'),
|
||||||
Auth_InversifyExpressWebSocketsController: Symbol.for('Auth_InversifyExpressWebSocketsController'),
|
Auth_InversifyExpressWebSocketsController: Symbol.for('Auth_InversifyExpressWebSocketsController'),
|
||||||
|
Auth_SessionsController: Symbol.for('Auth_SessionsController'),
|
||||||
|
Auth_InversifyExpressValetTokenController: Symbol.for('Auth_InversifyExpressValetTokenController'),
|
||||||
|
Auth_InversifyExpressUsersController: Symbol.for('Auth_InversifyExpressUsersController'),
|
||||||
|
Auth_InversifyExpressAdminController: Symbol.for('Auth_InversifyExpressAdminController'),
|
||||||
|
Auth_InversifyExpressSubscriptionTokensController: Symbol.for('Auth_InversifyExpressSubscriptionTokensController'),
|
||||||
|
Auth_InversifyExpressSubscriptionSettingsController: Symbol.for(
|
||||||
|
'Auth_InversifyExpressSubscriptionSettingsController',
|
||||||
|
),
|
||||||
|
Auth_InversifyExpressSettingsController: Symbol.for('Auth_InversifyExpressSettingsController'),
|
||||||
|
Auth_InversifyExpressSessionController: Symbol.for('Auth_InversifyExpressSessionController'),
|
||||||
|
Auth_InversifyExpressOfflineController: Symbol.for('Auth_InversifyExpressOfflineController'),
|
||||||
|
Auth_InversifyExpressListedController: Symbol.for('Auth_InversifyExpressListedController'),
|
||||||
|
Auth_InversifyExpressInternalController: Symbol.for('Auth_InversifyExpressInternalController'),
|
||||||
|
Auth_InversifyExpressFeaturesController: Symbol.for('Auth_InversifyExpressFeaturesController'),
|
||||||
}
|
}
|
||||||
|
|
||||||
export default TYPES
|
export default TYPES
|
||||||
|
|||||||
@@ -1,99 +0,0 @@
|
|||||||
import 'reflect-metadata'
|
|
||||||
|
|
||||||
import { ApiGatewayAuthMiddleware } from './ApiGatewayAuthMiddleware'
|
|
||||||
import { NextFunction, Request, Response } from 'express'
|
|
||||||
import { Logger } from 'winston'
|
|
||||||
import { CrossServiceTokenData, TokenDecoderInterface } from '@standardnotes/security'
|
|
||||||
import { RoleName } from '@standardnotes/domain-core'
|
|
||||||
|
|
||||||
describe('ApiGatewayAuthMiddleware', () => {
|
|
||||||
let tokenDecoder: TokenDecoderInterface<CrossServiceTokenData>
|
|
||||||
let request: Request
|
|
||||||
let response: Response
|
|
||||||
let next: NextFunction
|
|
||||||
|
|
||||||
const logger = {
|
|
||||||
debug: jest.fn(),
|
|
||||||
} as unknown as jest.Mocked<Logger>
|
|
||||||
|
|
||||||
const createMiddleware = () => new ApiGatewayAuthMiddleware(tokenDecoder, logger)
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
tokenDecoder = {} as jest.Mocked<TokenDecoderInterface<CrossServiceTokenData>>
|
|
||||||
tokenDecoder.decodeToken = jest.fn().mockReturnValue({
|
|
||||||
user: {
|
|
||||||
uuid: '1-2-3',
|
|
||||||
email: 'test@test.te',
|
|
||||||
},
|
|
||||||
roles: [
|
|
||||||
{
|
|
||||||
uuid: 'a-b-c',
|
|
||||||
name: RoleName.NAMES.CoreUser,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
})
|
|
||||||
|
|
||||||
request = {
|
|
||||||
headers: {},
|
|
||||||
} as jest.Mocked<Request>
|
|
||||||
response = {
|
|
||||||
locals: {},
|
|
||||||
} as jest.Mocked<Response>
|
|
||||||
response.status = jest.fn().mockReturnThis()
|
|
||||||
response.send = jest.fn()
|
|
||||||
next = jest.fn()
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should authorize user', async () => {
|
|
||||||
request.headers['x-auth-token'] = 'auth-jwt-token'
|
|
||||||
|
|
||||||
await createMiddleware().handler(request, response, next)
|
|
||||||
|
|
||||||
expect(response.locals.user).toEqual({
|
|
||||||
uuid: '1-2-3',
|
|
||||||
email: 'test@test.te',
|
|
||||||
})
|
|
||||||
expect(response.locals.roles).toEqual([
|
|
||||||
{
|
|
||||||
uuid: 'a-b-c',
|
|
||||||
name: RoleName.NAMES.CoreUser,
|
|
||||||
},
|
|
||||||
])
|
|
||||||
|
|
||||||
expect(next).toHaveBeenCalled()
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should not authorize if request is missing auth jwt token in headers', async () => {
|
|
||||||
await createMiddleware().handler(request, response, next)
|
|
||||||
|
|
||||||
expect(response.status).toHaveBeenCalledWith(401)
|
|
||||||
expect(next).not.toHaveBeenCalled()
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should not authorize if auth jwt token is malformed', async () => {
|
|
||||||
request.headers['x-auth-token'] = 'auth-jwt-token'
|
|
||||||
|
|
||||||
tokenDecoder.decodeToken = jest.fn().mockReturnValue(undefined)
|
|
||||||
|
|
||||||
await createMiddleware().handler(request, response, next)
|
|
||||||
|
|
||||||
expect(response.status).toHaveBeenCalledWith(401)
|
|
||||||
expect(next).not.toHaveBeenCalled()
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should pass the error to next middleware if one occurres', async () => {
|
|
||||||
request.headers['x-auth-token'] = 'auth-jwt-token'
|
|
||||||
|
|
||||||
const error = new Error('Ooops')
|
|
||||||
|
|
||||||
tokenDecoder.decodeToken = jest.fn().mockImplementation(() => {
|
|
||||||
throw error
|
|
||||||
})
|
|
||||||
|
|
||||||
await createMiddleware().handler(request, response, next)
|
|
||||||
|
|
||||||
expect(response.status).not.toHaveBeenCalled()
|
|
||||||
|
|
||||||
expect(next).toHaveBeenCalledWith(error)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
import 'reflect-metadata'
|
|
||||||
|
|
||||||
import { AuthMiddleware } from './AuthMiddleware'
|
|
||||||
import { NextFunction, Request, Response } from 'express'
|
|
||||||
import { User } from '../Domain/User/User'
|
|
||||||
import { AuthenticateRequest } from '../Domain/UseCase/AuthenticateRequest'
|
|
||||||
import { Session } from '../Domain/Session/Session'
|
|
||||||
import { Logger } from 'winston'
|
|
||||||
|
|
||||||
describe('AuthMiddleware', () => {
|
|
||||||
let authenticateRequest: AuthenticateRequest
|
|
||||||
let request: Request
|
|
||||||
let response: Response
|
|
||||||
let next: NextFunction
|
|
||||||
|
|
||||||
const logger = {
|
|
||||||
debug: jest.fn(),
|
|
||||||
} as unknown as jest.Mocked<Logger>
|
|
||||||
|
|
||||||
const createMiddleware = () => new AuthMiddleware(authenticateRequest, logger)
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
authenticateRequest = {} as jest.Mocked<AuthenticateRequest>
|
|
||||||
authenticateRequest.execute = jest.fn()
|
|
||||||
|
|
||||||
request = {
|
|
||||||
headers: {},
|
|
||||||
} as jest.Mocked<Request>
|
|
||||||
response = {
|
|
||||||
locals: {},
|
|
||||||
} as jest.Mocked<Response>
|
|
||||||
response.status = jest.fn().mockReturnThis()
|
|
||||||
response.send = jest.fn()
|
|
||||||
next = jest.fn()
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should authorize user', async () => {
|
|
||||||
const user = {} as jest.Mocked<User>
|
|
||||||
const session = {} as jest.Mocked<Session>
|
|
||||||
authenticateRequest.execute = jest.fn().mockReturnValue({
|
|
||||||
success: true,
|
|
||||||
user,
|
|
||||||
session,
|
|
||||||
})
|
|
||||||
|
|
||||||
await createMiddleware().handler(request, response, next)
|
|
||||||
|
|
||||||
expect(response.locals.user).toEqual(user)
|
|
||||||
expect(response.locals.session).toEqual(session)
|
|
||||||
|
|
||||||
expect(next).toHaveBeenCalled()
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should not authorize if request authentication fails', async () => {
|
|
||||||
authenticateRequest.execute = jest.fn().mockReturnValue({
|
|
||||||
success: false,
|
|
||||||
responseCode: 401,
|
|
||||||
})
|
|
||||||
|
|
||||||
await createMiddleware().handler(request, response, next)
|
|
||||||
|
|
||||||
expect(response.status).toHaveBeenCalledWith(401)
|
|
||||||
expect(next).not.toHaveBeenCalled()
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should pass the error to next middleware if one occurres', async () => {
|
|
||||||
const error = new Error('Ooops')
|
|
||||||
|
|
||||||
authenticateRequest.execute = jest.fn().mockImplementation(() => {
|
|
||||||
throw error
|
|
||||||
})
|
|
||||||
|
|
||||||
await createMiddleware().handler(request, response, next)
|
|
||||||
|
|
||||||
expect(response.status).not.toHaveBeenCalled()
|
|
||||||
|
|
||||||
expect(next).toHaveBeenCalledWith(error)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
import { NextFunction, Request, Response } from 'express'
|
|
||||||
import { inject, injectable } from 'inversify'
|
|
||||||
import { BaseMiddleware } from 'inversify-express-utils'
|
|
||||||
import { Logger } from 'winston'
|
|
||||||
import TYPES from '../Bootstrap/Types'
|
|
||||||
import { AuthenticateRequest } from '../Domain/UseCase/AuthenticateRequest'
|
|
||||||
|
|
||||||
@injectable()
|
|
||||||
export class AuthMiddleware extends BaseMiddleware {
|
|
||||||
constructor(
|
|
||||||
@inject(TYPES.Auth_AuthenticateRequest) private authenticateRequest: AuthenticateRequest,
|
|
||||||
@inject(TYPES.Auth_Logger) private logger: Logger,
|
|
||||||
) {
|
|
||||||
super()
|
|
||||||
}
|
|
||||||
|
|
||||||
async handler(request: Request, response: Response, next: NextFunction): Promise<void> {
|
|
||||||
try {
|
|
||||||
const authenticateRequestResponse = await this.authenticateRequest.execute({
|
|
||||||
authorizationHeader: request.headers.authorization,
|
|
||||||
})
|
|
||||||
|
|
||||||
if (!authenticateRequestResponse.success) {
|
|
||||||
this.logger.debug('AuthMiddleware authentication failure.')
|
|
||||||
|
|
||||||
response.status(authenticateRequestResponse.responseCode).send({
|
|
||||||
error: {
|
|
||||||
tag: authenticateRequestResponse.errorTag,
|
|
||||||
message: authenticateRequestResponse.errorMessage,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
response.locals.user = authenticateRequestResponse.user
|
|
||||||
response.locals.session = authenticateRequestResponse.session
|
|
||||||
response.locals.readOnlyAccess = authenticateRequestResponse.session?.readonlyAccess ?? false
|
|
||||||
|
|
||||||
return next()
|
|
||||||
} catch (error) {
|
|
||||||
return next(error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
import 'reflect-metadata'
|
|
||||||
|
|
||||||
import { AuthMiddlewareWithoutResponse } from './AuthMiddlewareWithoutResponse'
|
|
||||||
import { NextFunction, Request, Response } from 'express'
|
|
||||||
import { User } from '../Domain/User/User'
|
|
||||||
import { AuthenticateRequest } from '../Domain/UseCase/AuthenticateRequest'
|
|
||||||
import { Session } from '../Domain/Session/Session'
|
|
||||||
|
|
||||||
describe('AuthMiddlewareWithoutResponse', () => {
|
|
||||||
let authenticateRequest: AuthenticateRequest
|
|
||||||
let request: Request
|
|
||||||
let response: Response
|
|
||||||
let next: NextFunction
|
|
||||||
|
|
||||||
const createMiddleware = () => new AuthMiddlewareWithoutResponse(authenticateRequest)
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
authenticateRequest = {} as jest.Mocked<AuthenticateRequest>
|
|
||||||
authenticateRequest.execute = jest.fn()
|
|
||||||
|
|
||||||
request = {
|
|
||||||
headers: {},
|
|
||||||
} as jest.Mocked<Request>
|
|
||||||
response = {
|
|
||||||
locals: {},
|
|
||||||
} as jest.Mocked<Response>
|
|
||||||
response.status = jest.fn().mockReturnThis()
|
|
||||||
response.send = jest.fn()
|
|
||||||
next = jest.fn()
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should authorize user', async () => {
|
|
||||||
const user = {} as jest.Mocked<User>
|
|
||||||
const session = {} as jest.Mocked<Session>
|
|
||||||
authenticateRequest.execute = jest.fn().mockReturnValue({
|
|
||||||
success: true,
|
|
||||||
user,
|
|
||||||
session,
|
|
||||||
})
|
|
||||||
|
|
||||||
await createMiddleware().handler(request, response, next)
|
|
||||||
|
|
||||||
expect(response.locals.user).toEqual(user)
|
|
||||||
expect(response.locals.session).toEqual(session)
|
|
||||||
|
|
||||||
expect(next).toHaveBeenCalled()
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should skip middleware if authentication fails', async () => {
|
|
||||||
authenticateRequest.execute = jest.fn().mockReturnValue({
|
|
||||||
success: false,
|
|
||||||
})
|
|
||||||
|
|
||||||
await createMiddleware().handler(request, response, next)
|
|
||||||
|
|
||||||
expect(next).toHaveBeenCalled()
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should skip middleware if authentication errors', async () => {
|
|
||||||
authenticateRequest.execute = jest.fn().mockImplementation(() => {
|
|
||||||
throw new Error('Ooops')
|
|
||||||
})
|
|
||||||
|
|
||||||
await createMiddleware().handler(request, response, next)
|
|
||||||
|
|
||||||
expect(next).toHaveBeenCalled()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
import { NextFunction, Request, Response } from 'express'
|
|
||||||
import { inject, injectable } from 'inversify'
|
|
||||||
import { BaseMiddleware } from 'inversify-express-utils'
|
|
||||||
import TYPES from '../Bootstrap/Types'
|
|
||||||
import { AuthenticateRequest } from '../Domain/UseCase/AuthenticateRequest'
|
|
||||||
|
|
||||||
@injectable()
|
|
||||||
export class AuthMiddlewareWithoutResponse extends BaseMiddleware {
|
|
||||||
constructor(@inject(TYPES.Auth_AuthenticateRequest) private authenticateRequest: AuthenticateRequest) {
|
|
||||||
super()
|
|
||||||
}
|
|
||||||
|
|
||||||
async handler(request: Request, response: Response, next: NextFunction): Promise<void> {
|
|
||||||
try {
|
|
||||||
const authenticateRequestResponse = await this.authenticateRequest.execute({
|
|
||||||
authorizationHeader: request.headers.authorization,
|
|
||||||
})
|
|
||||||
|
|
||||||
if (!authenticateRequestResponse.success) {
|
|
||||||
return next()
|
|
||||||
}
|
|
||||||
|
|
||||||
response.locals.user = authenticateRequestResponse.user
|
|
||||||
response.locals.session = authenticateRequestResponse.session
|
|
||||||
response.locals.readOnlyAccess = authenticateRequestResponse.session?.readonlyAccess ?? false
|
|
||||||
|
|
||||||
return next()
|
|
||||||
} catch (error) {
|
|
||||||
return next()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -11,6 +11,7 @@ import { User } from '../../User/User'
|
|||||||
import { UserRepositoryInterface } from '../../User/UserRepositoryInterface'
|
import { UserRepositoryInterface } from '../../User/UserRepositoryInterface'
|
||||||
|
|
||||||
import { ChangeCredentials } from './ChangeCredentials'
|
import { ChangeCredentials } from './ChangeCredentials'
|
||||||
|
import { Username } from '@standardnotes/domain-core'
|
||||||
|
|
||||||
describe('ChangeCredentials', () => {
|
describe('ChangeCredentials', () => {
|
||||||
let userRepository: UserRepositoryInterface
|
let userRepository: UserRepositoryInterface
|
||||||
@@ -25,9 +26,6 @@ describe('ChangeCredentials', () => {
|
|||||||
new ChangeCredentials(userRepository, authResponseFactoryResolver, domainEventPublisher, domainEventFactory, timer)
|
new ChangeCredentials(userRepository, authResponseFactoryResolver, domainEventPublisher, domainEventFactory, timer)
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
userRepository = {} as jest.Mocked<UserRepositoryInterface>
|
|
||||||
userRepository.save = jest.fn()
|
|
||||||
|
|
||||||
authResponseFactory = {} as jest.Mocked<AuthResponseFactoryInterface>
|
authResponseFactory = {} as jest.Mocked<AuthResponseFactoryInterface>
|
||||||
authResponseFactory.createResponse = jest.fn().mockReturnValue({ foo: 'bar' })
|
authResponseFactory.createResponse = jest.fn().mockReturnValue({ foo: 'bar' })
|
||||||
|
|
||||||
@@ -39,6 +37,10 @@ describe('ChangeCredentials', () => {
|
|||||||
user.uuid = '1-2-3'
|
user.uuid = '1-2-3'
|
||||||
user.email = 'test@test.te'
|
user.email = 'test@test.te'
|
||||||
|
|
||||||
|
userRepository = {} as jest.Mocked<UserRepositoryInterface>
|
||||||
|
userRepository.save = jest.fn()
|
||||||
|
userRepository.findOneByUsernameOrEmail = jest.fn().mockReturnValue(user)
|
||||||
|
|
||||||
domainEventPublisher = {} as jest.Mocked<DomainEventPublisherInterface>
|
domainEventPublisher = {} as jest.Mocked<DomainEventPublisherInterface>
|
||||||
domainEventPublisher.publish = jest.fn()
|
domainEventPublisher.publish = jest.fn()
|
||||||
|
|
||||||
@@ -52,7 +54,7 @@ describe('ChangeCredentials', () => {
|
|||||||
it('should change password', async () => {
|
it('should change password', async () => {
|
||||||
expect(
|
expect(
|
||||||
await createUseCase().execute({
|
await createUseCase().execute({
|
||||||
user,
|
username: Username.create('test@test.te').getValue(),
|
||||||
apiVersion: '20190520',
|
apiVersion: '20190520',
|
||||||
currentPassword: 'qweqwe123123',
|
currentPassword: 'qweqwe123123',
|
||||||
newPassword: 'test234',
|
newPassword: 'test234',
|
||||||
@@ -82,11 +84,11 @@ describe('ChangeCredentials', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should change email', async () => {
|
it('should change email', async () => {
|
||||||
userRepository.findOneByUsernameOrEmail = jest.fn().mockReturnValue(null)
|
userRepository.findOneByUsernameOrEmail = jest.fn().mockReturnValueOnce(user).mockReturnValueOnce(null)
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
await createUseCase().execute({
|
await createUseCase().execute({
|
||||||
user,
|
username: Username.create('test@test.te').getValue(),
|
||||||
apiVersion: '20190520',
|
apiVersion: '20190520',
|
||||||
currentPassword: 'qweqwe123123',
|
currentPassword: 'qweqwe123123',
|
||||||
newPassword: 'test234',
|
newPassword: 'test234',
|
||||||
@@ -117,11 +119,14 @@ describe('ChangeCredentials', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should not change email if already taken', async () => {
|
it('should not change email if already taken', async () => {
|
||||||
userRepository.findOneByUsernameOrEmail = jest.fn().mockReturnValue({} as jest.Mocked<User>)
|
userRepository.findOneByUsernameOrEmail = jest
|
||||||
|
.fn()
|
||||||
|
.mockReturnValueOnce(user)
|
||||||
|
.mockReturnValueOnce({} as jest.Mocked<User>)
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
await createUseCase().execute({
|
await createUseCase().execute({
|
||||||
user,
|
username: Username.create('test@test.te').getValue(),
|
||||||
apiVersion: '20190520',
|
apiVersion: '20190520',
|
||||||
currentPassword: 'qweqwe123123',
|
currentPassword: 'qweqwe123123',
|
||||||
newPassword: 'test234',
|
newPassword: 'test234',
|
||||||
@@ -144,7 +149,7 @@ describe('ChangeCredentials', () => {
|
|||||||
it('should not change email if the new email is invalid', async () => {
|
it('should not change email if the new email is invalid', async () => {
|
||||||
expect(
|
expect(
|
||||||
await createUseCase().execute({
|
await createUseCase().execute({
|
||||||
user,
|
username: Username.create('test@test.te').getValue(),
|
||||||
apiVersion: '20190520',
|
apiVersion: '20190520',
|
||||||
currentPassword: 'qweqwe123123',
|
currentPassword: 'qweqwe123123',
|
||||||
newPassword: 'test234',
|
newPassword: 'test234',
|
||||||
@@ -164,10 +169,35 @@ describe('ChangeCredentials', () => {
|
|||||||
expect(domainEventPublisher.publish).not.toHaveBeenCalled()
|
expect(domainEventPublisher.publish).not.toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should not change email if the user is not found', async () => {
|
||||||
|
userRepository.findOneByUsernameOrEmail = jest.fn().mockReturnValue(null)
|
||||||
|
|
||||||
|
expect(
|
||||||
|
await createUseCase().execute({
|
||||||
|
username: Username.create('test@test.te').getValue(),
|
||||||
|
apiVersion: '20190520',
|
||||||
|
currentPassword: 'qweqwe123123',
|
||||||
|
newPassword: 'test234',
|
||||||
|
newEmail: '',
|
||||||
|
pwNonce: 'asdzxc',
|
||||||
|
updatedWithUserAgent: 'Google Chrome',
|
||||||
|
kpCreated: '123',
|
||||||
|
kpOrigination: 'password-change',
|
||||||
|
}),
|
||||||
|
).toEqual({
|
||||||
|
success: false,
|
||||||
|
errorMessage: 'User not found.',
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(userRepository.save).not.toHaveBeenCalled()
|
||||||
|
expect(domainEventFactory.createUserEmailChangedEvent).not.toHaveBeenCalled()
|
||||||
|
expect(domainEventPublisher.publish).not.toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
|
||||||
it('should not change password if current password is incorrect', async () => {
|
it('should not change password if current password is incorrect', async () => {
|
||||||
expect(
|
expect(
|
||||||
await createUseCase().execute({
|
await createUseCase().execute({
|
||||||
user,
|
username: Username.create('test@test.te').getValue(),
|
||||||
apiVersion: '20190520',
|
apiVersion: '20190520',
|
||||||
currentPassword: 'test123',
|
currentPassword: 'test123',
|
||||||
newPassword: 'test234',
|
newPassword: 'test234',
|
||||||
@@ -185,7 +215,7 @@ describe('ChangeCredentials', () => {
|
|||||||
it('should update protocol version while changing password', async () => {
|
it('should update protocol version while changing password', async () => {
|
||||||
expect(
|
expect(
|
||||||
await createUseCase().execute({
|
await createUseCase().execute({
|
||||||
user,
|
username: Username.create('test@test.te').getValue(),
|
||||||
apiVersion: '20190520',
|
apiVersion: '20190520',
|
||||||
currentPassword: 'qweqwe123123',
|
currentPassword: 'qweqwe123123',
|
||||||
newPassword: 'test234',
|
newPassword: 'test234',
|
||||||
|
|||||||
@@ -25,14 +25,22 @@ export class ChangeCredentials implements UseCaseInterface {
|
|||||||
) {}
|
) {}
|
||||||
|
|
||||||
async execute(dto: ChangeCredentialsDTO): Promise<ChangeCredentialsResponse> {
|
async execute(dto: ChangeCredentialsDTO): Promise<ChangeCredentialsResponse> {
|
||||||
if (!(await bcrypt.compare(dto.currentPassword, dto.user.encryptedPassword))) {
|
const user = await this.userRepository.findOneByUsernameOrEmail(dto.username)
|
||||||
|
if (!user) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
errorMessage: 'User not found.',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(await bcrypt.compare(dto.currentPassword, user.encryptedPassword))) {
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
errorMessage: 'The current password you entered is incorrect. Please try again.',
|
errorMessage: 'The current password you entered is incorrect. Please try again.',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dto.user.encryptedPassword = await bcrypt.hash(dto.newPassword, User.PASSWORD_HASH_COST)
|
user.encryptedPassword = await bcrypt.hash(dto.newPassword, User.PASSWORD_HASH_COST)
|
||||||
|
|
||||||
let userEmailChangedEvent: UserEmailChangedEvent | undefined = undefined
|
let userEmailChangedEvent: UserEmailChangedEvent | undefined = undefined
|
||||||
if (dto.newEmail !== undefined) {
|
if (dto.newEmail !== undefined) {
|
||||||
@@ -54,27 +62,27 @@ export class ChangeCredentials implements UseCaseInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
userEmailChangedEvent = this.domainEventFactory.createUserEmailChangedEvent(
|
userEmailChangedEvent = this.domainEventFactory.createUserEmailChangedEvent(
|
||||||
dto.user.uuid,
|
user.uuid,
|
||||||
dto.user.email,
|
user.email,
|
||||||
newUsername.value,
|
newUsername.value,
|
||||||
)
|
)
|
||||||
|
|
||||||
dto.user.email = newUsername.value
|
user.email = newUsername.value
|
||||||
}
|
}
|
||||||
|
|
||||||
dto.user.pwNonce = dto.pwNonce
|
user.pwNonce = dto.pwNonce
|
||||||
if (dto.protocolVersion) {
|
if (dto.protocolVersion) {
|
||||||
dto.user.version = dto.protocolVersion
|
user.version = dto.protocolVersion
|
||||||
}
|
}
|
||||||
if (dto.kpCreated) {
|
if (dto.kpCreated) {
|
||||||
dto.user.kpCreated = dto.kpCreated
|
user.kpCreated = dto.kpCreated
|
||||||
}
|
}
|
||||||
if (dto.kpOrigination) {
|
if (dto.kpOrigination) {
|
||||||
dto.user.kpOrigination = dto.kpOrigination
|
user.kpOrigination = dto.kpOrigination
|
||||||
}
|
}
|
||||||
dto.user.updatedAt = this.timer.getUTCDate()
|
user.updatedAt = this.timer.getUTCDate()
|
||||||
|
|
||||||
const updatedUser = await this.userRepository.save(dto.user)
|
const updatedUser = await this.userRepository.save(user)
|
||||||
|
|
||||||
if (userEmailChangedEvent !== undefined) {
|
if (userEmailChangedEvent !== undefined) {
|
||||||
await this.domainEventPublisher.publish(userEmailChangedEvent)
|
await this.domainEventPublisher.publish(userEmailChangedEvent)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { User } from '../../User/User'
|
import { Username } from '@standardnotes/domain-core'
|
||||||
|
|
||||||
export type ChangeCredentialsDTO = {
|
export type ChangeCredentialsDTO = {
|
||||||
user: User
|
username: Username
|
||||||
apiVersion: string
|
apiVersion: string
|
||||||
currentPassword: string
|
currentPassword: string
|
||||||
newPassword: string
|
newPassword: string
|
||||||
|
|||||||
@@ -35,9 +35,7 @@ describe('GetUserKeyParams', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should get key params for an authenticated user - searching by email', async () => {
|
it('should get key params for an authenticated user - searching by email', async () => {
|
||||||
expect(
|
expect(await createUseCase().execute({ email: 'test@test.te', authenticated: true })).toEqual({
|
||||||
await createUseCase().execute({ email: 'test@test.te', authenticated: true, authenticatedUser: user }),
|
|
||||||
).toEqual({
|
|
||||||
keyParams: {
|
keyParams: {
|
||||||
foo: 'bar',
|
foo: 'bar',
|
||||||
},
|
},
|
||||||
@@ -63,7 +61,7 @@ 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, authenticatedUser: user })).toEqual({
|
expect(await createUseCase().execute({ userUuid: '1-2-3', authenticated: true })).toEqual({
|
||||||
keyParams: {
|
keyParams: {
|
||||||
foo: 'bar',
|
foo: 'bar',
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -22,16 +22,6 @@ export class GetUserKeyParams implements UseCaseInterface {
|
|||||||
) {}
|
) {}
|
||||||
|
|
||||||
async execute(dto: GetUserKeyParamsDTO): Promise<GetUserKeyParamsResponse> {
|
async execute(dto: GetUserKeyParamsDTO): Promise<GetUserKeyParamsResponse> {
|
||||||
if (dto.authenticatedUser) {
|
|
||||||
this.logger.debug(`Creating key params for authenticated user ${dto.authenticatedUser.email}`)
|
|
||||||
|
|
||||||
const keyParams = await this.createKeyParams(dto, dto.authenticatedUser, true)
|
|
||||||
|
|
||||||
return {
|
|
||||||
keyParams,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let user: User | null = null
|
let user: User | null = null
|
||||||
if (dto.email !== undefined) {
|
if (dto.email !== undefined) {
|
||||||
const usernameOrError = Username.create(dto.email)
|
const usernameOrError = Username.create(dto.email)
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
import { User } from '../../User/User'
|
|
||||||
|
|
||||||
export type GetUserKeyParamsDTOV1Unchallenged = {
|
export type GetUserKeyParamsDTOV1Unchallenged = {
|
||||||
authenticated: boolean
|
authenticated: boolean
|
||||||
email?: string
|
email?: string
|
||||||
userUuid?: string
|
userUuid?: string
|
||||||
authenticatedUser?: User
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
import { User } from '../../User/User'
|
|
||||||
|
|
||||||
export type GetUserKeyParamsDTOV2Challenged = {
|
export type GetUserKeyParamsDTOV2Challenged = {
|
||||||
authenticated: boolean
|
authenticated: boolean
|
||||||
codeChallenge: string
|
codeChallenge: string
|
||||||
email?: string
|
email?: string
|
||||||
userUuid?: string
|
userUuid?: string
|
||||||
authenticatedUser?: User
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
import 'reflect-metadata'
|
import 'reflect-metadata'
|
||||||
|
|
||||||
import { AdminController } from './AdminController'
|
import { InversifyExpressAdminController } from './InversifyExpressAdminController'
|
||||||
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'
|
||||||
import * as express from 'express'
|
import * as express from 'express'
|
||||||
import { DeleteSetting } from '../Domain/UseCase/DeleteSetting/DeleteSetting'
|
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'
|
||||||
import { ControllerContainerInterface } from '@standardnotes/domain-core'
|
import { ControllerContainerInterface } from '@standardnotes/domain-core'
|
||||||
|
|
||||||
describe('AdminController', () => {
|
describe('InversifyExpressAdminController', () => {
|
||||||
let deleteSetting: DeleteSetting
|
let deleteSetting: DeleteSetting
|
||||||
let userRepository: UserRepositoryInterface
|
let userRepository: UserRepositoryInterface
|
||||||
let createSubscriptionToken: CreateSubscriptionToken
|
let createSubscriptionToken: CreateSubscriptionToken
|
||||||
@@ -20,7 +20,7 @@ describe('AdminController', () => {
|
|||||||
let controllerContainer: ControllerContainerInterface
|
let controllerContainer: ControllerContainerInterface
|
||||||
|
|
||||||
const createController = () =>
|
const createController = () =>
|
||||||
new AdminController(
|
new InversifyExpressAdminController(
|
||||||
deleteSetting,
|
deleteSetting,
|
||||||
userRepository,
|
userRepository,
|
||||||
createSubscriptionToken,
|
createSubscriptionToken,
|
||||||
@@ -11,14 +11,14 @@ import {
|
|||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
results,
|
results,
|
||||||
} from 'inversify-express-utils'
|
} from 'inversify-express-utils'
|
||||||
import TYPES from '../Bootstrap/Types'
|
import TYPES from '../../Bootstrap/Types'
|
||||||
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 AdminController extends BaseHttpController {
|
export class InversifyExpressAdminController extends BaseHttpController {
|
||||||
constructor(
|
constructor(
|
||||||
@inject(TYPES.Auth_DeleteSetting) private doDeleteSetting: DeleteSetting,
|
@inject(TYPES.Auth_DeleteSetting) private doDeleteSetting: DeleteSetting,
|
||||||
@inject(TYPES.Auth_UserRepository) private userRepository: UserRepositoryInterface,
|
@inject(TYPES.Auth_UserRepository) private userRepository: UserRepositoryInterface,
|
||||||
@@ -44,13 +44,12 @@ export class InversifyExpressAuthController extends BaseHttpController {
|
|||||||
this.controllerContainer.register('auth.signOut', this.signOut.bind(this))
|
this.controllerContainer.register('auth.signOut', this.signOut.bind(this))
|
||||||
}
|
}
|
||||||
|
|
||||||
@httpGet('/params', TYPES.Auth_AuthMiddlewareWithoutResponse)
|
@httpGet('/params', TYPES.Auth_OptionalCrossServiceTokenMiddleware)
|
||||||
async params(request: Request, response: Response): Promise<results.JsonResult> {
|
async params(request: Request, response: Response): Promise<results.JsonResult> {
|
||||||
if (response.locals.session) {
|
if (response.locals.session) {
|
||||||
const result = await this.getUserKeyParams.execute({
|
const result = await this.getUserKeyParams.execute({
|
||||||
email: response.locals.user.email,
|
email: response.locals.user.email,
|
||||||
authenticated: true,
|
authenticated: true,
|
||||||
authenticatedUser: response.locals.user,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return this.json(result.keyParams)
|
return this.json(result.keyParams)
|
||||||
@@ -155,7 +154,7 @@ export class InversifyExpressAuthController extends BaseHttpController {
|
|||||||
return this.json(signInResult.authResponse)
|
return this.json(signInResult.authResponse)
|
||||||
}
|
}
|
||||||
|
|
||||||
@httpPost('/pkce_params', TYPES.Auth_AuthMiddlewareWithoutResponse)
|
@httpPost('/pkce_params', TYPES.Auth_OptionalCrossServiceTokenMiddleware)
|
||||||
async pkceParams(request: Request, response: Response): Promise<results.JsonResult> {
|
async pkceParams(request: Request, response: Response): Promise<results.JsonResult> {
|
||||||
if (!request.body.code_challenge) {
|
if (!request.body.code_challenge) {
|
||||||
return this.json(
|
return this.json(
|
||||||
@@ -172,7 +171,6 @@ export class InversifyExpressAuthController extends BaseHttpController {
|
|||||||
const result = await this.getUserKeyParams.execute({
|
const result = await this.getUserKeyParams.execute({
|
||||||
email: response.locals.user.email,
|
email: response.locals.user.email,
|
||||||
authenticated: true,
|
authenticated: true,
|
||||||
authenticatedUser: response.locals.user,
|
|
||||||
codeChallenge: request.body.code_challenge as string,
|
codeChallenge: request.body.code_challenge as string,
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -261,7 +259,7 @@ export class InversifyExpressAuthController extends BaseHttpController {
|
|||||||
return this.json(signInResult.authResponse)
|
return this.json(signInResult.authResponse)
|
||||||
}
|
}
|
||||||
|
|
||||||
@httpPost('/recovery/codes', TYPES.Auth_ApiGatewayAuthMiddleware)
|
@httpPost('/recovery/codes', TYPES.Auth_RequiredCrossServiceTokenMiddleware)
|
||||||
async generateRecoveryCodes(_request: Request, response: Response): Promise<results.JsonResult> {
|
async generateRecoveryCodes(_request: Request, response: Response): Promise<results.JsonResult> {
|
||||||
const result = await this.authController.generateRecoveryCodes({
|
const result = await this.authController.generateRecoveryCodes({
|
||||||
userUuid: response.locals.user.uuid,
|
userUuid: response.locals.user.uuid,
|
||||||
@@ -296,7 +294,7 @@ export class InversifyExpressAuthController extends BaseHttpController {
|
|||||||
return this.json(result.data, result.status)
|
return this.json(result.data, result.status)
|
||||||
}
|
}
|
||||||
|
|
||||||
@httpPost('/sign_out', TYPES.Auth_AuthMiddlewareWithoutResponse)
|
@httpPost('/sign_out', TYPES.Auth_OptionalCrossServiceTokenMiddleware)
|
||||||
async signOut(request: Request, response: Response): Promise<results.JsonResult | void> {
|
async signOut(request: Request, response: Response): Promise<results.JsonResult | void> {
|
||||||
const result = await this.authController.signOut({
|
const result = await this.authController.signOut({
|
||||||
readOnlyAccess: response.locals.readOnlyAccess,
|
readOnlyAccess: response.locals.readOnlyAccess,
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ export class InversifyExpressAuthenticatorsController extends BaseHttpController
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@httpGet('/', TYPES.Auth_ApiGatewayAuthMiddleware)
|
@httpGet('/', TYPES.Auth_RequiredCrossServiceTokenMiddleware)
|
||||||
async list(_request: Request, response: Response): Promise<results.JsonResult> {
|
async list(_request: Request, response: Response): Promise<results.JsonResult> {
|
||||||
const result = await this.authenticatorsController.list({
|
const result = await this.authenticatorsController.list({
|
||||||
userUuid: response.locals.user.uuid,
|
userUuid: response.locals.user.uuid,
|
||||||
@@ -46,7 +46,7 @@ export class InversifyExpressAuthenticatorsController extends BaseHttpController
|
|||||||
return this.json(result.data, result.status)
|
return this.json(result.data, result.status)
|
||||||
}
|
}
|
||||||
|
|
||||||
@httpDelete('/:authenticatorId', TYPES.Auth_ApiGatewayAuthMiddleware)
|
@httpDelete('/:authenticatorId', TYPES.Auth_RequiredCrossServiceTokenMiddleware)
|
||||||
async delete(request: Request, response: Response): Promise<results.JsonResult> {
|
async delete(request: Request, response: Response): Promise<results.JsonResult> {
|
||||||
const result = await this.authenticatorsController.delete({
|
const result = await this.authenticatorsController.delete({
|
||||||
userUuid: response.locals.user.uuid,
|
userUuid: response.locals.user.uuid,
|
||||||
@@ -56,7 +56,7 @@ export class InversifyExpressAuthenticatorsController extends BaseHttpController
|
|||||||
return this.json(result.data, result.status)
|
return this.json(result.data, result.status)
|
||||||
}
|
}
|
||||||
|
|
||||||
@httpGet('/generate-registration-options', TYPES.Auth_ApiGatewayAuthMiddleware)
|
@httpGet('/generate-registration-options', TYPES.Auth_RequiredCrossServiceTokenMiddleware)
|
||||||
async generateRegistrationOptions(_request: Request, response: Response): Promise<results.JsonResult> {
|
async generateRegistrationOptions(_request: Request, response: Response): Promise<results.JsonResult> {
|
||||||
const result = await this.authenticatorsController.generateRegistrationOptions({
|
const result = await this.authenticatorsController.generateRegistrationOptions({
|
||||||
username: response.locals.user.email,
|
username: response.locals.user.email,
|
||||||
@@ -66,7 +66,7 @@ export class InversifyExpressAuthenticatorsController extends BaseHttpController
|
|||||||
return this.json(result.data, result.status)
|
return this.json(result.data, result.status)
|
||||||
}
|
}
|
||||||
|
|
||||||
@httpPost('/verify-registration', TYPES.Auth_ApiGatewayAuthMiddleware)
|
@httpPost('/verify-registration', TYPES.Auth_RequiredCrossServiceTokenMiddleware)
|
||||||
async verifyRegistration(request: Request, response: Response): Promise<results.JsonResult> {
|
async verifyRegistration(request: Request, response: Response): Promise<results.JsonResult> {
|
||||||
const result = await this.authenticatorsController.verifyRegistrationResponse({
|
const result = await this.authenticatorsController.verifyRegistrationResponse({
|
||||||
userUuid: response.locals.user.uuid,
|
userUuid: response.locals.user.uuid,
|
||||||
|
|||||||
@@ -2,13 +2,13 @@ import 'reflect-metadata'
|
|||||||
|
|
||||||
import * as express from 'express'
|
import * as express from 'express'
|
||||||
|
|
||||||
import { FeaturesController } from './FeaturesController'
|
import { InversifyExpressFeaturesController } from './InversifyExpressFeaturesController'
|
||||||
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 { ControllerContainerInterface } from '@standardnotes/domain-core'
|
import { ControllerContainerInterface } from '@standardnotes/domain-core'
|
||||||
|
|
||||||
describe('FeaturesController', () => {
|
describe('InversifyExpressFeaturesController', () => {
|
||||||
let getUserFeatures: GetUserFeatures
|
let getUserFeatures: GetUserFeatures
|
||||||
|
|
||||||
let request: express.Request
|
let request: express.Request
|
||||||
@@ -16,7 +16,7 @@ describe('FeaturesController', () => {
|
|||||||
let user: User
|
let user: User
|
||||||
let controllerContainer: ControllerContainerInterface
|
let controllerContainer: ControllerContainerInterface
|
||||||
|
|
||||||
const createController = () => new FeaturesController(getUserFeatures, controllerContainer)
|
const createController = () => new InversifyExpressFeaturesController(getUserFeatures, controllerContainer)
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
controllerContainer = {} as jest.Mocked<ControllerContainerInterface>
|
controllerContainer = {} as jest.Mocked<ControllerContainerInterface>
|
||||||
@@ -7,12 +7,12 @@ import {
|
|||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
results,
|
results,
|
||||||
} 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 { ControllerContainerInterface } from '@standardnotes/domain-core'
|
import { ControllerContainerInterface } from '@standardnotes/domain-core'
|
||||||
|
|
||||||
@controller('/users/:userUuid/features')
|
@controller('/users/:userUuid/features')
|
||||||
export class FeaturesController extends BaseHttpController {
|
export class InversifyExpressFeaturesController extends BaseHttpController {
|
||||||
constructor(
|
constructor(
|
||||||
@inject(TYPES.Auth_GetUserFeatures) private doGetUserFeatures: GetUserFeatures,
|
@inject(TYPES.Auth_GetUserFeatures) private doGetUserFeatures: GetUserFeatures,
|
||||||
@inject(TYPES.Auth_ControllerContainer) private controllerContainer: ControllerContainerInterface,
|
@inject(TYPES.Auth_ControllerContainer) private controllerContainer: ControllerContainerInterface,
|
||||||
@@ -22,7 +22,7 @@ export class FeaturesController extends BaseHttpController {
|
|||||||
this.controllerContainer.register('auth.users.getFeatures', this.getFeatures.bind(this))
|
this.controllerContainer.register('auth.users.getFeatures', this.getFeatures.bind(this))
|
||||||
}
|
}
|
||||||
|
|
||||||
@httpGet('/', TYPES.Auth_ApiGatewayAuthMiddleware)
|
@httpGet('/', TYPES.Auth_RequiredCrossServiceTokenMiddleware)
|
||||||
async getFeatures(request: Request, response: Response): Promise<results.JsonResult> {
|
async getFeatures(request: Request, response: Response): Promise<results.JsonResult> {
|
||||||
if (request.params.userUuid !== response.locals.user.uuid) {
|
if (request.params.userUuid !== response.locals.user.uuid) {
|
||||||
return this.json(
|
return this.json(
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import { controller, httpGet } from 'inversify-express-utils'
|
import { controller, httpGet } from 'inversify-express-utils'
|
||||||
|
|
||||||
@controller('/healthcheck')
|
@controller('/healthcheck')
|
||||||
export class HealthCheckController {
|
export class InversifyExpressHealthCheckController {
|
||||||
@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 { InternalController } from './InternalController'
|
import { InversifyExpressInternalController } from './InversifyExpressInternalController'
|
||||||
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('InternalController', () => {
|
describe('InversifyExpressInternalController', () => {
|
||||||
let getUserFeatures: GetUserFeatures
|
let getUserFeatures: GetUserFeatures
|
||||||
let getSetting: GetSetting
|
let getSetting: GetSetting
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ describe('InternalController', () => {
|
|||||||
let response: express.Response
|
let response: express.Response
|
||||||
let user: User
|
let user: User
|
||||||
|
|
||||||
const createController = () => new InternalController(getUserFeatures, getSetting)
|
const createController = () => new InversifyExpressInternalController(getUserFeatures, getSetting)
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
user = {} as jest.Mocked<User>
|
user = {} as jest.Mocked<User>
|
||||||
@@ -7,12 +7,12 @@ import {
|
|||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
results,
|
results,
|
||||||
} from 'inversify-express-utils'
|
} from 'inversify-express-utils'
|
||||||
import TYPES from '../Bootstrap/Types'
|
import TYPES from '../../Bootstrap/Types'
|
||||||
import { GetSetting } from '../Domain/UseCase/GetSetting/GetSetting'
|
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 InternalController extends BaseHttpController {
|
export class InversifyExpressInternalController 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,12 +3,12 @@ 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 { ListedController } from './ListedController'
|
import { InversifyExpressListedController } from './InversifyExpressListedController'
|
||||||
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'
|
||||||
import { ControllerContainerInterface } from '@standardnotes/domain-core'
|
import { ControllerContainerInterface } from '@standardnotes/domain-core'
|
||||||
|
|
||||||
describe('ListedController', () => {
|
describe('InversifyExpressListedController', () => {
|
||||||
let createListedAccount: CreateListedAccount
|
let createListedAccount: CreateListedAccount
|
||||||
|
|
||||||
let request: express.Request
|
let request: express.Request
|
||||||
@@ -16,7 +16,7 @@ describe('ListedController', () => {
|
|||||||
let user: User
|
let user: User
|
||||||
let controllerContainer: ControllerContainerInterface
|
let controllerContainer: ControllerContainerInterface
|
||||||
|
|
||||||
const createController = () => new ListedController(createListedAccount, controllerContainer)
|
const createController = () => new InversifyExpressListedController(createListedAccount, controllerContainer)
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
controllerContainer = {} as jest.Mocked<ControllerContainerInterface>
|
controllerContainer = {} as jest.Mocked<ControllerContainerInterface>
|
||||||
@@ -2,13 +2,13 @@ import { inject } from 'inversify'
|
|||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
import { BaseHttpController, controller, httpPost, results } from 'inversify-express-utils'
|
import { BaseHttpController, 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 { ErrorTag } from '@standardnotes/responses'
|
import { ErrorTag } from '@standardnotes/responses'
|
||||||
import { ControllerContainerInterface } from '@standardnotes/domain-core'
|
import { ControllerContainerInterface } from '@standardnotes/domain-core'
|
||||||
|
|
||||||
@controller('/listed')
|
@controller('/listed')
|
||||||
export class ListedController extends BaseHttpController {
|
export class InversifyExpressListedController extends BaseHttpController {
|
||||||
constructor(
|
constructor(
|
||||||
@inject(TYPES.Auth_CreateListedAccount) private doCreateListedAccount: CreateListedAccount,
|
@inject(TYPES.Auth_CreateListedAccount) private doCreateListedAccount: CreateListedAccount,
|
||||||
@inject(TYPES.Auth_ControllerContainer) private controllerContainer: ControllerContainerInterface,
|
@inject(TYPES.Auth_ControllerContainer) private controllerContainer: ControllerContainerInterface,
|
||||||
@@ -18,7 +18,7 @@ export class ListedController extends BaseHttpController {
|
|||||||
this.controllerContainer.register('auth.users.createListedAccount', this.createListedAccount.bind(this))
|
this.controllerContainer.register('auth.users.createListedAccount', this.createListedAccount.bind(this))
|
||||||
}
|
}
|
||||||
|
|
||||||
@httpPost('/', TYPES.Auth_ApiGatewayAuthMiddleware)
|
@httpPost('/', TYPES.Auth_RequiredCrossServiceTokenMiddleware)
|
||||||
async createListedAccount(_request: Request, response: Response): Promise<results.JsonResult> {
|
async createListedAccount(_request: Request, response: Response): Promise<results.JsonResult> {
|
||||||
if (response.locals.readOnlyAccess) {
|
if (response.locals.readOnlyAccess) {
|
||||||
return this.json(
|
return this.json(
|
||||||
@@ -2,21 +2,21 @@ import 'reflect-metadata'
|
|||||||
|
|
||||||
import * as express from 'express'
|
import * as express from 'express'
|
||||||
|
|
||||||
import { OfflineController } from './OfflineController'
|
import { InversifyExpressOfflineController } from './InversifyExpressOfflineController'
|
||||||
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 { CreateOfflineSubscriptionToken } from '../Domain/UseCase/CreateOfflineSubscriptionToken/CreateOfflineSubscriptionToken'
|
import { CreateOfflineSubscriptionToken } from '../../Domain/UseCase/CreateOfflineSubscriptionToken/CreateOfflineSubscriptionToken'
|
||||||
import { CreateOfflineSubscriptionTokenResponse } from '../Domain/UseCase/CreateOfflineSubscriptionToken/CreateOfflineSubscriptionTokenResponse'
|
import { CreateOfflineSubscriptionTokenResponse } from '../../Domain/UseCase/CreateOfflineSubscriptionToken/CreateOfflineSubscriptionTokenResponse'
|
||||||
import { AuthenticateOfflineSubscriptionToken } from '../Domain/UseCase/AuthenticateOfflineSubscriptionToken/AuthenticateOfflineSubscriptionToken'
|
import { AuthenticateOfflineSubscriptionToken } from '../../Domain/UseCase/AuthenticateOfflineSubscriptionToken/AuthenticateOfflineSubscriptionToken'
|
||||||
import { OfflineUserSubscription } from '../Domain/Subscription/OfflineUserSubscription'
|
import { OfflineUserSubscription } from '../../Domain/Subscription/OfflineUserSubscription'
|
||||||
import { GetUserOfflineSubscription } from '../Domain/UseCase/GetUserOfflineSubscription/GetUserOfflineSubscription'
|
import { GetUserOfflineSubscription } from '../../Domain/UseCase/GetUserOfflineSubscription/GetUserOfflineSubscription'
|
||||||
import { OfflineUserTokenData, TokenEncoderInterface } from '@standardnotes/security'
|
import { OfflineUserTokenData, TokenEncoderInterface } from '@standardnotes/security'
|
||||||
import { SubscriptionName } from '@standardnotes/common'
|
import { SubscriptionName } from '@standardnotes/common'
|
||||||
import { Logger } from 'winston'
|
import { Logger } from 'winston'
|
||||||
import { ControllerContainerInterface } from '@standardnotes/domain-core'
|
import { ControllerContainerInterface } from '@standardnotes/domain-core'
|
||||||
|
|
||||||
describe('OfflineController', () => {
|
describe('InversifyExpressOfflineController', () => {
|
||||||
let getUserFeatures: GetUserFeatures
|
let getUserFeatures: GetUserFeatures
|
||||||
let getUserOfflineSubscription: GetUserOfflineSubscription
|
let getUserOfflineSubscription: GetUserOfflineSubscription
|
||||||
let createOfflineSubscriptionToken: CreateOfflineSubscriptionToken
|
let createOfflineSubscriptionToken: CreateOfflineSubscriptionToken
|
||||||
@@ -32,7 +32,7 @@ describe('OfflineController', () => {
|
|||||||
let controllerContainer: ControllerContainerInterface
|
let controllerContainer: ControllerContainerInterface
|
||||||
|
|
||||||
const createController = () =>
|
const createController = () =>
|
||||||
new OfflineController(
|
new InversifyExpressOfflineController(
|
||||||
getUserFeatures,
|
getUserFeatures,
|
||||||
getUserOfflineSubscription,
|
getUserOfflineSubscription,
|
||||||
createOfflineSubscriptionToken,
|
createOfflineSubscriptionToken,
|
||||||
@@ -8,17 +8,17 @@ import {
|
|||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
results,
|
results,
|
||||||
} from 'inversify-express-utils'
|
} from 'inversify-express-utils'
|
||||||
import TYPES from '../Bootstrap/Types'
|
|
||||||
import { GetUserFeatures } from '../Domain/UseCase/GetUserFeatures/GetUserFeatures'
|
|
||||||
import { AuthenticateOfflineSubscriptionToken } from '../Domain/UseCase/AuthenticateOfflineSubscriptionToken/AuthenticateOfflineSubscriptionToken'
|
|
||||||
import { CreateOfflineSubscriptionToken } from '../Domain/UseCase/CreateOfflineSubscriptionToken/CreateOfflineSubscriptionToken'
|
|
||||||
import { GetUserOfflineSubscription } from '../Domain/UseCase/GetUserOfflineSubscription/GetUserOfflineSubscription'
|
|
||||||
import { Logger } from 'winston'
|
import { Logger } from 'winston'
|
||||||
import { OfflineUserTokenData, TokenEncoderInterface } from '@standardnotes/security'
|
import { OfflineUserTokenData, TokenEncoderInterface } from '@standardnotes/security'
|
||||||
import { ControllerContainerInterface } from '@standardnotes/domain-core'
|
import { ControllerContainerInterface } from '@standardnotes/domain-core'
|
||||||
|
import TYPES from '../../Bootstrap/Types'
|
||||||
|
import { AuthenticateOfflineSubscriptionToken } from '../../Domain/UseCase/AuthenticateOfflineSubscriptionToken/AuthenticateOfflineSubscriptionToken'
|
||||||
|
import { CreateOfflineSubscriptionToken } from '../../Domain/UseCase/CreateOfflineSubscriptionToken/CreateOfflineSubscriptionToken'
|
||||||
|
import { GetUserFeatures } from '../../Domain/UseCase/GetUserFeatures/GetUserFeatures'
|
||||||
|
import { GetUserOfflineSubscription } from '../../Domain/UseCase/GetUserOfflineSubscription/GetUserOfflineSubscription'
|
||||||
|
|
||||||
@controller('/offline')
|
@controller('/offline')
|
||||||
export class OfflineController extends BaseHttpController {
|
export class InversifyExpressOfflineController extends BaseHttpController {
|
||||||
constructor(
|
constructor(
|
||||||
@inject(TYPES.Auth_GetUserFeatures) private doGetUserFeatures: GetUserFeatures,
|
@inject(TYPES.Auth_GetUserFeatures) private doGetUserFeatures: GetUserFeatures,
|
||||||
@inject(TYPES.Auth_GetUserOfflineSubscription) private getUserOfflineSubscription: GetUserOfflineSubscription,
|
@inject(TYPES.Auth_GetUserOfflineSubscription) private getUserOfflineSubscription: GetUserOfflineSubscription,
|
||||||
@@ -2,14 +2,14 @@ import 'reflect-metadata'
|
|||||||
|
|
||||||
import * as express from 'express'
|
import * as express from 'express'
|
||||||
|
|
||||||
import { SessionController } from './SessionController'
|
import { InversifyExpressSessionController } from './InversifyExpressSessionController'
|
||||||
import { results } from 'inversify-express-utils'
|
import { results } from 'inversify-express-utils'
|
||||||
import { RefreshSessionToken } from '../Domain/UseCase/RefreshSessionToken'
|
|
||||||
import { DeletePreviousSessionsForUser } from '../Domain/UseCase/DeletePreviousSessionsForUser'
|
|
||||||
import { DeleteSessionForUser } from '../Domain/UseCase/DeleteSessionForUser'
|
|
||||||
import { ControllerContainerInterface } from '@standardnotes/domain-core'
|
import { ControllerContainerInterface } from '@standardnotes/domain-core'
|
||||||
|
import { DeletePreviousSessionsForUser } from '../../Domain/UseCase/DeletePreviousSessionsForUser'
|
||||||
|
import { DeleteSessionForUser } from '../../Domain/UseCase/DeleteSessionForUser'
|
||||||
|
import { RefreshSessionToken } from '../../Domain/UseCase/RefreshSessionToken'
|
||||||
|
|
||||||
describe('SessionController', () => {
|
describe('InversifyExpressSessionController', () => {
|
||||||
let deleteSessionForUser: DeleteSessionForUser
|
let deleteSessionForUser: DeleteSessionForUser
|
||||||
let deletePreviousSessionsForUser: DeletePreviousSessionsForUser
|
let deletePreviousSessionsForUser: DeletePreviousSessionsForUser
|
||||||
let refreshSessionToken: RefreshSessionToken
|
let refreshSessionToken: RefreshSessionToken
|
||||||
@@ -18,7 +18,12 @@ describe('SessionController', () => {
|
|||||||
let controllerContainer: ControllerContainerInterface
|
let controllerContainer: ControllerContainerInterface
|
||||||
|
|
||||||
const createController = () =>
|
const createController = () =>
|
||||||
new SessionController(deleteSessionForUser, deletePreviousSessionsForUser, refreshSessionToken, controllerContainer)
|
new InversifyExpressSessionController(
|
||||||
|
deleteSessionForUser,
|
||||||
|
deletePreviousSessionsForUser,
|
||||||
|
refreshSessionToken,
|
||||||
|
controllerContainer,
|
||||||
|
)
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
controllerContainer = {} as jest.Mocked<ControllerContainerInterface>
|
controllerContainer = {} as jest.Mocked<ControllerContainerInterface>
|
||||||
@@ -9,14 +9,14 @@ import {
|
|||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
results,
|
results,
|
||||||
} from 'inversify-express-utils'
|
} from 'inversify-express-utils'
|
||||||
import TYPES from '../Bootstrap/Types'
|
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 { ControllerContainerInterface } from '@standardnotes/domain-core'
|
import { ControllerContainerInterface } from '@standardnotes/domain-core'
|
||||||
|
|
||||||
@controller('/session')
|
@controller('/session')
|
||||||
export class SessionController extends BaseHttpController {
|
export class InversifyExpressSessionController extends BaseHttpController {
|
||||||
constructor(
|
constructor(
|
||||||
@inject(TYPES.Auth_DeleteSessionForUser) private deleteSessionForUser: DeleteSessionForUser,
|
@inject(TYPES.Auth_DeleteSessionForUser) private deleteSessionForUser: DeleteSessionForUser,
|
||||||
@inject(TYPES.Auth_DeletePreviousSessionsForUser)
|
@inject(TYPES.Auth_DeletePreviousSessionsForUser)
|
||||||
@@ -26,12 +26,12 @@ export class SessionController extends BaseHttpController {
|
|||||||
) {
|
) {
|
||||||
super()
|
super()
|
||||||
|
|
||||||
this.controllerContainer.register('auth.session.delete', this.deleteSession.bind(this))
|
this.controllerContainer.register('auth.sessions.delete', this.deleteSession.bind(this))
|
||||||
this.controllerContainer.register('auth.session.deleteAll', this.deleteAllSessions.bind(this))
|
this.controllerContainer.register('auth.sessions.deleteAll', this.deleteAllSessions.bind(this))
|
||||||
this.controllerContainer.register('auth.session.refresh', this.refresh.bind(this))
|
this.controllerContainer.register('auth.sessions.refresh', this.refresh.bind(this))
|
||||||
}
|
}
|
||||||
|
|
||||||
@httpDelete('/', TYPES.Auth_AuthMiddleware, TYPES.Auth_SessionMiddleware)
|
@httpDelete('/', TYPES.Auth_RequiredCrossServiceTokenMiddleware, TYPES.Auth_SessionMiddleware)
|
||||||
async deleteSession(request: Request, response: Response): Promise<results.JsonResult | void> {
|
async deleteSession(request: Request, response: Response): Promise<results.JsonResult | void> {
|
||||||
if (response.locals.readOnlyAccess) {
|
if (response.locals.readOnlyAccess) {
|
||||||
return this.json(
|
return this.json(
|
||||||
@@ -87,7 +87,7 @@ export class SessionController extends BaseHttpController {
|
|||||||
response.status(204).send()
|
response.status(204).send()
|
||||||
}
|
}
|
||||||
|
|
||||||
@httpDelete('/all', TYPES.Auth_AuthMiddleware, TYPES.Auth_SessionMiddleware)
|
@httpDelete('/all', TYPES.Auth_RequiredCrossServiceTokenMiddleware, TYPES.Auth_SessionMiddleware)
|
||||||
async deleteAllSessions(_request: Request, response: Response): Promise<results.JsonResult | void> {
|
async deleteAllSessions(_request: Request, response: Response): Promise<results.JsonResult | void> {
|
||||||
if (response.locals.readOnlyAccess) {
|
if (response.locals.readOnlyAccess) {
|
||||||
return this.json(
|
return this.json(
|
||||||
@@ -2,17 +2,18 @@ import 'reflect-metadata'
|
|||||||
|
|
||||||
import * as express from 'express'
|
import * as express from 'express'
|
||||||
|
|
||||||
import { SessionsController } from './SessionsController'
|
import { InversifyExpressSessionsController } from './InversifyExpressSessionsController'
|
||||||
import { results } from 'inversify-express-utils'
|
import { results } from 'inversify-express-utils'
|
||||||
import { Session } from '../Domain/Session/Session'
|
|
||||||
import { ProjectorInterface } from '../Projection/ProjectorInterface'
|
|
||||||
import { GetActiveSessionsForUser } from '../Domain/UseCase/GetActiveSessionsForUser'
|
|
||||||
import { AuthenticateRequest } from '../Domain/UseCase/AuthenticateRequest'
|
|
||||||
import { User } from '../Domain/User/User'
|
|
||||||
import { CreateCrossServiceToken } from '../Domain/UseCase/CreateCrossServiceToken/CreateCrossServiceToken'
|
|
||||||
import { ControllerContainerInterface } from '@standardnotes/domain-core'
|
import { ControllerContainerInterface } from '@standardnotes/domain-core'
|
||||||
|
import { User } from '@standardnotes/responses'
|
||||||
|
|
||||||
describe('SessionsController', () => {
|
import { AuthenticateRequest } from '../../Domain/UseCase/AuthenticateRequest'
|
||||||
|
import { CreateCrossServiceToken } from '../../Domain/UseCase/CreateCrossServiceToken/CreateCrossServiceToken'
|
||||||
|
import { GetActiveSessionsForUser } from '../../Domain/UseCase/GetActiveSessionsForUser'
|
||||||
|
import { ProjectorInterface } from '../../Projection/ProjectorInterface'
|
||||||
|
import { Session } from '../../Domain/Session/Session'
|
||||||
|
|
||||||
|
describe('InversifyExpressSessionsController', () => {
|
||||||
let getActiveSessionsForUser: GetActiveSessionsForUser
|
let getActiveSessionsForUser: GetActiveSessionsForUser
|
||||||
let authenticateRequest: AuthenticateRequest
|
let authenticateRequest: AuthenticateRequest
|
||||||
let sessionProjector: ProjectorInterface<Session>
|
let sessionProjector: ProjectorInterface<Session>
|
||||||
@@ -24,7 +25,7 @@ describe('SessionsController', () => {
|
|||||||
let controllerContainer: ControllerContainerInterface
|
let controllerContainer: ControllerContainerInterface
|
||||||
|
|
||||||
const createController = () =>
|
const createController = () =>
|
||||||
new SessionsController(
|
new InversifyExpressSessionsController(
|
||||||
getActiveSessionsForUser,
|
getActiveSessionsForUser,
|
||||||
authenticateRequest,
|
authenticateRequest,
|
||||||
sessionProjector,
|
sessionProjector,
|
||||||
@@ -8,18 +8,19 @@ import {
|
|||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
results,
|
results,
|
||||||
} from 'inversify-express-utils'
|
} from 'inversify-express-utils'
|
||||||
import TYPES from '../Bootstrap/Types'
|
|
||||||
import { Session } from '../Domain/Session/Session'
|
|
||||||
import { AuthenticateRequest } from '../Domain/UseCase/AuthenticateRequest'
|
|
||||||
import { GetActiveSessionsForUser } from '../Domain/UseCase/GetActiveSessionsForUser'
|
|
||||||
import { User } from '../Domain/User/User'
|
|
||||||
import { ProjectorInterface } from '../Projection/ProjectorInterface'
|
|
||||||
import { SessionProjector } from '../Projection/SessionProjector'
|
|
||||||
import { CreateCrossServiceToken } from '../Domain/UseCase/CreateCrossServiceToken/CreateCrossServiceToken'
|
|
||||||
import { ControllerContainerInterface } from '@standardnotes/domain-core'
|
import { ControllerContainerInterface } from '@standardnotes/domain-core'
|
||||||
|
|
||||||
|
import TYPES from '../../Bootstrap/Types'
|
||||||
|
import { AuthenticateRequest } from '../../Domain/UseCase/AuthenticateRequest'
|
||||||
|
import { CreateCrossServiceToken } from '../../Domain/UseCase/CreateCrossServiceToken/CreateCrossServiceToken'
|
||||||
|
import { GetActiveSessionsForUser } from '../../Domain/UseCase/GetActiveSessionsForUser'
|
||||||
|
import { ProjectorInterface } from '../../Projection/ProjectorInterface'
|
||||||
|
import { SessionProjector } from '../../Projection/SessionProjector'
|
||||||
|
import { User } from '../../Domain/User/User'
|
||||||
|
import { Session } from '../../Domain/Session/Session'
|
||||||
|
|
||||||
@controller('/sessions')
|
@controller('/sessions')
|
||||||
export class SessionsController extends BaseHttpController {
|
export class InversifyExpressSessionsController extends BaseHttpController {
|
||||||
constructor(
|
constructor(
|
||||||
@inject(TYPES.Auth_GetActiveSessionsForUser) private getActiveSessionsForUser: GetActiveSessionsForUser,
|
@inject(TYPES.Auth_GetActiveSessionsForUser) private getActiveSessionsForUser: GetActiveSessionsForUser,
|
||||||
@inject(TYPES.Auth_AuthenticateRequest) private authenticateRequest: AuthenticateRequest,
|
@inject(TYPES.Auth_AuthenticateRequest) private authenticateRequest: AuthenticateRequest,
|
||||||
@@ -30,6 +31,7 @@ export class SessionsController extends BaseHttpController {
|
|||||||
super()
|
super()
|
||||||
|
|
||||||
this.controllerContainer.register('auth.sessions.list', this.getSessions.bind(this))
|
this.controllerContainer.register('auth.sessions.list', this.getSessions.bind(this))
|
||||||
|
this.controllerContainer.register('auth.sessions.validate', this.validate.bind(this))
|
||||||
}
|
}
|
||||||
|
|
||||||
@httpPost('/validate')
|
@httpPost('/validate')
|
||||||
@@ -60,7 +62,7 @@ export class SessionsController extends BaseHttpController {
|
|||||||
return this.json({ authToken: result.token })
|
return this.json({ authToken: result.token })
|
||||||
}
|
}
|
||||||
|
|
||||||
@httpGet('/', TYPES.Auth_AuthMiddleware, TYPES.Auth_SessionMiddleware)
|
@httpGet('/', TYPES.Auth_RequiredCrossServiceTokenMiddleware, TYPES.Auth_SessionMiddleware)
|
||||||
async getSessions(_request: Request, response: Response): Promise<results.JsonResult> {
|
async getSessions(_request: Request, response: Response): Promise<results.JsonResult> {
|
||||||
if (response.locals.readOnlyAccess) {
|
if (response.locals.readOnlyAccess) {
|
||||||
return this.json([])
|
return this.json([])
|
||||||
@@ -2,17 +2,17 @@ import 'reflect-metadata'
|
|||||||
|
|
||||||
import * as express from 'express'
|
import * as express from 'express'
|
||||||
|
|
||||||
import { SettingsController } from './SettingsController'
|
import { InversifyExpressSettingsController } from './InversifyExpressSettingsController'
|
||||||
import { results } from 'inversify-express-utils'
|
import { results } from 'inversify-express-utils'
|
||||||
import { User } from '../Domain/User/User'
|
|
||||||
import { GetSettings } from '../Domain/UseCase/GetSettings/GetSettings'
|
|
||||||
import { GetSetting } from '../Domain/UseCase/GetSetting/GetSetting'
|
|
||||||
import { UpdateSetting } from '../Domain/UseCase/UpdateSetting/UpdateSetting'
|
|
||||||
import { DeleteSetting } from '../Domain/UseCase/DeleteSetting/DeleteSetting'
|
|
||||||
import { EncryptionVersion } from '../Domain/Encryption/EncryptionVersion'
|
|
||||||
import { ControllerContainerInterface } from '@standardnotes/domain-core'
|
import { ControllerContainerInterface } from '@standardnotes/domain-core'
|
||||||
|
import { EncryptionVersion } from '../../Domain/Encryption/EncryptionVersion'
|
||||||
|
import { DeleteSetting } from '../../Domain/UseCase/DeleteSetting/DeleteSetting'
|
||||||
|
import { GetSetting } from '../../Domain/UseCase/GetSetting/GetSetting'
|
||||||
|
import { GetSettings } from '../../Domain/UseCase/GetSettings/GetSettings'
|
||||||
|
import { UpdateSetting } from '../../Domain/UseCase/UpdateSetting/UpdateSetting'
|
||||||
|
import { User } from '../../Domain/User/User'
|
||||||
|
|
||||||
describe('SettingsController', () => {
|
describe('InversifyExpressSettingsController', () => {
|
||||||
let deleteSetting: DeleteSetting
|
let deleteSetting: DeleteSetting
|
||||||
let getSettings: GetSettings
|
let getSettings: GetSettings
|
||||||
let getSetting: GetSetting
|
let getSetting: GetSetting
|
||||||
@@ -24,7 +24,7 @@ describe('SettingsController', () => {
|
|||||||
let controllerContainer: ControllerContainerInterface
|
let controllerContainer: ControllerContainerInterface
|
||||||
|
|
||||||
const createController = () =>
|
const createController = () =>
|
||||||
new SettingsController(getSettings, getSetting, updateSetting, deleteSetting, controllerContainer)
|
new InversifyExpressSettingsController(getSettings, getSetting, updateSetting, deleteSetting, controllerContainer)
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
controllerContainer = {} as jest.Mocked<ControllerContainerInterface>
|
controllerContainer = {} as jest.Mocked<ControllerContainerInterface>
|
||||||
@@ -10,16 +10,16 @@ import {
|
|||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
results,
|
results,
|
||||||
} from 'inversify-express-utils'
|
} from 'inversify-express-utils'
|
||||||
import TYPES from '../Bootstrap/Types'
|
import TYPES from '../../Bootstrap/Types'
|
||||||
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'
|
||||||
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 { ControllerContainerInterface } from '@standardnotes/domain-core'
|
import { ControllerContainerInterface } from '@standardnotes/domain-core'
|
||||||
|
|
||||||
@controller('/users/:userUuid')
|
@controller('/users/:userUuid')
|
||||||
export class SettingsController extends BaseHttpController {
|
export class InversifyExpressSettingsController extends BaseHttpController {
|
||||||
constructor(
|
constructor(
|
||||||
@inject(TYPES.Auth_GetSettings) private doGetSettings: GetSettings,
|
@inject(TYPES.Auth_GetSettings) private doGetSettings: GetSettings,
|
||||||
@inject(TYPES.Auth_GetSetting) private doGetSetting: GetSetting,
|
@inject(TYPES.Auth_GetSetting) private doGetSetting: GetSetting,
|
||||||
@@ -35,7 +35,7 @@ export class SettingsController extends BaseHttpController {
|
|||||||
this.controllerContainer.register('auth.users.deleteSetting', this.deleteSetting.bind(this))
|
this.controllerContainer.register('auth.users.deleteSetting', this.deleteSetting.bind(this))
|
||||||
}
|
}
|
||||||
|
|
||||||
@httpGet('/settings', TYPES.Auth_ApiGatewayAuthMiddleware)
|
@httpGet('/settings', TYPES.Auth_RequiredCrossServiceTokenMiddleware)
|
||||||
async getSettings(request: Request, response: Response): Promise<results.JsonResult> {
|
async getSettings(request: Request, response: Response): Promise<results.JsonResult> {
|
||||||
if (request.params.userUuid !== response.locals.user.uuid) {
|
if (request.params.userUuid !== response.locals.user.uuid) {
|
||||||
return this.json(
|
return this.json(
|
||||||
@@ -54,7 +54,7 @@ export class SettingsController extends BaseHttpController {
|
|||||||
return this.json(result)
|
return this.json(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
@httpGet('/settings/:settingName', TYPES.Auth_ApiGatewayAuthMiddleware)
|
@httpGet('/settings/:settingName', TYPES.Auth_RequiredCrossServiceTokenMiddleware)
|
||||||
async getSetting(request: Request, response: Response): Promise<results.JsonResult> {
|
async getSetting(request: Request, response: Response): Promise<results.JsonResult> {
|
||||||
if (request.params.userUuid !== response.locals.user.uuid) {
|
if (request.params.userUuid !== response.locals.user.uuid) {
|
||||||
return this.json(
|
return this.json(
|
||||||
@@ -77,7 +77,7 @@ export class SettingsController extends BaseHttpController {
|
|||||||
return this.json(result, 400)
|
return this.json(result, 400)
|
||||||
}
|
}
|
||||||
|
|
||||||
@httpPut('/settings', TYPES.Auth_ApiGatewayAuthMiddleware)
|
@httpPut('/settings', TYPES.Auth_RequiredCrossServiceTokenMiddleware)
|
||||||
async updateSetting(request: Request, response: Response): Promise<results.JsonResult | results.StatusCodeResult> {
|
async updateSetting(request: Request, response: Response): Promise<results.JsonResult | results.StatusCodeResult> {
|
||||||
if (response.locals.readOnlyAccess) {
|
if (response.locals.readOnlyAccess) {
|
||||||
return this.json(
|
return this.json(
|
||||||
@@ -124,7 +124,7 @@ export class SettingsController extends BaseHttpController {
|
|||||||
return this.json(result, result.statusCode)
|
return this.json(result, result.statusCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
@httpDelete('/settings/:settingName', TYPES.Auth_ApiGatewayAuthMiddleware)
|
@httpDelete('/settings/:settingName', TYPES.Auth_RequiredCrossServiceTokenMiddleware)
|
||||||
async deleteSetting(request: Request, response: Response): Promise<results.JsonResult> {
|
async deleteSetting(request: Request, response: Response): Promise<results.JsonResult> {
|
||||||
if (response.locals.readOnlyAccess) {
|
if (response.locals.readOnlyAccess) {
|
||||||
return this.json(
|
return this.json(
|
||||||
@@ -31,7 +31,7 @@ export class InversifyExpressSubscriptionInvitesController extends BaseHttpContr
|
|||||||
this.controllerContainer.register('auth.subscriptionInvites.list', this.listInvites.bind(this))
|
this.controllerContainer.register('auth.subscriptionInvites.list', this.listInvites.bind(this))
|
||||||
}
|
}
|
||||||
|
|
||||||
@httpPost('/:inviteUuid/accept', TYPES.Auth_ApiGatewayAuthMiddleware)
|
@httpPost('/:inviteUuid/accept', TYPES.Auth_RequiredCrossServiceTokenMiddleware)
|
||||||
async acceptInvite(request: Request, response: Response): Promise<void> {
|
async acceptInvite(request: Request, response: Response): Promise<void> {
|
||||||
const result = await this.subscriptionInvitesController.acceptInvite({
|
const result = await this.subscriptionInvitesController.acceptInvite({
|
||||||
api: request.query.api as ApiVersion,
|
api: request.query.api as ApiVersion,
|
||||||
@@ -52,7 +52,7 @@ export class InversifyExpressSubscriptionInvitesController extends BaseHttpContr
|
|||||||
return this.json(response.data, response.status)
|
return this.json(response.data, response.status)
|
||||||
}
|
}
|
||||||
|
|
||||||
@httpPost('/', TYPES.Auth_ApiGatewayAuthMiddleware)
|
@httpPost('/', TYPES.Auth_RequiredCrossServiceTokenMiddleware)
|
||||||
async inviteToSubscriptionSharing(request: Request, response: Response): Promise<results.JsonResult> {
|
async inviteToSubscriptionSharing(request: Request, response: Response): Promise<results.JsonResult> {
|
||||||
const result = await this.subscriptionInvitesController.invite({
|
const result = await this.subscriptionInvitesController.invite({
|
||||||
...request.body,
|
...request.body,
|
||||||
@@ -64,7 +64,7 @@ export class InversifyExpressSubscriptionInvitesController extends BaseHttpContr
|
|||||||
return this.json(result.data, result.status)
|
return this.json(result.data, result.status)
|
||||||
}
|
}
|
||||||
|
|
||||||
@httpDelete('/:inviteUuid', TYPES.Auth_ApiGatewayAuthMiddleware)
|
@httpDelete('/:inviteUuid', TYPES.Auth_RequiredCrossServiceTokenMiddleware)
|
||||||
async cancelSubscriptionSharing(request: Request, response: Response): Promise<results.JsonResult> {
|
async cancelSubscriptionSharing(request: Request, response: Response): Promise<results.JsonResult> {
|
||||||
const result = await this.subscriptionInvitesController.cancelInvite({
|
const result = await this.subscriptionInvitesController.cancelInvite({
|
||||||
...request.body,
|
...request.body,
|
||||||
@@ -75,7 +75,7 @@ export class InversifyExpressSubscriptionInvitesController extends BaseHttpContr
|
|||||||
return this.json(result.data, result.status)
|
return this.json(result.data, result.status)
|
||||||
}
|
}
|
||||||
|
|
||||||
@httpGet('/', TYPES.Auth_ApiGatewayAuthMiddleware)
|
@httpGet('/', TYPES.Auth_RequiredCrossServiceTokenMiddleware)
|
||||||
async listInvites(request: Request, response: Response): Promise<results.JsonResult> {
|
async listInvites(request: Request, response: Response): Promise<results.JsonResult> {
|
||||||
const result = await this.subscriptionInvitesController.listInvites({
|
const result = await this.subscriptionInvitesController.listInvites({
|
||||||
...request.body,
|
...request.body,
|
||||||
|
|||||||
@@ -3,12 +3,12 @@ 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 { User } from '../Domain/User/User'
|
import { InversifyExpressSubscriptionSettingsController } from './InversifyExpressSubscriptionSettingsController'
|
||||||
import { SubscriptionSettingsController } from './SubscriptionSettingsController'
|
|
||||||
import { GetSetting } from '../Domain/UseCase/GetSetting/GetSetting'
|
|
||||||
import { ControllerContainerInterface } from '@standardnotes/domain-core'
|
import { ControllerContainerInterface } from '@standardnotes/domain-core'
|
||||||
|
import { User } from '../../Domain/User/User'
|
||||||
|
import { GetSetting } from '../../Domain/UseCase/GetSetting/GetSetting'
|
||||||
|
|
||||||
describe('SubscriptionSettingsController', () => {
|
describe('InversifyExpressSubscriptionSettingsController', () => {
|
||||||
let getSetting: GetSetting
|
let getSetting: GetSetting
|
||||||
|
|
||||||
let request: express.Request
|
let request: express.Request
|
||||||
@@ -16,7 +16,7 @@ describe('SubscriptionSettingsController', () => {
|
|||||||
let user: User
|
let user: User
|
||||||
let controllerContainer: ControllerContainerInterface
|
let controllerContainer: ControllerContainerInterface
|
||||||
|
|
||||||
const createController = () => new SubscriptionSettingsController(getSetting, controllerContainer)
|
const createController = () => new InversifyExpressSubscriptionSettingsController(getSetting, controllerContainer)
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
controllerContainer = {} as jest.Mocked<ControllerContainerInterface>
|
controllerContainer = {} as jest.Mocked<ControllerContainerInterface>
|
||||||
@@ -7,12 +7,12 @@ import {
|
|||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
results,
|
results,
|
||||||
} from 'inversify-express-utils'
|
} from 'inversify-express-utils'
|
||||||
import TYPES from '../Bootstrap/Types'
|
import TYPES from '../../Bootstrap/Types'
|
||||||
import { GetSetting } from '../Domain/UseCase/GetSetting/GetSetting'
|
import { GetSetting } from '../../Domain/UseCase/GetSetting/GetSetting'
|
||||||
import { ControllerContainerInterface } from '@standardnotes/domain-core'
|
import { ControllerContainerInterface } from '@standardnotes/domain-core'
|
||||||
|
|
||||||
@controller('/users/:userUuid')
|
@controller('/users/:userUuid')
|
||||||
export class SubscriptionSettingsController extends BaseHttpController {
|
export class InversifyExpressSubscriptionSettingsController extends BaseHttpController {
|
||||||
constructor(
|
constructor(
|
||||||
@inject(TYPES.Auth_GetSetting) private doGetSetting: GetSetting,
|
@inject(TYPES.Auth_GetSetting) private doGetSetting: GetSetting,
|
||||||
@inject(TYPES.Auth_ControllerContainer) private controllerContainer: ControllerContainerInterface,
|
@inject(TYPES.Auth_ControllerContainer) private controllerContainer: ControllerContainerInterface,
|
||||||
@@ -22,7 +22,7 @@ export class SubscriptionSettingsController extends BaseHttpController {
|
|||||||
this.controllerContainer.register('auth.users.getSubscriptionSetting', this.getSubscriptionSetting.bind(this))
|
this.controllerContainer.register('auth.users.getSubscriptionSetting', this.getSubscriptionSetting.bind(this))
|
||||||
}
|
}
|
||||||
|
|
||||||
@httpGet('/subscription-settings/:subscriptionSettingName', TYPES.Auth_ApiGatewayAuthMiddleware)
|
@httpGet('/subscription-settings/:subscriptionSettingName', TYPES.Auth_RequiredCrossServiceTokenMiddleware)
|
||||||
async getSubscriptionSetting(request: Request, response: Response): Promise<results.JsonResult> {
|
async getSubscriptionSetting(request: Request, response: Response): Promise<results.JsonResult> {
|
||||||
const result = await this.doGetSetting.execute({
|
const result = await this.doGetSetting.execute({
|
||||||
userUuid: response.locals.user.uuid,
|
userUuid: response.locals.user.uuid,
|
||||||
@@ -3,19 +3,19 @@ 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 { SubscriptionTokensController } from './SubscriptionTokensController'
|
import { InversifyExpressSubscriptionTokensController } from './InversifyExpressSubscriptionTokensController'
|
||||||
import { User } from '../Domain/User/User'
|
|
||||||
import { CreateSubscriptionToken } from '../Domain/UseCase/CreateSubscriptionToken/CreateSubscriptionToken'
|
|
||||||
import { CreateSubscriptionTokenResponse } from '../Domain/UseCase/CreateSubscriptionToken/CreateSubscriptionTokenResponse'
|
|
||||||
import { AuthenticateSubscriptionToken } from '../Domain/UseCase/AuthenticateSubscriptionToken/AuthenticateSubscriptionToken'
|
|
||||||
import { ProjectorInterface } from '../Projection/ProjectorInterface'
|
|
||||||
import { Role } from '../Domain/Role/Role'
|
|
||||||
import { SettingServiceInterface } from '../Domain/Setting/SettingServiceInterface'
|
|
||||||
import { Setting } from '../Domain/Setting/Setting'
|
|
||||||
import { CrossServiceTokenData, TokenEncoderInterface } from '@standardnotes/security'
|
import { CrossServiceTokenData, TokenEncoderInterface } from '@standardnotes/security'
|
||||||
import { ControllerContainerInterface } from '@standardnotes/domain-core'
|
import { ControllerContainerInterface } from '@standardnotes/domain-core'
|
||||||
|
import { Setting } from '../../Domain/Setting/Setting'
|
||||||
|
import { SettingServiceInterface } from '../../Domain/Setting/SettingServiceInterface'
|
||||||
|
import { AuthenticateSubscriptionToken } from '../../Domain/UseCase/AuthenticateSubscriptionToken/AuthenticateSubscriptionToken'
|
||||||
|
import { CreateSubscriptionToken } from '../../Domain/UseCase/CreateSubscriptionToken/CreateSubscriptionToken'
|
||||||
|
import { CreateSubscriptionTokenResponse } from '../../Domain/UseCase/CreateSubscriptionToken/CreateSubscriptionTokenResponse'
|
||||||
|
import { ProjectorInterface } from '../../Projection/ProjectorInterface'
|
||||||
|
import { User } from '../../Domain/User/User'
|
||||||
|
import { Role } from '../../Domain/Role/Role'
|
||||||
|
|
||||||
describe('SubscriptionTokensController', () => {
|
describe('InversifyExpressSubscriptionTokensController', () => {
|
||||||
let createSubscriptionToken: CreateSubscriptionToken
|
let createSubscriptionToken: CreateSubscriptionToken
|
||||||
let authenticateToken: AuthenticateSubscriptionToken
|
let authenticateToken: AuthenticateSubscriptionToken
|
||||||
const jwtTTL = 60
|
const jwtTTL = 60
|
||||||
@@ -33,7 +33,7 @@ describe('SubscriptionTokensController', () => {
|
|||||||
let controllerContainer: ControllerContainerInterface
|
let controllerContainer: ControllerContainerInterface
|
||||||
|
|
||||||
const createController = () =>
|
const createController = () =>
|
||||||
new SubscriptionTokensController(
|
new InversifyExpressSubscriptionTokensController(
|
||||||
createSubscriptionToken,
|
createSubscriptionToken,
|
||||||
authenticateToken,
|
authenticateToken,
|
||||||
settingService,
|
settingService,
|
||||||
@@ -11,17 +11,17 @@ import {
|
|||||||
results,
|
results,
|
||||||
} from 'inversify-express-utils'
|
} from 'inversify-express-utils'
|
||||||
|
|
||||||
import TYPES from '../Bootstrap/Types'
|
import TYPES from '../../Bootstrap/Types'
|
||||||
import { Role } from '../Domain/Role/Role'
|
import { Role } from '../../Domain/Role/Role'
|
||||||
import { SettingServiceInterface } from '../Domain/Setting/SettingServiceInterface'
|
import { SettingServiceInterface } from '../../Domain/Setting/SettingServiceInterface'
|
||||||
import { AuthenticateSubscriptionToken } from '../Domain/UseCase/AuthenticateSubscriptionToken/AuthenticateSubscriptionToken'
|
import { AuthenticateSubscriptionToken } from '../../Domain/UseCase/AuthenticateSubscriptionToken/AuthenticateSubscriptionToken'
|
||||||
import { CreateSubscriptionToken } from '../Domain/UseCase/CreateSubscriptionToken/CreateSubscriptionToken'
|
import { CreateSubscriptionToken } from '../../Domain/UseCase/CreateSubscriptionToken/CreateSubscriptionToken'
|
||||||
import { User } from '../Domain/User/User'
|
import { User } from '../../Domain/User/User'
|
||||||
import { ProjectorInterface } from '../Projection/ProjectorInterface'
|
import { ProjectorInterface } from '../../Projection/ProjectorInterface'
|
||||||
import { ControllerContainerInterface } from '@standardnotes/domain-core'
|
import { ControllerContainerInterface } from '@standardnotes/domain-core'
|
||||||
|
|
||||||
@controller('/subscription-tokens')
|
@controller('/subscription-tokens')
|
||||||
export class SubscriptionTokensController extends BaseHttpController {
|
export class InversifyExpressSubscriptionTokensController extends BaseHttpController {
|
||||||
constructor(
|
constructor(
|
||||||
@inject(TYPES.Auth_CreateSubscriptionToken) private createSubscriptionToken: CreateSubscriptionToken,
|
@inject(TYPES.Auth_CreateSubscriptionToken) private createSubscriptionToken: CreateSubscriptionToken,
|
||||||
@inject(TYPES.Auth_AuthenticateSubscriptionToken) private authenticateToken: AuthenticateSubscriptionToken,
|
@inject(TYPES.Auth_AuthenticateSubscriptionToken) private authenticateToken: AuthenticateSubscriptionToken,
|
||||||
@@ -37,7 +37,7 @@ export class SubscriptionTokensController extends BaseHttpController {
|
|||||||
this.controllerContainer.register('auth.subscription-tokens.create', this.createToken.bind(this))
|
this.controllerContainer.register('auth.subscription-tokens.create', this.createToken.bind(this))
|
||||||
}
|
}
|
||||||
|
|
||||||
@httpPost('/', TYPES.Auth_ApiGatewayAuthMiddleware)
|
@httpPost('/', TYPES.Auth_RequiredCrossServiceTokenMiddleware)
|
||||||
async createToken(_request: Request, response: Response): Promise<results.JsonResult> {
|
async createToken(_request: Request, response: Response): Promise<results.JsonResult> {
|
||||||
if (response.locals.readOnlyAccess) {
|
if (response.locals.readOnlyAccess) {
|
||||||
return this.json(
|
return this.json(
|
||||||
@@ -17,7 +17,7 @@ export class InversifyExpressUserRequestsController extends BaseHttpController {
|
|||||||
this.controllerContainer.register('auth.users.createRequest', this.submitRequest.bind(this))
|
this.controllerContainer.register('auth.users.createRequest', this.submitRequest.bind(this))
|
||||||
}
|
}
|
||||||
|
|
||||||
@httpPost('/', TYPES.Auth_ApiGatewayAuthMiddleware)
|
@httpPost('/', TYPES.Auth_RequiredCrossServiceTokenMiddleware)
|
||||||
async submitRequest(request: Request, response: Response): Promise<results.JsonResult> {
|
async submitRequest(request: Request, response: Response): Promise<results.JsonResult> {
|
||||||
const result = await this.userRequestsController.submitUserRequest({
|
const result = await this.userRequestsController.submitUserRequest({
|
||||||
requestType: request.body.requestType,
|
requestType: request.body.requestType,
|
||||||
|
|||||||
@@ -2,20 +2,20 @@ import 'reflect-metadata'
|
|||||||
|
|
||||||
import * as express from 'express'
|
import * as express from 'express'
|
||||||
|
|
||||||
import { UsersController } from './UsersController'
|
import { InversifyExpressUsersController } from './InversifyExpressUsersController'
|
||||||
import { results } from 'inversify-express-utils'
|
import { results } from 'inversify-express-utils'
|
||||||
import { User } from '../Domain/User/User'
|
import { ControllerContainerInterface, Username } from '@standardnotes/domain-core'
|
||||||
import { UpdateUser } from '../Domain/UseCase/UpdateUser'
|
import { DeleteAccount } from '../../Domain/UseCase/DeleteAccount/DeleteAccount'
|
||||||
import { GetUserKeyParams } from '../Domain/UseCase/GetUserKeyParams/GetUserKeyParams'
|
import { ChangeCredentials } from '../../Domain/UseCase/ChangeCredentials/ChangeCredentials'
|
||||||
import { DeleteAccount } from '../Domain/UseCase/DeleteAccount/DeleteAccount'
|
import { ClearLoginAttempts } from '../../Domain/UseCase/ClearLoginAttempts'
|
||||||
import { GetUserSubscription } from '../Domain/UseCase/GetUserSubscription/GetUserSubscription'
|
import { GetUserKeyParams } from '../../Domain/UseCase/GetUserKeyParams/GetUserKeyParams'
|
||||||
import { ClearLoginAttempts } from '../Domain/UseCase/ClearLoginAttempts'
|
import { GetUserSubscription } from '../../Domain/UseCase/GetUserSubscription/GetUserSubscription'
|
||||||
import { IncreaseLoginAttempts } from '../Domain/UseCase/IncreaseLoginAttempts'
|
import { IncreaseLoginAttempts } from '../../Domain/UseCase/IncreaseLoginAttempts'
|
||||||
import { ChangeCredentials } from '../Domain/UseCase/ChangeCredentials/ChangeCredentials'
|
import { InviteToSharedSubscription } from '../../Domain/UseCase/InviteToSharedSubscription/InviteToSharedSubscription'
|
||||||
import { InviteToSharedSubscription } from '../Domain/UseCase/InviteToSharedSubscription/InviteToSharedSubscription'
|
import { UpdateUser } from '../../Domain/UseCase/UpdateUser'
|
||||||
import { ControllerContainerInterface } from '@standardnotes/domain-core'
|
import { User } from '../../Domain/User/User'
|
||||||
|
|
||||||
describe('UsersController', () => {
|
describe('InversifyExpressUsersController', () => {
|
||||||
let updateUser: UpdateUser
|
let updateUser: UpdateUser
|
||||||
let deleteAccount: DeleteAccount
|
let deleteAccount: DeleteAccount
|
||||||
let getUserKeyParams: GetUserKeyParams
|
let getUserKeyParams: GetUserKeyParams
|
||||||
@@ -31,7 +31,7 @@ describe('UsersController', () => {
|
|||||||
let controllerContainer: ControllerContainerInterface
|
let controllerContainer: ControllerContainerInterface
|
||||||
|
|
||||||
const createController = () =>
|
const createController = () =>
|
||||||
new UsersController(
|
new InversifyExpressUsersController(
|
||||||
updateUser,
|
updateUser,
|
||||||
getUserKeyParams,
|
getUserKeyParams,
|
||||||
deleteAccount,
|
deleteAccount,
|
||||||
@@ -321,10 +321,7 @@ describe('UsersController', () => {
|
|||||||
kpOrigination: 'change-password',
|
kpOrigination: 'change-password',
|
||||||
pwNonce: 'asdzxc',
|
pwNonce: 'asdzxc',
|
||||||
protocolVersion: '004',
|
protocolVersion: '004',
|
||||||
user: {
|
username: Username.create('test@test.te').getValue(),
|
||||||
uuid: '123',
|
|
||||||
email: 'test@test.te',
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(clearLoginAttempts.execute).toHaveBeenCalled()
|
expect(clearLoginAttempts.execute).toHaveBeenCalled()
|
||||||
@@ -11,18 +11,18 @@ import {
|
|||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
results,
|
results,
|
||||||
} from 'inversify-express-utils'
|
} from 'inversify-express-utils'
|
||||||
import TYPES from '../Bootstrap/Types'
|
import TYPES from '../../Bootstrap/Types'
|
||||||
import { DeleteAccount } from '../Domain/UseCase/DeleteAccount/DeleteAccount'
|
import { DeleteAccount } from '../../Domain/UseCase/DeleteAccount/DeleteAccount'
|
||||||
import { GetUserKeyParams } from '../Domain/UseCase/GetUserKeyParams/GetUserKeyParams'
|
import { GetUserKeyParams } from '../../Domain/UseCase/GetUserKeyParams/GetUserKeyParams'
|
||||||
import { UpdateUser } from '../Domain/UseCase/UpdateUser'
|
import { UpdateUser } from '../../Domain/UseCase/UpdateUser'
|
||||||
import { GetUserSubscription } from '../Domain/UseCase/GetUserSubscription/GetUserSubscription'
|
import { GetUserSubscription } from '../../Domain/UseCase/GetUserSubscription/GetUserSubscription'
|
||||||
import { ClearLoginAttempts } from '../Domain/UseCase/ClearLoginAttempts'
|
import { ClearLoginAttempts } from '../../Domain/UseCase/ClearLoginAttempts'
|
||||||
import { IncreaseLoginAttempts } from '../Domain/UseCase/IncreaseLoginAttempts'
|
import { IncreaseLoginAttempts } from '../../Domain/UseCase/IncreaseLoginAttempts'
|
||||||
import { ChangeCredentials } from '../Domain/UseCase/ChangeCredentials/ChangeCredentials'
|
import { ChangeCredentials } from '../../Domain/UseCase/ChangeCredentials/ChangeCredentials'
|
||||||
import { ControllerContainerInterface } from '@standardnotes/domain-core'
|
import { ControllerContainerInterface, Username } from '@standardnotes/domain-core'
|
||||||
|
|
||||||
@controller('/users')
|
@controller('/users')
|
||||||
export class UsersController extends BaseHttpController {
|
export class InversifyExpressUsersController extends BaseHttpController {
|
||||||
constructor(
|
constructor(
|
||||||
@inject(TYPES.Auth_UpdateUser) private updateUser: UpdateUser,
|
@inject(TYPES.Auth_UpdateUser) private updateUser: UpdateUser,
|
||||||
@inject(TYPES.Auth_GetUserKeyParams) private getUserKeyParams: GetUserKeyParams,
|
@inject(TYPES.Auth_GetUserKeyParams) private getUserKeyParams: GetUserKeyParams,
|
||||||
@@ -41,7 +41,7 @@ export class UsersController extends BaseHttpController {
|
|||||||
this.controllerContainer.register('auth.users.updateCredentials', this.changeCredentials.bind(this))
|
this.controllerContainer.register('auth.users.updateCredentials', this.changeCredentials.bind(this))
|
||||||
}
|
}
|
||||||
|
|
||||||
@httpPatch('/:userId', TYPES.Auth_ApiGatewayAuthMiddleware)
|
@httpPatch('/:userId', TYPES.Auth_RequiredCrossServiceTokenMiddleware)
|
||||||
async update(request: Request, response: Response): Promise<results.JsonResult | void> {
|
async update(request: Request, response: Response): Promise<results.JsonResult | void> {
|
||||||
if (response.locals.readOnlyAccess) {
|
if (response.locals.readOnlyAccess) {
|
||||||
return this.json(
|
return this.json(
|
||||||
@@ -132,7 +132,7 @@ export class UsersController extends BaseHttpController {
|
|||||||
return this.json({ message: result.message }, result.responseCode)
|
return this.json({ message: result.message }, result.responseCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
@httpGet('/:userUuid/subscription', TYPES.Auth_ApiGatewayAuthMiddleware)
|
@httpGet('/:userUuid/subscription', TYPES.Auth_RequiredCrossServiceTokenMiddleware)
|
||||||
async getSubscription(request: Request, response: Response): Promise<results.JsonResult> {
|
async getSubscription(request: Request, response: Response): Promise<results.JsonResult> {
|
||||||
if (request.params.userUuid !== response.locals.user.uuid) {
|
if (request.params.userUuid !== response.locals.user.uuid) {
|
||||||
return this.json(
|
return this.json(
|
||||||
@@ -156,7 +156,7 @@ export class UsersController extends BaseHttpController {
|
|||||||
return this.json(result, 400)
|
return this.json(result, 400)
|
||||||
}
|
}
|
||||||
|
|
||||||
@httpPut('/:userId/attributes/credentials', TYPES.Auth_AuthMiddleware)
|
@httpPut('/:userId/attributes/credentials', TYPES.Auth_RequiredCrossServiceTokenMiddleware)
|
||||||
async changeCredentials(request: Request, response: Response): Promise<results.JsonResult | void> {
|
async changeCredentials(request: Request, response: Response): Promise<results.JsonResult | void> {
|
||||||
if (response.locals.readOnlyAccess) {
|
if (response.locals.readOnlyAccess) {
|
||||||
return this.json(
|
return this.json(
|
||||||
@@ -203,9 +203,21 @@ export class UsersController extends BaseHttpController {
|
|||||||
400,
|
400,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
const usernameOrError = Username.create(response.locals.user.email)
|
||||||
|
if (usernameOrError.isFailed()) {
|
||||||
|
return this.json(
|
||||||
|
{
|
||||||
|
error: {
|
||||||
|
message: 'Invalid username.',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
400,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
const username = usernameOrError.getValue()
|
||||||
|
|
||||||
const changeCredentialsResult = await this.changeCredentialsUseCase.execute({
|
const changeCredentialsResult = await this.changeCredentialsUseCase.execute({
|
||||||
user: response.locals.user,
|
username,
|
||||||
apiVersion: request.body.api,
|
apiVersion: request.body.api,
|
||||||
currentPassword: request.body.current_password,
|
currentPassword: request.body.current_password,
|
||||||
newPassword: request.body.new_password,
|
newPassword: request.body.new_password,
|
||||||
@@ -2,17 +2,17 @@ import 'reflect-metadata'
|
|||||||
|
|
||||||
import { Request, Response } from 'express'
|
import { Request, Response } from 'express'
|
||||||
import { results } from 'inversify-express-utils'
|
import { results } from 'inversify-express-utils'
|
||||||
import { ValetTokenController } from './ValetTokenController'
|
import { InversifyExpressValetTokenController } from './InversifyExpressValetTokenController'
|
||||||
import { CreateValetToken } from '../Domain/UseCase/CreateValetToken/CreateValetToken'
|
import { CreateValetToken } from '../../Domain/UseCase/CreateValetToken/CreateValetToken'
|
||||||
import { ControllerContainerInterface } from '@standardnotes/domain-core'
|
import { ControllerContainerInterface } from '@standardnotes/domain-core'
|
||||||
|
|
||||||
describe('ValetTokenController', () => {
|
describe('InversifyExpressValetTokenController', () => {
|
||||||
let createValetToken: CreateValetToken
|
let createValetToken: CreateValetToken
|
||||||
let request: Request
|
let request: Request
|
||||||
let response: Response
|
let response: Response
|
||||||
let controllerContainer: ControllerContainerInterface
|
let controllerContainer: ControllerContainerInterface
|
||||||
|
|
||||||
const createController = () => new ValetTokenController(createValetToken, controllerContainer)
|
const createController = () => new InversifyExpressValetTokenController(createValetToken, controllerContainer)
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
controllerContainer = {} as jest.Mocked<ControllerContainerInterface>
|
controllerContainer = {} as jest.Mocked<ControllerContainerInterface>
|
||||||
@@ -10,12 +10,11 @@ import {
|
|||||||
import { CreateValetTokenPayload, ErrorTag } from '@standardnotes/responses'
|
import { CreateValetTokenPayload, ErrorTag } from '@standardnotes/responses'
|
||||||
import { ValetTokenOperation } from '@standardnotes/security'
|
import { ValetTokenOperation } from '@standardnotes/security'
|
||||||
import { ControllerContainerInterface, Uuid } from '@standardnotes/domain-core'
|
import { ControllerContainerInterface, Uuid } from '@standardnotes/domain-core'
|
||||||
|
import TYPES from '../../Bootstrap/Types'
|
||||||
|
import { CreateValetToken } from '../../Domain/UseCase/CreateValetToken/CreateValetToken'
|
||||||
|
|
||||||
import TYPES from '../Bootstrap/Types'
|
@controller('/valet-tokens', TYPES.Auth_RequiredCrossServiceTokenMiddleware)
|
||||||
import { CreateValetToken } from '../Domain/UseCase/CreateValetToken/CreateValetToken'
|
export class InversifyExpressValetTokenController extends BaseHttpController {
|
||||||
|
|
||||||
@controller('/valet-tokens', TYPES.Auth_ApiGatewayAuthMiddleware)
|
|
||||||
export class ValetTokenController extends BaseHttpController {
|
|
||||||
constructor(
|
constructor(
|
||||||
@inject(TYPES.Auth_CreateValetToken) private createValetKey: CreateValetToken,
|
@inject(TYPES.Auth_CreateValetToken) private createValetKey: CreateValetToken,
|
||||||
@inject(TYPES.Auth_ControllerContainer) private controllerContainer: ControllerContainerInterface,
|
@inject(TYPES.Auth_ControllerContainer) private controllerContainer: ControllerContainerInterface,
|
||||||
@@ -1,31 +1,16 @@
|
|||||||
import { CrossServiceTokenData, TokenDecoderInterface } from '@standardnotes/security'
|
import { CrossServiceTokenData, TokenDecoderInterface } from '@standardnotes/security'
|
||||||
import { NextFunction, Request, Response } from 'express'
|
import { NextFunction, Request, Response } from 'express'
|
||||||
import { inject, injectable } from 'inversify'
|
|
||||||
import { BaseMiddleware } from 'inversify-express-utils'
|
import { BaseMiddleware } from 'inversify-express-utils'
|
||||||
import { Logger } from 'winston'
|
import { Logger } from 'winston'
|
||||||
import TYPES from '../Bootstrap/Types'
|
|
||||||
|
|
||||||
@injectable()
|
export abstract class ApiGatewayAuthMiddleware extends BaseMiddleware {
|
||||||
export class ApiGatewayAuthMiddleware extends BaseMiddleware {
|
constructor(private tokenDecoder: TokenDecoderInterface<CrossServiceTokenData>, private logger: Logger) {
|
||||||
constructor(
|
|
||||||
@inject(TYPES.Auth_CrossServiceTokenDecoder) private tokenDecoder: TokenDecoderInterface<CrossServiceTokenData>,
|
|
||||||
@inject(TYPES.Auth_Logger) private logger: Logger,
|
|
||||||
) {
|
|
||||||
super()
|
super()
|
||||||
}
|
}
|
||||||
|
|
||||||
async handler(request: Request, response: Response, next: NextFunction): Promise<void> {
|
async handler(request: Request, response: Response, next: NextFunction): Promise<void> {
|
||||||
try {
|
try {
|
||||||
if (!request.headers['x-auth-token']) {
|
if (!this.handleMissingToken(request, response, next)) {
|
||||||
this.logger.debug('ApiGatewayAuthMiddleware missing x-auth-token header.')
|
|
||||||
|
|
||||||
response.status(401).send({
|
|
||||||
error: {
|
|
||||||
tag: 'invalid-auth',
|
|
||||||
message: 'Invalid login credentials.',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,4 +41,6 @@ export class ApiGatewayAuthMiddleware extends BaseMiddleware {
|
|||||||
return next(error)
|
return next(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected abstract handleMissingToken(request: Request, response: Response, next: NextFunction): boolean
|
||||||
}
|
}
|
||||||
@@ -3,7 +3,7 @@ import { NextFunction, Request, Response } from 'express'
|
|||||||
import { inject, injectable } from 'inversify'
|
import { inject, injectable } from 'inversify'
|
||||||
import { BaseMiddleware } from 'inversify-express-utils'
|
import { BaseMiddleware } from 'inversify-express-utils'
|
||||||
import { Logger } from 'winston'
|
import { Logger } from 'winston'
|
||||||
import TYPES from '../Bootstrap/Types'
|
import TYPES from '../../../Bootstrap/Types'
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export class ApiGatewayOfflineAuthMiddleware extends BaseMiddleware {
|
export class ApiGatewayOfflineAuthMiddleware extends BaseMiddleware {
|
||||||
@@ -2,9 +2,9 @@ import 'reflect-metadata'
|
|||||||
|
|
||||||
import { LockMiddleware } from './LockMiddleware'
|
import { LockMiddleware } from './LockMiddleware'
|
||||||
import { NextFunction, Request, Response } from 'express'
|
import { NextFunction, Request, Response } from 'express'
|
||||||
import { User } from '../Domain/User/User'
|
import { User } from '../../../Domain/User/User'
|
||||||
import { UserRepositoryInterface } from '../Domain/User/UserRepositoryInterface'
|
import { UserRepositoryInterface } from '../../../Domain/User/UserRepositoryInterface'
|
||||||
import { LockRepositoryInterface } from '../Domain/User/LockRepositoryInterface'
|
import { LockRepositoryInterface } from '../../../Domain/User/LockRepositoryInterface'
|
||||||
|
|
||||||
describe('LockMiddleware', () => {
|
describe('LockMiddleware', () => {
|
||||||
let userRepository: UserRepositoryInterface
|
let userRepository: UserRepositoryInterface
|
||||||
@@ -2,10 +2,10 @@ import { Username } from '@standardnotes/domain-core'
|
|||||||
import { NextFunction, Request, Response } from 'express'
|
import { NextFunction, Request, Response } from 'express'
|
||||||
import { inject, injectable } from 'inversify'
|
import { inject, injectable } from 'inversify'
|
||||||
import { BaseMiddleware } from 'inversify-express-utils'
|
import { BaseMiddleware } from 'inversify-express-utils'
|
||||||
import TYPES from '../Bootstrap/Types'
|
import TYPES from '../../../Bootstrap/Types'
|
||||||
import { LockRepositoryInterface } from '../Domain/User/LockRepositoryInterface'
|
import { LockRepositoryInterface } from '../../../Domain/User/LockRepositoryInterface'
|
||||||
|
|
||||||
import { UserRepositoryInterface } from '../Domain/User/UserRepositoryInterface'
|
import { UserRepositoryInterface } from '../../../Domain/User/UserRepositoryInterface'
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export class LockMiddleware extends BaseMiddleware {
|
export class LockMiddleware extends BaseMiddleware {
|
||||||
@@ -3,8 +3,8 @@ import 'reflect-metadata'
|
|||||||
import { OfflineUserAuthMiddleware } from './OfflineUserAuthMiddleware'
|
import { OfflineUserAuthMiddleware } from './OfflineUserAuthMiddleware'
|
||||||
import { NextFunction, Request, Response } from 'express'
|
import { NextFunction, Request, Response } from 'express'
|
||||||
import { Logger } from 'winston'
|
import { Logger } from 'winston'
|
||||||
import { OfflineSettingRepositoryInterface } from '../Domain/Setting/OfflineSettingRepositoryInterface'
|
import { OfflineSettingRepositoryInterface } from '../../../Domain/Setting/OfflineSettingRepositoryInterface'
|
||||||
import { OfflineSetting } from '../Domain/Setting/OfflineSetting'
|
import { OfflineSetting } from '../../../Domain/Setting/OfflineSetting'
|
||||||
|
|
||||||
describe('OfflineUserAuthMiddleware', () => {
|
describe('OfflineUserAuthMiddleware', () => {
|
||||||
let offlineSettingRepository: OfflineSettingRepositoryInterface
|
let offlineSettingRepository: OfflineSettingRepositoryInterface
|
||||||
@@ -2,9 +2,9 @@ import { NextFunction, Request, Response } from 'express'
|
|||||||
import { inject, injectable } from 'inversify'
|
import { inject, injectable } from 'inversify'
|
||||||
import { BaseMiddleware } from 'inversify-express-utils'
|
import { BaseMiddleware } from 'inversify-express-utils'
|
||||||
import { Logger } from 'winston'
|
import { Logger } from 'winston'
|
||||||
import TYPES from '../Bootstrap/Types'
|
import TYPES from '../../../Bootstrap/Types'
|
||||||
import { OfflineSettingName } from '../Domain/Setting/OfflineSettingName'
|
import { OfflineSettingName } from '../../../Domain/Setting/OfflineSettingName'
|
||||||
import { OfflineSettingRepositoryInterface } from '../Domain/Setting/OfflineSettingRepositoryInterface'
|
import { OfflineSettingRepositoryInterface } from '../../../Domain/Setting/OfflineSettingRepositoryInterface'
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export class OfflineUserAuthMiddleware extends BaseMiddleware {
|
export class OfflineUserAuthMiddleware extends BaseMiddleware {
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import { CrossServiceTokenData, TokenDecoderInterface } from '@standardnotes/security'
|
||||||
|
import { NextFunction, Request, Response } from 'express'
|
||||||
|
import { inject, injectable } from 'inversify'
|
||||||
|
import { Logger } from 'winston'
|
||||||
|
|
||||||
|
import TYPES from '../../../Bootstrap/Types'
|
||||||
|
import { ApiGatewayAuthMiddleware } from './ApiGatewayAuthMiddleware'
|
||||||
|
|
||||||
|
@injectable()
|
||||||
|
export class OptionalCrossServiceTokenMiddleware extends ApiGatewayAuthMiddleware {
|
||||||
|
constructor(
|
||||||
|
@inject(TYPES.Auth_CrossServiceTokenDecoder) tokenDecoder: TokenDecoderInterface<CrossServiceTokenData>,
|
||||||
|
@inject(TYPES.Auth_Logger) logger: Logger,
|
||||||
|
) {
|
||||||
|
super(tokenDecoder, logger)
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override handleMissingToken(request: Request, _response: Response, next: NextFunction): boolean {
|
||||||
|
if (!request.headers['x-auth-token']) {
|
||||||
|
next()
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
import { CrossServiceTokenData, TokenDecoderInterface } from '@standardnotes/security'
|
||||||
|
import { NextFunction, Request, Response } from 'express'
|
||||||
|
import { inject, injectable } from 'inversify'
|
||||||
|
import { Logger } from 'winston'
|
||||||
|
|
||||||
|
import TYPES from '../../../Bootstrap/Types'
|
||||||
|
import { ApiGatewayAuthMiddleware } from './ApiGatewayAuthMiddleware'
|
||||||
|
|
||||||
|
@injectable()
|
||||||
|
export class RequiredCrossServiceTokenMiddleware extends ApiGatewayAuthMiddleware {
|
||||||
|
constructor(
|
||||||
|
@inject(TYPES.Auth_CrossServiceTokenDecoder) tokenDecoder: TokenDecoderInterface<CrossServiceTokenData>,
|
||||||
|
@inject(TYPES.Auth_Logger) logger: Logger,
|
||||||
|
) {
|
||||||
|
super(tokenDecoder, logger)
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override handleMissingToken(request: Request, response: Response, _next: NextFunction): boolean {
|
||||||
|
if (!request.headers['x-auth-token']) {
|
||||||
|
response.status(401).send({
|
||||||
|
error: {
|
||||||
|
tag: 'invalid-auth',
|
||||||
|
message: 'Invalid login credentials.',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,12 @@
|
|||||||
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.12.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.11.2...@standardnotes/domain-events-infra@1.12.0) (2023-05-17)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add direct event handling for home server ([#608](https://github.com/standardnotes/server/issues/608)) ([8a47d81](https://github.com/standardnotes/server/commit/8a47d81936acd765224e74fd083810579a83c9a7))
|
||||||
|
|
||||||
## [1.11.2](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.11.1...@standardnotes/domain-events-infra@1.11.2) (2023-05-15)
|
## [1.11.2](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.11.1...@standardnotes/domain-events-infra@1.11.2) (2023-05-15)
|
||||||
|
|
||||||
**Note:** Version bump only for package @standardnotes/domain-events-infra
|
**Note:** Version bump only for package @standardnotes/domain-events-infra
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/domain-events-infra",
|
"name": "@standardnotes/domain-events-infra",
|
||||||
"version": "1.11.2",
|
"version": "1.12.0",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.0.0 <21.0.0"
|
"node": ">=18.0.0 <21.0.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import {
|
||||||
|
DomainEventInterface,
|
||||||
|
DomainEventMessageHandlerInterface,
|
||||||
|
DomainEventPublisherInterface,
|
||||||
|
} from '@standardnotes/domain-events'
|
||||||
|
|
||||||
|
export class DirectCallDomainEventPublisher implements DomainEventPublisherInterface {
|
||||||
|
private handlers: Array<DomainEventMessageHandlerInterface> = []
|
||||||
|
|
||||||
|
register(domainEventMessageHandler: DomainEventMessageHandlerInterface): void {
|
||||||
|
this.handlers.push(domainEventMessageHandler)
|
||||||
|
}
|
||||||
|
|
||||||
|
async publish(event: DomainEventInterface): Promise<void> {
|
||||||
|
await Promise.all(this.handlers.map((handler) => handler.handleMessage(event)))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
import { Logger } from 'winston'
|
||||||
|
|
||||||
|
import {
|
||||||
|
DomainEventHandlerInterface,
|
||||||
|
DomainEventInterface,
|
||||||
|
DomainEventMessageHandlerInterface,
|
||||||
|
} from '@standardnotes/domain-events'
|
||||||
|
|
||||||
|
export class DirectCallEventMessageHandler implements DomainEventMessageHandlerInterface {
|
||||||
|
constructor(private handlers: Map<string, DomainEventHandlerInterface>, private logger: Logger) {}
|
||||||
|
|
||||||
|
async handleMessage(messageOrEvent: string | DomainEventInterface): Promise<void> {
|
||||||
|
if (typeof messageOrEvent === 'string') {
|
||||||
|
throw new Error('DirectCallEventMessageHandler does not support string messages')
|
||||||
|
}
|
||||||
|
|
||||||
|
const handler = this.handlers.get(messageOrEvent.type)
|
||||||
|
if (!handler) {
|
||||||
|
this.logger.debug(`Event handler for event type ${messageOrEvent.type} does not exist`)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.logger.debug(`Received event: ${messageOrEvent.type}`)
|
||||||
|
|
||||||
|
await handler.handle(messageOrEvent)
|
||||||
|
}
|
||||||
|
|
||||||
|
async handleError(error: Error): Promise<void> {
|
||||||
|
this.logger.error('Error occured while handling SQS message: %O', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,3 +1,6 @@
|
|||||||
|
export * from './DirectCall/DirectCallDomainEventPublisher'
|
||||||
|
export * from './DirectCall/DirectCallEventMessageHandler'
|
||||||
|
|
||||||
export * from './Redis/RedisDomainEventPublisher'
|
export * from './Redis/RedisDomainEventPublisher'
|
||||||
export * from './Redis/RedisDomainEventSubscriber'
|
export * from './Redis/RedisDomainEventSubscriber'
|
||||||
export * from './Redis/RedisDomainEventSubscriberFactory'
|
export * from './Redis/RedisDomainEventSubscriberFactory'
|
||||||
|
|||||||
@@ -3,6 +3,12 @@
|
|||||||
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.111.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.110.2...@standardnotes/domain-events@2.111.0) (2023-05-17)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add direct event handling for home server ([#608](https://github.com/standardnotes/server/issues/608)) ([8a47d81](https://github.com/standardnotes/server/commit/8a47d81936acd765224e74fd083810579a83c9a7))
|
||||||
|
|
||||||
## [2.110.2](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.110.1...@standardnotes/domain-events@2.110.2) (2023-05-09)
|
## [2.110.2](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.110.1...@standardnotes/domain-events@2.110.2) (2023-05-09)
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/domain-events",
|
"name": "@standardnotes/domain-events",
|
||||||
"version": "2.110.2",
|
"version": "2.111.0",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.0.0 <21.0.0"
|
"node": ">=18.0.0 <21.0.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
|
import { DomainEventInterface } from '../Event/DomainEventInterface'
|
||||||
|
|
||||||
export interface DomainEventMessageHandlerInterface {
|
export interface DomainEventMessageHandlerInterface {
|
||||||
handleMessage(message: string): Promise<void>
|
handleMessage(messageOrEvent: string | DomainEventInterface): Promise<void>
|
||||||
handleError(error: Error): Promise<void>
|
handleError(error: Error): Promise<void>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,10 @@
|
|||||||
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.8.3](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.8.2...@standardnotes/event-store@1.8.3) (2023-05-17)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/event-store
|
||||||
|
|
||||||
## [1.8.2](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.8.1...@standardnotes/event-store@1.8.2) (2023-05-15)
|
## [1.8.2](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.8.1...@standardnotes/event-store@1.8.2) (2023-05-15)
|
||||||
|
|
||||||
**Note:** Version bump only for package @standardnotes/event-store
|
**Note:** Version bump only for package @standardnotes/event-store
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/event-store",
|
"name": "@standardnotes/event-store",
|
||||||
"version": "1.8.2",
|
"version": "1.8.3",
|
||||||
"description": "Event Store Service",
|
"description": "Event Store Service",
|
||||||
"private": true,
|
"private": true,
|
||||||
"main": "dist/src/index.js",
|
"main": "dist/src/index.js",
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user