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